From 4ba210cf8102f2073c1ebc7062bd211c266ab46f Mon Sep 17 00:00:00 2001 From: deppbot Date: Sun, 24 Dec 2017 08:09:48 +0800 Subject: [PATCH 001/267] Bundle Update on 2017-12-24 --- Gemfile.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index b9a7ee954..31113ea38 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -181,8 +181,8 @@ GEM factory_bot_rails (4.8.2) factory_bot (~> 4.8.2) railties (>= 3.0.0) - faker (1.8.5) - i18n (~> 0.9.1) + faker (1.8.7) + i18n (>= 0.7) faraday (0.12.2) multipart-post (>= 1.2, < 3) ffi (1.9.18) @@ -238,7 +238,7 @@ GEM rake (>= 10, < 13) rubocop (>= 0.49.0) sysexits (~> 1.1) - hashie (3.5.6) + hashie (3.5.7) heroics (0.0.24) erubis (~> 2.0) excon @@ -276,7 +276,7 @@ GEM thor (>= 0.14, < 2.0) jquery-ui-rails (5.0.5) railties (>= 3.2.16) - js-routes (1.4.2) + js-routes (1.4.3) railties (>= 3.2) sprockets-rails json (2.1.0) @@ -329,7 +329,7 @@ GEM multi_xml (0.6.0) multipart-post (2.0.0) nenv (0.3.0) - newrelic_rpm (4.6.0.338) + newrelic_rpm (4.7.1.340) nokogiri (1.8.1) mini_portile2 (~> 2.3.0) notiffany (0.1.1) @@ -408,8 +408,8 @@ GEM rails-assets-leaflet (>= 1.0.3) rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.8) - activesupport (>= 4.2.0.beta, < 5.0) + rails-dom-testing (1.0.9) + activesupport (>= 4.2.0, < 5.0) nokogiri (~> 1.6) rails-deprecated_sanitizer (>= 1.0.1) rails-html-sanitizer (1.0.3) @@ -528,7 +528,7 @@ GEM uglifier (4.0.2) execjs (>= 0.3.0, < 3) unicode-display_width (1.3.0) - unicorn (5.3.1) + unicorn (5.4.0) kgio (~> 2.6) raindrops (~> 0.7) uniform_notifier (1.10.0) From 93eba14af976c1ac4d0342091f10eab3ad0e7b5c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 11:26:08 +1300 Subject: [PATCH 002/267] Adding package lock, and eslint --- .eslintrc.js | 3 + .overcommit.yml | 8 +- package-lock.json | 814 ++++++++++++++++++++++------------------------ package.json | 3 +- 4 files changed, 400 insertions(+), 428 deletions(-) create mode 100644 .eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..f2ddd9cea --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + "extends": "google" +}; \ No newline at end of file diff --git a/.overcommit.yml b/.overcommit.yml index 505c8e2e6..d7899885f 100644 --- a/.overcommit.yml +++ b/.overcommit.yml @@ -46,7 +46,9 @@ PreCommit: required_executable: 'npm' HamlLint: enabled: true - command: ['bundle', 'exec', 'haml-lint', 'app/views'] + include: + - 'app/views/**' + command: ['bundle', 'exec', 'haml-lint'] JsonSyntax: enabled: true BundleOutdated: @@ -55,13 +57,13 @@ PreCommit: BundleAudit: enabled: true on_warn: warn - JsHint: + EsLint: enabled: true exclude: - 'app/assets/**' - 'spec/javascripts/support/vendor/**' - '**/bootstrap*' - command: ['npm', 'run', 'jshint'] + command: ['./node_modules/.bin/eslint'] required_executable: 'npm' ScssLint: enabled: true diff --git a/package-lock.json b/package-lock.json index 013886a6b..baf5adb61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "acorn": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", + "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==", "dev": true }, "acorn-jsx": { @@ -28,25 +28,27 @@ } }, "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" } }, "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", "dev": true }, "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", "dev": true }, "ansi-regex": { @@ -100,6 +102,30 @@ "chalk": "1.1.3", "esutils": "2.0.2", "js-tokens": "3.0.2" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + } } }, "balanced-match": { @@ -134,22 +160,46 @@ "dev": true }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", "dev": true, "requires": { - "ansi-styles": "2.2.1", + "ansi-styles": "3.2.0", "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "supports-color": "4.5.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } } }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", "dev": true }, "cli": { @@ -163,12 +213,12 @@ } }, "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "1.0.1" + "restore-cursor": "2.0.0" } }, "cli-width": { @@ -189,12 +239,6 @@ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, "coffeelint": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/coffeelint/-/coffeelint-2.0.7.tgz", @@ -212,7 +256,22 @@ "coffeescript": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.0.3.tgz", - "integrity": "sha512-iIfUN+71IyI2FQABXh1luzZeQgqwUPeWh6lDovJatQQs+30bvyGnBY0r4BnD0hoMAasNuZVHlL1U09Oy1ZfSeg==", + "integrity": "sha1-dg8Cck9fCRG+fO+jSo4OEMXYUSo=", + "dev": true + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, "concat-map": { @@ -247,6 +306,17 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, "csslint": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/csslint/-/csslint-1.0.5.tgz", @@ -257,15 +327,6 @@ "parserlib": "1.1.1" } }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "0.10.35" - } - }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -273,9 +334,9 @@ "dev": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -303,13 +364,12 @@ } }, "doctrine": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", - "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.2.tgz", + "integrity": "sha512-y0tm5Pq6ywp3qSTZ1vPgVdAnbDEoeoc5wlOHXoY1c4Wug/a7JvqHIl7BTvwodaHmejWkK/9dSb3sCYfyo/om8A==", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "2.0.2" } }, "dom-serializer": { @@ -367,135 +427,55 @@ "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", "dev": true }, - "es5-ext": { - "version": "0.10.35", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.35.tgz", - "integrity": "sha1-GO6FjOajxFx9eekcFfzKnsVoSU8=", - "dev": true, - "requires": { - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35", - "es6-symbol": "3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35", - "es6-iterator": "2.0.3", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35", - "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" - } - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", - "estraverse": "4.2.0" - } - }, "eslint": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", - "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.14.0.tgz", + "integrity": "sha512-Ul6CSGRjKscEyg0X/EeNs7o2XdnbTEOD1OM8cTjmx85RPcBJQrEhZLevhuJZNAE/vS2iVl5Uhgiqf3h5uLMCJQ==", "dev": true, "requires": { + "ajv": "5.5.2", "babel-code-frame": "6.26.0", - "chalk": "1.1.3", + "chalk": "2.3.0", "concat-stream": "1.6.0", - "debug": "2.6.9", - "doctrine": "2.0.0", - "escope": "3.6.0", - "espree": "3.5.1", + "cross-spawn": "5.1.0", + "debug": "3.1.0", + "doctrine": "2.0.2", + "eslint-scope": "3.7.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.2", "esquery": "1.0.0", - "estraverse": "4.2.0", "esutils": "2.0.2", "file-entry-cache": "2.0.0", + "functional-red-black-tree": "1.0.1", "glob": "7.1.2", - "globals": "9.18.0", + "globals": "11.1.0", "ignore": "3.3.7", "imurmurhash": "0.1.4", - "inquirer": "0.12.0", - "is-my-json-valid": "2.16.1", - "is-resolvable": "1.0.0", + "inquirer": "3.3.0", + "is-resolvable": "1.0.1", "js-yaml": "3.10.0", - "json-stable-stringify": "1.0.1", + "json-stable-stringify-without-jsonify": "1.0.1", "levn": "0.3.0", "lodash": "4.17.4", + "minimatch": "3.0.4", "mkdirp": "0.5.1", "natural-compare": "1.4.0", "optionator": "0.8.2", "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", + "pluralize": "7.0.0", + "progress": "2.0.0", "require-uncached": "1.0.3", - "shelljs": "0.7.8", - "strip-bom": "3.0.0", + "semver": "5.4.1", + "strip-ansi": "4.0.0", "strip-json-comments": "2.0.1", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" + "table": "4.0.2", + "text-table": "0.2.0" }, "dependencies": { "strip-json-comments": { @@ -506,20 +486,42 @@ } } }, - "espree": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz", - "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", + "eslint-config-google": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.9.1.tgz", + "integrity": "sha512-5A83D+lH0PA81QMESKbLJd/a3ic8tPZtwUmqNrxMRo54nfFaUvtt89q/+icQ+fd66c2xQHn0KyFkzJDoAUfpZA==", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { - "acorn": "5.2.1", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", + "dev": true + }, + "espree": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", + "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", + "dev": true, + "requires": { + "acorn": "5.3.0", "acorn-jsx": "3.0.1" } }, "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", "dev": true }, "esquery": { @@ -553,26 +555,33 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.35" - } - }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "external-editor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha1-PQJqIbf5W1cmOH1CAKwWDTcsO0g=", + "dev": true, + "requires": { + "chardet": "0.4.2", + "iconv-lite": "0.4.19", + "tmp": "0.0.33" + } + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", "dev": true }, "fast-levenshtein": { @@ -582,13 +591,12 @@ "dev": true }, "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" + "escape-string-regexp": "1.0.5" } }, "file-entry-cache": { @@ -619,21 +627,12 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -649,9 +648,9 @@ } }, "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.1.0.tgz", + "integrity": "sha512-uEuWt9mqTlPDwSqi+sHjD4nWU/1N+q0fiWI9T1mZpD2UENqX20CFD5T/ziLZvztPaBKl7ZylUi1q6Qfm7E2CiQ==", "dev": true }, "globby": { @@ -683,6 +682,12 @@ "ansi-regex": "2.1.1" } }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, "htmlparser2": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", @@ -722,6 +727,12 @@ } } }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=", + "dev": true + }, "ignore": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", @@ -751,52 +762,32 @@ "dev": true }, "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", + "ansi-escapes": "3.0.0", + "chalk": "2.3.0", + "cli-cursor": "2.1.0", "cli-width": "2.2.0", - "figures": "1.7.0", + "external-editor": "2.1.0", + "figures": "2.0.0", "lodash": "4.17.4", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", "through": "2.3.8" } }, - "interpret": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", - "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", - "dev": true - }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true }, "is-path-cwd": { "version": "1.0.0", @@ -810,32 +801,29 @@ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", "dev": true, "requires": { - "is-path-inside": "1.0.0" + "is-path-inside": "1.0.1" } }, "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { "path-is-inside": "1.0.2" } }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", "dev": true }, "is-resolvable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", - "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", - "dev": true, - "requires": { - "tryit": "1.0.3" - } + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.1.tgz", + "integrity": "sha512-y5CXYbzvB3jTnWAZH1Nl7ykUWb6T3BcTs56HUruwBf8MhF56n1HWqhDWnVFo8GHrUPDgvUUNVhrc2U8W7iqz5g==", + "dev": true }, "isarray": { "version": "1.0.0", @@ -843,6 +831,12 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", @@ -852,7 +846,7 @@ "js-yaml": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", "dev": true, "requires": { "argparse": "1.0.9", @@ -889,25 +883,16 @@ } } }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, "levn": { @@ -926,6 +911,22 @@ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", "dev": true }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -965,9 +966,9 @@ "dev": true }, "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, "natural-compare": { @@ -976,12 +977,6 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -998,10 +993,13 @@ } }, "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } }, "optimist": { "version": "0.6.1", @@ -1035,10 +1033,10 @@ } } }, - "os-homedir": { + "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, "parserlib": { @@ -1059,12 +1057,6 @@ "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -1087,9 +1079,9 @@ } }, "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, "prelude-ls": { @@ -1105,15 +1097,21 @@ "dev": true }, "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", "dev": true }, "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -1125,37 +1123,6 @@ "util-deprecate": "1.0.2" } }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "mute-stream": "0.0.5" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "1.5.0" - }, - "dependencies": { - "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - } - } - }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -1179,62 +1146,90 @@ "dev": true }, "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" + "onetime": "2.0.1", + "signal-exit": "3.0.2" } }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "dev": true, "requires": { "glob": "7.1.2" } }, "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "once": "1.4.0" + "is-promise": "2.1.0" } }, "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", "dev": true }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", "dev": true }, - "shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "glob": "7.1.2", - "interpret": "1.0.4", - "rechoir": "0.6.2" + "shebang-regex": "1.0.0" } }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -1242,40 +1237,41 @@ "dev": true }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" } }, "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { "safe-buffer": "5.1.1" } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, "strip-json-comments": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", @@ -1289,50 +1285,17 @@ "dev": true }, "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.0", "lodash": "4.17.4", - "slice-ansi": "0.0.4", + "slice-ansi": "1.0.0", "string-width": "2.1.1" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - } } }, "text-table": { @@ -1347,11 +1310,14 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, - "tryit": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", - "dev": true + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } }, "type-check": { "version": "0.3.2", @@ -1368,21 +1334,21 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", @@ -1404,10 +1370,10 @@ "mkdirp": "0.5.1" } }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", "dev": true } } diff --git a/package.json b/package.json index f41b67b64..b0943cb2c 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "devDependencies": { "coffeelint": "^2.0.7", "csslint": "^1.0.5", - "eslint": "^3.17.1", + "eslint": "^4.14.0", + "eslint-config-google": "^0.9.1", "jshint": "^2.9.4" }, "repository": { From 4e0f7e9086fea82b96c1d2510998887637eb3acb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 11:49:06 +1300 Subject: [PATCH 003/267] Use the old "var" syntax, and max line 120 --- .eslintrc.js | 3 --- .eslintrc.json | 11 +++++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) delete mode 100644 .eslintrc.js create mode 100644 .eslintrc.json diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index f2ddd9cea..000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - "extends": "google" -}; \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 000000000..a2035e465 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,11 @@ +{ + "extends": "google", + "env": { + "browser": true, + "node": true + }, + "rules": { + "no-var": "off", + "max-len": ["error", { "code": 120, "tabWidth": 4 }] + } +} \ No newline at end of file From a836d6432fc1e4eead9d6c3b2200c8405e495552 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 11:51:14 +1300 Subject: [PATCH 004/267] Updating javascript style --- spec/javascripts/graphs/bar_group_spec.js | 52 ++++----- .../graphs/bar_label_group_spec.js | 26 ++--- spec/javascripts/graphs/height_scale_spec.js | 16 ++- .../graphs/horizontal_bar_graph_spec.js | 110 +++++++++--------- spec/javascripts/graphs/width_scale_spec.js | 17 ++- 5 files changed, 104 insertions(+), 117 deletions(-) diff --git a/spec/javascripts/graphs/bar_group_spec.js b/spec/javascripts/graphs/bar_group_spec.js index 6358d1d26..50af8d3a8 100644 --- a/spec/javascripts/graphs/bar_group_spec.js +++ b/spec/javascripts/graphs/bar_group_spec.js @@ -1,4 +1,4 @@ -(function(){ +(function() { 'use strict'; /* @@ -6,31 +6,30 @@ */ describe('when drawing the group of bars', function() { - var BarGroup, subject, widthScale, bars, data; + var BarGroup; var subject; var widthScale; var bars; var data; - beforeEach(function() { + beforeEach(function() { + var WidthScale = growstuff.WidthScale; + BarGroup = growstuff.BarGroup; - var WidthScale = growstuff.WidthScale; - BarGroup = growstuff.BarGroup; + bars = [ + {name: 'Shade', value: 0.2}, + {name: 'Half Shade', value: 0.5}, + ]; - bars = [ - {name: 'Shade', value: 0.2}, - {name: 'Half Shade', value: 0.5} - ]; + data = { + bars: bars, + bar_color: 'steelblue', + width: {size: 300, scale: 'linear'}, + height: {size: 400, scale: 'ordinal'}, + }; - data = { - bars: bars, - bar_color: 'steelblue', - width: {size: 300, scale: 'linear'}, - height: {size: 400, scale: 'ordinal'} - }; + widthScale = new WidthScale(data); + subject = new BarGroup(data); + subject.render(d3.select('#jasmine_content').append('svg')); + }); - widthScale = new WidthScale(data); - subject = new BarGroup(data); - subject.render(d3.select('#jasmine_content').append('svg')); - }); - - it('draws a group', function(){ + it('draws a group', function() { expect($('g.bar')).toExist(); }); @@ -38,23 +37,20 @@ expect($('g.bar rect')).toHaveLength(2); }); - it('fills the bars with color', function(){ + it('fills the bars with color', function() { expect($('g.bar rect')).toHaveAttr('fill', 'steelblue'); }); - it('shows a tooltip on hover', function(){ + it('shows a tooltip on hover', function() { var i; - //get all of the title nodes for the bars + // get all of the title nodes for the bars var barNodes = $('g.bar rect title'); - for (i = 0; i < bars.length; i++){ + for (i = 0; i < bars.length; i++) { expect(barNodes[i].textContent) .toBe('This value is ' + bars[i].value + '' + '.'); } }); - - }); - }()); diff --git a/spec/javascripts/graphs/bar_label_group_spec.js b/spec/javascripts/graphs/bar_label_group_spec.js index aaaf680c7..7cb6e5537 100644 --- a/spec/javascripts/graphs/bar_label_group_spec.js +++ b/spec/javascripts/graphs/bar_label_group_spec.js @@ -1,42 +1,38 @@ -(function(){ +(function() { 'use strict'; /* This file contains tests for the labels that get rendered next to each bar */ - describe('BarLabelGroup', function(){ + describe('BarLabelGroup', function() { + var BarLabelGroup; var subject; var data; - var BarLabelGroup, subject, data; - - beforeEach(function(){ + beforeEach(function() { BarLabelGroup = growstuff.BarLabelGroup; var bars = [ {name: 'Shade', value: 0.2}, - {name: 'Half Shade', value: 0.5} + {name: 'Half Shade', value: 0.5}, ]; data = { - bars: bars + bars: bars, }; subject = new BarLabelGroup(data); subject.render(d3.select('#jasmine_content').append('svg')); }); - it('draws a group for labels', function(){ + it('draws a group for labels', function() { expect($('g.bar-label')).toExist(); }); - it('draws 2 bar labels', function(){ + it('draws 2 bar labels', function() { expect($('g.bar-label text')).toHaveLength(2); }); - it ('has text for 2 bar labels', function(){ - //jquery jasmine appends text from all text elements + it('has text for 2 bar labels', function() { + // jquery jasmine appends text from all text elements // into one string expect($('g.bar-label text')).toHaveText('ShadeHalf Shade'); - }); - }); - -}()); \ No newline at end of file +}()); diff --git a/spec/javascripts/graphs/height_scale_spec.js b/spec/javascripts/graphs/height_scale_spec.js index 0de6a987a..3a257400c 100644 --- a/spec/javascripts/graphs/height_scale_spec.js +++ b/spec/javascripts/graphs/height_scale_spec.js @@ -1,4 +1,4 @@ -(function(){ +(function() { 'use strict'; /* @@ -6,18 +6,18 @@ */ describe('HeightScale when specifying height', function() { - var data, bars, HeightScale, subject, mockD3; + var data; var bars; var HeightScale; var subject; var mockD3; - beforeEach(function(){ + beforeEach(function() { HeightScale = growstuff.HeightScale; bars = [ {name: 'Shade', value: 0.2}, - {name: 'Half Shade', value: 0.5} + {name: 'Half Shade', value: 0.5}, ]; data = { bars: bars, width: {size: 300, scale: 'linear'}, - height: {size: 400, scale: 'ordinal'} + height: {size: 400, scale: 'ordinal'}, }; subject = new HeightScale(data); @@ -26,12 +26,10 @@ mockD3.rangeRoundBands.and.returnValue(mockD3); spyOn(d3.scale, 'ordinal').and.returnValue(mockD3); subject.render(); - }); - it('calls the d3 range round bands function to draw the height', function(){ + it('calls the d3 range round bands function to draw the height', function() { expect(mockD3.rangeRoundBands).toHaveBeenCalledWith([0, 400], 0.05, 0); }); }); - -}()); \ No newline at end of file +}()); diff --git a/spec/javascripts/graphs/horizontal_bar_graph_spec.js b/spec/javascripts/graphs/horizontal_bar_graph_spec.js index 8e6b62a48..b8fbed1a3 100644 --- a/spec/javascripts/graphs/horizontal_bar_graph_spec.js +++ b/spec/javascripts/graphs/horizontal_bar_graph_spec.js @@ -1,4 +1,4 @@ -(function(){ +(function() { 'use strict'; /* @@ -6,70 +6,68 @@ are more integration-y type tests that require the full graph. */ - describe('HorizontalBarGraph', function() { - var BarLabelGroup, BarGroup, subject, data; + describe('HorizontalBarGraph', function() { + var BarLabelGroup; var BarGroup; var subject; var data; - beforeEach(function() { - var HorizontalBarGraph = growstuff.HorizontalBarGraph; - var bars = [ - {name: 'Shade', value: 0.2}, - {name: 'Half Shade', value: 0.5} - ]; - data = { - bars: bars, - bar_color: 'steelblue', - width: {size: 300, scale: 'linear'}, - height: {size: 400, scale: 'ordinal'}, - //left is used to shift the bars over so that there is - //room for the labels - margin: {top: 0, right: 0, bottom: 0, left: 100} - }; + beforeEach(function() { + var HorizontalBarGraph = growstuff.HorizontalBarGraph; + var bars = [ + {name: 'Shade', value: 0.2}, + {name: 'Half Shade', value: 0.5}, + ]; + data = { + bars: bars, + bar_color: 'steelblue', + width: {size: 300, scale: 'linear'}, + height: {size: 400, scale: 'ordinal'}, + // left is used to shift the bars over so that there is + // room for the labels + margin: {top: 0, right: 0, bottom: 0, left: 100}, + }; - subject = new HorizontalBarGraph(data); - BarGroup = growstuff.BarGroup; - BarLabelGroup = growstuff.BarLabelGroup; - expect(BarLabelGroup).toExist(); - spyOn(BarGroup.prototype, 'render').and.callThrough(); - spyOn(BarLabelGroup.prototype, 'render').and.callThrough(); - subject.render(d3.select($('#jasmine_content')[0])); - }); + subject = new HorizontalBarGraph(data); + BarGroup = growstuff.BarGroup; + BarLabelGroup = growstuff.BarLabelGroup; + expect(BarLabelGroup).toExist(); + spyOn(BarGroup.prototype, 'render').and.callThrough(); + spyOn(BarLabelGroup.prototype, 'render').and.callThrough(); + subject.render(d3.select($('#jasmine_content')[0])); + }); - it('draws a graph', function() { - expect($('#jasmine_content svg')).toExist(); - }); + it('draws a graph', function() { + expect($('#jasmine_content svg')).toExist(); + }); - it('draws a group for the whole graph', function(){ - expect($('g.bar-graph')).toExist(); - }); + it('draws a group for the whole graph', function() { + expect($('g.bar-graph')).toExist(); + }); - it('draws a bar group', function(){ - expect(BarGroup.prototype.render).toHaveBeenCalled(); - }); + it('draws a bar group', function() { + expect(BarGroup.prototype.render).toHaveBeenCalled(); + }); - it('draws a group of bar labels', function() { - expect(BarLabelGroup.prototype.render).toHaveBeenCalled(); - }); + it('draws a group of bar labels', function() { + expect(BarLabelGroup.prototype.render).toHaveBeenCalled(); + }); - it('has the expected width and height', function() { - var $svg = $('svg'); - var margin = data.margin; - expect($svg).toHaveAttr('width', (data.width.size + margin.left + margin.right) + ''); - expect($svg).toHaveAttr('height', (data.height.size + margin.top + margin.bottom) + ''); - }); + it('has the expected width and height', function() { + var $svg = $('svg'); + var margin = data.margin; + expect($svg).toHaveAttr('width', (data.width.size + margin.left + margin.right) + ''); + expect($svg).toHaveAttr('height', (data.height.size + margin.top + margin.bottom) + ''); + }); - it('draws the graph shifted to the right to accommodate for labels', function(){ - expect('g.bar-graph').toHaveAttr('transform', 'translate(100,0)'); - }); + it('draws the graph shifted to the right to accommodate for labels', function() { + expect('g.bar-graph').toHaveAttr('transform', 'translate(100,0)'); + }); - it ('on the x axis, draws at least one bar at max width less margin width because of domain and range mapping', function(){ - expect('g.bar rect:eq(1)').toHaveAttr('width', '300' ); - }); - - it ('on the y axis, all bars are the same height', function(){ - expect('g.bar rect:eq(0)').toHaveAttr('height', '195'); - expect('g.bar rect:eq(1)').toHaveAttr('height', '195'); - }); + it('on the x axis, draws at least one bar at max width less margin width because of domain and range mapping', function() { + expect('g.bar rect:eq(1)').toHaveAttr('width', '300' ); + }); + it('on the y axis, all bars are the same height', function() { + expect('g.bar rect:eq(0)').toHaveAttr('height', '195'); + expect('g.bar rect:eq(1)').toHaveAttr('height', '195'); + }); }); - }()); diff --git a/spec/javascripts/graphs/width_scale_spec.js b/spec/javascripts/graphs/width_scale_spec.js index c6ca9204a..d8e34234a 100644 --- a/spec/javascripts/graphs/width_scale_spec.js +++ b/spec/javascripts/graphs/width_scale_spec.js @@ -1,4 +1,4 @@ -(function(){ +(function() { 'use strict'; /* @@ -6,19 +6,19 @@ the length of a bar so that it is the correct size for the screen */ - describe('GraphScale, when specifying width', function(){ - var data, WidthScale, subject, mockD3; + describe('GraphScale, when specifying width', function() { + var data; var WidthScale; var subject; var mockD3; - beforeEach(function(){ + beforeEach(function() { WidthScale = growstuff.WidthScale; var bars = [ {name: 'Shade', value: 0.2}, - {name: 'Half Shade', value: 0.5} + {name: 'Half Shade', value: 0.5}, ]; data = { bars: bars, width: {size: 300, scale: 'linear'}, - height: {size: 400, scale: 'ordinal'} + height: {size: 400, scale: 'ordinal'}, }; subject = new WidthScale(data, 'width'); @@ -29,13 +29,12 @@ subject.render(); }); - it ('gets the value of the longest bar', function(){ + it('gets the value of the longest bar', function() { expect(subject.getMaxValue()).toEqual(0.5); }); - it ('calls the d3 range function to draw the width', function(){ + it('calls the d3 range function to draw the width', function() { expect(mockD3.range).toHaveBeenCalledWith([0, 300]); }); }); - }()); From 74646680212ffe0108b50e557542d453603b16eb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 12:02:21 +1300 Subject: [PATCH 005/267] Add bootstrap js to codeclimate excludes --- .codeclimate.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.codeclimate.yml b/.codeclimate.yml index ca784c7a0..32904c026 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -42,3 +42,4 @@ exclude_paths: - spec/ - public/ - app/assets/stylesheets/bootstrap-accessibility.css +- app/assets/javascripts/bootstrap* From 5584da02c33ef1659dc6caf5e6c5aa1a609468b0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 12:35:30 +1300 Subject: [PATCH 006/267] Some js cleanups --- app/assets/javascripts/application.js | 18 +++++----- app/assets/javascripts/graphs/bar_group.js | 33 +++++++++---------- .../javascripts/graphs/bar_label_group.js | 30 +++++++++-------- app/assets/javascripts/graphs/height_scale.js | 14 ++++---- .../graphs/horizontal_bar_graph.js | 24 ++++++++------ app/assets/javascripts/graphs/width_scale.js | 13 ++++---- app/assets/javascripts/posts.js | 16 ++++----- 7 files changed, 78 insertions(+), 70 deletions(-) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 0ad04350c..fc3369264 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -10,12 +10,12 @@ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD // GO AFTER THE REQUIRES BELOW. // -//= require leaflet -//= require leaflet.markercluster -//= require js-routes -//= require jquery -//= require jquery_ujs -//= require jquery-ui/autocomplete -//= require bootstrap-sprockets -//= require bootstrap-datepicker -//= require_tree . +// = require leaflet +// = require leaflet.markercluster +// = require js-routes +// = require jquery +// = require jquery_ujs +// = require jquery-ui/autocomplete +// = require bootstrap-sprockets +// = require bootstrap-datepicker +// = require_tree . diff --git a/app/assets/javascripts/graphs/bar_group.js b/app/assets/javascripts/graphs/bar_group.js index ceff6afdf..a6abaa150 100644 --- a/app/assets/javascripts/graphs/bar_group.js +++ b/app/assets/javascripts/graphs/bar_group.js @@ -1,7 +1,7 @@ -//= require graphs/width_scale -//= require graphs/height_scale +// = require graphs/width_scale +// = require graphs/height_scale -(function(){ +(function() { 'use strict'; /* @@ -17,34 +17,33 @@ function BarGroup(data) { this._data = data; } -BarGroup.prototype.render = function(root){ - +BarGroup.prototype.render = function(root) { var data = this._data; var bars = this._data.bars; var widthScale = new WidthScale(data).render(); var heightScale = new HeightScale(data).render(); return root.append('g') - .attr("class", "bar") - .selectAll("rect") - .data(bars.map(function(bar) { return bar.value; })) + .attr('class', 'bar') + .selectAll('rect') + .data(bars.map(function(bar) { + return bar.value; +})) .enter() - .append("rect") - .attr("y", function(d, i){ + .append('rect') + .attr('y', function(d, i) { return heightScale(i); - }) - .attr("height", heightScale.rangeBand()) - .attr("fill", data.bar_color) - .attr("width", function(d){ + .attr('height', heightScale.rangeBand()) + .attr('fill', data.bar_color) + .attr('width', function(d) { return widthScale(d); }) - .append("title") - .text(function(d){ + .append('title') + .text(function(d) { return 'This value is ' + d + '.'; }); }; growstuff.BarGroup = BarGroup; - }()); diff --git a/app/assets/javascripts/graphs/bar_label_group.js b/app/assets/javascripts/graphs/bar_label_group.js index bfe2eee51..e60073743 100644 --- a/app/assets/javascripts/graphs/bar_label_group.js +++ b/app/assets/javascripts/graphs/bar_label_group.js @@ -11,30 +11,32 @@ This file draws the labels to the left of each bar. this._data = data; } - BarLabelGroup.prototype.render = function(d3){ + BarLabelGroup.prototype.render = function(d3) { var bars = this._data.bars; - //vvcopy pasta from spike vv -- this is a good candidate for refactor + // vvcopy pasta from spike vv -- this is a good candidate for refactor var barHeight = 40; return d3.append('g') - .attr("class", "bar-label") - .selectAll("text") - .data(bars.map(function(bar){ return bar.name;})) + .attr('class', 'bar-label') + .selectAll('text') + .data(bars.map(function(bar) { + return bar.name; +})) .enter() - .append("text") + .append('text') .attr('x', -80) - .attr('y', function(d, i){ - //shrink the margin between each label to give them an even spread with - //bars + .attr('y', function(d, i) { + // shrink the margin between each label to give them an even spread with + // bars var barLabelSpread = 2/3; - //move them downward to line up with bars + // move them downward to line up with bars var barLabelTopEdge = 17; return i * barHeight * (barLabelSpread) + barLabelTopEdge; }) - .text(function(d){return d;}); - + .text(function(d) { +return d; +}); }; growstuff.BarLabelGroup = BarLabelGroup; - -}()); \ No newline at end of file +}()); diff --git a/app/assets/javascripts/graphs/height_scale.js b/app/assets/javascripts/graphs/height_scale.js index 7521d50f0..8abc636c9 100644 --- a/app/assets/javascripts/graphs/height_scale.js +++ b/app/assets/javascripts/graphs/height_scale.js @@ -1,20 +1,23 @@ -//=require d3 +// =require d3 /* Height Scale is used to map the number of bars to the display size of the svg */ -(function(){ +(function() { 'use strict'; var growstuff = (window.growstuff = window.growstuff || {}); - function HeightScale(data){ + /** + * new heighscale object + */ + function HeightScale(data) { this._data = data; } - HeightScale.prototype.render = function(){ + HeightScale.prototype.render = function() { var data = this._data; var scaleType = data.height.scale; var axisSize = data.height.size; @@ -25,5 +28,4 @@ the svg }; growstuff.HeightScale = HeightScale; - -}()); \ No newline at end of file +}()); diff --git a/app/assets/javascripts/graphs/horizontal_bar_graph.js b/app/assets/javascripts/graphs/horizontal_bar_graph.js index 9760138fb..856bca885 100644 --- a/app/assets/javascripts/graphs/horizontal_bar_graph.js +++ b/app/assets/javascripts/graphs/horizontal_bar_graph.js @@ -1,6 +1,6 @@ -//= require d3 -//= require graphs/bar_group -//= require graphs/bar_label_group +// = require d3 +// = require graphs/bar_group +// = require graphs/bar_label_group /* Horizontal Bar Graph represents sum total of the graph including all of the parts: @@ -17,6 +17,10 @@ The main dimensions of the graph are rendered here. var BarGroup = growstuff.BarGroup; var BarLabelGroup = growstuff.BarLabelGroup; + /** + * create a new graph object + * @param {??} bar graph data + */ function HorizontalBarGraph(data) { this._data = data; this._d3 = d3; @@ -33,12 +37,12 @@ The main dimensions of the graph are rendered here. var barGroup = new BarGroup(this._data); var svg = root - .append("svg") - .attr("width", width.size + margin.left + margin.right) - .attr("height", height.size + margin.top + margin.bottom) - .append("g") - .attr("class","bar-graph") - .attr("transform","translate(" + margin.left + "," + margin.top + ")"); + .append('svg') + .attr('width', width.size + margin.left + margin.right) + .attr('height', height.size + margin.top + margin.bottom) + .append('g') + .attr('class', 'bar-graph') + .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); barGroup.render(svg); @@ -48,4 +52,4 @@ The main dimensions of the graph are rendered here. }; growstuff.HorizontalBarGraph = HorizontalBarGraph; -}()); \ No newline at end of file +}()); diff --git a/app/assets/javascripts/graphs/width_scale.js b/app/assets/javascripts/graphs/width_scale.js index d8997c8c9..4a5c71e19 100644 --- a/app/assets/javascripts/graphs/width_scale.js +++ b/app/assets/javascripts/graphs/width_scale.js @@ -1,16 +1,16 @@ -//=require d3 +// =require d3 /* Width scale is used to map the value for the length of each bar to the display size of the svg */ -(function(){ +(function() { 'use strict'; var growstuff = (window.growstuff = window.growstuff || {}); - function WidthScale (data){ + function WidthScale(data) { this._data = data; } @@ -24,10 +24,11 @@ to the display size of the svg .range([0, axisSize]); }; - WidthScale.prototype.getMaxValue = function(){ - return d3.max(this._data.bars.map(function(bar) { return bar.value; })); + WidthScale.prototype.getMaxValue = function() { + return d3.max(this._data.bars.map(function(bar) { + return bar.value; +})); }; growstuff.WidthScale = WidthScale; - }()); diff --git a/app/assets/javascripts/posts.js b/app/assets/javascripts/posts.js index c2cf3ff4e..94fe0fb92 100644 --- a/app/assets/javascripts/posts.js +++ b/app/assets/javascripts/posts.js @@ -1,4 +1,4 @@ -$(document).ready(function () { +$(document).ready(function() { $('.post-like').show(); $('.post-like').on('ajax:success', function(event, data) { @@ -6,13 +6,13 @@ $(document).ready(function () { $('#post-' + data.id + ' .like-count').text(data.description); if (data.liked_by_member) { - like_control.data("method", "delete"); - like_control.attr("href", data.url); - like_control.text("Unlike"); + like_control.data('method', 'delete'); + like_control.attr('href', data.url); + like_control.text('Unlike'); } else { - like_control.data("method", "post"); - like_control.attr("href", '/likes.json?post_id=' + data.id); - like_control.text("Like"); + like_control.data('method', 'post'); + like_control.attr('href', '/likes.json?post_id=' + data.id); + like_control.text('Like'); } }); -}); \ No newline at end of file +}); From 0db2d6b3464d6ef42056c5939b3393fba59f116a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 12:42:20 +1300 Subject: [PATCH 007/267] converted variable to camel case --- app/assets/javascripts/posts.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/posts.js b/app/assets/javascripts/posts.js index 94fe0fb92..37269e78e 100644 --- a/app/assets/javascripts/posts.js +++ b/app/assets/javascripts/posts.js @@ -2,17 +2,17 @@ $(document).ready(function() { $('.post-like').show(); $('.post-like').on('ajax:success', function(event, data) { - var like_control = $('#post-' + data.id + ' .post-like'); + var likeControl = $('#post-' + data.id + ' .post-like'); $('#post-' + data.id + ' .like-count').text(data.description); if (data.liked_by_member) { - like_control.data('method', 'delete'); - like_control.attr('href', data.url); - like_control.text('Unlike'); + likeControl.data('method', 'delete'); + likeControl.attr('href', data.url); + likeControl.text('Unlike'); } else { - like_control.data('method', 'post'); - like_control.attr('href', '/likes.json?post_id=' + data.id); - like_control.text('Like'); + likeControl.data('method', 'post'); + likeControl.attr('href', '/likes.json?post_id=' + data.id); + likeControl.text('Like'); } }); }); From 7c251615746cc3d417ce26c72c9739872c519210 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 12:48:13 +1300 Subject: [PATCH 008/267] contributors/commits update --- CONTRIBUTORS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 69c9fd2e4..f984400ae 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -8,14 +8,15 @@ submit the change with your pull request. ## Committers -- Alex Bayley / [Skud](https://github.com/Skud) - Cesy / [cesy](https://github.com/cesy) - Miles Gould / [pozorvlak](https://github.com/pozorvlak) -- Taylor Griffin / [tygriffin](https://github.com/tygriffin) - Mackenzie Morgan / [maco](https://github.com/maco) +- Brenda Wallace / [br3nda](https://github.com/br3nda) ## Contributors +- Alex Bayley / [Skud](https://github.com/Skud) +- Taylor Griffin / [tygriffin](https://github.com/tygriffin) - Joseph Caudle / [jcaudle](https://github.com/jcaudle) - Ricky Amianym / [amianym](https://github.com/amianym) - Juliet Kemp / [julietk](https://github.com/julietk) @@ -73,7 +74,6 @@ submit the change with your pull request. - Lucas Nogueira / [lucasnogueira](https://github.com/lucasnogueira) - Charley Lewittes / [ctlewitt](https://github.com/ctlewitt) - Kristine Nicole Polvoriza / [polveenomials](https://github.com/polveenomials) -- Brenda Wallace / [br3nda](https://github.com/br3nda) - Jim Stallings / [jestallin](https://github.com/jestallin) - Alyssa Ransbury / [alran](https://github.com/alran) - Thomas Countz / [thomascountz](https://github.com/thomascountz) From e910bfd50fa76aec98139cb2e5effd7a5eb5cb4b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 12:54:33 +1300 Subject: [PATCH 009/267] added JSDoc --- app/assets/javascripts/graphs/bar_group.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/javascripts/graphs/bar_group.js b/app/assets/javascripts/graphs/bar_group.js index a6abaa150..312fcd6f3 100644 --- a/app/assets/javascripts/graphs/bar_group.js +++ b/app/assets/javascripts/graphs/bar_group.js @@ -13,6 +13,10 @@ var WidthScale = growstuff.WidthScale; var HeightScale = growstuff.HeightScale; +/** + * data object for bar group + * @param {int} data The graph data + */ function BarGroup(data) { this._data = data; } From 591c95dca2a6f49d27d8fd2ebea04b0486f2d839 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 12:56:52 +1300 Subject: [PATCH 010/267] added JSDoc --- app/assets/javascripts/graphs/width_scale.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/assets/javascripts/graphs/width_scale.js b/app/assets/javascripts/graphs/width_scale.js index 4a5c71e19..891cfaf96 100644 --- a/app/assets/javascripts/graphs/width_scale.js +++ b/app/assets/javascripts/graphs/width_scale.js @@ -10,6 +10,10 @@ to the display size of the svg var growstuff = (window.growstuff = window.growstuff || {}); + /** + * Object for WidthScale + * @param {?} data Graph data + */ function WidthScale(data) { this._data = data; } From 122a7f17e211173c8ab162e5db93c80d2e37d2eb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 13:00:09 +1300 Subject: [PATCH 011/267] Fix up JSDoc --- app/assets/javascripts/graphs/bar_group.js | 2 +- app/assets/javascripts/graphs/height_scale.js | 1 + app/assets/javascripts/graphs/horizontal_bar_graph.js | 2 +- app/assets/javascripts/graphs/width_scale.js | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/graphs/bar_group.js b/app/assets/javascripts/graphs/bar_group.js index 312fcd6f3..cb6bf0ef6 100644 --- a/app/assets/javascripts/graphs/bar_group.js +++ b/app/assets/javascripts/graphs/bar_group.js @@ -15,7 +15,7 @@ /** * data object for bar group - * @param {int} data The graph data + * @param {Object} graph configuration */ function BarGroup(data) { this._data = data; diff --git a/app/assets/javascripts/graphs/height_scale.js b/app/assets/javascripts/graphs/height_scale.js index 8abc636c9..c4034a349 100644 --- a/app/assets/javascripts/graphs/height_scale.js +++ b/app/assets/javascripts/graphs/height_scale.js @@ -12,6 +12,7 @@ the svg /** * new heighscale object + * @param {Object} data Graph configuration */ function HeightScale(data) { this._data = data; diff --git a/app/assets/javascripts/graphs/horizontal_bar_graph.js b/app/assets/javascripts/graphs/horizontal_bar_graph.js index 856bca885..12dcae588 100644 --- a/app/assets/javascripts/graphs/horizontal_bar_graph.js +++ b/app/assets/javascripts/graphs/horizontal_bar_graph.js @@ -19,7 +19,7 @@ The main dimensions of the graph are rendered here. /** * create a new graph object - * @param {??} bar graph data + * @param {Object} data Graph configuration */ function HorizontalBarGraph(data) { this._data = data; diff --git a/app/assets/javascripts/graphs/width_scale.js b/app/assets/javascripts/graphs/width_scale.js index 891cfaf96..3ddd0decf 100644 --- a/app/assets/javascripts/graphs/width_scale.js +++ b/app/assets/javascripts/graphs/width_scale.js @@ -12,7 +12,7 @@ to the display size of the svg /** * Object for WidthScale - * @param {?} data Graph data + * @param {Object} data Graph configuration */ function WidthScale(data) { this._data = data; From 4570fda3846788500733442185bc5accddc145be Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 13:03:10 +1300 Subject: [PATCH 012/267] removed 2 unused variable in js --- app/assets/javascripts/graphs/height_scale.js | 1 - app/assets/javascripts/graphs/horizontal_bar_graph.js | 1 - 2 files changed, 2 deletions(-) diff --git a/app/assets/javascripts/graphs/height_scale.js b/app/assets/javascripts/graphs/height_scale.js index c4034a349..6a4f29528 100644 --- a/app/assets/javascripts/graphs/height_scale.js +++ b/app/assets/javascripts/graphs/height_scale.js @@ -21,7 +21,6 @@ the svg HeightScale.prototype.render = function() { var data = this._data; var scaleType = data.height.scale; - var axisSize = data.height.size; return d3.scale[scaleType]() .domain(d3.range(data.bars.length)) diff --git a/app/assets/javascripts/graphs/horizontal_bar_graph.js b/app/assets/javascripts/graphs/horizontal_bar_graph.js index 12dcae588..ea3853e94 100644 --- a/app/assets/javascripts/graphs/horizontal_bar_graph.js +++ b/app/assets/javascripts/graphs/horizontal_bar_graph.js @@ -27,7 +27,6 @@ The main dimensions of the graph are rendered here. } HorizontalBarGraph.prototype.render = function(root) { - var bars = this._data.bars; var width = this._data.width; var height = this._data.height; From 978317f47a13937539d2c80aba6e8d2dcc239e5f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 14:20:01 +1300 Subject: [PATCH 013/267] more JSDoc --- app/assets/javascripts/graphs/bar_group.js | 2 +- app/assets/javascripts/graphs/bar_label_group.js | 4 ++++ app/assets/javascripts/graphs/height_scale.js | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/graphs/bar_group.js b/app/assets/javascripts/graphs/bar_group.js index cb6bf0ef6..a0d18050d 100644 --- a/app/assets/javascripts/graphs/bar_group.js +++ b/app/assets/javascripts/graphs/bar_group.js @@ -15,7 +15,7 @@ /** * data object for bar group - * @param {Object} graph configuration + * @param {Object} data Graph configuration */ function BarGroup(data) { this._data = data; diff --git a/app/assets/javascripts/graphs/bar_label_group.js b/app/assets/javascripts/graphs/bar_label_group.js index e60073743..3c574d6ad 100644 --- a/app/assets/javascripts/graphs/bar_label_group.js +++ b/app/assets/javascripts/graphs/bar_label_group.js @@ -7,6 +7,10 @@ This file draws the labels to the left of each bar. var growstuff = (window.growstuff = window.growstuff || {}); + /** + * new bar label object + * @param {Object} data Graph configuration + */ function BarLabelGroup(data) { this._data = data; } diff --git a/app/assets/javascripts/graphs/height_scale.js b/app/assets/javascripts/graphs/height_scale.js index 6a4f29528..f4b76a044 100644 --- a/app/assets/javascripts/graphs/height_scale.js +++ b/app/assets/javascripts/graphs/height_scale.js @@ -11,7 +11,7 @@ the svg var growstuff = (window.growstuff = window.growstuff || {}); /** - * new heighscale object + * new height scale object * @param {Object} data Graph configuration */ function HeightScale(data) { From 2d98a7e793a4a12ca3012a4a80847cdbaa315063 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 14:21:29 +1300 Subject: [PATCH 014/267] Wrapped a long line --- spec/javascripts/graphs/horizontal_bar_graph_spec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/javascripts/graphs/horizontal_bar_graph_spec.js b/spec/javascripts/graphs/horizontal_bar_graph_spec.js index b8fbed1a3..16f35f018 100644 --- a/spec/javascripts/graphs/horizontal_bar_graph_spec.js +++ b/spec/javascripts/graphs/horizontal_bar_graph_spec.js @@ -61,7 +61,8 @@ expect('g.bar-graph').toHaveAttr('transform', 'translate(100,0)'); }); - it('on the x axis, draws at least one bar at max width less margin width because of domain and range mapping', function() { + it('on the x axis, draws at least one bar at max width less margin width', function() { + // because of domain and range mapping expect('g.bar rect:eq(1)').toHaveAttr('width', '300' ); }); From 56b056278542c9979f91dcf48b831a416624f540 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 14:24:08 +1300 Subject: [PATCH 015/267] Removed unused variables in js --- spec/javascripts/graphs/bar_group_spec.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spec/javascripts/graphs/bar_group_spec.js b/spec/javascripts/graphs/bar_group_spec.js index 50af8d3a8..a76992a6c 100644 --- a/spec/javascripts/graphs/bar_group_spec.js +++ b/spec/javascripts/graphs/bar_group_spec.js @@ -6,10 +6,9 @@ */ describe('when drawing the group of bars', function() { - var BarGroup; var subject; var widthScale; var bars; var data; + var BarGroup; var subject; var bars; var data; beforeEach(function() { - var WidthScale = growstuff.WidthScale; BarGroup = growstuff.BarGroup; bars = [ @@ -24,7 +23,6 @@ height: {size: 400, scale: 'ordinal'}, }; - widthScale = new WidthScale(data); subject = new BarGroup(data); subject.render(d3.select('#jasmine_content').append('svg')); }); From 0a71bfe99f6fdb6f1fea3d1a7f63d6ad1d9497eb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 14:40:22 +1300 Subject: [PATCH 016/267] Tabulation and jsdoc fixes --- app/assets/javascripts/graphs/bar_group.js | 36 +++++++++---------- .../javascripts/graphs/bar_label_group.js | 17 +++++---- app/assets/javascripts/graphs/height_scale.js | 6 ++-- .../graphs/horizontal_bar_graph.js | 12 +++---- app/assets/javascripts/graphs/width_scale.js | 7 ++-- 5 files changed, 38 insertions(+), 40 deletions(-) diff --git a/app/assets/javascripts/graphs/bar_group.js b/app/assets/javascripts/graphs/bar_group.js index a0d18050d..e8a90c20a 100644 --- a/app/assets/javascripts/graphs/bar_group.js +++ b/app/assets/javascripts/graphs/bar_group.js @@ -1,13 +1,14 @@ +// =require d3 // = require graphs/width_scale // = require graphs/height_scale +/* + * This represents bars for a bar graph. + * Currently these are used for HorizontalBarGraph. + */ (function() { 'use strict'; - /* - This represents bars for a bar graph. - Currently these are used for HorizontalBarGraph. - */ var growstuff = (window.growstuff = window.growstuff || {}); var WidthScale = growstuff.WidthScale; @@ -20,19 +21,18 @@ function BarGroup(data) { this._data = data; } + BarGroup.prototype.render = function(root) { + var data = this._data; + var bars = this._data.bars; + var widthScale = new WidthScale(data).render(); + var heightScale = new HeightScale(data).render(); -BarGroup.prototype.render = function(root) { - var data = this._data; - var bars = this._data.bars; - var widthScale = new WidthScale(data).render(); - var heightScale = new HeightScale(data).render(); - - return root.append('g') - .attr('class', 'bar') - .selectAll('rect') - .data(bars.map(function(bar) { - return bar.value; -})) + return root.append('g') + .attr('class', 'bar') + .selectAll('rect') + .data(bars.map(function(bar) { + return bar.value; + })) .enter() .append('rect') .attr('y', function(d, i) { @@ -47,7 +47,7 @@ BarGroup.prototype.render = function(root) { .text(function(d) { return 'This value is ' + d + '.'; }); -}; + }; -growstuff.BarGroup = BarGroup; + growstuff.BarGroup = BarGroup; }()); diff --git a/app/assets/javascripts/graphs/bar_label_group.js b/app/assets/javascripts/graphs/bar_label_group.js index 3c574d6ad..2da31f567 100644 --- a/app/assets/javascripts/graphs/bar_label_group.js +++ b/app/assets/javascripts/graphs/bar_label_group.js @@ -1,12 +1,11 @@ +// =require d3 +/** + * This file draws the labels to the left of each bar. + */ (function() { 'use strict'; -/* -This file draws the labels to the left of each bar. - */ - var growstuff = (window.growstuff = window.growstuff || {}); - /** * new bar label object * @param {Object} data Graph configuration @@ -24,8 +23,8 @@ This file draws the labels to the left of each bar. .attr('class', 'bar-label') .selectAll('text') .data(bars.map(function(bar) { - return bar.name; -})) + return bar.name; + })) .enter() .append('text') .attr('x', -80) @@ -38,8 +37,8 @@ This file draws the labels to the left of each bar. return i * barHeight * (barLabelSpread) + barLabelTopEdge; }) .text(function(d) { -return d; -}); + return d; + }); }; growstuff.BarLabelGroup = BarLabelGroup; diff --git a/app/assets/javascripts/graphs/height_scale.js b/app/assets/javascripts/graphs/height_scale.js index f4b76a044..5189ef800 100644 --- a/app/assets/javascripts/graphs/height_scale.js +++ b/app/assets/javascripts/graphs/height_scale.js @@ -1,8 +1,8 @@ // =require d3 -/* -Height Scale is used to map the number of bars to the display size of -the svg +/** + * Height Scale is used to map the number of bars to the display size of + * the svg */ (function() { diff --git a/app/assets/javascripts/graphs/horizontal_bar_graph.js b/app/assets/javascripts/graphs/horizontal_bar_graph.js index ea3853e94..ef2333ef1 100644 --- a/app/assets/javascripts/graphs/horizontal_bar_graph.js +++ b/app/assets/javascripts/graphs/horizontal_bar_graph.js @@ -2,12 +2,12 @@ // = require graphs/bar_group // = require graphs/bar_label_group -/* -Horizontal Bar Graph represents sum total of the graph including all of the parts: -Bars -Bar Labels - -The main dimensions of the graph are rendered here. +/** + * Horizontal Bar Graph represents sum total of the graph including all of the parts: + * Bars + * Bar Labels + * + * The main dimensions of the graph are rendered here. */ (function() { diff --git a/app/assets/javascripts/graphs/width_scale.js b/app/assets/javascripts/graphs/width_scale.js index 3ddd0decf..4ba275eda 100644 --- a/app/assets/javascripts/graphs/width_scale.js +++ b/app/assets/javascripts/graphs/width_scale.js @@ -1,10 +1,9 @@ // =require d3 -/* -Width scale is used to map the value for the length of each bar -to the display size of the svg +/** + * Width scale is used to map the value for the length of each bar + * to the display size of the svg */ - (function() { 'use strict'; From ee1617c7c3cdf0573fca117d97080be9c9b1fea9 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 14:43:29 +1300 Subject: [PATCH 017/267] Added new line at end of file --- spec/javascripts/support/spec_helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/javascripts/support/spec_helper.js b/spec/javascripts/support/spec_helper.js index 465207cf3..f9d26ae25 100644 --- a/spec/javascripts/support/spec_helper.js +++ b/spec/javascripts/support/spec_helper.js @@ -3,4 +3,4 @@ beforeEach(function() { $(document).off(); $('body').off(); $('#jasmine_content').replaceWith($('
')); -}); \ No newline at end of file +}); From a39c304fac6d06ea4701da360ab1256b11cda884 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 15:06:55 +1300 Subject: [PATCH 018/267] Fix ordering of crops' parent on form --- app/views/crops/_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/crops/_form.html.haml b/app/views/crops/_form.html.haml index c391c79d2..a8cfe0bea 100644 --- a/app/views/crops/_form.html.haml +++ b/app/views/crops/_form.html.haml @@ -51,7 +51,7 @@ .form-group = f.label :parent_id, 'Parent crop', class: 'control-label col-md-2' .col-md-8 - = collection_select(:crop, :parent_id, Crop.all, :id, :name, { include_blank: true }, class: 'form-control') + = collection_select(:crop, :parent_id, Crop.all.order(:name), :id, :name, { include_blank: true }, class: 'form-control') %span.help-block Optional. For setting up crop hierarchies for varieties etc. From d86de897c74aded2180c312badc8657c7317ae0d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 15:12:09 +1300 Subject: [PATCH 019/267] Wrap long line --- app/views/crops/_form.html.haml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/crops/_form.html.haml b/app/views/crops/_form.html.haml index a8cfe0bea..c16041f97 100644 --- a/app/views/crops/_form.html.haml +++ b/app/views/crops/_form.html.haml @@ -51,7 +51,8 @@ .form-group = f.label :parent_id, 'Parent crop', class: 'control-label col-md-2' .col-md-8 - = collection_select(:crop, :parent_id, Crop.all.order(:name), :id, :name, { include_blank: true }, class: 'form-control') + = collection_select(:crop, :parent_id, Crop.all.order(:name), :id, :name, + { include_blank: true }, class: 'form-control') %span.help-block Optional. For setting up crop hierarchies for varieties etc. From 26f525e88acb28dc6ca9132b437bdfdf5d3d47c6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 17:06:54 +1300 Subject: [PATCH 020/267] Upgrade gems for rails 5 Note: Unlocks elastic search gem, and removes debuggers --- Gemfile | 24 +++-- Gemfile.lock | 260 ++++++++++++++++++++++----------------------------- 2 files changed, 123 insertions(+), 161 deletions(-) diff --git a/Gemfile b/Gemfile index c5d5d1fe1..a5c7b7dce 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ source 'https://rubygems.org' ruby '2.4.1' -gem 'rails', '~> 4.2.8' +gem 'rails', '5.1.4' gem 'bundler', '>=1.1.5' @@ -22,7 +22,7 @@ gem 'font-awesome-sass' gem 'uglifier' # JavaScript compressor # planting and harvest predictions -gem 'active_median' +# gem 'active_median' gem 'flickraw' gem 'jquery-rails' @@ -88,7 +88,7 @@ gem 'd3-rails', '~> 3.5' # 4.* produces Error: : could not find an objec # Project does not use semver, so we want to be in sync with the version of # elasticsearch we use # See https://github.com/elastic/elasticsearch-ruby#compatibility -gem "elasticsearch-api", "~> 2.0.0" +gem "elasticsearch-api" gem "elasticsearch-model" gem "elasticsearch-rails" gem "hashie", ">= 3.5.3" @@ -99,7 +99,7 @@ gem 'rake', '>= 10.0.0' gem "responders" # allows soft delete. Used for members. -gem 'acts_as_paranoid', '~> 0.5.0' +gem "paranoia", "~> 2.2" gem 'xmlrpc' # fixes rake error - can be removed if not needed later @@ -113,16 +113,14 @@ group :production, :staging do end group :development do - # A debugger and irb alternative. Pry doesn't play nice - # with unicorn, so start a Webrick server when debugging - # with Pry - gem 'better_errors', '~> 2.2.0' - gem 'binding_of_caller' - gem 'guard' - gem 'guard-rspec' + gem 'better_errors' gem 'letter_opener' - gem 'pry' - gem 'quiet_assets' + gem 'listen' + # gem 'binding_of_caller' + # gem 'guard' + # gem 'guard-rspec' + # gem 'pry' + # gem 'quiet_assets' end group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index 31113ea38..bc54de685 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,71 +2,67 @@ GEM remote: https://rubygems.org/ remote: https://rails-assets.org/ specs: - actionmailer (4.2.10) - actionpack (= 4.2.10) - actionview (= 4.2.10) - activejob (= 4.2.10) + actioncable (5.1.4) + actionpack (= 5.1.4) + nio4r (~> 2.0) + websocket-driver (~> 0.6.1) + actionmailer (5.1.4) + actionpack (= 5.1.4) + actionview (= 5.1.4) + activejob (= 5.1.4) mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.10) - actionview (= 4.2.10) - activesupport (= 4.2.10) - rack (~> 1.6) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) + rails-dom-testing (~> 2.0) + actionpack (5.1.4) + actionview (= 5.1.4) + activesupport (= 5.1.4) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.10) - activesupport (= 4.2.10) + actionview (5.1.4) + activesupport (= 5.1.4) builder (~> 3.1) - erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) active_link_to (1.0.5) actionpack addressable - active_median (0.1.4) - activerecord active_merchant-paypal-bogus-gateway (0.1.0) activemerchant active_utils (3.3.9) activesupport (>= 3.2, < 5.2.0) i18n - activejob (4.2.10) - activesupport (= 4.2.10) - globalid (>= 0.3.0) + activejob (5.1.4) + activesupport (= 5.1.4) + globalid (>= 0.3.6) activemerchant (1.75.0) activesupport (>= 3.2.14, < 6.x) builder (>= 2.1.2, < 4.0.0) i18n (>= 0.6.9) nokogiri (~> 1.4) - activemodel (4.2.10) - activesupport (= 4.2.10) - builder (~> 3.1) - activerecord (4.2.10) - activemodel (= 4.2.10) - activesupport (= 4.2.10) - arel (~> 6.0) - activesupport (4.2.10) + activemodel (5.1.4) + activesupport (= 5.1.4) + activerecord (5.1.4) + activemodel (= 5.1.4) + activesupport (= 5.1.4) + arel (~> 8.0) + activesupport (5.1.4) + concurrent-ruby (~> 1.0, >= 1.0.2) i18n (~> 0.7) minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - acts_as_paranoid (0.5.0) - activerecord (>= 4.0, < 5.1) - activesupport (>= 4.0, < 5.1) addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) - arel (6.0.4) + arel (8.0.0) ast (2.3.0) - autoprefixer-rails (7.2.3) + autoprefixer-rails (7.2.4) execjs bcrypt (3.1.11) - better_errors (2.2.0) + better_errors (2.4.0) coderay (>= 1.0.0) - erubis (>= 2.6.6) + erubi (>= 1.0.0) rack (>= 0.9.0) - binding_of_caller (0.7.3) - debug_inspector (>= 0.0.1) bluecloth (2.2.0) bonsai-elasticsearch-rails (0.2.0) elasticsearch-model (~> 0) @@ -79,20 +75,19 @@ GEM bootstrap-sass (3.3.7) autoprefixer-rails (>= 5.2.1) sass (>= 3.3.4) - bootstrap_form (2.7.0) builder (3.2.3) bullet (5.7.0) activesupport (>= 3.0.0) uniform_notifier (~> 1.10.0) byebug (9.1.0) cancancan (2.1.2) - capybara (2.16.1) + capybara (2.17.0) addressable mini_mime (>= 0.1.3) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) - xpath (~> 2.0) + xpath (>= 2.0, < 4.0) capybara-email (2.5.0) capybara (~> 2.4) mail @@ -105,10 +100,8 @@ GEM cliver (0.3.2) cocaine (0.5.8) climate_control (>= 0.0.3, < 1.0) - codeclimate-test-reporter (1.0.8) - simplecov (<= 0.13) - codemirror-rails (5.16.0) - railties (>= 3.0, < 6.0) + codeclimate-test-reporter (1.0.7) + simplecov coderay (1.1.2) coffee-rails (4.2.2) coffee-script (>= 2.2.0) @@ -117,29 +110,25 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - comfortable_mexican_sofa (1.12.10) + comfortable_mexican_sofa (1.8.2) active_link_to (>= 1.0.0) - bootstrap-sass (>= 3.2.0) - bootstrap_form (>= 2.2.0) - codemirror-rails (>= 3.0.0) coffee-rails (>= 3.1.0) + formatted_form (>= 2.1.0) haml-rails (>= 0.3.0) jquery-rails (>= 3.0.0) - jquery-ui-rails (>= 5.0.0) - kramdown (>= 1.0.0) - paperclip (>= 4.0.0) - plupload-rails (>= 1.2.1) - rails (>= 4.0.0, < 5.1) - rails-i18n (>= 4.0.0) - sass-rails (>= 4.0.3) + jquery-ui-rails (>= 4.0.0) + paperclip (>= 3.4.0) + rails (>= 3.1.0) + redcarpet (>= 2.2.0) + sass-rails (>= 3.1.0) concurrent-ruby (1.0.5) connection_pool (2.2.1) - coveralls (0.8.19) - json (>= 1.8, < 3) - simplecov (~> 0.12.0) - term-ansicolor (~> 1.3) - thor (~> 0.19.1) - tins (~> 1.6) + coveralls (0.7.1) + multi_json (~> 1.3) + rest-client + simplecov (>= 0.7) + term-ansicolor + thor crass (1.0.3) csv_shaper (1.3.0) activesupport (>= 3.0.0) @@ -147,8 +136,7 @@ GEM railties (>= 3.1) dalli (2.7.6) database_cleaner (1.6.2) - debug_inspector (0.0.3) - devise (4.3.0) + devise (4.4.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0, < 5.2) @@ -156,23 +144,26 @@ GEM warden (~> 1.2.3) diff-lcs (1.3) docile (1.1.5) + domain_name (0.5.20170404) + unf (>= 0.0.5, < 1.0.0) easy_translate (0.5.0) json thread thread_safe - elasticsearch (2.0.2) - elasticsearch-api (= 2.0.2) - elasticsearch-transport (= 2.0.2) - elasticsearch-api (2.0.2) + elasticsearch (6.0.0) + elasticsearch-api (= 6.0.0) + elasticsearch-transport (= 6.0.0) + elasticsearch-api (6.0.0) multi_json elasticsearch-model (0.1.9) activesupport (> 3) elasticsearch (> 0.4) hashie elasticsearch-rails (0.1.9) - elasticsearch-transport (2.0.2) + elasticsearch-transport (6.0.0) faraday multi_json + erubi (1.7.0) erubis (2.7.0) excon (0.60.0) execjs (2.7.0) @@ -191,7 +182,8 @@ GEM flickraw (0.9.9) font-awesome-sass (4.7.0) sass (>= 3.2) - formatador (0.2.5) + formatted_form (2.1.2) + rails (>= 3.1) friendly_id (5.2.3) activerecord (>= 4.0.0) geocoder (1.4.5) @@ -203,20 +195,6 @@ GEM gravatar-ultimate (2.0.0) activesupport (>= 2.3.14) rack - guard (2.14.1) - formatador (>= 0.2.4) - listen (>= 2.7, < 4.0) - lumberjack (~> 1.0) - nenv (~> 0.1) - notiffany (~> 0.0) - pry (>= 0.9.12) - shellany (~> 0.0) - thor (>= 0.18.1) - guard-compat (1.2.1) - guard-rspec (4.7.3) - guard (~> 2.1) - guard-compat (~> 1.1) - rspec (>= 2.99.0, < 4.0) haml (5.0.4) temple (>= 0.8.0) tilt @@ -250,6 +228,8 @@ GEM haml (>= 4.0, < 6) nokogiri (>= 1.6.0) ruby_parser (~> 3.5) + http-cookie (1.0.3) + domain_name (~> 0.5) httparty (0.15.6) multi_xml (>= 0.5.2) i18n (0.9.1) @@ -298,12 +278,11 @@ GEM kaminari-core (= 1.1.1) kaminari-core (1.1.1) kgio (2.11.1) - kramdown (1.16.2) launchy (2.4.3) addressable (~> 2.3) leaflet-rails (1.2.0) rails (>= 4.2.0) - letter_opener (1.4.1) + letter_opener (1.5.0) launchy (~> 2.2) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) @@ -312,7 +291,6 @@ GEM loofah (2.1.1) crass (~> 1.0.2) nokogiri (>= 1.5.9) - lumberjack (1.0.12) mail (2.7.0) mini_mime (>= 0.1.1) memcachier (0.0.2) @@ -323,18 +301,16 @@ GEM mimemagic (0.3.2) mini_mime (1.0.0) mini_portile2 (2.3.0) - minitest (5.10.3) + minitest (5.11.1) moneta (0.8.1) multi_json (1.11.3) multi_xml (0.6.0) multipart-post (2.0.0) - nenv (0.3.0) + netrc (0.11.0) newrelic_rpm (4.7.1.340) + nio4r (2.2.0) nokogiri (1.8.1) mini_portile2 (~> 2.3.0) - notiffany (0.1.1) - nenv (~> 0.1) - shellany (~> 0.0) oauth (0.5.4) oauth2 (1.4.0) faraday (>= 0.8, < 0.13) @@ -342,7 +318,7 @@ GEM multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) - omniauth (1.7.1) + omniauth (1.8.1) hashie (>= 3.4.6, < 3.6.0) rack (>= 1.6.2, < 3) omniauth-facebook (4.0.0) @@ -367,6 +343,8 @@ GEM mime-types mimemagic (~> 0.3.0) parallel (1.12.1) + paranoia (2.4.0) + activerecord (>= 4.0, < 5.2) parser (2.4.0.2) ast (~> 2.3) pg (0.21.0) @@ -374,57 +352,46 @@ GEM platform-api (2.1.0) heroics (~> 0.0.23) moneta (~> 0.8.1) - plupload-rails (1.2.1) - rails (>= 3.1) poltergeist (1.17.0) capybara (~> 2.1) cliver (~> 0.3.1) websocket-driver (>= 0.2.0) powerpack (0.1.1) - pry (0.11.3) - coderay (~> 1.1.0) - method_source (~> 0.9.0) public_suffix (3.0.1) - quiet_assets (1.1.0) - railties (>= 3.1, < 5.0) - rack (1.6.8) + rack (2.0.3) rack-protection (2.0.0) rack - rack-test (0.6.3) - rack (>= 1.0) - rails (4.2.10) - actionmailer (= 4.2.10) - actionpack (= 4.2.10) - actionview (= 4.2.10) - activejob (= 4.2.10) - activemodel (= 4.2.10) - activerecord (= 4.2.10) - activesupport (= 4.2.10) - bundler (>= 1.3.0, < 2.0) - railties (= 4.2.10) - sprockets-rails + rack-test (0.8.2) + rack (>= 1.0, < 3) + rails (5.1.4) + actioncable (= 5.1.4) + actionmailer (= 5.1.4) + actionpack (= 5.1.4) + actionview (= 5.1.4) + activejob (= 5.1.4) + activemodel (= 5.1.4) + activerecord (= 5.1.4) + activesupport (= 5.1.4) + bundler (>= 1.3.0) + railties (= 5.1.4) + sprockets-rails (>= 2.0.0) rails-assets-leaflet (1.2.0) rails-assets-leaflet.markercluster (1.2.0) rails-assets-leaflet (>= 1.0.3) - rails-deprecated_sanitizer (1.0.3) - activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.9) - activesupport (>= 4.2.0, < 5.0) - nokogiri (~> 1.6) - rails-deprecated_sanitizer (>= 1.0.1) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) rails-html-sanitizer (1.0.3) loofah (~> 2.0) - rails-i18n (4.0.9) - i18n (~> 0.7) - railties (~> 4.0) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.5) - railties (4.2.10) - actionpack (= 4.2.10) - activesupport (= 4.2.10) + railties (5.1.4) + actionpack (= 5.1.4) + activesupport (= 5.1.4) + method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) rainbow (2.1.0) @@ -433,14 +400,15 @@ GEM rb-fsevent (0.10.2) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) + redcarpet (3.4.0) redis (4.0.1) responders (2.4.0) actionpack (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3) - rspec (3.7.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) + rest-client (2.0.2) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 4.0) + netrc (~> 0.8) rspec-activemodel-mocks (1.0.3) activemodel (>= 3.0) activesupport (>= 3.0) @@ -490,13 +458,12 @@ GEM childprocess (~> 0.5) rubyzip (~> 1.0) sexp_processor (4.10.0) - shellany (0.0.1) sidekiq (5.0.5) concurrent-ruby (~> 1.0) connection_pool (~> 2.2, >= 2.2.0) rack-protection (>= 1.5.0) redis (>= 3.3.4, < 5) - simplecov (0.12.0) + simplecov (0.15.1) docile (~> 1.1.0) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) @@ -516,7 +483,7 @@ GEM tins (~> 1.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) - thor (0.19.4) + thor (0.20.0) thread (0.2.2) thread_safe (0.3.6) tilt (2.0.8) @@ -525,8 +492,11 @@ GEM trollop (1.16.2) tzinfo (1.2.4) thread_safe (~> 0.1) - uglifier (4.0.2) + uglifier (4.1.2) execjs (>= 0.3.0, < 3) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.4) unicode-display_width (1.3.0) unicorn (5.4.0) kgio (~> 2.6) @@ -538,25 +508,22 @@ GEM nokogiri (>= 1.2.0) rack (>= 1.0) rack-test (>= 0.5.3) - websocket-driver (0.7.0) + websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) will_paginate (3.1.6) xmlrpc (0.3.0) - xpath (2.1.0) - nokogiri (~> 1.3) + xpath (3.0.0) + nokogiri (~> 1.8) PLATFORMS ruby DEPENDENCIES - active_median active_merchant-paypal-bogus-gateway active_utils activemerchant - acts_as_paranoid (~> 0.5.0) - better_errors (~> 2.2.0) - binding_of_caller + better_errors bluecloth bonsai-elasticsearch-rails bootstrap-datepicker-rails @@ -578,7 +545,7 @@ DEPENDENCIES dalli database_cleaner devise - elasticsearch-api (~> 2.0.0) + elasticsearch-api elasticsearch-model elasticsearch-rails factory_bot_rails @@ -590,8 +557,6 @@ DEPENDENCIES geocoder gibbon (~> 1.2.0) gravatar-ultimate - guard - guard-rspec haml haml-i18n-extractor haml-rails @@ -606,18 +571,18 @@ DEPENDENCIES kaminari leaflet-rails letter_opener + listen memcachier newrelic_rpm omniauth (~> 1.3) omniauth-facebook omniauth-flickr (>= 0.0.15) omniauth-twitter + paranoia (~> 2.2) pg platform-api poltergeist - pry - quiet_assets - rails (~> 4.2.8) + rails (= 5.1.4) rails-assets-leaflet.markercluster! rails_12factor rainbow (< 2.2.0) @@ -638,7 +603,6 @@ DEPENDENCIES will_paginate xmlrpc - RUBY VERSION ruby 2.4.1p111 From f1c8743623873d449a54702858904fa3ee253447 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 17:10:50 +1300 Subject: [PATCH 021/267] Config for rails 5 --- config/application.rb | 16 +++---- config/environments/development.rb | 61 +++++++++++++----------- config/environments/production.rb | 74 ++++++++++++++++++------------ config/environments/staging.rb | 2 +- config/environments/test.rb | 43 ++++++++--------- 5 files changed, 109 insertions(+), 87 deletions(-) diff --git a/config/application.rb b/config/application.rb index 5280dce7e..3a07ca429 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,17 +1,17 @@ -require File.expand_path('../boot', __FILE__) +require_relative 'boot' require 'rails/all' require 'openssl' -if defined?(Bundler) - # If you precompile assets before deploying to production, use this line - Bundler.require(*Rails.groups(assets: %w(development test))) - # If you want your assets lazily compiled in production, use this line - # Bundler.require(:default, :assets, Rails.env) -end +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) module Growstuff class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 5.1 + # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers # -- all .rb files in that directory are automatically loaded. @@ -105,6 +105,6 @@ module Growstuff # didn't work for us. config.cloudmade_key = '29a2d9e3cb3d429490a8f338b2388b1d' - config.active_record.raise_in_transactional_callbacks = true + # config.active_record.raise_in_transactional_callbacks = true end end diff --git a/config/environments/development.rb b/config/environments/development.rb index d3242353e..39abd19f1 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,48 +1,57 @@ -Growstuff::Application.configure do - # Settings specified here will take precedence over those in config/application.rb - - # Do not eager load code on boot. - config.eager_load = false +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. config.cache_classes = false - # Show full error reports and disable caching - config.consider_all_requests_local = true + # Do not eager load code on boot. + config.eager_load = false - # cache for testing/experimentation - turn off for normal dev use - config.action_controller.perform_caching = false - config.cache_store = :memory_store + # Show full error reports. + config.consider_all_requests_local = true - # Don't care if the mailer can't send + # Enable/disable caching. By default caching is disabled. + if Rails.root.join('tmp', 'caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false - # Print deprecation notices to the Rails logger + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log - # Only use best-standards-support built into browsers - config.action_dispatch.best_standards_support = :builtin + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load - # Do not compress assets - config.assets.compress = false - - # Expands the lines which load the assets + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. config.assets.debug = true - # Asset digests allow you to set far-future HTTP expiration dates on all assets, - # yet still be able to expire them through the digest params. - config.assets.digest = true - - # Adds additional error checking when serving assets at runtime. - # Checks for improperly declared sprockets dependencies. - # Raises helpful error messages. - config.assets.raise_runtime_errors = true + # Suppress logger output for asset requests. + config.assets.quiet = true # Raises error for missing translations # config.action_view.raise_on_missing_translations = true + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + config.file_watcher = ActiveSupport::EventedFileUpdateChecker + # Growstuff config config.action_mailer.default_url_options = { host: 'localhost:3000' } diff --git a/config/environments/production.rb b/config/environments/production.rb index c931c058e..99e25d577 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,5 +1,8 @@ -Growstuff::Application.configure do - # Settings specified here will take precedence over those in config/application.rb +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true # Eager load code on boot. This eager loads most of Rails and # your application in memory, allowing both threaded web servers @@ -7,57 +10,67 @@ Growstuff::Application.configure do # Rake tasks automatically ignore this option for performance. config.eager_load = true - # Code is not reloaded between requests - config.cache_classes = true - - # Full error reports are disabled and caching is turned on + # Full error reports are disabled and caching is turned on. config.consider_all_requests_local = false config.action_controller.perform_caching = true - # Disable Rails's static asset server (Apache or nginx will already do this) - config.serve_static_files = false + # Attempt to read encrypted secrets from `config/secrets.yml.enc`. + # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or + # `config/secrets.yml.key`. + config.read_encrypted_secrets = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? # Compress JavaScripts and CSS. config.assets.js_compressor = :uglifier - config.assets.css_compressor = :sass + # config.assets.css_compressor = :sass - # Don't fallback to assets pipeline if a precompiled asset is missed - config.assets.compile = true + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false - # Generate digests for assets URLs - config.assets.digest = true + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb - # Specifies the header that your server uses for sending files - # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache - # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true - # See everything in the log (default is :info) - # config.log_level = :debug + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :debug - # Prepend all log lines with the following tags - # config.log_tags = [ :subdomain, :uuid ] + # Prepend all log lines with the following tags. + config.log_tags = [:request_id] - # Use a different logger for distributed setups - # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + # Use a different cache store in production. + # config.cache_store = :mem_cache_store - # Use a different cache store in production - config.cache_store = :dalli_store - - # Enable serving of images, stylesheets, and JavaScripts from an asset server - # config.action_controller.asset_host = "http://assets.example.com" + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "growstuff_#{Rails.env}" + config.action_mailer.perform_caching = false # Ignore bad email addresses and do not raise email delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false # Enable locale fallbacks for I18n (makes lookups for any locale fall back to - # the I18n.default_locale when a translation can not be found) + # the I18n.default_locale when a translation cannot be found). config.i18n.fallbacks = true - # Send deprecation notices to registered listeners + # Send deprecation notices to registered listeners. config.active_support.deprecation = :notify # Use default logging formatter so that PID and timestamp are not suppressed. @@ -103,4 +116,7 @@ Growstuff::Application.configure do end config.active_job.queue_adapter = :sidekiq + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false end diff --git a/config/environments/staging.rb b/config/environments/staging.rb index a9e242381..ce1eeaf7c 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -1,4 +1,4 @@ -Growstuff::Application.configure do +Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb config.action_controller.action_on_unpermitted_parameters = :raise diff --git a/config/environments/test.rb b/config/environments/test.rb index bf4135f64..43a86a23a 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,43 +1,40 @@ -Growstuff::Application.configure do - # Settings specified here will take precedence over those in config/application.rb +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true # Do not eager load code on boot. This avoids loading your whole application # just for the purpose of running a single test. If you are using a tool that # preloads Rails for running tests, you may have to set it to true. config.eager_load = false - # Allow lazy compilation of assets. Required for running Jasmine tests via - # `rake spec:javascript`. - config.assets.compile = true + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{1.hour.seconds.to_i}" + } - # The test environment is used exclusively to run your application's - # test suite. You never need to work with it otherwise. Remember that - # your test database is "scratch space" for the test suite and is wiped - # and recreated between test runs. Don't rely on the data there! - - # Reload model classes when changed: otherwise Spork tests old versions. - config.cache_classes = false - - # Configure static asset server for tests with Cache-Control for performance - config.serve_static_files = true - config.static_cache_control = "public, max-age=3600" - - # Show full error reports and disable caching + # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = false - # Raise exceptions instead of rendering exception templates - config.action_dispatch.show_exceptions = true + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false - # Disable request forgery protection in test environment + # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false + config.action_mailer.perform_caching = false # Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test - # Print deprecation notices to the stderr + # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr # Raises error for missing translations @@ -46,7 +43,7 @@ Growstuff::Application.configure do # Growstuff config config.action_mailer.default_url_options = { host: 'localhost:8080' } - Growstuff::Application.configure do + Rails.application.configure do config.host = 'test.example.com' config.analytics_code = '' config.currency = 'AUD' From f4af682d454e5f1b024a9f6f083b86a32ebefa74 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 17:12:17 +1300 Subject: [PATCH 022/267] Updated code for Rail 5 --- Rakefile | 2 +- app/assets/javascripts/crops.js.erb | 4 +- app/assets/javascripts/members.js.erb | 4 +- app/assets/javascripts/places.js.erb | 6 +- app/controllers/orders_controller.rb | 4 +- app/helpers/application_helper.rb | 4 +- app/models/account.rb | 2 +- app/models/member.rb | 4 +- app/views/layouts/application.html.haml | 2 +- bin/rails | 2 +- bin/setup | 38 ++ bin/update | 29 + bin/yarn | 11 + config.ru | 2 +- config/boot.rb | 7 +- config/cable.yml | 10 + config/environment.rb | 8 +- .../application_controller_renderer.rb | 8 + config/initializers/assets.rb | 14 + config/initializers/cookies_serializer.rb | 5 + .../initializers/filter_parameter_logging.rb | 4 + config/initializers/geocoder.rb | 4 +- config/initializers/inflections.rb | 11 +- config/initializers/mime_types.rb | 1 - .../new_framework_defaults_5_1.rb | 14 + config/initializers/session_store.rb | 4 +- config/initializers/wrap_parameters.rb | 10 +- config/puma.rb | 56 ++ config/routes.rb | 6 +- config/spring.rb | 6 + db/schema.rb | 629 +++++++++--------- db/seeds.rb | 2 +- lib/haml/filters/growstuff_markdown.rb | 2 +- spec/helpers/application_helper_spec.rb | 2 +- .../haml/filters/growstuff_markdown_spec.rb | 2 +- spec/models/member_spec.rb | 2 +- spec/views/layouts/application_spec.rb | 2 +- spec/views/orders/show.html.haml_spec.rb | 2 +- spec/views/shop/index_spec.rb | 8 +- 39 files changed, 551 insertions(+), 382 deletions(-) create mode 100755 bin/setup create mode 100755 bin/update create mode 100755 bin/yarn create mode 100644 config/cable.yml create mode 100644 config/initializers/application_controller_renderer.rb create mode 100644 config/initializers/assets.rb create mode 100644 config/initializers/cookies_serializer.rb create mode 100644 config/initializers/filter_parameter_logging.rb create mode 100644 config/initializers/new_framework_defaults_5_1.rb create mode 100644 config/puma.rb create mode 100644 config/spring.rb diff --git a/Rakefile b/Rakefile index 7e5e8eed3..22553c357 100755 --- a/Rakefile +++ b/Rakefile @@ -5,4 +5,4 @@ require 'rake/dsl_definition' require File.expand_path('../config/application', __FILE__) -Growstuff::Application.load_tasks +Rails.application.load_tasks diff --git a/app/assets/javascripts/crops.js.erb b/app/assets/javascripts/crops.js.erb index afa16a009..f2eec8848 100644 --- a/app/assets/javascripts/crops.js.erb +++ b/app/assets/javascripts/crops.js.erb @@ -1,8 +1,8 @@ //= require graphs/horizontal_bar_graph if (document.getElementById("cropmap") !== null) { - mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>"; - mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>"; + mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Rails.application.config.mapbox_map_id %>"; + mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Rails.application.config.mapbox_access_token %>"; mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token; L.Icon.Default.imagePath = '/assets' diff --git a/app/assets/javascripts/members.js.erb b/app/assets/javascripts/members.js.erb index 500e79b25..1a3158f52 100644 --- a/app/assets/javascripts/members.js.erb +++ b/app/assets/javascripts/members.js.erb @@ -1,6 +1,6 @@ if (document.getElementById("membermap") !== null) { - mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>"; - mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>"; + mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Rails.application.config.mapbox_map_id %>"; + mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Rails.application.config.mapbox_access_token %>"; mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token; L.Icon.Default.imagePath = '/assets' diff --git a/app/assets/javascripts/places.js.erb b/app/assets/javascripts/places.js.erb index 48cb960d7..ad8b76266 100644 --- a/app/assets/javascripts/places.js.erb +++ b/app/assets/javascripts/places.js.erb @@ -1,10 +1,10 @@ if (document.getElementById("placesmap") !== null) { places_base_path = "/places"; - mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>"; - mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>"; + mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Rails.application.config.mapbox_map_id %>"; + mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Rails.application.config.mapbox_access_token %>"; mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token; nominatim_base_url = 'http://nominatim.openstreetmap.org/search/'; - nominatim_user_agent_email = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.user_agent_email %>"; + nominatim_user_agent_email = "<%= Rails.env == 'test' ? 0 : Rails.application.config.user_agent_email %>"; L.Icon.Default.imagePath = '/assets' diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 3bc9fe45c..31c709148 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -34,7 +34,7 @@ class OrdersController < ApplicationController response = EXPRESS_GATEWAY.setup_purchase( @order.total, items: @order.activemerchant_items, - currency: Growstuff::Application.config.currency, + currency: Rails.application.config.currency, no_shipping: true, ip: request.remote_ip, return_url: complete_order_url, @@ -51,7 +51,7 @@ class OrdersController < ApplicationController if params[:token] && params['PayerID'] purchase = EXPRESS_GATEWAY.purchase( @order.total, - currency: Growstuff::Application.config.currency, + currency: Rails.application.config.currency, ip: request.remote_ip, payer_id: params['PayerID'], token: params[:token] diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 639d27686..4e010cef1 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -5,7 +5,7 @@ module ApplicationHelper # 999 cents becomes 9.99 AUD -- for products/orders/etc def price_with_currency(price) - format('%.2f %s', price / 100.0, Growstuff::Application.config.currency) + format('%.2f %s', price / 100.0, Rails.application.config.currency) end def parse_date(str) @@ -15,7 +15,7 @@ module ApplicationHelper def forex_link(price) pid = price_in_dollars(price) - currency = Growstuff::Application.config.currency + currency = Rails.application.config.currency link = "http://www.wolframalpha.com/input/?i=#{pid}+#{currency}" link_to "(convert)", link, target: "_blank", rel: "noopener noreferrer" diff --git a/app/models/account.rb b/app/models/account.rb index 646e9db78..be14f406a 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -9,7 +9,7 @@ class Account < ActiveRecord::Base before_create do |account| unless account.account_type account.account_type = AccountType.find_or_create_by(name: - Growstuff::Application.config.default_account_type) + Rails.application.config.default_account_type) end end diff --git a/app/models/member.rb b/app/models/member.rb index 9828a005c..80a5ba840 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -210,7 +210,7 @@ class Member < ActiveRecord::Base def newsletter_subscribe(gb = Gibbon::API.new, testing = false) return true if Rails.env.test? && !testing gb.lists.subscribe( - id: Growstuff::Application.config.newsletter_list_id, + id: Rails.application.config.newsletter_list_id, email: { email: email }, merge_vars: { login_name: login_name }, double_optin: false # they already confirmed their email with us @@ -219,7 +219,7 @@ class Member < ActiveRecord::Base def newsletter_unsubscribe(gb = Gibbon::API.new, testing = false) return true if Rails.env.test? && !testing - gb.lists.unsubscribe(id: Growstuff::Application.config.newsletter_list_id, + gb.lists.unsubscribe(id: Rails.application.config.newsletter_list_id, email: { email: email }) end diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 7fe945d8a..d7e05a282 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -28,4 +28,4 @@ / Placed at the end of the document so the pages load faster = javascript_include_tag "application" - != Growstuff::Application.config.analytics_code + != Rails.application.config.analytics_code diff --git a/bin/rails b/bin/rails index 5191e6927..073966023 100755 --- a/bin/rails +++ b/bin/rails @@ -1,4 +1,4 @@ #!/usr/bin/env ruby -APP_PATH = File.expand_path('../../config/application', __FILE__) +APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' diff --git a/bin/setup b/bin/setup new file mode 100755 index 000000000..78c4e861d --- /dev/null +++ b/bin/setup @@ -0,0 +1,38 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bin/update b/bin/update new file mode 100755 index 000000000..a8e4462f2 --- /dev/null +++ b/bin/update @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bin/yarn b/bin/yarn new file mode 100755 index 000000000..c2bacef83 --- /dev/null +++ b/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +VENDOR_PATH = File.expand_path('..', __dir__) +Dir.chdir(VENDOR_PATH) do + begin + exec "yarnpkg #{ARGV.join(" ")}" + rescue Errno::ENOENT + $stderr.puts "Yarn executable was not detected in the system." + $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + exit 1 + end +end diff --git a/config.ru b/config.ru index d30ee4f18..bd83b2541 100644 --- a/config.ru +++ b/config.ru @@ -1,4 +1,4 @@ # This file is used by Rack-based servers to start the application. require ::File.expand_path('../config/environment', __FILE__) -run Growstuff::Application +run Rails.application diff --git a/config/boot.rb b/config/boot.rb index f2830ae31..30f5120df 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,6 +1,3 @@ -require 'rubygems' +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -# Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) - -require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) +require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 000000000..b6110a25b --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: redis://localhost:6379/1 + channel_prefix: growstuff_production diff --git a/config/environment.rb b/config/environment.rb index b175f6a30..426333bb4 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,5 @@ -# Load the rails application -require File.expand_path('../application', __FILE__) +# Load the Rails application. +require_relative 'application' -# Initialize the rails application -Growstuff::Application.initialize! +# Initialize the Rails application. +Rails.application.initialize! diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 000000000..89d2efab2 --- /dev/null +++ b/config/initializers/application_controller_renderer.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 000000000..4b828e80c --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path +# Add Yarn node_modules folder to the asset load path. +Rails.application.config.assets.paths << Rails.root.join('node_modules') + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb new file mode 100644 index 000000000..1389e86a3 --- /dev/null +++ b/config/initializers/cookies_serializer.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Specify a serializer for the signed and encrypted cookie jars. +# Valid options are :json, :marshal, and :hybrid. +Rails.application.config.action_dispatch.cookies_serializer = :marshal diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 000000000..4a994e1e7 --- /dev/null +++ b/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/config/initializers/geocoder.rb b/config/initializers/geocoder.rb index afe41f574..b31f1edf3 100644 --- a/config/initializers/geocoder.rb +++ b/config/initializers/geocoder.rb @@ -5,8 +5,8 @@ Geocoder.configure( timeout: 10, http_headers: { "User-Agent" => - "#{Growstuff::Application.config.user_agent} #{Growstuff::Application.config.user_agent_email}", - "From" => Growstuff::Application.config.user_agent_email + "#{Rails.application.config.user_agent} #{Rails.application.config.user_agent_email}", + "From" => Rails.application.config.user_agent_email } ) # This configuration takes precedence over environment/test.rb diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index 599d85bf4..22df44c07 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -1,16 +1,17 @@ # Be sure to restart your server when you modify this file. -# Add new inflection rules using the following format -# (all these examples are active by default): -# ActiveSupport::Inflector.inflections do |inflect| +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.plural /^(ox)$/i, '\1en' # inflect.singular /^(ox)en/i, '\1' # inflect.irregular 'person', 'people' # inflect.uncountable %w( fish sheep ) # end -# + # These inflection rules are supported but not enabled by default: -# ActiveSupport::Inflector.inflections do |inflect| +# ActiveSupport::Inflector.inflections(:en) do |inflect| # inflect.acronym 'RESTful' # end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index 72aca7e44..dc1899682 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -2,4 +2,3 @@ # Add new mime types for use in respond_to blocks: # Mime::Type.register "text/richtext", :rtf -# Mime::Type.register_alias "text/html", :iphone diff --git a/config/initializers/new_framework_defaults_5_1.rb b/config/initializers/new_framework_defaults_5_1.rb new file mode 100644 index 000000000..9010abd5c --- /dev/null +++ b/config/initializers/new_framework_defaults_5_1.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.1 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +# Make `form_with` generate non-remote forms. +Rails.application.config.action_view.form_with_generates_remote_forms = false + +# Unknown asset fallback will return the path passed in when the given +# asset is not present in the asset pipeline. +# Rails.application.config.assets.unknown_asset_fallback = false diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index 25119c9bc..9fc739015 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,8 +1,8 @@ # Be sure to restart your server when you modify this file. -Growstuff::Application.config.session_store :cookie_store, key: '_growstuff_session' +Rails.application.config.session_store :cookie_store, key: '_growstuff_session' # Use the database for sessions instead of the cookie-based default, # which shouldn't be used to store highly confidential information # (create the session table with "rails generate session_migration") -# Growstuff::Application.config.session_store :active_record_store +# Rails.application.config.session_store :active_record_store diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index 999df2018..bbfc3961b 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -1,5 +1,5 @@ # Be sure to restart your server when you modify this file. -# + # This file contains settings for ActionController::ParamsWrapper which # is enabled by default. @@ -8,7 +8,7 @@ ActiveSupport.on_load(:action_controller) do wrap_parameters format: [:json] end -# Disable root element in JSON by default. -ActiveSupport.on_load(:active_record) do - self.include_root_in_json = false -end +# To enable root element in JSON for ActiveRecord objects. +# ActiveSupport.on_load(:active_record) do +# self.include_root_in_json = true +# end diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 000000000..1e19380dc --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,56 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. If you use this option +# you need to make sure to reconnect any threads in the `on_worker_boot` +# block. +# +# preload_app! + +# If you are preloading your application and using Active Record, it's +# recommended that you close any connections to the database before workers +# are forked to prevent connection leakage. +# +# before_fork do +# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) +# end + +# The code in the `on_worker_boot` will be called if you are using +# clustered mode by specifying a number of `workers`. After each worker +# process is booted, this block will be run. If you are using the `preload_app!` +# option, you will want to use this block to reconnect to any threads +# or connections that may have been created at application boot, as Ruby +# cannot share connections between processes. +# +# on_worker_boot do +# ActiveRecord::Base.establish_connection if defined?(ActiveRecord) +# end +# + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/config/routes.rb b/config/routes.rb index eb963311a..013fee209 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,4 +1,4 @@ -Growstuff::Application.routes.draw do +Rails.application.routes.draw do get '/robots.txt' => 'robots#robots' resources :plant_parts @@ -89,7 +89,7 @@ Growstuff::Application.routes.draw do get '/shop' => 'shop#index' get '/shop/:action' => 'shop#:action' - comfy_route :cms_admin, path: '/admin/cms' + # comfy_route :cms_admin, path: '/admin/cms' namespace :admin do resources :members end @@ -113,5 +113,5 @@ Growstuff::Application.routes.draw do get '/.well-known/acme-challenge/:id' => 'pages#letsencrypt' # CMS stuff -- must remain LAST - comfy_route :cms, path: '/', sitemap: false + # comfy_route :cms, path: '/', sitemap: false end diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 000000000..c9119b40c --- /dev/null +++ b/config/spring.rb @@ -0,0 +1,6 @@ +%w( + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +).each { |path| Spring.watch(path) } diff --git a/db/schema.rb b/db/schema.rb index 473e756fa..ea66548f1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1,4 +1,3 @@ -# encoding: UTF-8 # This file is auto-generated from the current state of the database. Instead # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. @@ -11,371 +10,352 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20171129041341) do +ActiveRecord::Schema.define(version: 20180103024400) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" - create_table "account_types", force: :cascade do |t| - t.string "name", null: false - t.boolean "is_paid" - t.boolean "is_permanent_paid" + create_table "account_types", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.boolean "is_paid" + t.boolean "is_permanent_paid" t.datetime "created_at" t.datetime "updated_at" end - create_table "accounts", force: :cascade do |t| - t.integer "member_id", null: false - t.integer "account_type_id" + create_table "accounts", id: :serial, force: :cascade do |t| + t.integer "member_id", null: false + t.integer "account_type_id" t.datetime "paid_until" t.datetime "created_at" t.datetime "updated_at" end - create_table "alternate_names", force: :cascade do |t| - t.string "name", null: false - t.integer "crop_id", null: false - t.integer "creator_id", null: false + create_table "alternate_names", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.integer "crop_id", null: false + t.integer "creator_id", null: false t.datetime "created_at" t.datetime "updated_at" end - create_table "authentications", force: :cascade do |t| - t.integer "member_id", null: false - t.string "provider", null: false - t.string "uid" - t.string "token" - t.string "secret" + create_table "authentications", id: :serial, force: :cascade do |t| + t.integer "member_id", null: false + t.string "provider", null: false + t.string "uid" + t.string "token" + t.string "secret" t.datetime "created_at" t.datetime "updated_at" - t.string "name" + t.string "name" + t.index ["member_id"], name: "index_authentications_on_member_id" end - add_index "authentications", ["member_id"], name: "index_authentications_on_member_id", using: :btree - - create_table "comfy_cms_blocks", force: :cascade do |t| - t.string "identifier", null: false - t.text "content" - t.integer "blockable_id" - t.string "blockable_type" + create_table "comfy_cms_blocks", id: :serial, force: :cascade do |t| + t.string "identifier", null: false + t.text "content" + t.integer "blockable_id" + t.string "blockable_type" t.datetime "created_at" t.datetime "updated_at" + t.index ["blockable_id", "blockable_type"], name: "index_comfy_cms_blocks_on_blockable_id_and_blockable_type" + t.index ["identifier"], name: "index_comfy_cms_blocks_on_identifier" end - add_index "comfy_cms_blocks", ["blockable_id", "blockable_type"], name: "index_comfy_cms_blocks_on_blockable_id_and_blockable_type", using: :btree - add_index "comfy_cms_blocks", ["identifier"], name: "index_comfy_cms_blocks_on_identifier", using: :btree - - create_table "comfy_cms_categories", force: :cascade do |t| - t.integer "site_id", null: false - t.string "label", null: false - t.string "categorized_type", null: false + create_table "comfy_cms_categories", id: :serial, force: :cascade do |t| + t.integer "site_id", null: false + t.string "label", null: false + t.string "categorized_type", null: false + t.index ["site_id", "categorized_type", "label"], name: "index_cms_categories_on_site_id_and_cat_type_and_label", unique: true end - add_index "comfy_cms_categories", ["site_id", "categorized_type", "label"], name: "index_cms_categories_on_site_id_and_cat_type_and_label", unique: true, using: :btree - - create_table "comfy_cms_categorizations", force: :cascade do |t| - t.integer "category_id", null: false - t.string "categorized_type", null: false - t.integer "categorized_id", null: false + create_table "comfy_cms_categorizations", id: :serial, force: :cascade do |t| + t.integer "category_id", null: false + t.string "categorized_type", null: false + t.integer "categorized_id", null: false + t.index ["category_id", "categorized_type", "categorized_id"], name: "index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id", unique: true end - add_index "comfy_cms_categorizations", ["category_id", "categorized_type", "categorized_id"], name: "index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id", unique: true, using: :btree - - create_table "comfy_cms_files", force: :cascade do |t| - t.integer "site_id", null: false - t.integer "block_id" - t.string "label", null: false - t.string "file_file_name", null: false - t.string "file_content_type", null: false - t.integer "file_file_size", null: false - t.string "description", limit: 2048 - t.integer "position", default: 0, null: false + create_table "comfy_cms_files", id: :serial, force: :cascade do |t| + t.integer "site_id", null: false + t.integer "block_id" + t.string "label", null: false + t.string "file_file_name", null: false + t.string "file_content_type", null: false + t.integer "file_file_size", null: false + t.string "description", limit: 2048 + t.integer "position", default: 0, null: false t.datetime "created_at" t.datetime "updated_at" + t.index ["site_id", "block_id"], name: "index_comfy_cms_files_on_site_id_and_block_id" + t.index ["site_id", "file_file_name"], name: "index_comfy_cms_files_on_site_id_and_file_file_name" + t.index ["site_id", "label"], name: "index_comfy_cms_files_on_site_id_and_label" + t.index ["site_id", "position"], name: "index_comfy_cms_files_on_site_id_and_position" end - add_index "comfy_cms_files", ["site_id", "block_id"], name: "index_comfy_cms_files_on_site_id_and_block_id", using: :btree - add_index "comfy_cms_files", ["site_id", "file_file_name"], name: "index_comfy_cms_files_on_site_id_and_file_file_name", using: :btree - add_index "comfy_cms_files", ["site_id", "label"], name: "index_comfy_cms_files_on_site_id_and_label", using: :btree - add_index "comfy_cms_files", ["site_id", "position"], name: "index_comfy_cms_files_on_site_id_and_position", using: :btree - - create_table "comfy_cms_layouts", force: :cascade do |t| - t.integer "site_id", null: false - t.integer "parent_id" - t.string "app_layout" - t.string "label", null: false - t.string "identifier", null: false - t.text "content" - t.text "css" - t.text "js" - t.integer "position", default: 0, null: false - t.boolean "is_shared", default: false, null: false + create_table "comfy_cms_layouts", id: :serial, force: :cascade do |t| + t.integer "site_id", null: false + t.integer "parent_id" + t.string "app_layout" + t.string "label", null: false + t.string "identifier", null: false + t.text "content" + t.text "css" + t.text "js" + t.integer "position", default: 0, null: false + t.boolean "is_shared", default: false, null: false t.datetime "created_at" t.datetime "updated_at" + t.index ["parent_id", "position"], name: "index_comfy_cms_layouts_on_parent_id_and_position" + t.index ["site_id", "identifier"], name: "index_comfy_cms_layouts_on_site_id_and_identifier", unique: true end - add_index "comfy_cms_layouts", ["parent_id", "position"], name: "index_comfy_cms_layouts_on_parent_id_and_position", using: :btree - add_index "comfy_cms_layouts", ["site_id", "identifier"], name: "index_comfy_cms_layouts_on_site_id_and_identifier", unique: true, using: :btree - - create_table "comfy_cms_pages", force: :cascade do |t| - t.integer "site_id", null: false - t.integer "layout_id" - t.integer "parent_id" - t.integer "target_page_id" - t.string "label", null: false - t.string "slug" - t.string "full_path", null: false - t.text "content_cache" - t.integer "position", default: 0, null: false - t.integer "children_count", default: 0, null: false - t.boolean "is_published", default: true, null: false - t.boolean "is_shared", default: false, null: false + create_table "comfy_cms_pages", id: :serial, force: :cascade do |t| + t.integer "site_id", null: false + t.integer "layout_id" + t.integer "parent_id" + t.integer "target_page_id" + t.string "label", null: false + t.string "slug" + t.string "full_path", null: false + t.text "content_cache" + t.integer "position", default: 0, null: false + t.integer "children_count", default: 0, null: false + t.boolean "is_published", default: true, null: false + t.boolean "is_shared", default: false, null: false t.datetime "created_at" t.datetime "updated_at" + t.index ["parent_id", "position"], name: "index_comfy_cms_pages_on_parent_id_and_position" + t.index ["site_id", "full_path"], name: "index_comfy_cms_pages_on_site_id_and_full_path" end - add_index "comfy_cms_pages", ["parent_id", "position"], name: "index_comfy_cms_pages_on_parent_id_and_position", using: :btree - add_index "comfy_cms_pages", ["site_id", "full_path"], name: "index_comfy_cms_pages_on_site_id_and_full_path", using: :btree - - create_table "comfy_cms_revisions", force: :cascade do |t| - t.string "record_type", null: false - t.integer "record_id", null: false - t.text "data" + create_table "comfy_cms_revisions", id: :serial, force: :cascade do |t| + t.string "record_type", null: false + t.integer "record_id", null: false + t.text "data" t.datetime "created_at" + t.index ["record_type", "record_id", "created_at"], name: "index_cms_revisions_on_rtype_and_rid_and_created_at" end - add_index "comfy_cms_revisions", ["record_type", "record_id", "created_at"], name: "index_cms_revisions_on_rtype_and_rid_and_created_at", using: :btree - - create_table "comfy_cms_sites", force: :cascade do |t| - t.string "label", null: false - t.string "identifier", null: false - t.string "hostname", null: false - t.string "path" - t.string "locale", default: "en", null: false + create_table "comfy_cms_sites", id: :serial, force: :cascade do |t| + t.string "label", null: false + t.string "identifier", null: false + t.string "hostname", null: false + t.string "path" + t.string "locale", default: "en", null: false t.boolean "is_mirrored", default: false, null: false + t.index ["hostname"], name: "index_comfy_cms_sites_on_hostname" + t.index ["is_mirrored"], name: "index_comfy_cms_sites_on_is_mirrored" end - add_index "comfy_cms_sites", ["hostname"], name: "index_comfy_cms_sites_on_hostname", using: :btree - add_index "comfy_cms_sites", ["is_mirrored"], name: "index_comfy_cms_sites_on_is_mirrored", using: :btree + create_table "comfy_cms_snippets", id: :serial, force: :cascade do |t| + t.integer "site_id", null: false + t.string "label", null: false + t.string "identifier", null: false + t.text "content" + t.integer "position", default: 0, null: false + t.boolean "is_shared", default: false, null: false + t.datetime "created_at" + t.datetime "updated_at" + t.index ["site_id", "identifier"], name: "index_comfy_cms_snippets_on_site_id_and_identifier", unique: true + t.index ["site_id", "position"], name: "index_comfy_cms_snippets_on_site_id_and_position" + end - create_table "comfy_cms_snippets", force: :cascade do |t| - t.integer "site_id", null: false - t.string "label", null: false - t.string "identifier", null: false - t.text "content" - t.integer "position", default: 0, null: false - t.boolean "is_shared", default: false, null: false + create_table "comments", id: :serial, force: :cascade do |t| + t.integer "post_id", null: false + t.integer "author_id", null: false + t.text "body", null: false t.datetime "created_at" t.datetime "updated_at" end - add_index "comfy_cms_snippets", ["site_id", "identifier"], name: "index_comfy_cms_snippets_on_site_id_and_identifier", unique: true, using: :btree - add_index "comfy_cms_snippets", ["site_id", "position"], name: "index_comfy_cms_snippets_on_site_id_and_position", using: :btree - - create_table "comments", force: :cascade do |t| - t.integer "post_id", null: false - t.integer "author_id", null: false - t.text "body", null: false + create_table "crops", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.string "en_wikipedia_url" t.datetime "created_at" t.datetime "updated_at" + t.string "slug" + t.integer "parent_id" + t.integer "plantings_count", default: 0 + t.integer "creator_id" + t.integer "requester_id" + t.string "approval_status", default: "approved" + t.text "reason_for_rejection" + t.text "request_notes" + t.text "rejection_notes" + t.boolean "perennial", default: false + t.integer "median_lifespan" + t.integer "median_days_to_first_harvest" + t.integer "median_days_to_last_harvest" + t.index ["name"], name: "index_crops_on_name" + t.index ["requester_id"], name: "index_crops_on_requester_id" + t.index ["slug"], name: "index_crops_on_slug", unique: true end - create_table "crops", force: :cascade do |t| - t.string "name", null: false - t.string "en_wikipedia_url" - t.datetime "created_at" - t.datetime "updated_at" - t.string "slug" - t.integer "parent_id" - t.integer "plantings_count", default: 0 - t.integer "creator_id" - t.integer "requester_id" - t.string "approval_status", default: "approved" - t.text "reason_for_rejection" - t.text "request_notes" - t.text "rejection_notes" - t.boolean "perennial", default: false - t.integer "median_lifespan" - t.integer "median_days_to_first_harvest" - t.integer "median_days_to_last_harvest" - end - - add_index "crops", ["name"], name: "index_crops_on_name", using: :btree - add_index "crops", ["requester_id"], name: "index_crops_on_requester_id", using: :btree - add_index "crops", ["slug"], name: "index_crops_on_slug", unique: true, using: :btree - create_table "crops_posts", id: false, force: :cascade do |t| t.integer "crop_id" t.integer "post_id" + t.index ["crop_id", "post_id"], name: "index_crops_posts_on_crop_id_and_post_id" + t.index ["crop_id"], name: "index_crops_posts_on_crop_id" end - add_index "crops_posts", ["crop_id", "post_id"], name: "index_crops_posts_on_crop_id_and_post_id", using: :btree - add_index "crops_posts", ["crop_id"], name: "index_crops_posts_on_crop_id", using: :btree - - create_table "follows", force: :cascade do |t| - t.integer "follower_id" - t.integer "followed_id" + create_table "follows", id: :serial, force: :cascade do |t| + t.integer "follower_id" + t.integer "followed_id" t.datetime "created_at" t.datetime "updated_at" end - create_table "forums", force: :cascade do |t| - t.string "name", null: false - t.text "description", null: false - t.integer "owner_id", null: false + create_table "forums", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.text "description", null: false + t.integer "owner_id", null: false t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug" + t.index ["slug"], name: "index_forums_on_slug", unique: true end - add_index "forums", ["slug"], name: "index_forums_on_slug", unique: true, using: :btree - - create_table "gardens", force: :cascade do |t| - t.string "name", null: false - t.integer "owner_id" - t.string "slug", null: false + create_table "gardens", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.integer "owner_id" + t.string "slug", null: false t.datetime "created_at" t.datetime "updated_at" - t.text "description" - t.boolean "active", default: true - t.string "location" - t.float "latitude" - t.float "longitude" - t.decimal "area" - t.string "area_unit" + t.text "description" + t.boolean "active", default: true + t.string "location" + t.float "latitude" + t.float "longitude" + t.decimal "area" + t.string "area_unit" + t.index ["owner_id"], name: "index_gardens_on_owner_id" + t.index ["slug"], name: "index_gardens_on_slug", unique: true end - add_index "gardens", ["owner_id"], name: "index_gardens_on_owner_id", using: :btree - add_index "gardens", ["slug"], name: "index_gardens_on_slug", unique: true, using: :btree - create_table "gardens_photos", id: false, force: :cascade do |t| t.integer "photo_id" t.integer "garden_id" + t.index ["garden_id", "photo_id"], name: "index_gardens_photos_on_garden_id_and_photo_id" end - add_index "gardens_photos", ["garden_id", "photo_id"], name: "index_gardens_photos_on_garden_id_and_photo_id", using: :btree - - create_table "harvests", force: :cascade do |t| - t.integer "crop_id", null: false - t.integer "owner_id", null: false - t.date "harvested_at" - t.decimal "quantity" - t.string "unit" - t.text "description" + create_table "harvests", id: :serial, force: :cascade do |t| + t.integer "crop_id", null: false + t.integer "owner_id", null: false + t.date "harvested_at" + t.decimal "quantity" + t.string "unit" + t.text "description" t.datetime "created_at" t.datetime "updated_at" - t.string "slug" - t.decimal "weight_quantity" - t.string "weight_unit" - t.integer "plant_part_id" - t.float "si_weight" - t.integer "planting_id" + t.string "slug" + t.decimal "weight_quantity" + t.string "weight_unit" + t.integer "plant_part_id" + t.float "si_weight" + t.integer "planting_id" + t.index ["planting_id"], name: "index_harvests_on_planting_id" end - add_index "harvests", ["planting_id"], name: "index_harvests_on_planting_id", using: :btree - create_table "harvests_photos", id: false, force: :cascade do |t| t.integer "photo_id" t.integer "harvest_id" + t.index ["harvest_id", "photo_id"], name: "index_harvests_photos_on_harvest_id_and_photo_id" end - add_index "harvests_photos", ["harvest_id", "photo_id"], name: "index_harvests_photos_on_harvest_id_and_photo_id", using: :btree - - create_table "likes", force: :cascade do |t| - t.integer "member_id" - t.integer "likeable_id" - t.string "likeable_type" - t.string "categories", array: true + create_table "likes", id: :serial, force: :cascade do |t| + t.integer "member_id" + t.integer "likeable_id" + t.string "likeable_type" + t.string "categories", array: true t.datetime "created_at" t.datetime "updated_at" + t.index ["likeable_id"], name: "index_likes_on_likeable_id" + t.index ["likeable_type", "likeable_id"], name: "index_likes_on_likeable_type_and_likeable_id" + t.index ["member_id"], name: "index_likes_on_member_id" end - add_index "likes", ["likeable_id"], name: "index_likes_on_likeable_id", using: :btree - add_index "likes", ["likeable_type", "likeable_id"], name: "index_likes_on_likeable_type_and_likeable_id", using: :btree - add_index "likes", ["member_id"], name: "index_likes_on_member_id", using: :btree - - create_table "median_functions", force: :cascade do |t| + create_table "median_functions", id: :serial, force: :cascade do |t| end - create_table "members", force: :cascade do |t| - t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" + create_table "members", id: :serial, force: :cascade do |t| + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false + t.string "reset_password_token" t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0 + t.integer "sign_in_count", default: 0 t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.string "confirmation_token" + t.string "current_sign_in_ip" + t.string "last_sign_in_ip" + t.string "confirmation_token" t.datetime "confirmed_at" t.datetime "confirmation_sent_at" - t.string "unconfirmed_email" - t.integer "failed_attempts", default: 0 - t.string "unlock_token" + t.string "unconfirmed_email" + t.integer "failed_attempts", default: 0 + t.string "unlock_token" t.datetime "locked_at" t.datetime "created_at" t.datetime "updated_at" - t.string "login_name" - t.string "slug" - t.boolean "tos_agreement" - t.boolean "show_email" - t.string "location" - t.float "latitude" - t.float "longitude" - t.boolean "send_notification_email", default: true - t.text "bio" - t.integer "plantings_count" - t.boolean "newsletter" - t.boolean "send_planting_reminder", default: true - t.string "preferred_avatar_uri" - t.integer "gardens_count" - t.integer "harvests_count" - t.integer "seeds_count" + t.string "login_name" + t.string "slug" + t.boolean "tos_agreement" + t.boolean "show_email" + t.string "location" + t.float "latitude" + t.float "longitude" + t.boolean "send_notification_email", default: true + t.text "bio" + t.integer "plantings_count" + t.boolean "newsletter" + t.boolean "send_planting_reminder", default: true + t.string "preferred_avatar_uri" + t.integer "gardens_count" + t.integer "harvests_count" + t.integer "seeds_count" t.datetime "deleted_at" + t.index ["confirmation_token"], name: "index_members_on_confirmation_token", unique: true + t.index ["deleted_at"], name: "index_members_on_deleted_at" + t.index ["email"], name: "index_members_on_email", unique: true + t.index ["reset_password_token"], name: "index_members_on_reset_password_token", unique: true + t.index ["slug"], name: "index_members_on_slug", unique: true + t.index ["unlock_token"], name: "index_members_on_unlock_token", unique: true end - add_index "members", ["confirmation_token"], name: "index_members_on_confirmation_token", unique: true, using: :btree - add_index "members", ["deleted_at"], name: "index_members_on_deleted_at", using: :btree - add_index "members", ["email"], name: "index_members_on_email", unique: true, using: :btree - add_index "members", ["reset_password_token"], name: "index_members_on_reset_password_token", unique: true, using: :btree - add_index "members", ["slug"], name: "index_members_on_slug", unique: true, using: :btree - add_index "members", ["unlock_token"], name: "index_members_on_unlock_token", unique: true, using: :btree - create_table "members_roles", id: false, force: :cascade do |t| t.integer "member_id" t.integer "role_id" end - create_table "notifications", force: :cascade do |t| - t.integer "sender_id" - t.integer "recipient_id", null: false - t.string "subject" - t.text "body" - t.boolean "read", default: false - t.integer "post_id" + create_table "notifications", id: :serial, force: :cascade do |t| + t.integer "sender_id" + t.integer "recipient_id", null: false + t.string "subject" + t.text "body" + t.boolean "read", default: false + t.integer "post_id" t.datetime "created_at" t.datetime "updated_at" end - create_table "order_items", force: :cascade do |t| - t.integer "order_id" - t.integer "product_id" - t.integer "price" - t.integer "quantity" + create_table "order_items", id: :serial, force: :cascade do |t| + t.integer "order_id" + t.integer "product_id" + t.integer "price" + t.integer "quantity" t.datetime "created_at" t.datetime "updated_at" end - create_table "orders", force: :cascade do |t| + create_table "orders", id: :serial, force: :cascade do |t| t.datetime "created_at" t.datetime "updated_at" t.datetime "completed_at" - t.integer "member_id" - t.string "paypal_express_token" - t.string "paypal_express_payer_id" - t.string "referral_code" + t.integer "member_id" + t.string "paypal_express_token" + t.string "paypal_express_payer_id" + t.string "referral_code" end create_table "orders_products", id: false, force: :cascade do |t| @@ -383,28 +363,27 @@ ActiveRecord::Schema.define(version: 20171129041341) do t.integer "product_id" end - create_table "photographings", force: :cascade do |t| - t.integer "photo_id", null: false - t.integer "photographable_id", null: false - t.string "photographable_type", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + create_table "photographings", id: :serial, force: :cascade do |t| + t.integer "photo_id", null: false + t.integer "photographable_id", null: false + t.string "photographable_type", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["photographable_id", "photographable_type", "photo_id"], name: "items_to_photos_idx", unique: true + t.index ["photographable_id", "photographable_type"], name: "photographable_idx" end - add_index "photographings", ["photographable_id", "photographable_type", "photo_id"], name: "items_to_photos_idx", unique: true, using: :btree - add_index "photographings", ["photographable_id", "photographable_type"], name: "photographable_idx", using: :btree - - create_table "photos", force: :cascade do |t| - t.integer "owner_id", null: false - t.string "thumbnail_url", null: false - t.string "fullsize_url", null: false + create_table "photos", id: :serial, force: :cascade do |t| + t.integer "owner_id", null: false + t.string "thumbnail_url", null: false + t.string "fullsize_url", null: false t.datetime "created_at" t.datetime "updated_at" - t.string "title", null: false - t.string "license_name", null: false - t.string "license_url" - t.string "link_url", null: false - t.string "flickr_photo_id" + t.string "title", null: false + t.string "license_name", null: false + t.string "license_url" + t.string "link_url", null: false + t.string "flickr_photo_id" end create_table "photos_plantings", id: false, force: :cascade do |t| @@ -415,99 +394,97 @@ ActiveRecord::Schema.define(version: 20171129041341) do create_table "photos_seeds", id: false, force: :cascade do |t| t.integer "photo_id" t.integer "seed_id" + t.index ["seed_id", "photo_id"], name: "index_photos_seeds_on_seed_id_and_photo_id" end - add_index "photos_seeds", ["seed_id", "photo_id"], name: "index_photos_seeds_on_seed_id_and_photo_id", using: :btree - - create_table "plant_parts", force: :cascade do |t| - t.string "name" + create_table "plant_parts", id: :serial, force: :cascade do |t| + t.string "name" t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug" end - create_table "plantings", force: :cascade do |t| - t.integer "garden_id", null: false - t.integer "crop_id", null: false - t.date "planted_at" - t.integer "quantity" - t.text "description" + create_table "plantings", id: :serial, force: :cascade do |t| + t.integer "garden_id", null: false + t.integer "crop_id", null: false + t.date "planted_at" + t.integer "quantity" + t.text "description" t.datetime "created_at" t.datetime "updated_at" - t.string "slug" - t.string "sunniness" - t.string "planted_from" - t.integer "owner_id" - t.boolean "finished", default: false - t.date "finished_at" - t.integer "lifespan" - t.integer "days_to_first_harvest" - t.integer "days_to_last_harvest" + t.string "slug" + t.string "sunniness" + t.string "planted_from" + t.integer "owner_id" + t.boolean "finished", default: false + t.date "finished_at" + t.integer "lifespan" + t.integer "days_to_first_harvest" + t.integer "days_to_last_harvest" + t.boolean "failed" + t.text "failure_cause" + t.index ["failed"], name: "index_plantings_on_failed" + t.index ["slug"], name: "index_plantings_on_slug", unique: true end - add_index "plantings", ["slug"], name: "index_plantings_on_slug", unique: true, using: :btree - - create_table "posts", force: :cascade do |t| - t.integer "author_id", null: false - t.string "subject", null: false - t.text "body", null: false + create_table "posts", id: :serial, force: :cascade do |t| + t.integer "author_id", null: false + t.string "subject", null: false + t.text "body", null: false t.datetime "created_at" t.datetime "updated_at" - t.string "slug" - t.integer "forum_id" + t.string "slug" + t.integer "forum_id" + t.index ["created_at", "author_id"], name: "index_posts_on_created_at_and_author_id" + t.index ["slug"], name: "index_posts_on_slug", unique: true end - add_index "posts", ["created_at", "author_id"], name: "index_posts_on_created_at_and_author_id", using: :btree - add_index "posts", ["slug"], name: "index_posts_on_slug", unique: true, using: :btree - - create_table "products", force: :cascade do |t| - t.string "name", null: false - t.text "description", null: false - t.integer "min_price", null: false + create_table "products", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.text "description", null: false + t.integer "min_price", null: false t.datetime "created_at" t.datetime "updated_at" - t.integer "account_type_id" - t.integer "paid_months" - t.integer "recommended_price" + t.integer "account_type_id" + t.integer "paid_months" + t.integer "recommended_price" end - create_table "roles", force: :cascade do |t| - t.string "name", null: false - t.text "description" + create_table "roles", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.text "description" t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug" + t.index ["slug"], name: "index_roles_on_slug", unique: true end - add_index "roles", ["slug"], name: "index_roles_on_slug", unique: true, using: :btree - - create_table "scientific_names", force: :cascade do |t| - t.string "name", null: false - t.integer "crop_id", null: false + create_table "scientific_names", id: :serial, force: :cascade do |t| + t.string "name", null: false + t.integer "crop_id", null: false t.datetime "created_at" t.datetime "updated_at" - t.integer "creator_id" + t.integer "creator_id" end - create_table "seeds", force: :cascade do |t| - t.integer "owner_id", null: false - t.integer "crop_id", null: false - t.text "description" - t.integer "quantity" - t.date "plant_before" + create_table "seeds", id: :serial, force: :cascade do |t| + t.integer "owner_id", null: false + t.integer "crop_id", null: false + t.text "description" + t.integer "quantity" + t.date "plant_before" t.datetime "created_at" t.datetime "updated_at" - t.string "tradable_to", default: "nowhere" - t.string "slug" - t.integer "days_until_maturity_min" - t.integer "days_until_maturity_max" - t.text "organic", default: "unknown" - t.text "gmo", default: "unknown" - t.text "heirloom", default: "unknown" + t.string "tradable_to", default: "nowhere" + t.string "slug" + t.integer "days_until_maturity_min" + t.integer "days_until_maturity_max" + t.text "organic", default: "unknown" + t.text "gmo", default: "unknown" + t.text "heirloom", default: "unknown" + t.index ["slug"], name: "index_seeds_on_slug", unique: true end - add_index "seeds", ["slug"], name: "index_seeds_on_slug", unique: true, using: :btree - add_foreign_key "harvests", "plantings" add_foreign_key "photographings", "photos" end diff --git a/db/seeds.rb b/db/seeds.rb index 7df7e0e4c..a1477fbe6 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -134,7 +134,7 @@ end def create_cropbot @cropbot_user = Member.new( login_name: "cropbot", - email: Growstuff::Application.config.bot_email, + email: Rails.application.config.bot_email, password: SecureRandom.urlsafe_base64(64), tos_agreement: true ) diff --git a/lib/haml/filters/growstuff_markdown.rb b/lib/haml/filters/growstuff_markdown.rb index b7b257b53..51d95d1fe 100644 --- a/lib/haml/filters/growstuff_markdown.rb +++ b/lib/haml/filters/growstuff_markdown.rb @@ -17,7 +17,7 @@ module Haml::Filters # rubocop:disable Style/ClassAndModuleChildren MEMBER_REGEX = /(?#{name}" if name "#{crop.name}" end diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 1911ae8da..c538ad38d 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -29,7 +29,7 @@ describe 'member' do end it "should have a default-type account by default" do - member.account.account_type.name.should eq Growstuff::Application.config.default_account_type + member.account.account_type.name.should eq Rails.application.config.default_account_type member.paid?.should be(false) end diff --git a/spec/views/layouts/application_spec.rb b/spec/views/layouts/application_spec.rb index f094ae2c2..e706bc575 100644 --- a/spec/views/layouts/application_spec.rb +++ b/spec/views/layouts/application_spec.rb @@ -6,7 +6,7 @@ describe 'layouts/application.html.haml', type: "view" do end it 'includes the analytics code' do - Growstuff::Application.config.analytics_code = '' + Rails.application.config.analytics_code = '' render assert_select "script", text: 'alert("foo!")' rendered.should_not have_content 'script' diff --git a/spec/views/orders/show.html.haml_spec.rb b/spec/views/orders/show.html.haml_spec.rb index a9f662de9..4f9c7d7f6 100644 --- a/spec/views/orders/show.html.haml_spec.rb +++ b/spec/views/orders/show.html.haml_spec.rb @@ -31,7 +31,7 @@ describe "orders/show" do end it "shows a foreign exchange link for the total" do - currency = Growstuff::Application.config.currency + currency = Rails.application.config.currency assert_select("a[href='http://www.wolframalpha.com/input/?i=198.00+#{currency}']") end diff --git a/spec/views/shop/index_spec.rb b/spec/views/shop/index_spec.rb index 754f05c09..29b740c92 100644 --- a/spec/views/shop/index_spec.rb +++ b/spec/views/shop/index_spec.rb @@ -20,20 +20,20 @@ describe 'shop/index.html.haml', type: "view" do end it 'shows prices in configured currency' do - rendered.should have_content format('9.99 %s', Growstuff::Application.config.currency) + rendered.should have_content format('9.99 %s', Rails.application.config.currency) end it 'should contain an exchange rate link' do - currency = Growstuff::Application.config.currency + currency = Rails.application.config.currency assert_select("a[href='http://www.wolframalpha.com/input/?i=9.99+#{currency}']") end it 'shows recommended price for products that have it' do - rendered.should have_content format('12.00 %s', Growstuff::Application.config.currency) + rendered.should have_content format('12.00 %s', Rails.application.config.currency) end it 'should contain an exchange rate link for recommended price' do - currency = Growstuff::Application.config.currency + currency = Rails.application.config.currency assert_select("a[href='http://www.wolframalpha.com/input/?i=12.00+#{currency}']") end From b6c9b13d4d7ea1a0e44cabbecd26b4ec0e78cf1a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 17:16:14 +1300 Subject: [PATCH 023/267] Models inherit from application record --- app/models/account.rb | 2 +- app/models/account_type.rb | 2 +- app/models/alternate_name.rb | 2 +- app/models/application_record.rb | 3 +++ app/models/authentication.rb | 2 +- app/models/comment.rb | 2 +- app/models/crop.rb | 2 +- app/models/follow.rb | 2 +- app/models/forum.rb | 2 +- app/models/garden.rb | 2 +- app/models/harvest.rb | 2 +- app/models/like.rb | 2 +- app/models/member.rb | 2 +- app/models/notification.rb | 2 +- app/models/order.rb | 2 +- app/models/order_item.rb | 2 +- app/models/photo.rb | 2 +- app/models/photographing.rb | 2 +- app/models/plant_part.rb | 2 +- app/models/planting.rb | 2 +- app/models/post.rb | 2 +- app/models/product.rb | 2 +- app/models/role.rb | 2 +- app/models/scientific_name.rb | 2 +- app/models/seed.rb | 2 +- db/migrate/20171129041341_create_photographings.rb | 8 ++++---- 26 files changed, 31 insertions(+), 28 deletions(-) create mode 100644 app/models/application_record.rb diff --git a/app/models/account.rb b/app/models/account.rb index be14f406a..79d5327b7 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -1,4 +1,4 @@ -class Account < ActiveRecord::Base +class Account < ApplicationRecord belongs_to :member belongs_to :account_type diff --git a/app/models/account_type.rb b/app/models/account_type.rb index 06416751a..c2294ca53 100644 --- a/app/models/account_type.rb +++ b/app/models/account_type.rb @@ -1,4 +1,4 @@ -class AccountType < ActiveRecord::Base +class AccountType < ApplicationRecord # # Relationships has_many :products diff --git a/app/models/alternate_name.rb b/app/models/alternate_name.rb index aa960e1f4..0d7f12198 100644 --- a/app/models/alternate_name.rb +++ b/app/models/alternate_name.rb @@ -1,4 +1,4 @@ -class AlternateName < ActiveRecord::Base +class AlternateName < ApplicationRecord after_commit { |an| an.crop.__elasticsearch__.index_document if an.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == "true" } belongs_to :crop belongs_to :creator, class_name: 'Member' diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 000000000..10a4cba84 --- /dev/null +++ b/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end diff --git a/app/models/authentication.rb b/app/models/authentication.rb index e6171c8b7..91ecc8de9 100644 --- a/app/models/authentication.rb +++ b/app/models/authentication.rb @@ -1,3 +1,3 @@ -class Authentication < ActiveRecord::Base +class Authentication < ApplicationRecord belongs_to :member end diff --git a/app/models/comment.rb b/app/models/comment.rb index 7098e0b46..59d7102ad 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,4 +1,4 @@ -class Comment < ActiveRecord::Base +class Comment < ApplicationRecord belongs_to :author, class_name: 'Member' belongs_to :post diff --git a/app/models/crop.rb b/app/models/crop.rb index 15787f6f1..a961daf58 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -1,4 +1,4 @@ -class Crop < ActiveRecord::Base +class Crop < ApplicationRecord extend FriendlyId friendly_id :name, use: %i(slugged finders) diff --git a/app/models/follow.rb b/app/models/follow.rb index 557887cb6..34028857b 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -1,4 +1,4 @@ -class Follow < ActiveRecord::Base +class Follow < ApplicationRecord belongs_to :follower, class_name: "Member" belongs_to :followed, class_name: "Member" validates :follower_id, uniqueness: { scope: :followed_id } diff --git a/app/models/forum.rb b/app/models/forum.rb index 7cbc0d43d..2579876ad 100644 --- a/app/models/forum.rb +++ b/app/models/forum.rb @@ -1,4 +1,4 @@ -class Forum < ActiveRecord::Base +class Forum < ApplicationRecord extend FriendlyId validates :name, presence: true friendly_id :name, use: %i(slugged finders) diff --git a/app/models/garden.rb b/app/models/garden.rb index 0c3378b00..096647035 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -1,4 +1,4 @@ -class Garden < ActiveRecord::Base +class Garden < ApplicationRecord extend FriendlyId include Geocodable include PhotoCapable diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 6bb9aa048..a5328ef49 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -1,4 +1,4 @@ -class Harvest < ActiveRecord::Base +class Harvest < ApplicationRecord include ActionView::Helpers::NumberHelper extend FriendlyId include PhotoCapable diff --git a/app/models/like.rb b/app/models/like.rb index 8b4cfef9c..05911fc95 100644 --- a/app/models/like.rb +++ b/app/models/like.rb @@ -1,4 +1,4 @@ -class Like < ActiveRecord::Base +class Like < ApplicationRecord belongs_to :member belongs_to :likeable, polymorphic: true validates :member, :likeable, presence: true diff --git a/app/models/member.rb b/app/models/member.rb index 80a5ba840..654e6b3bd 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -1,4 +1,4 @@ -class Member < ActiveRecord::Base +class Member < ApplicationRecord acts_as_paranoid # implements soft deletion before_destroy :newsletter_unsubscribe include Geocodable diff --git a/app/models/notification.rb b/app/models/notification.rb index 1b09b1e5e..fe3ec8907 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -1,4 +1,4 @@ -class Notification < ActiveRecord::Base +class Notification < ApplicationRecord belongs_to :sender, class_name: 'Member' belongs_to :recipient, class_name: 'Member' belongs_to :post diff --git a/app/models/order.rb b/app/models/order.rb index 53a309c35..68d9e4fb3 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,4 +1,4 @@ -class Order < ActiveRecord::Base +class Order < ApplicationRecord # # Relationships belongs_to :member, with_deleted: true diff --git a/app/models/order_item.rb b/app/models/order_item.rb index 380fbff58..771919b55 100644 --- a/app/models/order_item.rb +++ b/app/models/order_item.rb @@ -1,4 +1,4 @@ -class OrderItem < ActiveRecord::Base +class OrderItem < ApplicationRecord belongs_to :order belongs_to :product diff --git a/app/models/photo.rb b/app/models/photo.rb index 5800ec6f9..0daae7825 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -1,4 +1,4 @@ -class Photo < ActiveRecord::Base +class Photo < ApplicationRecord belongs_to :owner, class_name: 'Member' PHOTO_CAPABLE = %w(Garden Planting Harvest Seed).freeze diff --git a/app/models/photographing.rb b/app/models/photographing.rb index 3edb78351..5d1ab1073 100644 --- a/app/models/photographing.rb +++ b/app/models/photographing.rb @@ -1,4 +1,4 @@ -class Photographing < ActiveRecord::Base +class Photographing < ApplicationRecord belongs_to :photo belongs_to :photographable, polymorphic: true diff --git a/app/models/plant_part.rb b/app/models/plant_part.rb index e5045baa8..2590fb966 100644 --- a/app/models/plant_part.rb +++ b/app/models/plant_part.rb @@ -1,4 +1,4 @@ -class PlantPart < ActiveRecord::Base +class PlantPart < ApplicationRecord extend FriendlyId friendly_id :name, use: %i(slugged finders) diff --git a/app/models/planting.rb b/app/models/planting.rb index c51166264..74795066c 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -1,4 +1,4 @@ -class Planting < ActiveRecord::Base +class Planting < ApplicationRecord extend FriendlyId include PhotoCapable friendly_id :planting_slug, use: %i(slugged finders) diff --git a/app/models/post.rb b/app/models/post.rb index 43885e99d..ae27dbb50 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1,4 +1,4 @@ -class Post < ActiveRecord::Base +class Post < ApplicationRecord extend FriendlyId include Likeable friendly_id :author_date_subject, use: %i(slugged finders) diff --git a/app/models/product.rb b/app/models/product.rb index 01b5a8902..3946645d3 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,4 +1,4 @@ -class Product < ActiveRecord::Base +class Product < ApplicationRecord # # Relationships belongs_to :account_type diff --git a/app/models/role.rb b/app/models/role.rb index 89b940125..3606641ea 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -1,4 +1,4 @@ -class Role < ActiveRecord::Base +class Role < ApplicationRecord extend FriendlyId friendly_id :name, use: %i(slugged finders) diff --git a/app/models/scientific_name.rb b/app/models/scientific_name.rb index bca467b5b..812b696b8 100644 --- a/app/models/scientific_name.rb +++ b/app/models/scientific_name.rb @@ -1,4 +1,4 @@ -class ScientificName < ActiveRecord::Base +class ScientificName < ApplicationRecord after_commit { |sn| sn.crop.__elasticsearch__.index_document if sn.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == "true" } belongs_to :crop belongs_to :creator, class_name: 'Member' diff --git a/app/models/seed.rb b/app/models/seed.rb index 56c9f809d..ca99c4fc3 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -1,4 +1,4 @@ -class Seed < ActiveRecord::Base +class Seed < ApplicationRecord extend FriendlyId include PhotoCapable friendly_id :seed_slug, use: %i(slugged finders) diff --git a/db/migrate/20171129041341_create_photographings.rb b/db/migrate/20171129041341_create_photographings.rb index 8054ba9cd..a18ab3680 100644 --- a/db/migrate/20171129041341_create_photographings.rb +++ b/db/migrate/20171129041341_create_photographings.rb @@ -35,19 +35,19 @@ class CreatePhotographings < ActiveRecord::Migration Photographing.create! photo_id: s.photo_id, photographable_id: s.seed_id, photographable_type: 'Seed' end end - class GardensPhoto < ActiveRecord::Base + class GardensPhoto < ApplicationRecord belongs_to :photo belongs_to :garden end - class PhotosPlanting < ActiveRecord::Base + class PhotosPlanting < ApplicationRecord belongs_to :photo belongs_to :planting end - class HarvestsPhoto < ActiveRecord::Base + class HarvestsPhoto < ApplicationRecord belongs_to :photo belongs_to :harvest end - class PhotosSeed < ActiveRecord::Base + class PhotosSeed < ApplicationRecord belongs_to :photo belongs_to :seed end From 65d5b2d61a0f178b6692c044e24bac0a000e0e14 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 17:18:41 +1300 Subject: [PATCH 024/267] Application mailer for rails 5 --- app/mailers/application_mailer.rb | 4 ++++ app/mailers/notifier.rb | 2 +- app/views/layouts/mailer.html.erb | 8 ++++++++ app/views/layouts/mailer.text.erb | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 app/mailers/application_mailer.rb create mode 100644 app/views/layouts/mailer.html.erb create mode 100644 app/views/layouts/mailer.text.erb diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb new file mode 100644 index 000000000..286b2239d --- /dev/null +++ b/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: 'from@example.com' + layout 'mailer' +end diff --git a/app/mailers/notifier.rb b/app/mailers/notifier.rb index 569400ce6..12c20cebe 100644 --- a/app/mailers/notifier.rb +++ b/app/mailers/notifier.rb @@ -1,4 +1,4 @@ -class Notifier < ActionMailer::Base +class Notifier < ApplicationMailer include NotificationsHelper default from: "Growstuff " diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb new file mode 100644 index 000000000..cb2589829 --- /dev/null +++ b/app/views/layouts/mailer.html.erb @@ -0,0 +1,8 @@ + + + + + + + <%= yield %> + \ No newline at end of file diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb new file mode 100644 index 000000000..37f0bddbd --- /dev/null +++ b/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> From 46d56fde319cb6f86e070eede329ce5aab4cf509 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 17:20:08 +1300 Subject: [PATCH 025/267] Application job for Rails 5 --- app/jobs/application_job.rb | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 app/jobs/application_job.rb diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb new file mode 100644 index 000000000..a009ace51 --- /dev/null +++ b/app/jobs/application_job.rb @@ -0,0 +1,2 @@ +class ApplicationJob < ActiveJob::Base +end From 4917ab9ae88ba5a83d9699e81b41b57dcc8be451 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 17:21:40 +1300 Subject: [PATCH 026/267] Fixed order->member relationship, after change to paranoia gem --- app/models/order.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/order.rb b/app/models/order.rb index 68d9e4fb3..fe5f65888 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,7 +1,7 @@ class Order < ApplicationRecord # # Relationships - belongs_to :member, with_deleted: true + belongs_to :member, -> { with_deleted } has_many :order_items, dependent: :destroy # From d456d045cd42cec1cd91b56e504a538fdeb54ea3 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 17:24:51 +1300 Subject: [PATCH 027/267] Changed order of photo association relationship declarations --- app/models/concerns/photo_capable.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/concerns/photo_capable.rb b/app/models/concerns/photo_capable.rb index 177a2f832..758569c35 100644 --- a/app/models/concerns/photo_capable.rb +++ b/app/models/concerns/photo_capable.rb @@ -2,8 +2,8 @@ module PhotoCapable extend ActiveSupport::Concern included do - has_many :photos, through: :photographings, as: :photographable has_many :photographings, as: :photographable, dependent: :destroy + has_many :photos, through: :photographings, as: :photographable scope :has_photos, -> { includes(:photos).where.not(photos: { id: nil }) } end From 7bc91e415a5624346350d318aa8638402f29026c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Wed, 3 Jan 2018 19:09:32 +1300 Subject: [PATCH 028/267] Re-instate active_median gem --- Gemfile | 6 +++--- Gemfile.lock | 11 +++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/Gemfile b/Gemfile index a5c7b7dce..3c40d1d38 100644 --- a/Gemfile +++ b/Gemfile @@ -22,11 +22,11 @@ gem 'font-awesome-sass' gem 'uglifier' # JavaScript compressor # planting and harvest predictions -# gem 'active_median' +gem 'active_median' gem 'flickraw' gem 'jquery-rails' -gem 'jquery-ui-rails', '~> 5.0.2' # needs careful upgrade with change of location +gem 'jquery-ui-rails' gem 'js-routes' # provides access to Rails routes in Javascript gem 'cancancan' # for checking member privileges @@ -79,7 +79,7 @@ gem 'omniauth-flickr', '>= 0.0.15' gem 'omniauth-twitter' # For charting data -gem 'd3-rails', '~> 3.5' # 4.* produces Error: : could not find an object to spy upon for linear() - see https://travis-ci.org/Growstuff/growstuff/jobs/204461482 +gem 'd3-rails' # client for Elasticsearch. Elasticsearch is a flexible # and powerful, distributed, real-time search and analytics engine. diff --git a/Gemfile.lock b/Gemfile.lock index bc54de685..db72f11dc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -28,6 +28,8 @@ GEM active_link_to (1.0.5) actionpack addressable + active_median (0.1.4) + activerecord active_merchant-paypal-bogus-gateway (0.1.0) activemerchant active_utils (3.3.9) @@ -132,7 +134,7 @@ GEM crass (1.0.3) csv_shaper (1.3.0) activesupport (>= 3.0.0) - d3-rails (3.5.17) + d3-rails (4.10.2) railties (>= 3.1) dalli (2.7.6) database_cleaner (1.6.2) @@ -254,7 +256,7 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) - jquery-ui-rails (5.0.5) + jquery-ui-rails (6.0.1) railties (>= 3.2.16) js-routes (1.4.3) railties (>= 3.2) @@ -520,6 +522,7 @@ PLATFORMS ruby DEPENDENCIES + active_median active_merchant-paypal-bogus-gateway active_utils activemerchant @@ -541,7 +544,7 @@ DEPENDENCIES comfortable_mexican_sofa coveralls csv_shaper - d3-rails (~> 3.5) + d3-rails dalli database_cleaner devise @@ -565,7 +568,7 @@ DEPENDENCIES i18n-tasks jasmine jquery-rails - jquery-ui-rails (~> 5.0.2) + jquery-ui-rails js-routes jsonapi-resources kaminari From 9d2732fffa381356b021e645a781fecc9d38feb8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 4 Jan 2018 14:29:09 +1300 Subject: [PATCH 029/267] removing comfortable mexican sofa for now --- Gemfile | 2 +- Gemfile.lock | 89 +++++++++++++--------------------------------------- 2 files changed, 23 insertions(+), 68 deletions(-) diff --git a/Gemfile b/Gemfile index 3c40d1d38..eb461c054 100644 --- a/Gemfile +++ b/Gemfile @@ -42,7 +42,7 @@ gem 'pg' gem 'ruby-units' # for unit conversion gem 'unicorn' # http server -gem 'comfortable_mexican_sofa' # content management system +# gem 'comfortable_mexican_sofa' # content management system gem 'bootstrap-kaminari-views' # bootstrap views for kaminari gem 'kaminari' # pagination diff --git a/Gemfile.lock b/Gemfile.lock index db72f11dc..bdd2bc94e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -25,9 +25,6 @@ GEM erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - active_link_to (1.0.5) - actionpack - addressable active_median (0.1.4) activerecord active_merchant-paypal-bogus-gateway (0.1.0) @@ -38,7 +35,7 @@ GEM activejob (5.1.4) activesupport (= 5.1.4) globalid (>= 0.3.6) - activemerchant (1.75.0) + activemerchant (1.76.0) activesupport (>= 3.2.14, < 6.x) builder (>= 2.1.2, < 4.0.0) i18n (>= 0.6.9) @@ -66,9 +63,7 @@ GEM erubi (>= 1.0.0) rack (>= 0.9.0) bluecloth (2.2.0) - bonsai-elasticsearch-rails (0.2.0) - elasticsearch-model (~> 0) - elasticsearch-rails (~> 0) + bonsai-elasticsearch-rails (0.0.4) bootstrap-datepicker-rails (1.7.1.1) railties (>= 3.0) bootstrap-kaminari-views (0.0.5) @@ -98,12 +93,9 @@ GEM launchy childprocess (0.8.0) ffi (~> 1.0, >= 1.0.11) - climate_control (0.2.0) cliver (0.3.2) - cocaine (0.5.8) - climate_control (>= 0.0.3, < 1.0) - codeclimate-test-reporter (1.0.7) - simplecov + codeclimate-test-reporter (1.0.8) + simplecov (<= 0.13) coderay (1.1.2) coffee-rails (4.2.2) coffee-script (>= 2.2.0) @@ -112,25 +104,14 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - comfortable_mexican_sofa (1.8.2) - active_link_to (>= 1.0.0) - coffee-rails (>= 3.1.0) - formatted_form (>= 2.1.0) - haml-rails (>= 0.3.0) - jquery-rails (>= 3.0.0) - jquery-ui-rails (>= 4.0.0) - paperclip (>= 3.4.0) - rails (>= 3.1.0) - redcarpet (>= 2.2.0) - sass-rails (>= 3.1.0) concurrent-ruby (1.0.5) connection_pool (2.2.1) - coveralls (0.7.1) - multi_json (~> 1.3) - rest-client - simplecov (>= 0.7) - term-ansicolor - thor + coveralls (0.8.19) + json (>= 1.8, < 3) + simplecov (~> 0.12.0) + term-ansicolor (~> 1.3) + thor (~> 0.19.1) + tins (~> 1.6) crass (1.0.3) csv_shaper (1.3.0) activesupport (>= 3.0.0) @@ -146,23 +127,21 @@ GEM warden (~> 1.2.3) diff-lcs (1.3) docile (1.1.5) - domain_name (0.5.20170404) - unf (>= 0.0.5, < 1.0.0) easy_translate (0.5.0) json thread thread_safe - elasticsearch (6.0.0) - elasticsearch-api (= 6.0.0) - elasticsearch-transport (= 6.0.0) - elasticsearch-api (6.0.0) + elasticsearch (5.0.4) + elasticsearch-api (= 5.0.4) + elasticsearch-transport (= 5.0.4) + elasticsearch-api (5.0.4) multi_json - elasticsearch-model (0.1.9) + elasticsearch-model (5.0.2) activesupport (> 3) - elasticsearch (> 0.4) + elasticsearch (~> 5) hashie - elasticsearch-rails (0.1.9) - elasticsearch-transport (6.0.0) + elasticsearch-rails (5.0.2) + elasticsearch-transport (5.0.4) faraday multi_json erubi (1.7.0) @@ -184,8 +163,6 @@ GEM flickraw (0.9.9) font-awesome-sass (4.7.0) sass (>= 3.2) - formatted_form (2.1.2) - rails (>= 3.1) friendly_id (5.2.3) activerecord (>= 4.0.0) geocoder (1.4.5) @@ -230,8 +207,6 @@ GEM haml (>= 4.0, < 6) nokogiri (>= 1.6.0) ruby_parser (~> 3.5) - http-cookie (1.0.3) - domain_name (~> 0.5) httparty (0.15.6) multi_xml (>= 0.5.2) i18n (0.9.1) @@ -297,10 +272,6 @@ GEM mini_mime (>= 0.1.1) memcachier (0.0.2) method_source (0.9.0) - mime-types (3.1) - mime-types-data (~> 3.2015) - mime-types-data (3.2016.0521) - mimemagic (0.3.2) mini_mime (1.0.0) mini_portile2 (2.3.0) minitest (5.11.1) @@ -308,7 +279,6 @@ GEM multi_json (1.11.3) multi_xml (0.6.0) multipart-post (2.0.0) - netrc (0.11.0) newrelic_rpm (4.7.1.340) nio4r (2.2.0) nokogiri (1.8.1) @@ -338,12 +308,6 @@ GEM omniauth-oauth (~> 1.1) rack orm_adapter (0.5.0) - paperclip (5.1.0) - activemodel (>= 4.2.0) - activesupport (>= 4.2.0) - cocaine (~> 0.5.5) - mime-types - mimemagic (~> 0.3.0) parallel (1.12.1) paranoia (2.4.0) activerecord (>= 4.0, < 5.2) @@ -402,20 +366,15 @@ GEM rb-fsevent (0.10.2) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) - redcarpet (3.4.0) redis (4.0.1) responders (2.4.0) actionpack (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3) - rest-client (2.0.2) - http-cookie (>= 1.0.2, < 2.0) - mime-types (>= 1.16, < 4.0) - netrc (~> 0.8) rspec-activemodel-mocks (1.0.3) activemodel (>= 3.0) activesupport (>= 3.0) rspec-mocks (>= 2.99, < 4.0) - rspec-core (3.7.0) + rspec-core (3.7.1) rspec-support (~> 3.7.0) rspec-expectations (3.7.0) diff-lcs (>= 1.2.0, < 2.0) @@ -465,7 +424,7 @@ GEM connection_pool (~> 2.2, >= 2.2.0) rack-protection (>= 1.5.0) redis (>= 3.3.4, < 5) - simplecov (0.15.1) + simplecov (0.12.0) docile (~> 1.1.0) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) @@ -485,7 +444,7 @@ GEM tins (~> 1.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) - thor (0.20.0) + thor (0.19.4) thread (0.2.2) thread_safe (0.3.6) tilt (2.0.8) @@ -496,9 +455,6 @@ GEM thread_safe (~> 0.1) uglifier (4.1.2) execjs (>= 0.3.0, < 3) - unf (0.1.4) - unf_ext - unf_ext (0.0.7.4) unicode-display_width (1.3.0) unicorn (5.4.0) kgio (~> 2.6) @@ -541,7 +497,6 @@ DEPENDENCIES capybara-screenshot codeclimate-test-reporter coffee-rails - comfortable_mexican_sofa coveralls csv_shaper d3-rails @@ -610,4 +565,4 @@ RUBY VERSION ruby 2.4.1p111 BUNDLED WITH - 1.16.0 + 1.16.1 From 79cf7b452c528360e83ee2b4cbee7b41f89dbe3f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 4 Jan 2018 14:31:24 +1300 Subject: [PATCH 030/267] removing some cms stuff --- app/views/layouts/_footer.html.haml | 6 +- .../initializers/comfortable_mexican_sofa.rb | 101 ------------------ 2 files changed, 3 insertions(+), 104 deletions(-) delete mode 100644 config/initializers/comfortable_mexican_sofa.rb diff --git a/app/views/layouts/_footer.html.haml b/app/views/layouts/_footer.html.haml index e004bf69a..b05b164d4 100644 --- a/app/views/layouts/_footer.html.haml +++ b/app/views/layouts/_footer.html.haml @@ -2,11 +2,11 @@ .container .row .col-md-4#footer1 - != cms_snippet_content(:footer1) + -# != cms_snippet_content(:footer1) .col-md-4#footer2 - != cms_snippet_content(:footer2) + -# != cms_snippet_content(:footer2) .col-md-4#footer3 - != cms_snippet_content(:footer3) + -# != cms_snippet_content(:footer3) %div{ style: "float: right;" } %a{ href: "http://opendefinition.org/ossd/" } %img{ src: "http://assets.okfn.org/images/ok_buttons/os_80x15_blue.png", alt: "" } diff --git a/config/initializers/comfortable_mexican_sofa.rb b/config/initializers/comfortable_mexican_sofa.rb deleted file mode 100644 index 78794d93c..000000000 --- a/config/initializers/comfortable_mexican_sofa.rb +++ /dev/null @@ -1,101 +0,0 @@ -# encoding: utf-8 - -ComfortableMexicanSofa.configure do |config| - # Title of the admin area - # config.cms_title = 'ComfortableMexicanSofa CMS Engine' - - # Controller that is inherited from CmsAdmin::BaseController - # config.base_controller = 'ApplicationController' - - # Module responsible for authentication. You can replace it with your own. - # It simply needs to have #authenticate method. See http_auth.rb for reference. - config.admin_auth = 'CmsDeviseAuth' - - # Module responsible for authorization on admin side. It should have #authorize - # method that returns true or false based on params and loaded instance - # variables available for a given controller. - # config.admin_authorization = 'ComfyAdminAuthorization' - - # Module responsible for public authentication. Similar to the above. You also - # will have access to @cms_site, @cms_layout, @cms_page so you can use them in - # your logic. Default module doesn't do anything. - # config.public_auth = 'ComfyPublicAuthentication' - - # When arriving at /cms-admin you may chose to redirect to arbirtary path, - # for example '/cms-admin/users' - # config.admin_route_redirect = '' - - # File uploads use Paperclip and can support filesystem or s3 uploads. Override - # the upload method and appropriate settings based on Paperclip. For S3 see: - # http://rdoc.info/gems/paperclip/2.3.8/Paperclip/Storage/S3, and for - # filesystem see: http://rdoc.info/gems/paperclip/2.3.8/Paperclip/Storage/Filesystem - # If you are using S3 and HTTPS, pass :s3_protocol => '' to have URLs that use the protocol of the page - # config.upload_file_options = {:url => '/system/:class/:id/:attachment/:style/:filename'} - - # Sofa allows you to setup entire site from files. Database is updated with each - # request (if necessary). Please note that database entries are destroyed if there's - # no corresponding file. Fixtures are disabled by default. - # config.enable_fixtures = false - - # Path where fixtures can be located. - # config.fixtures_path = File.expand_path('db/cms_fixtures', Rails.root) - - # Importing fixtures into Database - # To load fixtures into the database just run this rake task: - # local: $ rake comfortable_mexican_sofa:fixtures:import FROM=example.local TO=localhost - # Heroku: $ heroku run rake comfortable_mexican_sofa:fixtures:import FROM=example.local TO=yourapp.herokuapp.com - # From indicates folder the fixtures are in and to is the Site hostname you have defined in the database. - - # Exporting fixtures into Files - # If you need to dump database contents into fixture files run: - # local: $ rake comfortable_mexican_sofa:fixtures:export FROM=localhost TO=example.local - # Heroku: $ heroku run rake comfortable_mexican_sofa:fixtures:export FROM=yourapp.herokuapp.com TO=example.local - # This will create example.local folder and dump all content from example.com Site. - - # Content for Layouts, Pages and Snippets has a revision history. You can revert - # a previous version using this system. You can control how many revisions per - # object you want to keep. Set it to 0 if you wish to turn this feature off. - # config.revisions_limit = 25 - - # Locale definitions. If you want to define your own locale merge - # {:locale => 'Locale Title'} with this. - # config.locales = {:en => 'English', :es => 'Español'} - - # Admin interface will respect the locale of the site being managed. However you can - # force it to English by setting this to `:en` - # config.admin_locale = nil - - # A class that is included as a sweeper to admin base controller if it's set - # config.admin_cache_sweeper = nil - - # By default you cannot have irb code inside your layouts/pages/snippets. - # Generally this is to prevent putting something like this: - # <% User.delete_all %> but if you really want to allow it... - # config.allow_irb = false - - # Whitelist of all helper methods that can be used via {{cms:helper}} tag. By default - # all helpers are allowed except `eval`, `send`, `call` and few others. Empty array - # will prevent rendering of all helpers. - # config.allowed_helpers = nil - - # Whitelist of partials paths that can be used via {{cms:partial}} tag. All partials - # are accessible by default. Empty array will prevent rendering of all partials. - # config.allowed_partials = nil - - # Site aliases, if you want to have aliases for your site. Good for harmonizing - # production env with dev/testing envs. - # e.g. config.hostname_aliases = {'host.com' => 'host.inv', 'host_a.com' => ['host.lvh.me', 'host.dev']} - # Default is nil (not used) - # config.hostname_aliases = nil - - # Reveal partials that can be overwritten in the admin area. - # Default is false. - # config.reveal_cms_partials = false -end - -module CmsDeviseAuth - def authenticate - return if current_member && current_member.role?(:admin) - redirect_to root_path, alert: 'Permission denied. Please sign in as an admin user to use the CMS admin area.' - end -end From 2109ee1561667cdb6e894a176c94003fcc7c466e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 4 Jan 2018 14:34:30 +1300 Subject: [PATCH 031/267] Migrations need to specify a version --- db/migrate/20120903092956_devise_create_users.rb | 2 +- db/migrate/20120903112806_add_username_to_users.rb | 2 +- db/migrate/20121001212604_create_crops.rb | 2 +- .../20121003190731_require_system_name_for_crops.rb | 2 +- db/migrate/20121027035231_add_slug_to_crops.rb | 2 +- db/migrate/20121105032913_create_gardens.rb | 2 +- db/migrate/20121106101718_add_slug_to_users.rb | 2 +- db/migrate/20121107012827_create_scientific_names.rb | 2 +- db/migrate/20121108105440_create_updates.rb | 2 +- .../20121109130033_add_creation_index_to_updates.rb | 2 +- db/migrate/20121203034745_add_tos_agreement_to_users.rb | 2 +- db/migrate/20121214224227_add_slug_to_updates.rb | 2 +- db/migrate/20121219022554_create_plantings.rb | 2 +- db/migrate/20130113045802_rename_updates_to_posts.rb | 2 +- db/migrate/20130113060852_rename_users_to_members.rb | 2 +- .../20130113081521_rename_post_member_to_author.rb | 2 +- .../20130113095802_rename_garden_member_to_owner.rb | 2 +- db/migrate/20130118031942_add_description_to_gardens.rb | 2 +- db/migrate/20130118043431_add_slug_to_plantings.rb | 2 +- db/migrate/20130206033956_create_comments.rb | 2 +- db/migrate/20130206051328_add_show_email_to_member.rb | 2 +- db/migrate/20130208034248_require_fields_for_comments.rb | 2 +- db/migrate/20130212001748_add_geo_to_members.rb | 2 +- db/migrate/20130212123628_create_notifications.rb | 2 +- db/migrate/20130213014511_create_forums.rb | 2 +- db/migrate/20130213015708_add_forum_to_posts.rb | 2 +- db/migrate/20130214024117_create_roles.rb | 2 +- db/migrate/20130214034838_add_members_roles_table.rb | 2 +- db/migrate/20130215131921_rename_notification_fields.rb | 2 +- db/migrate/20130220044605_add_slug_to_forums.rb | 2 +- db/migrate/20130220044642_add_slug_to_roles.rb | 2 +- db/migrate/20130222060730_default_read_to_false.rb | 2 +- db/migrate/20130326092227_change_planted_at_to_date.rb | 2 +- db/migrate/20130327120024_add_send_email_to_member.rb | 2 +- db/migrate/20130329045744_add_sunniness_to_planting.rb | 2 +- db/migrate/20130404174459_create_authentications.rb | 2 +- db/migrate/20130409103549_make_post_subject_non_null.rb | 2 +- db/migrate/20130409162140_add_name_to_authentications.rb | 2 +- db/migrate/20130507105357_create_products.rb | 2 +- db/migrate/20130507110411_create_orders.rb | 2 +- db/migrate/20130507113915_add_orders_products_table.rb | 2 +- db/migrate/20130508050711_add_completed_to_order.rb | 2 +- db/migrate/20130508104506_create_photos.rb | 2 +- db/migrate/20130509123711_add_metadata_to_photos.rb | 2 +- db/migrate/20130514124515_add_parent_to_crop.rb | 2 +- db/migrate/20130515033842_create_order_items.rb | 2 +- .../20130515054017_change_order_member_id_to_integer.rb | 2 +- db/migrate/20130515122301_change_prices_to_integers.rb | 2 +- db/migrate/20130517015920_create_account_details.rb | 2 +- db/migrate/20130517051922_create_account_types.rb | 2 +- db/migrate/20130517234458_require_account_type_name.rb | 2 +- db/migrate/20130518000339_add_columns_to_product.rb | 2 +- .../20130518002942_rename_account_detail_to_account.rb | 2 +- db/migrate/20130529032813_add_express_token_to_orders.rb | 2 +- db/migrate/20130531110729_add_photos_plantings_table.rb | 2 +- .../20130601011725_change_flickr_photo_id_to_string.rb | 2 +- .../20130606230333_change_product_description_to_text.rb | 2 +- .../20130606233733_add_recommended_price_to_product.rb | 2 +- .../20130705104238_add_planted_from_to_planting.rb | 2 +- db/migrate/20130715110134_create_seeds.rb | 2 +- ...130718005600_change_use_by_to_plant_before_on_seed.rb | 2 +- db/migrate/20130718011247_add_trading_to_seeds.rb | 2 +- db/migrate/20130722050836_remove_tradable_from_seeds.rb | 2 +- .../20130723103128_set_default_tradable_to_on_seed.rb | 2 +- db/migrate/20130723110702_add_slug_to_seed.rb | 2 +- db/migrate/20130809012511_add_bio_to_members.rb | 2 +- db/migrate/20130819004549_add_planting_count_to_crop.rb | 2 +- db/migrate/20130821011352_add_creator_to_crops.rb | 2 +- .../20130821073736_add_creator_to_scientific_name.rb | 2 +- db/migrate/20130826012139_add_owner_to_planting.rb | 2 +- .../20130826023159_add_plantings_count_to_member.rb | 2 +- db/migrate/20130827105823_add_newsletter_to_member.rb | 2 +- db/migrate/20130913015118_add_referral_code_to_order.rb | 2 +- db/migrate/20130917053547_create_harvests.rb | 2 +- ...20130917060257_change_harvest_notes_to_description.rb | 2 +- .../20130917071545_change_harvest_units_to_unit.rb | 2 +- db/migrate/20130917075803_add_slug_to_harvests.rb | 2 +- db/migrate/20130925050304_add_weight_to_harvests.rb | 2 +- db/migrate/20131018101204_rename_system_name_to_name.rb | 2 +- db/migrate/20131025104228_add_fields_to_gardens.rb | 2 +- db/migrate/20131029053113_add_plant_part_to_harvests.rb | 2 +- db/migrate/20131030230908_create_plant_parts.rb | 2 +- .../20131030231202_change_plant_part_to_plant_part_id.rb | 2 +- db/migrate/20131031000655_add_slug_to_plant_part.rb | 2 +- .../20140718075753_default_plantings_count_to_zero.rb | 2 +- db/migrate/20140829230600_add_finished_to_planting.rb | 2 +- db/migrate/20140905001730_add_harvests_photos_table.rb | 2 +- db/migrate/20140928044231_add_crops_posts_table.rb | 2 +- ...0140928085713_add_send_planting_reminder_to_member.rb | 2 +- db/migrate/20141002022459_create_index_harvest_photos.rb | 2 +- db/migrate/20141018111015_create_alternate_names.rb | 2 +- db/migrate/20141111130849_create_follows.rb | 2 +- ...1119130555_change_follows_member_id_to_follower_id.rb | 2 +- db/migrate/20150124110540_add_properties_to_seeds.rb | 2 +- db/migrate/20150127043022_add_gardens_photos_table.rb | 2 +- db/migrate/20150129034206_add_si_weight_to_harvest.rb | 2 +- db/migrate/20150130224814_add_requester_to_crops.rb | 2 +- db/migrate/20150201052245_create_cms.rb | 2 +- .../20150201053200_add_approval_status_to_crops.rb | 2 +- .../20150201062506_add_reason_for_rejection_to_crops.rb | 2 +- db/migrate/20150201064502_add_request_notes_to_crops.rb | 2 +- db/migrate/20150203080226_create_likes.rb | 2 +- .../20150209105410_add_rejection_notes_to_crops.rb | 2 +- ...150625224805_add_days_before_maturity_to_plantings.rb | 2 +- db/migrate/20150824145414_add_member_preferred_image.rb | 2 +- db/migrate/20161129021533_rename_scientific_name.rb | 2 +- db/migrate/20161201154922_add_photos_seeds_table.rb | 2 +- .../20170104035248_add_planting_ref_to_harvests.rb | 2 +- db/migrate/20170413221549_counter_caches.rb | 2 +- db/migrate/20170520060252_add_deleted_to_members.rb | 2 +- db/migrate/20171022032108_all_the_predictions.rb | 2 +- db/migrate/20171028230429_create_median_function.rb | 2 +- db/migrate/20171105011017_set_prediction_data.rb | 2 +- db/migrate/20171129041341_create_photographings.rb | 2 +- db/schema.rb | 9 +++------ 115 files changed, 117 insertions(+), 120 deletions(-) diff --git a/db/migrate/20120903092956_devise_create_users.rb b/db/migrate/20120903092956_devise_create_users.rb index cf02cbe2a..62d84f3d1 100644 --- a/db/migrate/20120903092956_devise_create_users.rb +++ b/db/migrate/20120903092956_devise_create_users.rb @@ -1,4 +1,4 @@ -class DeviseCreateUsers < ActiveRecord::Migration +class DeviseCreateUsers < ActiveRecord::Migration[4.2] def change create_table(:users) do |t| ## Database authenticatable diff --git a/db/migrate/20120903112806_add_username_to_users.rb b/db/migrate/20120903112806_add_username_to_users.rb index 3b71a2769..2df3aa569 100644 --- a/db/migrate/20120903112806_add_username_to_users.rb +++ b/db/migrate/20120903112806_add_username_to_users.rb @@ -1,4 +1,4 @@ -class AddUsernameToUsers < ActiveRecord::Migration +class AddUsernameToUsers < ActiveRecord::Migration[4.2] def change add_column :users, :username, :string end diff --git a/db/migrate/20121001212604_create_crops.rb b/db/migrate/20121001212604_create_crops.rb index c0fd9fec5..6e6fbcc2c 100644 --- a/db/migrate/20121001212604_create_crops.rb +++ b/db/migrate/20121001212604_create_crops.rb @@ -1,4 +1,4 @@ -class CreateCrops < ActiveRecord::Migration +class CreateCrops < ActiveRecord::Migration[4.2] def change create_table :crops do |t| t.string :system_name diff --git a/db/migrate/20121003190731_require_system_name_for_crops.rb b/db/migrate/20121003190731_require_system_name_for_crops.rb index f4536c18b..7989fcecf 100644 --- a/db/migrate/20121003190731_require_system_name_for_crops.rb +++ b/db/migrate/20121003190731_require_system_name_for_crops.rb @@ -1,4 +1,4 @@ -class RequireSystemNameForCrops < ActiveRecord::Migration +class RequireSystemNameForCrops < ActiveRecord::Migration[4.2] def up change_table :crops do |t| t.index :system_name diff --git a/db/migrate/20121027035231_add_slug_to_crops.rb b/db/migrate/20121027035231_add_slug_to_crops.rb index f826e1705..d360b4a44 100644 --- a/db/migrate/20121027035231_add_slug_to_crops.rb +++ b/db/migrate/20121027035231_add_slug_to_crops.rb @@ -1,4 +1,4 @@ -class AddSlugToCrops < ActiveRecord::Migration +class AddSlugToCrops < ActiveRecord::Migration[4.2] def change add_column :crops, :slug, :string add_index :crops, :slug, unique: true diff --git a/db/migrate/20121105032913_create_gardens.rb b/db/migrate/20121105032913_create_gardens.rb index a269a1e5a..e6c7834e1 100644 --- a/db/migrate/20121105032913_create_gardens.rb +++ b/db/migrate/20121105032913_create_gardens.rb @@ -1,4 +1,4 @@ -class CreateGardens < ActiveRecord::Migration +class CreateGardens < ActiveRecord::Migration[4.2] def change create_table :gardens do |t| t.string :name, null: false diff --git a/db/migrate/20121106101718_add_slug_to_users.rb b/db/migrate/20121106101718_add_slug_to_users.rb index a551cf15f..5840e09d2 100644 --- a/db/migrate/20121106101718_add_slug_to_users.rb +++ b/db/migrate/20121106101718_add_slug_to_users.rb @@ -1,4 +1,4 @@ -class AddSlugToUsers < ActiveRecord::Migration +class AddSlugToUsers < ActiveRecord::Migration[4.2] def change add_column :users, :slug, :string add_index :users, :slug, unique: true diff --git a/db/migrate/20121107012827_create_scientific_names.rb b/db/migrate/20121107012827_create_scientific_names.rb index 4300e3667..0e6b179f7 100644 --- a/db/migrate/20121107012827_create_scientific_names.rb +++ b/db/migrate/20121107012827_create_scientific_names.rb @@ -1,4 +1,4 @@ -class CreateScientificNames < ActiveRecord::Migration +class CreateScientificNames < ActiveRecord::Migration[4.2] def change create_table :scientific_names do |t| t.string :scientific_name, null: false diff --git a/db/migrate/20121108105440_create_updates.rb b/db/migrate/20121108105440_create_updates.rb index 6db35c046..3caacb749 100644 --- a/db/migrate/20121108105440_create_updates.rb +++ b/db/migrate/20121108105440_create_updates.rb @@ -1,4 +1,4 @@ -class CreateUpdates < ActiveRecord::Migration +class CreateUpdates < ActiveRecord::Migration[4.2] def change create_table :updates do |t| t.integer :user_id, null: false diff --git a/db/migrate/20121109130033_add_creation_index_to_updates.rb b/db/migrate/20121109130033_add_creation_index_to_updates.rb index 46601ef3d..57c24d559 100644 --- a/db/migrate/20121109130033_add_creation_index_to_updates.rb +++ b/db/migrate/20121109130033_add_creation_index_to_updates.rb @@ -1,4 +1,4 @@ -class AddCreationIndexToUpdates < ActiveRecord::Migration +class AddCreationIndexToUpdates < ActiveRecord::Migration[4.2] def change add_index :updates, %i(created_at user_id) end diff --git a/db/migrate/20121203034745_add_tos_agreement_to_users.rb b/db/migrate/20121203034745_add_tos_agreement_to_users.rb index aacc06970..31354ea58 100644 --- a/db/migrate/20121203034745_add_tos_agreement_to_users.rb +++ b/db/migrate/20121203034745_add_tos_agreement_to_users.rb @@ -1,4 +1,4 @@ -class AddTosAgreementToUsers < ActiveRecord::Migration +class AddTosAgreementToUsers < ActiveRecord::Migration[4.2] def change add_column :users, :tos_agreement, :boolean end diff --git a/db/migrate/20121214224227_add_slug_to_updates.rb b/db/migrate/20121214224227_add_slug_to_updates.rb index 85a0510d5..78d25ef24 100644 --- a/db/migrate/20121214224227_add_slug_to_updates.rb +++ b/db/migrate/20121214224227_add_slug_to_updates.rb @@ -1,4 +1,4 @@ -class AddSlugToUpdates < ActiveRecord::Migration +class AddSlugToUpdates < ActiveRecord::Migration[4.2] def change add_column :updates, :slug, :string add_index :updates, :slug, unique: true diff --git a/db/migrate/20121219022554_create_plantings.rb b/db/migrate/20121219022554_create_plantings.rb index 67ffa962d..d586e2426 100644 --- a/db/migrate/20121219022554_create_plantings.rb +++ b/db/migrate/20121219022554_create_plantings.rb @@ -1,4 +1,4 @@ -class CreatePlantings < ActiveRecord::Migration +class CreatePlantings < ActiveRecord::Migration[4.2] def change create_table :plantings do |t| t.integer :garden_id, null: false diff --git a/db/migrate/20130113045802_rename_updates_to_posts.rb b/db/migrate/20130113045802_rename_updates_to_posts.rb index 9fa730976..6329df2bb 100644 --- a/db/migrate/20130113045802_rename_updates_to_posts.rb +++ b/db/migrate/20130113045802_rename_updates_to_posts.rb @@ -1,4 +1,4 @@ -class RenameUpdatesToPosts < ActiveRecord::Migration +class RenameUpdatesToPosts < ActiveRecord::Migration[4.2] def change rename_table :updates, :posts end diff --git a/db/migrate/20130113060852_rename_users_to_members.rb b/db/migrate/20130113060852_rename_users_to_members.rb index e01458fe2..bb248186e 100644 --- a/db/migrate/20130113060852_rename_users_to_members.rb +++ b/db/migrate/20130113060852_rename_users_to_members.rb @@ -1,4 +1,4 @@ -class RenameUsersToMembers < ActiveRecord::Migration +class RenameUsersToMembers < ActiveRecord::Migration[4.2] def change rename_table :users, :members rename_column :members, :username, :login_name diff --git a/db/migrate/20130113081521_rename_post_member_to_author.rb b/db/migrate/20130113081521_rename_post_member_to_author.rb index 8bfea089b..a1658925b 100644 --- a/db/migrate/20130113081521_rename_post_member_to_author.rb +++ b/db/migrate/20130113081521_rename_post_member_to_author.rb @@ -1,4 +1,4 @@ -class RenamePostMemberToAuthor < ActiveRecord::Migration +class RenamePostMemberToAuthor < ActiveRecord::Migration[4.2] def change rename_column :posts, :member_id, :author_id end diff --git a/db/migrate/20130113095802_rename_garden_member_to_owner.rb b/db/migrate/20130113095802_rename_garden_member_to_owner.rb index e6dbb0df5..ea6bd4c72 100644 --- a/db/migrate/20130113095802_rename_garden_member_to_owner.rb +++ b/db/migrate/20130113095802_rename_garden_member_to_owner.rb @@ -1,4 +1,4 @@ -class RenameGardenMemberToOwner < ActiveRecord::Migration +class RenameGardenMemberToOwner < ActiveRecord::Migration[4.2] def change rename_column :gardens, :member_id, :owner_id end diff --git a/db/migrate/20130118031942_add_description_to_gardens.rb b/db/migrate/20130118031942_add_description_to_gardens.rb index 30bb33c7e..f8eb0a441 100644 --- a/db/migrate/20130118031942_add_description_to_gardens.rb +++ b/db/migrate/20130118031942_add_description_to_gardens.rb @@ -1,4 +1,4 @@ -class AddDescriptionToGardens < ActiveRecord::Migration +class AddDescriptionToGardens < ActiveRecord::Migration[4.2] def change add_column :gardens, :description, :text end diff --git a/db/migrate/20130118043431_add_slug_to_plantings.rb b/db/migrate/20130118043431_add_slug_to_plantings.rb index e3e9fa46d..c4e5d434d 100644 --- a/db/migrate/20130118043431_add_slug_to_plantings.rb +++ b/db/migrate/20130118043431_add_slug_to_plantings.rb @@ -1,4 +1,4 @@ -class AddSlugToPlantings < ActiveRecord::Migration +class AddSlugToPlantings < ActiveRecord::Migration[4.2] def change add_column :plantings, :slug, :string add_index :plantings, :slug, unique: true diff --git a/db/migrate/20130206033956_create_comments.rb b/db/migrate/20130206033956_create_comments.rb index 79e42c688..0c4663ec7 100644 --- a/db/migrate/20130206033956_create_comments.rb +++ b/db/migrate/20130206033956_create_comments.rb @@ -1,4 +1,4 @@ -class CreateComments < ActiveRecord::Migration +class CreateComments < ActiveRecord::Migration[4.2] def change create_table :comments do |t| t.integer :post_id diff --git a/db/migrate/20130206051328_add_show_email_to_member.rb b/db/migrate/20130206051328_add_show_email_to_member.rb index b18d3ee3d..3185b1377 100644 --- a/db/migrate/20130206051328_add_show_email_to_member.rb +++ b/db/migrate/20130206051328_add_show_email_to_member.rb @@ -1,4 +1,4 @@ -class AddShowEmailToMember < ActiveRecord::Migration +class AddShowEmailToMember < ActiveRecord::Migration[4.2] def change add_column :members, :show_email, :boolean end diff --git a/db/migrate/20130208034248_require_fields_for_comments.rb b/db/migrate/20130208034248_require_fields_for_comments.rb index ecb17f302..da847671b 100644 --- a/db/migrate/20130208034248_require_fields_for_comments.rb +++ b/db/migrate/20130208034248_require_fields_for_comments.rb @@ -1,4 +1,4 @@ -class RequireFieldsForComments < ActiveRecord::Migration +class RequireFieldsForComments < ActiveRecord::Migration[4.2] def up change_table :comments do |t| t.change :post_id, :integer, null: false diff --git a/db/migrate/20130212001748_add_geo_to_members.rb b/db/migrate/20130212001748_add_geo_to_members.rb index f14173795..e60f355f8 100644 --- a/db/migrate/20130212001748_add_geo_to_members.rb +++ b/db/migrate/20130212001748_add_geo_to_members.rb @@ -1,4 +1,4 @@ -class AddGeoToMembers < ActiveRecord::Migration +class AddGeoToMembers < ActiveRecord::Migration[4.2] def change add_column :members, :location, :string add_column :members, :latitude, :float diff --git a/db/migrate/20130212123628_create_notifications.rb b/db/migrate/20130212123628_create_notifications.rb index 6a59cdd8f..b89b13656 100644 --- a/db/migrate/20130212123628_create_notifications.rb +++ b/db/migrate/20130212123628_create_notifications.rb @@ -1,4 +1,4 @@ -class CreateNotifications < ActiveRecord::Migration +class CreateNotifications < ActiveRecord::Migration[4.2] def change create_table :notifications do |t| t.integer :from_id diff --git a/db/migrate/20130213014511_create_forums.rb b/db/migrate/20130213014511_create_forums.rb index 2d5b34694..0df3f00a2 100644 --- a/db/migrate/20130213014511_create_forums.rb +++ b/db/migrate/20130213014511_create_forums.rb @@ -1,4 +1,4 @@ -class CreateForums < ActiveRecord::Migration +class CreateForums < ActiveRecord::Migration[4.2] def change create_table :forums do |t| t.string :name, null: false diff --git a/db/migrate/20130213015708_add_forum_to_posts.rb b/db/migrate/20130213015708_add_forum_to_posts.rb index 904183f90..315ae0be5 100644 --- a/db/migrate/20130213015708_add_forum_to_posts.rb +++ b/db/migrate/20130213015708_add_forum_to_posts.rb @@ -1,4 +1,4 @@ -class AddForumToPosts < ActiveRecord::Migration +class AddForumToPosts < ActiveRecord::Migration[4.2] def change add_column :posts, :forum_id, :integer end diff --git a/db/migrate/20130214024117_create_roles.rb b/db/migrate/20130214024117_create_roles.rb index a95150da4..e39c7565d 100644 --- a/db/migrate/20130214024117_create_roles.rb +++ b/db/migrate/20130214024117_create_roles.rb @@ -1,4 +1,4 @@ -class CreateRoles < ActiveRecord::Migration +class CreateRoles < ActiveRecord::Migration[4.2] def change create_table :roles do |t| t.string :name, null: false diff --git a/db/migrate/20130214034838_add_members_roles_table.rb b/db/migrate/20130214034838_add_members_roles_table.rb index 9e84fd37d..502266a87 100644 --- a/db/migrate/20130214034838_add_members_roles_table.rb +++ b/db/migrate/20130214034838_add_members_roles_table.rb @@ -1,4 +1,4 @@ -class AddMembersRolesTable < ActiveRecord::Migration +class AddMembersRolesTable < ActiveRecord::Migration[4.2] def change create_table :members_roles, id: false do |t| t.integer :member_id diff --git a/db/migrate/20130215131921_rename_notification_fields.rb b/db/migrate/20130215131921_rename_notification_fields.rb index 63f52ae6d..c2294d2fe 100644 --- a/db/migrate/20130215131921_rename_notification_fields.rb +++ b/db/migrate/20130215131921_rename_notification_fields.rb @@ -1,4 +1,4 @@ -class RenameNotificationFields < ActiveRecord::Migration +class RenameNotificationFields < ActiveRecord::Migration[4.2] def change change_table :notifications do |t| t.rename :to_id, :recipient_id diff --git a/db/migrate/20130220044605_add_slug_to_forums.rb b/db/migrate/20130220044605_add_slug_to_forums.rb index 6b7db208f..57fbdc145 100644 --- a/db/migrate/20130220044605_add_slug_to_forums.rb +++ b/db/migrate/20130220044605_add_slug_to_forums.rb @@ -1,4 +1,4 @@ -class AddSlugToForums < ActiveRecord::Migration +class AddSlugToForums < ActiveRecord::Migration[4.2] def change add_column :forums, :slug, :string add_index :forums, :slug, unique: true diff --git a/db/migrate/20130220044642_add_slug_to_roles.rb b/db/migrate/20130220044642_add_slug_to_roles.rb index bc4578b10..a3812d77b 100644 --- a/db/migrate/20130220044642_add_slug_to_roles.rb +++ b/db/migrate/20130220044642_add_slug_to_roles.rb @@ -1,4 +1,4 @@ -class AddSlugToRoles < ActiveRecord::Migration +class AddSlugToRoles < ActiveRecord::Migration[4.2] def change add_column :roles, :slug, :string add_index :roles, :slug, unique: true diff --git a/db/migrate/20130222060730_default_read_to_false.rb b/db/migrate/20130222060730_default_read_to_false.rb index efe6d4b61..81a10aa40 100644 --- a/db/migrate/20130222060730_default_read_to_false.rb +++ b/db/migrate/20130222060730_default_read_to_false.rb @@ -1,4 +1,4 @@ -class DefaultReadToFalse < ActiveRecord::Migration +class DefaultReadToFalse < ActiveRecord::Migration[4.2] def up change_table :notifications do |t| t.change :read, :boolean, default: false diff --git a/db/migrate/20130326092227_change_planted_at_to_date.rb b/db/migrate/20130326092227_change_planted_at_to_date.rb index bf14c624d..089c77ef5 100644 --- a/db/migrate/20130326092227_change_planted_at_to_date.rb +++ b/db/migrate/20130326092227_change_planted_at_to_date.rb @@ -1,4 +1,4 @@ -class ChangePlantedAtToDate < ActiveRecord::Migration +class ChangePlantedAtToDate < ActiveRecord::Migration[4.2] def change change_column :plantings, :planted_at, :date end diff --git a/db/migrate/20130327120024_add_send_email_to_member.rb b/db/migrate/20130327120024_add_send_email_to_member.rb index b83dd9e03..5421bb0d7 100644 --- a/db/migrate/20130327120024_add_send_email_to_member.rb +++ b/db/migrate/20130327120024_add_send_email_to_member.rb @@ -1,4 +1,4 @@ -class AddSendEmailToMember < ActiveRecord::Migration +class AddSendEmailToMember < ActiveRecord::Migration[4.2] def change add_column :members, :send_notification_email, :boolean, default: true end diff --git a/db/migrate/20130329045744_add_sunniness_to_planting.rb b/db/migrate/20130329045744_add_sunniness_to_planting.rb index 8fae8d1d0..74fe7a652 100644 --- a/db/migrate/20130329045744_add_sunniness_to_planting.rb +++ b/db/migrate/20130329045744_add_sunniness_to_planting.rb @@ -1,4 +1,4 @@ -class AddSunninessToPlanting < ActiveRecord::Migration +class AddSunninessToPlanting < ActiveRecord::Migration[4.2] def change add_column :plantings, :sunniness, :string end diff --git a/db/migrate/20130404174459_create_authentications.rb b/db/migrate/20130404174459_create_authentications.rb index 929ac756a..226f1c34c 100644 --- a/db/migrate/20130404174459_create_authentications.rb +++ b/db/migrate/20130404174459_create_authentications.rb @@ -1,4 +1,4 @@ -class CreateAuthentications < ActiveRecord::Migration +class CreateAuthentications < ActiveRecord::Migration[4.2] def change create_table :authentications do |t| t.integer :member_id, null: false diff --git a/db/migrate/20130409103549_make_post_subject_non_null.rb b/db/migrate/20130409103549_make_post_subject_non_null.rb index 877bd048f..ac05aca24 100644 --- a/db/migrate/20130409103549_make_post_subject_non_null.rb +++ b/db/migrate/20130409103549_make_post_subject_non_null.rb @@ -1,3 +1,3 @@ -class MakePostSubjectNonNull < ActiveRecord::Migration +class MakePostSubjectNonNull < ActiveRecord::Migration[4.2] change_column :posts, :subject, :string, null: false end diff --git a/db/migrate/20130409162140_add_name_to_authentications.rb b/db/migrate/20130409162140_add_name_to_authentications.rb index c8e981b5f..dabcb623a 100644 --- a/db/migrate/20130409162140_add_name_to_authentications.rb +++ b/db/migrate/20130409162140_add_name_to_authentications.rb @@ -1,4 +1,4 @@ -class AddNameToAuthentications < ActiveRecord::Migration +class AddNameToAuthentications < ActiveRecord::Migration[4.2] def change add_column :authentications, :name, :string end diff --git a/db/migrate/20130507105357_create_products.rb b/db/migrate/20130507105357_create_products.rb index 66a43c43b..5a1ddd995 100644 --- a/db/migrate/20130507105357_create_products.rb +++ b/db/migrate/20130507105357_create_products.rb @@ -1,4 +1,4 @@ -class CreateProducts < ActiveRecord::Migration +class CreateProducts < ActiveRecord::Migration[4.2] def change create_table :products do |t| t.string :name, null: false diff --git a/db/migrate/20130507110411_create_orders.rb b/db/migrate/20130507110411_create_orders.rb index 8d709e172..7974f10e9 100644 --- a/db/migrate/20130507110411_create_orders.rb +++ b/db/migrate/20130507110411_create_orders.rb @@ -1,4 +1,4 @@ -class CreateOrders < ActiveRecord::Migration +class CreateOrders < ActiveRecord::Migration[4.2] def change create_table :orders do |t| t.string :member_id, null: false diff --git a/db/migrate/20130507113915_add_orders_products_table.rb b/db/migrate/20130507113915_add_orders_products_table.rb index 8666e01ab..3d5845081 100644 --- a/db/migrate/20130507113915_add_orders_products_table.rb +++ b/db/migrate/20130507113915_add_orders_products_table.rb @@ -1,4 +1,4 @@ -class AddOrdersProductsTable < ActiveRecord::Migration +class AddOrdersProductsTable < ActiveRecord::Migration[4.2] def change create_table :orders_products, id: false do |t| t.integer :order_id diff --git a/db/migrate/20130508050711_add_completed_to_order.rb b/db/migrate/20130508050711_add_completed_to_order.rb index bcaffebbf..e7c9f422c 100644 --- a/db/migrate/20130508050711_add_completed_to_order.rb +++ b/db/migrate/20130508050711_add_completed_to_order.rb @@ -1,4 +1,4 @@ -class AddCompletedToOrder < ActiveRecord::Migration +class AddCompletedToOrder < ActiveRecord::Migration[4.2] def change add_column :orders, :completed_at, :datetime end diff --git a/db/migrate/20130508104506_create_photos.rb b/db/migrate/20130508104506_create_photos.rb index 84b54ed6c..b6fb3d19f 100644 --- a/db/migrate/20130508104506_create_photos.rb +++ b/db/migrate/20130508104506_create_photos.rb @@ -1,4 +1,4 @@ -class CreatePhotos < ActiveRecord::Migration +class CreatePhotos < ActiveRecord::Migration[4.2] def change create_table :photos do |t| t.integer :owner_id, null: false diff --git a/db/migrate/20130509123711_add_metadata_to_photos.rb b/db/migrate/20130509123711_add_metadata_to_photos.rb index cb76a901a..e05c260cb 100644 --- a/db/migrate/20130509123711_add_metadata_to_photos.rb +++ b/db/migrate/20130509123711_add_metadata_to_photos.rb @@ -1,4 +1,4 @@ -class AddMetadataToPhotos < ActiveRecord::Migration +class AddMetadataToPhotos < ActiveRecord::Migration[4.2] def up change_table :photos do |t| t.string :title diff --git a/db/migrate/20130514124515_add_parent_to_crop.rb b/db/migrate/20130514124515_add_parent_to_crop.rb index 8a6019808..65427c1c8 100644 --- a/db/migrate/20130514124515_add_parent_to_crop.rb +++ b/db/migrate/20130514124515_add_parent_to_crop.rb @@ -1,4 +1,4 @@ -class AddParentToCrop < ActiveRecord::Migration +class AddParentToCrop < ActiveRecord::Migration[4.2] def change add_column :crops, :parent_id, :integer end diff --git a/db/migrate/20130515033842_create_order_items.rb b/db/migrate/20130515033842_create_order_items.rb index cf06827ca..ed7966f46 100644 --- a/db/migrate/20130515033842_create_order_items.rb +++ b/db/migrate/20130515033842_create_order_items.rb @@ -1,4 +1,4 @@ -class CreateOrderItems < ActiveRecord::Migration +class CreateOrderItems < ActiveRecord::Migration[4.2] def change create_table :order_items do |t| t.integer :order_id diff --git a/db/migrate/20130515054017_change_order_member_id_to_integer.rb b/db/migrate/20130515054017_change_order_member_id_to_integer.rb index 2905204d7..508fb13ee 100644 --- a/db/migrate/20130515054017_change_order_member_id_to_integer.rb +++ b/db/migrate/20130515054017_change_order_member_id_to_integer.rb @@ -1,4 +1,4 @@ -class ChangeOrderMemberIdToInteger < ActiveRecord::Migration +class ChangeOrderMemberIdToInteger < ActiveRecord::Migration[4.2] def up remove_column :orders, :member_id add_column :orders, :member_id, :integer diff --git a/db/migrate/20130515122301_change_prices_to_integers.rb b/db/migrate/20130515122301_change_prices_to_integers.rb index f07d45dea..ef84683b2 100644 --- a/db/migrate/20130515122301_change_prices_to_integers.rb +++ b/db/migrate/20130515122301_change_prices_to_integers.rb @@ -1,4 +1,4 @@ -class ChangePricesToIntegers < ActiveRecord::Migration +class ChangePricesToIntegers < ActiveRecord::Migration[4.2] def up change_column :order_items, :price, :integer change_column :products, :min_price, :integer diff --git a/db/migrate/20130517015920_create_account_details.rb b/db/migrate/20130517015920_create_account_details.rb index 81d94a324..c949798dc 100644 --- a/db/migrate/20130517015920_create_account_details.rb +++ b/db/migrate/20130517015920_create_account_details.rb @@ -1,4 +1,4 @@ -class CreateAccountDetails < ActiveRecord::Migration +class CreateAccountDetails < ActiveRecord::Migration[4.2] def change create_table :account_details do |t| t.integer :member_id, null: false diff --git a/db/migrate/20130517051922_create_account_types.rb b/db/migrate/20130517051922_create_account_types.rb index 8858e9cad..25bef37b0 100644 --- a/db/migrate/20130517051922_create_account_types.rb +++ b/db/migrate/20130517051922_create_account_types.rb @@ -1,4 +1,4 @@ -class CreateAccountTypes < ActiveRecord::Migration +class CreateAccountTypes < ActiveRecord::Migration[4.2] def change create_table :account_types do |t| t.string :name diff --git a/db/migrate/20130517234458_require_account_type_name.rb b/db/migrate/20130517234458_require_account_type_name.rb index 6e745cb4b..2b118492a 100644 --- a/db/migrate/20130517234458_require_account_type_name.rb +++ b/db/migrate/20130517234458_require_account_type_name.rb @@ -1,4 +1,4 @@ -class RequireAccountTypeName < ActiveRecord::Migration +class RequireAccountTypeName < ActiveRecord::Migration[4.2] def up change_column :account_types, :name, :string, null: false end diff --git a/db/migrate/20130518000339_add_columns_to_product.rb b/db/migrate/20130518000339_add_columns_to_product.rb index bb3bcf781..b3bba3023 100644 --- a/db/migrate/20130518000339_add_columns_to_product.rb +++ b/db/migrate/20130518000339_add_columns_to_product.rb @@ -1,4 +1,4 @@ -class AddColumnsToProduct < ActiveRecord::Migration +class AddColumnsToProduct < ActiveRecord::Migration[4.2] def change add_column :products, :account_type_id, :integer add_column :products, :paid_months, :integer diff --git a/db/migrate/20130518002942_rename_account_detail_to_account.rb b/db/migrate/20130518002942_rename_account_detail_to_account.rb index 0a8434694..a806c63a7 100644 --- a/db/migrate/20130518002942_rename_account_detail_to_account.rb +++ b/db/migrate/20130518002942_rename_account_detail_to_account.rb @@ -1,4 +1,4 @@ -class RenameAccountDetailToAccount < ActiveRecord::Migration +class RenameAccountDetailToAccount < ActiveRecord::Migration[4.2] def change rename_table :account_details, :accounts end diff --git a/db/migrate/20130529032813_add_express_token_to_orders.rb b/db/migrate/20130529032813_add_express_token_to_orders.rb index cf32be434..e7d40f417 100644 --- a/db/migrate/20130529032813_add_express_token_to_orders.rb +++ b/db/migrate/20130529032813_add_express_token_to_orders.rb @@ -1,4 +1,4 @@ -class AddExpressTokenToOrders < ActiveRecord::Migration +class AddExpressTokenToOrders < ActiveRecord::Migration[4.2] def change add_column :orders, :paypal_express_token, :string add_column :orders, :paypal_express_payer_id, :string diff --git a/db/migrate/20130531110729_add_photos_plantings_table.rb b/db/migrate/20130531110729_add_photos_plantings_table.rb index ab08ff0d1..f4a3bb7bd 100644 --- a/db/migrate/20130531110729_add_photos_plantings_table.rb +++ b/db/migrate/20130531110729_add_photos_plantings_table.rb @@ -1,4 +1,4 @@ -class AddPhotosPlantingsTable < ActiveRecord::Migration +class AddPhotosPlantingsTable < ActiveRecord::Migration[4.2] def change create_table :photos_plantings, id: false do |t| t.integer :photo_id diff --git a/db/migrate/20130601011725_change_flickr_photo_id_to_string.rb b/db/migrate/20130601011725_change_flickr_photo_id_to_string.rb index 01afc35d3..92cfa1683 100644 --- a/db/migrate/20130601011725_change_flickr_photo_id_to_string.rb +++ b/db/migrate/20130601011725_change_flickr_photo_id_to_string.rb @@ -1,4 +1,4 @@ -class ChangeFlickrPhotoIdToString < ActiveRecord::Migration +class ChangeFlickrPhotoIdToString < ActiveRecord::Migration[4.2] def up remove_column :photos, :flickr_photo_id add_column :photos, :flickr_photo_id, :string diff --git a/db/migrate/20130606230333_change_product_description_to_text.rb b/db/migrate/20130606230333_change_product_description_to_text.rb index d20e44f64..3393a8ae9 100644 --- a/db/migrate/20130606230333_change_product_description_to_text.rb +++ b/db/migrate/20130606230333_change_product_description_to_text.rb @@ -1,4 +1,4 @@ -class ChangeProductDescriptionToText < ActiveRecord::Migration +class ChangeProductDescriptionToText < ActiveRecord::Migration[4.2] def up change_column :products, :description, :text end diff --git a/db/migrate/20130606233733_add_recommended_price_to_product.rb b/db/migrate/20130606233733_add_recommended_price_to_product.rb index c1aff96d4..d424618f5 100644 --- a/db/migrate/20130606233733_add_recommended_price_to_product.rb +++ b/db/migrate/20130606233733_add_recommended_price_to_product.rb @@ -1,4 +1,4 @@ -class AddRecommendedPriceToProduct < ActiveRecord::Migration +class AddRecommendedPriceToProduct < ActiveRecord::Migration[4.2] def change add_column :products, :recommended_price, :integer end diff --git a/db/migrate/20130705104238_add_planted_from_to_planting.rb b/db/migrate/20130705104238_add_planted_from_to_planting.rb index 7eb362a85..1dd4e070d 100644 --- a/db/migrate/20130705104238_add_planted_from_to_planting.rb +++ b/db/migrate/20130705104238_add_planted_from_to_planting.rb @@ -1,4 +1,4 @@ -class AddPlantedFromToPlanting < ActiveRecord::Migration +class AddPlantedFromToPlanting < ActiveRecord::Migration[4.2] def change add_column :plantings, :planted_from, :string end diff --git a/db/migrate/20130715110134_create_seeds.rb b/db/migrate/20130715110134_create_seeds.rb index 6d7cc9674..da8955718 100644 --- a/db/migrate/20130715110134_create_seeds.rb +++ b/db/migrate/20130715110134_create_seeds.rb @@ -1,4 +1,4 @@ -class CreateSeeds < ActiveRecord::Migration +class CreateSeeds < ActiveRecord::Migration[4.2] def change create_table :seeds do |t| t.integer :owner_id, null: false diff --git a/db/migrate/20130718005600_change_use_by_to_plant_before_on_seed.rb b/db/migrate/20130718005600_change_use_by_to_plant_before_on_seed.rb index 23ffefaf9..b440c2704 100644 --- a/db/migrate/20130718005600_change_use_by_to_plant_before_on_seed.rb +++ b/db/migrate/20130718005600_change_use_by_to_plant_before_on_seed.rb @@ -1,4 +1,4 @@ -class ChangeUseByToPlantBeforeOnSeed < ActiveRecord::Migration +class ChangeUseByToPlantBeforeOnSeed < ActiveRecord::Migration[4.2] def change rename_column :seeds, :use_by, :plant_before end diff --git a/db/migrate/20130718011247_add_trading_to_seeds.rb b/db/migrate/20130718011247_add_trading_to_seeds.rb index 2ed459577..52add7f50 100644 --- a/db/migrate/20130718011247_add_trading_to_seeds.rb +++ b/db/migrate/20130718011247_add_trading_to_seeds.rb @@ -1,4 +1,4 @@ -class AddTradingToSeeds < ActiveRecord::Migration +class AddTradingToSeeds < ActiveRecord::Migration[4.2] def change add_column :seeds, :tradable, :boolean add_column :seeds, :tradable_to, :string diff --git a/db/migrate/20130722050836_remove_tradable_from_seeds.rb b/db/migrate/20130722050836_remove_tradable_from_seeds.rb index 7e0457c10..9bea0bd10 100644 --- a/db/migrate/20130722050836_remove_tradable_from_seeds.rb +++ b/db/migrate/20130722050836_remove_tradable_from_seeds.rb @@ -1,4 +1,4 @@ -class RemoveTradableFromSeeds < ActiveRecord::Migration +class RemoveTradableFromSeeds < ActiveRecord::Migration[4.2] def up remove_column :seeds, :tradable end diff --git a/db/migrate/20130723103128_set_default_tradable_to_on_seed.rb b/db/migrate/20130723103128_set_default_tradable_to_on_seed.rb index df94b3150..56b88aadb 100644 --- a/db/migrate/20130723103128_set_default_tradable_to_on_seed.rb +++ b/db/migrate/20130723103128_set_default_tradable_to_on_seed.rb @@ -1,4 +1,4 @@ -class SetDefaultTradableToOnSeed < ActiveRecord::Migration +class SetDefaultTradableToOnSeed < ActiveRecord::Migration[4.2] def up change_column_default(:seeds, :tradable_to, 'nowhere') end diff --git a/db/migrate/20130723110702_add_slug_to_seed.rb b/db/migrate/20130723110702_add_slug_to_seed.rb index 684c2183e..ec52bdad6 100644 --- a/db/migrate/20130723110702_add_slug_to_seed.rb +++ b/db/migrate/20130723110702_add_slug_to_seed.rb @@ -1,4 +1,4 @@ -class AddSlugToSeed < ActiveRecord::Migration +class AddSlugToSeed < ActiveRecord::Migration[4.2] def change add_column :seeds, :slug, :string add_index :seeds, :slug, unique: true diff --git a/db/migrate/20130809012511_add_bio_to_members.rb b/db/migrate/20130809012511_add_bio_to_members.rb index 62a5a7706..b63d11bb4 100644 --- a/db/migrate/20130809012511_add_bio_to_members.rb +++ b/db/migrate/20130809012511_add_bio_to_members.rb @@ -1,4 +1,4 @@ -class AddBioToMembers < ActiveRecord::Migration +class AddBioToMembers < ActiveRecord::Migration[4.2] def change add_column :members, :bio, :text end diff --git a/db/migrate/20130819004549_add_planting_count_to_crop.rb b/db/migrate/20130819004549_add_planting_count_to_crop.rb index 0ae01f4bb..b25fc4a6b 100644 --- a/db/migrate/20130819004549_add_planting_count_to_crop.rb +++ b/db/migrate/20130819004549_add_planting_count_to_crop.rb @@ -1,4 +1,4 @@ -class AddPlantingCountToCrop < ActiveRecord::Migration +class AddPlantingCountToCrop < ActiveRecord::Migration[4.2] def change add_column :crops, :plantings_count, :integer end diff --git a/db/migrate/20130821011352_add_creator_to_crops.rb b/db/migrate/20130821011352_add_creator_to_crops.rb index 4da89b8d1..24aab3f74 100644 --- a/db/migrate/20130821011352_add_creator_to_crops.rb +++ b/db/migrate/20130821011352_add_creator_to_crops.rb @@ -1,4 +1,4 @@ -class AddCreatorToCrops < ActiveRecord::Migration +class AddCreatorToCrops < ActiveRecord::Migration[4.2] def change add_column :crops, :creator_id, :integer end diff --git a/db/migrate/20130821073736_add_creator_to_scientific_name.rb b/db/migrate/20130821073736_add_creator_to_scientific_name.rb index 0905a5c40..e2904811f 100644 --- a/db/migrate/20130821073736_add_creator_to_scientific_name.rb +++ b/db/migrate/20130821073736_add_creator_to_scientific_name.rb @@ -1,4 +1,4 @@ -class AddCreatorToScientificName < ActiveRecord::Migration +class AddCreatorToScientificName < ActiveRecord::Migration[4.2] def change add_column :scientific_names, :creator_id, :integer end diff --git a/db/migrate/20130826012139_add_owner_to_planting.rb b/db/migrate/20130826012139_add_owner_to_planting.rb index 0f32568b2..3399870d9 100644 --- a/db/migrate/20130826012139_add_owner_to_planting.rb +++ b/db/migrate/20130826012139_add_owner_to_planting.rb @@ -1,4 +1,4 @@ -class AddOwnerToPlanting < ActiveRecord::Migration +class AddOwnerToPlanting < ActiveRecord::Migration[4.2] def change add_column :plantings, :owner_id, :integer end diff --git a/db/migrate/20130826023159_add_plantings_count_to_member.rb b/db/migrate/20130826023159_add_plantings_count_to_member.rb index 06819f61c..973479981 100644 --- a/db/migrate/20130826023159_add_plantings_count_to_member.rb +++ b/db/migrate/20130826023159_add_plantings_count_to_member.rb @@ -1,4 +1,4 @@ -class AddPlantingsCountToMember < ActiveRecord::Migration +class AddPlantingsCountToMember < ActiveRecord::Migration[4.2] def change add_column :members, :plantings_count, :integer end diff --git a/db/migrate/20130827105823_add_newsletter_to_member.rb b/db/migrate/20130827105823_add_newsletter_to_member.rb index 919e5222f..25f16a69f 100644 --- a/db/migrate/20130827105823_add_newsletter_to_member.rb +++ b/db/migrate/20130827105823_add_newsletter_to_member.rb @@ -1,4 +1,4 @@ -class AddNewsletterToMember < ActiveRecord::Migration +class AddNewsletterToMember < ActiveRecord::Migration[4.2] def change add_column :members, :newsletter, :boolean end diff --git a/db/migrate/20130913015118_add_referral_code_to_order.rb b/db/migrate/20130913015118_add_referral_code_to_order.rb index efd06c21e..ff9e5a6ff 100644 --- a/db/migrate/20130913015118_add_referral_code_to_order.rb +++ b/db/migrate/20130913015118_add_referral_code_to_order.rb @@ -1,4 +1,4 @@ -class AddReferralCodeToOrder < ActiveRecord::Migration +class AddReferralCodeToOrder < ActiveRecord::Migration[4.2] def change add_column :orders, :referral_code, :string end diff --git a/db/migrate/20130917053547_create_harvests.rb b/db/migrate/20130917053547_create_harvests.rb index 928f60d08..f7e529a30 100644 --- a/db/migrate/20130917053547_create_harvests.rb +++ b/db/migrate/20130917053547_create_harvests.rb @@ -1,4 +1,4 @@ -class CreateHarvests < ActiveRecord::Migration +class CreateHarvests < ActiveRecord::Migration[4.2] def change create_table :harvests do |t| t.integer :crop_id, null: false diff --git a/db/migrate/20130917060257_change_harvest_notes_to_description.rb b/db/migrate/20130917060257_change_harvest_notes_to_description.rb index bac3167cf..8359c0b9c 100644 --- a/db/migrate/20130917060257_change_harvest_notes_to_description.rb +++ b/db/migrate/20130917060257_change_harvest_notes_to_description.rb @@ -1,4 +1,4 @@ -class ChangeHarvestNotesToDescription < ActiveRecord::Migration +class ChangeHarvestNotesToDescription < ActiveRecord::Migration[4.2] def change rename_column :harvests, :notes, :description end diff --git a/db/migrate/20130917071545_change_harvest_units_to_unit.rb b/db/migrate/20130917071545_change_harvest_units_to_unit.rb index d843c2c3d..7f859f47d 100644 --- a/db/migrate/20130917071545_change_harvest_units_to_unit.rb +++ b/db/migrate/20130917071545_change_harvest_units_to_unit.rb @@ -1,4 +1,4 @@ -class ChangeHarvestUnitsToUnit < ActiveRecord::Migration +class ChangeHarvestUnitsToUnit < ActiveRecord::Migration[4.2] def change rename_column :harvests, :units, :unit end diff --git a/db/migrate/20130917075803_add_slug_to_harvests.rb b/db/migrate/20130917075803_add_slug_to_harvests.rb index 21b44d0ae..b9bc376e0 100644 --- a/db/migrate/20130917075803_add_slug_to_harvests.rb +++ b/db/migrate/20130917075803_add_slug_to_harvests.rb @@ -1,4 +1,4 @@ -class AddSlugToHarvests < ActiveRecord::Migration +class AddSlugToHarvests < ActiveRecord::Migration[4.2] def change add_column :harvests, :slug, :string end diff --git a/db/migrate/20130925050304_add_weight_to_harvests.rb b/db/migrate/20130925050304_add_weight_to_harvests.rb index caf1fd87a..1aa43df6b 100644 --- a/db/migrate/20130925050304_add_weight_to_harvests.rb +++ b/db/migrate/20130925050304_add_weight_to_harvests.rb @@ -1,4 +1,4 @@ -class AddWeightToHarvests < ActiveRecord::Migration +class AddWeightToHarvests < ActiveRecord::Migration[4.2] def change add_column :harvests, :weight_quantity, :decimal add_column :harvests, :weight_unit, :string diff --git a/db/migrate/20131018101204_rename_system_name_to_name.rb b/db/migrate/20131018101204_rename_system_name_to_name.rb index 41f810a5d..6124d1746 100644 --- a/db/migrate/20131018101204_rename_system_name_to_name.rb +++ b/db/migrate/20131018101204_rename_system_name_to_name.rb @@ -1,4 +1,4 @@ -class RenameSystemNameToName < ActiveRecord::Migration +class RenameSystemNameToName < ActiveRecord::Migration[4.2] def up # Rails is smart enough to alter the column being indexed, but not the name # of the index, and there's no rename_index command. diff --git a/db/migrate/20131025104228_add_fields_to_gardens.rb b/db/migrate/20131025104228_add_fields_to_gardens.rb index 2c3983507..e77a9c6c9 100644 --- a/db/migrate/20131025104228_add_fields_to_gardens.rb +++ b/db/migrate/20131025104228_add_fields_to_gardens.rb @@ -1,4 +1,4 @@ -class AddFieldsToGardens < ActiveRecord::Migration +class AddFieldsToGardens < ActiveRecord::Migration[4.2] def change add_column :gardens, :active, :boolean, default: true add_column :gardens, :location, :string diff --git a/db/migrate/20131029053113_add_plant_part_to_harvests.rb b/db/migrate/20131029053113_add_plant_part_to_harvests.rb index 0619bbb3e..fad21613f 100644 --- a/db/migrate/20131029053113_add_plant_part_to_harvests.rb +++ b/db/migrate/20131029053113_add_plant_part_to_harvests.rb @@ -1,4 +1,4 @@ -class AddPlantPartToHarvests < ActiveRecord::Migration +class AddPlantPartToHarvests < ActiveRecord::Migration[4.2] def change add_column :harvests, :plant_part, :string end diff --git a/db/migrate/20131030230908_create_plant_parts.rb b/db/migrate/20131030230908_create_plant_parts.rb index 0772a22b2..f3454f978 100644 --- a/db/migrate/20131030230908_create_plant_parts.rb +++ b/db/migrate/20131030230908_create_plant_parts.rb @@ -1,4 +1,4 @@ -class CreatePlantParts < ActiveRecord::Migration +class CreatePlantParts < ActiveRecord::Migration[4.2] def change create_table :plant_parts do |t| t.string :name diff --git a/db/migrate/20131030231202_change_plant_part_to_plant_part_id.rb b/db/migrate/20131030231202_change_plant_part_to_plant_part_id.rb index cfadbf1c6..134eeca97 100644 --- a/db/migrate/20131030231202_change_plant_part_to_plant_part_id.rb +++ b/db/migrate/20131030231202_change_plant_part_to_plant_part_id.rb @@ -1,4 +1,4 @@ -class ChangePlantPartToPlantPartId < ActiveRecord::Migration +class ChangePlantPartToPlantPartId < ActiveRecord::Migration[4.2] def up remove_column :harvests, :plant_part add_column :harvests, :plant_part_id, :integer diff --git a/db/migrate/20131031000655_add_slug_to_plant_part.rb b/db/migrate/20131031000655_add_slug_to_plant_part.rb index 9af39cec6..242c30776 100644 --- a/db/migrate/20131031000655_add_slug_to_plant_part.rb +++ b/db/migrate/20131031000655_add_slug_to_plant_part.rb @@ -1,4 +1,4 @@ -class AddSlugToPlantPart < ActiveRecord::Migration +class AddSlugToPlantPart < ActiveRecord::Migration[4.2] def change add_column :plant_parts, :slug, :string end diff --git a/db/migrate/20140718075753_default_plantings_count_to_zero.rb b/db/migrate/20140718075753_default_plantings_count_to_zero.rb index ce8d0d075..15ee6df8d 100644 --- a/db/migrate/20140718075753_default_plantings_count_to_zero.rb +++ b/db/migrate/20140718075753_default_plantings_count_to_zero.rb @@ -1,4 +1,4 @@ -class DefaultPlantingsCountToZero < ActiveRecord::Migration +class DefaultPlantingsCountToZero < ActiveRecord::Migration[4.2] def up change_column :crops, :plantings_count, :integer, default: 0 end diff --git a/db/migrate/20140829230600_add_finished_to_planting.rb b/db/migrate/20140829230600_add_finished_to_planting.rb index f8cb41663..868298f6d 100644 --- a/db/migrate/20140829230600_add_finished_to_planting.rb +++ b/db/migrate/20140829230600_add_finished_to_planting.rb @@ -1,4 +1,4 @@ -class AddFinishedToPlanting < ActiveRecord::Migration +class AddFinishedToPlanting < ActiveRecord::Migration[4.2] def change add_column :plantings, :finished, :boolean, default: false add_column :plantings, :finished_at, :date diff --git a/db/migrate/20140905001730_add_harvests_photos_table.rb b/db/migrate/20140905001730_add_harvests_photos_table.rb index fb9c73a37..f05ae0135 100644 --- a/db/migrate/20140905001730_add_harvests_photos_table.rb +++ b/db/migrate/20140905001730_add_harvests_photos_table.rb @@ -1,4 +1,4 @@ -class AddHarvestsPhotosTable < ActiveRecord::Migration +class AddHarvestsPhotosTable < ActiveRecord::Migration[4.2] def change create_table :harvests_photos, id: false do |t| t.integer :photo_id diff --git a/db/migrate/20140928044231_add_crops_posts_table.rb b/db/migrate/20140928044231_add_crops_posts_table.rb index 6dcf9a494..a9e8761f9 100644 --- a/db/migrate/20140928044231_add_crops_posts_table.rb +++ b/db/migrate/20140928044231_add_crops_posts_table.rb @@ -1,4 +1,4 @@ -class AddCropsPostsTable < ActiveRecord::Migration +class AddCropsPostsTable < ActiveRecord::Migration[4.2] def change create_table :crops_posts, id: false do |t| t.integer :crop_id diff --git a/db/migrate/20140928085713_add_send_planting_reminder_to_member.rb b/db/migrate/20140928085713_add_send_planting_reminder_to_member.rb index 67c7184d7..cd464eeed 100644 --- a/db/migrate/20140928085713_add_send_planting_reminder_to_member.rb +++ b/db/migrate/20140928085713_add_send_planting_reminder_to_member.rb @@ -1,4 +1,4 @@ -class AddSendPlantingReminderToMember < ActiveRecord::Migration +class AddSendPlantingReminderToMember < ActiveRecord::Migration[4.2] def change add_column :members, :send_planting_reminder, :boolean, default: true end diff --git a/db/migrate/20141002022459_create_index_harvest_photos.rb b/db/migrate/20141002022459_create_index_harvest_photos.rb index 95913bd04..f9c8ee911 100644 --- a/db/migrate/20141002022459_create_index_harvest_photos.rb +++ b/db/migrate/20141002022459_create_index_harvest_photos.rb @@ -1,4 +1,4 @@ -class CreateIndexHarvestPhotos < ActiveRecord::Migration +class CreateIndexHarvestPhotos < ActiveRecord::Migration[4.2] def change add_index(:harvests_photos, %i(harvest_id photo_id)) end diff --git a/db/migrate/20141018111015_create_alternate_names.rb b/db/migrate/20141018111015_create_alternate_names.rb index facb96100..65400cc22 100644 --- a/db/migrate/20141018111015_create_alternate_names.rb +++ b/db/migrate/20141018111015_create_alternate_names.rb @@ -1,4 +1,4 @@ -class CreateAlternateNames < ActiveRecord::Migration +class CreateAlternateNames < ActiveRecord::Migration[4.2] def change create_table :alternate_names do |t| t.string :name, null: false diff --git a/db/migrate/20141111130849_create_follows.rb b/db/migrate/20141111130849_create_follows.rb index 9c3f03b74..5ca3f9b12 100644 --- a/db/migrate/20141111130849_create_follows.rb +++ b/db/migrate/20141111130849_create_follows.rb @@ -1,4 +1,4 @@ -class CreateFollows < ActiveRecord::Migration +class CreateFollows < ActiveRecord::Migration[4.2] def change create_table :follows do |t| t.integer :member_id diff --git a/db/migrate/20141119130555_change_follows_member_id_to_follower_id.rb b/db/migrate/20141119130555_change_follows_member_id_to_follower_id.rb index cb9e58d3a..a777fc79f 100644 --- a/db/migrate/20141119130555_change_follows_member_id_to_follower_id.rb +++ b/db/migrate/20141119130555_change_follows_member_id_to_follower_id.rb @@ -1,4 +1,4 @@ -class ChangeFollowsMemberIdToFollowerId < ActiveRecord::Migration +class ChangeFollowsMemberIdToFollowerId < ActiveRecord::Migration[4.2] def change rename_column :follows, :member_id, :follower_id end diff --git a/db/migrate/20150124110540_add_properties_to_seeds.rb b/db/migrate/20150124110540_add_properties_to_seeds.rb index 7d60735fd..0adb96600 100644 --- a/db/migrate/20150124110540_add_properties_to_seeds.rb +++ b/db/migrate/20150124110540_add_properties_to_seeds.rb @@ -1,4 +1,4 @@ -class AddPropertiesToSeeds < ActiveRecord::Migration +class AddPropertiesToSeeds < ActiveRecord::Migration[4.2] def change add_column :seeds, :days_until_maturity_min, :integer add_column :seeds, :days_until_maturity_max, :integer diff --git a/db/migrate/20150127043022_add_gardens_photos_table.rb b/db/migrate/20150127043022_add_gardens_photos_table.rb index 0c2b99dfe..459174245 100644 --- a/db/migrate/20150127043022_add_gardens_photos_table.rb +++ b/db/migrate/20150127043022_add_gardens_photos_table.rb @@ -1,4 +1,4 @@ -class AddGardensPhotosTable < ActiveRecord::Migration +class AddGardensPhotosTable < ActiveRecord::Migration[4.2] def change create_table :gardens_photos, id: false do |t| t.integer :photo_id diff --git a/db/migrate/20150129034206_add_si_weight_to_harvest.rb b/db/migrate/20150129034206_add_si_weight_to_harvest.rb index b1e532d8d..881d4ad01 100644 --- a/db/migrate/20150129034206_add_si_weight_to_harvest.rb +++ b/db/migrate/20150129034206_add_si_weight_to_harvest.rb @@ -1,4 +1,4 @@ -class AddSiWeightToHarvest < ActiveRecord::Migration +class AddSiWeightToHarvest < ActiveRecord::Migration[4.2] def change add_column :harvests, :si_weight, :float end diff --git a/db/migrate/20150130224814_add_requester_to_crops.rb b/db/migrate/20150130224814_add_requester_to_crops.rb index f284a6f68..0d9f70943 100644 --- a/db/migrate/20150130224814_add_requester_to_crops.rb +++ b/db/migrate/20150130224814_add_requester_to_crops.rb @@ -1,4 +1,4 @@ -class AddRequesterToCrops < ActiveRecord::Migration +class AddRequesterToCrops < ActiveRecord::Migration[4.2] def change add_column :crops, :requester_id, :integer add_index :crops, :requester_id diff --git a/db/migrate/20150201052245_create_cms.rb b/db/migrate/20150201052245_create_cms.rb index e8ba4fb9e..91fea54e8 100644 --- a/db/migrate/20150201052245_create_cms.rb +++ b/db/migrate/20150201052245_create_cms.rb @@ -1,4 +1,4 @@ -class CreateCms < ActiveRecord::Migration +class CreateCms < ActiveRecord::Migration[4.2] def self.up # rubocop:disable Metrics/MethodLength, Metrics/AbcSize text_limit = case ActiveRecord::Base.connection.adapter_name when 'PostgreSQL' diff --git a/db/migrate/20150201053200_add_approval_status_to_crops.rb b/db/migrate/20150201053200_add_approval_status_to_crops.rb index 07b1e0879..ff6b12cbb 100644 --- a/db/migrate/20150201053200_add_approval_status_to_crops.rb +++ b/db/migrate/20150201053200_add_approval_status_to_crops.rb @@ -1,4 +1,4 @@ -class AddApprovalStatusToCrops < ActiveRecord::Migration +class AddApprovalStatusToCrops < ActiveRecord::Migration[4.2] def change add_column :crops, :approval_status, :string, default: "approved" end diff --git a/db/migrate/20150201062506_add_reason_for_rejection_to_crops.rb b/db/migrate/20150201062506_add_reason_for_rejection_to_crops.rb index 0fd283a67..001cd795b 100644 --- a/db/migrate/20150201062506_add_reason_for_rejection_to_crops.rb +++ b/db/migrate/20150201062506_add_reason_for_rejection_to_crops.rb @@ -1,4 +1,4 @@ -class AddReasonForRejectionToCrops < ActiveRecord::Migration +class AddReasonForRejectionToCrops < ActiveRecord::Migration[4.2] def change add_column :crops, :reason_for_rejection, :text end diff --git a/db/migrate/20150201064502_add_request_notes_to_crops.rb b/db/migrate/20150201064502_add_request_notes_to_crops.rb index 0720bf4cb..433c5ad35 100644 --- a/db/migrate/20150201064502_add_request_notes_to_crops.rb +++ b/db/migrate/20150201064502_add_request_notes_to_crops.rb @@ -1,4 +1,4 @@ -class AddRequestNotesToCrops < ActiveRecord::Migration +class AddRequestNotesToCrops < ActiveRecord::Migration[4.2] def change add_column :crops, :request_notes, :text end diff --git a/db/migrate/20150203080226_create_likes.rb b/db/migrate/20150203080226_create_likes.rb index 71960699c..b5f7d427b 100644 --- a/db/migrate/20150203080226_create_likes.rb +++ b/db/migrate/20150203080226_create_likes.rb @@ -1,4 +1,4 @@ -class CreateLikes < ActiveRecord::Migration +class CreateLikes < ActiveRecord::Migration[4.2] def change create_table :likes do |t| t.references :member, index: true diff --git a/db/migrate/20150209105410_add_rejection_notes_to_crops.rb b/db/migrate/20150209105410_add_rejection_notes_to_crops.rb index 59239fd55..44fc9fb7b 100644 --- a/db/migrate/20150209105410_add_rejection_notes_to_crops.rb +++ b/db/migrate/20150209105410_add_rejection_notes_to_crops.rb @@ -1,4 +1,4 @@ -class AddRejectionNotesToCrops < ActiveRecord::Migration +class AddRejectionNotesToCrops < ActiveRecord::Migration[4.2] def change add_column :crops, :rejection_notes, :text end diff --git a/db/migrate/20150625224805_add_days_before_maturity_to_plantings.rb b/db/migrate/20150625224805_add_days_before_maturity_to_plantings.rb index 0ddf5acb5..c60e6f6a3 100644 --- a/db/migrate/20150625224805_add_days_before_maturity_to_plantings.rb +++ b/db/migrate/20150625224805_add_days_before_maturity_to_plantings.rb @@ -1,4 +1,4 @@ -class AddDaysBeforeMaturityToPlantings < ActiveRecord::Migration +class AddDaysBeforeMaturityToPlantings < ActiveRecord::Migration[4.2] def change add_column :plantings, :days_before_maturity, :integer end diff --git a/db/migrate/20150824145414_add_member_preferred_image.rb b/db/migrate/20150824145414_add_member_preferred_image.rb index dc24bd5a0..c3c563374 100644 --- a/db/migrate/20150824145414_add_member_preferred_image.rb +++ b/db/migrate/20150824145414_add_member_preferred_image.rb @@ -1,4 +1,4 @@ -class AddMemberPreferredImage < ActiveRecord::Migration +class AddMemberPreferredImage < ActiveRecord::Migration[4.2] def change add_column :members, :preferred_avatar_uri, :string end diff --git a/db/migrate/20161129021533_rename_scientific_name.rb b/db/migrate/20161129021533_rename_scientific_name.rb index e2ff2ea0e..3aac2e5d4 100644 --- a/db/migrate/20161129021533_rename_scientific_name.rb +++ b/db/migrate/20161129021533_rename_scientific_name.rb @@ -1,4 +1,4 @@ -class RenameScientificName < ActiveRecord::Migration +class RenameScientificName < ActiveRecord::Migration[4.2] def self.up rename_column :scientific_names, :scientific_name, :name end diff --git a/db/migrate/20161201154922_add_photos_seeds_table.rb b/db/migrate/20161201154922_add_photos_seeds_table.rb index f4a2f18fe..bbe7478c5 100644 --- a/db/migrate/20161201154922_add_photos_seeds_table.rb +++ b/db/migrate/20161201154922_add_photos_seeds_table.rb @@ -1,4 +1,4 @@ -class AddPhotosSeedsTable < ActiveRecord::Migration +class AddPhotosSeedsTable < ActiveRecord::Migration[4.2] def change create_table :photos_seeds, id: false do |t| t.integer :photo_id diff --git a/db/migrate/20170104035248_add_planting_ref_to_harvests.rb b/db/migrate/20170104035248_add_planting_ref_to_harvests.rb index 57935b073..515ffaa83 100644 --- a/db/migrate/20170104035248_add_planting_ref_to_harvests.rb +++ b/db/migrate/20170104035248_add_planting_ref_to_harvests.rb @@ -1,4 +1,4 @@ -class AddPlantingRefToHarvests < ActiveRecord::Migration +class AddPlantingRefToHarvests < ActiveRecord::Migration[4.2] def change add_reference :harvests, :planting, index: true, foreign_key: true end diff --git a/db/migrate/20170413221549_counter_caches.rb b/db/migrate/20170413221549_counter_caches.rb index 45624ea44..27f4f1f6b 100644 --- a/db/migrate/20170413221549_counter_caches.rb +++ b/db/migrate/20170413221549_counter_caches.rb @@ -1,4 +1,4 @@ -class CounterCaches < ActiveRecord::Migration +class CounterCaches < ActiveRecord::Migration[4.2] def change add_column :members, :gardens_count, :integer add_column :members, :harvests_count, :integer diff --git a/db/migrate/20170520060252_add_deleted_to_members.rb b/db/migrate/20170520060252_add_deleted_to_members.rb index 211989869..3e7059aec 100644 --- a/db/migrate/20170520060252_add_deleted_to_members.rb +++ b/db/migrate/20170520060252_add_deleted_to_members.rb @@ -1,4 +1,4 @@ -class AddDeletedToMembers < ActiveRecord::Migration +class AddDeletedToMembers < ActiveRecord::Migration[4.2] def change add_column :members, :deleted_at, :datetime add_index :members, :deleted_at diff --git a/db/migrate/20171022032108_all_the_predictions.rb b/db/migrate/20171022032108_all_the_predictions.rb index c4338ad2a..aa0f1bfde 100644 --- a/db/migrate/20171022032108_all_the_predictions.rb +++ b/db/migrate/20171022032108_all_the_predictions.rb @@ -1,4 +1,4 @@ -class AllThePredictions < ActiveRecord::Migration +class AllThePredictions < ActiveRecord::Migration[4.2] def change add_column :crops, :perennial, :boolean, default: false diff --git a/db/migrate/20171028230429_create_median_function.rb b/db/migrate/20171028230429_create_median_function.rb index e565a4f68..5e57c01d1 100644 --- a/db/migrate/20171028230429_create_median_function.rb +++ b/db/migrate/20171028230429_create_median_function.rb @@ -1,4 +1,4 @@ -class CreateMedianFunction < ActiveRecord::Migration +class CreateMedianFunction < ActiveRecord::Migration[4.2] def up ActiveMedian.create_function end diff --git a/db/migrate/20171105011017_set_prediction_data.rb b/db/migrate/20171105011017_set_prediction_data.rb index 149001927..d964c8848 100644 --- a/db/migrate/20171105011017_set_prediction_data.rb +++ b/db/migrate/20171105011017_set_prediction_data.rb @@ -1,4 +1,4 @@ -class SetPredictionData < ActiveRecord::Migration +class SetPredictionData < ActiveRecord::Migration[4.2] def up say "Updating all plantings time to first harvest" Planting.all.each(&:update_harvest_days) diff --git a/db/migrate/20171129041341_create_photographings.rb b/db/migrate/20171129041341_create_photographings.rb index a18ab3680..a0563fa3c 100644 --- a/db/migrate/20171129041341_create_photographings.rb +++ b/db/migrate/20171129041341_create_photographings.rb @@ -1,4 +1,4 @@ -class CreatePhotographings < ActiveRecord::Migration +class CreatePhotographings < ActiveRecord::Migration[4.2] def change create_table :photographings do |t| t.integer :photo_id, null: false diff --git a/db/schema.rb b/db/schema.rb index ea66548f1..dec08cc13 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180103024400) do +ActiveRecord::Schema.define(version: 20171129041341) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -54,8 +54,8 @@ ActiveRecord::Schema.define(version: 20180103024400) do create_table "comfy_cms_blocks", id: :serial, force: :cascade do |t| t.string "identifier", null: false t.text "content" - t.integer "blockable_id" t.string "blockable_type" + t.integer "blockable_id" t.datetime "created_at" t.datetime "updated_at" t.index ["blockable_id", "blockable_type"], name: "index_comfy_cms_blocks_on_blockable_id_and_blockable_type" @@ -265,8 +265,8 @@ ActiveRecord::Schema.define(version: 20180103024400) do create_table "likes", id: :serial, force: :cascade do |t| t.integer "member_id" - t.integer "likeable_id" t.string "likeable_type" + t.integer "likeable_id" t.string "categories", array: true t.datetime "created_at" t.datetime "updated_at" @@ -421,9 +421,6 @@ ActiveRecord::Schema.define(version: 20180103024400) do t.integer "lifespan" t.integer "days_to_first_harvest" t.integer "days_to_last_harvest" - t.boolean "failed" - t.text "failure_cause" - t.index ["failed"], name: "index_plantings_on_failed" t.index ["slug"], name: "index_plantings_on_slug", unique: true end From 2fd13e9b7c92372ac545e8eee678d90a7c7a30d1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 4 Jan 2018 14:44:52 +1300 Subject: [PATCH 032/267] Updated new path to jquery autocomplete --- app/assets/javascripts/application.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 0ad04350c..78d273c6c 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -15,7 +15,7 @@ //= require js-routes //= require jquery //= require jquery_ujs -//= require jquery-ui/autocomplete +//= require jquery-ui/widgets/autocomplete //= require bootstrap-sprockets //= require bootstrap-datepicker //= require_tree . From 090bc0226925ea0bd64faef6450f65893c82ce71 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 4 Jan 2018 14:55:36 +1300 Subject: [PATCH 033/267] `belongs_to` defaults to required. setting some to optional --- app/models/crop.rb | 4 ++-- app/models/harvest.rb | 2 +- app/models/post.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index a961daf58..f87fbb262 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -17,8 +17,8 @@ class Crop < ApplicationRecord has_many :harvests has_many :plant_parts, -> { uniq.reorder("plant_parts.name") }, through: :harvests belongs_to :creator, class_name: 'Member' - belongs_to :requester, class_name: 'Member' - belongs_to :parent, class_name: 'Crop' + belongs_to :requester, class_name: 'Member', optional: true + belongs_to :parent, class_name: 'Crop', optional: true has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id' has_and_belongs_to_many :posts # rubocop:disable Rails/HasAndBelongsToMany diff --git a/app/models/harvest.rb b/app/models/harvest.rb index a5328ef49..a58eaa991 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -35,7 +35,7 @@ class Harvest < ApplicationRecord belongs_to :crop belongs_to :owner, class_name: 'Member', counter_cache: true belongs_to :plant_part - belongs_to :planting + belongs_to :planting, optional: true ## ## Scopes diff --git a/app/models/post.rb b/app/models/post.rb index ae27dbb50..2dc254741 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -6,7 +6,7 @@ class Post < ApplicationRecord # # Relationships belongs_to :author, class_name: 'Member' - belongs_to :forum + belongs_to :forum, optional: true has_many :comments, dependent: :destroy has_and_belongs_to_many :crops # rubocop:disable Rails/HasAndBelongsToMany # also has_many notifications, but kinda meaningless to get at them From 79f6f7097aace417ed1bd0cf1716b9f0a6f57df6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 4 Jan 2018 15:01:09 +1300 Subject: [PATCH 034/267] updated npm package.json --- package-lock.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 013886a6b..7ed4e60ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -149,7 +149,7 @@ "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", "dev": true }, "cli": { @@ -212,7 +212,7 @@ "coffeescript": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.0.3.tgz", - "integrity": "sha512-iIfUN+71IyI2FQABXh1luzZeQgqwUPeWh6lDovJatQQs+30bvyGnBY0r4BnD0hoMAasNuZVHlL1U09Oy1ZfSeg==", + "integrity": "sha1-dg8Cck9fCRG+fO+jSo4OEMXYUSo=", "dev": true }, "concat-map": { @@ -519,7 +519,7 @@ "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", "dev": true }, "esquery": { @@ -852,7 +852,7 @@ "js-yaml": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", "dev": true, "requires": { "argparse": "1.0.9", @@ -1113,7 +1113,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -1191,7 +1191,7 @@ "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "dev": true, "requires": { "glob": "7.1.2" @@ -1215,7 +1215,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", "dev": true }, "shelljs": { @@ -1255,7 +1255,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { "safe-buffer": "5.1.1" From 53c9f89bc1b81ab99a3562e1185c7dfa1b9530fc Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 4 Jan 2018 15:11:36 +1300 Subject: [PATCH 035/267] Fixed up tabulation --- app/assets/javascripts/graphs/width_scale.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/graphs/width_scale.js b/app/assets/javascripts/graphs/width_scale.js index 4ba275eda..7f2b9dda2 100644 --- a/app/assets/javascripts/graphs/width_scale.js +++ b/app/assets/javascripts/graphs/width_scale.js @@ -29,8 +29,8 @@ WidthScale.prototype.getMaxValue = function() { return d3.max(this._data.bars.map(function(bar) { - return bar.value; -})); + return bar.value; + })); }; growstuff.WidthScale = WidthScale; From 46cfe527bc56ca0074ceafb2224c471c9a609541 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 4 Jan 2018 16:38:09 +1300 Subject: [PATCH 036/267] add in gem 'rails-controller-testing' --- Gemfile | 1 + Gemfile.lock | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/Gemfile b/Gemfile index eb461c054..32158db8f 100644 --- a/Gemfile +++ b/Gemfile @@ -150,6 +150,7 @@ end group :test do gem 'codeclimate-test-reporter', require: false + gem 'rails-controller-testing' gem 'timecop' end diff --git a/Gemfile.lock b/Gemfile.lock index bdd2bc94e..28e049445 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -344,6 +344,10 @@ GEM rails-assets-leaflet (1.2.0) rails-assets-leaflet.markercluster (1.2.0) rails-assets-leaflet (>= 1.0.3) + rails-controller-testing (1.0.2) + actionpack (~> 5.x, >= 5.0.1) + actionview (~> 5.x, >= 5.0.1) + activesupport (~> 5.x) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) @@ -542,6 +546,7 @@ DEPENDENCIES poltergeist rails (= 5.1.4) rails-assets-leaflet.markercluster! + rails-controller-testing rails_12factor rainbow (< 2.2.0) rake (>= 10.0.0) From 2f9610a60fd2c2cfefb4c0d856f9687f48a30891 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 4 Jan 2018 17:23:10 +1300 Subject: [PATCH 037/267] Http positional arguments in rails 5 --- .rubocop.yml | 4 -- .../admin/orders_controller_spec.rb | 4 +- spec/controllers/admin_controller_spec.rb | 15 +++-- spec/controllers/comments_controller_spec.rb | 10 ++-- spec/controllers/gardens_controller_spec.rb | 14 ++--- spec/controllers/harvests_controller_spec.rb | 44 +++++++------- spec/controllers/likes_controller_spec.rb | 4 +- spec/controllers/member_controller_spec.rb | 16 ++--- .../notifications_controller_spec.rb | 14 ++--- .../order_items_controller_spec.rb | 16 +++-- spec/controllers/orders_controller_spec.rb | 8 +-- .../photo_associations_controller_spec.rb | 6 +- spec/controllers/photos_controller_spec.rb | 58 ++++++++++++------- spec/controllers/places_controller_spec.rb | 6 +- spec/controllers/plantings_controller_spec.rb | 20 +++---- spec/controllers/posts_controller_spec.rb | 14 ++--- spec/controllers/roles_controller_spec.rb | 2 +- .../scientific_names_controller_spec.rb | 8 +-- spec/controllers/seeds_controller_spec.rb | 8 +-- spec/controllers/shop_controller_spec.rb | 4 +- 20 files changed, 145 insertions(+), 130 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 545e1c1fa..571a090bd 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -39,10 +39,6 @@ Layout/AlignParameters: Metrics/LineLength: Max: 120 -# turn these back on in Rails 5 -Rails/HttpPositionalArguments: # See https://github.com/bbatsov/rubocop/issues/3629 - Enabled: false - Style/Documentation: Enabled: false diff --git a/spec/controllers/admin/orders_controller_spec.rb b/spec/controllers/admin/orders_controller_spec.rb index fb475b34c..207112f39 100644 --- a/spec/controllers/admin/orders_controller_spec.rb +++ b/spec/controllers/admin/orders_controller_spec.rb @@ -6,12 +6,12 @@ describe Admin::OrdersController do describe "GET search" do it "assigns @orders" do order = FactoryBot.create(:order) - get :search, search_by: 'order_id', search_text: order.id + get :search, params: { search_by: 'order_id', search_text: order.id } assigns(:orders).should eq([order]) end it "sets an error message if nothing found" do - get :search, search_by: 'order_id', search_text: 'foo' + get :search, params: { search_by: 'order_id', search_text: 'foo' } flash[:alert].should have_text "Couldn't find order with" end end diff --git a/spec/controllers/admin_controller_spec.rb b/spec/controllers/admin_controller_spec.rb index 9f134bbab..5aa87e7cb 100644 --- a/spec/controllers/admin_controller_spec.rb +++ b/spec/controllers/admin_controller_spec.rb @@ -4,16 +4,15 @@ describe AdminController do login_member(:admin_member) describe "GET admin/newsletter" do - it 'fetches the admin newsletter page' do - get :newsletter - response.should be_success - response.should render_template("admin/newsletter") + before { get :newsletter } + describe 'fetches the admin newsletter page' do + it { expect(response).to be_success } + it { expect(response).to render_template("admin/newsletter") } end - it 'assigns @members' do - m = FactoryBot.create(:newsletter_recipient_member) - get :newsletter - assigns(:members).should eq [m] + describe 'assigns @members' do + let!(:m) { FactoryBot.create(:newsletter_recipient_member) } + it { expect(assigns(:members)).to eq [m] } end end end diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb index 0e986cc93..6b2383b36 100644 --- a/spec/controllers/comments_controller_spec.rb +++ b/spec/controllers/comments_controller_spec.rb @@ -29,7 +29,7 @@ describe CommentsController do let(:post) { FactoryBot.create(:post) } describe "with valid params" do - before { get :new, post_id: post.id } + before { get :new, params: { post_id: post.id } } it "picks up post from params" do assigns(:post).should eq(post) @@ -49,7 +49,7 @@ describe CommentsController do describe "GET edit" do let(:post) { FactoryBot.create(:post) } - before { get :edit, id: comment.to_param } + before { get :edit, params: { id: comment.to_param } } describe "my comment" do let!(:comment) { FactoryBot.create :comment, author: member, post: post } @@ -66,7 +66,7 @@ describe CommentsController do end describe "PUT update" do - before { put :update, id: comment.to_param, comment: valid_attributes } + before { put :update, params: { id: comment.to_param, comment: valid_attributes } } describe "my comment" do let(:comment) { FactoryBot.create :comment, author: member } @@ -74,10 +74,12 @@ describe CommentsController do expect(response).to redirect_to(comment.post) end end + describe "not my comment" do let(:comment) { FactoryBot.create :comment } it { expect(response).not_to be_success } end + describe "attempting to change post_id" do let(:post) { FactoryBot.create :post, subject: 'our post' } let(:other_post) { FactoryBot.create :post, subject: 'the other post' } @@ -91,7 +93,7 @@ describe CommentsController do end describe "DELETE destroy" do - before { delete :destroy, id: comment.to_param } + before { delete :destroy, params: { id: comment.to_param } } describe "my comment" do let(:comment) { FactoryBot.create :comment, author: member } diff --git a/spec/controllers/gardens_controller_spec.rb b/spec/controllers/gardens_controller_spec.rb index b0ccae0b8..f661a7299 100644 --- a/spec/controllers/gardens_controller_spec.rb +++ b/spec/controllers/gardens_controller_spec.rb @@ -7,7 +7,7 @@ RSpec.describe GardensController, type: :controller do context "when not signed in" do let(:garden) { double('garden') } describe 'GET new' do - before { get :new, id: garden.to_param } + before { get :new, params: { id: garden.to_param } } it { expect(response).to redirect_to(new_member_session_path) } end describe 'PUT create' do @@ -25,15 +25,15 @@ RSpec.describe GardensController, type: :controller do expect(garden).not_to receive(:destroy) end describe 'GET edit' do - before { get :edit, id: garden.to_param } + before { get :edit, params: { id: garden.to_param } } it { expect(response).to redirect_to(new_member_session_path) } end describe 'POST update' do - before { post :update, id: garden.to_param, garden: valid_params } + before { post :update, params: { id: garden.to_param, garden: valid_params } } it { expect(response).to redirect_to(new_member_session_path) } end describe 'DELETE' do - before { delete :destroy, id: garden.to_param, params: { garden: valid_params } } + before { delete :destroy, params: { id: garden.to_param, params: { garden: valid_params } } } it { expect(response).to redirect_to(new_member_session_path) } end end @@ -55,15 +55,15 @@ RSpec.describe GardensController, type: :controller do end describe 'GET edit' do - before { get :edit, id: not_my_garden.to_param } + before { get :edit, params: { id: not_my_garden.to_param } } it { expect(response).to redirect_to(root_path) } end describe 'POST update' do - before { post :update, id: not_my_garden.to_param, garden: valid_params } + before { post :update, params: { id: not_my_garden.to_param, garden: valid_params } } it { expect(response).to redirect_to(root_path) } end describe 'DELETE' do - before { delete :destroy, id: not_my_garden.to_param, params: { garden: valid_params } } + before { delete :destroy, params: { id: not_my_garden.to_param, params: { garden: valid_params } } } it { expect(response).to redirect_to(root_path) } end end diff --git a/spec/controllers/harvests_controller_spec.rb b/spec/controllers/harvests_controller_spec.rb index 8a2edb56b..fca0bb840 100644 --- a/spec/controllers/harvests_controller_spec.rb +++ b/spec/controllers/harvests_controller_spec.rb @@ -21,18 +21,18 @@ describe HarvestsController do let(:harvest2) { FactoryBot.create(:harvest, owner_id: member2.id, crop_id: maize.id) } describe "assigns all harvests as @harvests" do - before { get :index, {} } + before { get :index, params: {} } it { assigns(:harvests).should =~ [harvest1, harvest2] } end describe "picks up owner from params and shows owner's harvests only" do - before { get :index, owner: member1.slug } + before { get :index, params: { owner: member1.slug } } it { expect(assigns(:owner)).to eq member1 } it { expect(assigns(:harvests)).to eq [harvest1] } end describe "picks up crop from params and shows the harvests for the crop only" do - before { get :index, crop: maize.name } + before { get :index, params: { crop: maize.name } } it { expect(assigns(:crop)).to eq maize } it { expect(assigns(:harvests)).to eq [harvest2] } end @@ -46,13 +46,13 @@ describe HarvestsController do describe "GET show" do let(:harvest) { Harvest.create! valid_attributes } describe "assigns the requested harvest as @harvest" do - before { get :show, id: harvest.to_param } + before { get :show, params: { id: harvest.to_param } } it { expect(assigns(:harvest)).to eq(harvest) } end end describe "GET new" do - before { get :new, {} } + before { get :new, params: {} } describe "assigns a new harvest as @harvest" do it { expect(assigns(:harvest)).to be_a_new(Harvest) } @@ -66,7 +66,7 @@ describe HarvestsController do describe "GET edit" do let(:harvest) { Harvest.create! valid_attributes } describe "assigns the requested harvest as @harvest" do - before { get :edit, id: harvest.to_param } + before { get :edit, params: { id: harvest.to_param } } it { expect(assigns(:harvest)).to eq(harvest) } end end @@ -75,24 +75,24 @@ describe HarvestsController do describe "with valid params" do it "creates a new Harvest" do expect do - post :create, harvest: valid_attributes + post :create, params: { harvest: valid_attributes } end.to change(Harvest, :count).by(1) end it "assigns a newly created harvest as @harvest" do - post :create, harvest: valid_attributes + post :create, params: { harvest: valid_attributes } assigns(:harvest).should be_a(Harvest) assigns(:harvest).should be_persisted end it "redirects to the created harvest" do - post :create, harvest: valid_attributes + post :create, params: { harvest: valid_attributes } response.should redirect_to(Harvest.last) end describe "links to planting" do let(:planting) { FactoryBot.create(:planting, owner_id: member.id, garden: member.gardens.first) } - before { post :create, harvest: valid_attributes.merge(planting_id: planting.id) } + before { post :create, params: { harvest: valid_attributes.merge(planting_id: planting.id) } } it { expect(Harvest.last.planting.id).to eq(planting.id) } end end @@ -101,13 +101,13 @@ describe HarvestsController do it "assigns a newly created but unsaved harvest as @harvest" do # Trigger the behavior that occurs when invalid params are submitted Harvest.any_instance.stub(:save).and_return(false) - post :create, harvest: { "crop_id" => "invalid value" } + post :create, params: { harvest: { "crop_id" => "invalid value" } } assigns(:harvest).should be_a_new(Harvest) end it "re-renders the 'new' template" do # Trigger the behavior that occurs when invalid params are submitted - post :create, harvest: { "crop_id" => "invalid value" } + post :create, params: { harvest: { "crop_id" => "invalid value" } } response.should render_template("new") end end @@ -119,7 +119,7 @@ describe HarvestsController do describe "does not save planting_id" do before do allow(Harvest).to receive(:new).and_return(harvest) - post :create, harvest: valid_attributes.merge(planting_id: not_my_planting.id) + post :create, params: { harvest: valid_attributes.merge(planting_id: not_my_planting.id) } end it { expect(harvest.planting_id).not_to eq(not_my_planting.id) } end @@ -135,18 +135,18 @@ describe HarvestsController do # receives the :update message with whatever params are # submitted in the request. Harvest.any_instance.should_receive(:update).with("crop_id" => "1", "owner_id": member.id) - put :update, id: harvest.to_param, harvest: { "crop_id" => "1" } + put :update, params: { id: harvest.to_param, harvest: { "crop_id" => "1" } } end it "assigns the requested harvest as @harvest" do harvest = Harvest.create! valid_attributes - put :update, id: harvest.to_param, harvest: valid_attributes + put :update, params: { id: harvest.to_param, harvest: valid_attributes } assigns(:harvest).should eq(harvest) end it "redirects to the harvest" do harvest = Harvest.create! valid_attributes - put :update, id: harvest.to_param, harvest: valid_attributes + put :update, params: { id: harvest.to_param, harvest: valid_attributes } response.should redirect_to(harvest) end end @@ -156,13 +156,13 @@ describe HarvestsController do harvest = Harvest.create! valid_attributes # Trigger the behavior that occurs when invalid params are submitted Harvest.any_instance.stub(:save).and_return(false) - put :update, id: harvest.to_param, harvest: { "crop_id" => "invalid value" } + put :update, params: { id: harvest.to_param, harvest: { "crop_id" => "invalid value" } } assigns(:harvest).should eq(harvest) end it "re-renders the 'edit' template" do harvest = Harvest.create! valid_attributes - put :update, id: harvest.to_param, harvest: { "crop_id" => "invalid value" } + put :update, params: { id: harvest.to_param, harvest: { "crop_id" => "invalid value" } } response.should render_template("edit") end end @@ -172,8 +172,8 @@ describe HarvestsController do let(:harvest) { FactoryBot.create(:harvest) } describe "does not save planting_id" do before do - put :update, id: harvest.to_param, - harvest: valid_attributes.merge(planting_id: not_my_planting.id) + put :update, params: { id: harvest.to_param, + harvest: valid_attributes.merge(planting_id: not_my_planting.id) } end it { expect(harvest.planting_id).to eq(nil) } end @@ -184,13 +184,13 @@ describe HarvestsController do it "destroys the requested harvest" do harvest = Harvest.create! valid_attributes expect do - delete :destroy, id: harvest.to_param + delete :destroy, params: { id: harvest.to_param } end.to change(Harvest, :count).by(-1) end it "redirects to the harvests list" do harvest = Harvest.create! valid_attributes - delete :destroy, id: harvest.to_param + delete :destroy, params: { id: harvest.to_param } response.should redirect_to(harvests_url) end end diff --git a/spec/controllers/likes_controller_spec.rb b/spec/controllers/likes_controller_spec.rb index 6f43760c1..59e0ddd89 100644 --- a/spec/controllers/likes_controller_spec.rb +++ b/spec/controllers/likes_controller_spec.rb @@ -10,7 +10,7 @@ describe LikesController do describe "POST create" do it { expect(response.content_type).to eq "application/json" } - before { post :create, post_id: blogpost.id, format: :json } + before { post :create, params: { post_id: blogpost.id, format: :json } } it { expect(Like.last.likeable_id).to eq(blogpost.id) } it { expect(Like.last.likeable_type).to eq('Post') } it { JSON.parse(response.body)["description"] == "1 like" } @@ -25,7 +25,7 @@ describe LikesController do end describe "DELETE destroy" do - before { delete :destroy, id: like.id, format: :json } + before { delete :destroy, params: { id: like.id, format: :json } } it { expect(response.content_type).to eq "application/json" } describe "un-liking something i liked before" do diff --git a/spec/controllers/member_controller_spec.rb b/spec/controllers/member_controller_spec.rb index b04bcd799..dada0b013 100644 --- a/spec/controllers/member_controller_spec.rb +++ b/spec/controllers/member_controller_spec.rb @@ -10,7 +10,7 @@ describe MembersController do describe "GET index" do it "assigns only confirmed members as @members" do - get :index, {} + get :index, params: {} assigns(:members).should eq([@member]) end end @@ -24,38 +24,38 @@ describe MembersController do describe "GET show" do it "provides JSON for member profile" do - get :show, id: @member.id, format: 'json' + get :show, params: { id: @member.id }, format: 'json' response.should be_success end it "assigns @posts with the member's posts" do - get :show, id: @member.id + get :show, params: { id: @member.id } assigns(:posts).should eq(@posts) end it "assigns @twitter_auth" do - get :show, id: @member.id + get :show, params: { id: @member.id } assigns(:twitter_auth).should eq(@twitter_auth) end it "assigns @flickr_auth" do - get :show, id: @member.id + get :show, params: { id: @member.id } assigns(:flickr_auth).should eq(@flickr_auth) end it "doesn't show completely nonsense members" do - lambda { get :show, id: 9999 }.should raise_error(ActiveRecord::RecordNotFound) + lambda { get :show, params: { id: 9999 } }.should raise_error(ActiveRecord::RecordNotFound) end it "doesn't show unconfirmed members" do @member2 = FactoryBot.create(:unconfirmed_member) - lambda { get :show, id: @member2.id }.should raise_error(ActiveRecord::RecordNotFound) + lambda { get :show, params: { id: @member2.id } }.should raise_error(ActiveRecord::RecordNotFound) end end describe "GET member's RSS feed" do it "returns an RSS feed" do - get :show, id: @member.to_param, format: "rss" + get :show, params: { id: @member.to_param }, format: "rss" response.should be_success response.should render_template("members/show") response.content_type.should eq("application/rss+xml") diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb index fd6f40aa1..a7ed81ae5 100644 --- a/spec/controllers/notifications_controller_spec.rb +++ b/spec/controllers/notifications_controller_spec.rb @@ -31,7 +31,7 @@ describe NotificationsController do describe "GET index" do it "assigns all notifications as @notifications" do notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :index, {} + get :index, params: {} assigns(:notifications).should eq([notification]) end end @@ -39,14 +39,14 @@ describe NotificationsController do describe "GET show" do it "assigns the requested notification as @notification" do notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :show, id: notification.to_param + get :show, params: { id: notification.to_param } assigns(:notification).should eq(notification) end it "assigns the reply link for a post comment" do notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :show, id: notification.to_param + get :show, params: { id: notification.to_param } assigns(:reply_link).should_not be_nil assigns(:reply_link).should eq new_comment_url( post_id: notification.post.id @@ -55,7 +55,7 @@ describe NotificationsController do it "marks notifications as read" do notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :show, id: notification.to_param + get :show, params: { id: notification.to_param } # we need to fetch it from the db again, can't test against the old one n = Notification.find(notification.id) n.read.should eq true @@ -65,7 +65,7 @@ describe NotificationsController do describe "GET reply" do it "marks notifications as read" do notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id) - get :reply, id: notification.to_param + get :reply, params: { id: notification.to_param } # we need to fetch it from the db again, can't test against the old one n = Notification.find(notification.id) n.read.should eq true @@ -75,7 +75,7 @@ describe NotificationsController do describe "GET new" do it "assigns a recipient" do @recipient = FactoryBot.create(:member) - get :new, recipient_id: @recipient.id + get :new, params: { recipient_id: @recipient.id } assigns(:recipient).should be_an_instance_of(Member) end end @@ -84,7 +84,7 @@ describe NotificationsController do describe "with valid params" do it "redirects to the recipient's profile" do @recipient = FactoryBot.create(:member) - post :create, notification: { recipient_id: @recipient.id, subject: 'foo' } + post :create, params: { notification: { recipient_id: @recipient.id, subject: 'foo' } } response.should redirect_to(notifications_path) end end diff --git a/spec/controllers/order_items_controller_spec.rb b/spec/controllers/order_items_controller_spec.rb index 4de8eb98d..9064a0f2a 100644 --- a/spec/controllers/order_items_controller_spec.rb +++ b/spec/controllers/order_items_controller_spec.rb @@ -19,7 +19,9 @@ describe OrderItemsController do describe "POST create" do describe "redirects to order" do before do - post :create, order_item: { order_id: order.id, product_id: product.id, price: product.min_price } + post :create, params: { + order_item: { order_id: order.id, product_id: product.id, price: product.min_price } + } end it { expect(response).to redirect_to(OrderItem.last.order) } it { expect(OrderItem.last.order).to be_an_instance_of Order } @@ -28,9 +30,11 @@ describe OrderItemsController do describe 'creates an order for you' do it do expect do - post :create, order_item: { - product_id: product.id, - price: product.min_price + post :create, params: { + order_item: { + product_id: product.id, + price: product.min_price + } } end.to change(Order, :count).by(1) end @@ -41,7 +45,9 @@ describe OrderItemsController do order = FactoryBot.create(:order, member: member) product = FactoryBot.create(:product, min_price: 1) expect do - post :create, order_item: { order_id: order.id, product_id: product.id, price: 3.33 } + post :create, params: { + order_item: { order_id: order.id, product_id: product.id, price: 3.33 } + } end.to change(OrderItem, :count).by(1) OrderItem.last.price.should eq 333 end diff --git a/spec/controllers/orders_controller_spec.rb b/spec/controllers/orders_controller_spec.rb index 3c6631d8c..a36365aad 100644 --- a/spec/controllers/orders_controller_spec.rb +++ b/spec/controllers/orders_controller_spec.rb @@ -16,7 +16,7 @@ describe OrdersController do member = FactoryBot.create(:member) sign_in member order = Order.create!(member_id: member.id) - get :checkout, id: order.to_param, referral_code: 'FOOBAR' + get :checkout, params: { id: order.to_param, referral_code: 'FOOBAR' } order.reload order.referral_code.should eq 'FOOBAR' end @@ -25,7 +25,7 @@ describe OrdersController do member = FactoryBot.create(:member) sign_in member order = Order.create!(member_id: member.id) - get :checkout, id: order.to_param + get :checkout, params: { id: order.to_param } response.status.should eq 302 response.redirect_url.should match(/paypal\.com/) end @@ -36,7 +36,7 @@ describe OrdersController do member = FactoryBot.create(:member) sign_in member order = Order.create!(member_id: member.id) - get :complete, id: order.to_param + get :complete, params: { id: order.to_param } assigns(:order).should eq(order) end end @@ -46,7 +46,7 @@ describe OrdersController do member = FactoryBot.create(:member) sign_in member order = Order.create!(member_id: member.id) - delete :destroy, id: order.id + delete :destroy, params: { id: order.id } response.should redirect_to(shop_url) end end diff --git a/spec/controllers/photo_associations_controller_spec.rb b/spec/controllers/photo_associations_controller_spec.rb index 42e0ccc37..65a0dd37d 100644 --- a/spec/controllers/photo_associations_controller_spec.rb +++ b/spec/controllers/photo_associations_controller_spec.rb @@ -19,7 +19,7 @@ describe PhotoAssociationsController do let(:photo) { FactoryBot.create :photo, owner: member } it "removes link" do - expect { delete :destroy, valid_params }.to change { photo.harvests.count }.by(-1) + expect { delete :destroy, params: valid_params }.to change { photo.harvests.count }.by(-1) end end @@ -29,13 +29,13 @@ describe PhotoAssociationsController do it do expect do begin - delete :destroy, valid_params + delete :destroy, params: valid_params rescue nil end end.not_to change(photo.harvests, :count) end - it { expect { delete :destroy, valid_params }.to raise_error(ActiveRecord::RecordNotFound) } + it { expect { delete :destroy, params: valid_params }.to raise_error(ActiveRecord::RecordNotFound) } end end end diff --git a/spec/controllers/photos_controller_spec.rb b/spec/controllers/photos_controller_spec.rb index 3c4f9dacb..b001141ab 100644 --- a/spec/controllers/photos_controller_spec.rb +++ b/spec/controllers/photos_controller_spec.rb @@ -38,7 +38,7 @@ describe PhotosController do end describe "planting photos" do - before(:each) { get :new, type: "planting", id: planting.id } + before(:each) { get :new, params: { type: "planting", id: planting.id } } it { assigns(:flickr_auth).should be_an_instance_of(Authentication) } it { assigns(:item).should eq planting } it { expect(flash[:alert]).not_to be_present } @@ -46,7 +46,7 @@ describe PhotosController do end describe "harvest photos" do - before { get :new, type: "harvest", id: harvest.id } + before { get :new, params: { type: "harvest", id: harvest.id } } it { assigns(:item).should eq harvest } it { expect(flash[:alert]).not_to be_present } end @@ -76,15 +76,22 @@ describe PhotosController do describe "with valid params" do before { controller.stub(:current_member) { member } } it "attaches the photo to a planting" do - post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "planting", id: planting.id + post :create, params: { + photo: { flickr_photo_id: photo.flickr_photo_id }, + type: "planting", id: planting.id + } expect(flash[:alert]).not_to be_present Photo.last.plantings.first.should eq planting end describe "doesn't attach a photo to a planting twice" do before do - post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "planting", id: planting.id - post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "planting", id: planting.id + post :create, params: { + photo: { flickr_photo_id: photo.flickr_photo_id }, type: "planting", id: planting.id + } + post :create, params: { + photo: { flickr_photo_id: photo.flickr_photo_id }, type: "planting", id: planting.id + } end it { expect(flash[:alert]).not_to be_present } it { expect(Photo.last.plantings.size).to eq 1 } @@ -97,8 +104,12 @@ describe PhotosController do end it "doesn't attach a photo to a harvest twice" do - post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: harvest.id - post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: harvest.id + post :create, params: { + photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: harvest.id + } + post :create, params: { + photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: harvest.id + } expect(flash[:alert]).not_to be_present Photo.last.harvests.size.should eq 1 end @@ -106,20 +117,19 @@ describe PhotosController do it "doesn't attach photo to a comment" do comment = FactoryBot.create(:comment) expect do - post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "comment", id: comment.id + post :create, params: { + photo: { flickr_photo_id: photo.flickr_photo_id }, type: "comment", id: comment.id + } end.to raise_error end end describe "for the second time" do let(:planting) { FactoryBot.create :planting, owner: member } + let(:valid_params) { { photo: { flickr_photo_id: 1 }, id: planting.id, type: 'planting' } } it "does not add a photo twice" do - expect do - post :create, photo: { flickr_photo_id: 1 }, id: planting.id, type: 'planting' - end.to change(Photo, :count).by(1) - expect do - post :create, photo: { flickr_photo_id: 1 }, id: planting.id, type: 'planting' - end.to change(Photo, :count).by(0) + expect { post :create, params: valid_params }.to change(Photo, :count).by(1) + expect { post :create, params: valid_params }.not_to change(Photo, :count) end end @@ -128,15 +138,15 @@ describe PhotosController do it "creates the planting/photo link" do planting = FactoryBot.create(:planting, garden: garden, owner: member) photo = FactoryBot.create(:photo, owner: member) - post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "planting", id: planting.id + post :create, params: { photo: { flickr_photo_id: photo.flickr_photo_id }, type: "planting", id: planting.id } expect(flash[:alert]).not_to be_present - Photo.last.plantings.first.should eq planting + expect(Photo.last.plantings.first).to eq planting end - it "creates the harvest/photo link" do - post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: harvest.id - expect(flash[:alert]).not_to be_present - Photo.last.harvests.first.should eq harvest + describe "creates the harvest/photo link" do + before { post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: harvest.id } + it { expect(flash[:alert]).not_to be_present } + it { expect(Photo.last.harvests.first).to eq harvest } end end @@ -146,7 +156,9 @@ describe PhotosController do # members will be auto-created, and different another_planting = FactoryBot.create(:planting) expect do - post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "planting", id: another_planting.id + post :create, params: { + photo: { flickr_photo_id: photo.flickr_photo_id }, type: "planting", id: another_planting.id + } end.to raise_error(ActiveRecord::RecordNotFound) Photo.last.plantings.first.should_not eq another_planting end @@ -155,7 +167,9 @@ describe PhotosController do # members will be auto-created, and different another_harvest = FactoryBot.create(:harvest) expect do - post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: another_harvest.id + post :create, params: { + photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: another_harvest.id + } end.to raise_error(ActiveRecord::RecordNotFound) Photo.last.harvests.first.should_not eq another_harvest end diff --git a/spec/controllers/places_controller_spec.rb b/spec/controllers/places_controller_spec.rb index 8b6cb0a31..d235b98c9 100644 --- a/spec/controllers/places_controller_spec.rb +++ b/spec/controllers/places_controller_spec.rb @@ -12,19 +12,19 @@ describe PlacesController do end it "assigns place name" do - get :show, place: @member_london.location + get :show, params: { place: @member_london.location } assigns(:place).should eq @member_london.location end it "assigns nearby members" do - get :show, place: @member_london.location + get :show, params: { place: @member_london.location } assigns(:nearby_members).should eq [@member_london, @member_south_pole] end end describe "GET search" do it "redirects to the new place" do - get :search, new_place: "foo" + get :search, params: { new_place: "foo" } response.should redirect_to place_path("foo") end end diff --git a/spec/controllers/plantings_controller_spec.rb b/spec/controllers/plantings_controller_spec.rb index dd1340d44..c1e4cd72b 100644 --- a/spec/controllers/plantings_controller_spec.rb +++ b/spec/controllers/plantings_controller_spec.rb @@ -24,13 +24,13 @@ describe PlantingsController do end describe "picks up owner from params and shows owner's plantings only" do - before { get :index, owner: member1.slug } + before { get :index, params: { owner: member1.slug } } it { expect(assigns(:owner)).to eq member1 } it { expect(assigns(:plantings)).to eq [planting1] } end describe "picks up crop from params and shows the plantings for the crop only" do - before { get :index, crop: maize.name } + before { get :index, params: { crop: maize.name } } it { expect(assigns(:crop)).to eq maize } it { expect(assigns(:plantings)).to eq [planting2] } end @@ -39,44 +39,44 @@ describe PlantingsController do describe "GET new" do describe "picks up crop from params" do let(:crop) { FactoryBot.create(:crop) } - before { get :new, crop_id: crop.id } + before { get :new, params: { crop_id: crop.id } } it { expect(assigns(:crop)).to eq(crop) } end describe "doesn't die if no crop specified" do - before { get :new, {} } + before { get :new, params: {} } it { expect(assigns(:crop)).to be_a_new(Crop) } end describe "picks up member's garden from params" do let(:garden) { FactoryBot.create(:garden, owner: member) } - before { get :new, garden_id: garden.id } + before { get :new, params: { garden_id: garden.id } } it { expect(assigns(:garden)).to eq(garden) } end describe "Doesn't display another member's garden on planting form" do let(:another_member) { FactoryBot.create(:member) } # over-riding member from login_member() let(:garden) { FactoryBot.create(:garden, owner: another_member) } - before { get :new, garden_id: garden.id } + before { get :new, params: { garden_id: garden.id } } it { expect(assigns(:garden)).not_to eq(garden) } end describe "Doesn't display un-approved crops on planting form" do let(:crop) { FactoryBot.create(:crop, approval_status: 'pending') } let!(:garden) { FactoryBot.create(:garden, owner: member) } - before { get :new, crop_id: crop.id } + before { get :new, params: { crop_id: crop.id } } it { expect(assigns(:crop)).not_to eq(crop) } end describe "Doesn't display rejected crops on planting form" do let(:crop) { FactoryBot.create(:crop, approval_status: 'rejected', reason_for_rejection: 'nope') } let!(:garden) { FactoryBot.create(:garden, owner: member) } - before { get :new, crop_id: crop.id } + before { get :new, params: { crop_id: crop.id } } it { expect(assigns(:crop)).not_to eq(crop) } end describe "doesn't die if no garden specified" do - before { get :new, {} } + before { get :new, params: {} } it { expect(assigns(:garden)).to be_a_new(Garden) } end @@ -86,7 +86,7 @@ describe PlantingsController do end describe "sets the owner automatically" do - before { post :create, planting: valid_attributes } + before { post :create, params: { planting: valid_attributes } } it { expect(assigns(:planting).owner).to eq subject.current_member } end end diff --git a/spec/controllers/posts_controller_spec.rb b/spec/controllers/posts_controller_spec.rb index cbfe8b46c..2d7aba1ad 100644 --- a/spec/controllers/posts_controller_spec.rb +++ b/spec/controllers/posts_controller_spec.rb @@ -11,19 +11,19 @@ describe PostsController do describe "GET RSS feed" do it "returns an RSS feed" do get :index, format: "rss" - response.should be_success - response.should render_template("posts/index") - response.content_type.should eq("application/rss+xml") + expect(response).to be_success + expect(response).to render_template("posts/index") + expect(response).to.should eq("application/rss+xml") end end describe "GET RSS feed for individual post" do it "returns an RSS feed" do post = Post.create! valid_attributes - get :show, format: "rss", id: post.slug - response.should be_success - response.should render_template("posts/show") - response.content_type.should eq("application/rss+xml") + get :show, format: "rss", params: { id: post.slug } + expect(response).to be_success + expect(response).to render_template("posts/show") + expect(response).to.should eq("application/rss+xml") end end end diff --git a/spec/controllers/roles_controller_spec.rb b/spec/controllers/roles_controller_spec.rb index 9bf0ea1b5..17fe48dfe 100644 --- a/spec/controllers/roles_controller_spec.rb +++ b/spec/controllers/roles_controller_spec.rb @@ -10,7 +10,7 @@ describe RolesController do describe "GET index" do it "assigns all roles as @roles" do role = Role.create! valid_attributes - get :index, {} + get :index, params: {} # note that admin role exists because of login_admin_member assigns(:roles).should eq([Role.find_by(name: 'admin'), role]) end diff --git a/spec/controllers/scientific_names_controller_spec.rb b/spec/controllers/scientific_names_controller_spec.rb index 412f53224..a56735454 100644 --- a/spec/controllers/scientific_names_controller_spec.rb +++ b/spec/controllers/scientific_names_controller_spec.rb @@ -3,17 +3,15 @@ require 'rails_helper' describe ScientificNamesController do login_member(:crop_wrangling_member) - before(:each) do - @crop = FactoryBot.create(:tomato) - end + let!(:crop) { FactoryBot.create(:tomato) } def valid_attributes - { name: 'Solanum lycopersicum', crop_id: @crop.id } + { name: 'Solanum lycopersicum', crop_id: crop.id } end describe "GET new" do it "assigns crop if specified" do - get :new, crop_id: 1 + get :new, params: { crop_id: crop.id } assigns(:crop).should be_an_instance_of Crop end end diff --git a/spec/controllers/seeds_controller_spec.rb b/spec/controllers/seeds_controller_spec.rb index c2fd699eb..123516e43 100644 --- a/spec/controllers/seeds_controller_spec.rb +++ b/spec/controllers/seeds_controller_spec.rb @@ -2,10 +2,10 @@ require 'rails_helper' describe SeedsController do describe "GET index" do - it "picks up owner from params" do - owner = FactoryBot.create(:member) - get :index, owner: owner.slug - assigns(:owner).should eq(owner) + let(:owner) { FactoryBot.create(:member) } + describe "picks up owner from params" do + before { get :index, params: { owner: owner.slug } } + it { expect(assigns(:owner)).to eq(owner) } end end end diff --git a/spec/controllers/shop_controller_spec.rb b/spec/controllers/shop_controller_spec.rb index c25039d2d..c3fb1e3c0 100644 --- a/spec/controllers/shop_controller_spec.rb +++ b/spec/controllers/shop_controller_spec.rb @@ -6,7 +6,7 @@ describe ShopController do describe "GET index" do describe 'not logged in' do - before { get :index, {} } + before { get :index, params: {} } describe "assigns all products as @products ordered by name" do it { expect(assigns(:products)).to eq([product1, product2]) } @@ -26,7 +26,7 @@ describe ShopController do let!(:order) { FactoryBot.create(:order, member: member) } before do sign_in member - get :index, {} + get :index, params: {} end it { expect(assigns(:order)).to eq order } end From 2b69db77bf30e2dbfc37139a979a00a615bfc623 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Fri, 5 Jan 2018 21:33:21 +1300 Subject: [PATCH 038/267] Use faker gem for Member factorybot --- spec/factories/member.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/factories/member.rb b/spec/factories/member.rb index 619e7d4f2..c437ff1bb 100644 --- a/spec/factories/member.rb +++ b/spec/factories/member.rb @@ -3,9 +3,9 @@ FactoryBot.define do sequence(:login_name) { |n| "member#{n}" } factory :member, aliases: %i(author owner sender recipient creator) do - login_name { generate(:login_name) } + login_name { Faker::Name.unique.first_name } password 'password1' - email { generate(:email) } + email { Faker::Internet.unique.email } tos_agreement true confirmed_at Time.now show_email false From 4e5aa8077c94c66122a0a59719250a672f48b679 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Fri, 5 Jan 2018 21:34:11 +1300 Subject: [PATCH 039/267] Re-wrote harvests#update controller spec --- spec/controllers/harvests_controller_spec.rb | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/spec/controllers/harvests_controller_spec.rb b/spec/controllers/harvests_controller_spec.rb index fca0bb840..91f441443 100644 --- a/spec/controllers/harvests_controller_spec.rb +++ b/spec/controllers/harvests_controller_spec.rb @@ -129,13 +129,12 @@ describe HarvestsController do describe "PUT update" do describe "with valid params" do it "updates the requested harvest" do - harvest = Harvest.create! valid_attributes - # Assuming there are no other harvests in the database, this - # specifies that the Harvest created on the previous line - # receives the :update message with whatever params are - # submitted in the request. - Harvest.any_instance.should_receive(:update).with("crop_id" => "1", "owner_id": member.id) - put :update, params: { id: harvest.to_param, harvest: { "crop_id" => "1" } } + harvest = FactoryBot.create :harvest, valid_attributes + new_crop = FactoryBot.create :crop + expect do + put :update, params: { id: harvest.to_param, harvest: { crop_id: new_crop.id } } + harvest.reload + end.to change(harvest, :crop_id).to(new_crop.id) end it "assigns the requested harvest as @harvest" do From a0cc9c0a00424eb6c6a53c7725198cb2a8ad15a0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 08:41:34 +1300 Subject: [PATCH 040/267] fixed photo controller specs --- spec/controllers/photos_controller_spec.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/spec/controllers/photos_controller_spec.rb b/spec/controllers/photos_controller_spec.rb index b001141ab..1b2bb6fb1 100644 --- a/spec/controllers/photos_controller_spec.rb +++ b/spec/controllers/photos_controller_spec.rb @@ -52,8 +52,8 @@ describe PhotosController do end describe "garden photos" do - before { get :new, type: "garden", id: garden.id } - it { assigns(:item).should eq garden } + before { get :new, params: { type: "garden", id: garden.id } } + it { expect(assigns(:item)).to eq garden } it { expect(flash[:alert]).not_to be_present } end end @@ -98,7 +98,7 @@ describe PhotosController do end it "attaches the photo to a harvest" do - post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: harvest.id + post :create, params: { photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: harvest.id } expect(flash[:alert]).not_to be_present Photo.last.harvests.first.should eq harvest end @@ -144,7 +144,9 @@ describe PhotosController do end describe "creates the harvest/photo link" do - before { post :create, photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: harvest.id } + before do + post :create, params: { photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: harvest.id } + end it { expect(flash[:alert]).not_to be_present } it { expect(Photo.last.harvests.first).to eq harvest } end From 462654f26e5846b3b7dd75fccdd1d86314a3a0b1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 08:51:11 +1300 Subject: [PATCH 041/267] Fixed gardens controller specs --- spec/controllers/gardens_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/gardens_controller_spec.rb b/spec/controllers/gardens_controller_spec.rb index f661a7299..bdbc754ed 100644 --- a/spec/controllers/gardens_controller_spec.rb +++ b/spec/controllers/gardens_controller_spec.rb @@ -11,7 +11,7 @@ RSpec.describe GardensController, type: :controller do it { expect(response).to redirect_to(new_member_session_path) } end describe 'PUT create' do - before { put :create, garden: valid_params } + before { put :create, params: { garden: valid_params } } it { expect(response).to redirect_to(new_member_session_path) } end From a2190dc9847f1984c6ff478b677f8a6bba78e897 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 08:54:44 +1300 Subject: [PATCH 042/267] Fixed a matcher in posts controller spec --- spec/controllers/posts_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/posts_controller_spec.rb b/spec/controllers/posts_controller_spec.rb index 2d7aba1ad..2dde4f8ae 100644 --- a/spec/controllers/posts_controller_spec.rb +++ b/spec/controllers/posts_controller_spec.rb @@ -13,7 +13,7 @@ describe PostsController do get :index, format: "rss" expect(response).to be_success expect(response).to render_template("posts/index") - expect(response).to.should eq("application/rss+xml") + expect(response.content_type).to eq("application/rss+xml") end end @@ -23,7 +23,7 @@ describe PostsController do get :show, format: "rss", params: { id: post.slug } expect(response).to be_success expect(response).to render_template("posts/show") - expect(response).to.should eq("application/rss+xml") + expect(response.content_type).to eq("application/rss+xml") end end end From 62fd16e6b222f7a068fae5c7c536bbad2463dbbd Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 09:01:18 +1300 Subject: [PATCH 043/267] Notifications don't have a post if they are a message --- app/models/notification.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/notification.rb b/app/models/notification.rb index fe3ec8907..c9f915420 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -1,7 +1,7 @@ class Notification < ApplicationRecord belongs_to :sender, class_name: 'Member' belongs_to :recipient, class_name: 'Member' - belongs_to :post + belongs_to :post, optional: true validates :subject, length: { maximum: 255 } From 19382a8a36b4164cfb9149c535dcdad46a78a75a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 09:23:34 +1300 Subject: [PATCH 044/267] Random login name generator was running out of names So here's a name plus a random number instead It might collide sometimes alas --- spec/factories/member.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/factories/member.rb b/spec/factories/member.rb index c437ff1bb..1e986d9b2 100644 --- a/spec/factories/member.rb +++ b/spec/factories/member.rb @@ -3,7 +3,7 @@ FactoryBot.define do sequence(:login_name) { |n| "member#{n}" } factory :member, aliases: %i(author owner sender recipient creator) do - login_name { Faker::Name.unique.first_name } + login_name { "#{Faker::Name.first_name}_#{rand(1..1000)}" } password 'password1' email { Faker::Internet.unique.email } tos_agreement true From a0fe19651edadfbba67b8136cf9e53e2cec9ce39 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 09:31:39 +1300 Subject: [PATCH 045/267] Plant parts model using distinct query --- app/models/plant_part.rb | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/app/models/plant_part.rb b/app/models/plant_part.rb index 2590fb966..bbdbae8d2 100644 --- a/app/models/plant_part.rb +++ b/app/models/plant_part.rb @@ -3,21 +3,9 @@ class PlantPart < ApplicationRecord friendly_id :name, use: %i(slugged finders) has_many :harvests - has_many :crops, -> { uniq }, through: :harvests + has_many :crops, -> { distinct }, through: :harvests def to_s name end - - # Postgres complains if the ORDER BY clause of a SELECT DISTINCT query is - # not precisely one of the SELECTed fields. The default sort order on - # crops is lower(name), and Postgres is not smart enough to notice that it - # can calculate this from fields which are selected. The solution is to - # override PlantParts#crops to remove the ORDER BY clause, and replace it - # with `ORDER BY name`. This is not perfect, because it means the crops - # associated to plant parts will not be sorted in the same order as crops - # on the rest of the site. - def crops - super.reorder('name') - end end From fcbb57e6591f67c07a397eef3758fcc8fd112037 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 10:47:04 +1300 Subject: [PATCH 046/267] Respond with data on gardens#edit, so non-html formats don't break specs --- app/controllers/gardens_controller.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index ede5c2602..35efaf5d2 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -33,7 +33,9 @@ class GardensController < ApplicationController end # GET /gardens/1/edit - def edit; end + def edit + respond_with(@garden) + end # POST /gardens # POST /gardens.json From 7bb49f337f66a8c159822f651ec95eaf6a942c07 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 11:31:04 +1300 Subject: [PATCH 047/267] Fixing up member's account model creation, post rails 5 upgrade --- app/models/account.rb | 7 ++++--- app/models/member.rb | 19 +++++++++++++++---- spec/models/member_spec.rb | 32 +++++++++++++++----------------- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/app/models/account.rb b/app/models/account.rb index 79d5327b7..be5b1e9cf 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -6,9 +6,10 @@ class Account < ApplicationRecord message: 'already has account details associated with it' } - before_create do |account| - unless account.account_type - account.account_type = AccountType.find_or_create_by(name: + before_validation do + # If not account type, set to the free account + unless account_type + self.account_type = AccountType.find_or_create_by(name: Rails.application.config.default_account_type) end end diff --git a/app/models/member.rb b/app/models/member.rb index 654e6b3bd..b22561ed9 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -77,13 +77,16 @@ class Member < ApplicationRecord after_validation :geocode after_validation :empty_unwanted_geocodes after_save :update_newsletter_subscription + after_create :create_account_and_garden # Give each new member a default garden # and an account record (for paid accounts etc) # we use find_or_create to avoid accidentally creating a second one, # which can happen sometimes especially with FactoryBot associations - after_create { |member| Garden.create(name: "Garden", owner_id: member.id) } - after_create { |member| Account.find_or_create_by(member_id: member.id) } + def create_account_and_garden + Garden.create!(name: "Garden", owner_id: id) + Account.find_or_create_by!(member_id: id) + end # allow login via either login_name or email address def self.find_first_by_auth_conditions(warden_conditions) @@ -198,15 +201,23 @@ class Member < ApplicationRecord end def update_newsletter_subscription - return unless confirmed_at_changed? || newsletter_changed? + return unless will_save_change_to_attribute?(:confirmed) || will_save_change_to_attribute?(:newsletter) if newsletter - newsletter_subscribe if confirmed_at_changed? || confirmed_at && newsletter_changed? + newsletter_subscribe if confirmed_just_now? || requested_newsletter_just_now? elsif confirmed_at newsletter_unsubscribe end end + def confirmed_just_now? + will_save_change_to_attribute?(:confirmed_at) + end + + def requested_newsletter_just_now? + confirmed_at && will_save_change_to_attribute?(:newsletter) + end + def newsletter_subscribe(gb = Gibbon::API.new, testing = false) return true if Rails.env.test? && !testing gb.lists.subscribe( diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index c538ad38d..9cf80597b 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -2,53 +2,51 @@ require 'rails_helper' describe 'member' do context 'valid member' do - let(:member) { FactoryBot.create(:member) } + let!(:member) { FactoryBot.create(:member, login_name: 'hinemoa') } - it 'should be fetchable from the database' do - member2 = Member.find(member.id) - member2.should be_an_instance_of Member - member2.login_name.should match(/member\d+/) - member2.encrypted_password.should_not be_nil + describe 'should be fetchable from the database' do + subject { Member.find(member.id) } + it { is_expected.to be_an_instance_of Member } + it { expect(subject.encrypted_password).not_to be_nil } end - it 'should have a friendly slug' do - member.slug.should match(/member\d+/) + describe 'should have a friendly slug' do + it { expect(member.slug).to eq('hinemoa') } end it 'has a bio' do member.bio = 'I love seeds' - member.bio.should eq 'I love seeds' + expect(member.bio).to eq 'I love seeds' end it 'should have a default garden' do - member.gardens.size.should == 1 + expect(member.gardens.count).to eq 1 end it 'should have a accounts entry' do - member.account.should be_an_instance_of Account + expect(member.account).to be_an_instance_of Account end it "should have a default-type account by default" do member.account.account_type.name.should eq Rails.application.config.default_account_type - member.paid?.should be(false) + expect(member.paid?).to be_false end it "doesn't show email by default" do - member.show_email.should be(false) + expect(member.show_email).to be_false end it 'should stringify as the login_name' do - member.to_s.should match(/member\d+/) - member.to_s.should match(/member\d+/) + expect(member.to_s).to eq 'hinemoa' end it 'should be able to fetch posts' do post = FactoryBot.create(:post, author: member) - member.posts.should eq [post] + expect(member.posts).to eq [post] end it 'should be able to fetch gardens' do - member.gardens.first.name.should eq "Garden" + expect(member.gardens.first.name).to eq "Garden" end it 'has many plantings' do From e5beb066a049872873fe44e11f8c772790fdf8af Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 11:32:49 +1300 Subject: [PATCH 048/267] Moved members.create_account_and_garden to private --- app/models/member.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/models/member.rb b/app/models/member.rb index b22561ed9..7165faf4f 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -79,15 +79,6 @@ class Member < ApplicationRecord after_save :update_newsletter_subscription after_create :create_account_and_garden - # Give each new member a default garden - # and an account record (for paid accounts etc) - # we use find_or_create to avoid accidentally creating a second one, - # which can happen sometimes especially with FactoryBot associations - def create_account_and_garden - Garden.create!(name: "Garden", owner_id: id) - Account.find_or_create_by!(member_id: id) - end - # allow login via either login_name or email address def self.find_first_by_auth_conditions(warden_conditions) conditions = warden_conditions.dup @@ -241,4 +232,13 @@ class Member < ApplicationRecord def get_follow(member) follows.find_by(followed_id: member.id) if already_following?(member) end + + # Give each new member a default garden + # and an account record (for paid accounts etc) + # we use find_or_create to avoid accidentally creating a second one, + # which can happen sometimes especially with FactoryBot associations + def create_account_and_garden + Garden.create!(name: "Garden", owner_id: id) + Account.find_or_create_by!(member_id: id) + end end From 5eae80bc6d295b7f6e4ba4b98d61a2c1e3d47688 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 11:38:47 +1300 Subject: [PATCH 049/267] Specify login name in spec, so we know what to look for Becuase we're using the faker gem now --- spec/models/garden_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/models/garden_spec.rb b/spec/models/garden_spec.rb index f8e5a3311..3ee483c04 100644 --- a/spec/models/garden_spec.rb +++ b/spec/models/garden_spec.rb @@ -1,11 +1,11 @@ require 'rails_helper' describe Garden do - let(:owner) { FactoryBot.create(:member) } + let(:owner) { FactoryBot.create(:member, login_name: 'hatupatu') } let(:garden) { FactoryBot.create(:garden, owner: owner) } it "should have a slug" do - garden.slug.should match(/member\d+-springfield-community-garden/) + garden.slug.should match(/hatupatu-springfield-community-garden/) end it "should have a description" do From d642e7cf40bd9ab59ffdf800dd20bfe4aa2a67f6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 11:48:45 +1300 Subject: [PATCH 050/267] set login name on member so we know what to look for in slug spec --- spec/models/planting_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 48a035bb4..94fa1c291 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' describe Planting do let(:crop) { FactoryBot.create(:tomato) } - let(:garden_owner) { FactoryBot.create(:member) } + let(:garden_owner) { FactoryBot.create(:member, login_name: 'hatupatu') } let(:garden) { FactoryBot.create(:garden, owner: garden_owner) } let(:planting) { FactoryBot.create(:planting, crop: crop, garden: garden, owner: garden.owner) } let(:finished_planting) do @@ -156,7 +156,7 @@ describe Planting do end it "should have a slug" do - planting.slug.should match(/^member\d+-springfield-community-garden-tomato$/) + planting.slug.should match(/^hatupatu-springfield-community-garden-tomato$/) end it 'should sort in reverse creation order' do From 22fd422a6df68a168e839303b122584a339afc7d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 11:49:35 +1300 Subject: [PATCH 051/267] Look for eq false in member spec --- spec/models/member_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 9cf80597b..c0f7ac4f7 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -29,11 +29,11 @@ describe 'member' do it "should have a default-type account by default" do member.account.account_type.name.should eq Rails.application.config.default_account_type - expect(member.paid?).to be_false + expect(member.paid?).to eq false end it "doesn't show email by default" do - expect(member.show_email).to be_false + expect(member.show_email).to eq false end it 'should stringify as the login_name' do From dd980d3f4143909f16960b043946582ffe45bd02 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 12:06:26 +1300 Subject: [PATCH 052/267] Harvests#edit needs to respond with something --- app/controllers/harvests_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/harvests_controller.rb b/app/controllers/harvests_controller.rb index 2e7fbef3e..55254516a 100644 --- a/app/controllers/harvests_controller.rb +++ b/app/controllers/harvests_controller.rb @@ -31,6 +31,7 @@ class HarvestsController < ApplicationController def edit @planting = @harvest.planting if @harvest.planting_id + respond_with(@harvest) end def create From c95630e249174f447b9b2aa38c948c904e0dcda6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 12:19:42 +1300 Subject: [PATCH 053/267] Fixed api request specs after rails 5 upgrade --- spec/requests/api/v1/crop_request_spec.rb | 25 +++++++++------- spec/requests/api/v1/gardens_request_spec.rb | 25 +++++++++------- spec/requests/api/v1/harvest_request_spec.rb | 29 ++++++++++++------- spec/requests/api/v1/member_request_spec.rb | 28 +++++++++++------- spec/requests/api/v1/photos_request_spec.rb | 25 +++++++++------- .../requests/api/v1/plantings_request_spec.rb | 27 ++++++++++------- spec/requests/api/v1/seeds_request_spec.rb | 25 +++++++++------- 7 files changed, 107 insertions(+), 77 deletions(-) diff --git a/spec/requests/api/v1/crop_request_spec.rb b/spec/requests/api/v1/crop_request_spec.rb index cfac5fdb4..598a6993e 100644 --- a/spec/requests/api/v1/crop_request_spec.rb +++ b/spec/requests/api/v1/crop_request_spec.rb @@ -56,12 +56,12 @@ RSpec.describe 'Plantings', type: :request do subject { JSON.parse response.body } describe '#index' do - before { get '/api/v1/crops', {}, headers } + before { get '/api/v1/crops', params: {}, headers: headers } it { expect(subject['data']).to include(crop_encoded_as_json_api) } end describe '#show' do - before { get "/api/v1/crops/#{crop.id}", {}, headers } + before { get "/api/v1/crops/#{crop.id}", params: {}, headers: headers } it { expect(subject['data']['attributes']).to eq(attributes) } it { expect(subject['data']['relationships']).to include("plantings" => plantings_as_json_api) } it { expect(subject['data']['relationships']).to include("harvests" => harvests_as_json_api) } @@ -70,18 +70,21 @@ RSpec.describe 'Plantings', type: :request do it { expect(subject['data']).to eq(crop_encoded_as_json_api) } end - describe '#create' do - before { post '/api/v1/crops', { 'crop' => { 'name' => 'can i make this' } }, headers } - it { expect(response.code).to eq "404" } + it '#create' do + expect do + post '/api/v1/crops', params: { 'crop' => { 'name' => 'can i make this' } }, headers: headers + end.to raise_error ActionController::RoutingError end - describe '#update' do - before { post "/api/v1/crops/#{crop.id}", { 'crop' => { 'name' => 'can i modify this' } }, headers } - it { expect(response.code).to eq "404" } + it '#update' do + expect do + post "/api/v1/crops/#{crop.id}", params: { 'crop' => { 'name' => 'can i modify this' } }, headers: headers + end.to raise_error ActionController::RoutingError end - describe '#delete' do - before { delete "/api/v1/crops/#{crop.id}", {}, headers } - it { expect(response.code).to eq "404" } + it '#delete' do + expect do + delete "/api/v1/crops/#{crop.id}", params: {}, headers: headers + end.to raise_error ActionController::RoutingError end end diff --git a/spec/requests/api/v1/gardens_request_spec.rb b/spec/requests/api/v1/gardens_request_spec.rb index 65caf7044..ac1bb6786 100644 --- a/spec/requests/api/v1/gardens_request_spec.rb +++ b/spec/requests/api/v1/gardens_request_spec.rb @@ -38,27 +38,30 @@ RSpec.describe 'Gardens', type: :request do subject { JSON.parse response.body } scenario '#index' do - get '/api/v1/gardens', {}, headers + get '/api/v1/gardens', params: {}, headers: headers expect(subject['data']).to include(garden_encoded_as_json_api) end scenario '#show' do - get "/api/v1/gardens/#{garden.id}", {}, headers + get "/api/v1/gardens/#{garden.id}", params: {}, headers: headers expect(subject['data']).to include(garden_encoded_as_json_api) end - scenario '#create' do - post '/api/v1/gardens', { 'garden' => { 'name' => 'can i make this' } }, headers - expect(response.code).to eq "404" + it '#create' do + expect do + post '/api/v1/gardens', params: { 'garden' => { 'name' => 'can i make this' } }, headers: headers + end.to raise_error ActionController::RoutingError end - scenario '#update' do - post "/api/v1/gardens/#{garden.id}", { 'garden' => { 'name' => 'can i modify this' } }, headers - expect(response.code).to eq "404" + it '#update' do + expect do + post "/api/v1/gardens/#{garden.id}", params: { 'garden' => { 'name' => 'can i modify this' } }, headers: headers + end.to raise_error ActionController::RoutingError end - scenario '#delete' do - delete "/api/v1/gardens/#{garden.id}", {}, headers - expect(response.code).to eq "404" + it '#delete' do + expect do + delete "/api/v1/gardens/#{garden.id}", params: {}, headers: headers + end.to raise_error ActionController::RoutingError end end diff --git a/spec/requests/api/v1/harvest_request_spec.rb b/spec/requests/api/v1/harvest_request_spec.rb index 7d97dea08..ebb0b59ba 100644 --- a/spec/requests/api/v1/harvest_request_spec.rb +++ b/spec/requests/api/v1/harvest_request_spec.rb @@ -57,12 +57,12 @@ RSpec.describe 'Harvests', type: :request do subject { JSON.parse response.body } describe '#index' do - before { get '/api/v1/harvests', {}, headers } + before { get '/api/v1/harvests', params: {}, headers: headers } it { expect(subject['data']).to include(harvest_encoded_as_json_api) } end describe '#show' do - before { get "/api/v1/harvests/#{harvest.id}", {}, headers } + before { get "/api/v1/harvests/#{harvest.id}", params: {}, headers: headers } it { expect(subject['data']['attributes']).to eq(attributes) } it { expect(subject['data']['relationships']).to include("planting" => planting_as_json_api) } it { expect(subject['data']['relationships']).to include("crop" => crop_as_json_api) } @@ -71,18 +71,25 @@ RSpec.describe 'Harvests', type: :request do it { expect(subject['data']).to eq(harvest_encoded_as_json_api) } end - describe '#create' do - before { post '/api/v1/harvests', { 'harvest' => { 'description' => 'can i make this' } }, headers } - it { expect(response.code).to eq "404" } + it '#create' do + expect do + put '/api/v1/harvests', headers: headers, params: { + 'harvest' => { 'description' => 'can i make this' } + } + end.to raise_error ActionController::RoutingError end - describe '#update' do - before { post "/api/v1/harvests/#{harvest.id}", { 'harvest' => { 'description' => 'can i modify this' } }, headers } - it { expect(response.code).to eq "404" } + it '#update' do + expect do + post "/api/v1/harvests/#{harvest.id}", headers: headers, params: { + 'harvest' => { 'description' => 'can i modify this' } + } + end.to raise_error ActionController::RoutingError end - describe '#delete' do - before { delete "/api/v1/harvests/#{harvest.id}", {}, headers } - it { expect(response.code).to eq "404" } + it '#delete' do + expect do + delete "/api/v1/harvests/#{harvest.id}", headers: headers, params: {} + end.to raise_error ActionController::RoutingError end end diff --git a/spec/requests/api/v1/member_request_spec.rb b/spec/requests/api/v1/member_request_spec.rb index 0c74dc3cd..9536ec7c1 100644 --- a/spec/requests/api/v1/member_request_spec.rb +++ b/spec/requests/api/v1/member_request_spec.rb @@ -57,12 +57,12 @@ RSpec.describe 'Members', type: :request do subject { JSON.parse response.body } describe '#index' do - before { get '/api/v1/members', {}, headers } + before { get '/api/v1/members', params: {}, headers: headers } it { expect(subject['data']).to include(member_encoded_as_json_api) } end describe '#show' do - before { get "/api/v1/members/#{member.id}", {}, headers } + before { get "/api/v1/members/#{member.id}", params: {}, headers: headers } it { expect(subject['data']['relationships']).to include("gardens" => gardens_as_json_api) } it { expect(subject['data']['relationships']).to include("plantings" => plantings_as_json_api) } it { expect(subject['data']['relationships']).to include("seeds" => seeds_as_json_api) } @@ -71,18 +71,24 @@ RSpec.describe 'Members', type: :request do it { expect(subject['data']).to eq(member_encoded_as_json_api) } end - describe '#create' do - before { post '/api/v1/members', { 'member' => { 'login_name' => 'can i make this' } }, headers } - it { expect(response.code).to eq "404" } + it '#create' do + expect do + post '/api/v1/members', params: { 'member' => { 'login_name' => 'can i make this' } }, headers: headers + end.to raise_error ActionController::RoutingError end - describe '#update' do - before { post "/api/v1/members/#{member.id}", { 'member' => { 'login_name' => 'can i modify this' } }, headers } - it { expect(response.code).to eq "404" } + it '#update' do + expect do + post "/api/v1/members/#{member.id}", params: { + 'member' => { 'login_name' => 'can i modify this' } + }, + headers: headers + end.to raise_error ActionController::RoutingError end - describe '#delete' do - before { delete "/api/v1/members/#{member.id}", {}, headers } - it { expect(response.code).to eq "404" } + it '#delete' do + expect do + delete "/api/v1/members/#{member.id}", params: {}, headers: headers + end.to raise_error ActionController::RoutingError end end diff --git a/spec/requests/api/v1/photos_request_spec.rb b/spec/requests/api/v1/photos_request_spec.rb index cb205d972..3af370a54 100644 --- a/spec/requests/api/v1/photos_request_spec.rb +++ b/spec/requests/api/v1/photos_request_spec.rb @@ -55,12 +55,12 @@ RSpec.describe 'Photos', type: :request do subject { JSON.parse response.body } describe '#index' do - before { get '/api/v1/photos', {}, headers } + before { get '/api/v1/photos', params: {}, headers: headers } it { expect(subject['data']).to include(photo_encoded_as_json_api) } end describe '#show' do - before { get "/api/v1/photos/#{photo.id}", {}, headers } + before { get "/api/v1/photos/#{photo.id}", params: {}, headers: headers } it { expect(subject['data']['attributes']).to eq(attributes) } it { expect(subject['data']['relationships']).to include("plantings" => plantings_as_json_api) } it { expect(subject['data']['relationships']).to include("harvests" => harvests_as_json_api) } @@ -68,18 +68,21 @@ RSpec.describe 'Photos', type: :request do it { expect(subject['data']).to eq(photo_encoded_as_json_api) } end - describe '#create' do - before { post '/api/v1/photos', { 'photo' => { 'name' => 'can i make this' } }, headers } - it { expect(response.code).to eq "404" } + it '#create' do + expect do + post '/api/v1/photos', params: { 'photo' => { 'name' => 'can i make this' } }, headers: headers + end.to raise_error ActionController::RoutingError end - describe '#update' do - before { post "/api/v1/photos/#{photo.id}", { 'photo' => { 'name' => 'can i modify this' } }, headers } - it { expect(response.code).to eq "404" } + it '#update' do + expect do + post "/api/v1/photos/#{photo.id}", params: { 'photo' => { 'name' => 'can i modify this' } }, headers: headers + end.to raise_error ActionController::RoutingError end - describe '#delete' do - before { delete "/api/v1/photos/#{photo.id}", {}, headers } - it { expect(response.code).to eq "404" } + it '#delete' do + expect do + delete "/api/v1/photos/#{photo.id}", params: {}, headers: headers + end.to raise_error ActionController::RoutingError end end diff --git a/spec/requests/api/v1/plantings_request_spec.rb b/spec/requests/api/v1/plantings_request_spec.rb index 0591a28dc..ae561a66d 100644 --- a/spec/requests/api/v1/plantings_request_spec.rb +++ b/spec/requests/api/v1/plantings_request_spec.rb @@ -68,12 +68,12 @@ RSpec.describe 'Plantings', type: :request do subject { JSON.parse response.body } scenario '#index' do - get '/api/v1/plantings', {}, headers + get '/api/v1/plantings', params: {}, headers: headers expect(subject['data']).to include(planting_encoded_as_json_api) end scenario '#show' do - get "/api/v1/plantings/#{planting.id}", {}, headers + get "/api/v1/plantings/#{planting.id}", params: {}, headers: headers expect(subject['data']['relationships']).to include("garden" => garden_as_json_api) expect(subject['data']['relationships']).to include("crop" => crop_as_json_api) expect(subject['data']['relationships']).to include("owner" => owner_as_json_api) @@ -82,18 +82,23 @@ RSpec.describe 'Plantings', type: :request do expect(subject['data']).to eq(planting_encoded_as_json_api) end - scenario '#create' do - post '/api/v1/plantings', { 'planting' => { 'description' => 'can i make this' } }, headers - expect(response.code).to eq "404" + it '#create' do + expect do + post '/api/v1/plantings', params: { 'planting' => { 'description' => 'can i make this' } }, headers: headers + end.to raise_error ActionController::RoutingError end - scenario '#update' do - post "/api/v1/plantings/#{planting.id}", { 'planting' => { 'description' => 'can i modify this' } }, headers - expect(response.code).to eq "404" + it '#update' do + expect do + post "/api/v1/plantings/#{planting.id}", headers: headers, params: { + 'planting' => { 'description' => 'can i modify this' } + } + end.to raise_error ActionController::RoutingError end - scenario '#delete' do - delete "/api/v1/plantings/#{planting.id}", {}, headers - expect(response.code).to eq "404" + it '#delete' do + expect do + delete "/api/v1/plantings/#{planting.id}", params: {}, headers: headers + end.to raise_error ActionController::RoutingError end end diff --git a/spec/requests/api/v1/seeds_request_spec.rb b/spec/requests/api/v1/seeds_request_spec.rb index 41d622a1f..243e645f5 100644 --- a/spec/requests/api/v1/seeds_request_spec.rb +++ b/spec/requests/api/v1/seeds_request_spec.rb @@ -44,30 +44,33 @@ RSpec.describe 'Photos', type: :request do subject { JSON.parse response.body } describe '#index' do - before { get '/api/v1/seeds', {}, headers } + before { get '/api/v1/seeds', params: {}, headers: headers } it { expect(subject['data']).to include(seed_encoded_as_json_api) } end describe '#show' do - before { get "/api/v1/seeds/#{seed.id}", {}, headers } + before { get "/api/v1/seeds/#{seed.id}", params: {}, headers: headers } it { expect(subject['data']['attributes']).to eq(attributes) } it { expect(subject['data']['relationships']).to include("owner" => owner_as_json_api) } it { expect(subject['data']['relationships']).to include("crop" => crop_as_json_api) } it { expect(subject['data']).to eq(seed_encoded_as_json_api) } end - describe '#create' do - before { post '/api/v1/seeds', { 'seed' => { 'name' => 'can i make this' } }, headers } - it { expect(response.code).to eq "404" } + it '#create' do + expect do + post '/api/v1/seeds', params: { 'seed' => { 'name' => 'can i make this' } }, headers: headers + end.to raise_error ActionController::RoutingError end - describe '#update' do - before { post "/api/v1/seeds/#{seed.id}", { 'seed' => { 'name' => 'can i modify this' } }, headers } - it { expect(response.code).to eq "404" } + it '#update' do + expect do + post "/api/v1/seeds/#{seed.id}", params: { 'seed' => { 'name' => 'can i modify this' } }, headers: headers + end.to raise_error ActionController::RoutingError end - describe '#delete' do - before { delete "/api/v1/seeds/#{seed.id}", {}, headers } - it { expect(response.code).to eq "404" } + it '#delete' do + expect do + delete "/api/v1/seeds/#{seed.id}", params: {}, headers: headers + end.to raise_error ActionController::RoutingError end end From 987400526e828d0a6971fff410c377f12ffed4ce Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 12:32:04 +1300 Subject: [PATCH 054/267] Use distinct for plant parts --- app/models/crop.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index f87fbb262..4863b6658 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -15,7 +15,7 @@ class Crop < ApplicationRecord has_many :photos, through: :plantings has_many :seeds has_many :harvests - has_many :plant_parts, -> { uniq.reorder("plant_parts.name") }, through: :harvests + has_many :plant_parts, -> { distinct.reorder("plant_parts.name") }, through: :harvests belongs_to :creator, class_name: 'Member' belongs_to :requester, class_name: 'Member', optional: true belongs_to :parent, class_name: 'Crop', optional: true From 4800f405eaf023013e2d784e0b8a20b35e22d942 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 12:35:05 +1300 Subject: [PATCH 055/267] Two more fixes to tests for slug generation --- spec/models/post_spec.rb | 2 +- spec/models/seed_spec.rb | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index cb8cbcc91..08502fec7 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' describe Post do - let(:member) { FactoryBot.create(:member) } + let(:member) { FactoryBot.create(:member, login_name: 'whinacooper') } it_behaves_like "it is likeable" it "should have a slug" do diff --git a/spec/models/seed_spec.rb b/spec/models/seed_spec.rb index c1cd95cbd..d1ad584d1 100644 --- a/spec/models/seed_spec.rb +++ b/spec/models/seed_spec.rb @@ -1,7 +1,8 @@ require 'rails_helper' describe Seed do - let(:seed) { FactoryBot.build(:seed) } + let(:owner) { FactoryBot.create :owner, login_name: 'tamateapokaiwhenua' } + let(:seed) { FactoryBot.build(:seed, owner: owner) } it 'should save a basic seed' do seed.save.should be(true) @@ -9,7 +10,7 @@ describe Seed do it "should have a slug" do seed.save - seed.slug.should match(/member\d+-magic-bean/) + seed.slug.should match(/tamateapokaiwhenua-magic-bean/) end context 'quantity' do From a9043b8f5ac5fe2d231f8070305999cdc8679938 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 15:10:25 +1300 Subject: [PATCH 056/267] specify login name and post body in spec don't rely on factory to produce predictable results, specify what we're gonna be looking for in spec --- spec/views/posts/show.html.haml_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/views/posts/show.html.haml_spec.rb b/spec/views/posts/show.html.haml_spec.rb index 169e90da0..9ac4434c6 100644 --- a/spec/views/posts/show.html.haml_spec.rb +++ b/spec/views/posts/show.html.haml_spec.rb @@ -1,7 +1,7 @@ require 'rails_helper' describe "posts/show" do - let(:author) { FactoryBot.create(:member) } + let(:author) { FactoryBot.create(:member, login_name: 'mary') } before(:each) do controller.stub(:current_user) { nil } @@ -12,12 +12,12 @@ describe "posts/show" do describe 'render post' do before { render } describe "basic post" do - let(:post) { FactoryBot.create(:post, author: author) } + let(:post) { FactoryBot.create(:post, author: author, body: 'hello there') } # show the name of the member who posted the post - it { is_expected.to match(/member\d+/) } + it { is_expected.to have_text author.login_name } # Subject goes in title - it { is_expected.to have_text('This is some text.') } + it { is_expected.to have_text('hello there') } # shouldn't show the subject on a single post page # (it appears in the title/h1 via the layout, not via this view) it { is_expected.not_to have_text('An Update') } From f02d328d1c5de1d8a58eecb934c3821115903563 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 15:34:51 +1300 Subject: [PATCH 057/267] commented out a cms link --- app/views/admin/index.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/index.html.haml b/app/views/admin/index.html.haml index 294e16199..389cc2dee 100644 --- a/app/views/admin/index.html.haml +++ b/app/views/admin/index.html.haml @@ -10,7 +10,7 @@ %li= link_to "Products", products_path %li= link_to "Roles", roles_path %li= link_to "Forums", forums_path - %li= link_to "CMS", comfy_admin_cms_path + -# %li= link_to "CMS", comfy_admin_cms_path .col-md-4 %h2 Crop data admin From ca40d0714895c55ac6ca19a343c27e9415bf12ac Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 16:42:18 +1300 Subject: [PATCH 058/267] Fixed up crops view spec --- spec/views/home/_crops.html.haml_spec.rb | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/spec/views/home/_crops.html.haml_spec.rb b/spec/views/home/_crops.html.haml_spec.rb index 254fcb2f6..bfc8dc856 100644 --- a/spec/views/home/_crops.html.haml_spec.rb +++ b/spec/views/home/_crops.html.haml_spec.rb @@ -1,10 +1,16 @@ require 'rails_helper' describe 'home/_crops.html.haml', type: "view" do - let!(:crop) { FactoryBot.create(:crop, plantings: FactoryBot.create_list(:planting, 3)) } - let!(:photo) { FactoryBot.create(:photo, plantings: [crop.plantings.first]) } + let(:crop) { FactoryBot.create(:crop, name: 'pūhā') } + let(:photo) { FactoryBot.create(:photo) } + before(:each) do + plantings = FactoryBot.create_list(:planting, 3, crop: crop) + plantings.each do |p| + p.photos << photo + end + render + end let(:planting) { crop.plantings.first } - before(:each) { render } it 'shows crops section' do assert_select 'h2', text: 'Some of our crops' assert_select "a[href='#{crop_path(crop)}']" From 482d15e36dd814cc0b787d2051be1010e2a41b67 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 6 Jan 2018 16:48:28 +1300 Subject: [PATCH 059/267] Fixed spec to specify login name before checking --- spec/views/members/show.rss.haml_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/views/members/show.rss.haml_spec.rb b/spec/views/members/show.rss.haml_spec.rb index 23366a9a8..0ea36d1c0 100644 --- a/spec/views/members/show.rss.haml_spec.rb +++ b/spec/views/members/show.rss.haml_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' describe 'members/show.rss.haml', type: "view" do before(:each) do - @member = assign(:member, FactoryBot.create(:member)) + @member = assign(:member, FactoryBot.create(:member, login_name: 'callum')) @post1 = FactoryBot.create(:post, id: 1, author: @member) @post2 = FactoryBot.create(:markdown_post, id: 2, author: @member) assign(:posts, [@post1, @post2]) @@ -12,7 +12,7 @@ describe 'members/show.rss.haml', type: "view" do subject { rendered } it 'shows RSS feed title' do - is_expected.to match(/member\d+'s recent posts/) + is_expected.to have_text("callum's recent posts") end it 'shows content of posts' do From bf34feacbafc98242b31decaaa5f40c4eaa018ce Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 7 Jan 2018 17:25:16 +1300 Subject: [PATCH 060/267] Convert to use chartkick gem --- .overcommit.yml | 1 + Gemfile | 3 +- Gemfile.lock | 5 +- app/assets/javascripts/charts.js | 2 + app/assets/javascripts/crops.js.erb | 37 -- app/assets/javascripts/graphs/bar_group.js | 53 --- .../javascripts/graphs/bar_label_group.js | 45 -- app/assets/javascripts/graphs/height_scale.js | 31 -- .../graphs/horizontal_bar_graph.js | 54 --- app/assets/javascripts/graphs/width_scale.js | 37 -- app/assets/javascripts/highcharts.js | 389 ++++++++++++++++++ app/assets/stylesheets/application.sass | 1 + .../custom_bootstrap/variables.sass | 1 + app/assets/stylesheets/overrides.sass | 19 - app/assets/stylesheets/predictions.sass | 11 + app/controllers/crops_controller.rb | 14 +- app/views/crops/_predictions.html.haml | 55 +-- app/views/crops/show.html.haml | 35 +- app/views/layouts/application.html.haml | 1 + config/initializers/assets.rb | 1 + config/routes.rb | 1 + 21 files changed, 470 insertions(+), 326 deletions(-) create mode 100644 app/assets/javascripts/charts.js delete mode 100644 app/assets/javascripts/graphs/bar_group.js delete mode 100644 app/assets/javascripts/graphs/bar_label_group.js delete mode 100644 app/assets/javascripts/graphs/height_scale.js delete mode 100644 app/assets/javascripts/graphs/horizontal_bar_graph.js delete mode 100644 app/assets/javascripts/graphs/width_scale.js create mode 100644 app/assets/javascripts/highcharts.js create mode 100644 app/assets/stylesheets/predictions.sass diff --git a/.overcommit.yml b/.overcommit.yml index d7899885f..200a90e42 100644 --- a/.overcommit.yml +++ b/.overcommit.yml @@ -61,6 +61,7 @@ PreCommit: enabled: true exclude: - 'app/assets/**' + - 'app/assets/javascripts/highcharts.js' - 'spec/javascripts/support/vendor/**' - '**/bootstrap*' command: ['./node_modules/.bin/eslint'] diff --git a/Gemfile b/Gemfile index 32158db8f..85b77b245 100644 --- a/Gemfile +++ b/Gemfile @@ -78,8 +78,7 @@ gem 'omniauth-facebook' gem 'omniauth-flickr', '>= 0.0.15' gem 'omniauth-twitter' -# For charting data -gem 'd3-rails' +gem "chartkick" # client for Elasticsearch. Elasticsearch is a flexible # and powerful, distributed, real-time search and analytics engine. diff --git a/Gemfile.lock b/Gemfile.lock index 28e049445..b7f899e78 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -91,6 +91,7 @@ GEM capybara-screenshot (1.0.18) capybara (>= 1.0, < 3) launchy + chartkick (2.2.5) childprocess (0.8.0) ffi (~> 1.0, >= 1.0.11) cliver (0.3.2) @@ -115,8 +116,6 @@ GEM crass (1.0.3) csv_shaper (1.3.0) activesupport (>= 3.0.0) - d3-rails (4.10.2) - railties (>= 3.1) dalli (2.7.6) database_cleaner (1.6.2) devise (4.4.0) @@ -499,11 +498,11 @@ DEPENDENCIES capybara capybara-email capybara-screenshot + chartkick codeclimate-test-reporter coffee-rails coveralls csv_shaper - d3-rails dalli database_cleaner devise diff --git a/app/assets/javascripts/charts.js b/app/assets/javascripts/charts.js new file mode 100644 index 000000000..1c42da456 --- /dev/null +++ b/app/assets/javascripts/charts.js @@ -0,0 +1,2 @@ +// = require Chart.bundle +// = require chartkick diff --git a/app/assets/javascripts/crops.js.erb b/app/assets/javascripts/crops.js.erb index f2eec8848..ad438190a 100644 --- a/app/assets/javascripts/crops.js.erb +++ b/app/assets/javascripts/crops.js.erb @@ -1,5 +1,3 @@ -//= require graphs/horizontal_bar_graph - if (document.getElementById("cropmap") !== null) { mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Rails.application.config.mapbox_map_id %>"; mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Rails.application.config.mapbox_access_token %>"; @@ -51,41 +49,6 @@ function showCropMap(cropmap) { cropmap.addLayer(markers); } -function plantingStats(crop) { - var sunniness_counts = { 'empty': 0, 'sun': 0, 'semi-shade': 0, 'shade': 0 }; - $.each(crop.plantings, function(i, planting) { - if (planting.sunniness) { - sunniness_counts[planting.sunniness]++; - } else { - sunniness_counts['Empty']++; - } - }); - return [ - {name: 'Empty', value: sunniness_counts['empty']}, - {name: 'Sun', value: sunniness_counts['sun']}, - {name: 'Semi-shade', value: sunniness_counts['semi-shade']}, - {name: 'Shade', value: sunniness_counts['shade']} - ]; -} - -if ($("#sunchart")[0] !== null) { - var HorizontalBarGraph = growstuff.HorizontalBarGraph; - $.getJSON(location.pathname + '.json', function (crop) { - data = { - bars: plantingStats(crop), - bar_color: 'steelblue', - width: {size: 300, scale: 'linear'}, - height: {size: 100, scale: 'ordinal'}, - //left is used to shift the bars over so that there is - //room for the labels - margin: {top: 0, right: 0, bottom: 0, left: 100} - }; - - var graph = new HorizontalBarGraph(data); - graph.render(d3.select($('#sunchart')[0])); - }); -} - $('.btn.toggle.crop-hierarchy').click(function () { $('.toggle.crop-hierarchy').toggleClass('hide'); }); diff --git a/app/assets/javascripts/graphs/bar_group.js b/app/assets/javascripts/graphs/bar_group.js deleted file mode 100644 index e8a90c20a..000000000 --- a/app/assets/javascripts/graphs/bar_group.js +++ /dev/null @@ -1,53 +0,0 @@ -// =require d3 -// = require graphs/width_scale -// = require graphs/height_scale - -/* - * This represents bars for a bar graph. - * Currently these are used for HorizontalBarGraph. - */ -(function() { - 'use strict'; - - - var growstuff = (window.growstuff = window.growstuff || {}); - var WidthScale = growstuff.WidthScale; - var HeightScale = growstuff.HeightScale; - -/** - * data object for bar group - * @param {Object} data Graph configuration - */ -function BarGroup(data) { - this._data = data; -} - BarGroup.prototype.render = function(root) { - var data = this._data; - var bars = this._data.bars; - var widthScale = new WidthScale(data).render(); - var heightScale = new HeightScale(data).render(); - - return root.append('g') - .attr('class', 'bar') - .selectAll('rect') - .data(bars.map(function(bar) { - return bar.value; - })) - .enter() - .append('rect') - .attr('y', function(d, i) { - return heightScale(i); - }) - .attr('height', heightScale.rangeBand()) - .attr('fill', data.bar_color) - .attr('width', function(d) { - return widthScale(d); - }) - .append('title') - .text(function(d) { - return 'This value is ' + d + '.'; - }); - }; - - growstuff.BarGroup = BarGroup; -}()); diff --git a/app/assets/javascripts/graphs/bar_label_group.js b/app/assets/javascripts/graphs/bar_label_group.js deleted file mode 100644 index 2da31f567..000000000 --- a/app/assets/javascripts/graphs/bar_label_group.js +++ /dev/null @@ -1,45 +0,0 @@ -// =require d3 -/** - * This file draws the labels to the left of each bar. - */ -(function() { - 'use strict'; - - var growstuff = (window.growstuff = window.growstuff || {}); - /** - * new bar label object - * @param {Object} data Graph configuration - */ - function BarLabelGroup(data) { - this._data = data; - } - - BarLabelGroup.prototype.render = function(d3) { - var bars = this._data.bars; - // vvcopy pasta from spike vv -- this is a good candidate for refactor - var barHeight = 40; - - return d3.append('g') - .attr('class', 'bar-label') - .selectAll('text') - .data(bars.map(function(bar) { - return bar.name; - })) - .enter() - .append('text') - .attr('x', -80) - .attr('y', function(d, i) { - // shrink the margin between each label to give them an even spread with - // bars - var barLabelSpread = 2/3; - // move them downward to line up with bars - var barLabelTopEdge = 17; - return i * barHeight * (barLabelSpread) + barLabelTopEdge; - }) - .text(function(d) { - return d; - }); - }; - - growstuff.BarLabelGroup = BarLabelGroup; -}()); diff --git a/app/assets/javascripts/graphs/height_scale.js b/app/assets/javascripts/graphs/height_scale.js deleted file mode 100644 index 5189ef800..000000000 --- a/app/assets/javascripts/graphs/height_scale.js +++ /dev/null @@ -1,31 +0,0 @@ -// =require d3 - -/** - * Height Scale is used to map the number of bars to the display size of - * the svg - */ - -(function() { - 'use strict'; - - var growstuff = (window.growstuff = window.growstuff || {}); - - /** - * new height scale object - * @param {Object} data Graph configuration - */ - function HeightScale(data) { - this._data = data; - } - - HeightScale.prototype.render = function() { - var data = this._data; - var scaleType = data.height.scale; - - return d3.scale[scaleType]() - .domain(d3.range(data.bars.length)) - .rangeRoundBands([0, data.height.size], 0.05, 0); - }; - - growstuff.HeightScale = HeightScale; -}()); diff --git a/app/assets/javascripts/graphs/horizontal_bar_graph.js b/app/assets/javascripts/graphs/horizontal_bar_graph.js deleted file mode 100644 index ef2333ef1..000000000 --- a/app/assets/javascripts/graphs/horizontal_bar_graph.js +++ /dev/null @@ -1,54 +0,0 @@ -// = require d3 -// = require graphs/bar_group -// = require graphs/bar_label_group - -/** - * Horizontal Bar Graph represents sum total of the graph including all of the parts: - * Bars - * Bar Labels - * - * The main dimensions of the graph are rendered here. - */ - -(function() { - 'use strict'; - - var growstuff = (window.growstuff = window.growstuff || {}); - var BarGroup = growstuff.BarGroup; - var BarLabelGroup = growstuff.BarLabelGroup; - - /** - * create a new graph object - * @param {Object} data Graph configuration - */ - function HorizontalBarGraph(data) { - this._data = data; - this._d3 = d3; - } - - HorizontalBarGraph.prototype.render = function(root) { - var width = this._data.width; - var height = this._data.height; - - var barLabelGroup = new BarLabelGroup(this._data); - var margin = this._data.margin; - - var barGroup = new BarGroup(this._data); - - var svg = root - .append('svg') - .attr('width', width.size + margin.left + margin.right) - .attr('height', height.size + margin.top + margin.bottom) - .append('g') - .attr('class', 'bar-graph') - .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); - - - barGroup.render(svg); - barLabelGroup.render(svg); - - return svg; - }; - - growstuff.HorizontalBarGraph = HorizontalBarGraph; -}()); diff --git a/app/assets/javascripts/graphs/width_scale.js b/app/assets/javascripts/graphs/width_scale.js deleted file mode 100644 index 7f2b9dda2..000000000 --- a/app/assets/javascripts/graphs/width_scale.js +++ /dev/null @@ -1,37 +0,0 @@ -// =require d3 - -/** - * Width scale is used to map the value for the length of each bar - * to the display size of the svg - */ -(function() { - 'use strict'; - - var growstuff = (window.growstuff = window.growstuff || {}); - - /** - * Object for WidthScale - * @param {Object} data Graph configuration - */ - function WidthScale(data) { - this._data = data; - } - - WidthScale.prototype.render = function() { - var data = this._data; - var scaleType = data.width.scale; - var axisSize = data.width.size; - - return d3.scale[scaleType]() - .domain([0, this.getMaxValue()]) - .range([0, axisSize]); - }; - - WidthScale.prototype.getMaxValue = function() { - return d3.max(this._data.bars.map(function(bar) { - return bar.value; - })); - }; - - growstuff.WidthScale = WidthScale; -}()); diff --git a/app/assets/javascripts/highcharts.js b/app/assets/javascripts/highcharts.js new file mode 100644 index 000000000..9554ef58b --- /dev/null +++ b/app/assets/javascripts/highcharts.js @@ -0,0 +1,389 @@ +/* + Highcharts JS v6.0.4 (2017-12-15) + + (c) 2009-2016 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(S,M){"object"===typeof module&&module.exports?module.exports=S.document?M(S):M:S.Highcharts=M(S)})("undefined"!==typeof window?window:this,function(S){var M=function(){var a="undefined"===typeof S?window:S,E=a.document,D=a.navigator&&a.navigator.userAgent||"",H=E&&E.createElementNS&&!!E.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,p=/(edge|msie|trident)/i.test(D)&&!a.opera,f=/Firefox/.test(D),l=f&&4>parseInt(D.split("Firefox/")[1],10);return a.Highcharts?a.Highcharts.error(16, +!0):{product:"Highcharts",version:"6.0.4",deg2rad:2*Math.PI/360,doc:E,hasBidiBug:l,hasTouch:E&&void 0!==E.documentElement.ontouchstart,isMS:p,isWebKit:/AppleWebKit/.test(D),isFirefox:f,isTouchDevice:/(Mobile|Android|Windows Phone)/.test(D),SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:H,win:a,marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){},charts:[]}}();(function(a){a.timers=[];var E=a.charts,D=a.doc,H=a.win;a.error=function(p, +f){p=a.isNumber(p)?"Highcharts error #"+p+": www.highcharts.com/errors/"+p:p;if(f)throw Error(p);H.console&&console.log(p)};a.Fx=function(a,f,l){this.options=f;this.elem=a;this.prop=l};a.Fx.prototype={dSetter:function(){var a=this.paths[0],f=this.paths[1],l=[],r=this.now,n=a.length,w;if(1===r)l=this.toD;else if(n===f.length&&1>r)for(;n--;)w=parseFloat(a[n]),l[n]=isNaN(w)?f[n]:r*parseFloat(f[n]-w)+w;else l=f;this.elem.attr("d",l,null,!0)},update:function(){var a=this.elem,f=this.prop,l=this.now,r= +this.options.step;if(this[f+"Setter"])this[f+"Setter"]();else a.attr?a.element&&a.attr(f,l,null,!0):a.style[f]=l+this.unit;r&&r.call(a,l,this)},run:function(p,f,l){var r=this,n=r.options,w=function(a){return w.stopped?!1:r.step(a)},u=H.requestAnimationFrame||function(a){setTimeout(a,13)},e=function(){for(var h=0;h=u+this.startTime?(this.now=this.end,this.pos=1,this.update(),l=e[this.prop]=!0,a.objectEach(e,function(a){!0!==a&&(l=!1)}),l&&w&&w.call(n),p=!1):(this.pos=r.easing((f-this.startTime)/u),this.now=this.start+(this.end- +this.start)*this.pos,this.update(),p=!0);return p},initPath:function(p,f,l){function r(a){var b,c;for(k=a.length;k--;)b="M"===a[k]||"L"===a[k],c=/[a-zA-Z]/.test(a[k+3]),b&&c&&a.splice(k+1,0,a[k+1],a[k+2],a[k+1],a[k+2])}function n(a,b){for(;a.lengtha&&-Infinityw?"AM":"PM",P:12>w?"am":"pm",S:k(n.getSeconds()),L:k(Math.round(f%1E3),3)},a.dateFormats);a.objectEach(r,function(a,b){for(;-1!==p.indexOf("%"+b);)p=p.replace("%"+b,"function"===typeof a?a(f):a)});return l?p.substr(0,1).toUpperCase()+p.substr(1):p};a.formatSingle=function(p,f){var l=/\.([0-9])/,r=a.defaultOptions.lang;/f$/.test(p)?(l=(l=p.match(l))?l[1]:-1,null!==f&&(f=a.numberFormat(f,l,r.decimalPoint,-1=l&&(f=[1/l])));for(r=0;r=p||!n&&w<=(f[r]+(f[r+1]||f[r]))/2);r++);return u=a.correctFloat(u*l,-Math.round(Math.log(.001)/Math.LN10))};a.stableSort=function(a,f){var l=a.length,p,n;for(n=0;nl&&(l=a[f]);return l};a.destroyObjectProperties=function(p,f){a.objectEach(p,function(a,r){a&&a!==f&&a.destroy&&a.destroy();delete p[r]})};a.discardElement=function(p){var f=a.garbageBin;f||(f=a.createElement("div"));p&&f.appendChild(p);f.innerHTML=""};a.correctFloat=function(a,f){return parseFloat(a.toPrecision(f||14))};a.setAnimation=function(p,f){f.renderer.globalAnimation=a.pick(p,f.options.chart.animation, +!0)};a.animObject=function(p){return a.isObject(p)?a.merge(p):{duration:p?500:0}};a.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5,month:24192E5,year:314496E5};a.numberFormat=function(p,f,l,r){p=+p||0;f=+f;var n=a.defaultOptions.lang,w=(p.toString().split(".")[1]||"").split("e")[0].length,u,e,h=p.toString().split("e");-1===f?f=Math.min(w,20):a.isNumber(f)?f&&h[1]&&0>h[1]&&(u=f+ +h[1],0<=u?(h[0]=(+h[0]).toExponential(u).split("e")[0],f=u):(h[0]=h[0].split(".")[0]||0, +p=20>f?(h[0]*Math.pow(10,h[1])).toFixed(f):0,h[1]=0)):f=2;e=(Math.abs(h[1]?h[0]:p)+Math.pow(10,-Math.max(f,w)-1)).toFixed(f);w=String(a.pInt(e));u=3p?"-":"")+(u?w.substr(0,u)+r:"");p+=w.substr(u).replace(/(\d{3})(?=\d)/g,"$1"+r);f&&(p+=l+e.slice(-f));h[1]&&0!==+p&&(p+="e"+h[1]);return p};Math.easeInOutSine=function(a){return-.5*(Math.cos(Math.PI*a)-1)};a.getStyle=function(p,f,l){if("width"===f)return Math.min(p.offsetWidth, +p.scrollWidth)-a.getStyle(p,"padding-left")-a.getStyle(p,"padding-right");if("height"===f)return Math.min(p.offsetHeight,p.scrollHeight)-a.getStyle(p,"padding-top")-a.getStyle(p,"padding-bottom");H.getComputedStyle||a.error(27,!0);if(p=H.getComputedStyle(p,void 0))p=p.getPropertyValue(f),a.pick(l,"opacity"!==f)&&(p=a.pInt(p));return p};a.inArray=function(p,f){return(a.indexOfPolyfill||Array.prototype.indexOf).call(f,p)};a.grep=function(p,f){return(a.filterPolyfill||Array.prototype.filter).call(p, +f)};a.find=Array.prototype.find?function(a,f){return a.find(f)}:function(a,f){var l,r=a.length;for(l=0;l>16,(l&65280)>> +8,l&255,1]:4===f&&(n=[(l&3840)>>4|(l&3840)>>8,(l&240)>>4|l&240,(l&15)<<4|l&15,1])),!n)for(w=this.parsers.length;w--&&!n;)u=this.parsers[w],(f=u.regex.exec(l))&&(n=u.parse(f));this.rgba=n||[]},get:function(a){var f=this.input,n=this.rgba,l;this.stops?(l=p(f),l.stops=[].concat(l.stops),E(this.stops,function(n,e){l.stops[e]=[l.stops[e][0],n.get(a)]})):l=n&&D(n[0])?"rgb"===a||!a&&1===n[3]?"rgb("+n[0]+","+n[1]+","+n[2]+")":"a"===a?n[3]:"rgba("+n.join(",")+")":f;return l},brighten:function(a){var l,n=this.rgba; +if(this.stops)E(this.stops,function(n){n.brighten(a)});else if(D(a)&&0!==a)for(l=0;3>l;l++)n[l]+=f(255*a),0>n[l]&&(n[l]=0),255y.width)y={width:0,height:0}}else y=this.htmlGetBBox();b.isSVG&& +(a=y.width,b=y.height,q&&"11px"===q.fontSize&&17===Math.round(b)&&(y.height=b=14),g&&(y.width=Math.abs(b*Math.sin(v))+Math.abs(a*Math.cos(v)),y.height=Math.abs(b*Math.cos(v))+Math.abs(a*Math.sin(v))));if(A&&0]*>/g,"")))},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,g,b){"string"===typeof a?b.setAttribute(g,a):a&&this.colorGradient(a,g,b)},visibilitySetter:function(a,g,b){"inherit"===a?b.removeAttribute(g):this[g]!==a&&b.setAttribute(g,a);this[g]=a},zIndexSetter:function(a,b){var v=this.renderer,y=this.parentGroup,c=(y||v).element||v.box,k,d=this.element,q,e,v=c===v.box;k=this.added;var z;u(a)&& +(d.zIndex=a,a=+a,this[b]===a&&(k=!1),this[b]=a);if(k){(a=this.zIndex)&&y&&(y.handleZ=!0);b=c.childNodes;for(z=b.length-1;0<=z&&!q;z--)if(y=b[z],k=y.zIndex,e=!u(k),y!==d)if(0>a&&e&&!v&&!z)c.insertBefore(d,b[z]),q=!0;else if(g(k)<=a||e&&(!u(a)||0<=a))c.insertBefore(d,b[z+1]||null),q=!0;q||(c.insertBefore(d,b[v?3:0]||null),q=!0)}return q},_defaultSetter:function(a,g,b){b.setAttribute(g,a)}});E.prototype.yGetter=E.prototype.xGetter;E.prototype.translateXSetter=E.prototype.translateYSetter=E.prototype.rotationSetter= +E.prototype.verticalAlignSetter=E.prototype.rotationOriginXSetter=E.prototype.rotationOriginYSetter=E.prototype.scaleXSetter=E.prototype.scaleYSetter=E.prototype.matrixSetter=function(a,g){this[g]=a;this.doTransform=!0};E.prototype["stroke-widthSetter"]=E.prototype.strokeSetter=function(a,g,b){this[g]=a;this.stroke&&this["stroke-width"]?(E.prototype.fillSetter.call(this,this.stroke,"stroke",b),b.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0):"stroke-width"===g&&0===a&&this.hasStroke&& +(b.removeAttribute("stroke"),this.hasStroke=!1)};D=a.SVGRenderer=function(){this.init.apply(this,arguments)};c(D.prototype,{Element:E,SVG_NS:P,init:function(a,g,b,v,c,k){var y;v=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"}).css(this.getStyle(v));y=v.element;a.appendChild(y);f(a,"dir","ltr");-1===a.innerHTML.indexOf("xmlns")&&f(y,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=y;this.boxWrapper=v;this.alignedObjects=[];this.url=(x||N)&&m.getElementsByTagName("base").length? +R.location.href.replace(/#.*?$/,"").replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(m.createTextNode("Created with Highcharts 6.0.4"));this.defs=this.createElement("defs").add();this.allowHTML=k;this.forExport=c;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(g,b,!1);var d;x&&a.getBoundingClientRect&&(g=function(){n(a,{left:0,top:0});d=a.getBoundingClientRect();n(a,{left:Math.ceil(d.left)- +d.left+"px",top:Math.ceil(d.top)-d.top+"px"})},g(),this.unSubPixelFix=H(R,"resize",g))},getStyle:function(a){return this.style=c({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},setStyle:function(a){this.boxWrapper.css(this.getStyle(a))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();h(this.gradients||{});this.gradients=null;a&&(this.defs=a.destroy()); +this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(a){var g=new this.Element;g.init(this,a);return g},draw:A,getRadialAttr:function(a,g){return{cx:a[0]-a[2]/2+g.cx*a[2],cy:a[1]-a[2]/2+g.cy*a[2],r:g.r*a[2]}},getSpanWidth:function(a,g){var b=a.getBBox(!0).width;!L&&this.forExport&&(b=this.measureSpanWidth(g.firstChild.data,a.styles));return b},applyEllipsis:function(a,g,b,v){var c=a.rotation,y=b,k,d=0,q=b.length,e=function(a){g.removeChild(g.firstChild); +a&&g.appendChild(m.createTextNode(a))},z;a.rotation=0;y=this.getSpanWidth(a,g);if(z=y>v){for(;d<=q;)k=Math.ceil((d+q)/2),y=b.substring(0,k)+"\u2026",e(y),y=this.getSpanWidth(a,g),d===q?d=q+1:y>v?q=k-1:d=k;0===q&&e("")}a.rotation=c;return z},escapes:{"\x26":"\x26amp;","\x3c":"\x26lt;","\x3e":"\x26gt;","'":"\x26#39;",'"':"\x26quot;"},buildText:function(a){var b=a.element,v=this,c=v.forExport,y=G(a.textStr,"").toString(),q=-1!==y.indexOf("\x3c"),e=b.childNodes,z,h,A,J,t=f(b,"x"),x=a.styles,B=a.textWidth, +l=x&&x.lineHeight,C=x&&x.textOutline,u=x&&"ellipsis"===x.textOverflow,Q=x&&"nowrap"===x.whiteSpace,w=x&&x.fontSize,R,I,r=e.length,x=B&&!a.added&&this.box,p=function(a){var c;c=/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:w||v.style.fontSize||12;return l?g(l):v.fontMetrics(c,a.getAttribute("style")?a:b).h},K=function(a){F(v.escapes,function(g,b){a=a.replace(new RegExp(g,"g"),b)});return a};R=[y,u,Q,l,C,w,B].join();if(R!==a.textCache){for(a.textCache=R;r--;)b.removeChild(e[r]);q||C||u||B|| +-1!==y.indexOf(" ")?(z=/<.*class="([^"]+)".*>/,h=/<.*style="([^"]+)".*>/,A=/<.*href="([^"]+)".*>/,x&&x.appendChild(b),y=q?y.replace(/<(b|strong)>/g,'\x3cspan style\x3d"font-weight:bold"\x3e').replace(/<(i|em)>/g,'\x3cspan style\x3d"font-style:italic"\x3e').replace(//g,"\x3c/span\x3e").split(//g):[y],y=k(y,function(a){return""!==a}),d(y,function(g,y){var k,q=0;g=g.replace(/^\s+|\s+$/g,"").replace(//g,"\x3c/span\x3e|||"); +k=g.split("|||");d(k,function(g){if(""!==g||1===k.length){var d={},e=m.createElementNS(v.SVG_NS,"tspan"),x,F;z.test(g)&&(x=g.match(z)[1],f(e,"class",x));h.test(g)&&(F=g.match(h)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),f(e,"style",F));A.test(g)&&!c&&(f(e,"onclick",'location.href\x3d"'+g.match(A)[1]+'"'),f(e,"class","highcharts-anchor"),n(e,{cursor:"pointer"}));g=K(g.replace(/<[a-zA-Z\/](.|\n)*?>/g,"")||" ");if(" "!==g){e.appendChild(m.createTextNode(g));q?d.dx=0:y&&null!==t&&(d.x=t);f(e,d);b.appendChild(e); +!q&&I&&(!L&&c&&n(e,{display:"block"}),f(e,"dy",p(e)));if(B){d=g.replace(/([^\^])-/g,"$1- ").split(" ");x=1B,void 0===J&&(J=g),g&&1!==d.length?(e.removeChild(e.firstChild),O.unshift(d.pop())):(d=O,O=[],d.length&&!Q&&(e=m.createElementNS(P,"tspan"),f(e,{dy:C,x:t}),F&&f(e,"style",F),b.appendChild(e)),l>B&&(B=l)),d.length&&e.appendChild(m.createTextNode(d.join(" ").replace(/- /g, +"-")));a.rotation=G}q++}}});I=I||b.childNodes.length}),J&&a.attr("title",a.textStr),x&&x.removeChild(b),C&&a.applyTextOutline&&a.applyTextOutline(C)):b.appendChild(m.createTextNode(K(y)))}},getContrast:function(a){a=r(a).rgba;return 510Math.abs(c.end-c.start-2*Math.PI));var y=Math.cos(k),z=Math.sin(k),h=Math.cos(e),e=Math.sin(e);c=.001>c.end-k-Math.PI?0:1;d=["M",a+d*y,g+q*z,"A",d,q,0,c,1,a+d*h,g+q*e];u(b)&&d.push(v?"M":"L",a+b* +h,g+b*e,"A",b,b,0,c,0,a+b*y,g+b*z);d.push(v?"":"Z");return d},callout:function(a,g,b,v,c){var d=Math.min(c&&c.r||0,b,v),k=d+6,q=c&&c.anchorX;c=c&&c.anchorY;var e;e=["M",a+d,g,"L",a+b-d,g,"C",a+b,g,a+b,g,a+b,g+d,"L",a+b,g+v-d,"C",a+b,g+v,a+b,g+v,a+b-d,g+v,"L",a+d,g+v,"C",a,g+v,a,g+v,a,g+v-d,"L",a,g+d,"C",a,g,a,g,a+d,g];q&&q>b?c>g+k&&cq?c>g+k&&cv&&q>a+k&&qc&&q>a+k&&qa?a+3:Math.round(1.2*a);return{h:b,b:Math.round(.8* +b),f:a}},rotCorr:function(a,g,b){var v=a;g&&b&&(v=Math.max(v*Math.cos(g*e),4));return{x:-a/3*Math.sin(g*e),y:v}},label:function(g,b,k,e,z,h,m,A,L){var y=this,J=y.g("button"!==L&&"label"),t=J.text=y.text("",0,0,m).attr({zIndex:1}),x,F,n=0,B=3,l=0,C,f,Q,G,w,R={},I,P,r=/^url\((.*?)\)$/.test(e),p=r,K,O,N,T;L&&J.addClass("highcharts-"+L);p=r;K=function(){return(I||0)%2/2};O=function(){var a=t.element.style,g={};F=(void 0===C||void 0===f||w)&&u(t.textStr)&&t.getBBox();J.width=(C||F.width||0)+2*B+l;J.height= +(f||F.height||0)+2*B;P=B+y.fontMetrics(a&&a.fontSize,t).b;p&&(x||(J.box=x=y.symbols[e]||r?y.symbol(e):y.rect(),x.addClass(("button"===L?"":"highcharts-label-box")+(L?" highcharts-"+L+"-box":"")),x.add(J),a=K(),g.x=a,g.y=(A?-P:0)+a),g.width=Math.round(J.width),g.height=Math.round(J.height),x.attr(c(g,R)),R={})};N=function(){var a=l+B,g;g=A?0:P;u(C)&&F&&("center"===w||"right"===w)&&(a+={center:.5,right:1}[w]*(C-F.width));if(a!==t.x||g!==t.y)t.attr("x",a),void 0!==g&&t.attr("y",g);t.x=a;t.y=g};T=function(a, +g){x?x.attr(a,g):R[a]=g};J.onAdd=function(){t.add(J);J.attr({text:g||0===g?g:"",x:b,y:k});x&&u(z)&&J.attr({anchorX:z,anchorY:h})};J.widthSetter=function(g){C=a.isNumber(g)?g:null};J.heightSetter=function(a){f=a};J["text-alignSetter"]=function(a){w=a};J.paddingSetter=function(a){u(a)&&a!==B&&(B=J.padding=a,N())};J.paddingLeftSetter=function(a){u(a)&&a!==l&&(l=a,N())};J.alignSetter=function(a){a={left:0,center:.5,right:1}[a];a!==n&&(n=a,F&&J.attr({x:Q}))};J.textSetter=function(a){void 0!==a&&t.textSetter(a); +O();N()};J["stroke-widthSetter"]=function(a,g){a&&(p=!0);I=this["stroke-width"]=a;T(g,a)};J.strokeSetter=J.fillSetter=J.rSetter=function(a,g){"r"!==g&&("fill"===g&&a&&(p=!0),J[g]=a);T(g,a)};J.anchorXSetter=function(a,g){z=J.anchorX=a;T(g,Math.round(a)-K()-Q)};J.anchorYSetter=function(a,g){h=J.anchorY=a;T(g,a-G)};J.xSetter=function(a){J.x=a;n&&(a-=n*((C||F.width)+2*B));Q=Math.round(a);J.attr("translateX",Q)};J.ySetter=function(a){G=J.y=Math.round(a);J.attr("translateY",G)};var U=J.css;return c(J,{css:function(a){if(a){var g= +{};a=q(a);d(J.textProps,function(b){void 0!==a[b]&&(g[b]=a[b],delete a[b])});t.css(g)}return U.call(J,a)},getBBox:function(){return{width:F.width+2*B,height:F.height+2*B,x:F.x-B,y:F.y-B}},shadow:function(a){a&&(O(),x&&x.shadow(a));return J},destroy:function(){v(J.element,"mouseenter");v(J.element,"mouseleave");t&&(t=t.destroy());x&&(x=x.destroy());E.prototype.destroy.call(J);J=y=O=N=T=null}})}});a.Renderer=D})(M);(function(a){var E=a.attr,D=a.createElement,H=a.css,p=a.defined,f=a.each,l=a.extend, +r=a.isFirefox,n=a.isMS,w=a.isWebKit,u=a.pick,e=a.pInt,h=a.SVGRenderer,m=a.win,d=a.wrap;l(a.SVGElement.prototype,{htmlCss:function(a){var b=this.element;if(b=a&&"SPAN"===b.tagName&&a.width)delete a.width,this.textWidth=b,this.updateTransform();a&&"ellipsis"===a.textOverflow&&(a.whiteSpace="nowrap",a.overflow="hidden");this.styles=l(this.styles,a);H(this.element,a);return this},htmlGetBBox:function(){var a=this.element;return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}, +htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,d=this.translateX||0,z=this.translateY||0,h=this.x||0,m=this.y||0,x=this.textAlign||"left",n={left:0,center:.5,right:1}[x],t=this.styles;H(b,{marginLeft:d,marginTop:z});this.shadows&&f(this.shadows,function(a){H(a,{marginLeft:d+1,marginTop:z+1})});this.inverted&&f(b.childNodes,function(c){a.invertChild(c,b)});if("SPAN"===b.tagName){var l=this.rotation,u=e(this.textWidth),q=t&&t.whiteSpace,A=[l,x,b.innerHTML,this.textWidth, +this.textAlign].join();A!==this.cTT&&(t=a.fontMetrics(b.style.fontSize).b,p(l)&&this.setSpanRotation(l,n,t),H(b,{width:"",whiteSpace:q||"nowrap"}),b.offsetWidth>u&&/[ \-]/.test(b.textContent||b.innerText)&&H(b,{width:u+"px",display:"block",whiteSpace:q||"normal"}),this.getSpanCorrection(b.offsetWidth,t,n,l,x));H(b,{left:h+(this.xCorr||0)+"px",top:m+(this.yCorr||0)+"px"});w&&(t=b.offsetHeight);this.cTT=A}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,d){var c={},k=this.renderer.getTransformKey(); +c[k]=c.transform="rotate("+a+"deg)";c[k+(r?"Origin":"-origin")]=c.transformOrigin=100*b+"% "+d+"px";H(this.element,c)},getSpanCorrection:function(a,b,d){this.xCorr=-a*d;this.yCorr=-b}});l(h.prototype,{getTransformKey:function(){return n&&!/Edge/.test(m.navigator.userAgent)?"-ms-transform":w?"-webkit-transform":r?"MozTransform":m.opera?"-o-transform":""},html:function(a,b,k){var c=this.createElement("span"),e=c.element,h=c.renderer,m=h.isSVG,w=function(a,b){f(["opacity","visibility"],function(c){d(a, +c+"Setter",function(a,c,d,k){a.call(this,c,d,k);b[d]=c})})};c.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;this.textStr=a;e.innerHTML=u(a,"");c.htmlUpdateTransform()};m&&w(c,c.element.style);c.xSetter=c.ySetter=c.alignSetter=c.rotationSetter=function(a,b){"align"===b&&(b="textAlign");c[b]=a;c.htmlUpdateTransform()};c.attr({text:a,x:Math.round(b),y:Math.round(k)}).css({fontFamily:this.style.fontFamily,fontSize:this.style.fontSize,position:"absolute"});e.style.whiteSpace="nowrap";c.css= +c.htmlCss;m&&(c.add=function(a){var b,d=h.box.parentNode,k=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)k.push(a),a=a.parentGroup;f(k.reverse(),function(a){function e(g,b){a[b]=g;n?q[h.getTransformKey()]="translate("+(a.x||a.translateX)+"px,"+(a.y||a.translateY)+"px)":"translateX"===b?q.left=g+"px":q.top=g+"px";a.doTransform=!0}var q,g=E(a.element,"class");g&&(g={className:g});b=a.div=a.div||D("div",g,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px",display:a.display, +opacity:a.opacity,pointerEvents:a.styles&&a.styles.pointerEvents},b||d);q=b.style;l(a,{classSetter:function(a){return function(g){this.element.setAttribute("class",g);a.className=g}}(b),on:function(){k[0].div&&c.on.apply({element:k[0].div},arguments);return a},translateXSetter:e,translateYSetter:e});w(a,q)})}}else b=d;b.appendChild(e);c.added=!0;c.alignOnAdd&&c.htmlUpdateTransform();return c});return c}})})(M);(function(a){function E(){var n=a.defaultOptions.global,l=r.moment;if(n.timezone){if(l)return function(a){return-l.tz(a, +n.timezone).utcOffset()};a.error(25)}return n.useUTC&&n.getTimezoneOffset}function D(){var n=a.defaultOptions.global,f,u=n.useUTC,e=u?"getUTC":"get",h=u?"setUTC":"set",m="Minutes Hours Day Date Month FullYear".split(" "),d=m.concat(["Milliseconds","Seconds"]);a.Date=f=n.Date||r.Date;f.hcTimezoneOffset=u&&n.timezoneOffset;f.hcGetTimezoneOffset=E();f.hcHasTimeZone=!(!f.hcTimezoneOffset&&!f.hcGetTimezoneOffset);f.hcMakeTime=function(a,b,d,e,h,m){var c;u?(c=f.UTC.apply(0,arguments),c+=p(c)):c=(new f(a, +b,l(d,1),l(e,0),l(h,0),l(m,0))).getTime();return c};for(n=0;nb&&e-k*zm&&(p=Math.round((h-e)/Math.cos(b*r)));else if(h=e+(1-k)*z,e-k*zm&&(I=m-a.x+I*k,x=-1),I=Math.min(B,I),II||f.autoRotation&&(c.styles||{}).width)p=I;p&&(t.width=p,(n.style||{}).textOverflow||(t.textOverflow="ellipsis"),c.css(t))},getPosition:function(a,f,l,e){var h=this.axis,m=h.chart,d=e&&m.oldChartHeight||m.chartHeight;return{x:a?h.translate(f+l,null,null,e)+h.transB:h.left+h.offset+(h.opposite?(e&&m.oldChartWidth||m.chartWidth)-h.right-h.left:0),y:a?d-h.bottom+h.offset-(h.opposite?h.height:0):d-h.translate(f+l,null,null,e)-h.transB}},getLabelPosition:function(a, +f,l,e,h,m,d,c){var b=this.axis,k=b.transA,z=b.reversed,B=b.staggerLines,n=b.tickRotCorr||{x:0,y:0},x=h.y,u=e||b.reserveSpaceDefault?0:-b.labelOffset*("center"===b.labelAlign?.5:1);D(x)||(x=0===b.side?l.rotation?-8:-l.getBBox().height:2===b.side?n.y+8:Math.cos(l.rotation*r)*(n.y-l.getBBox(!1,0).height/2));a=a+h.x+u+n.x-(m&&e?m*k*(z?-1:1):0);f=f+x-(m&&!e?m*k*(z?1:-1):0);B&&(l=d/(c||1)%B,b.opposite&&(l=B-l-1),f+=b.labelOffset/B*l);return{x:a,y:Math.round(f)}},getMarkPath:function(a,f,l,e,h,m){return m.crispLine(["M", +a,f,"L",a+(h?0:-l),f+(h?l:0)],e)},renderGridLine:function(a,f,l){var e=this.axis,h=e.options,m=this.gridLine,d={},c=this.pos,b=this.type,k=e.tickmarkOffset,z=e.chart.renderer,B=b?b+"Grid":"grid",n=h[B+"LineWidth"],x=h[B+"LineColor"],h=h[B+"LineDashStyle"];m||(d.stroke=x,d["stroke-width"]=n,h&&(d.dashstyle=h),b||(d.zIndex=1),a&&(d.opacity=0),this.gridLine=m=z.path().attr(d).addClass("highcharts-"+(b?b+"-":"")+"grid-line").add(e.gridGroup));if(!a&&m&&(a=e.getPlotLinePath(c+k,m.strokeWidth()*l,a,!0)))m[this.isNew? +"attr":"animate"]({d:a,opacity:f})},renderMark:function(a,f,u){var e=this.axis,h=e.options,m=e.chart.renderer,d=this.type,c=d?d+"Tick":"tick",b=e.tickSize(c),k=this.mark,z=!k,B=a.x;a=a.y;var n=l(h[c+"Width"],!d&&e.isXAxis?1:0),h=h[c+"Color"];b&&(e.opposite&&(b[0]=-b[0]),z&&(this.mark=k=m.path().addClass("highcharts-"+(d?d+"-":"")+"tick").add(e.axisGroup),k.attr({stroke:h,"stroke-width":n})),k[z?"attr":"animate"]({d:this.getMarkPath(B,a,b[0],k.strokeWidth()*u,e.horiz,m),opacity:f}))},renderLabel:function(a, +f,u,e){var h=this.axis,m=h.horiz,d=h.options,c=this.label,b=d.labels,k=b.step,h=h.tickmarkOffset,z=!0,B=a.x;a=a.y;c&&p(B)&&(c.xy=a=this.getLabelPosition(B,a,c,m,b,h,e,k),this.isFirst&&!this.isLast&&!l(d.showFirstLabel,1)||this.isLast&&!this.isFirst&&!l(d.showLastLabel,1)?z=!1:!m||b.step||b.rotation||f||0===u||this.handleOverflow(a),k&&e%k&&(z=!1),z&&p(a.y)?(a.opacity=u,c[this.isNewLabel?"attr":"animate"](a),this.isNewLabel=!1):(c.attr("y",-9999),this.isNewLabel=!0))},render:function(a,f,u){var e= +this.axis,h=e.horiz,m=this.getPosition(h,this.pos,e.tickmarkOffset,f),d=m.x,c=m.y,e=h&&d===e.pos+e.len||!h&&c===e.pos?-1:1;u=l(u,1);this.isActive=!0;this.renderGridLine(f,u,e);this.renderMark(m,u,e);this.renderLabel(m,f,u,a);this.isNew=!1},destroy:function(){H(this,this.axis)}}})(M);var V=function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.color,l=a.correctFloat,r=a.defaultOptions,n=a.defined,w=a.deg2rad,u=a.destroyObjectProperties,e=a.each,h=a.extend,m=a.fireEvent,d=a.format, +c=a.getMagnitude,b=a.grep,k=a.inArray,z=a.isArray,B=a.isNumber,I=a.isString,x=a.merge,K=a.normalizeTickInterval,t=a.objectEach,C=a.pick,N=a.removeEvent,q=a.splat,A=a.syncTimeout,F=a.Tick,G=function(){this.init.apply(this,arguments)};a.extend(G.prototype,{defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,labels:{enabled:!0,style:{color:"#666666",cursor:"default",fontSize:"11px"}, +x:0},maxPadding:.01,minorTickLength:2,minorTickPosition:"outside",minPadding:.01,startOfWeek:1,startOnTick:!1,tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",title:{align:"middle",style:{color:"#666666"}},type:"linear",minorGridLineColor:"#f2f2f2",minorGridLineWidth:1,minorTickColor:"#999999",lineColor:"#ccd6eb",lineWidth:1,gridLineColor:"#e6e6e6",tickColor:"#ccd6eb"},defaultYAxisOptions:{endOnTick:!0,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8},maxPadding:.05, +minPadding:.05,startOnTick:!0,title:{rotation:270,text:"Values"},stackLabels:{allowOverlap:!1,enabled:!1,formatter:function(){return a.numberFormat(this.total,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"#000000",textOutline:"1px contrast"}},gridLineWidth:1,lineWidth:0},defaultLeftAxisOptions:{labels:{x:-15},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45], +x:0},title:{rotation:0}},init:function(a,b){var g=b.isX,v=this;v.chart=a;v.horiz=a.inverted&&!v.isZAxis?!g:g;v.isXAxis=g;v.coll=v.coll||(g?"xAxis":"yAxis");v.opposite=b.opposite;v.side=b.side||(v.horiz?v.opposite?0:2:v.opposite?1:3);v.setOptions(b);var c=this.options,d=c.type;v.labelFormatter=c.labels.formatter||v.defaultLabelFormatter;v.userOptions=b;v.minPixelPadding=0;v.reversed=c.reversed;v.visible=!1!==c.visible;v.zoomEnabled=!1!==c.zoomEnabled;v.hasNames="category"===d||!0===c.categories;v.categories= +c.categories||v.hasNames;v.names=v.names||[];v.plotLinesAndBandsGroups={};v.isLog="logarithmic"===d;v.isDatetimeAxis="datetime"===d;v.positiveValuesOnly=v.isLog&&!v.allowNegativeLog;v.isLinked=n(c.linkedTo);v.ticks={};v.labelEdge=[];v.minorTicks={};v.plotLinesAndBands=[];v.alternateBands={};v.len=0;v.minRange=v.userMinRange=c.minRange||c.maxZoom;v.range=c.range;v.offset=c.offset||0;v.stacks={};v.oldStacks={};v.stacksTouched=0;v.max=null;v.min=null;v.crosshair=C(c.crosshair,q(a.options.tooltip.crosshairs)[g? +0:1],!1);b=v.options.events;-1===k(v,a.axes)&&(g?a.axes.splice(a.xAxis.length,0,v):a.axes.push(v),a[v.coll].push(v));v.series=v.series||[];a.inverted&&!v.isZAxis&&g&&void 0===v.reversed&&(v.reversed=!0);t(b,function(a,g){E(v,g,a)});v.lin2log=c.linearToLogConverter||v.lin2log;v.isLog&&(v.val2lin=v.log2lin,v.lin2val=v.lin2log)},setOptions:function(a){this.options=x(this.defaultOptions,"yAxis"===this.coll&&this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions, +this.defaultLeftAxisOptions][this.side],x(r[this.coll],a))},defaultLabelFormatter:function(){var g=this.axis,b=this.value,c=g.categories,k=this.dateTimeLabelFormat,e=r.lang,q=e.numericSymbols,e=e.numericSymbolMagnitude||1E3,h=q&&q.length,m,z=g.options.labels.format,g=g.isLog?Math.abs(b):g.tickInterval;if(z)m=d(z,this);else if(c)m=b;else if(k)m=a.dateFormat(k,b);else if(h&&1E3<=g)for(;h--&&void 0===m;)c=Math.pow(e,h+1),g>=c&&0===10*b%c&&null!==q[h]&&0!==b&&(m=a.numberFormat(b/c,-1)+q[h]);void 0=== +m&&(m=1E4<=Math.abs(b)?a.numberFormat(b,-1):a.numberFormat(b,-1,void 0,""));return m},getSeriesExtremes:function(){var a=this,v=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.threshold=null;a.softThreshold=!a.isXAxis;a.buildStacks&&a.buildStacks();e(a.series,function(g){if(g.visible||!v.options.chart.ignoreHiddenSeries){var c=g.options,d=c.threshold,k;a.hasVisibleSeries=!0;a.positiveValuesOnly&&0>=d&&(d=null);if(a.isXAxis)c=g.xData,c.length&&(g=p(c),k=H(c),B(g)||g instanceof Date||(c=b(c,B), +g=p(c)),a.dataMin=Math.min(C(a.dataMin,c[0],g),g),a.dataMax=Math.max(C(a.dataMax,c[0],k),k));else if(g.getExtremes(),k=g.dataMax,g=g.dataMin,n(g)&&n(k)&&(a.dataMin=Math.min(C(a.dataMin,g),g),a.dataMax=Math.max(C(a.dataMax,k),k)),n(d)&&(a.threshold=d),!c.softThreshold||a.positiveValuesOnly)a.softThreshold=!1}})},translate:function(a,b,c,d,k,e){var g=this.linkedParent||this,v=1,q=0,h=d?g.oldTransA:g.transA;d=d?g.oldMin:g.min;var m=g.minPixelPadding;k=(g.isOrdinal||g.isBroken||g.isLog&&k)&&g.lin2val; +h||(h=g.transA);c&&(v*=-1,q=g.len);g.reversed&&(v*=-1,q-=v*(g.sector||g.len));b?(a=(a*v+q-m)/h+d,k&&(a=g.lin2val(a))):(k&&(a=g.val2lin(a)),a=B(d)?v*(a-d)*h+q+v*m+(B(e)?h*e:0):void 0);return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d,k){var g=this.chart,v=this.left,q=this.top,e,h,m=c&&g.oldChartHeight||g.chartHeight,z=c&&g.oldChartWidth|| +g.chartWidth,A;e=this.transB;var t=function(a,g,b){if(ab)d?a=Math.min(Math.max(g,a),b):A=!0;return a};k=C(k,this.translate(a,null,null,c));a=c=Math.round(k+e);e=h=Math.round(m-k-e);B(k)?this.horiz?(e=q,h=m-this.bottom,a=c=t(a,v,v+this.width)):(a=v,c=z-this.right,e=h=t(e,q,q+this.height)):(A=!0,d=!1);return A&&!d?null:g.renderer.crispLine(["M",a,e,"L",c,h],b||1)},getLinearTickPositions:function(a,b,c){var g,v=l(Math.floor(b/a)*a);c=l(Math.ceil(c/a)*a);var d=[],k;l(v+a)===v&&(k=20);if(this.single)return[b]; +for(b=v;b<=c;){d.push(b);b=l(b+a,k);if(b===g)break;g=b}return d},getMinorTickInterval:function(){var a=this.options;return!0===a.minorTicks?C(a.minorTickInterval,"auto"):!1===a.minorTicks?null:a.minorTickInterval},getMinorTickPositions:function(){var a=this,b=a.options,c=a.tickPositions,d=a.minorTickInterval,k=[],q=a.pointRangePadding||0,h=a.min-q,q=a.max+q,m=q-h;if(m&&m/d=this.minRange,t=this.minRange,d=(t-c+b)/2,d=[b-d,C(a.min,b-d)],k&&(d[2]=this.isLog?this.log2lin(this.dataMin):this.dataMin),b=H(d),c=[b+t,C(a.max,b+t)],k&&(c[2]=this.isLog?this.log2lin(this.dataMax):this.dataMax),c=p(c),c-b=p?(r=p,f=0):b.dataMax<=p&&(w=p,x=0)),b.min= +C(N,r,b.dataMin),b.max=C(D,w,b.dataMax));q&&(b.positiveValuesOnly&&!g&&0>=Math.min(b.min,C(b.dataMin,b.min))&&a.error(10,1),b.min=l(h(b.min),15),b.max=l(h(b.max),15));b.range&&n(b.max)&&(b.userMin=b.min=N=Math.max(b.dataMin,b.minFromRange()),b.userMax=D=b.max,b.range=null);m(b,"foundExtremes");b.beforePadding&&b.beforePadding();b.adjustForMinRange();!(G||b.axisPointRange||b.usePercentage||t)&&n(b.min)&&n(b.max)&&(h=b.max-b.min)&&(!n(N)&&f&&(b.min-=h*f),!n(D)&&x&&(b.max+=h*x));B(k.softMin)&&!B(b.userMin)&& +(b.min=Math.min(b.min,k.softMin));B(k.softMax)&&!B(b.userMax)&&(b.max=Math.max(b.max,k.softMax));B(k.floor)&&(b.min=Math.max(b.min,k.floor));B(k.ceiling)&&(b.max=Math.min(b.max,k.ceiling));I&&n(b.dataMin)&&(p=p||0,!n(N)&&b.min=p?b.min=p:!n(D)&&b.max>p&&b.dataMax<=p&&(b.max=p));b.tickInterval=b.min===b.max||void 0===b.min||void 0===b.max?1:t&&!F&&u===b.linkedParent.options.tickPixelInterval?F=b.linkedParent.tickInterval:C(F,this.tickAmount?(b.max-b.min)/Math.max(this.tickAmount-1,1): +void 0,G?1:(b.max-b.min)*u/Math.max(b.len,u));A&&!g&&e(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();b.postProcessTickInterval&&(b.tickInterval=b.postProcessTickInterval(b.tickInterval));b.pointRange&&!F&&(b.tickInterval=Math.max(b.pointRange,b.tickInterval));g=C(k.minTickInterval,b.isDatetimeAxis&&b.closestPointRange);!F&&b.tickIntervalb.tickInterval&&1E3b.max)),!!this.tickAmount));this.tickAmount||(b.tickInterval=b.unsquish());this.setTickPositions()},setTickPositions:function(){var a=this.options,b,c=a.tickPositions;b=this.getMinorTickInterval();var d=a.tickPositioner,k=a.startOnTick,q=a.endOnTick;this.tickmarkOffset=this.categories&&"between"===a.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===b&&this.tickInterval?this.tickInterval/ +5:b;this.single=this.min===this.max&&n(this.min)&&!this.tickAmount&&(parseInt(this.min,10)===this.min||!1!==a.allowDecimals);this.tickPositions=b=c&&c.slice();!b&&(b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),b.length>this.len&&(b= +[b[0],b.pop()],b[0]===b[1]&&(b.length=1)),this.tickPositions=b,d&&(d=d.apply(this,[this.min,this.max])))&&(this.tickPositions=b=d);this.paddedTicks=b.slice(0);this.trimTicks(b,k,q);this.isLinked||(this.single&&2>b.length&&(this.min-=.5,this.max+=.5),c||d||this.adjustTickAmount())},trimTicks:function(a,b,c){var g=a[0],d=a[a.length-1],k=this.minPointOffset||0;if(!this.isLinked){if(b&&-Infinity!==g)this.min=g;else for(;this.min-k>a[0];)a.shift();if(c)this.max=d;else for(;this.max+kb&&(this.finalTickAmt=b,b=5);this.tickAmount=b},adjustTickAmount:function(){var a=this.tickInterval,b=this.tickPositions,c=this.tickAmount,d=this.finalTickAmt,k=b&&b.length,q=C(this.threshold,this.softThreshold?0:null);if(this.hasData()){if(kc&&(this.tickInterval*= +2,this.setTickPositions());if(n(d)){for(a=c=b.length;a--;)(3===d&&1===a%2||2>=d&&0d&&(a=d)),n(c)&&(bd&&(b=d))),this.displayBtn=void 0!==a||void 0!==b,this.setExtremes(a,b,!1,void 0,{trigger:"zoom"});return!0},setAxisSize:function(){var b=this.chart,c=this.options,d=c.offsets||[0,0,0,0],k=this.horiz,q=this.width=Math.round(a.relativeLength(C(c.width,b.plotWidth-d[3]+d[1]),b.plotWidth)),e=this.height=Math.round(a.relativeLength(C(c.height, +b.plotHeight-d[0]+d[2]),b.plotHeight)),h=this.top=Math.round(a.relativeLength(C(c.top,b.plotTop+d[0]),b.plotHeight,b.plotTop)),c=this.left=Math.round(a.relativeLength(C(c.left,b.plotLeft+d[3]),b.plotWidth,b.plotLeft));this.bottom=b.chartHeight-e-h;this.right=b.chartWidth-q-c;this.len=Math.max(k?q:e,0);this.pos=k?c:h},getExtremes:function(){var a=this.isLog,b=this.lin2log;return{min:a?l(b(this.min)):this.min,max:a?l(b(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin, +userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,g=this.lin2log,c=b?g(this.min):this.min,b=b?g(this.max):this.max;null===a?a=c:c>a?a=c:ba?"right":195a?"left":"center"},tickSize:function(a){var b=this.options,g=b[a+"Length"],c=C(b[a+"Width"],"tick"===a&&this.isXAxis?1:0);if(c&&g)return"inside"===b[a+"Position"]&&(g=-g),[g,c]},labelMetrics:function(){var a= +this.tickPositions&&this.tickPositions[0]||0;return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize,this.ticks[a]&&this.ticks[a].label)},unsquish:function(){var a=this.options.labels,b=this.horiz,c=this.tickInterval,d=c,k=this.len/(((this.categories?1:0)+this.max-this.min)/c),q,h=a.rotation,m=this.labelMetrics(),z,A=Number.MAX_VALUE,t,x=function(a){a/=k||1;a=1=a)z=x(Math.abs(m.h/Math.sin(w*a))),b=z+Math.abs(a/360),b(c.step||0)&&!c.rotation&&(this.staggerLines||1)*this.len/d||!b&&(c.style&&parseInt(c.style.width,10)||k&&k-a.spacing[3]|| +.33*a.chartWidth)},renderUnsquish:function(){var a=this.chart,b=a.renderer,c=this.tickPositions,d=this.ticks,k=this.options.labels,q=this.horiz,h=this.getSlotWidth(),m=Math.max(1,Math.round(h-2*(k.padding||5))),z={},A=this.labelMetrics(),t=k.style&&k.style.textOverflow,f,F=0,l,B;I(k.rotation)||(z.rotation=k.rotation||0);e(c,function(a){(a=d[a])&&a.labelLength>F&&(F=a.labelLength)});this.maxLabelLength=F;if(this.autoRotation)F>m&&F>A.h?z.rotation=this.labelRotation:this.labelRotation=0;else if(h&& +(f={width:m+"px"},!t))for(f.textOverflow="clip",l=c.length;!q&&l--;)if(B=c[l],m=d[B].label)m.styles&&"ellipsis"===m.styles.textOverflow?m.css({textOverflow:"clip"}):d[B].labelLength>h&&m.css({width:h+"px"}),m.getBBox().height>this.len/c.length-(A.h-A.f)&&(m.specCss={textOverflow:"ellipsis"});z.rotation&&(f={width:(F>.5*a.chartHeight?.33*a.chartHeight:a.chartHeight)+"px"},t||(f.textOverflow="ellipsis"));if(this.labelAlign=k.align||this.autoLabelAlign(this.labelRotation))z.align=this.labelAlign;e(c, +function(a){var b=(a=d[a])&&a.label;b&&(b.attr(z),f&&b.css(x(f,b.specCss)),delete b.specCss,a.rotation=z.rotation)});this.tickRotCorr=b.rotCorr(A.b,this.labelRotation||0,0!==this.side)},hasData:function(){return this.hasVisibleSeries||n(this.min)&&n(this.max)&&this.tickPositions&&0=this.min&&a<=this.max)g[a]||(g[a]=new F(this,a)),d&&g[a].isNew&&g[a].render(b,!0,.1),g[a].render(b)},render:function(){var b= +this,c=b.chart,d=b.options,k=b.isLog,q=b.lin2log,h=b.isLinked,m=b.tickPositions,z=b.axisTitle,x=b.ticks,f=b.minorTicks,l=b.alternateBands,C=d.stackLabels,n=d.alternateGridColor,u=b.tickmarkOffset,G=b.axisLine,p=b.showAxis,I=D(c.renderer.globalAnimation),r,w;b.labelEdge.length=0;b.overlap=!1;e([x,f,l],function(a){t(a,function(a){a.isActive=!1})});if(b.hasData()||h)b.minorTickInterval&&!b.categories&&e(b.getMinorTickPositions(),function(a){b.renderMinorTick(a)}),m.length&&(e(m,function(a,c){b.renderTick(a, +c)}),u&&(0===b.min||b.single)&&(x[-1]||(x[-1]=new F(b,-1,null,!0)),x[-1].render(-1))),n&&e(m,function(d,g){w=void 0!==m[g+1]?m[g+1]+u:b.max-u;0===g%2&&d=h.second?0:C*Math.floor(x.getMilliseconds()/C));if(t>=h.second)x[D.hcSetSeconds](t>=h.minute? +0:C*Math.floor(x.getSeconds()/C));if(t>=h.minute)x[D.hcSetMinutes](t>=h.hour?0:C*Math.floor(x[D.hcGetMinutes]()/C));if(t>=h.hour)x[D.hcSetHours](t>=h.day?0:C*Math.floor(x[D.hcGetHours]()/C));if(t>=h.day)x[D.hcSetDate](t>=h.month?1:C*Math.floor(x[D.hcGetDate]()/C));t>=h.month&&(x[D.hcSetMonth](t>=h.year?0:C*Math.floor(x[D.hcGetMonth]()/C)),n=x[D.hcGetFullYear]());if(t>=h.year)x[D.hcSetFullYear](n-n%C);if(t===h.week)x[D.hcSetDate](x[D.hcGetDate]()-x[D.hcGetDay]()+e(b,1));n=x[D.hcGetFullYear]();b=x[D.hcGetMonth](); +var A=x[D.hcGetDate](),F=x[D.hcGetHours]();d=x.getTime();D.hcHasTimeZone&&(q=(!B||!!D.hcGetTimezoneOffset)&&(c-d>4*h.month||w(d)!==w(c)),N=w(x),x=new D(d+N));B=x.getTime();for(d=1;Bk.length&&l(k,function(a){0===a%18E5&&"000000000"===H("%H%M%S%L",a)&&(m[a]="day")})}k.info=r(a,{higherRanks:m,totalRange:t*C});return k}; +E.prototype.normalizeTimeTickInterval=function(a,d){var c=d||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2,3,4,6]],["year",null]];d=c[c.length-1];var b=h[d[0]],k=d[1],e;for(e=0;er&&(!w||z<=n)&&void 0!==z&&d.push(z),z>n&& +(B=!0),z=k;else r=h(r),n=h(n),a=w?this.getMinorTickInterval():l.tickInterval,a=f("auto"===a?null:a,this._minorAutoInterval,l.tickPixelInterval/(w?5:1)*(n-r)/((w?e/this.tickPositions.length:e)||1)),a=p(a,null,D(a)),d=H(this.getLinearTickPositions(a,r,n),m),w||(this._minorAutoInterval=a/5);w||(this.tickInterval=a);return d};E.prototype.log2lin=function(a){return Math.log(a)/Math.LN10};E.prototype.lin2log=function(a){return Math.pow(10,a)}})(M);(function(a,E){var D=a.arrayMax,H=a.arrayMin,p=a.defined, +f=a.destroyObjectProperties,l=a.each,r=a.erase,n=a.merge,w=a.pick;a.PlotLineOrBand=function(a,e){this.axis=a;e&&(this.options=e,this.id=e.id)};a.PlotLineOrBand.prototype={render:function(){var f=this,e=f.axis,h=e.horiz,m=f.options,d=m.label,c=f.label,b=m.to,k=m.from,z=m.value,l=p(k)&&p(b),r=p(z),x=f.svgElem,K=!x,t=[],C=m.color,N=w(m.zIndex,0),q=m.events,t={"class":"highcharts-plot-"+(l?"band ":"line ")+(m.className||"")},A={},F=e.chart.renderer,G=l?"bands":"lines",g=e.log2lin;e.isLog&&(k=g(k),b=g(b), +z=g(z));r?(t={stroke:C,"stroke-width":m.width},m.dashStyle&&(t.dashstyle=m.dashStyle)):l&&(C&&(t.fill=C),m.borderWidth&&(t.stroke=m.borderColor,t["stroke-width"]=m.borderWidth));A.zIndex=N;G+="-"+N;(C=e.plotLinesAndBandsGroups[G])||(e.plotLinesAndBandsGroups[G]=C=F.g("plot-"+G).attr(A).add());K&&(f.svgElem=x=F.path().attr(t).add(C));if(r)t=e.getPlotLinePath(z,x.strokeWidth());else if(l)t=e.getPlotBandPath(k,b,m);else return;K&&t&&t.length?(x.attr({d:t}),q&&a.objectEach(q,function(a,b){x.on(b,function(a){q[b].apply(f, +[a])})})):x&&(t?(x.show(),x.animate({d:t})):(x.hide(),c&&(f.label=c=c.destroy())));d&&p(d.text)&&t&&t.length&&0this.max&& +e>this.max;if(m&&h)for(a&&(k=m.toString()===h.toString(),b=0),a=0;aA-h?A:A-h);else if(z)k[a]=Math.max(e,g+h+d>c?g:g+h);else return!1},C=function(a,c,d,g){var e;gc-b?e=!1:k[a]=gc-d/2?c-d-2:g-d/2;return e},p=function(a){var b=f;f=x;x=b;m=a},q=function(){!1!==t.apply(0,f)?!1!==C.apply(0,x)||m||(p(!0),q()):m?k.x=k.y=0:(p(!0),q())};(c.inverted||1q&&(h=!1);a=(e.series&& +e.series.yAxis&&e.series.yAxis.pos)+(e.plotY||0);a-=b.plotTop;c.push({target:e.isHeader?b.plotHeight+l:a,rank:e.isHeader?1:0,size:z.tt.getBBox().height+1,point:e,x:q,tt:t})}});this.cleanSplit();a.distribute(c,b.plotHeight+l);D(c,function(a){var c=a.point,d=c.series;a.tt.attr({visibility:void 0===a.pos?"hidden":"inherit",x:h||c.isHeader?a.x:c.plotX+b.plotLeft+n(f.distance,16),y:a.pos+b.plotTop,anchorX:c.isHeader?c.plotX+b.plotLeft:c.plotX+d.xAxis.pos,anchorY:c.isHeader?a.pos+b.plotTop-15:c.plotY+d.yAxis.pos})})}, +updatePosition:function(a){var e=this.chart,d=this.getLabel(),d=(this.options.positioner||this.getPosition).call(this,d.width,d.height,a);this.move(Math.round(d.x),Math.round(d.y||0),a.plotX+e.plotLeft,a.plotY+e.plotTop)},getDateFormat:function(a,m,d,c){var b=E("%m-%d %H:%M:%S.%L",m),k,h,f={millisecond:15,second:12,minute:9,hour:6,day:3},l="millisecond";for(h in e){if(a===e.week&&+E("%w",m)===d&&"00:00:00.000"===b.substr(6)){h="week";break}if(e[h]>a){h=l;break}if(f[h]&&b.substr(f[h])!=="01-01 00:00:00.000".substr(f[h]))break; +"week"!==h&&(l=h)}h&&(k=c[h]);return k},getXDateFormat:function(a,e,d){e=e.dateTimeLabelFormats;var c=d&&d.closestPointRange;return(c?this.getDateFormat(c,a.x,d.options.startOfWeek,e):e.day)||e.year},tooltipFooterHeaderFormatter:function(a,e){e=e?"footer":"header";var d=a.series,c=d.tooltipOptions,b=c.xDateFormat,k=d.xAxis,h=k&&"datetime"===k.options.type&&f(a.key),m=c[e+"Format"];h&&!b&&(b=this.getXDateFormat(a,c,k));h&&b&&D(a.point&&a.point.tooltipDateKeys||["key"],function(a){m=m.replace("{point."+ +a+"}","{point."+a+":"+b+"}")});return p(m,{point:a,series:d})},bodyFormatter:function(a){return l(a,function(a){var d=a.series.tooltipOptions;return(d[(a.point.formatPrefix||"point")+"Formatter"]||a.point.tooltipFormatter).call(a.point,d[(a.point.formatPrefix||"point")+"Format"])})}}})(M);(function(a){var E=a.addEvent,D=a.attr,H=a.charts,p=a.color,f=a.css,l=a.defined,r=a.each,n=a.extend,w=a.find,u=a.fireEvent,e=a.isObject,h=a.offset,m=a.pick,d=a.splat,c=a.Tooltip;a.Pointer=function(a,c){this.init(a, +c)};a.Pointer.prototype={init:function(a,d){this.options=d;this.chart=a;this.runChartClick=d.chart.events&&!!d.chart.events.click;this.pinchDown=[];this.lastValidTouch={};c&&(a.tooltip=new c(a,d.tooltip),this.followTouchMove=m(d.tooltip.followTouchMove,!0));this.setDOMEvents()},zoomOption:function(a){var b=this.chart,c=b.options.chart,d=c.zoomType||"",b=b.inverted;/touch/.test(a.type)&&(d=m(c.pinchType,d));this.zoomX=a=/x/.test(d);this.zoomY=d=/y/.test(d);this.zoomHor=a&&!b||d&&b;this.zoomVert=d&& +!b||a&&b;this.hasZoom=a||d},normalize:function(a,c){var b;b=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:a;c||(this.chartPosition=c=h(this.chart.container));return n(a,{chartX:Math.round(b.pageX-c.left),chartY:Math.round(b.pageY-c.top)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};r(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},findNearestKDPoint:function(a,c,d){var b;r(a,function(a){var k= +!(a.noSharedTooltip&&c)&&0>a.options.findNearestPointBy.indexOf("y");a=a.searchPoint(d,k);if((k=e(a,!0))&&!(k=!e(b,!0)))var k=b.distX-a.distX,h=b.dist-a.dist,m=(a.series.group&&a.series.group.zIndex)-(b.series.group&&b.series.group.zIndex),k=0<(0!==k&&c?k:0!==h?h:0!==m?m:b.series.index>a.series.index?-1:1);k&&(b=a)});return b},getPointFromEvent:function(a){a=a.target;for(var b;a&&!b;)b=a.point,a=a.parentNode;return b},getChartCoordinatesFromPoint:function(a,c){var b=a.series,d=b.xAxis,b=b.yAxis,k= +m(a.clientX,a.plotX);if(d&&b)return c?{chartX:d.len+d.pos-k,chartY:b.len+b.pos-a.plotY}:{chartX:k+d.pos,chartY:a.plotY+b.pos}},getHoverData:function(b,c,d,h,f,l,n){var k,z=[],x=n&&n.isBoosting;h=!(!h||!b);n=c&&!c.stickyTracking?[c]:a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking,!0)&&a.stickyTracking});c=(k=h?b:this.findNearestKDPoint(n,f,l))&&k.series;k&&(f&&!c.noSharedTooltip?(n=a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking, +!0)&&!a.noSharedTooltip}),r(n,function(a){var b=w(a.points,function(a){return a.x===k.x&&!a.isNull});e(b)&&(x&&(b=a.getPoint(b)),z.push(b))})):z.push(k));return{hoverPoint:k,hoverSeries:c,hoverPoints:z}},runPointActions:function(b,c){var d=this.chart,k=d.tooltip&&d.tooltip.options.enabled?d.tooltip:void 0,e=k?k.shared:!1,h=c||d.hoverPoint,f=h&&h.series||d.hoverSeries,f=this.getHoverData(h,f,d.series,!!c||f&&f.directTouch&&this.isDirectTouch,e,b,{isBoosting:d.isBoosting}),l,h=f.hoverPoint;l=f.hoverPoints; +c=(f=f.hoverSeries)&&f.tooltipOptions.followPointer;e=e&&f&&!f.noSharedTooltip;if(h&&(h!==d.hoverPoint||k&&k.isHidden)){r(d.hoverPoints||[],function(b){-1===a.inArray(b,l)&&b.setState()});r(l||[],function(a){a.setState("hover")});if(d.hoverSeries!==f)f.onMouseOver();d.hoverPoint&&d.hoverPoint.firePointEvent("mouseOut");if(!h.series)return;h.firePointEvent("mouseOver");d.hoverPoints=l;d.hoverPoint=h;k&&k.refresh(e?l:h,b)}else c&&k&&!k.isHidden&&(h=k.getAnchor([{}],b),k.updatePosition({plotX:h[0],plotY:h[1]})); +this.unDocMouseMove||(this.unDocMouseMove=E(d.container.ownerDocument,"mousemove",function(b){var c=H[a.hoverChartIndex];if(c)c.pointer.onDocumentMouseMove(b)}));r(d.axes,function(c){var d=m(c.crosshair.snap,!0),k=d?a.find(l,function(a){return a.series[c.coll]===c}):void 0;k||!d?c.drawCrosshair(b,k):c.hideCrosshair()})},reset:function(a,c){var b=this.chart,k=b.hoverSeries,e=b.hoverPoint,h=b.hoverPoints,m=b.tooltip,f=m&&m.shared?h:e;a&&f&&r(d(f),function(b){b.series.isCartesian&&void 0===b.plotX&& +(a=!1)});if(a)m&&f&&(m.refresh(f),e&&(e.setState(e.state,!0),r(b.axes,function(a){a.crosshair&&a.drawCrosshair(null,e)})));else{if(e)e.onMouseOut();h&&r(h,function(a){a.setState()});if(k)k.onMouseOut();m&&m.hide(c);this.unDocMouseMove&&(this.unDocMouseMove=this.unDocMouseMove());r(b.axes,function(a){a.hideCrosshair()});this.hoverX=b.hoverPoints=b.hoverPoint=null}},scaleGroups:function(a,c){var b=this.chart,d;r(b.series,function(k){d=a||k.getPlotBox();k.xAxis&&k.xAxis.zoomEnabled&&k.group&&(k.group.attr(d), +k.markerGroup&&(k.markerGroup.attr(d),k.markerGroup.clip(c?b.clipRect:null)),k.dataLabelsGroup&&k.dataLabelsGroup.attr(d))});b.clipRect.attr(c||b.clipBox)},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,h=this.zoomHor,m=this.zoomVert,f=b.plotLeft,l=b.plotTop,n=b.plotWidth,q=b.plotHeight,A,F=this.selectionMarker,G=this.mouseDownX, +g=this.mouseDownY,v=c.panKey&&a[c.panKey+"Key"];F&&F.touch||(df+n&&(d=f+n),el+q&&(e=l+q),this.hasDragged=Math.sqrt(Math.pow(G-d,2)+Math.pow(g-e,2)),10u.max&&(f=u.max-x,v=!0);v?(F-=.8*(F-m[b][0]),q||(g-=.8*(g-m[b][1])),l()):m[b]=[F,g];C||(h[b]=w-r,h[n]=x);h=C?1/t:t;e[n]=x;e[b]=f;p[C?a?"scaleY":"scaleX":"scale"+k]=t;p["translate"+k]=h*r+(F-h*A)},pinch:function(a){var n=this,r=n.chart,u=n.pinchDown,e=a.touches,h=e.length,m=n.lastValidTouch, +d=n.hasZoom,c=n.selectionMarker,b={},k=1===h&&(n.inClass(a.target,"highcharts-tracker")&&r.runTrackerClick||n.runChartClick),z={};1c-6&&h(q||c.spacingBox.width-2*t-d.x)&&(this.itemX=t,this.itemY+=F+this.lastLineHeight+A,this.lastLineHeight=0);this.maxItemWidth=Math.max(this.maxItemWidth,m);this.lastItemY=F+this.itemY+A;this.lastLineHeight=Math.max(b,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=m:(this.itemY+=F+b+A,this.lastLineHeight=b);this.offsetWidth=q||Math.max((e?this.itemX-t-(a.checkbox?0:p):m)+t,this.offsetWidth)}, +getAllItems:function(){var a=[];f(this.chart.series,function(c){var b=c&&c.options;c&&w(b.showInLegend,p(b.linkedTo)?!1:void 0,!0)&&(a=a.concat(c.legendItems||("point"===b.legendType?c.data:c)))});return a},getAlignment:function(){var a=this.options;return a.floating?"":a.align.charAt(0)+a.verticalAlign.charAt(0)+a.layout.charAt(0)},adjustMargins:function(a,c){var b=this.chart,d=this.options,e=this.getAlignment();e&&f([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(k,h){k.test(e)&& +!p(a[h])&&(b[r[h]]=Math.max(b[r[h]],b.legend[(h+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][h]*d[h%2?"x":"y"]+w(d.margin,12)+c[h]+(0===h?b.titleOffset+b.options.title.margin:0)))})},render:function(){var a=this,c=a.chart,b=c.renderer,k=a.group,h,m,l,x,p=a.box,t=a.options,C=a.padding;a.itemX=C;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;k||(a.group=k=b.g("legend").attr({zIndex:7}).add(),a.contentGroup=b.g().attr({zIndex:1}).add(k),a.scrollGroup=b.g().add(a.contentGroup));a.renderTitle(); +h=a.getAllItems();e(h,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});t.reversed&&h.reverse();a.allItems=h;a.display=m=!!h.length;a.lastLineHeight=0;f(h,function(b){a.renderItem(b)});l=(t.width||a.offsetWidth)+C;x=a.lastItemY+a.lastLineHeight+a.titleHeight;x=a.handleOverflow(x);x+=C;p||(a.box=p=b.rect().addClass("highcharts-legend-box").attr({r:t.borderRadius}).add(k),p.isNew=!0);p.attr({stroke:t.borderColor,"stroke-width":t.borderWidth||0,fill:t.backgroundColor|| +"none"}).shadow(t.shadow);0b&&!1!==t.enabled?(this.clipHeight=l=Math.max(b-20-this.titleHeight-m,0),this.currentPage=w(this.currentPage,1),this.fullHeight=a,f(G,function(a,b){var c=a._legendItemPos[1],d=Math.round(a.legendItem.getBBox().height),g=A.length;if(!g||c-A[g-1]>l&&(F||c)!==A[g-1])A.push(F||c),g++;a.pageIx=g-1;F&&(G[b-1].pageIx=g-1);b===G.length-1&&c+d-A[g-1]>l&&(A.push(c),a.pageIx=g);c!==F&&(F=c)}),n||(n=c.clipRect=d.clipRect(0,m,9999,0),c.contentGroup.clip(n)),g(l),q||(this.nav=q=d.g().attr({zIndex:1}).add(this.group), +this.up=d.symbol("triangle",0,0,r,r).on("click",function(){c.scroll(-1,p)}).add(q),this.pager=d.text("",15,10).addClass("highcharts-legend-navigation").css(t.style).add(q),this.down=d.symbol("triangle-down",0,0,r,r).on("click",function(){c.scroll(1,p)}).add(q)),c.scroll(0),a=b):q&&(g(),this.nav=q.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return a},scroll:function(a,c){var b=this.pages,d=b.length;a=this.currentPage+a;var e=this.clipHeight,h=this.options.navigation,f=this.pager, +m=this.padding;a>d&&(a=d);0b&&(f=typeof a[0],"string"===f?e.name=a[0]:"number"===f&&(e.x=a[0]),k++);l=d.value;)d=h[++f];d&&d.color&&!this.options.color&&(this.color=d.color);return d},destroy:function(){var a=this.series.chart,h=a.hoverPoints,f;a.pointCount--;h&&(this.setState(),p(h,this),h.length||(a.hoverPoints=null));if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)u(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(f in this)this[f]=null},destroyElements:function(){for(var a=["graphic","dataLabel", +"dataLabelUpper","connector","shadowGroup"],h,f=6;f--;)h=a[f],this[h]&&(this[h]=this[h].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,color:this.color,colorIndex:this.colorIndex,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},tooltipFormatter:function(a){var e=this.series,f=e.tooltipOptions,d=w(f.valueDecimals,""),c=f.valuePrefix||"",b=f.valueSuffix||"";D(e.pointArrayMap||["y"],function(e){e="{point."+ +e;if(c||b)a=a.replace(e+"}",c+e+"}"+b);a=a.replace(e+"}",e+":,."+d+"f}")});return l(a,{point:this,series:this.series})},firePointEvent:function(a,h,m){var d=this,c=this.series.options;(c.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents();"click"===a&&c.allowPointSelect&&(m=function(a){d.select&&d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});f(this,a,h,m)},visible:!0}})(M);(function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.correctFloat, +l=a.Date,r=a.defaultOptions,n=a.defaultPlotOptions,w=a.defined,u=a.each,e=a.erase,h=a.extend,m=a.fireEvent,d=a.grep,c=a.isArray,b=a.isNumber,k=a.isString,z=a.merge,B=a.objectEach,I=a.pick,x=a.removeEvent,K=a.splat,t=a.SVGElement,C=a.syncTimeout,N=a.win;a.Series=a.seriesType("line",null,{lineWidth:2,allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},marker:{lineWidth:0,lineColor:"#ffffff",radius:4,states:{hover:{animation:{duration:50},enabled:!0,radiusPlus:2,lineWidthPlus:1},select:{fillColor:"#cccccc", +lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:{align:"center",formatter:function(){return null===this.y?"":a.numberFormat(this.y,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"contrast",textOutline:"1px contrast"},verticalAlign:"bottom",x:0,y:0,padding:5},cropThreshold:300,pointRange:0,softThreshold:!0,states:{hover:{animation:{duration:50},lineWidthPlus:1,marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1E3,findNearestPointBy:"x"}, +{isCartesian:!0,pointClass:a.Point,sorted:!0,requireSorting:!0,directTouch:!1,axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],coll:"series",init:function(a,b){var c=this,d,g=a.series,e;c.chart=a;c.options=b=c.setOptions(b);c.linkedSeries=[];c.bindAxes();h(c,{name:b.name,state:"",visible:!1!==b.visible,selected:!0===b.selected});d=b.events;B(d,function(a,b){E(c,b,a)});if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;c.getColor(); +c.getSymbol();u(c.parallelArrays,function(a){c[a+"Data"]=[]});c.setData(b.data,!1);c.isCartesian&&(a.hasCartesianSeries=!0);g.length&&(e=g[g.length-1]);c._i=I(e&&e._i,-1)+1;a.orderSeries(this.insert(g))},insert:function(a){var c=this.options.index,d;if(b(c)){for(d=a.length;d--;)if(c>=I(a[d].options.index,a[d]._i)){a.splice(d+1,0,this);break}-1===d&&a.unshift(this);d+=1}else a.push(this);return I(d,a.length-1)},bindAxes:function(){var b=this,c=b.options,d=b.chart,e;u(b.axisTypes||[],function(g){u(d[g], +function(a){e=a.options;if(c[g]===e.index||void 0!==c[g]&&c[g]===e.id||void 0===c[g]&&0===e.index)b.insert(a.series),b[g]=a,a.isDirty=!0});b[g]||b.optionalAxis===g||a.error(18,!0)})},updateParallelArrays:function(a,c){var d=a.series,e=arguments,g=b(c)?function(b){var g="y"===b&&d.toYData?d.toYData(a):a[b];d[b+"Data"][c]=g}:function(a){Array.prototype[c].apply(d[a+"Data"],Array.prototype.slice.call(e,2))};u(d.parallelArrays,g)},autoIncrement:function(){var b=this.options,c=this.xIncrement,d,e=b.pointIntervalUnit, +g=0,c=I(c,b.pointStart,0);this.pointInterval=d=I(this.pointInterval,b.pointInterval,1);e&&(b=new l(c),"day"===e?b=+b[l.hcSetDate](b[l.hcGetDate]()+d):"month"===e?b=+b[l.hcSetMonth](b[l.hcGetMonth]()+d):"year"===e&&(b=+b[l.hcSetFullYear](b[l.hcGetFullYear]()+d)),l.hcHasTimeZone&&(g=a.getTZOffset(b)-a.getTZOffset(c)),d=b-c+g);this.xIncrement=c+d;return c},setOptions:function(a){var b=this.chart,c=b.options,d=c.plotOptions,g=(b.userOptions||{}).plotOptions||{},e=d[this.type];this.userOptions=a;b=z(e, +d.series,a);this.tooltipOptions=z(r.tooltip,r.plotOptions.series&&r.plotOptions.series.tooltip,r.plotOptions[this.type].tooltip,c.tooltip.userOptions,d.series&&d.series.tooltip,d[this.type].tooltip,a.tooltip);this.stickyTracking=I(a.stickyTracking,g[this.type]&&g[this.type].stickyTracking,g.series&&g.series.stickyTracking,this.tooltipOptions.shared&&!this.noSharedTooltip?!0:b.stickyTracking);null===e.marker&&delete b.marker;this.zoneAxis=b.zoneAxis;a=this.zones=(b.zones||[]).slice();!b.negativeColor&& +!b.negativeFillColor||b.zones||a.push({value:b[this.zoneAxis+"Threshold"]||b.threshold||0,className:"highcharts-negative",color:b.negativeColor,fillColor:b.negativeFillColor});a.length&&w(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return b},getCyclic:function(a,b,c){var d,g=this.chart,e=this.userOptions,k=a+"Index",h=a+"Counter",q=c?c.length:I(g.options.chart[a+"Count"],g[a+"Count"]);b||(d=I(e[k],e["_"+k]),w(d)||(g.series.length||(g[h]=0),e["_"+k]=d=g[h]%q,g[h]+=1), +c&&(b=c[d]));void 0!==d&&(this[k]=d);this[a]=b},getColor:function(){this.options.colorByPoint?this.options.color=null:this.getCyclic("color",this.options.color||n[this.type].color,this.chart.options.colors)},getSymbol:function(){this.getCyclic("symbol",this.options.marker.symbol,this.chart.options.symbols)},drawLegendSymbol:a.LegendSymbolMixin.drawLineMarker,setData:function(d,e,h,f){var g=this,q=g.points,m=q&&q.length||0,l,A=g.options,t=g.chart,x=null,n=g.xAxis,p=A.turboThreshold,z=this.xData,F= +this.yData,C=(l=g.pointArrayMap)&&l.length;d=d||[];l=d.length;e=I(e,!0);if(!1!==f&&l&&m===l&&!g.cropped&&!g.hasGroupedData&&g.visible)u(d,function(a,b){q[b].update&&a!==A.data[b]&&q[b].update(a,!1,null,!1)});else{g.xIncrement=null;g.colorCounter=0;u(this.parallelArrays,function(a){g[a+"Data"].length=0});if(p&&l>p){for(h=0;null===x&&hf||this.forceCrop))if(c[e-1]z)c=[],d=[];else if(c[0]z)g=this.cropData(this.xData,this.yData,p,z),c=g.xData,d=g.yData,g=g.start,k=!0;for(f=c.length|| +1;--f;)e=x?m(c[f])-m(c[f-1]):c[f]-c[f-1],0e&&n&&(a.error(15),n=!1);this.cropped=k;this.cropStart=g;this.processedXData=c;this.processedYData=d;this.closestPointRange=h},cropData:function(a,b,c,d){var g=a.length,e=0,k=g,h=I(this.cropShoulder,1),f;for(f=0;f=c){e=Math.max(0,f-h);break}for(c=f;cd){k=c+h;break}return{xData:a.slice(e,k),yData:b.slice(e,k),start:e,end:k}},generatePoints:function(){var a=this.options,b=a.data,c=this.data,d,g=this.processedXData, +e=this.processedYData,k=this.pointClass,h=g.length,f=this.cropStart||0,m,l=this.hasGroupedData,a=a.keys,t,x=[],n;c||l||(c=[],c.length=b.length,c=this.data=c);a&&l&&(this.options.keys=!1);for(n=0;n=f&&(e[n-1]||l)<=q,m&&l)if(m=t.length)for(;m--;)"number"===typeof t[m]&&(g[h++]=t[m]);else g[h++]=t;this.dataMin= +p(g);this.dataMax=H(g)},translate:function(){this.processedXData||this.processData();this.generatePoints();var a=this.options,c=a.stacking,d=this.xAxis,e=d.categories,g=this.yAxis,k=this.points,h=k.length,m=!!this.modifyValue,l=a.pointPlacement,t="between"===l||b(l),n=a.threshold,x=a.startFromThreshold?n:0,p,z,C,r,u=Number.MAX_VALUE;"between"===l&&(l=.5);b(l)&&(l*=I(a.pointRange||d.pointRange));for(a=0;a=K&&(B.isNull=!0);B.plotX=p=f(Math.min(Math.max(-1E5,d.translate(N,0,0,0,1,l,"flags"===this.type)),1E5));c&&this.visible&&!B.isNull&&D&&D[N]&&(r=this.getStackIndicator(r,N,this.index),E=D[N],K=E.points[r.key],z=K[0],K=K[1],z===x&&r.key===D[N].base&&(z=I(n,g.min)),g.positiveValuesOnly&&0>=z&&(z=null),B.total=B.stackTotal=E.total,B.percentage=E.total&&B.y/E.total*100,B.stackY=K,E.setOffset(this.pointXOffset||0,this.barW||0));B.yBottom=w(z)?g.translate(z,0,1,0,1): +null;m&&(K=this.modifyValue(K,B));B.plotY=z="number"===typeof K&&Infinity!==K?Math.min(Math.max(-1E5,g.translate(K,0,1,0,1)),1E5):void 0;B.isInside=void 0!==z&&0<=z&&z<=g.len&&0<=p&&p<=d.len;B.clientX=t?f(d.translate(N,0,0,0,1,l)):p;B.negative=B.y<(n||0);B.category=e&&void 0!==e[B.x]?e[B.x]:B.x;B.isNull||(void 0!==C&&(u=Math.min(u,Math.abs(p-C))),C=p);B.zone=this.zones.length&&B.getZone()}this.closestPointRangePx=u},getValidPoints:function(a,b){var c=this.chart;return d(a||this.points||[],function(a){return b&& +!c.isInsidePlot(a.plotX,a.plotY,c.inverted)?!1:!a.isNull})},setClip:function(a){var b=this.chart,c=this.options,d=b.renderer,g=b.inverted,e=this.clipBox,k=e||b.clipBox,h=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,k.height,c.xAxis,c.yAxis].join(),f=b[h],q=b[h+"m"];f||(a&&(k.width=0,g&&(k.x=b.plotSizeX),b[h+"m"]=q=d.clipRect(g?b.plotSizeX+99:-99,g?-b.plotLeft:-b.plotTop,99,g?b.chartWidth:b.chartHeight)),b[h]=f=d.clipRect(k),f.count={length:0});a&&!f.count[this.index]&&(f.count[this.index]= +!0,f.count.length+=1);!1!==c.clip&&(this.group.clip(a||e?f:b.clipRect),this.markerGroup.clip(q),this.sharedClipKey=h);a||(f.count[this.index]&&(delete f.count[this.index],--f.count.length),0===f.count.length&&h&&b[h]&&(e||(b[h]=b[h].destroy()),b[h+"m"]&&(b[h+"m"]=b[h+"m"].destroy())))},animate:function(a){var b=this.chart,c=D(this.options.animation),d;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX,x:0},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99,x:0},c),this.animate= +null)},afterAnimate:function(){this.setClip();m(this,"afterAnimate");this.finishedAnimating=!0},drawPoints:function(){var a=this.points,b=this.chart,c,d,g,e,k=this.options.marker,h,f,l,m=this[this.specialGroup]||this.markerGroup,t,n=I(k.enabled,this.xAxis.isRadial?!0:null,this.closestPointRangePx>=2*k.radius);if(!1!==k.enabled||this._hasPointMarkers)for(c=0;ce&&b.shadow));k&&(k.startX=c.xMap,k.isArea=c.isArea)})}, +applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,e,k,h=this.clips||[],f,m=this.graph,l=this.area,t=Math.max(b.chartWidth,b.chartHeight),n=this[(this.zoneAxis||"y")+"Axis"],x,p,z=b.inverted,C,r,w,B,K=!1;d.length&&(m||l)&&n&&void 0!==n.min&&(p=n.reversed,C=n.horiz,m&&m.hide(),l&&l.hide(),x=n.getExtremes(),u(d,function(d,g){e=p?C?b.plotWidth:0:C?0:n.toPixels(x.min);e=Math.min(Math.max(I(k,e),0),t);k=Math.min(Math.max(Math.round(n.toPixels(I(d.value,x.max),!0)),0),t);K&&(e=k=n.toPixels(x.max)); +r=Math.abs(e-k);w=Math.min(e,k);B=Math.max(e,k);n.isXAxis?(f={x:z?B:w,y:0,width:r,height:t},C||(f.x=b.plotHeight-f.x)):(f={x:0,y:z?B:w,width:t,height:r},C&&(f.y=b.plotWidth-f.y));z&&c.isVML&&(f=n.isXAxis?{x:0,y:p?w:B,height:f.width,width:b.chartWidth}:{x:f.y-b.plotLeft-b.spacingBox.x,y:0,width:f.height,height:b.chartHeight});h[g]?h[g].animate(f):(h[g]=c.clipRect(f),m&&a["zone-graph-"+g].clip(h[g]),l&&a["zone-area-"+g].clip(h[g]));K=d.value>x.max}),this.clips=h)},invertGroups:function(a){function b(){u(["group", +"markerGroup"],function(b){c[b]&&(d.renderer.isVML&&c[b].attr({width:c.yAxis.len,height:c.xAxis.len}),c[b].width=c.yAxis.len,c[b].height=c.xAxis.len,c[b].invert(a))})}var c=this,d=c.chart,e;c.xAxis&&(e=E(d,"resize",b),E(c,"destroy",e),b(a),c.invertGroups=b)},plotGroup:function(a,b,c,d,e){var g=this[a],k=!g;k&&(this[a]=g=this.chart.renderer.g().attr({zIndex:d||.1}).add(e));g.addClass("highcharts-"+b+" highcharts-series-"+this.index+" highcharts-"+this.type+"-series "+(w(this.colorIndex)?"highcharts-color-"+ +this.colorIndex+" ":"")+(this.options.className||"")+(g.hasClass("highcharts-tracker")?" highcharts-tracker":""),!0);g.attr({visibility:c})[k?"attr":"animate"](this.getPlotBox());return g},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;a.inverted&&(b=c,c=this.xAxis);return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this,b=a.chart,c,d=a.options,e=!!a.animate&&b.renderer.isSVG&&D(d.animation).duration,k=a.visible?"inherit": +"hidden",h=d.zIndex,f=a.hasRendered,m=b.seriesGroup,l=b.inverted;c=a.plotGroup("group","series",k,h,m);a.markerGroup=a.plotGroup("markerGroup","markers",k,h,m);e&&a.animate(!0);c.inverted=a.isCartesian?l:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(l);!1===d.clip||a.sharedClipKey||f||c.clip(b.clipRect);e&&a.animate();f||(a.animationTimeout=C(function(){a.afterAnimate()}, +e));a.isDirty=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirty||this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:I(d&&d.left,a.plotLeft),translateY:I(e&&e.top,a.plotTop)}));this.translate();this.render();b&&delete this.kdTree},kdAxisArray:["clientX","plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,e=this.chart.inverted;return this.searchKDTree({clientX:e?c.len-a.chartY+ +c.pos:a.chartX-c.pos,plotY:e?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(c,d,e){var g,k;if(k=c&&c.length)return g=b.kdAxisArray[d%e],c.sort(function(a,b){return a[g]-b[g]}),k=Math.floor(k/2),{point:c[k],left:a(c.slice(0,k),d+1,e),right:a(c.slice(k+1),d+1,e)}}this.buildingKdTree=!0;var b=this,c=-1l?"left":"right";t=0>l?"right":"left";b[q]&&(q=c(a,b[q],g+1,f),n=q[h]x;)q--;this.updateParallelArrays(m,"splice",q,0,0);this.updateParallelArrays(m,q);g&&m.name&&(g[x]=m.name);l.splice(q,0,a);n&&(this.data.splice(q,0,null),this.processData());"point"===e.legendType&&this.generatePoints();c&&(h[0]&&h[0].remove?h[0].remove(!1):(h.shift(),this.updateParallelArrays(m,"shift"),l.shift()));this.isDirtyData=this.isDirty=!0;b&&f.redraw(d)},removePoint:function(a,b,c){var d=this,e=d.data,h=e[a],f=d.points,g=d.chart,l=function(){f&&f.length===e.length&& +f.splice(a,1);e.splice(a,1);d.options.data.splice(a,1);d.updateParallelArrays(h||{series:d},"splice",a,1);h&&h.destroy();d.isDirty=!0;d.isDirtyData=!0;b&&g.redraw()};x(c,g);b=k(b,!0);h?h.firePointEvent("remove",null,l):l()},remove:function(a,b,c){function d(){e.destroy();h.isDirtyLegend=h.isDirtyBox=!0;h.linkSeries();k(a,!0)&&h.redraw(b)}var e=this,h=e.chart;!1!==c?u(e,"remove",null,d):d()},update:function(a,b){var d=this,e=d.chart,h=d.userOptions,f=d.oldType||d.type,l=a.type||h.type||e.options.chart.type, +g=I[f].prototype,m,n=["group","markerGroup","dataLabelsGroup"],t=["navigatorSeries","baseSeries"],x=d.finishedAnimating&&{animation:!1};if(Object.keys&&"data"===Object.keys(a).toString())return this.setData(a.data,b);t=n.concat(t);r(t,function(a){t[a]=d[a];delete d[a]});a=c(h,x,{index:d.index,pointStart:d.xData[0]},{data:d.options.data},a);d.remove(!1,null,!1);for(m in g)d[m]=void 0;w(d,I[l||f].prototype);r(t,function(a){d[a]=t[a]});d.init(e,a);a.zIndex!==h.zIndex&&r(n,function(b){d[b]&&d[b].attr({zIndex:a.zIndex})}); +d.oldType=f;e.linkSeries();k(b,!0)&&e.redraw(!1)}});w(H.prototype,{update:function(a,b){var d=this.chart;a=d.options[this.coll][this.options.index]=c(this.userOptions,a);this.destroy(!0);this.init(d,w(a,{events:void 0}));d.isDirtyBox=!0;k(b,!0)&&d.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,e=this.series,h=e.length;h--;)e[h]&&e[h].remove(!1);n(b.axes,this);n(b[c],this);d(b.options[c])?b.options[c].splice(this.options.index,1):delete b.options[c];r(b[c],function(a,b){a.options.index= +b});this.destroy();b.isDirtyBox=!0;k(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}})})(M);(function(a){var E=a.color,D=a.each,H=a.map,p=a.pick,f=a.Series,l=a.seriesType;l("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(f){var l=[],r=[],u=this.xAxis,e=this.yAxis,h=e.stacks[this.stackKey],m={},d=this.index,c=e.series,b=c.length,k,z=p(e.options.reversedStacks,!0)?1:-1,B;f=f||this.points; +if(this.options.stacking){for(B=0;Ba&&w>l?(w=Math.max(a,l),e=2*l-w):wp&&e>l?(e=Math.max(p,l),w=2*l-e):e=Math.abs(h)&&.5a.closestPointRange*a.xAxis.transA,d=a.borderWidth=r(f.borderWidth,d?0:1),c=a.yAxis,b=f.threshold,k=a.translatedThreshold=c.getThreshold(b),l=r(f.minPointLength,5),p=a.getColumnMetrics(),u=p.width,x=a.barW=Math.max(u,1+2*d),w=a.pointXOffset=p.offset;h.inverted&&(k-=.5);f.pointPadding&&(x=Math.ceil(x));n.prototype.translate.apply(a);H(a.points,function(d){var e=r(d.yBottom,k),f=999+Math.abs(e),f=Math.min(Math.max(-f,d.plotY),c.len+f),m=d.plotX+w,n=x,t=Math.min(f,e),p,g=Math.max(f,e)-t;l&& +Math.abs(g)l?e-l:k-(p?l:0));d.barX=m;d.pointWidth=u;d.tooltipPos=h.inverted?[c.len+c.pos-h.plotLeft-f,a.xAxis.len-m-n/2,g]:[m+n/2,f+c.pos-h.plotTop,g];d.shapeType="rect";d.shapeArgs=a.crispCol.apply(a,d.isNull?[m,k,n,0]:[m,t,n,g])})},getSymbol:a.noop,drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")}, +pointAttribs:function(a,f){var e=this.options,d,c=this.pointAttrToOptions||{};d=c.stroke||"borderColor";var b=c["stroke-width"]||"borderWidth",k=a&&a.color||this.color,h=a&&a[d]||e[d]||this.color||k,n=a&&a[b]||e[b]||this[b]||0,c=e.dashStyle;a&&this.zones.length&&(k=a.getZone(),k=a.options.color||k&&k.color||this.color);f&&(a=l(e.states[f],a.options.states&&a.options.states[f]||{}),f=a.brightness,k=a.color||void 0!==f&&D(k).brighten(a.brightness).get()||k,h=a[d]||h,n=a[b]||n,c=a.dashStyle||c);d={fill:k, +stroke:h,"stroke-width":n};c&&(d.dashstyle=c);return d},drawPoints:function(){var a=this,h=this.chart,m=a.options,d=h.renderer,c=m.animationLimit||250,b;H(a.points,function(e){var k=e.graphic;if(f(e.plotY)&&null!==e.y){b=e.shapeArgs;if(k)k[h.pointCounte;++e)h=w[e],a=2>e||2===e&&/%$/.test(h),w[e]=p(h,[n,l,u,w[2]][e])+(a?r:0);w[3]>w[2]&&(w[3]=w[2]);return w},getStartAndEndRadians:function(a,l){a=D(a)?a:0;l=D(l)&&l>a&&360>l-a?l:a+360;return{start:E*(a+-90),end:E*(l+-90)}}}})(M);(function(a){var E=a.addEvent,D=a.CenteredSeriesMixin,H=a.defined,p=a.each,f=a.extend,l=D.getStartAndEndRadians,r=a.inArray,n=a.noop,w=a.pick,u=a.Point,e=a.Series,h=a.seriesType,m=a.setAnimation;h("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30, +enabled:!0,formatter:function(){return this.point.isNull?void 0:this.point.name},x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff",borderWidth:1,states:{hover:{brightness:.1,shadow:!1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:a.seriesTypes.column.prototype.pointAttribs,animate:function(a){var c= +this,b=c.points,d=c.startAngleRad;a||(p(b,function(a){var b=a.graphic,e=a.shapeArgs;b&&(b.attr({r:a.startR||c.center[3]/2,start:d,end:d}),b.animate({r:e.r,start:e.start,end:e.end},c.options.animation))}),c.animate=null)},updateTotals:function(){var a,c=0,b=this.points,e=b.length,f,h=this.options.ignoreHiddenPoint;for(a=0;a1.5*Math.PI?m-=2*Math.PI:m<-Math.PI/2&&(m+=2*Math.PI);G.slicedTranslation={translateX:Math.round(Math.cos(m)*d),translateY:Math.round(Math.sin(m)*d)};h=Math.cos(m)*a[2]/ +2;u=Math.sin(m)*a[2]/2;G.tooltipPos=[a[0]+.7*h,a[1]+.7*u];G.half=m<-Math.PI/2||m>Math.PI/2?1:0;G.angle=m;f=Math.min(e,G.labelDistance/5);G.labelPos=[a[0]+h+Math.cos(m)*G.labelDistance,a[1]+u+Math.sin(m)*G.labelDistance,a[0]+h+Math.cos(m)*f,a[1]+u+Math.sin(m)*f,a[0]+h,a[1]+u,0>G.labelDistance?"center":G.half?"right":"left",m]}},drawGraph:null,drawPoints:function(){var a=this,c=a.chart.renderer,b,e,h,l,m=a.options.shadow;m&&!a.shadowGroup&&(a.shadowGroup=c.g("shadow").add(a.group));p(a.points,function(d){e= +d.graphic;if(d.isNull)e&&(d.graphic=e.destroy());else{l=d.shapeArgs;b=d.getTranslate();var k=d.shadowGroup;m&&!k&&(k=d.shadowGroup=c.g("shadow").add(a.shadowGroup));k&&k.attr(b);h=a.pointAttribs(d,d.selected&&"select");e?e.setRadialReference(a.center).attr(h).animate(f(l,b)):(d.graphic=e=c[d.shapeType](l).setRadialReference(a.center).attr(b).add(a.group),d.visible||e.attr({visibility:"hidden"}),e.attr(h).attr({"stroke-linejoin":"round"}).shadow(m,k));e.addClass(d.getClassName())}})},searchPoint:n, +sortByAngle:function(a,c){a.sort(function(a,d){return void 0!==a.angle&&(d.angle-a.angle)*c})},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,getCenter:D.getCenter,getSymbol:n},{init:function(){u.prototype.init.apply(this,arguments);var a=this,c;a.name=w(a.name,"Slice");c=function(b){a.slice("select"===b.type)};E(a,"select",c);E(a,"unselect",c);return a},isValid:function(){return a.isNumber(this.y,!0)&&0<=this.y},setVisible:function(a,c){var b=this,d=b.series,e=d.chart,f=d.options.ignoreHiddenPoint; +c=w(c,f);a!==b.visible&&(b.visible=b.options.visible=a=void 0===a?!b.visible:a,d.options.data[r(b,d.data)]=b.options,p(["graphic","dataLabel","connector","shadowGroup"],function(c){if(b[c])b[c][a?"show":"hide"](!0)}),b.legendItem&&e.legend.colorizeItem(b,a),a||"hover"!==b.state||b.setState(""),f&&(d.isDirty=!0),c&&e.redraw())},slice:function(a,c,b){var d=this.series;m(b,d.chart);w(c,!0);this.sliced=this.options.sliced=H(a)?a:!this.sliced;d.options.data[r(this,d.data)]=this.options;this.graphic.animate(this.getTranslate()); +this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())},getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(a){var c=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.x,c.y,c.r+a,c.r+a,{innerR:this.shapeArgs.r-1,start:c.start,end:c.end})}})})(M);(function(a){var E=a.addEvent,D=a.arrayMax,H=a.defined,p=a.each,f=a.extend,l=a.format,r=a.map,n=a.merge,w=a.noop,u=a.pick,e=a.relativeLength,h= +a.Series,m=a.seriesTypes,d=a.stableSort;a.distribute=function(a,b){function c(a,b){return a.target-b.target}var e,f=!0,h=a,l=[],m;m=0;for(e=a.length;e--;)m+=a[e].size;if(m>b){d(a,function(a,b){return(b.rank||0)-(a.rank||0)});for(m=e=0;m<=b;)m+=a[e].size,e++;l=a.splice(e-1,a.length)}d(a,c);for(a=r(a,function(a){return{size:a.size,targets:[a.target],align:u(a.align,.5)}});f;){for(e=a.length;e--;)f=a[e],m=(Math.min.apply(0,f.targets)+Math.max.apply(0,f.targets))/2,f.pos=Math.min(Math.max(0,m-f.size* +f.align),b-f.size);e=a.length;for(f=!1;e--;)0a[e].pos&&(a[e-1].size+=a[e].size,a[e-1].targets=a[e-1].targets.concat(a[e].targets),a[e-1].align=.5,a[e-1].pos+a[e-1].size>b&&(a[e-1].pos=b-a[e-1].size),a.splice(e,1),f=!0)}e=0;p(a,function(a){var b=0;p(a.targets,function(){h[e].pos=a.pos+b;b+=h[e].size;e++})});h.push.apply(h,l);d(h,c)};h.prototype.drawDataLabels=function(){function c(a,b){var c=b.filter;return c?(b=c.operator,a=a[c.property],c=c.value,"\x3e"===b&&a>c||"\x3c"=== +b&&a=c||"\x3c\x3d"===b&&a<=c||"\x3d\x3d"===b&&a==c||"\x3d\x3d\x3d"===b&&a===c?!0:!1):!0}var b=this,d=b.options,e=d.dataLabels,f=b.points,h,m,r=b.hasRendered||0,t,w,D=u(e.defer,!!d.animation),q=b.chart.renderer;if(e.enabled||b._hasPointLabels)b.dlProcessOptions&&b.dlProcessOptions(e),w=b.plotGroup("dataLabelsGroup","data-labels",D&&!r?"hidden":"visible",e.zIndex||6),D&&(w.attr({opacity:+r}),r||E(b,"afterAnimate",function(){b.visible&&w.show(!0);w[d.animation?"animate":"attr"]({opacity:1}, +{duration:200})})),m=e,p(f,function(f){var k,p=f.dataLabel,g,x,r=f.connector,z=!p,C;h=f.dlOptions||f.options&&f.options.dataLabels;(k=u(h&&h.enabled,m.enabled)&&!f.isNull)&&(k=!0===c(f,h||e));k&&(e=n(m,h),g=f.getLabelConfig(),C=e[f.formatPrefix+"Format"]||e.format,t=H(C)?l(C,g):(e[f.formatPrefix+"Formatter"]||e.formatter).call(g,e),C=e.style,g=e.rotation,C.color=u(e.color,C.color,b.color,"#000000"),"contrast"===C.color&&(f.contrastColor=q.getContrast(f.color||b.color),C.color=e.inside||0>u(f.labelDistance, +e.distance)||d.stacking?f.contrastColor:"#000000"),d.cursor&&(C.cursor=d.cursor),x={fill:e.backgroundColor,stroke:e.borderColor,"stroke-width":e.borderWidth,r:e.borderRadius||0,rotation:g,padding:e.padding,zIndex:1},a.objectEach(x,function(a,b){void 0===a&&delete x[b]}));!p||k&&H(t)?k&&H(t)&&(p?x.text=t:(p=f.dataLabel=g?q.text(t,0,-9999).addClass("highcharts-data-label"):q.label(t,0,-9999,e.shape,null,null,e.useHTML,null,"data-label"),p.addClass(" highcharts-data-label-color-"+f.colorIndex+" "+(e.className|| +"")+(e.useHTML?"highcharts-tracker":""))),p.attr(x),p.css(C).shadow(e.shadow),p.added||p.add(w),b.alignDataLabel(f,p,e,null,z)):(f.dataLabel=p=p.destroy(),r&&(f.connector=r.destroy()))})};h.prototype.alignDataLabel=function(a,b,d,e,h){var c=this.chart,k=c.inverted,l=u(a.dlBox&&a.dlBox.centerX,a.plotX,-9999),m=u(a.plotY,-9999),n=b.getBBox(),p,q=d.rotation,r=d.align,w=this.visible&&(a.series.forceDL||c.isInsidePlot(l,Math.round(m),k)||e&&c.isInsidePlot(l,k?e.x+1:e.y+e.height-1,k)),z="justify"===u(d.overflow, +"justify");if(w&&(p=d.style.fontSize,p=c.renderer.fontMetrics(p,b).b,e=f({x:k?this.yAxis.len-m:l,y:Math.round(k?this.xAxis.len-l:m),width:0,height:0},e),f(d,{width:n.width,height:n.height}),q?(z=!1,l=c.renderer.rotCorr(p,q),l={x:e.x+d.x+e.width/2+l.x,y:e.y+d.y+{top:0,middle:.5,bottom:1}[d.verticalAlign]*e.height},b[h?"attr":"animate"](l).attr({align:r}),m=(q+720)%360,m=180m,"left"===r?l.y-=m?n.height:0:"center"===r?(l.x-=n.width/2,l.y-=n.height/2):"right"===r&&(l.x-=n.width,l.y-=m?0:n.height)): +(b.align(d,null,e),l=b.alignAttr),z?a.isLabelJustified=this.justifyDataLabel(b,d,l,n,e,h):u(d.crop,!0)&&(w=c.isInsidePlot(l.x,l.y)&&c.isInsidePlot(l.x+n.width,l.y+n.height)),d.shape&&!q))b[h?"attr":"animate"]({anchorX:k?c.plotWidth-a.plotY:a.plotX,anchorY:k?c.plotHeight-a.plotX:a.plotY});w||(b.attr({y:-9999}),b.placed=!1)};h.prototype.justifyDataLabel=function(a,b,d,e,f,h){var c=this.chart,k=b.align,l=b.verticalAlign,m,n,p=a.box?0:a.padding||0;m=d.x+p;0>m&&("right"===k?b.align="left":b.x=-m,n=!0); +m=d.x+e.width-p;m>c.plotWidth&&("left"===k?b.align="right":b.x=c.plotWidth-m,n=!0);m=d.y+p;0>m&&("bottom"===l?b.verticalAlign="top":b.y=-m,n=!0);m=d.y+e.height-p;m>c.plotHeight&&("top"===l?b.verticalAlign="bottom":b.y=c.plotHeight-m,n=!0);n&&(a.placed=!h,a.align(b,null,f));return n};m.pie&&(m.pie.prototype.drawDataLabels=function(){var c=this,b=c.data,d,e=c.chart,f=c.options.dataLabels,l=u(f.connectorPadding,10),m=u(f.connectorWidth,1),n=e.plotWidth,t=e.plotHeight,r,w=c.center,q=w[2]/2,A=w[1],F,G, +g,v,E=[[],[]],L,P,J,M,y=[0,0,0,0];c.visible&&(f.enabled||c._hasPointLabels)&&(p(b,function(a){a.dataLabel&&a.visible&&a.dataLabel.shortened&&(a.dataLabel.attr({width:"auto"}).css({width:"auto",textOverflow:"clip"}),a.dataLabel.shortened=!1)}),h.prototype.drawDataLabels.apply(c),p(b,function(a){a.dataLabel&&a.visible&&(E[a.half].push(a),a.dataLabel._pos=null)}),p(E,function(b,h){var k,m,x=b.length,r=[],z;if(x)for(c.sortByAngle(b,h-.5),0d.bottom-2?k:P,h,d),F._attr={visibility:J,align:g[6]},F._pos={x:L+f.x+({left:l,right:-l}[g[6]]||0),y:P+f.y-10},g.x=L,g.y=P,u(f.crop,!0)&&(G=F.getBBox().width,k=null,L-Gn-l&&(k=Math.round(L+G-n+l),y[1]=Math.max(k,y[1])),0>P-v/2?y[0]=Math.max(Math.round(-P+v/2),y[0]):P+v/2>t&&(y[2]=Math.max(Math.round(P+v/2-t),y[2])),F.sideOverflow=k)}),0===D(y)||this.verifyDataLabelOverflow(y))&&(this.placeDataLabels(), +m&&p(this.points,function(a){var b;r=a.connector;if((F=a.dataLabel)&&F._pos&&a.visible&&0u(this.translatedThreshold,k.yAxis.len)),p=u(d.inside,!!this.options.stacking);l&&(e=n(l),0>e.y&&(e.height+=e.y,e.y=0),l=e.y+e.height-k.yAxis.len,0a+c||e+hb+d||f+lthis.pointCount))},pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&r(d,function(a){a.setState()});r("xy"===b?[1,0]:[1],function(b){b= +c[b?"xAxis":"yAxis"][0];var d=b.horiz,f=a[d?"chartX":"chartY"],d=d?"mouseDownX":"mouseDownY",h=c[d],g=(b.pointRange||0)/2,k=b.getExtremes(),l=b.toValue(h-f,!0)+g,m=b.toValue(h+b.len-f,!0)-g,n=m=l(n.minWidth,0)&&this.chartHeight>=l(n.minHeight,0)}).call(this)&&f.push(a._id)};E.prototype.currentOptions=function(l){function n(e,h,l,d){var c;a.objectEach(e,function(a,e){if(!d&&-1 li.first padding-left: 0px h2 font-size: 150% - -//#subtitle -// color: lighten($brown, 30%) -// font-style: italic -// font-weight: normal -// margin-top: 0px -// padding-left: 1em -// padding-top: 0px - h3 font-size: 120% diff --git a/app/assets/stylesheets/predictions.sass b/app/assets/stylesheets/predictions.sass new file mode 100644 index 000000000..b9496ebc5 --- /dev/null +++ b/app/assets/stylesheets/predictions.sass @@ -0,0 +1,11 @@ +.predictions + .metric + height: 180px + border: #000000 2px + background: $white + margin: 4px + strong + font-size: 250% + font-align: center + h3 + diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 3df1a7ca7..b62177e5d 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -51,11 +51,7 @@ class CropsController < ApplicationController def show @crop = Crop.includes(:scientific_names, plantings: :photos).find(params[:id]) @posts = @crop.posts.order(created_at: :desc).paginate(page: params[:page]) - - respond_to do |format| - format.html # show.html.haml - format.json { render json: @crop.to_json(crop_json_fields) } - end + respond_with(@crop) end def new @@ -106,6 +102,14 @@ class CropsController < ApplicationController respond_with @crop end + def sunniness + @crop = Crop.find(params[:crop_id]) + render json: Planting.where(crop: @crop) + .where.not(sunniness: nil) + .where.not(sunniness: '') + .group(:sunniness).count(:id) + end + private def notifier diff --git a/app/views/crops/_predictions.html.haml b/app/views/crops/_predictions.html.haml index dbde9c783..343f4f6bd 100644 --- a/app/views/crops/_predictions.html.haml +++ b/app/views/crops/_predictions.html.haml @@ -1,29 +1,34 @@ - unless crop.perennial.nil? - %p - #{crop.name} is - - if crop.perennial == true - = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do - a perennial crop - (living more than two years) - - elsif crop.perennial == false - = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do - an annual crop - (living and reproducing in a single year or less) + .predictions + .row + %p + #{crop.name} is + - if crop.perennial == true + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + a perennial crop + (living more than two years) + - elsif crop.perennial == false + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + an annual crop + (living and reproducing in a single year or less) -- if crop.annual? && crop.median_lifespan.present? - %p - Median lifespan of #{crop.name} plants is - %strong= crop.median_lifespan - days + .row + - if crop.annual? && crop.median_lifespan.present? + .metric.col-md-3.col-xs-5 + %h3 Median lifespan + %strong= crop.median_lifespan + %span days -- if crop.median_days_to_first_harvest.present? - %p - First harvest expected - %strong= crop.median_days_to_first_harvest - days after planting + - if crop.median_days_to_first_harvest.present? + .metric.col-md-3.col-xs-5 + %h3 First harvest expected + %strong= crop.median_days_to_first_harvest + %span days + after planting -- if crop.annual? && crop.median_days_to_last_harvest.present? - %p - Last harvest expected - %strong= crop.median_days_to_last_harvest - days after planting + - if crop.annual? && crop.median_days_to_last_harvest.present? + .metric.col-md-3.col-xs-5 + %h3 Last harvest expected + %strong= crop.median_days_to_last_harvest + %span days + after planting diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index 2789d61ef..cf401681e 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -8,6 +8,9 @@ = tag("meta", property: "og:url", content: request.original_url) = tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME']) +- content_for :scripts do + = javascript_include_tag "charts" + = render partial: 'approval_status_message', locals: { crop: @crop } - if @crop.approved? @@ -27,11 +30,6 @@ = display_seed_availability(@current_member, @crop) = link_to "View your seeds", seeds_by_owner_path(owner: current_member.slug) - %h2 Predictions - = render 'predictions', crop: @crop - - %p= render 'crops/photos', crop: @crop - %h2 - if !@crop.plantings.empty? = @crop.name.titleize @@ -41,19 +39,26 @@ - else Nobody is growing this yet. You could be the first! - %h2 - Sunniness Chart + .row + .col-md-3 + %h2 Sunniness Chart + = pie_chart crop_sunniness_path(@crop), legend: "bottom" - #sunchart + .col-md-9 + %h2 Predictions + = render 'predictions', crop: @crop - %h2 - Crop Map - %p - Only plantings by members who have set their locations are shown on this map. - - if current_member && current_member.location.blank? - = link_to "Set your location.", edit_member_registration_path + .row + .col-md-12 + %h2 Photos + %p= render 'crops/photos', crop: @crop - #cropmap + %h2 Crop Map + %p + Only plantings by members who have set their locations are shown on this map. + - if current_member && current_member.location.blank? + = link_to "Set your location.", edit_member_registration_path + #cropmap %a{ name: 'posts' } %h2 What people are saying about #{@crop.name.pluralize} diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index d7e05a282..b7d570330 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,5 +1,6 @@ !!! 5 %html{ lang: "en", prefix: "og: http://ogp.me/ns#" } + = yield :scripts = render partial: "layouts/meta" %body = render partial: "layouts/header" diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 4b828e80c..60484d4a4 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -12,3 +12,4 @@ Rails.application.config.assets.paths << Rails.root.join('node_modules') # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. # Rails.application.config.assets.precompile += %w( admin.js admin.css ) +Rails.application.config.assets.precompile += %w(charts.js) diff --git a/config/routes.rb b/config/routes.rb index 013fee209..d22049d55 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -50,6 +50,7 @@ Rails.application.routes.draw do get 'crops/search' => 'crops#search', as: 'crops_search' resources :crops do get 'photos' => 'photos#index' + get 'sunniness' => 'crops#sunniness' end resources :comments From ac16347f0d4bf0ee42d4f0a7ec15c7fc19cb0b42 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 7 Jan 2018 18:23:42 +1300 Subject: [PATCH 061/267] Small change to plantings model, so feature spec passes again --- app/controllers/plantings_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index 0853b897a..b0e339710 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -54,7 +54,7 @@ class PlantingsController < ApplicationController def create @planting = Planting.new(planting_params) @planting.owner = current_member - @planting.save! + @planting.save respond_with @planting end @@ -71,7 +71,7 @@ class PlantingsController < ApplicationController private def update_crop_medians - @planting.crop.update_lifespan_medians + @planting.crop.update_lifespan_medians if @planting.crop.present? end def update_planting_medians From 9e5aba75d8afbeb34c7100d3bc19279d58fba732 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 7 Jan 2018 18:35:28 +1300 Subject: [PATCH 062/267] Added full path to jpeg in spec, so does'nt throw asset pipeline errors --- spec/features/crops/crop_photos_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/features/crops/crop_photos_spec.rb b/spec/features/crops/crop_photos_spec.rb index 260283057..f86978645 100644 --- a/spec/features/crops/crop_photos_spec.rb +++ b/spec/features/crops/crop_photos_spec.rb @@ -8,16 +8,16 @@ feature "crop detail page", js: true do let(:harvest) { create :harvest, owner: member } let(:photo1) do - create(:photo, owner: member, title: 'photo 1', fullsize_url: 'photo1.jpg', thumbnail_url: 'thumb1.jpg') + create(:photo, owner: member, title: 'photo 1', fullsize_url: 'http://example.com/photo1.jpg', thumbnail_url: 'http://example.com/thumb1.jpg') end let(:photo2) do - create(:photo, owner: member, title: 'photo 2', fullsize_url: 'photo2.jpg', thumbnail_url: 'thumb2.jpg') + create(:photo, owner: member, title: 'photo 2', fullsize_url: 'http://example.com/photo2.jpg', thumbnail_url: 'http://example.com/thumb2.jpg') end let(:photo3) do - create(:photo, owner: member, title: 'photo 3', fullsize_url: 'photo3.jpg', thumbnail_url: 'thumb3.jpg') + create(:photo, owner: member, title: 'photo 3', fullsize_url: 'http://example.com/photo3.jpg', thumbnail_url: 'http://example.com/thumb3.jpg') end let(:photo4) do - create(:photo, owner: member, title: 'photo 4', fullsize_url: 'photo4.jpg', thumbnail_url: 'thumb4.jpg') + create(:photo, owner: member, title: 'photo 4', fullsize_url: 'http://example.com/photo4.jpg', thumbnail_url: 'http://example.com/thumb4.jpg') end before do From 73ffbb0272dbc31db46c31e475fb99ec329be9c1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 7 Jan 2018 18:44:03 +1300 Subject: [PATCH 063/267] crop creator is optional doesn't get set when crop has just been requested --- app/models/crop.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 4863b6658..a5105fb94 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -16,7 +16,7 @@ class Crop < ApplicationRecord has_many :seeds has_many :harvests has_many :plant_parts, -> { distinct.reorder("plant_parts.name") }, through: :harvests - belongs_to :creator, class_name: 'Member' + belongs_to :creator, class_name: 'Member', optional: true belongs_to :requester, class_name: 'Member', optional: true belongs_to :parent, class_name: 'Crop', optional: true has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id' From 52e3f03bb52f1b20568a12c91f13810c3ead5888 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 7 Jan 2018 19:25:05 +1300 Subject: [PATCH 064/267] Add timeline to gardens --- app/controllers/gardens_controller.rb | 11 +++++++++++ app/views/gardens/show.html.haml | 9 +++++++++ config/routes.rb | 4 +++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index 35efaf5d2..6a130b19d 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -60,6 +60,17 @@ class GardensController < ApplicationController redirect_to(gardens_by_owner_path(owner: @garden.owner)) end + def timeline + @data = [] + @garden = Garden.find(params[:garden_id]) + @garden.plantings.where.not(finished_at: nil) + .where.not(planted_at: nil) + .order(finished_at: :desc).each do |p| + @data << [p.crop.name, p.planted_at, p.finished_at] + end + render json: @data + end + private def garden_params diff --git a/app/views/gardens/show.html.haml b/app/views/gardens/show.html.haml index ef5b41cfb..5ffed7152 100644 --- a/app/views/gardens/show.html.haml +++ b/app/views/gardens/show.html.haml @@ -9,6 +9,11 @@ = tag("meta", property: "og:type", content: "website") = tag("meta", property: "og:url", content: request.original_url) = tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME']) + +- content_for :scripts do + = javascript_include_tag "charts" + = javascript_include_tag "https://www.gstatic.com/charts/loader.js" + .row .col-md-9 %p.btn-group= render 'gardens/actions', garden: @garden @@ -32,6 +37,10 @@ Why not = link_to 'tell us more.', edit_garden_path(@garden) + %h3 Garden timeline + .row + = timeline garden_timeline_path(@garden), adapter: "google" + %h3 What's planted here? .row - if @current_plantings.size.positive? diff --git a/config/routes.rb b/config/routes.rb index d22049d55..9aa2d3859 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,7 +27,9 @@ Rails.application.routes.draw do get '/plantings/owner/:owner' => 'plantings#index', as: 'plantings_by_owner' get '/plantings/crop/:crop' => 'plantings#index', as: 'plantings_by_crop' - resources :gardens + resources :gardens do + get 'timeline' => 'gardens#timeline' + end get '/gardens/owner/:owner' => 'gardens#index', as: 'gardens_by_owner' resources :seeds From 8e59e68dd76971bbbd723db663d1e162e05535a7 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 7 Jan 2018 19:30:52 +1300 Subject: [PATCH 065/267] Add valid DNS entry to feature spec, so it doesn't fail --- spec/features/crops/crop_photos_spec.rb | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/spec/features/crops/crop_photos_spec.rb b/spec/features/crops/crop_photos_spec.rb index f86978645..9d92449ea 100644 --- a/spec/features/crops/crop_photos_spec.rb +++ b/spec/features/crops/crop_photos_spec.rb @@ -6,18 +6,30 @@ feature "crop detail page", js: true do let(:crop) { create :crop, plantings: [planting], harvests: [harvest] } let(:planting) { create :planting, owner: member } let(:harvest) { create :harvest, owner: member } - + let(:valid_server) { 'https://farm5.staticflickr.com/' } let(:photo1) do - create(:photo, owner: member, title: 'photo 1', fullsize_url: 'http://example.com/photo1.jpg', thumbnail_url: 'http://example.com/thumb1.jpg') + create(:photo, owner: member, + title: 'photo 1', + fullsize_url: "#{valid_server}photo1.jpg", + thumbnail_url: "#{valid_server}thumb1.jpg") end let(:photo2) do - create(:photo, owner: member, title: 'photo 2', fullsize_url: 'http://example.com/photo2.jpg', thumbnail_url: 'http://example.com/thumb2.jpg') + create(:photo, owner: member, + title: 'photo 2', + fullsize_url: "#{valid_server}photo2.jpg", + thumbnail_url: "#{valid_server}thumb2.jpg") end let(:photo3) do - create(:photo, owner: member, title: 'photo 3', fullsize_url: 'http://example.com/photo3.jpg', thumbnail_url: 'http://example.com/thumb3.jpg') + create(:photo, owner: member, + title: 'photo 3', + fullsize_url: "#{valid_server}photo3.jpg", + thumbnail_url: "#{valid_server}thumb3.jpg") end let(:photo4) do - create(:photo, owner: member, title: 'photo 4', fullsize_url: 'http://example.com/photo4.jpg', thumbnail_url: 'http://example.com/thumb4.jpg') + create(:photo, owner: member, + title: 'photo 4', + fullsize_url: "#{valid_server}photo4.jpg", + thumbnail_url: "#{valid_server}thumb4.jpg") end before do From 386dc5ad7f950745a8bb554a2b17cd512649c67a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 7 Jan 2018 19:37:03 +1300 Subject: [PATCH 066/267] Use factory bot in specs --- spec/features/crops/creating_a_crop_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/features/crops/creating_a_crop_spec.rb b/spec/features/crops/creating_a_crop_spec.rb index 2b1300485..e03179933 100644 --- a/spec/features/crops/creating_a_crop_spec.rb +++ b/spec/features/crops/creating_a_crop_spec.rb @@ -1,8 +1,8 @@ require 'rails_helper' feature "Crop - " do - let!(:crop_wrangler) { create :crop_wrangling_member } - let!(:member) { create :member } + let!(:crop_wrangler) { FactoryBot.create :crop_wrangling_member } + let!(:member) { FactoryBot.create :member } background do login_as member From 865fe106ad2ed2dd0197d560d0a2cebf9765349c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 7 Jan 2018 22:10:27 +1300 Subject: [PATCH 067/267] Unique member name on notifications spec --- spec/features/notifications_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb index aa81403d6..8b4442927 100644 --- a/spec/features/notifications_spec.rb +++ b/spec/features/notifications_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' feature "Notifications", :js do let(:sender) { create :member } - let(:recipient) { create :member } + let(:recipient) { create :member, login_name: 'beyonce' } context "On existing notification" do let!(:notification) do From 34280123e5999b8e3c91b45d09cc17b64dec6a98 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 7 Jan 2018 17:25:16 +1300 Subject: [PATCH 068/267] Convert to use chartkick gem Conflicts: Gemfile Gemfile.lock config/initializers/assets.rb --- .overcommit.yml | 1 + Gemfile | 3 +- Gemfile.lock | 5 +- app/assets/javascripts/charts.js | 2 + app/assets/javascripts/crops.js.erb | 37 -- app/assets/javascripts/graphs/bar_group.js | 53 --- .../javascripts/graphs/bar_label_group.js | 45 -- app/assets/javascripts/graphs/height_scale.js | 31 -- .../graphs/horizontal_bar_graph.js | 54 --- app/assets/javascripts/graphs/width_scale.js | 37 -- app/assets/javascripts/highcharts.js | 389 ++++++++++++++++++ app/assets/stylesheets/application.sass | 1 + .../custom_bootstrap/variables.sass | 1 + app/assets/stylesheets/overrides.sass | 19 - app/assets/stylesheets/predictions.sass | 11 + app/controllers/crops_controller.rb | 14 +- app/views/crops/_predictions.html.haml | 55 +-- app/views/crops/show.html.haml | 35 +- app/views/layouts/application.html.haml | 1 + config/initializers/assets.rb | 15 + config/routes.rb | 1 + 21 files changed, 484 insertions(+), 326 deletions(-) create mode 100644 app/assets/javascripts/charts.js delete mode 100644 app/assets/javascripts/graphs/bar_group.js delete mode 100644 app/assets/javascripts/graphs/bar_label_group.js delete mode 100644 app/assets/javascripts/graphs/height_scale.js delete mode 100644 app/assets/javascripts/graphs/horizontal_bar_graph.js delete mode 100644 app/assets/javascripts/graphs/width_scale.js create mode 100644 app/assets/javascripts/highcharts.js create mode 100644 app/assets/stylesheets/predictions.sass create mode 100644 config/initializers/assets.rb diff --git a/.overcommit.yml b/.overcommit.yml index d7899885f..200a90e42 100644 --- a/.overcommit.yml +++ b/.overcommit.yml @@ -61,6 +61,7 @@ PreCommit: enabled: true exclude: - 'app/assets/**' + - 'app/assets/javascripts/highcharts.js' - 'spec/javascripts/support/vendor/**' - '**/bootstrap*' command: ['./node_modules/.bin/eslint'] diff --git a/Gemfile b/Gemfile index c5d5d1fe1..1e26e67fc 100644 --- a/Gemfile +++ b/Gemfile @@ -78,8 +78,7 @@ gem 'omniauth-facebook' gem 'omniauth-flickr', '>= 0.0.15' gem 'omniauth-twitter' -# For charting data -gem 'd3-rails', '~> 3.5' # 4.* produces Error: : could not find an object to spy upon for linear() - see https://travis-ci.org/Growstuff/growstuff/jobs/204461482 +gem "chartkick" # client for Elasticsearch. Elasticsearch is a flexible # and powerful, distributed, real-time search and analytics engine. diff --git a/Gemfile.lock b/Gemfile.lock index 31113ea38..637ee3f44 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -99,6 +99,7 @@ GEM capybara-screenshot (1.0.18) capybara (>= 1.0, < 3) launchy + chartkick (2.2.5) childprocess (0.8.0) ffi (~> 1.0, >= 1.0.11) climate_control (0.2.0) @@ -143,8 +144,6 @@ GEM crass (1.0.3) csv_shaper (1.3.0) activesupport (>= 3.0.0) - d3-rails (3.5.17) - railties (>= 3.1) dalli (2.7.6) database_cleaner (1.6.2) debug_inspector (0.0.3) @@ -569,12 +568,12 @@ DEPENDENCIES capybara capybara-email capybara-screenshot + chartkick codeclimate-test-reporter coffee-rails comfortable_mexican_sofa coveralls csv_shaper - d3-rails (~> 3.5) dalli database_cleaner devise diff --git a/app/assets/javascripts/charts.js b/app/assets/javascripts/charts.js new file mode 100644 index 000000000..1c42da456 --- /dev/null +++ b/app/assets/javascripts/charts.js @@ -0,0 +1,2 @@ +// = require Chart.bundle +// = require chartkick diff --git a/app/assets/javascripts/crops.js.erb b/app/assets/javascripts/crops.js.erb index afa16a009..9a60dd60c 100644 --- a/app/assets/javascripts/crops.js.erb +++ b/app/assets/javascripts/crops.js.erb @@ -1,5 +1,3 @@ -//= require graphs/horizontal_bar_graph - if (document.getElementById("cropmap") !== null) { mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>"; mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>"; @@ -51,41 +49,6 @@ function showCropMap(cropmap) { cropmap.addLayer(markers); } -function plantingStats(crop) { - var sunniness_counts = { 'empty': 0, 'sun': 0, 'semi-shade': 0, 'shade': 0 }; - $.each(crop.plantings, function(i, planting) { - if (planting.sunniness) { - sunniness_counts[planting.sunniness]++; - } else { - sunniness_counts['Empty']++; - } - }); - return [ - {name: 'Empty', value: sunniness_counts['empty']}, - {name: 'Sun', value: sunniness_counts['sun']}, - {name: 'Semi-shade', value: sunniness_counts['semi-shade']}, - {name: 'Shade', value: sunniness_counts['shade']} - ]; -} - -if ($("#sunchart")[0] !== null) { - var HorizontalBarGraph = growstuff.HorizontalBarGraph; - $.getJSON(location.pathname + '.json', function (crop) { - data = { - bars: plantingStats(crop), - bar_color: 'steelblue', - width: {size: 300, scale: 'linear'}, - height: {size: 100, scale: 'ordinal'}, - //left is used to shift the bars over so that there is - //room for the labels - margin: {top: 0, right: 0, bottom: 0, left: 100} - }; - - var graph = new HorizontalBarGraph(data); - graph.render(d3.select($('#sunchart')[0])); - }); -} - $('.btn.toggle.crop-hierarchy').click(function () { $('.toggle.crop-hierarchy').toggleClass('hide'); }); diff --git a/app/assets/javascripts/graphs/bar_group.js b/app/assets/javascripts/graphs/bar_group.js deleted file mode 100644 index e8a90c20a..000000000 --- a/app/assets/javascripts/graphs/bar_group.js +++ /dev/null @@ -1,53 +0,0 @@ -// =require d3 -// = require graphs/width_scale -// = require graphs/height_scale - -/* - * This represents bars for a bar graph. - * Currently these are used for HorizontalBarGraph. - */ -(function() { - 'use strict'; - - - var growstuff = (window.growstuff = window.growstuff || {}); - var WidthScale = growstuff.WidthScale; - var HeightScale = growstuff.HeightScale; - -/** - * data object for bar group - * @param {Object} data Graph configuration - */ -function BarGroup(data) { - this._data = data; -} - BarGroup.prototype.render = function(root) { - var data = this._data; - var bars = this._data.bars; - var widthScale = new WidthScale(data).render(); - var heightScale = new HeightScale(data).render(); - - return root.append('g') - .attr('class', 'bar') - .selectAll('rect') - .data(bars.map(function(bar) { - return bar.value; - })) - .enter() - .append('rect') - .attr('y', function(d, i) { - return heightScale(i); - }) - .attr('height', heightScale.rangeBand()) - .attr('fill', data.bar_color) - .attr('width', function(d) { - return widthScale(d); - }) - .append('title') - .text(function(d) { - return 'This value is ' + d + '.'; - }); - }; - - growstuff.BarGroup = BarGroup; -}()); diff --git a/app/assets/javascripts/graphs/bar_label_group.js b/app/assets/javascripts/graphs/bar_label_group.js deleted file mode 100644 index 2da31f567..000000000 --- a/app/assets/javascripts/graphs/bar_label_group.js +++ /dev/null @@ -1,45 +0,0 @@ -// =require d3 -/** - * This file draws the labels to the left of each bar. - */ -(function() { - 'use strict'; - - var growstuff = (window.growstuff = window.growstuff || {}); - /** - * new bar label object - * @param {Object} data Graph configuration - */ - function BarLabelGroup(data) { - this._data = data; - } - - BarLabelGroup.prototype.render = function(d3) { - var bars = this._data.bars; - // vvcopy pasta from spike vv -- this is a good candidate for refactor - var barHeight = 40; - - return d3.append('g') - .attr('class', 'bar-label') - .selectAll('text') - .data(bars.map(function(bar) { - return bar.name; - })) - .enter() - .append('text') - .attr('x', -80) - .attr('y', function(d, i) { - // shrink the margin between each label to give them an even spread with - // bars - var barLabelSpread = 2/3; - // move them downward to line up with bars - var barLabelTopEdge = 17; - return i * barHeight * (barLabelSpread) + barLabelTopEdge; - }) - .text(function(d) { - return d; - }); - }; - - growstuff.BarLabelGroup = BarLabelGroup; -}()); diff --git a/app/assets/javascripts/graphs/height_scale.js b/app/assets/javascripts/graphs/height_scale.js deleted file mode 100644 index 5189ef800..000000000 --- a/app/assets/javascripts/graphs/height_scale.js +++ /dev/null @@ -1,31 +0,0 @@ -// =require d3 - -/** - * Height Scale is used to map the number of bars to the display size of - * the svg - */ - -(function() { - 'use strict'; - - var growstuff = (window.growstuff = window.growstuff || {}); - - /** - * new height scale object - * @param {Object} data Graph configuration - */ - function HeightScale(data) { - this._data = data; - } - - HeightScale.prototype.render = function() { - var data = this._data; - var scaleType = data.height.scale; - - return d3.scale[scaleType]() - .domain(d3.range(data.bars.length)) - .rangeRoundBands([0, data.height.size], 0.05, 0); - }; - - growstuff.HeightScale = HeightScale; -}()); diff --git a/app/assets/javascripts/graphs/horizontal_bar_graph.js b/app/assets/javascripts/graphs/horizontal_bar_graph.js deleted file mode 100644 index ef2333ef1..000000000 --- a/app/assets/javascripts/graphs/horizontal_bar_graph.js +++ /dev/null @@ -1,54 +0,0 @@ -// = require d3 -// = require graphs/bar_group -// = require graphs/bar_label_group - -/** - * Horizontal Bar Graph represents sum total of the graph including all of the parts: - * Bars - * Bar Labels - * - * The main dimensions of the graph are rendered here. - */ - -(function() { - 'use strict'; - - var growstuff = (window.growstuff = window.growstuff || {}); - var BarGroup = growstuff.BarGroup; - var BarLabelGroup = growstuff.BarLabelGroup; - - /** - * create a new graph object - * @param {Object} data Graph configuration - */ - function HorizontalBarGraph(data) { - this._data = data; - this._d3 = d3; - } - - HorizontalBarGraph.prototype.render = function(root) { - var width = this._data.width; - var height = this._data.height; - - var barLabelGroup = new BarLabelGroup(this._data); - var margin = this._data.margin; - - var barGroup = new BarGroup(this._data); - - var svg = root - .append('svg') - .attr('width', width.size + margin.left + margin.right) - .attr('height', height.size + margin.top + margin.bottom) - .append('g') - .attr('class', 'bar-graph') - .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); - - - barGroup.render(svg); - barLabelGroup.render(svg); - - return svg; - }; - - growstuff.HorizontalBarGraph = HorizontalBarGraph; -}()); diff --git a/app/assets/javascripts/graphs/width_scale.js b/app/assets/javascripts/graphs/width_scale.js deleted file mode 100644 index 7f2b9dda2..000000000 --- a/app/assets/javascripts/graphs/width_scale.js +++ /dev/null @@ -1,37 +0,0 @@ -// =require d3 - -/** - * Width scale is used to map the value for the length of each bar - * to the display size of the svg - */ -(function() { - 'use strict'; - - var growstuff = (window.growstuff = window.growstuff || {}); - - /** - * Object for WidthScale - * @param {Object} data Graph configuration - */ - function WidthScale(data) { - this._data = data; - } - - WidthScale.prototype.render = function() { - var data = this._data; - var scaleType = data.width.scale; - var axisSize = data.width.size; - - return d3.scale[scaleType]() - .domain([0, this.getMaxValue()]) - .range([0, axisSize]); - }; - - WidthScale.prototype.getMaxValue = function() { - return d3.max(this._data.bars.map(function(bar) { - return bar.value; - })); - }; - - growstuff.WidthScale = WidthScale; -}()); diff --git a/app/assets/javascripts/highcharts.js b/app/assets/javascripts/highcharts.js new file mode 100644 index 000000000..9554ef58b --- /dev/null +++ b/app/assets/javascripts/highcharts.js @@ -0,0 +1,389 @@ +/* + Highcharts JS v6.0.4 (2017-12-15) + + (c) 2009-2016 Torstein Honsi + + License: www.highcharts.com/license +*/ +(function(S,M){"object"===typeof module&&module.exports?module.exports=S.document?M(S):M:S.Highcharts=M(S)})("undefined"!==typeof window?window:this,function(S){var M=function(){var a="undefined"===typeof S?window:S,E=a.document,D=a.navigator&&a.navigator.userAgent||"",H=E&&E.createElementNS&&!!E.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,p=/(edge|msie|trident)/i.test(D)&&!a.opera,f=/Firefox/.test(D),l=f&&4>parseInt(D.split("Firefox/")[1],10);return a.Highcharts?a.Highcharts.error(16, +!0):{product:"Highcharts",version:"6.0.4",deg2rad:2*Math.PI/360,doc:E,hasBidiBug:l,hasTouch:E&&void 0!==E.documentElement.ontouchstart,isMS:p,isWebKit:/AppleWebKit/.test(D),isFirefox:f,isTouchDevice:/(Mobile|Android|Windows Phone)/.test(D),SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:H,win:a,marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){},charts:[]}}();(function(a){a.timers=[];var E=a.charts,D=a.doc,H=a.win;a.error=function(p, +f){p=a.isNumber(p)?"Highcharts error #"+p+": www.highcharts.com/errors/"+p:p;if(f)throw Error(p);H.console&&console.log(p)};a.Fx=function(a,f,l){this.options=f;this.elem=a;this.prop=l};a.Fx.prototype={dSetter:function(){var a=this.paths[0],f=this.paths[1],l=[],r=this.now,n=a.length,w;if(1===r)l=this.toD;else if(n===f.length&&1>r)for(;n--;)w=parseFloat(a[n]),l[n]=isNaN(w)?f[n]:r*parseFloat(f[n]-w)+w;else l=f;this.elem.attr("d",l,null,!0)},update:function(){var a=this.elem,f=this.prop,l=this.now,r= +this.options.step;if(this[f+"Setter"])this[f+"Setter"]();else a.attr?a.element&&a.attr(f,l,null,!0):a.style[f]=l+this.unit;r&&r.call(a,l,this)},run:function(p,f,l){var r=this,n=r.options,w=function(a){return w.stopped?!1:r.step(a)},u=H.requestAnimationFrame||function(a){setTimeout(a,13)},e=function(){for(var h=0;h=u+this.startTime?(this.now=this.end,this.pos=1,this.update(),l=e[this.prop]=!0,a.objectEach(e,function(a){!0!==a&&(l=!1)}),l&&w&&w.call(n),p=!1):(this.pos=r.easing((f-this.startTime)/u),this.now=this.start+(this.end- +this.start)*this.pos,this.update(),p=!0);return p},initPath:function(p,f,l){function r(a){var b,c;for(k=a.length;k--;)b="M"===a[k]||"L"===a[k],c=/[a-zA-Z]/.test(a[k+3]),b&&c&&a.splice(k+1,0,a[k+1],a[k+2],a[k+1],a[k+2])}function n(a,b){for(;a.lengtha&&-Infinityw?"AM":"PM",P:12>w?"am":"pm",S:k(n.getSeconds()),L:k(Math.round(f%1E3),3)},a.dateFormats);a.objectEach(r,function(a,b){for(;-1!==p.indexOf("%"+b);)p=p.replace("%"+b,"function"===typeof a?a(f):a)});return l?p.substr(0,1).toUpperCase()+p.substr(1):p};a.formatSingle=function(p,f){var l=/\.([0-9])/,r=a.defaultOptions.lang;/f$/.test(p)?(l=(l=p.match(l))?l[1]:-1,null!==f&&(f=a.numberFormat(f,l,r.decimalPoint,-1=l&&(f=[1/l])));for(r=0;r=p||!n&&w<=(f[r]+(f[r+1]||f[r]))/2);r++);return u=a.correctFloat(u*l,-Math.round(Math.log(.001)/Math.LN10))};a.stableSort=function(a,f){var l=a.length,p,n;for(n=0;nl&&(l=a[f]);return l};a.destroyObjectProperties=function(p,f){a.objectEach(p,function(a,r){a&&a!==f&&a.destroy&&a.destroy();delete p[r]})};a.discardElement=function(p){var f=a.garbageBin;f||(f=a.createElement("div"));p&&f.appendChild(p);f.innerHTML=""};a.correctFloat=function(a,f){return parseFloat(a.toPrecision(f||14))};a.setAnimation=function(p,f){f.renderer.globalAnimation=a.pick(p,f.options.chart.animation, +!0)};a.animObject=function(p){return a.isObject(p)?a.merge(p):{duration:p?500:0}};a.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5,month:24192E5,year:314496E5};a.numberFormat=function(p,f,l,r){p=+p||0;f=+f;var n=a.defaultOptions.lang,w=(p.toString().split(".")[1]||"").split("e")[0].length,u,e,h=p.toString().split("e");-1===f?f=Math.min(w,20):a.isNumber(f)?f&&h[1]&&0>h[1]&&(u=f+ +h[1],0<=u?(h[0]=(+h[0]).toExponential(u).split("e")[0],f=u):(h[0]=h[0].split(".")[0]||0, +p=20>f?(h[0]*Math.pow(10,h[1])).toFixed(f):0,h[1]=0)):f=2;e=(Math.abs(h[1]?h[0]:p)+Math.pow(10,-Math.max(f,w)-1)).toFixed(f);w=String(a.pInt(e));u=3p?"-":"")+(u?w.substr(0,u)+r:"");p+=w.substr(u).replace(/(\d{3})(?=\d)/g,"$1"+r);f&&(p+=l+e.slice(-f));h[1]&&0!==+p&&(p+="e"+h[1]);return p};Math.easeInOutSine=function(a){return-.5*(Math.cos(Math.PI*a)-1)};a.getStyle=function(p,f,l){if("width"===f)return Math.min(p.offsetWidth, +p.scrollWidth)-a.getStyle(p,"padding-left")-a.getStyle(p,"padding-right");if("height"===f)return Math.min(p.offsetHeight,p.scrollHeight)-a.getStyle(p,"padding-top")-a.getStyle(p,"padding-bottom");H.getComputedStyle||a.error(27,!0);if(p=H.getComputedStyle(p,void 0))p=p.getPropertyValue(f),a.pick(l,"opacity"!==f)&&(p=a.pInt(p));return p};a.inArray=function(p,f){return(a.indexOfPolyfill||Array.prototype.indexOf).call(f,p)};a.grep=function(p,f){return(a.filterPolyfill||Array.prototype.filter).call(p, +f)};a.find=Array.prototype.find?function(a,f){return a.find(f)}:function(a,f){var l,r=a.length;for(l=0;l>16,(l&65280)>> +8,l&255,1]:4===f&&(n=[(l&3840)>>4|(l&3840)>>8,(l&240)>>4|l&240,(l&15)<<4|l&15,1])),!n)for(w=this.parsers.length;w--&&!n;)u=this.parsers[w],(f=u.regex.exec(l))&&(n=u.parse(f));this.rgba=n||[]},get:function(a){var f=this.input,n=this.rgba,l;this.stops?(l=p(f),l.stops=[].concat(l.stops),E(this.stops,function(n,e){l.stops[e]=[l.stops[e][0],n.get(a)]})):l=n&&D(n[0])?"rgb"===a||!a&&1===n[3]?"rgb("+n[0]+","+n[1]+","+n[2]+")":"a"===a?n[3]:"rgba("+n.join(",")+")":f;return l},brighten:function(a){var l,n=this.rgba; +if(this.stops)E(this.stops,function(n){n.brighten(a)});else if(D(a)&&0!==a)for(l=0;3>l;l++)n[l]+=f(255*a),0>n[l]&&(n[l]=0),255y.width)y={width:0,height:0}}else y=this.htmlGetBBox();b.isSVG&& +(a=y.width,b=y.height,q&&"11px"===q.fontSize&&17===Math.round(b)&&(y.height=b=14),g&&(y.width=Math.abs(b*Math.sin(v))+Math.abs(a*Math.cos(v)),y.height=Math.abs(b*Math.cos(v))+Math.abs(a*Math.sin(v))));if(A&&0]*>/g,"")))},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,g,b){"string"===typeof a?b.setAttribute(g,a):a&&this.colorGradient(a,g,b)},visibilitySetter:function(a,g,b){"inherit"===a?b.removeAttribute(g):this[g]!==a&&b.setAttribute(g,a);this[g]=a},zIndexSetter:function(a,b){var v=this.renderer,y=this.parentGroup,c=(y||v).element||v.box,k,d=this.element,q,e,v=c===v.box;k=this.added;var z;u(a)&& +(d.zIndex=a,a=+a,this[b]===a&&(k=!1),this[b]=a);if(k){(a=this.zIndex)&&y&&(y.handleZ=!0);b=c.childNodes;for(z=b.length-1;0<=z&&!q;z--)if(y=b[z],k=y.zIndex,e=!u(k),y!==d)if(0>a&&e&&!v&&!z)c.insertBefore(d,b[z]),q=!0;else if(g(k)<=a||e&&(!u(a)||0<=a))c.insertBefore(d,b[z+1]||null),q=!0;q||(c.insertBefore(d,b[v?3:0]||null),q=!0)}return q},_defaultSetter:function(a,g,b){b.setAttribute(g,a)}});E.prototype.yGetter=E.prototype.xGetter;E.prototype.translateXSetter=E.prototype.translateYSetter=E.prototype.rotationSetter= +E.prototype.verticalAlignSetter=E.prototype.rotationOriginXSetter=E.prototype.rotationOriginYSetter=E.prototype.scaleXSetter=E.prototype.scaleYSetter=E.prototype.matrixSetter=function(a,g){this[g]=a;this.doTransform=!0};E.prototype["stroke-widthSetter"]=E.prototype.strokeSetter=function(a,g,b){this[g]=a;this.stroke&&this["stroke-width"]?(E.prototype.fillSetter.call(this,this.stroke,"stroke",b),b.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0):"stroke-width"===g&&0===a&&this.hasStroke&& +(b.removeAttribute("stroke"),this.hasStroke=!1)};D=a.SVGRenderer=function(){this.init.apply(this,arguments)};c(D.prototype,{Element:E,SVG_NS:P,init:function(a,g,b,v,c,k){var y;v=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"}).css(this.getStyle(v));y=v.element;a.appendChild(y);f(a,"dir","ltr");-1===a.innerHTML.indexOf("xmlns")&&f(y,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=y;this.boxWrapper=v;this.alignedObjects=[];this.url=(x||N)&&m.getElementsByTagName("base").length? +R.location.href.replace(/#.*?$/,"").replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(m.createTextNode("Created with Highcharts 6.0.4"));this.defs=this.createElement("defs").add();this.allowHTML=k;this.forExport=c;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(g,b,!1);var d;x&&a.getBoundingClientRect&&(g=function(){n(a,{left:0,top:0});d=a.getBoundingClientRect();n(a,{left:Math.ceil(d.left)- +d.left+"px",top:Math.ceil(d.top)-d.top+"px"})},g(),this.unSubPixelFix=H(R,"resize",g))},getStyle:function(a){return this.style=c({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},setStyle:function(a){this.boxWrapper.css(this.getStyle(a))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();h(this.gradients||{});this.gradients=null;a&&(this.defs=a.destroy()); +this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(a){var g=new this.Element;g.init(this,a);return g},draw:A,getRadialAttr:function(a,g){return{cx:a[0]-a[2]/2+g.cx*a[2],cy:a[1]-a[2]/2+g.cy*a[2],r:g.r*a[2]}},getSpanWidth:function(a,g){var b=a.getBBox(!0).width;!L&&this.forExport&&(b=this.measureSpanWidth(g.firstChild.data,a.styles));return b},applyEllipsis:function(a,g,b,v){var c=a.rotation,y=b,k,d=0,q=b.length,e=function(a){g.removeChild(g.firstChild); +a&&g.appendChild(m.createTextNode(a))},z;a.rotation=0;y=this.getSpanWidth(a,g);if(z=y>v){for(;d<=q;)k=Math.ceil((d+q)/2),y=b.substring(0,k)+"\u2026",e(y),y=this.getSpanWidth(a,g),d===q?d=q+1:y>v?q=k-1:d=k;0===q&&e("")}a.rotation=c;return z},escapes:{"\x26":"\x26amp;","\x3c":"\x26lt;","\x3e":"\x26gt;","'":"\x26#39;",'"':"\x26quot;"},buildText:function(a){var b=a.element,v=this,c=v.forExport,y=G(a.textStr,"").toString(),q=-1!==y.indexOf("\x3c"),e=b.childNodes,z,h,A,J,t=f(b,"x"),x=a.styles,B=a.textWidth, +l=x&&x.lineHeight,C=x&&x.textOutline,u=x&&"ellipsis"===x.textOverflow,Q=x&&"nowrap"===x.whiteSpace,w=x&&x.fontSize,R,I,r=e.length,x=B&&!a.added&&this.box,p=function(a){var c;c=/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:w||v.style.fontSize||12;return l?g(l):v.fontMetrics(c,a.getAttribute("style")?a:b).h},K=function(a){F(v.escapes,function(g,b){a=a.replace(new RegExp(g,"g"),b)});return a};R=[y,u,Q,l,C,w,B].join();if(R!==a.textCache){for(a.textCache=R;r--;)b.removeChild(e[r]);q||C||u||B|| +-1!==y.indexOf(" ")?(z=/<.*class="([^"]+)".*>/,h=/<.*style="([^"]+)".*>/,A=/<.*href="([^"]+)".*>/,x&&x.appendChild(b),y=q?y.replace(/<(b|strong)>/g,'\x3cspan style\x3d"font-weight:bold"\x3e').replace(/<(i|em)>/g,'\x3cspan style\x3d"font-style:italic"\x3e').replace(//g,"\x3c/span\x3e").split(//g):[y],y=k(y,function(a){return""!==a}),d(y,function(g,y){var k,q=0;g=g.replace(/^\s+|\s+$/g,"").replace(//g,"\x3c/span\x3e|||"); +k=g.split("|||");d(k,function(g){if(""!==g||1===k.length){var d={},e=m.createElementNS(v.SVG_NS,"tspan"),x,F;z.test(g)&&(x=g.match(z)[1],f(e,"class",x));h.test(g)&&(F=g.match(h)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),f(e,"style",F));A.test(g)&&!c&&(f(e,"onclick",'location.href\x3d"'+g.match(A)[1]+'"'),f(e,"class","highcharts-anchor"),n(e,{cursor:"pointer"}));g=K(g.replace(/<[a-zA-Z\/](.|\n)*?>/g,"")||" ");if(" "!==g){e.appendChild(m.createTextNode(g));q?d.dx=0:y&&null!==t&&(d.x=t);f(e,d);b.appendChild(e); +!q&&I&&(!L&&c&&n(e,{display:"block"}),f(e,"dy",p(e)));if(B){d=g.replace(/([^\^])-/g,"$1- ").split(" ");x=1B,void 0===J&&(J=g),g&&1!==d.length?(e.removeChild(e.firstChild),O.unshift(d.pop())):(d=O,O=[],d.length&&!Q&&(e=m.createElementNS(P,"tspan"),f(e,{dy:C,x:t}),F&&f(e,"style",F),b.appendChild(e)),l>B&&(B=l)),d.length&&e.appendChild(m.createTextNode(d.join(" ").replace(/- /g, +"-")));a.rotation=G}q++}}});I=I||b.childNodes.length}),J&&a.attr("title",a.textStr),x&&x.removeChild(b),C&&a.applyTextOutline&&a.applyTextOutline(C)):b.appendChild(m.createTextNode(K(y)))}},getContrast:function(a){a=r(a).rgba;return 510Math.abs(c.end-c.start-2*Math.PI));var y=Math.cos(k),z=Math.sin(k),h=Math.cos(e),e=Math.sin(e);c=.001>c.end-k-Math.PI?0:1;d=["M",a+d*y,g+q*z,"A",d,q,0,c,1,a+d*h,g+q*e];u(b)&&d.push(v?"M":"L",a+b* +h,g+b*e,"A",b,b,0,c,0,a+b*y,g+b*z);d.push(v?"":"Z");return d},callout:function(a,g,b,v,c){var d=Math.min(c&&c.r||0,b,v),k=d+6,q=c&&c.anchorX;c=c&&c.anchorY;var e;e=["M",a+d,g,"L",a+b-d,g,"C",a+b,g,a+b,g,a+b,g+d,"L",a+b,g+v-d,"C",a+b,g+v,a+b,g+v,a+b-d,g+v,"L",a+d,g+v,"C",a,g+v,a,g+v,a,g+v-d,"L",a,g+d,"C",a,g,a,g,a+d,g];q&&q>b?c>g+k&&cq?c>g+k&&cv&&q>a+k&&qc&&q>a+k&&qa?a+3:Math.round(1.2*a);return{h:b,b:Math.round(.8* +b),f:a}},rotCorr:function(a,g,b){var v=a;g&&b&&(v=Math.max(v*Math.cos(g*e),4));return{x:-a/3*Math.sin(g*e),y:v}},label:function(g,b,k,e,z,h,m,A,L){var y=this,J=y.g("button"!==L&&"label"),t=J.text=y.text("",0,0,m).attr({zIndex:1}),x,F,n=0,B=3,l=0,C,f,Q,G,w,R={},I,P,r=/^url\((.*?)\)$/.test(e),p=r,K,O,N,T;L&&J.addClass("highcharts-"+L);p=r;K=function(){return(I||0)%2/2};O=function(){var a=t.element.style,g={};F=(void 0===C||void 0===f||w)&&u(t.textStr)&&t.getBBox();J.width=(C||F.width||0)+2*B+l;J.height= +(f||F.height||0)+2*B;P=B+y.fontMetrics(a&&a.fontSize,t).b;p&&(x||(J.box=x=y.symbols[e]||r?y.symbol(e):y.rect(),x.addClass(("button"===L?"":"highcharts-label-box")+(L?" highcharts-"+L+"-box":"")),x.add(J),a=K(),g.x=a,g.y=(A?-P:0)+a),g.width=Math.round(J.width),g.height=Math.round(J.height),x.attr(c(g,R)),R={})};N=function(){var a=l+B,g;g=A?0:P;u(C)&&F&&("center"===w||"right"===w)&&(a+={center:.5,right:1}[w]*(C-F.width));if(a!==t.x||g!==t.y)t.attr("x",a),void 0!==g&&t.attr("y",g);t.x=a;t.y=g};T=function(a, +g){x?x.attr(a,g):R[a]=g};J.onAdd=function(){t.add(J);J.attr({text:g||0===g?g:"",x:b,y:k});x&&u(z)&&J.attr({anchorX:z,anchorY:h})};J.widthSetter=function(g){C=a.isNumber(g)?g:null};J.heightSetter=function(a){f=a};J["text-alignSetter"]=function(a){w=a};J.paddingSetter=function(a){u(a)&&a!==B&&(B=J.padding=a,N())};J.paddingLeftSetter=function(a){u(a)&&a!==l&&(l=a,N())};J.alignSetter=function(a){a={left:0,center:.5,right:1}[a];a!==n&&(n=a,F&&J.attr({x:Q}))};J.textSetter=function(a){void 0!==a&&t.textSetter(a); +O();N()};J["stroke-widthSetter"]=function(a,g){a&&(p=!0);I=this["stroke-width"]=a;T(g,a)};J.strokeSetter=J.fillSetter=J.rSetter=function(a,g){"r"!==g&&("fill"===g&&a&&(p=!0),J[g]=a);T(g,a)};J.anchorXSetter=function(a,g){z=J.anchorX=a;T(g,Math.round(a)-K()-Q)};J.anchorYSetter=function(a,g){h=J.anchorY=a;T(g,a-G)};J.xSetter=function(a){J.x=a;n&&(a-=n*((C||F.width)+2*B));Q=Math.round(a);J.attr("translateX",Q)};J.ySetter=function(a){G=J.y=Math.round(a);J.attr("translateY",G)};var U=J.css;return c(J,{css:function(a){if(a){var g= +{};a=q(a);d(J.textProps,function(b){void 0!==a[b]&&(g[b]=a[b],delete a[b])});t.css(g)}return U.call(J,a)},getBBox:function(){return{width:F.width+2*B,height:F.height+2*B,x:F.x-B,y:F.y-B}},shadow:function(a){a&&(O(),x&&x.shadow(a));return J},destroy:function(){v(J.element,"mouseenter");v(J.element,"mouseleave");t&&(t=t.destroy());x&&(x=x.destroy());E.prototype.destroy.call(J);J=y=O=N=T=null}})}});a.Renderer=D})(M);(function(a){var E=a.attr,D=a.createElement,H=a.css,p=a.defined,f=a.each,l=a.extend, +r=a.isFirefox,n=a.isMS,w=a.isWebKit,u=a.pick,e=a.pInt,h=a.SVGRenderer,m=a.win,d=a.wrap;l(a.SVGElement.prototype,{htmlCss:function(a){var b=this.element;if(b=a&&"SPAN"===b.tagName&&a.width)delete a.width,this.textWidth=b,this.updateTransform();a&&"ellipsis"===a.textOverflow&&(a.whiteSpace="nowrap",a.overflow="hidden");this.styles=l(this.styles,a);H(this.element,a);return this},htmlGetBBox:function(){var a=this.element;return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}, +htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,d=this.translateX||0,z=this.translateY||0,h=this.x||0,m=this.y||0,x=this.textAlign||"left",n={left:0,center:.5,right:1}[x],t=this.styles;H(b,{marginLeft:d,marginTop:z});this.shadows&&f(this.shadows,function(a){H(a,{marginLeft:d+1,marginTop:z+1})});this.inverted&&f(b.childNodes,function(c){a.invertChild(c,b)});if("SPAN"===b.tagName){var l=this.rotation,u=e(this.textWidth),q=t&&t.whiteSpace,A=[l,x,b.innerHTML,this.textWidth, +this.textAlign].join();A!==this.cTT&&(t=a.fontMetrics(b.style.fontSize).b,p(l)&&this.setSpanRotation(l,n,t),H(b,{width:"",whiteSpace:q||"nowrap"}),b.offsetWidth>u&&/[ \-]/.test(b.textContent||b.innerText)&&H(b,{width:u+"px",display:"block",whiteSpace:q||"normal"}),this.getSpanCorrection(b.offsetWidth,t,n,l,x));H(b,{left:h+(this.xCorr||0)+"px",top:m+(this.yCorr||0)+"px"});w&&(t=b.offsetHeight);this.cTT=A}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,d){var c={},k=this.renderer.getTransformKey(); +c[k]=c.transform="rotate("+a+"deg)";c[k+(r?"Origin":"-origin")]=c.transformOrigin=100*b+"% "+d+"px";H(this.element,c)},getSpanCorrection:function(a,b,d){this.xCorr=-a*d;this.yCorr=-b}});l(h.prototype,{getTransformKey:function(){return n&&!/Edge/.test(m.navigator.userAgent)?"-ms-transform":w?"-webkit-transform":r?"MozTransform":m.opera?"-o-transform":""},html:function(a,b,k){var c=this.createElement("span"),e=c.element,h=c.renderer,m=h.isSVG,w=function(a,b){f(["opacity","visibility"],function(c){d(a, +c+"Setter",function(a,c,d,k){a.call(this,c,d,k);b[d]=c})})};c.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;this.textStr=a;e.innerHTML=u(a,"");c.htmlUpdateTransform()};m&&w(c,c.element.style);c.xSetter=c.ySetter=c.alignSetter=c.rotationSetter=function(a,b){"align"===b&&(b="textAlign");c[b]=a;c.htmlUpdateTransform()};c.attr({text:a,x:Math.round(b),y:Math.round(k)}).css({fontFamily:this.style.fontFamily,fontSize:this.style.fontSize,position:"absolute"});e.style.whiteSpace="nowrap";c.css= +c.htmlCss;m&&(c.add=function(a){var b,d=h.box.parentNode,k=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)k.push(a),a=a.parentGroup;f(k.reverse(),function(a){function e(g,b){a[b]=g;n?q[h.getTransformKey()]="translate("+(a.x||a.translateX)+"px,"+(a.y||a.translateY)+"px)":"translateX"===b?q.left=g+"px":q.top=g+"px";a.doTransform=!0}var q,g=E(a.element,"class");g&&(g={className:g});b=a.div=a.div||D("div",g,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px",display:a.display, +opacity:a.opacity,pointerEvents:a.styles&&a.styles.pointerEvents},b||d);q=b.style;l(a,{classSetter:function(a){return function(g){this.element.setAttribute("class",g);a.className=g}}(b),on:function(){k[0].div&&c.on.apply({element:k[0].div},arguments);return a},translateXSetter:e,translateYSetter:e});w(a,q)})}}else b=d;b.appendChild(e);c.added=!0;c.alignOnAdd&&c.htmlUpdateTransform();return c});return c}})})(M);(function(a){function E(){var n=a.defaultOptions.global,l=r.moment;if(n.timezone){if(l)return function(a){return-l.tz(a, +n.timezone).utcOffset()};a.error(25)}return n.useUTC&&n.getTimezoneOffset}function D(){var n=a.defaultOptions.global,f,u=n.useUTC,e=u?"getUTC":"get",h=u?"setUTC":"set",m="Minutes Hours Day Date Month FullYear".split(" "),d=m.concat(["Milliseconds","Seconds"]);a.Date=f=n.Date||r.Date;f.hcTimezoneOffset=u&&n.timezoneOffset;f.hcGetTimezoneOffset=E();f.hcHasTimeZone=!(!f.hcTimezoneOffset&&!f.hcGetTimezoneOffset);f.hcMakeTime=function(a,b,d,e,h,m){var c;u?(c=f.UTC.apply(0,arguments),c+=p(c)):c=(new f(a, +b,l(d,1),l(e,0),l(h,0),l(m,0))).getTime();return c};for(n=0;nb&&e-k*zm&&(p=Math.round((h-e)/Math.cos(b*r)));else if(h=e+(1-k)*z,e-k*zm&&(I=m-a.x+I*k,x=-1),I=Math.min(B,I),II||f.autoRotation&&(c.styles||{}).width)p=I;p&&(t.width=p,(n.style||{}).textOverflow||(t.textOverflow="ellipsis"),c.css(t))},getPosition:function(a,f,l,e){var h=this.axis,m=h.chart,d=e&&m.oldChartHeight||m.chartHeight;return{x:a?h.translate(f+l,null,null,e)+h.transB:h.left+h.offset+(h.opposite?(e&&m.oldChartWidth||m.chartWidth)-h.right-h.left:0),y:a?d-h.bottom+h.offset-(h.opposite?h.height:0):d-h.translate(f+l,null,null,e)-h.transB}},getLabelPosition:function(a, +f,l,e,h,m,d,c){var b=this.axis,k=b.transA,z=b.reversed,B=b.staggerLines,n=b.tickRotCorr||{x:0,y:0},x=h.y,u=e||b.reserveSpaceDefault?0:-b.labelOffset*("center"===b.labelAlign?.5:1);D(x)||(x=0===b.side?l.rotation?-8:-l.getBBox().height:2===b.side?n.y+8:Math.cos(l.rotation*r)*(n.y-l.getBBox(!1,0).height/2));a=a+h.x+u+n.x-(m&&e?m*k*(z?-1:1):0);f=f+x-(m&&!e?m*k*(z?1:-1):0);B&&(l=d/(c||1)%B,b.opposite&&(l=B-l-1),f+=b.labelOffset/B*l);return{x:a,y:Math.round(f)}},getMarkPath:function(a,f,l,e,h,m){return m.crispLine(["M", +a,f,"L",a+(h?0:-l),f+(h?l:0)],e)},renderGridLine:function(a,f,l){var e=this.axis,h=e.options,m=this.gridLine,d={},c=this.pos,b=this.type,k=e.tickmarkOffset,z=e.chart.renderer,B=b?b+"Grid":"grid",n=h[B+"LineWidth"],x=h[B+"LineColor"],h=h[B+"LineDashStyle"];m||(d.stroke=x,d["stroke-width"]=n,h&&(d.dashstyle=h),b||(d.zIndex=1),a&&(d.opacity=0),this.gridLine=m=z.path().attr(d).addClass("highcharts-"+(b?b+"-":"")+"grid-line").add(e.gridGroup));if(!a&&m&&(a=e.getPlotLinePath(c+k,m.strokeWidth()*l,a,!0)))m[this.isNew? +"attr":"animate"]({d:a,opacity:f})},renderMark:function(a,f,u){var e=this.axis,h=e.options,m=e.chart.renderer,d=this.type,c=d?d+"Tick":"tick",b=e.tickSize(c),k=this.mark,z=!k,B=a.x;a=a.y;var n=l(h[c+"Width"],!d&&e.isXAxis?1:0),h=h[c+"Color"];b&&(e.opposite&&(b[0]=-b[0]),z&&(this.mark=k=m.path().addClass("highcharts-"+(d?d+"-":"")+"tick").add(e.axisGroup),k.attr({stroke:h,"stroke-width":n})),k[z?"attr":"animate"]({d:this.getMarkPath(B,a,b[0],k.strokeWidth()*u,e.horiz,m),opacity:f}))},renderLabel:function(a, +f,u,e){var h=this.axis,m=h.horiz,d=h.options,c=this.label,b=d.labels,k=b.step,h=h.tickmarkOffset,z=!0,B=a.x;a=a.y;c&&p(B)&&(c.xy=a=this.getLabelPosition(B,a,c,m,b,h,e,k),this.isFirst&&!this.isLast&&!l(d.showFirstLabel,1)||this.isLast&&!this.isFirst&&!l(d.showLastLabel,1)?z=!1:!m||b.step||b.rotation||f||0===u||this.handleOverflow(a),k&&e%k&&(z=!1),z&&p(a.y)?(a.opacity=u,c[this.isNewLabel?"attr":"animate"](a),this.isNewLabel=!1):(c.attr("y",-9999),this.isNewLabel=!0))},render:function(a,f,u){var e= +this.axis,h=e.horiz,m=this.getPosition(h,this.pos,e.tickmarkOffset,f),d=m.x,c=m.y,e=h&&d===e.pos+e.len||!h&&c===e.pos?-1:1;u=l(u,1);this.isActive=!0;this.renderGridLine(f,u,e);this.renderMark(m,u,e);this.renderLabel(m,f,u,a);this.isNew=!1},destroy:function(){H(this,this.axis)}}})(M);var V=function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.color,l=a.correctFloat,r=a.defaultOptions,n=a.defined,w=a.deg2rad,u=a.destroyObjectProperties,e=a.each,h=a.extend,m=a.fireEvent,d=a.format, +c=a.getMagnitude,b=a.grep,k=a.inArray,z=a.isArray,B=a.isNumber,I=a.isString,x=a.merge,K=a.normalizeTickInterval,t=a.objectEach,C=a.pick,N=a.removeEvent,q=a.splat,A=a.syncTimeout,F=a.Tick,G=function(){this.init.apply(this,arguments)};a.extend(G.prototype,{defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,labels:{enabled:!0,style:{color:"#666666",cursor:"default",fontSize:"11px"}, +x:0},maxPadding:.01,minorTickLength:2,minorTickPosition:"outside",minPadding:.01,startOfWeek:1,startOnTick:!1,tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",title:{align:"middle",style:{color:"#666666"}},type:"linear",minorGridLineColor:"#f2f2f2",minorGridLineWidth:1,minorTickColor:"#999999",lineColor:"#ccd6eb",lineWidth:1,gridLineColor:"#e6e6e6",tickColor:"#ccd6eb"},defaultYAxisOptions:{endOnTick:!0,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8},maxPadding:.05, +minPadding:.05,startOnTick:!0,title:{rotation:270,text:"Values"},stackLabels:{allowOverlap:!1,enabled:!1,formatter:function(){return a.numberFormat(this.total,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"#000000",textOutline:"1px contrast"}},gridLineWidth:1,lineWidth:0},defaultLeftAxisOptions:{labels:{x:-15},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45], +x:0},title:{rotation:0}},init:function(a,b){var g=b.isX,v=this;v.chart=a;v.horiz=a.inverted&&!v.isZAxis?!g:g;v.isXAxis=g;v.coll=v.coll||(g?"xAxis":"yAxis");v.opposite=b.opposite;v.side=b.side||(v.horiz?v.opposite?0:2:v.opposite?1:3);v.setOptions(b);var c=this.options,d=c.type;v.labelFormatter=c.labels.formatter||v.defaultLabelFormatter;v.userOptions=b;v.minPixelPadding=0;v.reversed=c.reversed;v.visible=!1!==c.visible;v.zoomEnabled=!1!==c.zoomEnabled;v.hasNames="category"===d||!0===c.categories;v.categories= +c.categories||v.hasNames;v.names=v.names||[];v.plotLinesAndBandsGroups={};v.isLog="logarithmic"===d;v.isDatetimeAxis="datetime"===d;v.positiveValuesOnly=v.isLog&&!v.allowNegativeLog;v.isLinked=n(c.linkedTo);v.ticks={};v.labelEdge=[];v.minorTicks={};v.plotLinesAndBands=[];v.alternateBands={};v.len=0;v.minRange=v.userMinRange=c.minRange||c.maxZoom;v.range=c.range;v.offset=c.offset||0;v.stacks={};v.oldStacks={};v.stacksTouched=0;v.max=null;v.min=null;v.crosshair=C(c.crosshair,q(a.options.tooltip.crosshairs)[g? +0:1],!1);b=v.options.events;-1===k(v,a.axes)&&(g?a.axes.splice(a.xAxis.length,0,v):a.axes.push(v),a[v.coll].push(v));v.series=v.series||[];a.inverted&&!v.isZAxis&&g&&void 0===v.reversed&&(v.reversed=!0);t(b,function(a,g){E(v,g,a)});v.lin2log=c.linearToLogConverter||v.lin2log;v.isLog&&(v.val2lin=v.log2lin,v.lin2val=v.lin2log)},setOptions:function(a){this.options=x(this.defaultOptions,"yAxis"===this.coll&&this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions, +this.defaultLeftAxisOptions][this.side],x(r[this.coll],a))},defaultLabelFormatter:function(){var g=this.axis,b=this.value,c=g.categories,k=this.dateTimeLabelFormat,e=r.lang,q=e.numericSymbols,e=e.numericSymbolMagnitude||1E3,h=q&&q.length,m,z=g.options.labels.format,g=g.isLog?Math.abs(b):g.tickInterval;if(z)m=d(z,this);else if(c)m=b;else if(k)m=a.dateFormat(k,b);else if(h&&1E3<=g)for(;h--&&void 0===m;)c=Math.pow(e,h+1),g>=c&&0===10*b%c&&null!==q[h]&&0!==b&&(m=a.numberFormat(b/c,-1)+q[h]);void 0=== +m&&(m=1E4<=Math.abs(b)?a.numberFormat(b,-1):a.numberFormat(b,-1,void 0,""));return m},getSeriesExtremes:function(){var a=this,v=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.threshold=null;a.softThreshold=!a.isXAxis;a.buildStacks&&a.buildStacks();e(a.series,function(g){if(g.visible||!v.options.chart.ignoreHiddenSeries){var c=g.options,d=c.threshold,k;a.hasVisibleSeries=!0;a.positiveValuesOnly&&0>=d&&(d=null);if(a.isXAxis)c=g.xData,c.length&&(g=p(c),k=H(c),B(g)||g instanceof Date||(c=b(c,B), +g=p(c)),a.dataMin=Math.min(C(a.dataMin,c[0],g),g),a.dataMax=Math.max(C(a.dataMax,c[0],k),k));else if(g.getExtremes(),k=g.dataMax,g=g.dataMin,n(g)&&n(k)&&(a.dataMin=Math.min(C(a.dataMin,g),g),a.dataMax=Math.max(C(a.dataMax,k),k)),n(d)&&(a.threshold=d),!c.softThreshold||a.positiveValuesOnly)a.softThreshold=!1}})},translate:function(a,b,c,d,k,e){var g=this.linkedParent||this,v=1,q=0,h=d?g.oldTransA:g.transA;d=d?g.oldMin:g.min;var m=g.minPixelPadding;k=(g.isOrdinal||g.isBroken||g.isLog&&k)&&g.lin2val; +h||(h=g.transA);c&&(v*=-1,q=g.len);g.reversed&&(v*=-1,q-=v*(g.sector||g.len));b?(a=(a*v+q-m)/h+d,k&&(a=g.lin2val(a))):(k&&(a=g.val2lin(a)),a=B(d)?v*(a-d)*h+q+v*m+(B(e)?h*e:0):void 0);return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d,k){var g=this.chart,v=this.left,q=this.top,e,h,m=c&&g.oldChartHeight||g.chartHeight,z=c&&g.oldChartWidth|| +g.chartWidth,A;e=this.transB;var t=function(a,g,b){if(ab)d?a=Math.min(Math.max(g,a),b):A=!0;return a};k=C(k,this.translate(a,null,null,c));a=c=Math.round(k+e);e=h=Math.round(m-k-e);B(k)?this.horiz?(e=q,h=m-this.bottom,a=c=t(a,v,v+this.width)):(a=v,c=z-this.right,e=h=t(e,q,q+this.height)):(A=!0,d=!1);return A&&!d?null:g.renderer.crispLine(["M",a,e,"L",c,h],b||1)},getLinearTickPositions:function(a,b,c){var g,v=l(Math.floor(b/a)*a);c=l(Math.ceil(c/a)*a);var d=[],k;l(v+a)===v&&(k=20);if(this.single)return[b]; +for(b=v;b<=c;){d.push(b);b=l(b+a,k);if(b===g)break;g=b}return d},getMinorTickInterval:function(){var a=this.options;return!0===a.minorTicks?C(a.minorTickInterval,"auto"):!1===a.minorTicks?null:a.minorTickInterval},getMinorTickPositions:function(){var a=this,b=a.options,c=a.tickPositions,d=a.minorTickInterval,k=[],q=a.pointRangePadding||0,h=a.min-q,q=a.max+q,m=q-h;if(m&&m/d=this.minRange,t=this.minRange,d=(t-c+b)/2,d=[b-d,C(a.min,b-d)],k&&(d[2]=this.isLog?this.log2lin(this.dataMin):this.dataMin),b=H(d),c=[b+t,C(a.max,b+t)],k&&(c[2]=this.isLog?this.log2lin(this.dataMax):this.dataMax),c=p(c),c-b=p?(r=p,f=0):b.dataMax<=p&&(w=p,x=0)),b.min= +C(N,r,b.dataMin),b.max=C(D,w,b.dataMax));q&&(b.positiveValuesOnly&&!g&&0>=Math.min(b.min,C(b.dataMin,b.min))&&a.error(10,1),b.min=l(h(b.min),15),b.max=l(h(b.max),15));b.range&&n(b.max)&&(b.userMin=b.min=N=Math.max(b.dataMin,b.minFromRange()),b.userMax=D=b.max,b.range=null);m(b,"foundExtremes");b.beforePadding&&b.beforePadding();b.adjustForMinRange();!(G||b.axisPointRange||b.usePercentage||t)&&n(b.min)&&n(b.max)&&(h=b.max-b.min)&&(!n(N)&&f&&(b.min-=h*f),!n(D)&&x&&(b.max+=h*x));B(k.softMin)&&!B(b.userMin)&& +(b.min=Math.min(b.min,k.softMin));B(k.softMax)&&!B(b.userMax)&&(b.max=Math.max(b.max,k.softMax));B(k.floor)&&(b.min=Math.max(b.min,k.floor));B(k.ceiling)&&(b.max=Math.min(b.max,k.ceiling));I&&n(b.dataMin)&&(p=p||0,!n(N)&&b.min=p?b.min=p:!n(D)&&b.max>p&&b.dataMax<=p&&(b.max=p));b.tickInterval=b.min===b.max||void 0===b.min||void 0===b.max?1:t&&!F&&u===b.linkedParent.options.tickPixelInterval?F=b.linkedParent.tickInterval:C(F,this.tickAmount?(b.max-b.min)/Math.max(this.tickAmount-1,1): +void 0,G?1:(b.max-b.min)*u/Math.max(b.len,u));A&&!g&&e(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();b.postProcessTickInterval&&(b.tickInterval=b.postProcessTickInterval(b.tickInterval));b.pointRange&&!F&&(b.tickInterval=Math.max(b.pointRange,b.tickInterval));g=C(k.minTickInterval,b.isDatetimeAxis&&b.closestPointRange);!F&&b.tickIntervalb.tickInterval&&1E3b.max)),!!this.tickAmount));this.tickAmount||(b.tickInterval=b.unsquish());this.setTickPositions()},setTickPositions:function(){var a=this.options,b,c=a.tickPositions;b=this.getMinorTickInterval();var d=a.tickPositioner,k=a.startOnTick,q=a.endOnTick;this.tickmarkOffset=this.categories&&"between"===a.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===b&&this.tickInterval?this.tickInterval/ +5:b;this.single=this.min===this.max&&n(this.min)&&!this.tickAmount&&(parseInt(this.min,10)===this.min||!1!==a.allowDecimals);this.tickPositions=b=c&&c.slice();!b&&(b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),b.length>this.len&&(b= +[b[0],b.pop()],b[0]===b[1]&&(b.length=1)),this.tickPositions=b,d&&(d=d.apply(this,[this.min,this.max])))&&(this.tickPositions=b=d);this.paddedTicks=b.slice(0);this.trimTicks(b,k,q);this.isLinked||(this.single&&2>b.length&&(this.min-=.5,this.max+=.5),c||d||this.adjustTickAmount())},trimTicks:function(a,b,c){var g=a[0],d=a[a.length-1],k=this.minPointOffset||0;if(!this.isLinked){if(b&&-Infinity!==g)this.min=g;else for(;this.min-k>a[0];)a.shift();if(c)this.max=d;else for(;this.max+kb&&(this.finalTickAmt=b,b=5);this.tickAmount=b},adjustTickAmount:function(){var a=this.tickInterval,b=this.tickPositions,c=this.tickAmount,d=this.finalTickAmt,k=b&&b.length,q=C(this.threshold,this.softThreshold?0:null);if(this.hasData()){if(kc&&(this.tickInterval*= +2,this.setTickPositions());if(n(d)){for(a=c=b.length;a--;)(3===d&&1===a%2||2>=d&&0d&&(a=d)),n(c)&&(bd&&(b=d))),this.displayBtn=void 0!==a||void 0!==b,this.setExtremes(a,b,!1,void 0,{trigger:"zoom"});return!0},setAxisSize:function(){var b=this.chart,c=this.options,d=c.offsets||[0,0,0,0],k=this.horiz,q=this.width=Math.round(a.relativeLength(C(c.width,b.plotWidth-d[3]+d[1]),b.plotWidth)),e=this.height=Math.round(a.relativeLength(C(c.height, +b.plotHeight-d[0]+d[2]),b.plotHeight)),h=this.top=Math.round(a.relativeLength(C(c.top,b.plotTop+d[0]),b.plotHeight,b.plotTop)),c=this.left=Math.round(a.relativeLength(C(c.left,b.plotLeft+d[3]),b.plotWidth,b.plotLeft));this.bottom=b.chartHeight-e-h;this.right=b.chartWidth-q-c;this.len=Math.max(k?q:e,0);this.pos=k?c:h},getExtremes:function(){var a=this.isLog,b=this.lin2log;return{min:a?l(b(this.min)):this.min,max:a?l(b(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin, +userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,g=this.lin2log,c=b?g(this.min):this.min,b=b?g(this.max):this.max;null===a?a=c:c>a?a=c:ba?"right":195a?"left":"center"},tickSize:function(a){var b=this.options,g=b[a+"Length"],c=C(b[a+"Width"],"tick"===a&&this.isXAxis?1:0);if(c&&g)return"inside"===b[a+"Position"]&&(g=-g),[g,c]},labelMetrics:function(){var a= +this.tickPositions&&this.tickPositions[0]||0;return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize,this.ticks[a]&&this.ticks[a].label)},unsquish:function(){var a=this.options.labels,b=this.horiz,c=this.tickInterval,d=c,k=this.len/(((this.categories?1:0)+this.max-this.min)/c),q,h=a.rotation,m=this.labelMetrics(),z,A=Number.MAX_VALUE,t,x=function(a){a/=k||1;a=1=a)z=x(Math.abs(m.h/Math.sin(w*a))),b=z+Math.abs(a/360),b(c.step||0)&&!c.rotation&&(this.staggerLines||1)*this.len/d||!b&&(c.style&&parseInt(c.style.width,10)||k&&k-a.spacing[3]|| +.33*a.chartWidth)},renderUnsquish:function(){var a=this.chart,b=a.renderer,c=this.tickPositions,d=this.ticks,k=this.options.labels,q=this.horiz,h=this.getSlotWidth(),m=Math.max(1,Math.round(h-2*(k.padding||5))),z={},A=this.labelMetrics(),t=k.style&&k.style.textOverflow,f,F=0,l,B;I(k.rotation)||(z.rotation=k.rotation||0);e(c,function(a){(a=d[a])&&a.labelLength>F&&(F=a.labelLength)});this.maxLabelLength=F;if(this.autoRotation)F>m&&F>A.h?z.rotation=this.labelRotation:this.labelRotation=0;else if(h&& +(f={width:m+"px"},!t))for(f.textOverflow="clip",l=c.length;!q&&l--;)if(B=c[l],m=d[B].label)m.styles&&"ellipsis"===m.styles.textOverflow?m.css({textOverflow:"clip"}):d[B].labelLength>h&&m.css({width:h+"px"}),m.getBBox().height>this.len/c.length-(A.h-A.f)&&(m.specCss={textOverflow:"ellipsis"});z.rotation&&(f={width:(F>.5*a.chartHeight?.33*a.chartHeight:a.chartHeight)+"px"},t||(f.textOverflow="ellipsis"));if(this.labelAlign=k.align||this.autoLabelAlign(this.labelRotation))z.align=this.labelAlign;e(c, +function(a){var b=(a=d[a])&&a.label;b&&(b.attr(z),f&&b.css(x(f,b.specCss)),delete b.specCss,a.rotation=z.rotation)});this.tickRotCorr=b.rotCorr(A.b,this.labelRotation||0,0!==this.side)},hasData:function(){return this.hasVisibleSeries||n(this.min)&&n(this.max)&&this.tickPositions&&0=this.min&&a<=this.max)g[a]||(g[a]=new F(this,a)),d&&g[a].isNew&&g[a].render(b,!0,.1),g[a].render(b)},render:function(){var b= +this,c=b.chart,d=b.options,k=b.isLog,q=b.lin2log,h=b.isLinked,m=b.tickPositions,z=b.axisTitle,x=b.ticks,f=b.minorTicks,l=b.alternateBands,C=d.stackLabels,n=d.alternateGridColor,u=b.tickmarkOffset,G=b.axisLine,p=b.showAxis,I=D(c.renderer.globalAnimation),r,w;b.labelEdge.length=0;b.overlap=!1;e([x,f,l],function(a){t(a,function(a){a.isActive=!1})});if(b.hasData()||h)b.minorTickInterval&&!b.categories&&e(b.getMinorTickPositions(),function(a){b.renderMinorTick(a)}),m.length&&(e(m,function(a,c){b.renderTick(a, +c)}),u&&(0===b.min||b.single)&&(x[-1]||(x[-1]=new F(b,-1,null,!0)),x[-1].render(-1))),n&&e(m,function(d,g){w=void 0!==m[g+1]?m[g+1]+u:b.max-u;0===g%2&&d=h.second?0:C*Math.floor(x.getMilliseconds()/C));if(t>=h.second)x[D.hcSetSeconds](t>=h.minute? +0:C*Math.floor(x.getSeconds()/C));if(t>=h.minute)x[D.hcSetMinutes](t>=h.hour?0:C*Math.floor(x[D.hcGetMinutes]()/C));if(t>=h.hour)x[D.hcSetHours](t>=h.day?0:C*Math.floor(x[D.hcGetHours]()/C));if(t>=h.day)x[D.hcSetDate](t>=h.month?1:C*Math.floor(x[D.hcGetDate]()/C));t>=h.month&&(x[D.hcSetMonth](t>=h.year?0:C*Math.floor(x[D.hcGetMonth]()/C)),n=x[D.hcGetFullYear]());if(t>=h.year)x[D.hcSetFullYear](n-n%C);if(t===h.week)x[D.hcSetDate](x[D.hcGetDate]()-x[D.hcGetDay]()+e(b,1));n=x[D.hcGetFullYear]();b=x[D.hcGetMonth](); +var A=x[D.hcGetDate](),F=x[D.hcGetHours]();d=x.getTime();D.hcHasTimeZone&&(q=(!B||!!D.hcGetTimezoneOffset)&&(c-d>4*h.month||w(d)!==w(c)),N=w(x),x=new D(d+N));B=x.getTime();for(d=1;Bk.length&&l(k,function(a){0===a%18E5&&"000000000"===H("%H%M%S%L",a)&&(m[a]="day")})}k.info=r(a,{higherRanks:m,totalRange:t*C});return k}; +E.prototype.normalizeTimeTickInterval=function(a,d){var c=d||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2,3,4,6]],["year",null]];d=c[c.length-1];var b=h[d[0]],k=d[1],e;for(e=0;er&&(!w||z<=n)&&void 0!==z&&d.push(z),z>n&& +(B=!0),z=k;else r=h(r),n=h(n),a=w?this.getMinorTickInterval():l.tickInterval,a=f("auto"===a?null:a,this._minorAutoInterval,l.tickPixelInterval/(w?5:1)*(n-r)/((w?e/this.tickPositions.length:e)||1)),a=p(a,null,D(a)),d=H(this.getLinearTickPositions(a,r,n),m),w||(this._minorAutoInterval=a/5);w||(this.tickInterval=a);return d};E.prototype.log2lin=function(a){return Math.log(a)/Math.LN10};E.prototype.lin2log=function(a){return Math.pow(10,a)}})(M);(function(a,E){var D=a.arrayMax,H=a.arrayMin,p=a.defined, +f=a.destroyObjectProperties,l=a.each,r=a.erase,n=a.merge,w=a.pick;a.PlotLineOrBand=function(a,e){this.axis=a;e&&(this.options=e,this.id=e.id)};a.PlotLineOrBand.prototype={render:function(){var f=this,e=f.axis,h=e.horiz,m=f.options,d=m.label,c=f.label,b=m.to,k=m.from,z=m.value,l=p(k)&&p(b),r=p(z),x=f.svgElem,K=!x,t=[],C=m.color,N=w(m.zIndex,0),q=m.events,t={"class":"highcharts-plot-"+(l?"band ":"line ")+(m.className||"")},A={},F=e.chart.renderer,G=l?"bands":"lines",g=e.log2lin;e.isLog&&(k=g(k),b=g(b), +z=g(z));r?(t={stroke:C,"stroke-width":m.width},m.dashStyle&&(t.dashstyle=m.dashStyle)):l&&(C&&(t.fill=C),m.borderWidth&&(t.stroke=m.borderColor,t["stroke-width"]=m.borderWidth));A.zIndex=N;G+="-"+N;(C=e.plotLinesAndBandsGroups[G])||(e.plotLinesAndBandsGroups[G]=C=F.g("plot-"+G).attr(A).add());K&&(f.svgElem=x=F.path().attr(t).add(C));if(r)t=e.getPlotLinePath(z,x.strokeWidth());else if(l)t=e.getPlotBandPath(k,b,m);else return;K&&t&&t.length?(x.attr({d:t}),q&&a.objectEach(q,function(a,b){x.on(b,function(a){q[b].apply(f, +[a])})})):x&&(t?(x.show(),x.animate({d:t})):(x.hide(),c&&(f.label=c=c.destroy())));d&&p(d.text)&&t&&t.length&&0this.max&& +e>this.max;if(m&&h)for(a&&(k=m.toString()===h.toString(),b=0),a=0;aA-h?A:A-h);else if(z)k[a]=Math.max(e,g+h+d>c?g:g+h);else return!1},C=function(a,c,d,g){var e;gc-b?e=!1:k[a]=gc-d/2?c-d-2:g-d/2;return e},p=function(a){var b=f;f=x;x=b;m=a},q=function(){!1!==t.apply(0,f)?!1!==C.apply(0,x)||m||(p(!0),q()):m?k.x=k.y=0:(p(!0),q())};(c.inverted||1q&&(h=!1);a=(e.series&& +e.series.yAxis&&e.series.yAxis.pos)+(e.plotY||0);a-=b.plotTop;c.push({target:e.isHeader?b.plotHeight+l:a,rank:e.isHeader?1:0,size:z.tt.getBBox().height+1,point:e,x:q,tt:t})}});this.cleanSplit();a.distribute(c,b.plotHeight+l);D(c,function(a){var c=a.point,d=c.series;a.tt.attr({visibility:void 0===a.pos?"hidden":"inherit",x:h||c.isHeader?a.x:c.plotX+b.plotLeft+n(f.distance,16),y:a.pos+b.plotTop,anchorX:c.isHeader?c.plotX+b.plotLeft:c.plotX+d.xAxis.pos,anchorY:c.isHeader?a.pos+b.plotTop-15:c.plotY+d.yAxis.pos})})}, +updatePosition:function(a){var e=this.chart,d=this.getLabel(),d=(this.options.positioner||this.getPosition).call(this,d.width,d.height,a);this.move(Math.round(d.x),Math.round(d.y||0),a.plotX+e.plotLeft,a.plotY+e.plotTop)},getDateFormat:function(a,m,d,c){var b=E("%m-%d %H:%M:%S.%L",m),k,h,f={millisecond:15,second:12,minute:9,hour:6,day:3},l="millisecond";for(h in e){if(a===e.week&&+E("%w",m)===d&&"00:00:00.000"===b.substr(6)){h="week";break}if(e[h]>a){h=l;break}if(f[h]&&b.substr(f[h])!=="01-01 00:00:00.000".substr(f[h]))break; +"week"!==h&&(l=h)}h&&(k=c[h]);return k},getXDateFormat:function(a,e,d){e=e.dateTimeLabelFormats;var c=d&&d.closestPointRange;return(c?this.getDateFormat(c,a.x,d.options.startOfWeek,e):e.day)||e.year},tooltipFooterHeaderFormatter:function(a,e){e=e?"footer":"header";var d=a.series,c=d.tooltipOptions,b=c.xDateFormat,k=d.xAxis,h=k&&"datetime"===k.options.type&&f(a.key),m=c[e+"Format"];h&&!b&&(b=this.getXDateFormat(a,c,k));h&&b&&D(a.point&&a.point.tooltipDateKeys||["key"],function(a){m=m.replace("{point."+ +a+"}","{point."+a+":"+b+"}")});return p(m,{point:a,series:d})},bodyFormatter:function(a){return l(a,function(a){var d=a.series.tooltipOptions;return(d[(a.point.formatPrefix||"point")+"Formatter"]||a.point.tooltipFormatter).call(a.point,d[(a.point.formatPrefix||"point")+"Format"])})}}})(M);(function(a){var E=a.addEvent,D=a.attr,H=a.charts,p=a.color,f=a.css,l=a.defined,r=a.each,n=a.extend,w=a.find,u=a.fireEvent,e=a.isObject,h=a.offset,m=a.pick,d=a.splat,c=a.Tooltip;a.Pointer=function(a,c){this.init(a, +c)};a.Pointer.prototype={init:function(a,d){this.options=d;this.chart=a;this.runChartClick=d.chart.events&&!!d.chart.events.click;this.pinchDown=[];this.lastValidTouch={};c&&(a.tooltip=new c(a,d.tooltip),this.followTouchMove=m(d.tooltip.followTouchMove,!0));this.setDOMEvents()},zoomOption:function(a){var b=this.chart,c=b.options.chart,d=c.zoomType||"",b=b.inverted;/touch/.test(a.type)&&(d=m(c.pinchType,d));this.zoomX=a=/x/.test(d);this.zoomY=d=/y/.test(d);this.zoomHor=a&&!b||d&&b;this.zoomVert=d&& +!b||a&&b;this.hasZoom=a||d},normalize:function(a,c){var b;b=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:a;c||(this.chartPosition=c=h(this.chart.container));return n(a,{chartX:Math.round(b.pageX-c.left),chartY:Math.round(b.pageY-c.top)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};r(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},findNearestKDPoint:function(a,c,d){var b;r(a,function(a){var k= +!(a.noSharedTooltip&&c)&&0>a.options.findNearestPointBy.indexOf("y");a=a.searchPoint(d,k);if((k=e(a,!0))&&!(k=!e(b,!0)))var k=b.distX-a.distX,h=b.dist-a.dist,m=(a.series.group&&a.series.group.zIndex)-(b.series.group&&b.series.group.zIndex),k=0<(0!==k&&c?k:0!==h?h:0!==m?m:b.series.index>a.series.index?-1:1);k&&(b=a)});return b},getPointFromEvent:function(a){a=a.target;for(var b;a&&!b;)b=a.point,a=a.parentNode;return b},getChartCoordinatesFromPoint:function(a,c){var b=a.series,d=b.xAxis,b=b.yAxis,k= +m(a.clientX,a.plotX);if(d&&b)return c?{chartX:d.len+d.pos-k,chartY:b.len+b.pos-a.plotY}:{chartX:k+d.pos,chartY:a.plotY+b.pos}},getHoverData:function(b,c,d,h,f,l,n){var k,z=[],x=n&&n.isBoosting;h=!(!h||!b);n=c&&!c.stickyTracking?[c]:a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking,!0)&&a.stickyTracking});c=(k=h?b:this.findNearestKDPoint(n,f,l))&&k.series;k&&(f&&!c.noSharedTooltip?(n=a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking, +!0)&&!a.noSharedTooltip}),r(n,function(a){var b=w(a.points,function(a){return a.x===k.x&&!a.isNull});e(b)&&(x&&(b=a.getPoint(b)),z.push(b))})):z.push(k));return{hoverPoint:k,hoverSeries:c,hoverPoints:z}},runPointActions:function(b,c){var d=this.chart,k=d.tooltip&&d.tooltip.options.enabled?d.tooltip:void 0,e=k?k.shared:!1,h=c||d.hoverPoint,f=h&&h.series||d.hoverSeries,f=this.getHoverData(h,f,d.series,!!c||f&&f.directTouch&&this.isDirectTouch,e,b,{isBoosting:d.isBoosting}),l,h=f.hoverPoint;l=f.hoverPoints; +c=(f=f.hoverSeries)&&f.tooltipOptions.followPointer;e=e&&f&&!f.noSharedTooltip;if(h&&(h!==d.hoverPoint||k&&k.isHidden)){r(d.hoverPoints||[],function(b){-1===a.inArray(b,l)&&b.setState()});r(l||[],function(a){a.setState("hover")});if(d.hoverSeries!==f)f.onMouseOver();d.hoverPoint&&d.hoverPoint.firePointEvent("mouseOut");if(!h.series)return;h.firePointEvent("mouseOver");d.hoverPoints=l;d.hoverPoint=h;k&&k.refresh(e?l:h,b)}else c&&k&&!k.isHidden&&(h=k.getAnchor([{}],b),k.updatePosition({plotX:h[0],plotY:h[1]})); +this.unDocMouseMove||(this.unDocMouseMove=E(d.container.ownerDocument,"mousemove",function(b){var c=H[a.hoverChartIndex];if(c)c.pointer.onDocumentMouseMove(b)}));r(d.axes,function(c){var d=m(c.crosshair.snap,!0),k=d?a.find(l,function(a){return a.series[c.coll]===c}):void 0;k||!d?c.drawCrosshair(b,k):c.hideCrosshair()})},reset:function(a,c){var b=this.chart,k=b.hoverSeries,e=b.hoverPoint,h=b.hoverPoints,m=b.tooltip,f=m&&m.shared?h:e;a&&f&&r(d(f),function(b){b.series.isCartesian&&void 0===b.plotX&& +(a=!1)});if(a)m&&f&&(m.refresh(f),e&&(e.setState(e.state,!0),r(b.axes,function(a){a.crosshair&&a.drawCrosshair(null,e)})));else{if(e)e.onMouseOut();h&&r(h,function(a){a.setState()});if(k)k.onMouseOut();m&&m.hide(c);this.unDocMouseMove&&(this.unDocMouseMove=this.unDocMouseMove());r(b.axes,function(a){a.hideCrosshair()});this.hoverX=b.hoverPoints=b.hoverPoint=null}},scaleGroups:function(a,c){var b=this.chart,d;r(b.series,function(k){d=a||k.getPlotBox();k.xAxis&&k.xAxis.zoomEnabled&&k.group&&(k.group.attr(d), +k.markerGroup&&(k.markerGroup.attr(d),k.markerGroup.clip(c?b.clipRect:null)),k.dataLabelsGroup&&k.dataLabelsGroup.attr(d))});b.clipRect.attr(c||b.clipBox)},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,h=this.zoomHor,m=this.zoomVert,f=b.plotLeft,l=b.plotTop,n=b.plotWidth,q=b.plotHeight,A,F=this.selectionMarker,G=this.mouseDownX, +g=this.mouseDownY,v=c.panKey&&a[c.panKey+"Key"];F&&F.touch||(df+n&&(d=f+n),el+q&&(e=l+q),this.hasDragged=Math.sqrt(Math.pow(G-d,2)+Math.pow(g-e,2)),10u.max&&(f=u.max-x,v=!0);v?(F-=.8*(F-m[b][0]),q||(g-=.8*(g-m[b][1])),l()):m[b]=[F,g];C||(h[b]=w-r,h[n]=x);h=C?1/t:t;e[n]=x;e[b]=f;p[C?a?"scaleY":"scaleX":"scale"+k]=t;p["translate"+k]=h*r+(F-h*A)},pinch:function(a){var n=this,r=n.chart,u=n.pinchDown,e=a.touches,h=e.length,m=n.lastValidTouch, +d=n.hasZoom,c=n.selectionMarker,b={},k=1===h&&(n.inClass(a.target,"highcharts-tracker")&&r.runTrackerClick||n.runChartClick),z={};1c-6&&h(q||c.spacingBox.width-2*t-d.x)&&(this.itemX=t,this.itemY+=F+this.lastLineHeight+A,this.lastLineHeight=0);this.maxItemWidth=Math.max(this.maxItemWidth,m);this.lastItemY=F+this.itemY+A;this.lastLineHeight=Math.max(b,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=m:(this.itemY+=F+b+A,this.lastLineHeight=b);this.offsetWidth=q||Math.max((e?this.itemX-t-(a.checkbox?0:p):m)+t,this.offsetWidth)}, +getAllItems:function(){var a=[];f(this.chart.series,function(c){var b=c&&c.options;c&&w(b.showInLegend,p(b.linkedTo)?!1:void 0,!0)&&(a=a.concat(c.legendItems||("point"===b.legendType?c.data:c)))});return a},getAlignment:function(){var a=this.options;return a.floating?"":a.align.charAt(0)+a.verticalAlign.charAt(0)+a.layout.charAt(0)},adjustMargins:function(a,c){var b=this.chart,d=this.options,e=this.getAlignment();e&&f([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(k,h){k.test(e)&& +!p(a[h])&&(b[r[h]]=Math.max(b[r[h]],b.legend[(h+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][h]*d[h%2?"x":"y"]+w(d.margin,12)+c[h]+(0===h?b.titleOffset+b.options.title.margin:0)))})},render:function(){var a=this,c=a.chart,b=c.renderer,k=a.group,h,m,l,x,p=a.box,t=a.options,C=a.padding;a.itemX=C;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;k||(a.group=k=b.g("legend").attr({zIndex:7}).add(),a.contentGroup=b.g().attr({zIndex:1}).add(k),a.scrollGroup=b.g().add(a.contentGroup));a.renderTitle(); +h=a.getAllItems();e(h,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});t.reversed&&h.reverse();a.allItems=h;a.display=m=!!h.length;a.lastLineHeight=0;f(h,function(b){a.renderItem(b)});l=(t.width||a.offsetWidth)+C;x=a.lastItemY+a.lastLineHeight+a.titleHeight;x=a.handleOverflow(x);x+=C;p||(a.box=p=b.rect().addClass("highcharts-legend-box").attr({r:t.borderRadius}).add(k),p.isNew=!0);p.attr({stroke:t.borderColor,"stroke-width":t.borderWidth||0,fill:t.backgroundColor|| +"none"}).shadow(t.shadow);0b&&!1!==t.enabled?(this.clipHeight=l=Math.max(b-20-this.titleHeight-m,0),this.currentPage=w(this.currentPage,1),this.fullHeight=a,f(G,function(a,b){var c=a._legendItemPos[1],d=Math.round(a.legendItem.getBBox().height),g=A.length;if(!g||c-A[g-1]>l&&(F||c)!==A[g-1])A.push(F||c),g++;a.pageIx=g-1;F&&(G[b-1].pageIx=g-1);b===G.length-1&&c+d-A[g-1]>l&&(A.push(c),a.pageIx=g);c!==F&&(F=c)}),n||(n=c.clipRect=d.clipRect(0,m,9999,0),c.contentGroup.clip(n)),g(l),q||(this.nav=q=d.g().attr({zIndex:1}).add(this.group), +this.up=d.symbol("triangle",0,0,r,r).on("click",function(){c.scroll(-1,p)}).add(q),this.pager=d.text("",15,10).addClass("highcharts-legend-navigation").css(t.style).add(q),this.down=d.symbol("triangle-down",0,0,r,r).on("click",function(){c.scroll(1,p)}).add(q)),c.scroll(0),a=b):q&&(g(),this.nav=q.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return a},scroll:function(a,c){var b=this.pages,d=b.length;a=this.currentPage+a;var e=this.clipHeight,h=this.options.navigation,f=this.pager, +m=this.padding;a>d&&(a=d);0b&&(f=typeof a[0],"string"===f?e.name=a[0]:"number"===f&&(e.x=a[0]),k++);l=d.value;)d=h[++f];d&&d.color&&!this.options.color&&(this.color=d.color);return d},destroy:function(){var a=this.series.chart,h=a.hoverPoints,f;a.pointCount--;h&&(this.setState(),p(h,this),h.length||(a.hoverPoints=null));if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)u(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(f in this)this[f]=null},destroyElements:function(){for(var a=["graphic","dataLabel", +"dataLabelUpper","connector","shadowGroup"],h,f=6;f--;)h=a[f],this[h]&&(this[h]=this[h].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,color:this.color,colorIndex:this.colorIndex,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},tooltipFormatter:function(a){var e=this.series,f=e.tooltipOptions,d=w(f.valueDecimals,""),c=f.valuePrefix||"",b=f.valueSuffix||"";D(e.pointArrayMap||["y"],function(e){e="{point."+ +e;if(c||b)a=a.replace(e+"}",c+e+"}"+b);a=a.replace(e+"}",e+":,."+d+"f}")});return l(a,{point:this,series:this.series})},firePointEvent:function(a,h,m){var d=this,c=this.series.options;(c.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents();"click"===a&&c.allowPointSelect&&(m=function(a){d.select&&d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});f(this,a,h,m)},visible:!0}})(M);(function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.correctFloat, +l=a.Date,r=a.defaultOptions,n=a.defaultPlotOptions,w=a.defined,u=a.each,e=a.erase,h=a.extend,m=a.fireEvent,d=a.grep,c=a.isArray,b=a.isNumber,k=a.isString,z=a.merge,B=a.objectEach,I=a.pick,x=a.removeEvent,K=a.splat,t=a.SVGElement,C=a.syncTimeout,N=a.win;a.Series=a.seriesType("line",null,{lineWidth:2,allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},marker:{lineWidth:0,lineColor:"#ffffff",radius:4,states:{hover:{animation:{duration:50},enabled:!0,radiusPlus:2,lineWidthPlus:1},select:{fillColor:"#cccccc", +lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:{align:"center",formatter:function(){return null===this.y?"":a.numberFormat(this.y,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"contrast",textOutline:"1px contrast"},verticalAlign:"bottom",x:0,y:0,padding:5},cropThreshold:300,pointRange:0,softThreshold:!0,states:{hover:{animation:{duration:50},lineWidthPlus:1,marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1E3,findNearestPointBy:"x"}, +{isCartesian:!0,pointClass:a.Point,sorted:!0,requireSorting:!0,directTouch:!1,axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],coll:"series",init:function(a,b){var c=this,d,g=a.series,e;c.chart=a;c.options=b=c.setOptions(b);c.linkedSeries=[];c.bindAxes();h(c,{name:b.name,state:"",visible:!1!==b.visible,selected:!0===b.selected});d=b.events;B(d,function(a,b){E(c,b,a)});if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;c.getColor(); +c.getSymbol();u(c.parallelArrays,function(a){c[a+"Data"]=[]});c.setData(b.data,!1);c.isCartesian&&(a.hasCartesianSeries=!0);g.length&&(e=g[g.length-1]);c._i=I(e&&e._i,-1)+1;a.orderSeries(this.insert(g))},insert:function(a){var c=this.options.index,d;if(b(c)){for(d=a.length;d--;)if(c>=I(a[d].options.index,a[d]._i)){a.splice(d+1,0,this);break}-1===d&&a.unshift(this);d+=1}else a.push(this);return I(d,a.length-1)},bindAxes:function(){var b=this,c=b.options,d=b.chart,e;u(b.axisTypes||[],function(g){u(d[g], +function(a){e=a.options;if(c[g]===e.index||void 0!==c[g]&&c[g]===e.id||void 0===c[g]&&0===e.index)b.insert(a.series),b[g]=a,a.isDirty=!0});b[g]||b.optionalAxis===g||a.error(18,!0)})},updateParallelArrays:function(a,c){var d=a.series,e=arguments,g=b(c)?function(b){var g="y"===b&&d.toYData?d.toYData(a):a[b];d[b+"Data"][c]=g}:function(a){Array.prototype[c].apply(d[a+"Data"],Array.prototype.slice.call(e,2))};u(d.parallelArrays,g)},autoIncrement:function(){var b=this.options,c=this.xIncrement,d,e=b.pointIntervalUnit, +g=0,c=I(c,b.pointStart,0);this.pointInterval=d=I(this.pointInterval,b.pointInterval,1);e&&(b=new l(c),"day"===e?b=+b[l.hcSetDate](b[l.hcGetDate]()+d):"month"===e?b=+b[l.hcSetMonth](b[l.hcGetMonth]()+d):"year"===e&&(b=+b[l.hcSetFullYear](b[l.hcGetFullYear]()+d)),l.hcHasTimeZone&&(g=a.getTZOffset(b)-a.getTZOffset(c)),d=b-c+g);this.xIncrement=c+d;return c},setOptions:function(a){var b=this.chart,c=b.options,d=c.plotOptions,g=(b.userOptions||{}).plotOptions||{},e=d[this.type];this.userOptions=a;b=z(e, +d.series,a);this.tooltipOptions=z(r.tooltip,r.plotOptions.series&&r.plotOptions.series.tooltip,r.plotOptions[this.type].tooltip,c.tooltip.userOptions,d.series&&d.series.tooltip,d[this.type].tooltip,a.tooltip);this.stickyTracking=I(a.stickyTracking,g[this.type]&&g[this.type].stickyTracking,g.series&&g.series.stickyTracking,this.tooltipOptions.shared&&!this.noSharedTooltip?!0:b.stickyTracking);null===e.marker&&delete b.marker;this.zoneAxis=b.zoneAxis;a=this.zones=(b.zones||[]).slice();!b.negativeColor&& +!b.negativeFillColor||b.zones||a.push({value:b[this.zoneAxis+"Threshold"]||b.threshold||0,className:"highcharts-negative",color:b.negativeColor,fillColor:b.negativeFillColor});a.length&&w(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return b},getCyclic:function(a,b,c){var d,g=this.chart,e=this.userOptions,k=a+"Index",h=a+"Counter",q=c?c.length:I(g.options.chart[a+"Count"],g[a+"Count"]);b||(d=I(e[k],e["_"+k]),w(d)||(g.series.length||(g[h]=0),e["_"+k]=d=g[h]%q,g[h]+=1), +c&&(b=c[d]));void 0!==d&&(this[k]=d);this[a]=b},getColor:function(){this.options.colorByPoint?this.options.color=null:this.getCyclic("color",this.options.color||n[this.type].color,this.chart.options.colors)},getSymbol:function(){this.getCyclic("symbol",this.options.marker.symbol,this.chart.options.symbols)},drawLegendSymbol:a.LegendSymbolMixin.drawLineMarker,setData:function(d,e,h,f){var g=this,q=g.points,m=q&&q.length||0,l,A=g.options,t=g.chart,x=null,n=g.xAxis,p=A.turboThreshold,z=this.xData,F= +this.yData,C=(l=g.pointArrayMap)&&l.length;d=d||[];l=d.length;e=I(e,!0);if(!1!==f&&l&&m===l&&!g.cropped&&!g.hasGroupedData&&g.visible)u(d,function(a,b){q[b].update&&a!==A.data[b]&&q[b].update(a,!1,null,!1)});else{g.xIncrement=null;g.colorCounter=0;u(this.parallelArrays,function(a){g[a+"Data"].length=0});if(p&&l>p){for(h=0;null===x&&hf||this.forceCrop))if(c[e-1]z)c=[],d=[];else if(c[0]z)g=this.cropData(this.xData,this.yData,p,z),c=g.xData,d=g.yData,g=g.start,k=!0;for(f=c.length|| +1;--f;)e=x?m(c[f])-m(c[f-1]):c[f]-c[f-1],0e&&n&&(a.error(15),n=!1);this.cropped=k;this.cropStart=g;this.processedXData=c;this.processedYData=d;this.closestPointRange=h},cropData:function(a,b,c,d){var g=a.length,e=0,k=g,h=I(this.cropShoulder,1),f;for(f=0;f=c){e=Math.max(0,f-h);break}for(c=f;cd){k=c+h;break}return{xData:a.slice(e,k),yData:b.slice(e,k),start:e,end:k}},generatePoints:function(){var a=this.options,b=a.data,c=this.data,d,g=this.processedXData, +e=this.processedYData,k=this.pointClass,h=g.length,f=this.cropStart||0,m,l=this.hasGroupedData,a=a.keys,t,x=[],n;c||l||(c=[],c.length=b.length,c=this.data=c);a&&l&&(this.options.keys=!1);for(n=0;n=f&&(e[n-1]||l)<=q,m&&l)if(m=t.length)for(;m--;)"number"===typeof t[m]&&(g[h++]=t[m]);else g[h++]=t;this.dataMin= +p(g);this.dataMax=H(g)},translate:function(){this.processedXData||this.processData();this.generatePoints();var a=this.options,c=a.stacking,d=this.xAxis,e=d.categories,g=this.yAxis,k=this.points,h=k.length,m=!!this.modifyValue,l=a.pointPlacement,t="between"===l||b(l),n=a.threshold,x=a.startFromThreshold?n:0,p,z,C,r,u=Number.MAX_VALUE;"between"===l&&(l=.5);b(l)&&(l*=I(a.pointRange||d.pointRange));for(a=0;a=K&&(B.isNull=!0);B.plotX=p=f(Math.min(Math.max(-1E5,d.translate(N,0,0,0,1,l,"flags"===this.type)),1E5));c&&this.visible&&!B.isNull&&D&&D[N]&&(r=this.getStackIndicator(r,N,this.index),E=D[N],K=E.points[r.key],z=K[0],K=K[1],z===x&&r.key===D[N].base&&(z=I(n,g.min)),g.positiveValuesOnly&&0>=z&&(z=null),B.total=B.stackTotal=E.total,B.percentage=E.total&&B.y/E.total*100,B.stackY=K,E.setOffset(this.pointXOffset||0,this.barW||0));B.yBottom=w(z)?g.translate(z,0,1,0,1): +null;m&&(K=this.modifyValue(K,B));B.plotY=z="number"===typeof K&&Infinity!==K?Math.min(Math.max(-1E5,g.translate(K,0,1,0,1)),1E5):void 0;B.isInside=void 0!==z&&0<=z&&z<=g.len&&0<=p&&p<=d.len;B.clientX=t?f(d.translate(N,0,0,0,1,l)):p;B.negative=B.y<(n||0);B.category=e&&void 0!==e[B.x]?e[B.x]:B.x;B.isNull||(void 0!==C&&(u=Math.min(u,Math.abs(p-C))),C=p);B.zone=this.zones.length&&B.getZone()}this.closestPointRangePx=u},getValidPoints:function(a,b){var c=this.chart;return d(a||this.points||[],function(a){return b&& +!c.isInsidePlot(a.plotX,a.plotY,c.inverted)?!1:!a.isNull})},setClip:function(a){var b=this.chart,c=this.options,d=b.renderer,g=b.inverted,e=this.clipBox,k=e||b.clipBox,h=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,k.height,c.xAxis,c.yAxis].join(),f=b[h],q=b[h+"m"];f||(a&&(k.width=0,g&&(k.x=b.plotSizeX),b[h+"m"]=q=d.clipRect(g?b.plotSizeX+99:-99,g?-b.plotLeft:-b.plotTop,99,g?b.chartWidth:b.chartHeight)),b[h]=f=d.clipRect(k),f.count={length:0});a&&!f.count[this.index]&&(f.count[this.index]= +!0,f.count.length+=1);!1!==c.clip&&(this.group.clip(a||e?f:b.clipRect),this.markerGroup.clip(q),this.sharedClipKey=h);a||(f.count[this.index]&&(delete f.count[this.index],--f.count.length),0===f.count.length&&h&&b[h]&&(e||(b[h]=b[h].destroy()),b[h+"m"]&&(b[h+"m"]=b[h+"m"].destroy())))},animate:function(a){var b=this.chart,c=D(this.options.animation),d;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX,x:0},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99,x:0},c),this.animate= +null)},afterAnimate:function(){this.setClip();m(this,"afterAnimate");this.finishedAnimating=!0},drawPoints:function(){var a=this.points,b=this.chart,c,d,g,e,k=this.options.marker,h,f,l,m=this[this.specialGroup]||this.markerGroup,t,n=I(k.enabled,this.xAxis.isRadial?!0:null,this.closestPointRangePx>=2*k.radius);if(!1!==k.enabled||this._hasPointMarkers)for(c=0;ce&&b.shadow));k&&(k.startX=c.xMap,k.isArea=c.isArea)})}, +applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,e,k,h=this.clips||[],f,m=this.graph,l=this.area,t=Math.max(b.chartWidth,b.chartHeight),n=this[(this.zoneAxis||"y")+"Axis"],x,p,z=b.inverted,C,r,w,B,K=!1;d.length&&(m||l)&&n&&void 0!==n.min&&(p=n.reversed,C=n.horiz,m&&m.hide(),l&&l.hide(),x=n.getExtremes(),u(d,function(d,g){e=p?C?b.plotWidth:0:C?0:n.toPixels(x.min);e=Math.min(Math.max(I(k,e),0),t);k=Math.min(Math.max(Math.round(n.toPixels(I(d.value,x.max),!0)),0),t);K&&(e=k=n.toPixels(x.max)); +r=Math.abs(e-k);w=Math.min(e,k);B=Math.max(e,k);n.isXAxis?(f={x:z?B:w,y:0,width:r,height:t},C||(f.x=b.plotHeight-f.x)):(f={x:0,y:z?B:w,width:t,height:r},C&&(f.y=b.plotWidth-f.y));z&&c.isVML&&(f=n.isXAxis?{x:0,y:p?w:B,height:f.width,width:b.chartWidth}:{x:f.y-b.plotLeft-b.spacingBox.x,y:0,width:f.height,height:b.chartHeight});h[g]?h[g].animate(f):(h[g]=c.clipRect(f),m&&a["zone-graph-"+g].clip(h[g]),l&&a["zone-area-"+g].clip(h[g]));K=d.value>x.max}),this.clips=h)},invertGroups:function(a){function b(){u(["group", +"markerGroup"],function(b){c[b]&&(d.renderer.isVML&&c[b].attr({width:c.yAxis.len,height:c.xAxis.len}),c[b].width=c.yAxis.len,c[b].height=c.xAxis.len,c[b].invert(a))})}var c=this,d=c.chart,e;c.xAxis&&(e=E(d,"resize",b),E(c,"destroy",e),b(a),c.invertGroups=b)},plotGroup:function(a,b,c,d,e){var g=this[a],k=!g;k&&(this[a]=g=this.chart.renderer.g().attr({zIndex:d||.1}).add(e));g.addClass("highcharts-"+b+" highcharts-series-"+this.index+" highcharts-"+this.type+"-series "+(w(this.colorIndex)?"highcharts-color-"+ +this.colorIndex+" ":"")+(this.options.className||"")+(g.hasClass("highcharts-tracker")?" highcharts-tracker":""),!0);g.attr({visibility:c})[k?"attr":"animate"](this.getPlotBox());return g},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;a.inverted&&(b=c,c=this.xAxis);return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this,b=a.chart,c,d=a.options,e=!!a.animate&&b.renderer.isSVG&&D(d.animation).duration,k=a.visible?"inherit": +"hidden",h=d.zIndex,f=a.hasRendered,m=b.seriesGroup,l=b.inverted;c=a.plotGroup("group","series",k,h,m);a.markerGroup=a.plotGroup("markerGroup","markers",k,h,m);e&&a.animate(!0);c.inverted=a.isCartesian?l:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(l);!1===d.clip||a.sharedClipKey||f||c.clip(b.clipRect);e&&a.animate();f||(a.animationTimeout=C(function(){a.afterAnimate()}, +e));a.isDirty=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirty||this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:I(d&&d.left,a.plotLeft),translateY:I(e&&e.top,a.plotTop)}));this.translate();this.render();b&&delete this.kdTree},kdAxisArray:["clientX","plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,e=this.chart.inverted;return this.searchKDTree({clientX:e?c.len-a.chartY+ +c.pos:a.chartX-c.pos,plotY:e?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(c,d,e){var g,k;if(k=c&&c.length)return g=b.kdAxisArray[d%e],c.sort(function(a,b){return a[g]-b[g]}),k=Math.floor(k/2),{point:c[k],left:a(c.slice(0,k),d+1,e),right:a(c.slice(k+1),d+1,e)}}this.buildingKdTree=!0;var b=this,c=-1l?"left":"right";t=0>l?"right":"left";b[q]&&(q=c(a,b[q],g+1,f),n=q[h]x;)q--;this.updateParallelArrays(m,"splice",q,0,0);this.updateParallelArrays(m,q);g&&m.name&&(g[x]=m.name);l.splice(q,0,a);n&&(this.data.splice(q,0,null),this.processData());"point"===e.legendType&&this.generatePoints();c&&(h[0]&&h[0].remove?h[0].remove(!1):(h.shift(),this.updateParallelArrays(m,"shift"),l.shift()));this.isDirtyData=this.isDirty=!0;b&&f.redraw(d)},removePoint:function(a,b,c){var d=this,e=d.data,h=e[a],f=d.points,g=d.chart,l=function(){f&&f.length===e.length&& +f.splice(a,1);e.splice(a,1);d.options.data.splice(a,1);d.updateParallelArrays(h||{series:d},"splice",a,1);h&&h.destroy();d.isDirty=!0;d.isDirtyData=!0;b&&g.redraw()};x(c,g);b=k(b,!0);h?h.firePointEvent("remove",null,l):l()},remove:function(a,b,c){function d(){e.destroy();h.isDirtyLegend=h.isDirtyBox=!0;h.linkSeries();k(a,!0)&&h.redraw(b)}var e=this,h=e.chart;!1!==c?u(e,"remove",null,d):d()},update:function(a,b){var d=this,e=d.chart,h=d.userOptions,f=d.oldType||d.type,l=a.type||h.type||e.options.chart.type, +g=I[f].prototype,m,n=["group","markerGroup","dataLabelsGroup"],t=["navigatorSeries","baseSeries"],x=d.finishedAnimating&&{animation:!1};if(Object.keys&&"data"===Object.keys(a).toString())return this.setData(a.data,b);t=n.concat(t);r(t,function(a){t[a]=d[a];delete d[a]});a=c(h,x,{index:d.index,pointStart:d.xData[0]},{data:d.options.data},a);d.remove(!1,null,!1);for(m in g)d[m]=void 0;w(d,I[l||f].prototype);r(t,function(a){d[a]=t[a]});d.init(e,a);a.zIndex!==h.zIndex&&r(n,function(b){d[b]&&d[b].attr({zIndex:a.zIndex})}); +d.oldType=f;e.linkSeries();k(b,!0)&&e.redraw(!1)}});w(H.prototype,{update:function(a,b){var d=this.chart;a=d.options[this.coll][this.options.index]=c(this.userOptions,a);this.destroy(!0);this.init(d,w(a,{events:void 0}));d.isDirtyBox=!0;k(b,!0)&&d.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,e=this.series,h=e.length;h--;)e[h]&&e[h].remove(!1);n(b.axes,this);n(b[c],this);d(b.options[c])?b.options[c].splice(this.options.index,1):delete b.options[c];r(b[c],function(a,b){a.options.index= +b});this.destroy();b.isDirtyBox=!0;k(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}})})(M);(function(a){var E=a.color,D=a.each,H=a.map,p=a.pick,f=a.Series,l=a.seriesType;l("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(f){var l=[],r=[],u=this.xAxis,e=this.yAxis,h=e.stacks[this.stackKey],m={},d=this.index,c=e.series,b=c.length,k,z=p(e.options.reversedStacks,!0)?1:-1,B;f=f||this.points; +if(this.options.stacking){for(B=0;Ba&&w>l?(w=Math.max(a,l),e=2*l-w):wp&&e>l?(e=Math.max(p,l),w=2*l-e):e=Math.abs(h)&&.5a.closestPointRange*a.xAxis.transA,d=a.borderWidth=r(f.borderWidth,d?0:1),c=a.yAxis,b=f.threshold,k=a.translatedThreshold=c.getThreshold(b),l=r(f.minPointLength,5),p=a.getColumnMetrics(),u=p.width,x=a.barW=Math.max(u,1+2*d),w=a.pointXOffset=p.offset;h.inverted&&(k-=.5);f.pointPadding&&(x=Math.ceil(x));n.prototype.translate.apply(a);H(a.points,function(d){var e=r(d.yBottom,k),f=999+Math.abs(e),f=Math.min(Math.max(-f,d.plotY),c.len+f),m=d.plotX+w,n=x,t=Math.min(f,e),p,g=Math.max(f,e)-t;l&& +Math.abs(g)l?e-l:k-(p?l:0));d.barX=m;d.pointWidth=u;d.tooltipPos=h.inverted?[c.len+c.pos-h.plotLeft-f,a.xAxis.len-m-n/2,g]:[m+n/2,f+c.pos-h.plotTop,g];d.shapeType="rect";d.shapeArgs=a.crispCol.apply(a,d.isNull?[m,k,n,0]:[m,t,n,g])})},getSymbol:a.noop,drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")}, +pointAttribs:function(a,f){var e=this.options,d,c=this.pointAttrToOptions||{};d=c.stroke||"borderColor";var b=c["stroke-width"]||"borderWidth",k=a&&a.color||this.color,h=a&&a[d]||e[d]||this.color||k,n=a&&a[b]||e[b]||this[b]||0,c=e.dashStyle;a&&this.zones.length&&(k=a.getZone(),k=a.options.color||k&&k.color||this.color);f&&(a=l(e.states[f],a.options.states&&a.options.states[f]||{}),f=a.brightness,k=a.color||void 0!==f&&D(k).brighten(a.brightness).get()||k,h=a[d]||h,n=a[b]||n,c=a.dashStyle||c);d={fill:k, +stroke:h,"stroke-width":n};c&&(d.dashstyle=c);return d},drawPoints:function(){var a=this,h=this.chart,m=a.options,d=h.renderer,c=m.animationLimit||250,b;H(a.points,function(e){var k=e.graphic;if(f(e.plotY)&&null!==e.y){b=e.shapeArgs;if(k)k[h.pointCounte;++e)h=w[e],a=2>e||2===e&&/%$/.test(h),w[e]=p(h,[n,l,u,w[2]][e])+(a?r:0);w[3]>w[2]&&(w[3]=w[2]);return w},getStartAndEndRadians:function(a,l){a=D(a)?a:0;l=D(l)&&l>a&&360>l-a?l:a+360;return{start:E*(a+-90),end:E*(l+-90)}}}})(M);(function(a){var E=a.addEvent,D=a.CenteredSeriesMixin,H=a.defined,p=a.each,f=a.extend,l=D.getStartAndEndRadians,r=a.inArray,n=a.noop,w=a.pick,u=a.Point,e=a.Series,h=a.seriesType,m=a.setAnimation;h("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30, +enabled:!0,formatter:function(){return this.point.isNull?void 0:this.point.name},x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff",borderWidth:1,states:{hover:{brightness:.1,shadow:!1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:a.seriesTypes.column.prototype.pointAttribs,animate:function(a){var c= +this,b=c.points,d=c.startAngleRad;a||(p(b,function(a){var b=a.graphic,e=a.shapeArgs;b&&(b.attr({r:a.startR||c.center[3]/2,start:d,end:d}),b.animate({r:e.r,start:e.start,end:e.end},c.options.animation))}),c.animate=null)},updateTotals:function(){var a,c=0,b=this.points,e=b.length,f,h=this.options.ignoreHiddenPoint;for(a=0;a1.5*Math.PI?m-=2*Math.PI:m<-Math.PI/2&&(m+=2*Math.PI);G.slicedTranslation={translateX:Math.round(Math.cos(m)*d),translateY:Math.round(Math.sin(m)*d)};h=Math.cos(m)*a[2]/ +2;u=Math.sin(m)*a[2]/2;G.tooltipPos=[a[0]+.7*h,a[1]+.7*u];G.half=m<-Math.PI/2||m>Math.PI/2?1:0;G.angle=m;f=Math.min(e,G.labelDistance/5);G.labelPos=[a[0]+h+Math.cos(m)*G.labelDistance,a[1]+u+Math.sin(m)*G.labelDistance,a[0]+h+Math.cos(m)*f,a[1]+u+Math.sin(m)*f,a[0]+h,a[1]+u,0>G.labelDistance?"center":G.half?"right":"left",m]}},drawGraph:null,drawPoints:function(){var a=this,c=a.chart.renderer,b,e,h,l,m=a.options.shadow;m&&!a.shadowGroup&&(a.shadowGroup=c.g("shadow").add(a.group));p(a.points,function(d){e= +d.graphic;if(d.isNull)e&&(d.graphic=e.destroy());else{l=d.shapeArgs;b=d.getTranslate();var k=d.shadowGroup;m&&!k&&(k=d.shadowGroup=c.g("shadow").add(a.shadowGroup));k&&k.attr(b);h=a.pointAttribs(d,d.selected&&"select");e?e.setRadialReference(a.center).attr(h).animate(f(l,b)):(d.graphic=e=c[d.shapeType](l).setRadialReference(a.center).attr(b).add(a.group),d.visible||e.attr({visibility:"hidden"}),e.attr(h).attr({"stroke-linejoin":"round"}).shadow(m,k));e.addClass(d.getClassName())}})},searchPoint:n, +sortByAngle:function(a,c){a.sort(function(a,d){return void 0!==a.angle&&(d.angle-a.angle)*c})},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,getCenter:D.getCenter,getSymbol:n},{init:function(){u.prototype.init.apply(this,arguments);var a=this,c;a.name=w(a.name,"Slice");c=function(b){a.slice("select"===b.type)};E(a,"select",c);E(a,"unselect",c);return a},isValid:function(){return a.isNumber(this.y,!0)&&0<=this.y},setVisible:function(a,c){var b=this,d=b.series,e=d.chart,f=d.options.ignoreHiddenPoint; +c=w(c,f);a!==b.visible&&(b.visible=b.options.visible=a=void 0===a?!b.visible:a,d.options.data[r(b,d.data)]=b.options,p(["graphic","dataLabel","connector","shadowGroup"],function(c){if(b[c])b[c][a?"show":"hide"](!0)}),b.legendItem&&e.legend.colorizeItem(b,a),a||"hover"!==b.state||b.setState(""),f&&(d.isDirty=!0),c&&e.redraw())},slice:function(a,c,b){var d=this.series;m(b,d.chart);w(c,!0);this.sliced=this.options.sliced=H(a)?a:!this.sliced;d.options.data[r(this,d.data)]=this.options;this.graphic.animate(this.getTranslate()); +this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())},getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(a){var c=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.x,c.y,c.r+a,c.r+a,{innerR:this.shapeArgs.r-1,start:c.start,end:c.end})}})})(M);(function(a){var E=a.addEvent,D=a.arrayMax,H=a.defined,p=a.each,f=a.extend,l=a.format,r=a.map,n=a.merge,w=a.noop,u=a.pick,e=a.relativeLength,h= +a.Series,m=a.seriesTypes,d=a.stableSort;a.distribute=function(a,b){function c(a,b){return a.target-b.target}var e,f=!0,h=a,l=[],m;m=0;for(e=a.length;e--;)m+=a[e].size;if(m>b){d(a,function(a,b){return(b.rank||0)-(a.rank||0)});for(m=e=0;m<=b;)m+=a[e].size,e++;l=a.splice(e-1,a.length)}d(a,c);for(a=r(a,function(a){return{size:a.size,targets:[a.target],align:u(a.align,.5)}});f;){for(e=a.length;e--;)f=a[e],m=(Math.min.apply(0,f.targets)+Math.max.apply(0,f.targets))/2,f.pos=Math.min(Math.max(0,m-f.size* +f.align),b-f.size);e=a.length;for(f=!1;e--;)0a[e].pos&&(a[e-1].size+=a[e].size,a[e-1].targets=a[e-1].targets.concat(a[e].targets),a[e-1].align=.5,a[e-1].pos+a[e-1].size>b&&(a[e-1].pos=b-a[e-1].size),a.splice(e,1),f=!0)}e=0;p(a,function(a){var b=0;p(a.targets,function(){h[e].pos=a.pos+b;b+=h[e].size;e++})});h.push.apply(h,l);d(h,c)};h.prototype.drawDataLabels=function(){function c(a,b){var c=b.filter;return c?(b=c.operator,a=a[c.property],c=c.value,"\x3e"===b&&a>c||"\x3c"=== +b&&a=c||"\x3c\x3d"===b&&a<=c||"\x3d\x3d"===b&&a==c||"\x3d\x3d\x3d"===b&&a===c?!0:!1):!0}var b=this,d=b.options,e=d.dataLabels,f=b.points,h,m,r=b.hasRendered||0,t,w,D=u(e.defer,!!d.animation),q=b.chart.renderer;if(e.enabled||b._hasPointLabels)b.dlProcessOptions&&b.dlProcessOptions(e),w=b.plotGroup("dataLabelsGroup","data-labels",D&&!r?"hidden":"visible",e.zIndex||6),D&&(w.attr({opacity:+r}),r||E(b,"afterAnimate",function(){b.visible&&w.show(!0);w[d.animation?"animate":"attr"]({opacity:1}, +{duration:200})})),m=e,p(f,function(f){var k,p=f.dataLabel,g,x,r=f.connector,z=!p,C;h=f.dlOptions||f.options&&f.options.dataLabels;(k=u(h&&h.enabled,m.enabled)&&!f.isNull)&&(k=!0===c(f,h||e));k&&(e=n(m,h),g=f.getLabelConfig(),C=e[f.formatPrefix+"Format"]||e.format,t=H(C)?l(C,g):(e[f.formatPrefix+"Formatter"]||e.formatter).call(g,e),C=e.style,g=e.rotation,C.color=u(e.color,C.color,b.color,"#000000"),"contrast"===C.color&&(f.contrastColor=q.getContrast(f.color||b.color),C.color=e.inside||0>u(f.labelDistance, +e.distance)||d.stacking?f.contrastColor:"#000000"),d.cursor&&(C.cursor=d.cursor),x={fill:e.backgroundColor,stroke:e.borderColor,"stroke-width":e.borderWidth,r:e.borderRadius||0,rotation:g,padding:e.padding,zIndex:1},a.objectEach(x,function(a,b){void 0===a&&delete x[b]}));!p||k&&H(t)?k&&H(t)&&(p?x.text=t:(p=f.dataLabel=g?q.text(t,0,-9999).addClass("highcharts-data-label"):q.label(t,0,-9999,e.shape,null,null,e.useHTML,null,"data-label"),p.addClass(" highcharts-data-label-color-"+f.colorIndex+" "+(e.className|| +"")+(e.useHTML?"highcharts-tracker":""))),p.attr(x),p.css(C).shadow(e.shadow),p.added||p.add(w),b.alignDataLabel(f,p,e,null,z)):(f.dataLabel=p=p.destroy(),r&&(f.connector=r.destroy()))})};h.prototype.alignDataLabel=function(a,b,d,e,h){var c=this.chart,k=c.inverted,l=u(a.dlBox&&a.dlBox.centerX,a.plotX,-9999),m=u(a.plotY,-9999),n=b.getBBox(),p,q=d.rotation,r=d.align,w=this.visible&&(a.series.forceDL||c.isInsidePlot(l,Math.round(m),k)||e&&c.isInsidePlot(l,k?e.x+1:e.y+e.height-1,k)),z="justify"===u(d.overflow, +"justify");if(w&&(p=d.style.fontSize,p=c.renderer.fontMetrics(p,b).b,e=f({x:k?this.yAxis.len-m:l,y:Math.round(k?this.xAxis.len-l:m),width:0,height:0},e),f(d,{width:n.width,height:n.height}),q?(z=!1,l=c.renderer.rotCorr(p,q),l={x:e.x+d.x+e.width/2+l.x,y:e.y+d.y+{top:0,middle:.5,bottom:1}[d.verticalAlign]*e.height},b[h?"attr":"animate"](l).attr({align:r}),m=(q+720)%360,m=180m,"left"===r?l.y-=m?n.height:0:"center"===r?(l.x-=n.width/2,l.y-=n.height/2):"right"===r&&(l.x-=n.width,l.y-=m?0:n.height)): +(b.align(d,null,e),l=b.alignAttr),z?a.isLabelJustified=this.justifyDataLabel(b,d,l,n,e,h):u(d.crop,!0)&&(w=c.isInsidePlot(l.x,l.y)&&c.isInsidePlot(l.x+n.width,l.y+n.height)),d.shape&&!q))b[h?"attr":"animate"]({anchorX:k?c.plotWidth-a.plotY:a.plotX,anchorY:k?c.plotHeight-a.plotX:a.plotY});w||(b.attr({y:-9999}),b.placed=!1)};h.prototype.justifyDataLabel=function(a,b,d,e,f,h){var c=this.chart,k=b.align,l=b.verticalAlign,m,n,p=a.box?0:a.padding||0;m=d.x+p;0>m&&("right"===k?b.align="left":b.x=-m,n=!0); +m=d.x+e.width-p;m>c.plotWidth&&("left"===k?b.align="right":b.x=c.plotWidth-m,n=!0);m=d.y+p;0>m&&("bottom"===l?b.verticalAlign="top":b.y=-m,n=!0);m=d.y+e.height-p;m>c.plotHeight&&("top"===l?b.verticalAlign="bottom":b.y=c.plotHeight-m,n=!0);n&&(a.placed=!h,a.align(b,null,f));return n};m.pie&&(m.pie.prototype.drawDataLabels=function(){var c=this,b=c.data,d,e=c.chart,f=c.options.dataLabels,l=u(f.connectorPadding,10),m=u(f.connectorWidth,1),n=e.plotWidth,t=e.plotHeight,r,w=c.center,q=w[2]/2,A=w[1],F,G, +g,v,E=[[],[]],L,P,J,M,y=[0,0,0,0];c.visible&&(f.enabled||c._hasPointLabels)&&(p(b,function(a){a.dataLabel&&a.visible&&a.dataLabel.shortened&&(a.dataLabel.attr({width:"auto"}).css({width:"auto",textOverflow:"clip"}),a.dataLabel.shortened=!1)}),h.prototype.drawDataLabels.apply(c),p(b,function(a){a.dataLabel&&a.visible&&(E[a.half].push(a),a.dataLabel._pos=null)}),p(E,function(b,h){var k,m,x=b.length,r=[],z;if(x)for(c.sortByAngle(b,h-.5),0d.bottom-2?k:P,h,d),F._attr={visibility:J,align:g[6]},F._pos={x:L+f.x+({left:l,right:-l}[g[6]]||0),y:P+f.y-10},g.x=L,g.y=P,u(f.crop,!0)&&(G=F.getBBox().width,k=null,L-Gn-l&&(k=Math.round(L+G-n+l),y[1]=Math.max(k,y[1])),0>P-v/2?y[0]=Math.max(Math.round(-P+v/2),y[0]):P+v/2>t&&(y[2]=Math.max(Math.round(P+v/2-t),y[2])),F.sideOverflow=k)}),0===D(y)||this.verifyDataLabelOverflow(y))&&(this.placeDataLabels(), +m&&p(this.points,function(a){var b;r=a.connector;if((F=a.dataLabel)&&F._pos&&a.visible&&0u(this.translatedThreshold,k.yAxis.len)),p=u(d.inside,!!this.options.stacking);l&&(e=n(l),0>e.y&&(e.height+=e.y,e.y=0),l=e.y+e.height-k.yAxis.len,0a+c||e+hb+d||f+lthis.pointCount))},pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&r(d,function(a){a.setState()});r("xy"===b?[1,0]:[1],function(b){b= +c[b?"xAxis":"yAxis"][0];var d=b.horiz,f=a[d?"chartX":"chartY"],d=d?"mouseDownX":"mouseDownY",h=c[d],g=(b.pointRange||0)/2,k=b.getExtremes(),l=b.toValue(h-f,!0)+g,m=b.toValue(h+b.len-f,!0)-g,n=m=l(n.minWidth,0)&&this.chartHeight>=l(n.minHeight,0)}).call(this)&&f.push(a._id)};E.prototype.currentOptions=function(l){function n(e,h,l,d){var c;a.objectEach(e,function(a,e){if(!d&&-1 li.first padding-left: 0px h2 font-size: 150% - -//#subtitle -// color: lighten($brown, 30%) -// font-style: italic -// font-weight: normal -// margin-top: 0px -// padding-left: 1em -// padding-top: 0px - h3 font-size: 120% diff --git a/app/assets/stylesheets/predictions.sass b/app/assets/stylesheets/predictions.sass new file mode 100644 index 000000000..b9496ebc5 --- /dev/null +++ b/app/assets/stylesheets/predictions.sass @@ -0,0 +1,11 @@ +.predictions + .metric + height: 180px + border: #000000 2px + background: $white + margin: 4px + strong + font-size: 250% + font-align: center + h3 + diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 3df1a7ca7..b62177e5d 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -51,11 +51,7 @@ class CropsController < ApplicationController def show @crop = Crop.includes(:scientific_names, plantings: :photos).find(params[:id]) @posts = @crop.posts.order(created_at: :desc).paginate(page: params[:page]) - - respond_to do |format| - format.html # show.html.haml - format.json { render json: @crop.to_json(crop_json_fields) } - end + respond_with(@crop) end def new @@ -106,6 +102,14 @@ class CropsController < ApplicationController respond_with @crop end + def sunniness + @crop = Crop.find(params[:crop_id]) + render json: Planting.where(crop: @crop) + .where.not(sunniness: nil) + .where.not(sunniness: '') + .group(:sunniness).count(:id) + end + private def notifier diff --git a/app/views/crops/_predictions.html.haml b/app/views/crops/_predictions.html.haml index dbde9c783..343f4f6bd 100644 --- a/app/views/crops/_predictions.html.haml +++ b/app/views/crops/_predictions.html.haml @@ -1,29 +1,34 @@ - unless crop.perennial.nil? - %p - #{crop.name} is - - if crop.perennial == true - = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do - a perennial crop - (living more than two years) - - elsif crop.perennial == false - = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do - an annual crop - (living and reproducing in a single year or less) + .predictions + .row + %p + #{crop.name} is + - if crop.perennial == true + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + a perennial crop + (living more than two years) + - elsif crop.perennial == false + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + an annual crop + (living and reproducing in a single year or less) -- if crop.annual? && crop.median_lifespan.present? - %p - Median lifespan of #{crop.name} plants is - %strong= crop.median_lifespan - days + .row + - if crop.annual? && crop.median_lifespan.present? + .metric.col-md-3.col-xs-5 + %h3 Median lifespan + %strong= crop.median_lifespan + %span days -- if crop.median_days_to_first_harvest.present? - %p - First harvest expected - %strong= crop.median_days_to_first_harvest - days after planting + - if crop.median_days_to_first_harvest.present? + .metric.col-md-3.col-xs-5 + %h3 First harvest expected + %strong= crop.median_days_to_first_harvest + %span days + after planting -- if crop.annual? && crop.median_days_to_last_harvest.present? - %p - Last harvest expected - %strong= crop.median_days_to_last_harvest - days after planting + - if crop.annual? && crop.median_days_to_last_harvest.present? + .metric.col-md-3.col-xs-5 + %h3 Last harvest expected + %strong= crop.median_days_to_last_harvest + %span days + after planting diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index 2789d61ef..cf401681e 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -8,6 +8,9 @@ = tag("meta", property: "og:url", content: request.original_url) = tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME']) +- content_for :scripts do + = javascript_include_tag "charts" + = render partial: 'approval_status_message', locals: { crop: @crop } - if @crop.approved? @@ -27,11 +30,6 @@ = display_seed_availability(@current_member, @crop) = link_to "View your seeds", seeds_by_owner_path(owner: current_member.slug) - %h2 Predictions - = render 'predictions', crop: @crop - - %p= render 'crops/photos', crop: @crop - %h2 - if !@crop.plantings.empty? = @crop.name.titleize @@ -41,19 +39,26 @@ - else Nobody is growing this yet. You could be the first! - %h2 - Sunniness Chart + .row + .col-md-3 + %h2 Sunniness Chart + = pie_chart crop_sunniness_path(@crop), legend: "bottom" - #sunchart + .col-md-9 + %h2 Predictions + = render 'predictions', crop: @crop - %h2 - Crop Map - %p - Only plantings by members who have set their locations are shown on this map. - - if current_member && current_member.location.blank? - = link_to "Set your location.", edit_member_registration_path + .row + .col-md-12 + %h2 Photos + %p= render 'crops/photos', crop: @crop - #cropmap + %h2 Crop Map + %p + Only plantings by members who have set their locations are shown on this map. + - if current_member && current_member.location.blank? + = link_to "Set your location.", edit_member_registration_path + #cropmap %a{ name: 'posts' } %h2 What people are saying about #{@crop.name.pluralize} diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 7fe945d8a..40f83db5b 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,5 +1,6 @@ !!! 5 %html{ lang: "en", prefix: "og: http://ogp.me/ns#" } + = yield :scripts = render partial: "layouts/meta" %body = render partial: "layouts/header" diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 000000000..60484d4a4 --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,15 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path +# Add Yarn node_modules folder to the asset load path. +Rails.application.config.assets.paths << Rails.root.join('node_modules') + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) +Rails.application.config.assets.precompile += %w(charts.js) diff --git a/config/routes.rb b/config/routes.rb index eb963311a..14c4bd401 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -50,6 +50,7 @@ Growstuff::Application.routes.draw do get 'crops/search' => 'crops#search', as: 'crops_search' resources :crops do get 'photos' => 'photos#index' + get 'sunniness' => 'crops#sunniness' end resources :comments From c5699610299d84c52957bd1621fc8f425f54ba76 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 7 Jan 2018 19:25:05 +1300 Subject: [PATCH 069/267] Add timeline to gardens --- app/controllers/gardens_controller.rb | 11 +++++++++++ app/views/gardens/show.html.haml | 9 +++++++++ config/routes.rb | 4 +++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index ede5c2602..d2aa8bfe0 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -58,6 +58,17 @@ class GardensController < ApplicationController redirect_to(gardens_by_owner_path(owner: @garden.owner)) end + def timeline + @data = [] + @garden = Garden.find(params[:garden_id]) + @garden.plantings.where.not(finished_at: nil) + .where.not(planted_at: nil) + .order(finished_at: :desc).each do |p| + @data << [p.crop.name, p.planted_at, p.finished_at] + end + render json: @data + end + private def garden_params diff --git a/app/views/gardens/show.html.haml b/app/views/gardens/show.html.haml index ef5b41cfb..5ffed7152 100644 --- a/app/views/gardens/show.html.haml +++ b/app/views/gardens/show.html.haml @@ -9,6 +9,11 @@ = tag("meta", property: "og:type", content: "website") = tag("meta", property: "og:url", content: request.original_url) = tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME']) + +- content_for :scripts do + = javascript_include_tag "charts" + = javascript_include_tag "https://www.gstatic.com/charts/loader.js" + .row .col-md-9 %p.btn-group= render 'gardens/actions', garden: @garden @@ -32,6 +37,10 @@ Why not = link_to 'tell us more.', edit_garden_path(@garden) + %h3 Garden timeline + .row + = timeline garden_timeline_path(@garden), adapter: "google" + %h3 What's planted here? .row - if @current_plantings.size.positive? diff --git a/config/routes.rb b/config/routes.rb index 14c4bd401..cc90a4063 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -27,7 +27,9 @@ Growstuff::Application.routes.draw do get '/plantings/owner/:owner' => 'plantings#index', as: 'plantings_by_owner' get '/plantings/crop/:crop' => 'plantings#index', as: 'plantings_by_crop' - resources :gardens + resources :gardens do + get 'timeline' => 'gardens#timeline' + end get '/gardens/owner/:owner' => 'gardens#index', as: 'gardens_by_owner' resources :seeds From d8cce280e2498a63e9341b12d8ed1607a1ef8df4 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 8 Jan 2018 18:03:20 +1300 Subject: [PATCH 070/267] Remove highcharts.js, we're not using it --- app/assets/javascripts/highcharts.js | 389 --------------------------- 1 file changed, 389 deletions(-) delete mode 100644 app/assets/javascripts/highcharts.js diff --git a/app/assets/javascripts/highcharts.js b/app/assets/javascripts/highcharts.js deleted file mode 100644 index 9554ef58b..000000000 --- a/app/assets/javascripts/highcharts.js +++ /dev/null @@ -1,389 +0,0 @@ -/* - Highcharts JS v6.0.4 (2017-12-15) - - (c) 2009-2016 Torstein Honsi - - License: www.highcharts.com/license -*/ -(function(S,M){"object"===typeof module&&module.exports?module.exports=S.document?M(S):M:S.Highcharts=M(S)})("undefined"!==typeof window?window:this,function(S){var M=function(){var a="undefined"===typeof S?window:S,E=a.document,D=a.navigator&&a.navigator.userAgent||"",H=E&&E.createElementNS&&!!E.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,p=/(edge|msie|trident)/i.test(D)&&!a.opera,f=/Firefox/.test(D),l=f&&4>parseInt(D.split("Firefox/")[1],10);return a.Highcharts?a.Highcharts.error(16, -!0):{product:"Highcharts",version:"6.0.4",deg2rad:2*Math.PI/360,doc:E,hasBidiBug:l,hasTouch:E&&void 0!==E.documentElement.ontouchstart,isMS:p,isWebKit:/AppleWebKit/.test(D),isFirefox:f,isTouchDevice:/(Mobile|Android|Windows Phone)/.test(D),SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:H,win:a,marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){},charts:[]}}();(function(a){a.timers=[];var E=a.charts,D=a.doc,H=a.win;a.error=function(p, -f){p=a.isNumber(p)?"Highcharts error #"+p+": www.highcharts.com/errors/"+p:p;if(f)throw Error(p);H.console&&console.log(p)};a.Fx=function(a,f,l){this.options=f;this.elem=a;this.prop=l};a.Fx.prototype={dSetter:function(){var a=this.paths[0],f=this.paths[1],l=[],r=this.now,n=a.length,w;if(1===r)l=this.toD;else if(n===f.length&&1>r)for(;n--;)w=parseFloat(a[n]),l[n]=isNaN(w)?f[n]:r*parseFloat(f[n]-w)+w;else l=f;this.elem.attr("d",l,null,!0)},update:function(){var a=this.elem,f=this.prop,l=this.now,r= -this.options.step;if(this[f+"Setter"])this[f+"Setter"]();else a.attr?a.element&&a.attr(f,l,null,!0):a.style[f]=l+this.unit;r&&r.call(a,l,this)},run:function(p,f,l){var r=this,n=r.options,w=function(a){return w.stopped?!1:r.step(a)},u=H.requestAnimationFrame||function(a){setTimeout(a,13)},e=function(){for(var h=0;h=u+this.startTime?(this.now=this.end,this.pos=1,this.update(),l=e[this.prop]=!0,a.objectEach(e,function(a){!0!==a&&(l=!1)}),l&&w&&w.call(n),p=!1):(this.pos=r.easing((f-this.startTime)/u),this.now=this.start+(this.end- -this.start)*this.pos,this.update(),p=!0);return p},initPath:function(p,f,l){function r(a){var b,c;for(k=a.length;k--;)b="M"===a[k]||"L"===a[k],c=/[a-zA-Z]/.test(a[k+3]),b&&c&&a.splice(k+1,0,a[k+1],a[k+2],a[k+1],a[k+2])}function n(a,b){for(;a.lengtha&&-Infinityw?"AM":"PM",P:12>w?"am":"pm",S:k(n.getSeconds()),L:k(Math.round(f%1E3),3)},a.dateFormats);a.objectEach(r,function(a,b){for(;-1!==p.indexOf("%"+b);)p=p.replace("%"+b,"function"===typeof a?a(f):a)});return l?p.substr(0,1).toUpperCase()+p.substr(1):p};a.formatSingle=function(p,f){var l=/\.([0-9])/,r=a.defaultOptions.lang;/f$/.test(p)?(l=(l=p.match(l))?l[1]:-1,null!==f&&(f=a.numberFormat(f,l,r.decimalPoint,-1=l&&(f=[1/l])));for(r=0;r=p||!n&&w<=(f[r]+(f[r+1]||f[r]))/2);r++);return u=a.correctFloat(u*l,-Math.round(Math.log(.001)/Math.LN10))};a.stableSort=function(a,f){var l=a.length,p,n;for(n=0;nl&&(l=a[f]);return l};a.destroyObjectProperties=function(p,f){a.objectEach(p,function(a,r){a&&a!==f&&a.destroy&&a.destroy();delete p[r]})};a.discardElement=function(p){var f=a.garbageBin;f||(f=a.createElement("div"));p&&f.appendChild(p);f.innerHTML=""};a.correctFloat=function(a,f){return parseFloat(a.toPrecision(f||14))};a.setAnimation=function(p,f){f.renderer.globalAnimation=a.pick(p,f.options.chart.animation, -!0)};a.animObject=function(p){return a.isObject(p)?a.merge(p):{duration:p?500:0}};a.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5,month:24192E5,year:314496E5};a.numberFormat=function(p,f,l,r){p=+p||0;f=+f;var n=a.defaultOptions.lang,w=(p.toString().split(".")[1]||"").split("e")[0].length,u,e,h=p.toString().split("e");-1===f?f=Math.min(w,20):a.isNumber(f)?f&&h[1]&&0>h[1]&&(u=f+ +h[1],0<=u?(h[0]=(+h[0]).toExponential(u).split("e")[0],f=u):(h[0]=h[0].split(".")[0]||0, -p=20>f?(h[0]*Math.pow(10,h[1])).toFixed(f):0,h[1]=0)):f=2;e=(Math.abs(h[1]?h[0]:p)+Math.pow(10,-Math.max(f,w)-1)).toFixed(f);w=String(a.pInt(e));u=3p?"-":"")+(u?w.substr(0,u)+r:"");p+=w.substr(u).replace(/(\d{3})(?=\d)/g,"$1"+r);f&&(p+=l+e.slice(-f));h[1]&&0!==+p&&(p+="e"+h[1]);return p};Math.easeInOutSine=function(a){return-.5*(Math.cos(Math.PI*a)-1)};a.getStyle=function(p,f,l){if("width"===f)return Math.min(p.offsetWidth, -p.scrollWidth)-a.getStyle(p,"padding-left")-a.getStyle(p,"padding-right");if("height"===f)return Math.min(p.offsetHeight,p.scrollHeight)-a.getStyle(p,"padding-top")-a.getStyle(p,"padding-bottom");H.getComputedStyle||a.error(27,!0);if(p=H.getComputedStyle(p,void 0))p=p.getPropertyValue(f),a.pick(l,"opacity"!==f)&&(p=a.pInt(p));return p};a.inArray=function(p,f){return(a.indexOfPolyfill||Array.prototype.indexOf).call(f,p)};a.grep=function(p,f){return(a.filterPolyfill||Array.prototype.filter).call(p, -f)};a.find=Array.prototype.find?function(a,f){return a.find(f)}:function(a,f){var l,r=a.length;for(l=0;l>16,(l&65280)>> -8,l&255,1]:4===f&&(n=[(l&3840)>>4|(l&3840)>>8,(l&240)>>4|l&240,(l&15)<<4|l&15,1])),!n)for(w=this.parsers.length;w--&&!n;)u=this.parsers[w],(f=u.regex.exec(l))&&(n=u.parse(f));this.rgba=n||[]},get:function(a){var f=this.input,n=this.rgba,l;this.stops?(l=p(f),l.stops=[].concat(l.stops),E(this.stops,function(n,e){l.stops[e]=[l.stops[e][0],n.get(a)]})):l=n&&D(n[0])?"rgb"===a||!a&&1===n[3]?"rgb("+n[0]+","+n[1]+","+n[2]+")":"a"===a?n[3]:"rgba("+n.join(",")+")":f;return l},brighten:function(a){var l,n=this.rgba; -if(this.stops)E(this.stops,function(n){n.brighten(a)});else if(D(a)&&0!==a)for(l=0;3>l;l++)n[l]+=f(255*a),0>n[l]&&(n[l]=0),255y.width)y={width:0,height:0}}else y=this.htmlGetBBox();b.isSVG&& -(a=y.width,b=y.height,q&&"11px"===q.fontSize&&17===Math.round(b)&&(y.height=b=14),g&&(y.width=Math.abs(b*Math.sin(v))+Math.abs(a*Math.cos(v)),y.height=Math.abs(b*Math.cos(v))+Math.abs(a*Math.sin(v))));if(A&&0]*>/g,"")))},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,g,b){"string"===typeof a?b.setAttribute(g,a):a&&this.colorGradient(a,g,b)},visibilitySetter:function(a,g,b){"inherit"===a?b.removeAttribute(g):this[g]!==a&&b.setAttribute(g,a);this[g]=a},zIndexSetter:function(a,b){var v=this.renderer,y=this.parentGroup,c=(y||v).element||v.box,k,d=this.element,q,e,v=c===v.box;k=this.added;var z;u(a)&& -(d.zIndex=a,a=+a,this[b]===a&&(k=!1),this[b]=a);if(k){(a=this.zIndex)&&y&&(y.handleZ=!0);b=c.childNodes;for(z=b.length-1;0<=z&&!q;z--)if(y=b[z],k=y.zIndex,e=!u(k),y!==d)if(0>a&&e&&!v&&!z)c.insertBefore(d,b[z]),q=!0;else if(g(k)<=a||e&&(!u(a)||0<=a))c.insertBefore(d,b[z+1]||null),q=!0;q||(c.insertBefore(d,b[v?3:0]||null),q=!0)}return q},_defaultSetter:function(a,g,b){b.setAttribute(g,a)}});E.prototype.yGetter=E.prototype.xGetter;E.prototype.translateXSetter=E.prototype.translateYSetter=E.prototype.rotationSetter= -E.prototype.verticalAlignSetter=E.prototype.rotationOriginXSetter=E.prototype.rotationOriginYSetter=E.prototype.scaleXSetter=E.prototype.scaleYSetter=E.prototype.matrixSetter=function(a,g){this[g]=a;this.doTransform=!0};E.prototype["stroke-widthSetter"]=E.prototype.strokeSetter=function(a,g,b){this[g]=a;this.stroke&&this["stroke-width"]?(E.prototype.fillSetter.call(this,this.stroke,"stroke",b),b.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0):"stroke-width"===g&&0===a&&this.hasStroke&& -(b.removeAttribute("stroke"),this.hasStroke=!1)};D=a.SVGRenderer=function(){this.init.apply(this,arguments)};c(D.prototype,{Element:E,SVG_NS:P,init:function(a,g,b,v,c,k){var y;v=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"}).css(this.getStyle(v));y=v.element;a.appendChild(y);f(a,"dir","ltr");-1===a.innerHTML.indexOf("xmlns")&&f(y,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=y;this.boxWrapper=v;this.alignedObjects=[];this.url=(x||N)&&m.getElementsByTagName("base").length? -R.location.href.replace(/#.*?$/,"").replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(m.createTextNode("Created with Highcharts 6.0.4"));this.defs=this.createElement("defs").add();this.allowHTML=k;this.forExport=c;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(g,b,!1);var d;x&&a.getBoundingClientRect&&(g=function(){n(a,{left:0,top:0});d=a.getBoundingClientRect();n(a,{left:Math.ceil(d.left)- -d.left+"px",top:Math.ceil(d.top)-d.top+"px"})},g(),this.unSubPixelFix=H(R,"resize",g))},getStyle:function(a){return this.style=c({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},setStyle:function(a){this.boxWrapper.css(this.getStyle(a))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();h(this.gradients||{});this.gradients=null;a&&(this.defs=a.destroy()); -this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(a){var g=new this.Element;g.init(this,a);return g},draw:A,getRadialAttr:function(a,g){return{cx:a[0]-a[2]/2+g.cx*a[2],cy:a[1]-a[2]/2+g.cy*a[2],r:g.r*a[2]}},getSpanWidth:function(a,g){var b=a.getBBox(!0).width;!L&&this.forExport&&(b=this.measureSpanWidth(g.firstChild.data,a.styles));return b},applyEllipsis:function(a,g,b,v){var c=a.rotation,y=b,k,d=0,q=b.length,e=function(a){g.removeChild(g.firstChild); -a&&g.appendChild(m.createTextNode(a))},z;a.rotation=0;y=this.getSpanWidth(a,g);if(z=y>v){for(;d<=q;)k=Math.ceil((d+q)/2),y=b.substring(0,k)+"\u2026",e(y),y=this.getSpanWidth(a,g),d===q?d=q+1:y>v?q=k-1:d=k;0===q&&e("")}a.rotation=c;return z},escapes:{"\x26":"\x26amp;","\x3c":"\x26lt;","\x3e":"\x26gt;","'":"\x26#39;",'"':"\x26quot;"},buildText:function(a){var b=a.element,v=this,c=v.forExport,y=G(a.textStr,"").toString(),q=-1!==y.indexOf("\x3c"),e=b.childNodes,z,h,A,J,t=f(b,"x"),x=a.styles,B=a.textWidth, -l=x&&x.lineHeight,C=x&&x.textOutline,u=x&&"ellipsis"===x.textOverflow,Q=x&&"nowrap"===x.whiteSpace,w=x&&x.fontSize,R,I,r=e.length,x=B&&!a.added&&this.box,p=function(a){var c;c=/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:w||v.style.fontSize||12;return l?g(l):v.fontMetrics(c,a.getAttribute("style")?a:b).h},K=function(a){F(v.escapes,function(g,b){a=a.replace(new RegExp(g,"g"),b)});return a};R=[y,u,Q,l,C,w,B].join();if(R!==a.textCache){for(a.textCache=R;r--;)b.removeChild(e[r]);q||C||u||B|| --1!==y.indexOf(" ")?(z=/<.*class="([^"]+)".*>/,h=/<.*style="([^"]+)".*>/,A=/<.*href="([^"]+)".*>/,x&&x.appendChild(b),y=q?y.replace(/<(b|strong)>/g,'\x3cspan style\x3d"font-weight:bold"\x3e').replace(/<(i|em)>/g,'\x3cspan style\x3d"font-style:italic"\x3e').replace(//g,"\x3c/span\x3e").split(//g):[y],y=k(y,function(a){return""!==a}),d(y,function(g,y){var k,q=0;g=g.replace(/^\s+|\s+$/g,"").replace(//g,"\x3c/span\x3e|||"); -k=g.split("|||");d(k,function(g){if(""!==g||1===k.length){var d={},e=m.createElementNS(v.SVG_NS,"tspan"),x,F;z.test(g)&&(x=g.match(z)[1],f(e,"class",x));h.test(g)&&(F=g.match(h)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),f(e,"style",F));A.test(g)&&!c&&(f(e,"onclick",'location.href\x3d"'+g.match(A)[1]+'"'),f(e,"class","highcharts-anchor"),n(e,{cursor:"pointer"}));g=K(g.replace(/<[a-zA-Z\/](.|\n)*?>/g,"")||" ");if(" "!==g){e.appendChild(m.createTextNode(g));q?d.dx=0:y&&null!==t&&(d.x=t);f(e,d);b.appendChild(e); -!q&&I&&(!L&&c&&n(e,{display:"block"}),f(e,"dy",p(e)));if(B){d=g.replace(/([^\^])-/g,"$1- ").split(" ");x=1B,void 0===J&&(J=g),g&&1!==d.length?(e.removeChild(e.firstChild),O.unshift(d.pop())):(d=O,O=[],d.length&&!Q&&(e=m.createElementNS(P,"tspan"),f(e,{dy:C,x:t}),F&&f(e,"style",F),b.appendChild(e)),l>B&&(B=l)),d.length&&e.appendChild(m.createTextNode(d.join(" ").replace(/- /g, -"-")));a.rotation=G}q++}}});I=I||b.childNodes.length}),J&&a.attr("title",a.textStr),x&&x.removeChild(b),C&&a.applyTextOutline&&a.applyTextOutline(C)):b.appendChild(m.createTextNode(K(y)))}},getContrast:function(a){a=r(a).rgba;return 510Math.abs(c.end-c.start-2*Math.PI));var y=Math.cos(k),z=Math.sin(k),h=Math.cos(e),e=Math.sin(e);c=.001>c.end-k-Math.PI?0:1;d=["M",a+d*y,g+q*z,"A",d,q,0,c,1,a+d*h,g+q*e];u(b)&&d.push(v?"M":"L",a+b* -h,g+b*e,"A",b,b,0,c,0,a+b*y,g+b*z);d.push(v?"":"Z");return d},callout:function(a,g,b,v,c){var d=Math.min(c&&c.r||0,b,v),k=d+6,q=c&&c.anchorX;c=c&&c.anchorY;var e;e=["M",a+d,g,"L",a+b-d,g,"C",a+b,g,a+b,g,a+b,g+d,"L",a+b,g+v-d,"C",a+b,g+v,a+b,g+v,a+b-d,g+v,"L",a+d,g+v,"C",a,g+v,a,g+v,a,g+v-d,"L",a,g+d,"C",a,g,a,g,a+d,g];q&&q>b?c>g+k&&cq?c>g+k&&cv&&q>a+k&&qc&&q>a+k&&qa?a+3:Math.round(1.2*a);return{h:b,b:Math.round(.8* -b),f:a}},rotCorr:function(a,g,b){var v=a;g&&b&&(v=Math.max(v*Math.cos(g*e),4));return{x:-a/3*Math.sin(g*e),y:v}},label:function(g,b,k,e,z,h,m,A,L){var y=this,J=y.g("button"!==L&&"label"),t=J.text=y.text("",0,0,m).attr({zIndex:1}),x,F,n=0,B=3,l=0,C,f,Q,G,w,R={},I,P,r=/^url\((.*?)\)$/.test(e),p=r,K,O,N,T;L&&J.addClass("highcharts-"+L);p=r;K=function(){return(I||0)%2/2};O=function(){var a=t.element.style,g={};F=(void 0===C||void 0===f||w)&&u(t.textStr)&&t.getBBox();J.width=(C||F.width||0)+2*B+l;J.height= -(f||F.height||0)+2*B;P=B+y.fontMetrics(a&&a.fontSize,t).b;p&&(x||(J.box=x=y.symbols[e]||r?y.symbol(e):y.rect(),x.addClass(("button"===L?"":"highcharts-label-box")+(L?" highcharts-"+L+"-box":"")),x.add(J),a=K(),g.x=a,g.y=(A?-P:0)+a),g.width=Math.round(J.width),g.height=Math.round(J.height),x.attr(c(g,R)),R={})};N=function(){var a=l+B,g;g=A?0:P;u(C)&&F&&("center"===w||"right"===w)&&(a+={center:.5,right:1}[w]*(C-F.width));if(a!==t.x||g!==t.y)t.attr("x",a),void 0!==g&&t.attr("y",g);t.x=a;t.y=g};T=function(a, -g){x?x.attr(a,g):R[a]=g};J.onAdd=function(){t.add(J);J.attr({text:g||0===g?g:"",x:b,y:k});x&&u(z)&&J.attr({anchorX:z,anchorY:h})};J.widthSetter=function(g){C=a.isNumber(g)?g:null};J.heightSetter=function(a){f=a};J["text-alignSetter"]=function(a){w=a};J.paddingSetter=function(a){u(a)&&a!==B&&(B=J.padding=a,N())};J.paddingLeftSetter=function(a){u(a)&&a!==l&&(l=a,N())};J.alignSetter=function(a){a={left:0,center:.5,right:1}[a];a!==n&&(n=a,F&&J.attr({x:Q}))};J.textSetter=function(a){void 0!==a&&t.textSetter(a); -O();N()};J["stroke-widthSetter"]=function(a,g){a&&(p=!0);I=this["stroke-width"]=a;T(g,a)};J.strokeSetter=J.fillSetter=J.rSetter=function(a,g){"r"!==g&&("fill"===g&&a&&(p=!0),J[g]=a);T(g,a)};J.anchorXSetter=function(a,g){z=J.anchorX=a;T(g,Math.round(a)-K()-Q)};J.anchorYSetter=function(a,g){h=J.anchorY=a;T(g,a-G)};J.xSetter=function(a){J.x=a;n&&(a-=n*((C||F.width)+2*B));Q=Math.round(a);J.attr("translateX",Q)};J.ySetter=function(a){G=J.y=Math.round(a);J.attr("translateY",G)};var U=J.css;return c(J,{css:function(a){if(a){var g= -{};a=q(a);d(J.textProps,function(b){void 0!==a[b]&&(g[b]=a[b],delete a[b])});t.css(g)}return U.call(J,a)},getBBox:function(){return{width:F.width+2*B,height:F.height+2*B,x:F.x-B,y:F.y-B}},shadow:function(a){a&&(O(),x&&x.shadow(a));return J},destroy:function(){v(J.element,"mouseenter");v(J.element,"mouseleave");t&&(t=t.destroy());x&&(x=x.destroy());E.prototype.destroy.call(J);J=y=O=N=T=null}})}});a.Renderer=D})(M);(function(a){var E=a.attr,D=a.createElement,H=a.css,p=a.defined,f=a.each,l=a.extend, -r=a.isFirefox,n=a.isMS,w=a.isWebKit,u=a.pick,e=a.pInt,h=a.SVGRenderer,m=a.win,d=a.wrap;l(a.SVGElement.prototype,{htmlCss:function(a){var b=this.element;if(b=a&&"SPAN"===b.tagName&&a.width)delete a.width,this.textWidth=b,this.updateTransform();a&&"ellipsis"===a.textOverflow&&(a.whiteSpace="nowrap",a.overflow="hidden");this.styles=l(this.styles,a);H(this.element,a);return this},htmlGetBBox:function(){var a=this.element;return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}, -htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,d=this.translateX||0,z=this.translateY||0,h=this.x||0,m=this.y||0,x=this.textAlign||"left",n={left:0,center:.5,right:1}[x],t=this.styles;H(b,{marginLeft:d,marginTop:z});this.shadows&&f(this.shadows,function(a){H(a,{marginLeft:d+1,marginTop:z+1})});this.inverted&&f(b.childNodes,function(c){a.invertChild(c,b)});if("SPAN"===b.tagName){var l=this.rotation,u=e(this.textWidth),q=t&&t.whiteSpace,A=[l,x,b.innerHTML,this.textWidth, -this.textAlign].join();A!==this.cTT&&(t=a.fontMetrics(b.style.fontSize).b,p(l)&&this.setSpanRotation(l,n,t),H(b,{width:"",whiteSpace:q||"nowrap"}),b.offsetWidth>u&&/[ \-]/.test(b.textContent||b.innerText)&&H(b,{width:u+"px",display:"block",whiteSpace:q||"normal"}),this.getSpanCorrection(b.offsetWidth,t,n,l,x));H(b,{left:h+(this.xCorr||0)+"px",top:m+(this.yCorr||0)+"px"});w&&(t=b.offsetHeight);this.cTT=A}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,d){var c={},k=this.renderer.getTransformKey(); -c[k]=c.transform="rotate("+a+"deg)";c[k+(r?"Origin":"-origin")]=c.transformOrigin=100*b+"% "+d+"px";H(this.element,c)},getSpanCorrection:function(a,b,d){this.xCorr=-a*d;this.yCorr=-b}});l(h.prototype,{getTransformKey:function(){return n&&!/Edge/.test(m.navigator.userAgent)?"-ms-transform":w?"-webkit-transform":r?"MozTransform":m.opera?"-o-transform":""},html:function(a,b,k){var c=this.createElement("span"),e=c.element,h=c.renderer,m=h.isSVG,w=function(a,b){f(["opacity","visibility"],function(c){d(a, -c+"Setter",function(a,c,d,k){a.call(this,c,d,k);b[d]=c})})};c.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;this.textStr=a;e.innerHTML=u(a,"");c.htmlUpdateTransform()};m&&w(c,c.element.style);c.xSetter=c.ySetter=c.alignSetter=c.rotationSetter=function(a,b){"align"===b&&(b="textAlign");c[b]=a;c.htmlUpdateTransform()};c.attr({text:a,x:Math.round(b),y:Math.round(k)}).css({fontFamily:this.style.fontFamily,fontSize:this.style.fontSize,position:"absolute"});e.style.whiteSpace="nowrap";c.css= -c.htmlCss;m&&(c.add=function(a){var b,d=h.box.parentNode,k=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)k.push(a),a=a.parentGroup;f(k.reverse(),function(a){function e(g,b){a[b]=g;n?q[h.getTransformKey()]="translate("+(a.x||a.translateX)+"px,"+(a.y||a.translateY)+"px)":"translateX"===b?q.left=g+"px":q.top=g+"px";a.doTransform=!0}var q,g=E(a.element,"class");g&&(g={className:g});b=a.div=a.div||D("div",g,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px",display:a.display, -opacity:a.opacity,pointerEvents:a.styles&&a.styles.pointerEvents},b||d);q=b.style;l(a,{classSetter:function(a){return function(g){this.element.setAttribute("class",g);a.className=g}}(b),on:function(){k[0].div&&c.on.apply({element:k[0].div},arguments);return a},translateXSetter:e,translateYSetter:e});w(a,q)})}}else b=d;b.appendChild(e);c.added=!0;c.alignOnAdd&&c.htmlUpdateTransform();return c});return c}})})(M);(function(a){function E(){var n=a.defaultOptions.global,l=r.moment;if(n.timezone){if(l)return function(a){return-l.tz(a, -n.timezone).utcOffset()};a.error(25)}return n.useUTC&&n.getTimezoneOffset}function D(){var n=a.defaultOptions.global,f,u=n.useUTC,e=u?"getUTC":"get",h=u?"setUTC":"set",m="Minutes Hours Day Date Month FullYear".split(" "),d=m.concat(["Milliseconds","Seconds"]);a.Date=f=n.Date||r.Date;f.hcTimezoneOffset=u&&n.timezoneOffset;f.hcGetTimezoneOffset=E();f.hcHasTimeZone=!(!f.hcTimezoneOffset&&!f.hcGetTimezoneOffset);f.hcMakeTime=function(a,b,d,e,h,m){var c;u?(c=f.UTC.apply(0,arguments),c+=p(c)):c=(new f(a, -b,l(d,1),l(e,0),l(h,0),l(m,0))).getTime();return c};for(n=0;nb&&e-k*zm&&(p=Math.round((h-e)/Math.cos(b*r)));else if(h=e+(1-k)*z,e-k*zm&&(I=m-a.x+I*k,x=-1),I=Math.min(B,I),II||f.autoRotation&&(c.styles||{}).width)p=I;p&&(t.width=p,(n.style||{}).textOverflow||(t.textOverflow="ellipsis"),c.css(t))},getPosition:function(a,f,l,e){var h=this.axis,m=h.chart,d=e&&m.oldChartHeight||m.chartHeight;return{x:a?h.translate(f+l,null,null,e)+h.transB:h.left+h.offset+(h.opposite?(e&&m.oldChartWidth||m.chartWidth)-h.right-h.left:0),y:a?d-h.bottom+h.offset-(h.opposite?h.height:0):d-h.translate(f+l,null,null,e)-h.transB}},getLabelPosition:function(a, -f,l,e,h,m,d,c){var b=this.axis,k=b.transA,z=b.reversed,B=b.staggerLines,n=b.tickRotCorr||{x:0,y:0},x=h.y,u=e||b.reserveSpaceDefault?0:-b.labelOffset*("center"===b.labelAlign?.5:1);D(x)||(x=0===b.side?l.rotation?-8:-l.getBBox().height:2===b.side?n.y+8:Math.cos(l.rotation*r)*(n.y-l.getBBox(!1,0).height/2));a=a+h.x+u+n.x-(m&&e?m*k*(z?-1:1):0);f=f+x-(m&&!e?m*k*(z?1:-1):0);B&&(l=d/(c||1)%B,b.opposite&&(l=B-l-1),f+=b.labelOffset/B*l);return{x:a,y:Math.round(f)}},getMarkPath:function(a,f,l,e,h,m){return m.crispLine(["M", -a,f,"L",a+(h?0:-l),f+(h?l:0)],e)},renderGridLine:function(a,f,l){var e=this.axis,h=e.options,m=this.gridLine,d={},c=this.pos,b=this.type,k=e.tickmarkOffset,z=e.chart.renderer,B=b?b+"Grid":"grid",n=h[B+"LineWidth"],x=h[B+"LineColor"],h=h[B+"LineDashStyle"];m||(d.stroke=x,d["stroke-width"]=n,h&&(d.dashstyle=h),b||(d.zIndex=1),a&&(d.opacity=0),this.gridLine=m=z.path().attr(d).addClass("highcharts-"+(b?b+"-":"")+"grid-line").add(e.gridGroup));if(!a&&m&&(a=e.getPlotLinePath(c+k,m.strokeWidth()*l,a,!0)))m[this.isNew? -"attr":"animate"]({d:a,opacity:f})},renderMark:function(a,f,u){var e=this.axis,h=e.options,m=e.chart.renderer,d=this.type,c=d?d+"Tick":"tick",b=e.tickSize(c),k=this.mark,z=!k,B=a.x;a=a.y;var n=l(h[c+"Width"],!d&&e.isXAxis?1:0),h=h[c+"Color"];b&&(e.opposite&&(b[0]=-b[0]),z&&(this.mark=k=m.path().addClass("highcharts-"+(d?d+"-":"")+"tick").add(e.axisGroup),k.attr({stroke:h,"stroke-width":n})),k[z?"attr":"animate"]({d:this.getMarkPath(B,a,b[0],k.strokeWidth()*u,e.horiz,m),opacity:f}))},renderLabel:function(a, -f,u,e){var h=this.axis,m=h.horiz,d=h.options,c=this.label,b=d.labels,k=b.step,h=h.tickmarkOffset,z=!0,B=a.x;a=a.y;c&&p(B)&&(c.xy=a=this.getLabelPosition(B,a,c,m,b,h,e,k),this.isFirst&&!this.isLast&&!l(d.showFirstLabel,1)||this.isLast&&!this.isFirst&&!l(d.showLastLabel,1)?z=!1:!m||b.step||b.rotation||f||0===u||this.handleOverflow(a),k&&e%k&&(z=!1),z&&p(a.y)?(a.opacity=u,c[this.isNewLabel?"attr":"animate"](a),this.isNewLabel=!1):(c.attr("y",-9999),this.isNewLabel=!0))},render:function(a,f,u){var e= -this.axis,h=e.horiz,m=this.getPosition(h,this.pos,e.tickmarkOffset,f),d=m.x,c=m.y,e=h&&d===e.pos+e.len||!h&&c===e.pos?-1:1;u=l(u,1);this.isActive=!0;this.renderGridLine(f,u,e);this.renderMark(m,u,e);this.renderLabel(m,f,u,a);this.isNew=!1},destroy:function(){H(this,this.axis)}}})(M);var V=function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.color,l=a.correctFloat,r=a.defaultOptions,n=a.defined,w=a.deg2rad,u=a.destroyObjectProperties,e=a.each,h=a.extend,m=a.fireEvent,d=a.format, -c=a.getMagnitude,b=a.grep,k=a.inArray,z=a.isArray,B=a.isNumber,I=a.isString,x=a.merge,K=a.normalizeTickInterval,t=a.objectEach,C=a.pick,N=a.removeEvent,q=a.splat,A=a.syncTimeout,F=a.Tick,G=function(){this.init.apply(this,arguments)};a.extend(G.prototype,{defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,labels:{enabled:!0,style:{color:"#666666",cursor:"default",fontSize:"11px"}, -x:0},maxPadding:.01,minorTickLength:2,minorTickPosition:"outside",minPadding:.01,startOfWeek:1,startOnTick:!1,tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",title:{align:"middle",style:{color:"#666666"}},type:"linear",minorGridLineColor:"#f2f2f2",minorGridLineWidth:1,minorTickColor:"#999999",lineColor:"#ccd6eb",lineWidth:1,gridLineColor:"#e6e6e6",tickColor:"#ccd6eb"},defaultYAxisOptions:{endOnTick:!0,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8},maxPadding:.05, -minPadding:.05,startOnTick:!0,title:{rotation:270,text:"Values"},stackLabels:{allowOverlap:!1,enabled:!1,formatter:function(){return a.numberFormat(this.total,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"#000000",textOutline:"1px contrast"}},gridLineWidth:1,lineWidth:0},defaultLeftAxisOptions:{labels:{x:-15},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45], -x:0},title:{rotation:0}},init:function(a,b){var g=b.isX,v=this;v.chart=a;v.horiz=a.inverted&&!v.isZAxis?!g:g;v.isXAxis=g;v.coll=v.coll||(g?"xAxis":"yAxis");v.opposite=b.opposite;v.side=b.side||(v.horiz?v.opposite?0:2:v.opposite?1:3);v.setOptions(b);var c=this.options,d=c.type;v.labelFormatter=c.labels.formatter||v.defaultLabelFormatter;v.userOptions=b;v.minPixelPadding=0;v.reversed=c.reversed;v.visible=!1!==c.visible;v.zoomEnabled=!1!==c.zoomEnabled;v.hasNames="category"===d||!0===c.categories;v.categories= -c.categories||v.hasNames;v.names=v.names||[];v.plotLinesAndBandsGroups={};v.isLog="logarithmic"===d;v.isDatetimeAxis="datetime"===d;v.positiveValuesOnly=v.isLog&&!v.allowNegativeLog;v.isLinked=n(c.linkedTo);v.ticks={};v.labelEdge=[];v.minorTicks={};v.plotLinesAndBands=[];v.alternateBands={};v.len=0;v.minRange=v.userMinRange=c.minRange||c.maxZoom;v.range=c.range;v.offset=c.offset||0;v.stacks={};v.oldStacks={};v.stacksTouched=0;v.max=null;v.min=null;v.crosshair=C(c.crosshair,q(a.options.tooltip.crosshairs)[g? -0:1],!1);b=v.options.events;-1===k(v,a.axes)&&(g?a.axes.splice(a.xAxis.length,0,v):a.axes.push(v),a[v.coll].push(v));v.series=v.series||[];a.inverted&&!v.isZAxis&&g&&void 0===v.reversed&&(v.reversed=!0);t(b,function(a,g){E(v,g,a)});v.lin2log=c.linearToLogConverter||v.lin2log;v.isLog&&(v.val2lin=v.log2lin,v.lin2val=v.lin2log)},setOptions:function(a){this.options=x(this.defaultOptions,"yAxis"===this.coll&&this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions, -this.defaultLeftAxisOptions][this.side],x(r[this.coll],a))},defaultLabelFormatter:function(){var g=this.axis,b=this.value,c=g.categories,k=this.dateTimeLabelFormat,e=r.lang,q=e.numericSymbols,e=e.numericSymbolMagnitude||1E3,h=q&&q.length,m,z=g.options.labels.format,g=g.isLog?Math.abs(b):g.tickInterval;if(z)m=d(z,this);else if(c)m=b;else if(k)m=a.dateFormat(k,b);else if(h&&1E3<=g)for(;h--&&void 0===m;)c=Math.pow(e,h+1),g>=c&&0===10*b%c&&null!==q[h]&&0!==b&&(m=a.numberFormat(b/c,-1)+q[h]);void 0=== -m&&(m=1E4<=Math.abs(b)?a.numberFormat(b,-1):a.numberFormat(b,-1,void 0,""));return m},getSeriesExtremes:function(){var a=this,v=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.threshold=null;a.softThreshold=!a.isXAxis;a.buildStacks&&a.buildStacks();e(a.series,function(g){if(g.visible||!v.options.chart.ignoreHiddenSeries){var c=g.options,d=c.threshold,k;a.hasVisibleSeries=!0;a.positiveValuesOnly&&0>=d&&(d=null);if(a.isXAxis)c=g.xData,c.length&&(g=p(c),k=H(c),B(g)||g instanceof Date||(c=b(c,B), -g=p(c)),a.dataMin=Math.min(C(a.dataMin,c[0],g),g),a.dataMax=Math.max(C(a.dataMax,c[0],k),k));else if(g.getExtremes(),k=g.dataMax,g=g.dataMin,n(g)&&n(k)&&(a.dataMin=Math.min(C(a.dataMin,g),g),a.dataMax=Math.max(C(a.dataMax,k),k)),n(d)&&(a.threshold=d),!c.softThreshold||a.positiveValuesOnly)a.softThreshold=!1}})},translate:function(a,b,c,d,k,e){var g=this.linkedParent||this,v=1,q=0,h=d?g.oldTransA:g.transA;d=d?g.oldMin:g.min;var m=g.minPixelPadding;k=(g.isOrdinal||g.isBroken||g.isLog&&k)&&g.lin2val; -h||(h=g.transA);c&&(v*=-1,q=g.len);g.reversed&&(v*=-1,q-=v*(g.sector||g.len));b?(a=(a*v+q-m)/h+d,k&&(a=g.lin2val(a))):(k&&(a=g.val2lin(a)),a=B(d)?v*(a-d)*h+q+v*m+(B(e)?h*e:0):void 0);return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d,k){var g=this.chart,v=this.left,q=this.top,e,h,m=c&&g.oldChartHeight||g.chartHeight,z=c&&g.oldChartWidth|| -g.chartWidth,A;e=this.transB;var t=function(a,g,b){if(ab)d?a=Math.min(Math.max(g,a),b):A=!0;return a};k=C(k,this.translate(a,null,null,c));a=c=Math.round(k+e);e=h=Math.round(m-k-e);B(k)?this.horiz?(e=q,h=m-this.bottom,a=c=t(a,v,v+this.width)):(a=v,c=z-this.right,e=h=t(e,q,q+this.height)):(A=!0,d=!1);return A&&!d?null:g.renderer.crispLine(["M",a,e,"L",c,h],b||1)},getLinearTickPositions:function(a,b,c){var g,v=l(Math.floor(b/a)*a);c=l(Math.ceil(c/a)*a);var d=[],k;l(v+a)===v&&(k=20);if(this.single)return[b]; -for(b=v;b<=c;){d.push(b);b=l(b+a,k);if(b===g)break;g=b}return d},getMinorTickInterval:function(){var a=this.options;return!0===a.minorTicks?C(a.minorTickInterval,"auto"):!1===a.minorTicks?null:a.minorTickInterval},getMinorTickPositions:function(){var a=this,b=a.options,c=a.tickPositions,d=a.minorTickInterval,k=[],q=a.pointRangePadding||0,h=a.min-q,q=a.max+q,m=q-h;if(m&&m/d=this.minRange,t=this.minRange,d=(t-c+b)/2,d=[b-d,C(a.min,b-d)],k&&(d[2]=this.isLog?this.log2lin(this.dataMin):this.dataMin),b=H(d),c=[b+t,C(a.max,b+t)],k&&(c[2]=this.isLog?this.log2lin(this.dataMax):this.dataMax),c=p(c),c-b=p?(r=p,f=0):b.dataMax<=p&&(w=p,x=0)),b.min= -C(N,r,b.dataMin),b.max=C(D,w,b.dataMax));q&&(b.positiveValuesOnly&&!g&&0>=Math.min(b.min,C(b.dataMin,b.min))&&a.error(10,1),b.min=l(h(b.min),15),b.max=l(h(b.max),15));b.range&&n(b.max)&&(b.userMin=b.min=N=Math.max(b.dataMin,b.minFromRange()),b.userMax=D=b.max,b.range=null);m(b,"foundExtremes");b.beforePadding&&b.beforePadding();b.adjustForMinRange();!(G||b.axisPointRange||b.usePercentage||t)&&n(b.min)&&n(b.max)&&(h=b.max-b.min)&&(!n(N)&&f&&(b.min-=h*f),!n(D)&&x&&(b.max+=h*x));B(k.softMin)&&!B(b.userMin)&& -(b.min=Math.min(b.min,k.softMin));B(k.softMax)&&!B(b.userMax)&&(b.max=Math.max(b.max,k.softMax));B(k.floor)&&(b.min=Math.max(b.min,k.floor));B(k.ceiling)&&(b.max=Math.min(b.max,k.ceiling));I&&n(b.dataMin)&&(p=p||0,!n(N)&&b.min=p?b.min=p:!n(D)&&b.max>p&&b.dataMax<=p&&(b.max=p));b.tickInterval=b.min===b.max||void 0===b.min||void 0===b.max?1:t&&!F&&u===b.linkedParent.options.tickPixelInterval?F=b.linkedParent.tickInterval:C(F,this.tickAmount?(b.max-b.min)/Math.max(this.tickAmount-1,1): -void 0,G?1:(b.max-b.min)*u/Math.max(b.len,u));A&&!g&&e(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();b.postProcessTickInterval&&(b.tickInterval=b.postProcessTickInterval(b.tickInterval));b.pointRange&&!F&&(b.tickInterval=Math.max(b.pointRange,b.tickInterval));g=C(k.minTickInterval,b.isDatetimeAxis&&b.closestPointRange);!F&&b.tickIntervalb.tickInterval&&1E3b.max)),!!this.tickAmount));this.tickAmount||(b.tickInterval=b.unsquish());this.setTickPositions()},setTickPositions:function(){var a=this.options,b,c=a.tickPositions;b=this.getMinorTickInterval();var d=a.tickPositioner,k=a.startOnTick,q=a.endOnTick;this.tickmarkOffset=this.categories&&"between"===a.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===b&&this.tickInterval?this.tickInterval/ -5:b;this.single=this.min===this.max&&n(this.min)&&!this.tickAmount&&(parseInt(this.min,10)===this.min||!1!==a.allowDecimals);this.tickPositions=b=c&&c.slice();!b&&(b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),b.length>this.len&&(b= -[b[0],b.pop()],b[0]===b[1]&&(b.length=1)),this.tickPositions=b,d&&(d=d.apply(this,[this.min,this.max])))&&(this.tickPositions=b=d);this.paddedTicks=b.slice(0);this.trimTicks(b,k,q);this.isLinked||(this.single&&2>b.length&&(this.min-=.5,this.max+=.5),c||d||this.adjustTickAmount())},trimTicks:function(a,b,c){var g=a[0],d=a[a.length-1],k=this.minPointOffset||0;if(!this.isLinked){if(b&&-Infinity!==g)this.min=g;else for(;this.min-k>a[0];)a.shift();if(c)this.max=d;else for(;this.max+kb&&(this.finalTickAmt=b,b=5);this.tickAmount=b},adjustTickAmount:function(){var a=this.tickInterval,b=this.tickPositions,c=this.tickAmount,d=this.finalTickAmt,k=b&&b.length,q=C(this.threshold,this.softThreshold?0:null);if(this.hasData()){if(kc&&(this.tickInterval*= -2,this.setTickPositions());if(n(d)){for(a=c=b.length;a--;)(3===d&&1===a%2||2>=d&&0d&&(a=d)),n(c)&&(bd&&(b=d))),this.displayBtn=void 0!==a||void 0!==b,this.setExtremes(a,b,!1,void 0,{trigger:"zoom"});return!0},setAxisSize:function(){var b=this.chart,c=this.options,d=c.offsets||[0,0,0,0],k=this.horiz,q=this.width=Math.round(a.relativeLength(C(c.width,b.plotWidth-d[3]+d[1]),b.plotWidth)),e=this.height=Math.round(a.relativeLength(C(c.height, -b.plotHeight-d[0]+d[2]),b.plotHeight)),h=this.top=Math.round(a.relativeLength(C(c.top,b.plotTop+d[0]),b.plotHeight,b.plotTop)),c=this.left=Math.round(a.relativeLength(C(c.left,b.plotLeft+d[3]),b.plotWidth,b.plotLeft));this.bottom=b.chartHeight-e-h;this.right=b.chartWidth-q-c;this.len=Math.max(k?q:e,0);this.pos=k?c:h},getExtremes:function(){var a=this.isLog,b=this.lin2log;return{min:a?l(b(this.min)):this.min,max:a?l(b(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin, -userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,g=this.lin2log,c=b?g(this.min):this.min,b=b?g(this.max):this.max;null===a?a=c:c>a?a=c:ba?"right":195a?"left":"center"},tickSize:function(a){var b=this.options,g=b[a+"Length"],c=C(b[a+"Width"],"tick"===a&&this.isXAxis?1:0);if(c&&g)return"inside"===b[a+"Position"]&&(g=-g),[g,c]},labelMetrics:function(){var a= -this.tickPositions&&this.tickPositions[0]||0;return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize,this.ticks[a]&&this.ticks[a].label)},unsquish:function(){var a=this.options.labels,b=this.horiz,c=this.tickInterval,d=c,k=this.len/(((this.categories?1:0)+this.max-this.min)/c),q,h=a.rotation,m=this.labelMetrics(),z,A=Number.MAX_VALUE,t,x=function(a){a/=k||1;a=1=a)z=x(Math.abs(m.h/Math.sin(w*a))),b=z+Math.abs(a/360),b(c.step||0)&&!c.rotation&&(this.staggerLines||1)*this.len/d||!b&&(c.style&&parseInt(c.style.width,10)||k&&k-a.spacing[3]|| -.33*a.chartWidth)},renderUnsquish:function(){var a=this.chart,b=a.renderer,c=this.tickPositions,d=this.ticks,k=this.options.labels,q=this.horiz,h=this.getSlotWidth(),m=Math.max(1,Math.round(h-2*(k.padding||5))),z={},A=this.labelMetrics(),t=k.style&&k.style.textOverflow,f,F=0,l,B;I(k.rotation)||(z.rotation=k.rotation||0);e(c,function(a){(a=d[a])&&a.labelLength>F&&(F=a.labelLength)});this.maxLabelLength=F;if(this.autoRotation)F>m&&F>A.h?z.rotation=this.labelRotation:this.labelRotation=0;else if(h&& -(f={width:m+"px"},!t))for(f.textOverflow="clip",l=c.length;!q&&l--;)if(B=c[l],m=d[B].label)m.styles&&"ellipsis"===m.styles.textOverflow?m.css({textOverflow:"clip"}):d[B].labelLength>h&&m.css({width:h+"px"}),m.getBBox().height>this.len/c.length-(A.h-A.f)&&(m.specCss={textOverflow:"ellipsis"});z.rotation&&(f={width:(F>.5*a.chartHeight?.33*a.chartHeight:a.chartHeight)+"px"},t||(f.textOverflow="ellipsis"));if(this.labelAlign=k.align||this.autoLabelAlign(this.labelRotation))z.align=this.labelAlign;e(c, -function(a){var b=(a=d[a])&&a.label;b&&(b.attr(z),f&&b.css(x(f,b.specCss)),delete b.specCss,a.rotation=z.rotation)});this.tickRotCorr=b.rotCorr(A.b,this.labelRotation||0,0!==this.side)},hasData:function(){return this.hasVisibleSeries||n(this.min)&&n(this.max)&&this.tickPositions&&0=this.min&&a<=this.max)g[a]||(g[a]=new F(this,a)),d&&g[a].isNew&&g[a].render(b,!0,.1),g[a].render(b)},render:function(){var b= -this,c=b.chart,d=b.options,k=b.isLog,q=b.lin2log,h=b.isLinked,m=b.tickPositions,z=b.axisTitle,x=b.ticks,f=b.minorTicks,l=b.alternateBands,C=d.stackLabels,n=d.alternateGridColor,u=b.tickmarkOffset,G=b.axisLine,p=b.showAxis,I=D(c.renderer.globalAnimation),r,w;b.labelEdge.length=0;b.overlap=!1;e([x,f,l],function(a){t(a,function(a){a.isActive=!1})});if(b.hasData()||h)b.minorTickInterval&&!b.categories&&e(b.getMinorTickPositions(),function(a){b.renderMinorTick(a)}),m.length&&(e(m,function(a,c){b.renderTick(a, -c)}),u&&(0===b.min||b.single)&&(x[-1]||(x[-1]=new F(b,-1,null,!0)),x[-1].render(-1))),n&&e(m,function(d,g){w=void 0!==m[g+1]?m[g+1]+u:b.max-u;0===g%2&&d=h.second?0:C*Math.floor(x.getMilliseconds()/C));if(t>=h.second)x[D.hcSetSeconds](t>=h.minute? -0:C*Math.floor(x.getSeconds()/C));if(t>=h.minute)x[D.hcSetMinutes](t>=h.hour?0:C*Math.floor(x[D.hcGetMinutes]()/C));if(t>=h.hour)x[D.hcSetHours](t>=h.day?0:C*Math.floor(x[D.hcGetHours]()/C));if(t>=h.day)x[D.hcSetDate](t>=h.month?1:C*Math.floor(x[D.hcGetDate]()/C));t>=h.month&&(x[D.hcSetMonth](t>=h.year?0:C*Math.floor(x[D.hcGetMonth]()/C)),n=x[D.hcGetFullYear]());if(t>=h.year)x[D.hcSetFullYear](n-n%C);if(t===h.week)x[D.hcSetDate](x[D.hcGetDate]()-x[D.hcGetDay]()+e(b,1));n=x[D.hcGetFullYear]();b=x[D.hcGetMonth](); -var A=x[D.hcGetDate](),F=x[D.hcGetHours]();d=x.getTime();D.hcHasTimeZone&&(q=(!B||!!D.hcGetTimezoneOffset)&&(c-d>4*h.month||w(d)!==w(c)),N=w(x),x=new D(d+N));B=x.getTime();for(d=1;Bk.length&&l(k,function(a){0===a%18E5&&"000000000"===H("%H%M%S%L",a)&&(m[a]="day")})}k.info=r(a,{higherRanks:m,totalRange:t*C});return k}; -E.prototype.normalizeTimeTickInterval=function(a,d){var c=d||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2,3,4,6]],["year",null]];d=c[c.length-1];var b=h[d[0]],k=d[1],e;for(e=0;er&&(!w||z<=n)&&void 0!==z&&d.push(z),z>n&& -(B=!0),z=k;else r=h(r),n=h(n),a=w?this.getMinorTickInterval():l.tickInterval,a=f("auto"===a?null:a,this._minorAutoInterval,l.tickPixelInterval/(w?5:1)*(n-r)/((w?e/this.tickPositions.length:e)||1)),a=p(a,null,D(a)),d=H(this.getLinearTickPositions(a,r,n),m),w||(this._minorAutoInterval=a/5);w||(this.tickInterval=a);return d};E.prototype.log2lin=function(a){return Math.log(a)/Math.LN10};E.prototype.lin2log=function(a){return Math.pow(10,a)}})(M);(function(a,E){var D=a.arrayMax,H=a.arrayMin,p=a.defined, -f=a.destroyObjectProperties,l=a.each,r=a.erase,n=a.merge,w=a.pick;a.PlotLineOrBand=function(a,e){this.axis=a;e&&(this.options=e,this.id=e.id)};a.PlotLineOrBand.prototype={render:function(){var f=this,e=f.axis,h=e.horiz,m=f.options,d=m.label,c=f.label,b=m.to,k=m.from,z=m.value,l=p(k)&&p(b),r=p(z),x=f.svgElem,K=!x,t=[],C=m.color,N=w(m.zIndex,0),q=m.events,t={"class":"highcharts-plot-"+(l?"band ":"line ")+(m.className||"")},A={},F=e.chart.renderer,G=l?"bands":"lines",g=e.log2lin;e.isLog&&(k=g(k),b=g(b), -z=g(z));r?(t={stroke:C,"stroke-width":m.width},m.dashStyle&&(t.dashstyle=m.dashStyle)):l&&(C&&(t.fill=C),m.borderWidth&&(t.stroke=m.borderColor,t["stroke-width"]=m.borderWidth));A.zIndex=N;G+="-"+N;(C=e.plotLinesAndBandsGroups[G])||(e.plotLinesAndBandsGroups[G]=C=F.g("plot-"+G).attr(A).add());K&&(f.svgElem=x=F.path().attr(t).add(C));if(r)t=e.getPlotLinePath(z,x.strokeWidth());else if(l)t=e.getPlotBandPath(k,b,m);else return;K&&t&&t.length?(x.attr({d:t}),q&&a.objectEach(q,function(a,b){x.on(b,function(a){q[b].apply(f, -[a])})})):x&&(t?(x.show(),x.animate({d:t})):(x.hide(),c&&(f.label=c=c.destroy())));d&&p(d.text)&&t&&t.length&&0this.max&& -e>this.max;if(m&&h)for(a&&(k=m.toString()===h.toString(),b=0),a=0;aA-h?A:A-h);else if(z)k[a]=Math.max(e,g+h+d>c?g:g+h);else return!1},C=function(a,c,d,g){var e;gc-b?e=!1:k[a]=gc-d/2?c-d-2:g-d/2;return e},p=function(a){var b=f;f=x;x=b;m=a},q=function(){!1!==t.apply(0,f)?!1!==C.apply(0,x)||m||(p(!0),q()):m?k.x=k.y=0:(p(!0),q())};(c.inverted||1q&&(h=!1);a=(e.series&& -e.series.yAxis&&e.series.yAxis.pos)+(e.plotY||0);a-=b.plotTop;c.push({target:e.isHeader?b.plotHeight+l:a,rank:e.isHeader?1:0,size:z.tt.getBBox().height+1,point:e,x:q,tt:t})}});this.cleanSplit();a.distribute(c,b.plotHeight+l);D(c,function(a){var c=a.point,d=c.series;a.tt.attr({visibility:void 0===a.pos?"hidden":"inherit",x:h||c.isHeader?a.x:c.plotX+b.plotLeft+n(f.distance,16),y:a.pos+b.plotTop,anchorX:c.isHeader?c.plotX+b.plotLeft:c.plotX+d.xAxis.pos,anchorY:c.isHeader?a.pos+b.plotTop-15:c.plotY+d.yAxis.pos})})}, -updatePosition:function(a){var e=this.chart,d=this.getLabel(),d=(this.options.positioner||this.getPosition).call(this,d.width,d.height,a);this.move(Math.round(d.x),Math.round(d.y||0),a.plotX+e.plotLeft,a.plotY+e.plotTop)},getDateFormat:function(a,m,d,c){var b=E("%m-%d %H:%M:%S.%L",m),k,h,f={millisecond:15,second:12,minute:9,hour:6,day:3},l="millisecond";for(h in e){if(a===e.week&&+E("%w",m)===d&&"00:00:00.000"===b.substr(6)){h="week";break}if(e[h]>a){h=l;break}if(f[h]&&b.substr(f[h])!=="01-01 00:00:00.000".substr(f[h]))break; -"week"!==h&&(l=h)}h&&(k=c[h]);return k},getXDateFormat:function(a,e,d){e=e.dateTimeLabelFormats;var c=d&&d.closestPointRange;return(c?this.getDateFormat(c,a.x,d.options.startOfWeek,e):e.day)||e.year},tooltipFooterHeaderFormatter:function(a,e){e=e?"footer":"header";var d=a.series,c=d.tooltipOptions,b=c.xDateFormat,k=d.xAxis,h=k&&"datetime"===k.options.type&&f(a.key),m=c[e+"Format"];h&&!b&&(b=this.getXDateFormat(a,c,k));h&&b&&D(a.point&&a.point.tooltipDateKeys||["key"],function(a){m=m.replace("{point."+ -a+"}","{point."+a+":"+b+"}")});return p(m,{point:a,series:d})},bodyFormatter:function(a){return l(a,function(a){var d=a.series.tooltipOptions;return(d[(a.point.formatPrefix||"point")+"Formatter"]||a.point.tooltipFormatter).call(a.point,d[(a.point.formatPrefix||"point")+"Format"])})}}})(M);(function(a){var E=a.addEvent,D=a.attr,H=a.charts,p=a.color,f=a.css,l=a.defined,r=a.each,n=a.extend,w=a.find,u=a.fireEvent,e=a.isObject,h=a.offset,m=a.pick,d=a.splat,c=a.Tooltip;a.Pointer=function(a,c){this.init(a, -c)};a.Pointer.prototype={init:function(a,d){this.options=d;this.chart=a;this.runChartClick=d.chart.events&&!!d.chart.events.click;this.pinchDown=[];this.lastValidTouch={};c&&(a.tooltip=new c(a,d.tooltip),this.followTouchMove=m(d.tooltip.followTouchMove,!0));this.setDOMEvents()},zoomOption:function(a){var b=this.chart,c=b.options.chart,d=c.zoomType||"",b=b.inverted;/touch/.test(a.type)&&(d=m(c.pinchType,d));this.zoomX=a=/x/.test(d);this.zoomY=d=/y/.test(d);this.zoomHor=a&&!b||d&&b;this.zoomVert=d&& -!b||a&&b;this.hasZoom=a||d},normalize:function(a,c){var b;b=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:a;c||(this.chartPosition=c=h(this.chart.container));return n(a,{chartX:Math.round(b.pageX-c.left),chartY:Math.round(b.pageY-c.top)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};r(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},findNearestKDPoint:function(a,c,d){var b;r(a,function(a){var k= -!(a.noSharedTooltip&&c)&&0>a.options.findNearestPointBy.indexOf("y");a=a.searchPoint(d,k);if((k=e(a,!0))&&!(k=!e(b,!0)))var k=b.distX-a.distX,h=b.dist-a.dist,m=(a.series.group&&a.series.group.zIndex)-(b.series.group&&b.series.group.zIndex),k=0<(0!==k&&c?k:0!==h?h:0!==m?m:b.series.index>a.series.index?-1:1);k&&(b=a)});return b},getPointFromEvent:function(a){a=a.target;for(var b;a&&!b;)b=a.point,a=a.parentNode;return b},getChartCoordinatesFromPoint:function(a,c){var b=a.series,d=b.xAxis,b=b.yAxis,k= -m(a.clientX,a.plotX);if(d&&b)return c?{chartX:d.len+d.pos-k,chartY:b.len+b.pos-a.plotY}:{chartX:k+d.pos,chartY:a.plotY+b.pos}},getHoverData:function(b,c,d,h,f,l,n){var k,z=[],x=n&&n.isBoosting;h=!(!h||!b);n=c&&!c.stickyTracking?[c]:a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking,!0)&&a.stickyTracking});c=(k=h?b:this.findNearestKDPoint(n,f,l))&&k.series;k&&(f&&!c.noSharedTooltip?(n=a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking, -!0)&&!a.noSharedTooltip}),r(n,function(a){var b=w(a.points,function(a){return a.x===k.x&&!a.isNull});e(b)&&(x&&(b=a.getPoint(b)),z.push(b))})):z.push(k));return{hoverPoint:k,hoverSeries:c,hoverPoints:z}},runPointActions:function(b,c){var d=this.chart,k=d.tooltip&&d.tooltip.options.enabled?d.tooltip:void 0,e=k?k.shared:!1,h=c||d.hoverPoint,f=h&&h.series||d.hoverSeries,f=this.getHoverData(h,f,d.series,!!c||f&&f.directTouch&&this.isDirectTouch,e,b,{isBoosting:d.isBoosting}),l,h=f.hoverPoint;l=f.hoverPoints; -c=(f=f.hoverSeries)&&f.tooltipOptions.followPointer;e=e&&f&&!f.noSharedTooltip;if(h&&(h!==d.hoverPoint||k&&k.isHidden)){r(d.hoverPoints||[],function(b){-1===a.inArray(b,l)&&b.setState()});r(l||[],function(a){a.setState("hover")});if(d.hoverSeries!==f)f.onMouseOver();d.hoverPoint&&d.hoverPoint.firePointEvent("mouseOut");if(!h.series)return;h.firePointEvent("mouseOver");d.hoverPoints=l;d.hoverPoint=h;k&&k.refresh(e?l:h,b)}else c&&k&&!k.isHidden&&(h=k.getAnchor([{}],b),k.updatePosition({plotX:h[0],plotY:h[1]})); -this.unDocMouseMove||(this.unDocMouseMove=E(d.container.ownerDocument,"mousemove",function(b){var c=H[a.hoverChartIndex];if(c)c.pointer.onDocumentMouseMove(b)}));r(d.axes,function(c){var d=m(c.crosshair.snap,!0),k=d?a.find(l,function(a){return a.series[c.coll]===c}):void 0;k||!d?c.drawCrosshair(b,k):c.hideCrosshair()})},reset:function(a,c){var b=this.chart,k=b.hoverSeries,e=b.hoverPoint,h=b.hoverPoints,m=b.tooltip,f=m&&m.shared?h:e;a&&f&&r(d(f),function(b){b.series.isCartesian&&void 0===b.plotX&& -(a=!1)});if(a)m&&f&&(m.refresh(f),e&&(e.setState(e.state,!0),r(b.axes,function(a){a.crosshair&&a.drawCrosshair(null,e)})));else{if(e)e.onMouseOut();h&&r(h,function(a){a.setState()});if(k)k.onMouseOut();m&&m.hide(c);this.unDocMouseMove&&(this.unDocMouseMove=this.unDocMouseMove());r(b.axes,function(a){a.hideCrosshair()});this.hoverX=b.hoverPoints=b.hoverPoint=null}},scaleGroups:function(a,c){var b=this.chart,d;r(b.series,function(k){d=a||k.getPlotBox();k.xAxis&&k.xAxis.zoomEnabled&&k.group&&(k.group.attr(d), -k.markerGroup&&(k.markerGroup.attr(d),k.markerGroup.clip(c?b.clipRect:null)),k.dataLabelsGroup&&k.dataLabelsGroup.attr(d))});b.clipRect.attr(c||b.clipBox)},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,h=this.zoomHor,m=this.zoomVert,f=b.plotLeft,l=b.plotTop,n=b.plotWidth,q=b.plotHeight,A,F=this.selectionMarker,G=this.mouseDownX, -g=this.mouseDownY,v=c.panKey&&a[c.panKey+"Key"];F&&F.touch||(df+n&&(d=f+n),el+q&&(e=l+q),this.hasDragged=Math.sqrt(Math.pow(G-d,2)+Math.pow(g-e,2)),10u.max&&(f=u.max-x,v=!0);v?(F-=.8*(F-m[b][0]),q||(g-=.8*(g-m[b][1])),l()):m[b]=[F,g];C||(h[b]=w-r,h[n]=x);h=C?1/t:t;e[n]=x;e[b]=f;p[C?a?"scaleY":"scaleX":"scale"+k]=t;p["translate"+k]=h*r+(F-h*A)},pinch:function(a){var n=this,r=n.chart,u=n.pinchDown,e=a.touches,h=e.length,m=n.lastValidTouch, -d=n.hasZoom,c=n.selectionMarker,b={},k=1===h&&(n.inClass(a.target,"highcharts-tracker")&&r.runTrackerClick||n.runChartClick),z={};1c-6&&h(q||c.spacingBox.width-2*t-d.x)&&(this.itemX=t,this.itemY+=F+this.lastLineHeight+A,this.lastLineHeight=0);this.maxItemWidth=Math.max(this.maxItemWidth,m);this.lastItemY=F+this.itemY+A;this.lastLineHeight=Math.max(b,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=m:(this.itemY+=F+b+A,this.lastLineHeight=b);this.offsetWidth=q||Math.max((e?this.itemX-t-(a.checkbox?0:p):m)+t,this.offsetWidth)}, -getAllItems:function(){var a=[];f(this.chart.series,function(c){var b=c&&c.options;c&&w(b.showInLegend,p(b.linkedTo)?!1:void 0,!0)&&(a=a.concat(c.legendItems||("point"===b.legendType?c.data:c)))});return a},getAlignment:function(){var a=this.options;return a.floating?"":a.align.charAt(0)+a.verticalAlign.charAt(0)+a.layout.charAt(0)},adjustMargins:function(a,c){var b=this.chart,d=this.options,e=this.getAlignment();e&&f([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(k,h){k.test(e)&& -!p(a[h])&&(b[r[h]]=Math.max(b[r[h]],b.legend[(h+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][h]*d[h%2?"x":"y"]+w(d.margin,12)+c[h]+(0===h?b.titleOffset+b.options.title.margin:0)))})},render:function(){var a=this,c=a.chart,b=c.renderer,k=a.group,h,m,l,x,p=a.box,t=a.options,C=a.padding;a.itemX=C;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;k||(a.group=k=b.g("legend").attr({zIndex:7}).add(),a.contentGroup=b.g().attr({zIndex:1}).add(k),a.scrollGroup=b.g().add(a.contentGroup));a.renderTitle(); -h=a.getAllItems();e(h,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});t.reversed&&h.reverse();a.allItems=h;a.display=m=!!h.length;a.lastLineHeight=0;f(h,function(b){a.renderItem(b)});l=(t.width||a.offsetWidth)+C;x=a.lastItemY+a.lastLineHeight+a.titleHeight;x=a.handleOverflow(x);x+=C;p||(a.box=p=b.rect().addClass("highcharts-legend-box").attr({r:t.borderRadius}).add(k),p.isNew=!0);p.attr({stroke:t.borderColor,"stroke-width":t.borderWidth||0,fill:t.backgroundColor|| -"none"}).shadow(t.shadow);0b&&!1!==t.enabled?(this.clipHeight=l=Math.max(b-20-this.titleHeight-m,0),this.currentPage=w(this.currentPage,1),this.fullHeight=a,f(G,function(a,b){var c=a._legendItemPos[1],d=Math.round(a.legendItem.getBBox().height),g=A.length;if(!g||c-A[g-1]>l&&(F||c)!==A[g-1])A.push(F||c),g++;a.pageIx=g-1;F&&(G[b-1].pageIx=g-1);b===G.length-1&&c+d-A[g-1]>l&&(A.push(c),a.pageIx=g);c!==F&&(F=c)}),n||(n=c.clipRect=d.clipRect(0,m,9999,0),c.contentGroup.clip(n)),g(l),q||(this.nav=q=d.g().attr({zIndex:1}).add(this.group), -this.up=d.symbol("triangle",0,0,r,r).on("click",function(){c.scroll(-1,p)}).add(q),this.pager=d.text("",15,10).addClass("highcharts-legend-navigation").css(t.style).add(q),this.down=d.symbol("triangle-down",0,0,r,r).on("click",function(){c.scroll(1,p)}).add(q)),c.scroll(0),a=b):q&&(g(),this.nav=q.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return a},scroll:function(a,c){var b=this.pages,d=b.length;a=this.currentPage+a;var e=this.clipHeight,h=this.options.navigation,f=this.pager, -m=this.padding;a>d&&(a=d);0b&&(f=typeof a[0],"string"===f?e.name=a[0]:"number"===f&&(e.x=a[0]),k++);l=d.value;)d=h[++f];d&&d.color&&!this.options.color&&(this.color=d.color);return d},destroy:function(){var a=this.series.chart,h=a.hoverPoints,f;a.pointCount--;h&&(this.setState(),p(h,this),h.length||(a.hoverPoints=null));if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)u(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(f in this)this[f]=null},destroyElements:function(){for(var a=["graphic","dataLabel", -"dataLabelUpper","connector","shadowGroup"],h,f=6;f--;)h=a[f],this[h]&&(this[h]=this[h].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,color:this.color,colorIndex:this.colorIndex,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},tooltipFormatter:function(a){var e=this.series,f=e.tooltipOptions,d=w(f.valueDecimals,""),c=f.valuePrefix||"",b=f.valueSuffix||"";D(e.pointArrayMap||["y"],function(e){e="{point."+ -e;if(c||b)a=a.replace(e+"}",c+e+"}"+b);a=a.replace(e+"}",e+":,."+d+"f}")});return l(a,{point:this,series:this.series})},firePointEvent:function(a,h,m){var d=this,c=this.series.options;(c.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents();"click"===a&&c.allowPointSelect&&(m=function(a){d.select&&d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});f(this,a,h,m)},visible:!0}})(M);(function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.correctFloat, -l=a.Date,r=a.defaultOptions,n=a.defaultPlotOptions,w=a.defined,u=a.each,e=a.erase,h=a.extend,m=a.fireEvent,d=a.grep,c=a.isArray,b=a.isNumber,k=a.isString,z=a.merge,B=a.objectEach,I=a.pick,x=a.removeEvent,K=a.splat,t=a.SVGElement,C=a.syncTimeout,N=a.win;a.Series=a.seriesType("line",null,{lineWidth:2,allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},marker:{lineWidth:0,lineColor:"#ffffff",radius:4,states:{hover:{animation:{duration:50},enabled:!0,radiusPlus:2,lineWidthPlus:1},select:{fillColor:"#cccccc", -lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:{align:"center",formatter:function(){return null===this.y?"":a.numberFormat(this.y,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"contrast",textOutline:"1px contrast"},verticalAlign:"bottom",x:0,y:0,padding:5},cropThreshold:300,pointRange:0,softThreshold:!0,states:{hover:{animation:{duration:50},lineWidthPlus:1,marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1E3,findNearestPointBy:"x"}, -{isCartesian:!0,pointClass:a.Point,sorted:!0,requireSorting:!0,directTouch:!1,axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],coll:"series",init:function(a,b){var c=this,d,g=a.series,e;c.chart=a;c.options=b=c.setOptions(b);c.linkedSeries=[];c.bindAxes();h(c,{name:b.name,state:"",visible:!1!==b.visible,selected:!0===b.selected});d=b.events;B(d,function(a,b){E(c,b,a)});if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;c.getColor(); -c.getSymbol();u(c.parallelArrays,function(a){c[a+"Data"]=[]});c.setData(b.data,!1);c.isCartesian&&(a.hasCartesianSeries=!0);g.length&&(e=g[g.length-1]);c._i=I(e&&e._i,-1)+1;a.orderSeries(this.insert(g))},insert:function(a){var c=this.options.index,d;if(b(c)){for(d=a.length;d--;)if(c>=I(a[d].options.index,a[d]._i)){a.splice(d+1,0,this);break}-1===d&&a.unshift(this);d+=1}else a.push(this);return I(d,a.length-1)},bindAxes:function(){var b=this,c=b.options,d=b.chart,e;u(b.axisTypes||[],function(g){u(d[g], -function(a){e=a.options;if(c[g]===e.index||void 0!==c[g]&&c[g]===e.id||void 0===c[g]&&0===e.index)b.insert(a.series),b[g]=a,a.isDirty=!0});b[g]||b.optionalAxis===g||a.error(18,!0)})},updateParallelArrays:function(a,c){var d=a.series,e=arguments,g=b(c)?function(b){var g="y"===b&&d.toYData?d.toYData(a):a[b];d[b+"Data"][c]=g}:function(a){Array.prototype[c].apply(d[a+"Data"],Array.prototype.slice.call(e,2))};u(d.parallelArrays,g)},autoIncrement:function(){var b=this.options,c=this.xIncrement,d,e=b.pointIntervalUnit, -g=0,c=I(c,b.pointStart,0);this.pointInterval=d=I(this.pointInterval,b.pointInterval,1);e&&(b=new l(c),"day"===e?b=+b[l.hcSetDate](b[l.hcGetDate]()+d):"month"===e?b=+b[l.hcSetMonth](b[l.hcGetMonth]()+d):"year"===e&&(b=+b[l.hcSetFullYear](b[l.hcGetFullYear]()+d)),l.hcHasTimeZone&&(g=a.getTZOffset(b)-a.getTZOffset(c)),d=b-c+g);this.xIncrement=c+d;return c},setOptions:function(a){var b=this.chart,c=b.options,d=c.plotOptions,g=(b.userOptions||{}).plotOptions||{},e=d[this.type];this.userOptions=a;b=z(e, -d.series,a);this.tooltipOptions=z(r.tooltip,r.plotOptions.series&&r.plotOptions.series.tooltip,r.plotOptions[this.type].tooltip,c.tooltip.userOptions,d.series&&d.series.tooltip,d[this.type].tooltip,a.tooltip);this.stickyTracking=I(a.stickyTracking,g[this.type]&&g[this.type].stickyTracking,g.series&&g.series.stickyTracking,this.tooltipOptions.shared&&!this.noSharedTooltip?!0:b.stickyTracking);null===e.marker&&delete b.marker;this.zoneAxis=b.zoneAxis;a=this.zones=(b.zones||[]).slice();!b.negativeColor&& -!b.negativeFillColor||b.zones||a.push({value:b[this.zoneAxis+"Threshold"]||b.threshold||0,className:"highcharts-negative",color:b.negativeColor,fillColor:b.negativeFillColor});a.length&&w(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return b},getCyclic:function(a,b,c){var d,g=this.chart,e=this.userOptions,k=a+"Index",h=a+"Counter",q=c?c.length:I(g.options.chart[a+"Count"],g[a+"Count"]);b||(d=I(e[k],e["_"+k]),w(d)||(g.series.length||(g[h]=0),e["_"+k]=d=g[h]%q,g[h]+=1), -c&&(b=c[d]));void 0!==d&&(this[k]=d);this[a]=b},getColor:function(){this.options.colorByPoint?this.options.color=null:this.getCyclic("color",this.options.color||n[this.type].color,this.chart.options.colors)},getSymbol:function(){this.getCyclic("symbol",this.options.marker.symbol,this.chart.options.symbols)},drawLegendSymbol:a.LegendSymbolMixin.drawLineMarker,setData:function(d,e,h,f){var g=this,q=g.points,m=q&&q.length||0,l,A=g.options,t=g.chart,x=null,n=g.xAxis,p=A.turboThreshold,z=this.xData,F= -this.yData,C=(l=g.pointArrayMap)&&l.length;d=d||[];l=d.length;e=I(e,!0);if(!1!==f&&l&&m===l&&!g.cropped&&!g.hasGroupedData&&g.visible)u(d,function(a,b){q[b].update&&a!==A.data[b]&&q[b].update(a,!1,null,!1)});else{g.xIncrement=null;g.colorCounter=0;u(this.parallelArrays,function(a){g[a+"Data"].length=0});if(p&&l>p){for(h=0;null===x&&hf||this.forceCrop))if(c[e-1]z)c=[],d=[];else if(c[0]z)g=this.cropData(this.xData,this.yData,p,z),c=g.xData,d=g.yData,g=g.start,k=!0;for(f=c.length|| -1;--f;)e=x?m(c[f])-m(c[f-1]):c[f]-c[f-1],0e&&n&&(a.error(15),n=!1);this.cropped=k;this.cropStart=g;this.processedXData=c;this.processedYData=d;this.closestPointRange=h},cropData:function(a,b,c,d){var g=a.length,e=0,k=g,h=I(this.cropShoulder,1),f;for(f=0;f=c){e=Math.max(0,f-h);break}for(c=f;cd){k=c+h;break}return{xData:a.slice(e,k),yData:b.slice(e,k),start:e,end:k}},generatePoints:function(){var a=this.options,b=a.data,c=this.data,d,g=this.processedXData, -e=this.processedYData,k=this.pointClass,h=g.length,f=this.cropStart||0,m,l=this.hasGroupedData,a=a.keys,t,x=[],n;c||l||(c=[],c.length=b.length,c=this.data=c);a&&l&&(this.options.keys=!1);for(n=0;n=f&&(e[n-1]||l)<=q,m&&l)if(m=t.length)for(;m--;)"number"===typeof t[m]&&(g[h++]=t[m]);else g[h++]=t;this.dataMin= -p(g);this.dataMax=H(g)},translate:function(){this.processedXData||this.processData();this.generatePoints();var a=this.options,c=a.stacking,d=this.xAxis,e=d.categories,g=this.yAxis,k=this.points,h=k.length,m=!!this.modifyValue,l=a.pointPlacement,t="between"===l||b(l),n=a.threshold,x=a.startFromThreshold?n:0,p,z,C,r,u=Number.MAX_VALUE;"between"===l&&(l=.5);b(l)&&(l*=I(a.pointRange||d.pointRange));for(a=0;a=K&&(B.isNull=!0);B.plotX=p=f(Math.min(Math.max(-1E5,d.translate(N,0,0,0,1,l,"flags"===this.type)),1E5));c&&this.visible&&!B.isNull&&D&&D[N]&&(r=this.getStackIndicator(r,N,this.index),E=D[N],K=E.points[r.key],z=K[0],K=K[1],z===x&&r.key===D[N].base&&(z=I(n,g.min)),g.positiveValuesOnly&&0>=z&&(z=null),B.total=B.stackTotal=E.total,B.percentage=E.total&&B.y/E.total*100,B.stackY=K,E.setOffset(this.pointXOffset||0,this.barW||0));B.yBottom=w(z)?g.translate(z,0,1,0,1): -null;m&&(K=this.modifyValue(K,B));B.plotY=z="number"===typeof K&&Infinity!==K?Math.min(Math.max(-1E5,g.translate(K,0,1,0,1)),1E5):void 0;B.isInside=void 0!==z&&0<=z&&z<=g.len&&0<=p&&p<=d.len;B.clientX=t?f(d.translate(N,0,0,0,1,l)):p;B.negative=B.y<(n||0);B.category=e&&void 0!==e[B.x]?e[B.x]:B.x;B.isNull||(void 0!==C&&(u=Math.min(u,Math.abs(p-C))),C=p);B.zone=this.zones.length&&B.getZone()}this.closestPointRangePx=u},getValidPoints:function(a,b){var c=this.chart;return d(a||this.points||[],function(a){return b&& -!c.isInsidePlot(a.plotX,a.plotY,c.inverted)?!1:!a.isNull})},setClip:function(a){var b=this.chart,c=this.options,d=b.renderer,g=b.inverted,e=this.clipBox,k=e||b.clipBox,h=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,k.height,c.xAxis,c.yAxis].join(),f=b[h],q=b[h+"m"];f||(a&&(k.width=0,g&&(k.x=b.plotSizeX),b[h+"m"]=q=d.clipRect(g?b.plotSizeX+99:-99,g?-b.plotLeft:-b.plotTop,99,g?b.chartWidth:b.chartHeight)),b[h]=f=d.clipRect(k),f.count={length:0});a&&!f.count[this.index]&&(f.count[this.index]= -!0,f.count.length+=1);!1!==c.clip&&(this.group.clip(a||e?f:b.clipRect),this.markerGroup.clip(q),this.sharedClipKey=h);a||(f.count[this.index]&&(delete f.count[this.index],--f.count.length),0===f.count.length&&h&&b[h]&&(e||(b[h]=b[h].destroy()),b[h+"m"]&&(b[h+"m"]=b[h+"m"].destroy())))},animate:function(a){var b=this.chart,c=D(this.options.animation),d;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX,x:0},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99,x:0},c),this.animate= -null)},afterAnimate:function(){this.setClip();m(this,"afterAnimate");this.finishedAnimating=!0},drawPoints:function(){var a=this.points,b=this.chart,c,d,g,e,k=this.options.marker,h,f,l,m=this[this.specialGroup]||this.markerGroup,t,n=I(k.enabled,this.xAxis.isRadial?!0:null,this.closestPointRangePx>=2*k.radius);if(!1!==k.enabled||this._hasPointMarkers)for(c=0;ce&&b.shadow));k&&(k.startX=c.xMap,k.isArea=c.isArea)})}, -applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,e,k,h=this.clips||[],f,m=this.graph,l=this.area,t=Math.max(b.chartWidth,b.chartHeight),n=this[(this.zoneAxis||"y")+"Axis"],x,p,z=b.inverted,C,r,w,B,K=!1;d.length&&(m||l)&&n&&void 0!==n.min&&(p=n.reversed,C=n.horiz,m&&m.hide(),l&&l.hide(),x=n.getExtremes(),u(d,function(d,g){e=p?C?b.plotWidth:0:C?0:n.toPixels(x.min);e=Math.min(Math.max(I(k,e),0),t);k=Math.min(Math.max(Math.round(n.toPixels(I(d.value,x.max),!0)),0),t);K&&(e=k=n.toPixels(x.max)); -r=Math.abs(e-k);w=Math.min(e,k);B=Math.max(e,k);n.isXAxis?(f={x:z?B:w,y:0,width:r,height:t},C||(f.x=b.plotHeight-f.x)):(f={x:0,y:z?B:w,width:t,height:r},C&&(f.y=b.plotWidth-f.y));z&&c.isVML&&(f=n.isXAxis?{x:0,y:p?w:B,height:f.width,width:b.chartWidth}:{x:f.y-b.plotLeft-b.spacingBox.x,y:0,width:f.height,height:b.chartHeight});h[g]?h[g].animate(f):(h[g]=c.clipRect(f),m&&a["zone-graph-"+g].clip(h[g]),l&&a["zone-area-"+g].clip(h[g]));K=d.value>x.max}),this.clips=h)},invertGroups:function(a){function b(){u(["group", -"markerGroup"],function(b){c[b]&&(d.renderer.isVML&&c[b].attr({width:c.yAxis.len,height:c.xAxis.len}),c[b].width=c.yAxis.len,c[b].height=c.xAxis.len,c[b].invert(a))})}var c=this,d=c.chart,e;c.xAxis&&(e=E(d,"resize",b),E(c,"destroy",e),b(a),c.invertGroups=b)},plotGroup:function(a,b,c,d,e){var g=this[a],k=!g;k&&(this[a]=g=this.chart.renderer.g().attr({zIndex:d||.1}).add(e));g.addClass("highcharts-"+b+" highcharts-series-"+this.index+" highcharts-"+this.type+"-series "+(w(this.colorIndex)?"highcharts-color-"+ -this.colorIndex+" ":"")+(this.options.className||"")+(g.hasClass("highcharts-tracker")?" highcharts-tracker":""),!0);g.attr({visibility:c})[k?"attr":"animate"](this.getPlotBox());return g},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;a.inverted&&(b=c,c=this.xAxis);return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this,b=a.chart,c,d=a.options,e=!!a.animate&&b.renderer.isSVG&&D(d.animation).duration,k=a.visible?"inherit": -"hidden",h=d.zIndex,f=a.hasRendered,m=b.seriesGroup,l=b.inverted;c=a.plotGroup("group","series",k,h,m);a.markerGroup=a.plotGroup("markerGroup","markers",k,h,m);e&&a.animate(!0);c.inverted=a.isCartesian?l:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(l);!1===d.clip||a.sharedClipKey||f||c.clip(b.clipRect);e&&a.animate();f||(a.animationTimeout=C(function(){a.afterAnimate()}, -e));a.isDirty=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirty||this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:I(d&&d.left,a.plotLeft),translateY:I(e&&e.top,a.plotTop)}));this.translate();this.render();b&&delete this.kdTree},kdAxisArray:["clientX","plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,e=this.chart.inverted;return this.searchKDTree({clientX:e?c.len-a.chartY+ -c.pos:a.chartX-c.pos,plotY:e?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(c,d,e){var g,k;if(k=c&&c.length)return g=b.kdAxisArray[d%e],c.sort(function(a,b){return a[g]-b[g]}),k=Math.floor(k/2),{point:c[k],left:a(c.slice(0,k),d+1,e),right:a(c.slice(k+1),d+1,e)}}this.buildingKdTree=!0;var b=this,c=-1l?"left":"right";t=0>l?"right":"left";b[q]&&(q=c(a,b[q],g+1,f),n=q[h]x;)q--;this.updateParallelArrays(m,"splice",q,0,0);this.updateParallelArrays(m,q);g&&m.name&&(g[x]=m.name);l.splice(q,0,a);n&&(this.data.splice(q,0,null),this.processData());"point"===e.legendType&&this.generatePoints();c&&(h[0]&&h[0].remove?h[0].remove(!1):(h.shift(),this.updateParallelArrays(m,"shift"),l.shift()));this.isDirtyData=this.isDirty=!0;b&&f.redraw(d)},removePoint:function(a,b,c){var d=this,e=d.data,h=e[a],f=d.points,g=d.chart,l=function(){f&&f.length===e.length&& -f.splice(a,1);e.splice(a,1);d.options.data.splice(a,1);d.updateParallelArrays(h||{series:d},"splice",a,1);h&&h.destroy();d.isDirty=!0;d.isDirtyData=!0;b&&g.redraw()};x(c,g);b=k(b,!0);h?h.firePointEvent("remove",null,l):l()},remove:function(a,b,c){function d(){e.destroy();h.isDirtyLegend=h.isDirtyBox=!0;h.linkSeries();k(a,!0)&&h.redraw(b)}var e=this,h=e.chart;!1!==c?u(e,"remove",null,d):d()},update:function(a,b){var d=this,e=d.chart,h=d.userOptions,f=d.oldType||d.type,l=a.type||h.type||e.options.chart.type, -g=I[f].prototype,m,n=["group","markerGroup","dataLabelsGroup"],t=["navigatorSeries","baseSeries"],x=d.finishedAnimating&&{animation:!1};if(Object.keys&&"data"===Object.keys(a).toString())return this.setData(a.data,b);t=n.concat(t);r(t,function(a){t[a]=d[a];delete d[a]});a=c(h,x,{index:d.index,pointStart:d.xData[0]},{data:d.options.data},a);d.remove(!1,null,!1);for(m in g)d[m]=void 0;w(d,I[l||f].prototype);r(t,function(a){d[a]=t[a]});d.init(e,a);a.zIndex!==h.zIndex&&r(n,function(b){d[b]&&d[b].attr({zIndex:a.zIndex})}); -d.oldType=f;e.linkSeries();k(b,!0)&&e.redraw(!1)}});w(H.prototype,{update:function(a,b){var d=this.chart;a=d.options[this.coll][this.options.index]=c(this.userOptions,a);this.destroy(!0);this.init(d,w(a,{events:void 0}));d.isDirtyBox=!0;k(b,!0)&&d.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,e=this.series,h=e.length;h--;)e[h]&&e[h].remove(!1);n(b.axes,this);n(b[c],this);d(b.options[c])?b.options[c].splice(this.options.index,1):delete b.options[c];r(b[c],function(a,b){a.options.index= -b});this.destroy();b.isDirtyBox=!0;k(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}})})(M);(function(a){var E=a.color,D=a.each,H=a.map,p=a.pick,f=a.Series,l=a.seriesType;l("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(f){var l=[],r=[],u=this.xAxis,e=this.yAxis,h=e.stacks[this.stackKey],m={},d=this.index,c=e.series,b=c.length,k,z=p(e.options.reversedStacks,!0)?1:-1,B;f=f||this.points; -if(this.options.stacking){for(B=0;Ba&&w>l?(w=Math.max(a,l),e=2*l-w):wp&&e>l?(e=Math.max(p,l),w=2*l-e):e=Math.abs(h)&&.5a.closestPointRange*a.xAxis.transA,d=a.borderWidth=r(f.borderWidth,d?0:1),c=a.yAxis,b=f.threshold,k=a.translatedThreshold=c.getThreshold(b),l=r(f.minPointLength,5),p=a.getColumnMetrics(),u=p.width,x=a.barW=Math.max(u,1+2*d),w=a.pointXOffset=p.offset;h.inverted&&(k-=.5);f.pointPadding&&(x=Math.ceil(x));n.prototype.translate.apply(a);H(a.points,function(d){var e=r(d.yBottom,k),f=999+Math.abs(e),f=Math.min(Math.max(-f,d.plotY),c.len+f),m=d.plotX+w,n=x,t=Math.min(f,e),p,g=Math.max(f,e)-t;l&& -Math.abs(g)l?e-l:k-(p?l:0));d.barX=m;d.pointWidth=u;d.tooltipPos=h.inverted?[c.len+c.pos-h.plotLeft-f,a.xAxis.len-m-n/2,g]:[m+n/2,f+c.pos-h.plotTop,g];d.shapeType="rect";d.shapeArgs=a.crispCol.apply(a,d.isNull?[m,k,n,0]:[m,t,n,g])})},getSymbol:a.noop,drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")}, -pointAttribs:function(a,f){var e=this.options,d,c=this.pointAttrToOptions||{};d=c.stroke||"borderColor";var b=c["stroke-width"]||"borderWidth",k=a&&a.color||this.color,h=a&&a[d]||e[d]||this.color||k,n=a&&a[b]||e[b]||this[b]||0,c=e.dashStyle;a&&this.zones.length&&(k=a.getZone(),k=a.options.color||k&&k.color||this.color);f&&(a=l(e.states[f],a.options.states&&a.options.states[f]||{}),f=a.brightness,k=a.color||void 0!==f&&D(k).brighten(a.brightness).get()||k,h=a[d]||h,n=a[b]||n,c=a.dashStyle||c);d={fill:k, -stroke:h,"stroke-width":n};c&&(d.dashstyle=c);return d},drawPoints:function(){var a=this,h=this.chart,m=a.options,d=h.renderer,c=m.animationLimit||250,b;H(a.points,function(e){var k=e.graphic;if(f(e.plotY)&&null!==e.y){b=e.shapeArgs;if(k)k[h.pointCounte;++e)h=w[e],a=2>e||2===e&&/%$/.test(h),w[e]=p(h,[n,l,u,w[2]][e])+(a?r:0);w[3]>w[2]&&(w[3]=w[2]);return w},getStartAndEndRadians:function(a,l){a=D(a)?a:0;l=D(l)&&l>a&&360>l-a?l:a+360;return{start:E*(a+-90),end:E*(l+-90)}}}})(M);(function(a){var E=a.addEvent,D=a.CenteredSeriesMixin,H=a.defined,p=a.each,f=a.extend,l=D.getStartAndEndRadians,r=a.inArray,n=a.noop,w=a.pick,u=a.Point,e=a.Series,h=a.seriesType,m=a.setAnimation;h("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30, -enabled:!0,formatter:function(){return this.point.isNull?void 0:this.point.name},x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff",borderWidth:1,states:{hover:{brightness:.1,shadow:!1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:a.seriesTypes.column.prototype.pointAttribs,animate:function(a){var c= -this,b=c.points,d=c.startAngleRad;a||(p(b,function(a){var b=a.graphic,e=a.shapeArgs;b&&(b.attr({r:a.startR||c.center[3]/2,start:d,end:d}),b.animate({r:e.r,start:e.start,end:e.end},c.options.animation))}),c.animate=null)},updateTotals:function(){var a,c=0,b=this.points,e=b.length,f,h=this.options.ignoreHiddenPoint;for(a=0;a1.5*Math.PI?m-=2*Math.PI:m<-Math.PI/2&&(m+=2*Math.PI);G.slicedTranslation={translateX:Math.round(Math.cos(m)*d),translateY:Math.round(Math.sin(m)*d)};h=Math.cos(m)*a[2]/ -2;u=Math.sin(m)*a[2]/2;G.tooltipPos=[a[0]+.7*h,a[1]+.7*u];G.half=m<-Math.PI/2||m>Math.PI/2?1:0;G.angle=m;f=Math.min(e,G.labelDistance/5);G.labelPos=[a[0]+h+Math.cos(m)*G.labelDistance,a[1]+u+Math.sin(m)*G.labelDistance,a[0]+h+Math.cos(m)*f,a[1]+u+Math.sin(m)*f,a[0]+h,a[1]+u,0>G.labelDistance?"center":G.half?"right":"left",m]}},drawGraph:null,drawPoints:function(){var a=this,c=a.chart.renderer,b,e,h,l,m=a.options.shadow;m&&!a.shadowGroup&&(a.shadowGroup=c.g("shadow").add(a.group));p(a.points,function(d){e= -d.graphic;if(d.isNull)e&&(d.graphic=e.destroy());else{l=d.shapeArgs;b=d.getTranslate();var k=d.shadowGroup;m&&!k&&(k=d.shadowGroup=c.g("shadow").add(a.shadowGroup));k&&k.attr(b);h=a.pointAttribs(d,d.selected&&"select");e?e.setRadialReference(a.center).attr(h).animate(f(l,b)):(d.graphic=e=c[d.shapeType](l).setRadialReference(a.center).attr(b).add(a.group),d.visible||e.attr({visibility:"hidden"}),e.attr(h).attr({"stroke-linejoin":"round"}).shadow(m,k));e.addClass(d.getClassName())}})},searchPoint:n, -sortByAngle:function(a,c){a.sort(function(a,d){return void 0!==a.angle&&(d.angle-a.angle)*c})},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,getCenter:D.getCenter,getSymbol:n},{init:function(){u.prototype.init.apply(this,arguments);var a=this,c;a.name=w(a.name,"Slice");c=function(b){a.slice("select"===b.type)};E(a,"select",c);E(a,"unselect",c);return a},isValid:function(){return a.isNumber(this.y,!0)&&0<=this.y},setVisible:function(a,c){var b=this,d=b.series,e=d.chart,f=d.options.ignoreHiddenPoint; -c=w(c,f);a!==b.visible&&(b.visible=b.options.visible=a=void 0===a?!b.visible:a,d.options.data[r(b,d.data)]=b.options,p(["graphic","dataLabel","connector","shadowGroup"],function(c){if(b[c])b[c][a?"show":"hide"](!0)}),b.legendItem&&e.legend.colorizeItem(b,a),a||"hover"!==b.state||b.setState(""),f&&(d.isDirty=!0),c&&e.redraw())},slice:function(a,c,b){var d=this.series;m(b,d.chart);w(c,!0);this.sliced=this.options.sliced=H(a)?a:!this.sliced;d.options.data[r(this,d.data)]=this.options;this.graphic.animate(this.getTranslate()); -this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())},getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(a){var c=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.x,c.y,c.r+a,c.r+a,{innerR:this.shapeArgs.r-1,start:c.start,end:c.end})}})})(M);(function(a){var E=a.addEvent,D=a.arrayMax,H=a.defined,p=a.each,f=a.extend,l=a.format,r=a.map,n=a.merge,w=a.noop,u=a.pick,e=a.relativeLength,h= -a.Series,m=a.seriesTypes,d=a.stableSort;a.distribute=function(a,b){function c(a,b){return a.target-b.target}var e,f=!0,h=a,l=[],m;m=0;for(e=a.length;e--;)m+=a[e].size;if(m>b){d(a,function(a,b){return(b.rank||0)-(a.rank||0)});for(m=e=0;m<=b;)m+=a[e].size,e++;l=a.splice(e-1,a.length)}d(a,c);for(a=r(a,function(a){return{size:a.size,targets:[a.target],align:u(a.align,.5)}});f;){for(e=a.length;e--;)f=a[e],m=(Math.min.apply(0,f.targets)+Math.max.apply(0,f.targets))/2,f.pos=Math.min(Math.max(0,m-f.size* -f.align),b-f.size);e=a.length;for(f=!1;e--;)0a[e].pos&&(a[e-1].size+=a[e].size,a[e-1].targets=a[e-1].targets.concat(a[e].targets),a[e-1].align=.5,a[e-1].pos+a[e-1].size>b&&(a[e-1].pos=b-a[e-1].size),a.splice(e,1),f=!0)}e=0;p(a,function(a){var b=0;p(a.targets,function(){h[e].pos=a.pos+b;b+=h[e].size;e++})});h.push.apply(h,l);d(h,c)};h.prototype.drawDataLabels=function(){function c(a,b){var c=b.filter;return c?(b=c.operator,a=a[c.property],c=c.value,"\x3e"===b&&a>c||"\x3c"=== -b&&a=c||"\x3c\x3d"===b&&a<=c||"\x3d\x3d"===b&&a==c||"\x3d\x3d\x3d"===b&&a===c?!0:!1):!0}var b=this,d=b.options,e=d.dataLabels,f=b.points,h,m,r=b.hasRendered||0,t,w,D=u(e.defer,!!d.animation),q=b.chart.renderer;if(e.enabled||b._hasPointLabels)b.dlProcessOptions&&b.dlProcessOptions(e),w=b.plotGroup("dataLabelsGroup","data-labels",D&&!r?"hidden":"visible",e.zIndex||6),D&&(w.attr({opacity:+r}),r||E(b,"afterAnimate",function(){b.visible&&w.show(!0);w[d.animation?"animate":"attr"]({opacity:1}, -{duration:200})})),m=e,p(f,function(f){var k,p=f.dataLabel,g,x,r=f.connector,z=!p,C;h=f.dlOptions||f.options&&f.options.dataLabels;(k=u(h&&h.enabled,m.enabled)&&!f.isNull)&&(k=!0===c(f,h||e));k&&(e=n(m,h),g=f.getLabelConfig(),C=e[f.formatPrefix+"Format"]||e.format,t=H(C)?l(C,g):(e[f.formatPrefix+"Formatter"]||e.formatter).call(g,e),C=e.style,g=e.rotation,C.color=u(e.color,C.color,b.color,"#000000"),"contrast"===C.color&&(f.contrastColor=q.getContrast(f.color||b.color),C.color=e.inside||0>u(f.labelDistance, -e.distance)||d.stacking?f.contrastColor:"#000000"),d.cursor&&(C.cursor=d.cursor),x={fill:e.backgroundColor,stroke:e.borderColor,"stroke-width":e.borderWidth,r:e.borderRadius||0,rotation:g,padding:e.padding,zIndex:1},a.objectEach(x,function(a,b){void 0===a&&delete x[b]}));!p||k&&H(t)?k&&H(t)&&(p?x.text=t:(p=f.dataLabel=g?q.text(t,0,-9999).addClass("highcharts-data-label"):q.label(t,0,-9999,e.shape,null,null,e.useHTML,null,"data-label"),p.addClass(" highcharts-data-label-color-"+f.colorIndex+" "+(e.className|| -"")+(e.useHTML?"highcharts-tracker":""))),p.attr(x),p.css(C).shadow(e.shadow),p.added||p.add(w),b.alignDataLabel(f,p,e,null,z)):(f.dataLabel=p=p.destroy(),r&&(f.connector=r.destroy()))})};h.prototype.alignDataLabel=function(a,b,d,e,h){var c=this.chart,k=c.inverted,l=u(a.dlBox&&a.dlBox.centerX,a.plotX,-9999),m=u(a.plotY,-9999),n=b.getBBox(),p,q=d.rotation,r=d.align,w=this.visible&&(a.series.forceDL||c.isInsidePlot(l,Math.round(m),k)||e&&c.isInsidePlot(l,k?e.x+1:e.y+e.height-1,k)),z="justify"===u(d.overflow, -"justify");if(w&&(p=d.style.fontSize,p=c.renderer.fontMetrics(p,b).b,e=f({x:k?this.yAxis.len-m:l,y:Math.round(k?this.xAxis.len-l:m),width:0,height:0},e),f(d,{width:n.width,height:n.height}),q?(z=!1,l=c.renderer.rotCorr(p,q),l={x:e.x+d.x+e.width/2+l.x,y:e.y+d.y+{top:0,middle:.5,bottom:1}[d.verticalAlign]*e.height},b[h?"attr":"animate"](l).attr({align:r}),m=(q+720)%360,m=180m,"left"===r?l.y-=m?n.height:0:"center"===r?(l.x-=n.width/2,l.y-=n.height/2):"right"===r&&(l.x-=n.width,l.y-=m?0:n.height)): -(b.align(d,null,e),l=b.alignAttr),z?a.isLabelJustified=this.justifyDataLabel(b,d,l,n,e,h):u(d.crop,!0)&&(w=c.isInsidePlot(l.x,l.y)&&c.isInsidePlot(l.x+n.width,l.y+n.height)),d.shape&&!q))b[h?"attr":"animate"]({anchorX:k?c.plotWidth-a.plotY:a.plotX,anchorY:k?c.plotHeight-a.plotX:a.plotY});w||(b.attr({y:-9999}),b.placed=!1)};h.prototype.justifyDataLabel=function(a,b,d,e,f,h){var c=this.chart,k=b.align,l=b.verticalAlign,m,n,p=a.box?0:a.padding||0;m=d.x+p;0>m&&("right"===k?b.align="left":b.x=-m,n=!0); -m=d.x+e.width-p;m>c.plotWidth&&("left"===k?b.align="right":b.x=c.plotWidth-m,n=!0);m=d.y+p;0>m&&("bottom"===l?b.verticalAlign="top":b.y=-m,n=!0);m=d.y+e.height-p;m>c.plotHeight&&("top"===l?b.verticalAlign="bottom":b.y=c.plotHeight-m,n=!0);n&&(a.placed=!h,a.align(b,null,f));return n};m.pie&&(m.pie.prototype.drawDataLabels=function(){var c=this,b=c.data,d,e=c.chart,f=c.options.dataLabels,l=u(f.connectorPadding,10),m=u(f.connectorWidth,1),n=e.plotWidth,t=e.plotHeight,r,w=c.center,q=w[2]/2,A=w[1],F,G, -g,v,E=[[],[]],L,P,J,M,y=[0,0,0,0];c.visible&&(f.enabled||c._hasPointLabels)&&(p(b,function(a){a.dataLabel&&a.visible&&a.dataLabel.shortened&&(a.dataLabel.attr({width:"auto"}).css({width:"auto",textOverflow:"clip"}),a.dataLabel.shortened=!1)}),h.prototype.drawDataLabels.apply(c),p(b,function(a){a.dataLabel&&a.visible&&(E[a.half].push(a),a.dataLabel._pos=null)}),p(E,function(b,h){var k,m,x=b.length,r=[],z;if(x)for(c.sortByAngle(b,h-.5),0d.bottom-2?k:P,h,d),F._attr={visibility:J,align:g[6]},F._pos={x:L+f.x+({left:l,right:-l}[g[6]]||0),y:P+f.y-10},g.x=L,g.y=P,u(f.crop,!0)&&(G=F.getBBox().width,k=null,L-Gn-l&&(k=Math.round(L+G-n+l),y[1]=Math.max(k,y[1])),0>P-v/2?y[0]=Math.max(Math.round(-P+v/2),y[0]):P+v/2>t&&(y[2]=Math.max(Math.round(P+v/2-t),y[2])),F.sideOverflow=k)}),0===D(y)||this.verifyDataLabelOverflow(y))&&(this.placeDataLabels(), -m&&p(this.points,function(a){var b;r=a.connector;if((F=a.dataLabel)&&F._pos&&a.visible&&0u(this.translatedThreshold,k.yAxis.len)),p=u(d.inside,!!this.options.stacking);l&&(e=n(l),0>e.y&&(e.height+=e.y,e.y=0),l=e.y+e.height-k.yAxis.len,0a+c||e+hb+d||f+lthis.pointCount))},pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&r(d,function(a){a.setState()});r("xy"===b?[1,0]:[1],function(b){b= -c[b?"xAxis":"yAxis"][0];var d=b.horiz,f=a[d?"chartX":"chartY"],d=d?"mouseDownX":"mouseDownY",h=c[d],g=(b.pointRange||0)/2,k=b.getExtremes(),l=b.toValue(h-f,!0)+g,m=b.toValue(h+b.len-f,!0)-g,n=m=l(n.minWidth,0)&&this.chartHeight>=l(n.minHeight,0)}).call(this)&&f.push(a._id)};E.prototype.currentOptions=function(l){function n(e,h,l,d){var c;a.objectEach(e,function(a,e){if(!d&&-1 Date: Mon, 8 Jan 2018 18:12:57 +1300 Subject: [PATCH 071/267] Add a green border around predictions boxes --- app/assets/stylesheets/predictions.sass | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/stylesheets/predictions.sass b/app/assets/stylesheets/predictions.sass index b9496ebc5..00be9af21 100644 --- a/app/assets/stylesheets/predictions.sass +++ b/app/assets/stylesheets/predictions.sass @@ -1,7 +1,7 @@ .predictions .metric height: 180px - border: #000000 2px + border: 1px solid lighten($green, 20%) background: $white margin: 4px strong From 29a9643f00516b15e4e6d59c3e3575bc95a54e84 Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Mon, 8 Jan 2018 23:46:00 +0000 Subject: [PATCH 072/267] trigger awesomecode.io notification From a5fa033f2db1de52c55c6c99c15246f6b08b34f7 Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Mon, 8 Jan 2018 23:46:57 +0000 Subject: [PATCH 073/267] Auto corrected by following EmptyLine --- script/check_contributors_md.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/script/check_contributors_md.rb b/script/check_contributors_md.rb index 3fca50489..4792abbb5 100755 --- a/script/check_contributors_md.rb +++ b/script/check_contributors_md.rb @@ -22,7 +22,6 @@ else abort %( Couldn't determine your GitHub username, and not in a Travis PR build Please set it using - git config --add github.user [username] ) end From 74ff648f90c29cc11a719a459d883a8d3cbc78c6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 9 Jan 2018 12:51:21 +1300 Subject: [PATCH 074/267] Moved chart includes to application.js, attempting to fix json parse error --- app/assets/javascripts/application.js | 2 ++ app/assets/javascripts/charts.js | 2 -- app/views/crops/show.html.haml | 3 --- app/views/layouts/application.html.haml | 4 +--- config/initializers/assets.rb | 1 - 5 files changed, 3 insertions(+), 9 deletions(-) delete mode 100644 app/assets/javascripts/charts.js diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index fc3369264..e0d7b8463 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -10,6 +10,8 @@ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD // GO AFTER THE REQUIRES BELOW. // +// = require Chart.bundle +// = require chartkick // = require leaflet // = require leaflet.markercluster // = require js-routes diff --git a/app/assets/javascripts/charts.js b/app/assets/javascripts/charts.js deleted file mode 100644 index 1c42da456..000000000 --- a/app/assets/javascripts/charts.js +++ /dev/null @@ -1,2 +0,0 @@ -// = require Chart.bundle -// = require chartkick diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index cf401681e..e5e7e7a1a 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -8,9 +8,6 @@ = tag("meta", property: "og:url", content: request.original_url) = tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME']) -- content_for :scripts do - = javascript_include_tag "charts" - = render partial: 'approval_status_message', locals: { crop: @crop } - if @crop.approved? diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 40f83db5b..b90c025e7 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,6 +1,6 @@ !!! 5 %html{ lang: "en", prefix: "og: http://ogp.me/ns#" } - = yield :scripts + = javascript_include_tag "application" = render partial: "layouts/meta" %body = render partial: "layouts/header" @@ -27,6 +27,4 @@ Javascripts \================================================== / Placed at the end of the document so the pages load faster - = javascript_include_tag "application" - != Growstuff::Application.config.analytics_code diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 60484d4a4..4b828e80c 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -12,4 +12,3 @@ Rails.application.config.assets.paths << Rails.root.join('node_modules') # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. # Rails.application.config.assets.precompile += %w( admin.js admin.css ) -Rails.application.config.assets.precompile += %w(charts.js) From 2c3fe3c2046bc386efb0bddd378eebedf8aba4f2 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 9 Jan 2018 13:18:58 +1300 Subject: [PATCH 075/267] updated prediction spec --- spec/features/crops/crop_detail_page_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 05ebdb6e7..29d73a47a 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -215,7 +215,7 @@ feature "crop detail page", js: true do end it "predicts lifespan" do - is_expected.to have_text "Median lifespan of #{crop.name} plants is 99 days" + is_expected.to have_text "Median lifespan 99 days" end it "describes annual crops" do From c5c6f7ad47775b875662a9cdb7b78298001b5db3 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 9 Jan 2018 14:31:03 +1300 Subject: [PATCH 076/267] Removed ignore of highcharts --- .overcommit.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.overcommit.yml b/.overcommit.yml index 200a90e42..d7899885f 100644 --- a/.overcommit.yml +++ b/.overcommit.yml @@ -61,7 +61,6 @@ PreCommit: enabled: true exclude: - 'app/assets/**' - - 'app/assets/javascripts/highcharts.js' - 'spec/javascripts/support/vendor/**' - '**/bootstrap*' command: ['./node_modules/.bin/eslint'] From a2e4863f006056530b5eb5b6ac03f38d76e660ac Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 9 Jan 2018 14:37:21 +1300 Subject: [PATCH 077/267] Fixing up prediction specs --- spec/features/crops/crop_detail_page_spec.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 29d73a47a..e21c5eb47 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -181,6 +181,7 @@ feature "crop detail page", js: true do # 10 days to harvest FactoryBot.create(:harvest, harvested_at: 190.days.ago, crop: planting.crop, planting: FactoryBot.create(:planting, planted_at: 200.days.ago, crop: crop)) + planting.crop.update_medians end it "predicts harvest" do is_expected.to have_text("First harvest expected 20 days after planting") @@ -215,7 +216,8 @@ feature "crop detail page", js: true do end it "predicts lifespan" do - is_expected.to have_text "Median lifespan 99 days" + is_expected.to have_text "Median lifespan" + is_expected.to have_text "99 days" end it "describes annual crops" do From 3ece5843909373c39317fd16f6a44213e699ce79 Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Tue, 9 Jan 2018 01:59:43 +0000 Subject: [PATCH 078/267] Auto corrected by following FactoryBot/DynamicAttributeDefinedStatically --- spec/factories/harvests.rb | 2 +- spec/factories/member.rb | 2 +- spec/factories/planting.rb | 6 +++--- spec/factories/post.rb | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/factories/harvests.rb b/spec/factories/harvests.rb index c707a2e2c..ae3144a1e 100644 --- a/spec/factories/harvests.rb +++ b/spec/factories/harvests.rb @@ -6,7 +6,7 @@ FactoryBot.define do plant_part planting nil owner { planting.present? ? planting.owner : FactoryBot.create(:member) } - harvested_at Time.zone.local(2015, 9, 17) + harvested_at { Time.zone.local(2015, 9, 17) } quantity "3" unit "individual" weight_quantity 6 diff --git a/spec/factories/member.rb b/spec/factories/member.rb index 619e7d4f2..016b12263 100644 --- a/spec/factories/member.rb +++ b/spec/factories/member.rb @@ -7,7 +7,7 @@ FactoryBot.define do password 'password1' email { generate(:email) } tos_agreement true - confirmed_at Time.now + confirmed_at { Time.now } show_email false bio 'I love seeds' diff --git a/spec/factories/planting.rb b/spec/factories/planting.rb index 2bcfac397..5b7311025 100644 --- a/spec/factories/planting.rb +++ b/spec/factories/planting.rb @@ -3,7 +3,7 @@ FactoryBot.define do owner garden { FactoryBot.create :garden, owner: owner } crop - planted_at Time.zone.local(2014, 7, 30) + planted_at { Time.zone.local(2014, 7, 30) } quantity 33 description "This is a *really* good plant." @@ -33,8 +33,8 @@ FactoryBot.define do factory :finished_planting do finished true - planted_at Time.zone.local(2014, 7, 30) - finished_at Time.zone.local(2014, 8, 30) + planted_at { Time.zone.local(2014, 7, 30) } + finished_at { Time.zone.local(2014, 8, 30) } end end end diff --git a/spec/factories/post.rb b/spec/factories/post.rb index d53f33100..da6390ef8 100644 --- a/spec/factories/post.rb +++ b/spec/factories/post.rb @@ -3,7 +3,7 @@ FactoryBot.define do subject "A Post" body "This is some text." author - created_at Time.now + created_at { Time.now } # Markdown is allowed in posts factory :markdown_post do From e46f530dc3d6e6ad0e1884e767e9cbed15b5dbc4 Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Tue, 9 Jan 2018 02:00:40 +0000 Subject: [PATCH 079/267] Auto corrected by following RSpec/EmptyLineAfterFinalLet --- spec/controllers/account_types_controller_spec.rb | 1 + spec/controllers/comments_controller_spec.rb | 11 +++++++++++ spec/controllers/gardens_controller_spec.rb | 2 ++ spec/controllers/harvests_controller_spec.rb | 4 ++++ spec/controllers/likes_controller_spec.rb | 1 + .../controllers/photo_associations_controller_spec.rb | 1 + spec/controllers/photos_controller_spec.rb | 3 +++ spec/controllers/plantings_controller_spec.rb | 5 +++++ spec/controllers/shop_controller_spec.rb | 1 + spec/features/crops/crop_detail_page_spec.rb | 4 ++++ spec/features/crops/requested_crops_spec.rb | 1 + spec/features/gardens_spec.rb | 1 + spec/features/members/deletion_spec.rb | 1 + spec/features/plantings/planting_a_crop_spec.rb | 1 + spec/features/seeds/seed_photos.rb | 2 ++ spec/features/signout_spec.rb | 1 + spec/models/crop_spec.rb | 8 ++++++++ spec/models/member_spec.rb | 4 ++++ spec/models/photo_spec.rb | 1 + spec/models/planting_spec.rb | 11 +++++++++++ spec/models/post_spec.rb | 1 + spec/models/role_spec.rb | 2 ++ spec/models/seed_spec.rb | 1 + spec/views/crops/_planting_advice.html.haml_spec.rb | 1 + spec/views/home/_crops.html.haml_spec.rb | 1 + spec/views/members/index.html.haml_spec.rb | 1 + spec/views/plantings/index.html.haml_spec.rb | 1 + spec/views/plantings/show.html.haml_spec.rb | 1 + spec/views/posts/show.html.haml_spec.rb | 9 +++++++++ 29 files changed, 82 insertions(+) diff --git a/spec/controllers/account_types_controller_spec.rb b/spec/controllers/account_types_controller_spec.rb index 37dbfa706..010c8bf1f 100644 --- a/spec/controllers/account_types_controller_spec.rb +++ b/spec/controllers/account_types_controller_spec.rb @@ -21,6 +21,7 @@ describe AccountTypesController do describe '#index' do let!(:aaa) { FactoryBot.create :account_type, name: 'aaa' } let!(:zzz) { FactoryBot.create :account_type, name: 'zzz' } + before { get :index } it { is_expected.to be_success } it { expect(assigns[:account_types].first).to eql(aaa) } diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb index 0e986cc93..2d265de5f 100644 --- a/spec/controllers/comments_controller_spec.rb +++ b/spec/controllers/comments_controller_spec.rb @@ -3,6 +3,7 @@ require 'rails_helper' describe CommentsController do subject { response } let(:member) { FactoryBot.create(:member) } + before(:each) do sign_in member controller.stub(:current_member) { member } @@ -16,6 +17,7 @@ describe CommentsController do describe "GET RSS feed" do let!(:first_comment) { FactoryBot.create :comment, created_at: 10.days.ago } let!(:last_comment) { FactoryBot.create :comment, created_at: 4.minutes.ago } + describe "returns an RSS feed" do before { get :index, format: "rss" } it { is_expected.to be_success } @@ -36,6 +38,7 @@ describe CommentsController do end let(:old_comment) { FactoryBot.create(:comment, post: post) } + it "assigns the old comments as @comments" do assigns(:comments).should eq [old_comment] end @@ -49,11 +52,13 @@ describe CommentsController do describe "GET edit" do let(:post) { FactoryBot.create(:post) } + before { get :edit, id: comment.to_param } describe "my comment" do let!(:comment) { FactoryBot.create :comment, author: member, post: post } let!(:old_comment) { FactoryBot.create(:comment, post: post, created_at: Time.zone.yesterday) } + it "assigns previous comments as @comments" do expect(assigns(:comments)).to eq([comment, old_comment]) end @@ -61,6 +66,7 @@ describe CommentsController do describe "not my comment" do let(:comment) { FactoryBot.create :comment, post: post } + it { expect(response).not_to be_success } end end @@ -70,12 +76,14 @@ describe CommentsController do describe "my comment" do let(:comment) { FactoryBot.create :comment, author: member } + it "redirects to the comment's post" do expect(response).to redirect_to(comment.post) end end describe "not my comment" do let(:comment) { FactoryBot.create :comment } + it { expect(response).not_to be_success } end describe "attempting to change post_id" do @@ -83,6 +91,7 @@ describe CommentsController do let(:other_post) { FactoryBot.create :post, subject: 'the other post' } let(:valid_attributes) { { post_id: other_post.id, body: "kōrero" } } let(:comment) { FactoryBot.create :comment, author: member, post: post } + it "does not change post_id" do comment.reload expect(comment.post_id).to eq(post.id) @@ -95,6 +104,7 @@ describe CommentsController do describe "my comment" do let(:comment) { FactoryBot.create :comment, author: member } + it "redirects to the post the comment was on" do expect(response).to redirect_to(comment.post) end @@ -102,6 +112,7 @@ describe CommentsController do describe "not my comment" do let(:comment) { FactoryBot.create :comment } + it { expect(response).not_to be_success } end end diff --git a/spec/controllers/gardens_controller_spec.rb b/spec/controllers/gardens_controller_spec.rb index b0ccae0b8..9253b5ddb 100644 --- a/spec/controllers/gardens_controller_spec.rb +++ b/spec/controllers/gardens_controller_spec.rb @@ -6,6 +6,7 @@ RSpec.describe GardensController, type: :controller do context "when not signed in" do let(:garden) { double('garden') } + describe 'GET new' do before { get :new, id: garden.to_param } it { expect(response).to redirect_to(new_member_session_path) } @@ -45,6 +46,7 @@ RSpec.describe GardensController, type: :controller do describe "for another member's garden" do let(:not_my_garden) { double('garden') } + before do expect(Garden).to receive(:find).and_return(:not_my_garden) expect(not_my_garden).not_to receive(:save) diff --git a/spec/controllers/harvests_controller_spec.rb b/spec/controllers/harvests_controller_spec.rb index 8a2edb56b..705f954b5 100644 --- a/spec/controllers/harvests_controller_spec.rb +++ b/spec/controllers/harvests_controller_spec.rb @@ -45,6 +45,7 @@ describe HarvestsController do describe "GET show" do let(:harvest) { Harvest.create! valid_attributes } + describe "assigns the requested harvest as @harvest" do before { get :show, id: harvest.to_param } it { expect(assigns(:harvest)).to eq(harvest) } @@ -65,6 +66,7 @@ describe HarvestsController do describe "GET edit" do let(:harvest) { Harvest.create! valid_attributes } + describe "assigns the requested harvest as @harvest" do before { get :edit, id: harvest.to_param } it { expect(assigns(:harvest)).to eq(harvest) } @@ -92,6 +94,7 @@ describe HarvestsController do describe "links to planting" do let(:planting) { FactoryBot.create(:planting, owner_id: member.id, garden: member.gardens.first) } + before { post :create, harvest: valid_attributes.merge(planting_id: planting.id) } it { expect(Harvest.last.planting.id).to eq(planting.id) } end @@ -170,6 +173,7 @@ describe HarvestsController do describe "not my planting" do let(:not_my_planting) { FactoryBot.create(:planting) } let(:harvest) { FactoryBot.create(:harvest) } + describe "does not save planting_id" do before do put :update, id: harvest.to_param, diff --git a/spec/controllers/likes_controller_spec.rb b/spec/controllers/likes_controller_spec.rb index 6f43760c1..a80fc0d56 100644 --- a/spec/controllers/likes_controller_spec.rb +++ b/spec/controllers/likes_controller_spec.rb @@ -35,6 +35,7 @@ describe LikesController do describe "Deleting someone else's like" do let(:like) { FactoryBot.create :like } + it { expect(response.code).to eq('403') } it { JSON.parse(response.body)["error"] == "Unable to like" } end diff --git a/spec/controllers/photo_associations_controller_spec.rb b/spec/controllers/photo_associations_controller_spec.rb index 42e0ccc37..75a04eedd 100644 --- a/spec/controllers/photo_associations_controller_spec.rb +++ b/spec/controllers/photo_associations_controller_spec.rb @@ -26,6 +26,7 @@ describe PhotoAssociationsController do describe "another member's harvest from another member's photo" do let(:harvest) { FactoryBot.create :harvest } let(:photo) { FactoryBot.create :photo } + it do expect do begin diff --git a/spec/controllers/photos_controller_spec.rb b/spec/controllers/photos_controller_spec.rb index 3c4f9dacb..76869ebf3 100644 --- a/spec/controllers/photos_controller_spec.rb +++ b/spec/controllers/photos_controller_spec.rb @@ -73,6 +73,7 @@ describe PhotosController do let(:planting) { FactoryBot.create(:planting, garden: garden, owner: member) } let(:harvest) { FactoryBot.create(:harvest, owner: member) } let(:photo) { FactoryBot.create(:photo, owner: member) } + describe "with valid params" do before { controller.stub(:current_member) { member } } it "attaches the photo to a planting" do @@ -113,6 +114,7 @@ describe PhotosController do describe "for the second time" do let(:planting) { FactoryBot.create :planting, owner: member } + it "does not add a photo twice" do expect do post :create, photo: { flickr_photo_id: 1 }, id: planting.id, type: 'planting' @@ -142,6 +144,7 @@ describe PhotosController do describe "with mismatched owners" do let(:photo) { FactoryBot.create(:photo) } + it "does not create the planting/photo link" do # members will be auto-created, and different another_planting = FactoryBot.create(:planting) diff --git a/spec/controllers/plantings_controller_spec.rb b/spec/controllers/plantings_controller_spec.rb index dd1340d44..abe5ea626 100644 --- a/spec/controllers/plantings_controller_spec.rb +++ b/spec/controllers/plantings_controller_spec.rb @@ -39,6 +39,7 @@ describe PlantingsController do describe "GET new" do describe "picks up crop from params" do let(:crop) { FactoryBot.create(:crop) } + before { get :new, crop_id: crop.id } it { expect(assigns(:crop)).to eq(crop) } end @@ -50,6 +51,7 @@ describe PlantingsController do describe "picks up member's garden from params" do let(:garden) { FactoryBot.create(:garden, owner: member) } + before { get :new, garden_id: garden.id } it { expect(assigns(:garden)).to eq(garden) } end @@ -57,6 +59,7 @@ describe PlantingsController do describe "Doesn't display another member's garden on planting form" do let(:another_member) { FactoryBot.create(:member) } # over-riding member from login_member() let(:garden) { FactoryBot.create(:garden, owner: another_member) } + before { get :new, garden_id: garden.id } it { expect(assigns(:garden)).not_to eq(garden) } end @@ -64,6 +67,7 @@ describe PlantingsController do describe "Doesn't display un-approved crops on planting form" do let(:crop) { FactoryBot.create(:crop, approval_status: 'pending') } let!(:garden) { FactoryBot.create(:garden, owner: member) } + before { get :new, crop_id: crop.id } it { expect(assigns(:crop)).not_to eq(crop) } end @@ -71,6 +75,7 @@ describe PlantingsController do describe "Doesn't display rejected crops on planting form" do let(:crop) { FactoryBot.create(:crop, approval_status: 'rejected', reason_for_rejection: 'nope') } let!(:garden) { FactoryBot.create(:garden, owner: member) } + before { get :new, crop_id: crop.id } it { expect(assigns(:crop)).not_to eq(crop) } end diff --git a/spec/controllers/shop_controller_spec.rb b/spec/controllers/shop_controller_spec.rb index c25039d2d..2fc6b77f7 100644 --- a/spec/controllers/shop_controller_spec.rb +++ b/spec/controllers/shop_controller_spec.rb @@ -24,6 +24,7 @@ describe ShopController do describe "assigns @order as current_order if there is one" do let(:member) { FactoryBot.create(:member) } let!(:order) { FactoryBot.create(:order, member: member) } + before do sign_in member get :index, {} diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 05ebdb6e7..7e927756d 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -204,6 +204,7 @@ feature "crop detail page", js: true do planted_at: 100.days.ago, finished_at: 1.day.ago) end + context 'crop is an annual' do let(:crop) { FactoryBot.create(:annual_crop) } @@ -256,16 +257,19 @@ feature "crop detail page", js: true do before { visit crop_path(crop) } context 'crop is an annual' do let(:crop) { FactoryBot.create :annual_crop } + it { expect(page).to have_text 'annual crop (living and reproducing in a single year or less)' } it { expect(page).not_to have_text 'perennial crop (living more than two years)' } end context 'crop is perennial' do let(:crop) { FactoryBot.create :perennial_crop } + it { expect(page).to have_text 'perennial crop (living more than two years)' } it { expect(page).not_to have_text 'annual crop (living and reproducing in a single year or less)' } end context 'crop perennial value is null' do let(:crop) { FactoryBot.create :crop, perennial: nil } + it { expect(page).not_to have_text 'perennial crop (living more than two years)' } it { expect(page).not_to have_text 'annual crop (living and reproducing in a single year or less)' } end diff --git a/spec/features/crops/requested_crops_spec.rb b/spec/features/crops/requested_crops_spec.rb index 6bfb8220c..15226efe4 100644 --- a/spec/features/crops/requested_crops_spec.rb +++ b/spec/features/crops/requested_crops_spec.rb @@ -3,6 +3,7 @@ require 'rails_helper' feature "Crop - " do let(:member) { create :member } let!(:requested_crop) { create :crop, requester: member, approval_status: 'pending', name: 'puha for dinner' } + background do login_as member visit requested_crops_path diff --git a/spec/features/gardens_spec.rb b/spec/features/gardens_spec.rb index a299a0197..0954d35eb 100644 --- a/spec/features/gardens_spec.rb +++ b/spec/features/gardens_spec.rb @@ -88,6 +88,7 @@ feature "Planting a crop", js: true do describe "Making a planting inactive from garden show" do let(:path) { garden_path garden } let(:link_text) { "Mark as finished" } + it_behaves_like "append date" end diff --git a/spec/features/members/deletion_spec.rb b/spec/features/members/deletion_spec.rb index 3009f51be..793a6ada5 100644 --- a/spec/features/members/deletion_spec.rb +++ b/spec/features/members/deletion_spec.rb @@ -12,6 +12,7 @@ feature "member deletion" do let!(:secondgarden) { FactoryBot.create(:garden, owner: member) } let!(:order) { FactoryBot.create(:order, member: member, completed_at: Time.zone.now) } let(:admin) { FactoryBot.create(:admin_member) } + background do login_as(member) visit member_path(other_member) diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index 0c984837b..51ff69be2 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -270,6 +270,7 @@ feature "Planting a crop", :js, :elasticsearch do describe "Marking a planting as finished from the show page" do let(:path) { planting_path(planting) } let(:link_text) { "Mark as finished" } + it_behaves_like "append date" end diff --git a/spec/features/seeds/seed_photos.rb b/spec/features/seeds/seed_photos.rb index 635b4dc4d..3d57f2cfe 100644 --- a/spec/features/seeds/seed_photos.rb +++ b/spec/features/seeds/seed_photos.rb @@ -19,12 +19,14 @@ feature "Seeds", :js do context 'has one photo' do before { seed.photos = [photo] } let!(:photo) { FactoryBot.create :photo, title: 'hello photo' } + it { is_expected.to have_xpath("//img[contains(@src,'#{photo.thumbnail_url}')]") } it { is_expected.to have_xpath("//a[contains(@href,'#{photo_path(photo)}')]") } end context 'has 50 photos' do before { seed.photos = photos } let!(:photos) { FactoryBot.create_list :photo, 50 } + it "shows newest photo" do is_expected.to have_xpath("//img[contains(@src,'#{photos.last.thumbnail_url}')]") end diff --git a/spec/features/signout_spec.rb b/spec/features/signout_spec.rb index a6402df2c..35cd8af9b 100644 --- a/spec/features/signout_spec.rb +++ b/spec/features/signout_spec.rb @@ -30,6 +30,7 @@ feature "signout" do end let(:path) {} + describe 'after signout, redirect to signin page if page needs authentication' do include_examples "sign-in redirects", "/plantings/new" include_examples "sign-in redirects", "/harvests/new" diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index f89cc3377..515d0160c 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -82,36 +82,43 @@ describe Crop do context 'not a url' do let(:wikipedia_url) { 'this is not valid' } + it { expect(subject).not_to be_valid } end context 'http url' do let(:wikipedia_url) { 'http://en.wikipedia.org/wiki/SomePage' } + it { expect(subject).to be_valid } end context 'with ssl' do let(:wikipedia_url) { 'https://en.wikipedia.org/wiki/SomePage' } + it { expect(subject).to be_valid } end context 'with utf8 macrons' do let(:wikipedia_url) { 'https://en.wikipedia.org/wiki/Māori' } + it { expect(subject).to be_valid } end context 'urlencoded' do let(:wikipedia_url) { 'https://en.wikipedia.org/wiki/M%C4%81ori' } + it { expect(subject).to be_valid } end context 'with new lines in url' do let(:wikipedia_url) { 'http://en.wikipedia.org/wiki/SomePage\n\nBrendaRocks' } + it { expect(subject).not_to be_valid } end context "with script tags in url" do let(:wikipedia_url) { 'http://en.wikipedia.org/wiki/SomePage' } + it { expect(subject).not_to be_valid } end end @@ -330,6 +337,7 @@ describe Crop do let(:h2) { FactoryBot.create(:harvest, crop: maize, plant_part: pp2) } let!(:crop) { FactoryBot.create(:crop) } let!(:harvest) { FactoryBot.create(:harvest, crop: crop) } + it "has harvests" do expect(crop.harvests).to eq [harvest] end diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index 1911ae8da..cf7b81486 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -432,6 +432,7 @@ describe 'member' do context 'member deleted' do let(:member) { FactoryBot.create(:member) } + context 'queries a scope' do before { member.destroy } it { expect(Member.all).not_to include(member) } @@ -450,10 +451,12 @@ describe 'member' do context "deleted admin member" do let(:member) { FactoryBot.create(:admin_member) } + before { member.destroy } context 'crop creator' do let!(:crop) { FactoryBot.create(:crop, creator: member) } + it "leaves crops behind, reassigned to cropbot" do expect(Crop.all).to include(crop) end @@ -461,6 +464,7 @@ describe 'member' do context 'forum owners' do let!(:forum) { FactoryBot.create(:forum, owner: member) } + it "leaves forums behind, reassigned to ex_admin" do expect(forum.owner).to eq(member) end diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index e220bfe59..c971ce2fd 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -3,6 +3,7 @@ require 'rails_helper' describe Photo do let(:photo) { FactoryBot.create(:photo, owner: member) } let(:member) { FactoryBot.create(:member) } + describe 'add/delete functionality' do let(:planting) { FactoryBot.create(:planting) } let(:harvest) { FactoryBot.create(:harvest) } diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 48a035bb4..60a95c245 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -13,6 +13,7 @@ describe Planting do context 'no predications data yet' do describe 'planting planted, not finished' do let(:planting) { FactoryBot.create :planting, planted_at: 30.days.ago, finished_at: nil, finished: false } + it { expect(planting.crop.median_lifespan).to eq(nil) } it { expect(planting.expected_lifespan).to eq(nil) } it { expect(planting.days_since_planted).to eq(30) } @@ -20,6 +21,7 @@ describe Planting do end describe 'planting not planted yet' do let(:planting) { FactoryBot.create :planting, planted_at: nil, finished_at: nil, finished: false } + it { expect(planting.crop.median_lifespan).to eq(nil) } it { expect(planting.expected_lifespan).to eq(nil) } it { expect(planting.days_since_planted).to eq(nil) } @@ -27,6 +29,7 @@ describe Planting do end describe 'planting finished, no planted_at' do let(:planting) { FactoryBot.create :planting, planted_at: nil, finished_at: 1.day.ago, finished: true } + it { expect(planting.crop.median_lifespan).to eq(nil) } it { expect(planting.expected_lifespan).to eq(nil) } it { expect(planting.days_since_planted).to eq(nil) } @@ -34,6 +37,7 @@ describe Planting do end describe 'planting all finished' do let(:planting) { FactoryBot.create :planting, planted_at: 30.days.ago, finished_at: 1.day.ago, finished: true } + it { expect(planting.crop.median_lifespan).to eq(nil) } it { expect(planting.expected_lifespan).to eq(29) } it { expect(planting.days_since_planted).to eq(30) } @@ -63,16 +67,19 @@ describe Planting do describe 'planting not planted yet' do let(:planting) { FactoryBot.create :planting, planted_at: nil, finished_at: nil } + it { expect(planting.percentage_grown).to eq nil } end describe 'planting finished 10 days, but was never planted' do let(:planting) { FactoryBot.create :planting, planted_at: nil, finished_at: 10.days.ago } + it { expect(planting.percentage_grown).to eq nil } end describe 'planted 30 days ago, finished 10 days ago' do let(:planting) { FactoryBot.create :planting, planted_at: 30.days.ago, finished_at: 10.days.ago } + it { expect(planting.days_since_planted).to eq 30 } it { expect(planting.percentage_grown).to eq 100 } end @@ -82,6 +89,7 @@ describe Planting do describe 'planting first harvest preductions' do context 'no data' do let(:planting) { FactoryBot.create :planting } + it { expect(planting.crop.median_days_to_first_harvest).to eq(nil) } it { expect(planting.crop.median_days_to_last_harvest).to eq(nil) } it { expect(planting.days_to_first_harvest).to eq(nil) } @@ -114,11 +122,13 @@ describe Planting do planting.crop.update_harvest_medians end let(:planting) { FactoryBot.create :planting } + it { expect(planting.days_to_first_harvest).to eq(nil) } it { expect(planting.days_to_last_harvest).to eq(nil) } end describe 'planting has first harvest' do let(:planting) { FactoryBot.create :planting, planted_at: 100.days.ago } + before do FactoryBot.create(:harvest, planting: planting, @@ -134,6 +144,7 @@ describe Planting do end describe 'planting has last harvest' do let(:planting) { FactoryBot.create :planting, planted_at: 100.days.ago, finished_at: 1.day.ago, finished: true } + before do FactoryBot.create :harvest, planting: planting, crop: planting.crop, harvested_at: 90.days.ago FactoryBot.create :harvest, planting: planting, crop: planting.crop, harvested_at: 10.days.ago diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index cb8cbcc91..062aba487 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -2,6 +2,7 @@ require 'rails_helper' describe Post do let(:member) { FactoryBot.create(:member) } + it_behaves_like "it is likeable" it "should have a slug" do diff --git a/spec/models/role_spec.rb b/spec/models/role_spec.rb index 3016591b7..a7cfbecd3 100644 --- a/spec/models/role_spec.rb +++ b/spec/models/role_spec.rb @@ -19,6 +19,7 @@ describe Role do describe '.crop_wranglers' do let!(:crop_wranglers) { FactoryBot.create_list(:crop_wrangling_member, 3) } + it 'return the crop wranglers that are members of that role' do expect(Role.crop_wranglers).to match_array(crop_wranglers) end @@ -26,6 +27,7 @@ describe Role do describe '.admins' do let!(:admins) { FactoryBot.create_list(:admin_member, 3) } + it 'return the members that have the role of admin' do expect(Role.admins).to match_array(admins) end diff --git a/spec/models/seed_spec.rb b/spec/models/seed_spec.rb index c1cd95cbd..e45d0e240 100644 --- a/spec/models/seed_spec.rb +++ b/spec/models/seed_spec.rb @@ -151,6 +151,7 @@ describe Seed do context 'photos' do let(:seed) { FactoryBot.create :seed } + before { seed.photos << FactoryBot.create(:photo) } it 'is found in has_photos scope' do Seed.has_photos.should include(seed) diff --git a/spec/views/crops/_planting_advice.html.haml_spec.rb b/spec/views/crops/_planting_advice.html.haml_spec.rb index c7a4719b5..38499e2d9 100644 --- a/spec/views/crops/_planting_advice.html.haml_spec.rb +++ b/spec/views/crops/_planting_advice.html.haml_spec.rb @@ -2,6 +2,7 @@ require 'rails_helper' describe "crops/_planting_advice" do let(:planting) { FactoryBot.create(:planting) } + subject { rendered } shared_examples "render planting_advice" do diff --git a/spec/views/home/_crops.html.haml_spec.rb b/spec/views/home/_crops.html.haml_spec.rb index 254fcb2f6..3ed655438 100644 --- a/spec/views/home/_crops.html.haml_spec.rb +++ b/spec/views/home/_crops.html.haml_spec.rb @@ -4,6 +4,7 @@ describe 'home/_crops.html.haml', type: "view" do let!(:crop) { FactoryBot.create(:crop, plantings: FactoryBot.create_list(:planting, 3)) } let!(:photo) { FactoryBot.create(:photo, plantings: [crop.plantings.first]) } let(:planting) { crop.plantings.first } + before(:each) { render } it 'shows crops section' do assert_select 'h2', text: 'Some of our crops' diff --git a/spec/views/members/index.html.haml_spec.rb b/spec/views/members/index.html.haml_spec.rb index 81e8a6670..87dd3a285 100644 --- a/spec/views/members/index.html.haml_spec.rb +++ b/spec/views/members/index.html.haml_spec.rb @@ -2,6 +2,7 @@ require 'rails_helper' describe "members/index" do let(:member) { FactoryBot.create(:london_member) } + before(:each) do controller.stub(:current_user) { nil } page = 1 diff --git a/spec/views/plantings/index.html.haml_spec.rb b/spec/views/plantings/index.html.haml_spec.rb index f682d62e9..a3a713100 100644 --- a/spec/views/plantings/index.html.haml_spec.rb +++ b/spec/views/plantings/index.html.haml_spec.rb @@ -5,6 +5,7 @@ describe "plantings/index" do let(:garden) { FactoryBot.create(:garden, owner: member) } let(:tomato) { FactoryBot.create(:tomato) } let(:maize) { FactoryBot.create(:maize) } + before(:each) do controller.stub(:current_user) { nil } page = 1 diff --git a/spec/views/plantings/show.html.haml_spec.rb b/spec/views/plantings/show.html.haml_spec.rb index 040a0f6b0..899724ac7 100644 --- a/spec/views/plantings/show.html.haml_spec.rb +++ b/spec/views/plantings/show.html.haml_spec.rb @@ -28,6 +28,7 @@ describe "plantings/show" do context 'planted from' do let(:planting) { FactoryBot.create(:cutting_planting) } + it "shows planted_from" do render rendered.should have_content 'Planted from:' diff --git a/spec/views/posts/show.html.haml_spec.rb b/spec/views/posts/show.html.haml_spec.rb index 169e90da0..273f400cc 100644 --- a/spec/views/posts/show.html.haml_spec.rb +++ b/spec/views/posts/show.html.haml_spec.rb @@ -25,25 +25,30 @@ describe "posts/show" do describe "should parse markdown into html" do let(:post) { FactoryBot.create(:markdown_post, author: author) } + it { assert_select "strong", "strong" } end describe "shouldn't let html through in body" do let(:post) { FactoryBot.create(:post, author: author, body: 'EVIL') } + it { is_expected.to have_content('EVIL') } it { is_expected.not_to have_link("http://evil.com") } end describe 'script tag in post body' do let(:post) { FactoryBot.create(:post, author: author, body: "") } + it { is_expected.not_to have_selector('script') } end describe 'script tag in post title' do let(:post) { FactoryBot.create(:post, author: author, subject: "") } + it { is_expected.not_to have_selector('script') } end describe 'has an anchor to the comments' do let(:post) { FactoryBot.create(:post, author: author) } + it { is_expected.to have_selector('a[name=comments]') } end end @@ -51,6 +56,7 @@ describe "posts/show" do context "when there is one comment" do let(:post) { FactoryBot.create(:html_post, author: author) } let!(:comment) { FactoryBot.create(:comment, post: post) } + before(:each) do @comments = post.comments render @@ -71,6 +77,7 @@ describe "posts/show" do context "when there is more than one comment" do let(:post) { FactoryBot.create(:html_post, author: author) } + before(:each) do @comment1 = FactoryBot.create(:comment, post: post, body: "F1rst!!!", created_at: Date.new(2010, 5, 17)) @@ -90,6 +97,7 @@ describe "posts/show" do context "forum post" do let(:post) { FactoryBot.create(:forum_post, author: author) } + before { render } it "shows forum name" do is_expected.to have_content "in #{post.forum.name}" @@ -98,6 +106,7 @@ describe "posts/show" do context "signed in" do let(:post) { FactoryBot.create(:post, author: author) } + before(:each) do sign_in author controller.stub(:current_user) { author } From dc86404b6f3b44109aad1a9744d03bb5e6f2283a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 9 Jan 2018 15:53:40 +1300 Subject: [PATCH 080/267] Fix predictions, it wasn't showing nil --- app/views/crops/_predictions.html.haml | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/app/views/crops/_predictions.html.haml b/app/views/crops/_predictions.html.haml index 343f4f6bd..2a647d350 100644 --- a/app/views/crops/_predictions.html.haml +++ b/app/views/crops/_predictions.html.haml @@ -1,5 +1,5 @@ -- unless crop.perennial.nil? - .predictions +.predictions + - unless crop.perennial.nil? .row %p #{crop.name} is @@ -12,23 +12,23 @@ an annual crop (living and reproducing in a single year or less) - .row - - if crop.annual? && crop.median_lifespan.present? - .metric.col-md-3.col-xs-5 - %h3 Median lifespan - %strong= crop.median_lifespan - %span days + .row + - if crop.annual? && crop.median_lifespan.present? + .metric.col-md-3.col-xs-5 + %h3 Median lifespan + %strong= crop.median_lifespan + %span days - - if crop.median_days_to_first_harvest.present? - .metric.col-md-3.col-xs-5 - %h3 First harvest expected - %strong= crop.median_days_to_first_harvest - %span days - after planting + - if crop.median_days_to_first_harvest.present? + .metric.col-md-3.col-xs-5 + %h3 First harvest expected + %strong= crop.median_days_to_first_harvest + %span days + after planting - - if crop.annual? && crop.median_days_to_last_harvest.present? - .metric.col-md-3.col-xs-5 - %h3 Last harvest expected - %strong= crop.median_days_to_last_harvest - %span days - after planting + - if crop.annual? && crop.median_days_to_last_harvest.present? + .metric.col-md-3.col-xs-5 + %h3 Last harvest expected + %strong= crop.median_days_to_last_harvest + %span days + after planting From 15594c020977077cc053526eb3ab474654b86fd1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jan 2018 08:26:59 +1300 Subject: [PATCH 081/267] Wrapped thre crops show js in a document.ready --- app/assets/javascripts/crops.js.erb | 31 ++++++++++++++++------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/app/assets/javascripts/crops.js.erb b/app/assets/javascripts/crops.js.erb index 9a60dd60c..4e2a67e82 100644 --- a/app/assets/javascripts/crops.js.erb +++ b/app/assets/javascripts/crops.js.erb @@ -1,14 +1,3 @@ -if (document.getElementById("cropmap") !== null) { - mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>"; - mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>"; - mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token; - - L.Icon.Default.imagePath = '/assets' - - cropmap = L.map('cropmap').setView([0.0, -0.0], 2); - showCropMap(cropmap); -} - function showCropMap(cropmap) { L.tileLayer(mapbox_base_url, { @@ -49,6 +38,20 @@ function showCropMap(cropmap) { cropmap.addLayer(markers); } -$('.btn.toggle.crop-hierarchy').click(function () { - $('.toggle.crop-hierarchy').toggleClass('hide'); -}); +$(document).ready(function() { + + if (document.getElementById("cropmap") !== null) { + mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>"; + mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>"; + mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token; + + L.Icon.Default.imagePath = '/assets' + + cropmap = L.map('cropmap').setView([0.0, -0.0], 2); + showCropMap(cropmap); + } + + $('.btn.toggle.crop-hierarchy').click(function () { + $('.toggle.crop-hierarchy').toggleClass('hide'); + }); +}); \ No newline at end of file From ad6601b356d0442f5ee605e591ab60332337322c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jan 2018 08:29:20 +1300 Subject: [PATCH 082/267] Add planted_from chart --- app/controllers/crops_controller.rb | 8 +++++ app/views/crops/_predictions.html.haml | 21 ++++++------- app/views/crops/show.html.haml | 41 ++++++++++++++++---------- config/routes.rb | 1 + 4 files changed, 45 insertions(+), 26 deletions(-) diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index b62177e5d..371e70726 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -110,6 +110,14 @@ class CropsController < ApplicationController .group(:sunniness).count(:id) end + def planted_from + @crop = Crop.find(params[:crop_id]) + render json: Planting.where(crop: @crop) + .where.not(planted_from: nil) + .where.not(planted_from: '') + .group(:planted_from).count(:id) + end + private def notifier diff --git a/app/views/crops/_predictions.html.haml b/app/views/crops/_predictions.html.haml index 2a647d350..74e8bafb1 100644 --- a/app/views/crops/_predictions.html.haml +++ b/app/views/crops/_predictions.html.haml @@ -1,16 +1,17 @@ .predictions - unless crop.perennial.nil? .row - %p - #{crop.name} is - - if crop.perennial == true - = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do - a perennial crop - (living more than two years) - - elsif crop.perennial == false - = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do - an annual crop - (living and reproducing in a single year or less) + .col-md-12 + %p + #{crop.name} is + - if crop.perennial == true + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + a perennial crop + (living more than two years) + - elsif crop.perennial == false + = link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do + an annual crop + (living and reproducing in a single year or less) .row - if crop.annual? && crop.median_lifespan.present? diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index e5e7e7a1a..8f4486fe9 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -23,25 +23,24 @@ .row .col-md-9 - - if member_signed_in? - = display_seed_availability(@current_member, @crop) - = link_to "View your seeds", seeds_by_owner_path(owner: current_member.slug) + .row + .col-md-12 + - if member_signed_in? + = display_seed_availability(@current_member, @crop) + = link_to "View your seeds", seeds_by_owner_path(owner: current_member.slug) + + %h2 + - if !@crop.plantings.empty? + = @crop.name.titleize + has been planted + = pluralize(@crop.plantings.size, "time") + by #{ENV['GROWSTUFF_SITE_NAME']} members. + - else + Nobody is growing this yet. You could be the first! - %h2 - - if !@crop.plantings.empty? - = @crop.name.titleize - has been planted - = pluralize(@crop.plantings.size, "time") - by #{ENV['GROWSTUFF_SITE_NAME']} members. - - else - Nobody is growing this yet. You could be the first! .row - .col-md-3 - %h2 Sunniness Chart - = pie_chart crop_sunniness_path(@crop), legend: "bottom" - - .col-md-9 + .col-md-12 %h2 Predictions = render 'predictions', crop: @crop @@ -49,7 +48,17 @@ .col-md-12 %h2 Photos %p= render 'crops/photos', crop: @crop + .row + .col-md-3 + %h2 Sunniness + = pie_chart crop_sunniness_path(@crop), legend: "bottom" + .col-md-3 + %h2 Planted from + = pie_chart crop_planted_from_path(@crop), legend: "bottom" + + .row + .col-md-12 %h2 Crop Map %p Only plantings by members who have set their locations are shown on this map. diff --git a/config/routes.rb b/config/routes.rb index 14c4bd401..2872db18b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -51,6 +51,7 @@ Growstuff::Application.routes.draw do resources :crops do get 'photos' => 'photos#index' get 'sunniness' => 'crops#sunniness' + get 'planted_from' => 'crops#planted_from' end resources :comments From 390282f9f231118db926810b1fe1ecc336c4e5d3 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jan 2018 09:03:13 +1300 Subject: [PATCH 083/267] Added Harvested for chart --- app/controllers/crops_controller.rb | 24 +++++++++++++++--------- app/views/crops/show.html.haml | 3 +++ config/routes.rb | 1 + 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 371e70726..d3bd5dcf9 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -103,23 +103,29 @@ class CropsController < ApplicationController end def sunniness - @crop = Crop.find(params[:crop_id]) - render json: Planting.where(crop: @crop) - .where.not(sunniness: nil) - .where.not(sunniness: '') - .group(:sunniness).count(:id) + pie_chart_query 'sunniness' end def planted_from + pie_chart_query 'planted_from' + end + + def harvested_for @crop = Crop.find(params[:crop_id]) - render json: Planting.where(crop: @crop) - .where.not(planted_from: nil) - .where.not(planted_from: '') - .group(:planted_from).count(:id) + render json: Harvest.joins(:plant_part).where(crop: @crop) + .group("plant_parts.name").count(:id) end private + def pie_chart_query(field) + @crop = Crop.find(params[:crop_id]) + render json: Planting.where(crop: @crop) + .where.not(field.to_sym => nil) + .where.not(field.to_sym => '') + .group(field.to_sym).count(:id) + end + def notifier case @crop.approval_status when "approved" diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index 8f4486fe9..270c0db2b 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -56,6 +56,9 @@ .col-md-3 %h2 Planted from = pie_chart crop_planted_from_path(@crop), legend: "bottom" + .col-md-3 + %h2 Harvested for + = pie_chart crop_harvested_for_path(@crop), legend: "bottom" .row .col-md-12 diff --git a/config/routes.rb b/config/routes.rb index 2872db18b..9d4e3fe60 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -52,6 +52,7 @@ Growstuff::Application.routes.draw do get 'photos' => 'photos#index' get 'sunniness' => 'crops#sunniness' get 'planted_from' => 'crops#planted_from' + get 'harvested_for' => 'crops#harvested_for' end resources :comments From bd326471781bf95582b32f5efa44b0a78e5494bd Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Wed, 10 Jan 2018 20:17:58 +0000 Subject: [PATCH 084/267] Auto corrected by following Style/OrAssignment --- app/models/csv_importer.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/csv_importer.rb b/app/models/csv_importer.rb index 66297b13c..e24991e80 100644 --- a/app/models/csv_importer.rb +++ b/app/models/csv_importer.rb @@ -46,7 +46,7 @@ class CsvImporter names_to_add.each do |name| sciname = ScientificName.find_by(name: name, crop: @crop) - sciname = ScientificName.create!(name: name, crop: @crop, creator: cropbot) unless sciname + sciname ||= ScientificName.create!(name: name, crop: @crop, creator: cropbot) @crop.scientific_names << sciname end end @@ -56,13 +56,13 @@ class CsvImporter return if alternate_names.blank? alternate_names.split(/,\s*/).each do |name| altname = AlternateName.find_by(name: name, crop: @crop) - altname = AlternateName.create! name: name, crop: @crop, creator: cropbot unless altname + altname ||= AlternateName.create! name: name, crop: @crop, creator: cropbot @crop.alternate_names << altname end end def cropbot - @cropbot = Member.find_by!(login_name: 'cropbot') unless @cropbot + @cropbot ||= Member.find_by!(login_name: 'cropbot') @cropbot rescue raise "cropbot account not found: run rake db:seed" From e865e9366560aefffc4c6cdb43cc6550a4c5e3a7 Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Wed, 10 Jan 2018 20:18:10 +0000 Subject: [PATCH 085/267] Auto corrected by following Style/ParallelAssignment --- app/mailers/notifier.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/mailers/notifier.rb b/app/mailers/notifier.rb index 569400ce6..6c479f51f 100644 --- a/app/mailers/notifier.rb +++ b/app/mailers/notifier.rb @@ -37,17 +37,20 @@ class Notifier < ActionMailer::Base end def new_crop_request(member, request) - @member, @request = member, request + @member = member + @request = request mail(to: @member.email, subject: "#{@request.requester.login_name} has requested #{@request.name} as a new crop") end def crop_request_approved(member, crop) - @member, @crop = member, crop + @member = member + @crop = crop mail(to: @member.email, subject: "#{crop.name.capitalize} has been approved") end def crop_request_rejected(member, crop) - @member, @crop = member, crop + @member = member + @crop = crop mail(to: @member.email, subject: "#{crop.name.capitalize} has been rejected") end end From 1a4e0bd48a473ac1b587215bda75cbe19a597b99 Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Wed, 10 Jan 2018 20:18:17 +0000 Subject: [PATCH 086/267] Auto corrected by following Style/RescueStandardError --- app/models/csv_importer.rb | 2 +- db/seeds.rb | 2 +- spec/controllers/photo_associations_controller_spec.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/csv_importer.rb b/app/models/csv_importer.rb index 66297b13c..f95fae8f2 100644 --- a/app/models/csv_importer.rb +++ b/app/models/csv_importer.rb @@ -64,7 +64,7 @@ class CsvImporter def cropbot @cropbot = Member.find_by!(login_name: 'cropbot') unless @cropbot @cropbot - rescue + rescue StandardError raise "cropbot account not found: run rake db:seed" end end diff --git a/db/seeds.rb b/db/seeds.rb index 7df7e0e4c..be885a352 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -65,7 +65,7 @@ def load_test_users # rubocop:disable Metrics/AbcSize source_path = Rails.root.join('db', 'seeds') begin suburb_file = File.open("#{source_path}/suburbs.csv") - rescue + rescue StandardError puts "Warning: unable to open suburbs.csv" end diff --git a/spec/controllers/photo_associations_controller_spec.rb b/spec/controllers/photo_associations_controller_spec.rb index 75a04eedd..f021d5aa8 100644 --- a/spec/controllers/photo_associations_controller_spec.rb +++ b/spec/controllers/photo_associations_controller_spec.rb @@ -31,7 +31,7 @@ describe PhotoAssociationsController do expect do begin delete :destroy, valid_params - rescue + rescue StandardError nil end end.not_to change(photo.harvests, :count) From 0d35b4ca6d443b137d0119d46fa217ec50391c13 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jan 2018 09:26:48 +1300 Subject: [PATCH 087/267] Updating rubocop todo --- .rubocop.yml | 2 +- .rubocop_todo.yml | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 571a090bd..27309055f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -64,7 +64,7 @@ Metrics/MethodLength: Metrics/AbcSize: Max: 31 Metrics/ClassLength: - Max: 179 + Max: 182 Metrics/CyclomaticComplexity: Max: 11 Metrics/PerceivedComplexity: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 4e0d899c7..1adfe8921 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,11 +1,16 @@ # This configuration was generated by # `rubocop --auto-gen-config --no-offense-counts` -# on 2017-12-06 11:20:15 +1300 using RuboCop version 0.49.1. +# on 2018-01-11 09:25:35 +1300 using RuboCop version 0.49.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. +# Cop supports --auto-correct. +Layout/EmptyLines: + Exclude: + - 'bin/setup' + Lint/HandleExceptions: Exclude: - 'lib/tasks/testing.rake' @@ -52,15 +57,10 @@ Style/AndOr: - 'config/unicorn.rb' - 'lib/tasks/growstuff.rake' -Style/AsciiComments: - Exclude: - - 'config/initializers/comfortable_mexican_sofa.rb' - # Configuration parameters: EnforcedStyle, SupportedStyles. # SupportedStyles: nested, compact Style/ClassAndModuleChildren: Exclude: - - 'app/controllers/admin/orders_controller.rb' - 'lib/actions/oauth_signup_action.rb' - 'lib/haml/filters/escaped_markdown.rb' @@ -111,3 +111,10 @@ Style/RegexpLiteral: - 'spec/views/devise/registrations/edit_spec.rb' - 'spec/views/members/index.html.haml_spec.rb' - 'spec/views/posts/index.html.haml_spec.rb' + +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, SupportedStyles. +# SupportedStyles: single_quotes, double_quotes +Style/StringLiteralsInInterpolation: + Exclude: + - 'bin/yarn' From 7dab57f9bad636554bef011afe9b1cfd5759b7b9 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jan 2018 09:31:59 +1300 Subject: [PATCH 088/267] Removed d3 graph tests --- spec/javascripts/graphs/bar_group_spec.js | 54 -------------- .../graphs/bar_label_group_spec.js | 38 ---------- spec/javascripts/graphs/height_scale_spec.js | 35 --------- .../graphs/horizontal_bar_graph_spec.js | 74 ------------------- spec/javascripts/graphs/width_scale_spec.js | 40 ---------- 5 files changed, 241 deletions(-) delete mode 100644 spec/javascripts/graphs/bar_group_spec.js delete mode 100644 spec/javascripts/graphs/bar_label_group_spec.js delete mode 100644 spec/javascripts/graphs/height_scale_spec.js delete mode 100644 spec/javascripts/graphs/horizontal_bar_graph_spec.js delete mode 100644 spec/javascripts/graphs/width_scale_spec.js diff --git a/spec/javascripts/graphs/bar_group_spec.js b/spec/javascripts/graphs/bar_group_spec.js deleted file mode 100644 index a76992a6c..000000000 --- a/spec/javascripts/graphs/bar_group_spec.js +++ /dev/null @@ -1,54 +0,0 @@ -(function() { - 'use strict'; - - /* - These tests are for the BarGroup object. - */ - - describe('when drawing the group of bars', function() { - var BarGroup; var subject; var bars; var data; - - beforeEach(function() { - BarGroup = growstuff.BarGroup; - - bars = [ - {name: 'Shade', value: 0.2}, - {name: 'Half Shade', value: 0.5}, - ]; - - data = { - bars: bars, - bar_color: 'steelblue', - width: {size: 300, scale: 'linear'}, - height: {size: 400, scale: 'ordinal'}, - }; - - subject = new BarGroup(data); - subject.render(d3.select('#jasmine_content').append('svg')); - }); - - it('draws a group', function() { - expect($('g.bar')).toExist(); - }); - - it('draws 2 bars', function() { - expect($('g.bar rect')).toHaveLength(2); - }); - - it('fills the bars with color', function() { - expect($('g.bar rect')).toHaveAttr('fill', 'steelblue'); - }); - - it('shows a tooltip on hover', function() { - var i; - - // get all of the title nodes for the bars - var barNodes = $('g.bar rect title'); - - for (i = 0; i < bars.length; i++) { - expect(barNodes[i].textContent) - .toBe('This value is ' + bars[i].value + '' + '.'); - } - }); - }); -}()); diff --git a/spec/javascripts/graphs/bar_label_group_spec.js b/spec/javascripts/graphs/bar_label_group_spec.js deleted file mode 100644 index 7cb6e5537..000000000 --- a/spec/javascripts/graphs/bar_label_group_spec.js +++ /dev/null @@ -1,38 +0,0 @@ -(function() { - 'use strict'; - - /* - This file contains tests for the labels that get rendered next to each bar - */ - - describe('BarLabelGroup', function() { - var BarLabelGroup; var subject; var data; - - beforeEach(function() { - BarLabelGroup = growstuff.BarLabelGroup; - var bars = [ - {name: 'Shade', value: 0.2}, - {name: 'Half Shade', value: 0.5}, - ]; - data = { - bars: bars, - }; - subject = new BarLabelGroup(data); - subject.render(d3.select('#jasmine_content').append('svg')); - }); - - it('draws a group for labels', function() { - expect($('g.bar-label')).toExist(); - }); - - it('draws 2 bar labels', function() { - expect($('g.bar-label text')).toHaveLength(2); - }); - - it('has text for 2 bar labels', function() { - // jquery jasmine appends text from all text elements - // into one string - expect($('g.bar-label text')).toHaveText('ShadeHalf Shade'); - }); - }); -}()); diff --git a/spec/javascripts/graphs/height_scale_spec.js b/spec/javascripts/graphs/height_scale_spec.js deleted file mode 100644 index 3a257400c..000000000 --- a/spec/javascripts/graphs/height_scale_spec.js +++ /dev/null @@ -1,35 +0,0 @@ -(function() { - 'use strict'; - - /* - Tests for mapping the number of bars to the size of the svg - */ - - describe('HeightScale when specifying height', function() { - var data; var bars; var HeightScale; var subject; var mockD3; - - beforeEach(function() { - HeightScale = growstuff.HeightScale; - bars = [ - {name: 'Shade', value: 0.2}, - {name: 'Half Shade', value: 0.5}, - ]; - data = { - bars: bars, - width: {size: 300, scale: 'linear'}, - height: {size: 400, scale: 'ordinal'}, - }; - - subject = new HeightScale(data); - mockD3 = jasmine.createSpyObj('d3', ['domain', 'rangeRoundBands']); - mockD3.domain.and.returnValue(mockD3); - mockD3.rangeRoundBands.and.returnValue(mockD3); - spyOn(d3.scale, 'ordinal').and.returnValue(mockD3); - subject.render(); - }); - - it('calls the d3 range round bands function to draw the height', function() { - expect(mockD3.rangeRoundBands).toHaveBeenCalledWith([0, 400], 0.05, 0); - }); - }); -}()); diff --git a/spec/javascripts/graphs/horizontal_bar_graph_spec.js b/spec/javascripts/graphs/horizontal_bar_graph_spec.js deleted file mode 100644 index 16f35f018..000000000 --- a/spec/javascripts/graphs/horizontal_bar_graph_spec.js +++ /dev/null @@ -1,74 +0,0 @@ -(function() { - 'use strict'; - - /* - Tests in this file are for the pieces of HorizontalBarGraph or - are more integration-y type tests that require the full graph. - */ - - describe('HorizontalBarGraph', function() { - var BarLabelGroup; var BarGroup; var subject; var data; - - beforeEach(function() { - var HorizontalBarGraph = growstuff.HorizontalBarGraph; - var bars = [ - {name: 'Shade', value: 0.2}, - {name: 'Half Shade', value: 0.5}, - ]; - data = { - bars: bars, - bar_color: 'steelblue', - width: {size: 300, scale: 'linear'}, - height: {size: 400, scale: 'ordinal'}, - // left is used to shift the bars over so that there is - // room for the labels - margin: {top: 0, right: 0, bottom: 0, left: 100}, - }; - - subject = new HorizontalBarGraph(data); - BarGroup = growstuff.BarGroup; - BarLabelGroup = growstuff.BarLabelGroup; - expect(BarLabelGroup).toExist(); - spyOn(BarGroup.prototype, 'render').and.callThrough(); - spyOn(BarLabelGroup.prototype, 'render').and.callThrough(); - subject.render(d3.select($('#jasmine_content')[0])); - }); - - it('draws a graph', function() { - expect($('#jasmine_content svg')).toExist(); - }); - - it('draws a group for the whole graph', function() { - expect($('g.bar-graph')).toExist(); - }); - - it('draws a bar group', function() { - expect(BarGroup.prototype.render).toHaveBeenCalled(); - }); - - it('draws a group of bar labels', function() { - expect(BarLabelGroup.prototype.render).toHaveBeenCalled(); - }); - - it('has the expected width and height', function() { - var $svg = $('svg'); - var margin = data.margin; - expect($svg).toHaveAttr('width', (data.width.size + margin.left + margin.right) + ''); - expect($svg).toHaveAttr('height', (data.height.size + margin.top + margin.bottom) + ''); - }); - - it('draws the graph shifted to the right to accommodate for labels', function() { - expect('g.bar-graph').toHaveAttr('transform', 'translate(100,0)'); - }); - - it('on the x axis, draws at least one bar at max width less margin width', function() { - // because of domain and range mapping - expect('g.bar rect:eq(1)').toHaveAttr('width', '300' ); - }); - - it('on the y axis, all bars are the same height', function() { - expect('g.bar rect:eq(0)').toHaveAttr('height', '195'); - expect('g.bar rect:eq(1)').toHaveAttr('height', '195'); - }); - }); -}()); diff --git a/spec/javascripts/graphs/width_scale_spec.js b/spec/javascripts/graphs/width_scale_spec.js deleted file mode 100644 index d8e34234a..000000000 --- a/spec/javascripts/graphs/width_scale_spec.js +++ /dev/null @@ -1,40 +0,0 @@ -(function() { - 'use strict'; - - /* - This file contains tests for the mapping the data values to - the length of a bar so that it is the correct size for the screen - */ - - describe('GraphScale, when specifying width', function() { - var data; var WidthScale; var subject; var mockD3; - - beforeEach(function() { - WidthScale = growstuff.WidthScale; - var bars = [ - {name: 'Shade', value: 0.2}, - {name: 'Half Shade', value: 0.5}, - ]; - data = { - bars: bars, - width: {size: 300, scale: 'linear'}, - height: {size: 400, scale: 'ordinal'}, - }; - - subject = new WidthScale(data, 'width'); - mockD3 = jasmine.createSpyObj('d3', ['domain', 'range', 'max']); - mockD3.domain.and.returnValue(mockD3); - mockD3.range.and.returnValue(mockD3); - spyOn(d3.scale, 'linear').and.returnValue(mockD3); - subject.render(); - }); - - it('gets the value of the longest bar', function() { - expect(subject.getMaxValue()).toEqual(0.5); - }); - - it('calls the d3 range function to draw the width', function() { - expect(mockD3.range).toHaveBeenCalledWith([0, 300]); - }); - }); -}()); From 2d813e49de82071e10a6fa2b3102a3ea99da1897 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jan 2018 15:36:27 +1300 Subject: [PATCH 089/267] add google js to gardens#show --- app/views/gardens/show.html.haml | 1 - app/views/layouts/application.html.haml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/gardens/show.html.haml b/app/views/gardens/show.html.haml index 5ffed7152..c6c08b792 100644 --- a/app/views/gardens/show.html.haml +++ b/app/views/gardens/show.html.haml @@ -11,7 +11,6 @@ = tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME']) - content_for :scripts do - = javascript_include_tag "charts" = javascript_include_tag "https://www.gstatic.com/charts/loader.js" .row diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index b90c025e7..7e9bee03d 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,6 +1,7 @@ !!! 5 %html{ lang: "en", prefix: "og: http://ogp.me/ns#" } = javascript_include_tag "application" + = yield :script = render partial: "layouts/meta" %body = render partial: "layouts/header" From c442bdbd45f6924d5af51c7ba340ee1ad0981fc2 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 11 Jan 2018 15:36:27 +1300 Subject: [PATCH 090/267] add google js to gardens#show --- app/views/gardens/show.html.haml | 1 - app/views/layouts/application.html.haml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/gardens/show.html.haml b/app/views/gardens/show.html.haml index 5ffed7152..c6c08b792 100644 --- a/app/views/gardens/show.html.haml +++ b/app/views/gardens/show.html.haml @@ -11,7 +11,6 @@ = tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME']) - content_for :scripts do - = javascript_include_tag "charts" = javascript_include_tag "https://www.gstatic.com/charts/loader.js" .row diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index b90c025e7..7fa9b185f 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,5 +1,6 @@ !!! 5 %html{ lang: "en", prefix: "og: http://ogp.me/ns#" } + = yield :scripts = javascript_include_tag "application" = render partial: "layouts/meta" %body From cc1d3b4f43ec4ebebf193cacc3ee16ffb47ad21f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Fri, 12 Jan 2018 08:07:38 +1300 Subject: [PATCH 091/267] Use predicted finish times to put current plantings on the timeline --- app/controllers/gardens_controller.rb | 11 ++++++++--- app/views/gardens/show.html.haml | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index d2aa8bfe0..a8f664b6d 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -61,10 +61,15 @@ class GardensController < ApplicationController def timeline @data = [] @garden = Garden.find(params[:garden_id]) - @garden.plantings.where.not(finished_at: nil) - .where.not(planted_at: nil) + @garden.plantings.where.not(planted_at: nil) .order(finished_at: :desc).each do |p| - @data << [p.crop.name, p.planted_at, p.finished_at] + + finish = if p.finished_at.present? + p.finished_at + else + p.finish_predicted_at + end + @data << [p.crop.name, p.planted_at, finish] if finish.present? end render json: @data end diff --git a/app/views/gardens/show.html.haml b/app/views/gardens/show.html.haml index c6c08b792..3928cfa58 100644 --- a/app/views/gardens/show.html.haml +++ b/app/views/gardens/show.html.haml @@ -40,7 +40,7 @@ .row = timeline garden_timeline_path(@garden), adapter: "google" - %h3 What's planted here? + %h3 Current plantings in garden .row - if @current_plantings.size.positive? - @current_plantings.each do |planting| From b831c29c97d5117e8cbecb49e160a1771408ef8d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Fri, 12 Jan 2018 08:07:38 +1300 Subject: [PATCH 092/267] Use .presence to find finished ts in timeline --- app/controllers/gardens_controller.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index a8f664b6d..585966e54 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -63,12 +63,8 @@ class GardensController < ApplicationController @garden = Garden.find(params[:garden_id]) @garden.plantings.where.not(planted_at: nil) .order(finished_at: :desc).each do |p| - - finish = if p.finished_at.present? - p.finished_at - else - p.finish_predicted_at - end + # use finished_at if we have it, otherwise use predictions + finish = p.finished_at.presence || p.finish_predicted_at @data << [p.crop.name, p.planted_at, finish] if finish.present? end render json: @data From e8bcce2ad3a8762a486bde1ccfbd4c1944026b37 Mon Sep 17 00:00:00 2001 From: pozorvlak Date: Fri, 12 Jan 2018 11:31:28 +0000 Subject: [PATCH 093/267] Only deploy from the Elasticsearch build job Fixes #1099, or at least works around it, though a better solution would be to rewrite our deployment system using Travis build stages or Heroku build pipelines. The Elasticsearch job was picked because it's the one most likely to fail, and I can't work out how to deploy only if all three jobs pass. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ef68fec4f..5d94d6a86 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,6 +56,7 @@ deploy: secure: "WrQxf0fEKkCdXrjcejurobOnNNz3he4dDwjBbToXbQTQNDObPp7NetJrLsfM8FiUFEeOuvhIHHiDQtMvY720zGGAGxDptvgFS+0QHCUqoTRZA/yFfUmHlG2jROXTzk5uVK0AE4k6Ion5kX8+mM0EnMT/7u+MTFiukrJctSiEXfg=" on: repo: Growstuff/growstuff + condition: "$RSPEC_TAG = elasticsearch" app: dev: growstuff-staging master: growstuff-prod From 3a4443a4fe6497d91abeff6a5e390693ef0767d7 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 13 Jan 2018 22:11:02 +1300 Subject: [PATCH 094/267] Permissions (and specs) for charts json --- app/controllers/gardens_controller.rb | 2 +- app/models/ability.rb | 6 ++++++ spec/controllers/crops_controller_spec.rb | 16 ++++++++++++++++ spec/controllers/gardens_controller_spec.rb | 13 ++++++++++--- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index 585966e54..a61d6cf88 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -1,5 +1,5 @@ class GardensController < ApplicationController - before_action :authenticate_member!, except: %i(index show) + before_action :authenticate_member!, except: %i(index show timeline) after_action :expire_homepage, only: %i(create delete) load_and_authorize_resource respond_to :html, :json diff --git a/app/models/ability.rb b/app/models/ability.rb index efba2aeb0..283bf45cc 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -15,6 +15,12 @@ class Ability can :view_follows, Member can :view_followers, Member + # Everyone can see the charts + can :timeline, Garden + can :sunniness, Crop + can :planted_from, Crop + can :harvested_for, Crop + # except these, which don't make sense if you're not logged in cannot :read, Notification cannot :read, Authentication diff --git a/spec/controllers/crops_controller_spec.rb b/spec/controllers/crops_controller_spec.rb index 5b682f6c2..9e54307bf 100644 --- a/spec/controllers/crops_controller_spec.rb +++ b/spec/controllers/crops_controller_spec.rb @@ -46,4 +46,20 @@ describe CropsController do it { expect(response.content_type).to eq("application/rss+xml") } end end + + describe 'GET charts' do + let(:crop) { FactoryBot.create :crop } + describe 'sunniness' do + before { get :sunniness, crop_id: crop.to_param } + it { expect(response).to be_success } + end + describe 'planted_from' do + before { get :planted_from, crop_id: crop.to_param } + it { expect(response).to be_success } + end + describe 'harvested_for' do + before { get :harvested_for, crop_id: crop.to_param } + it { expect(response).to be_success } + end + end end diff --git a/spec/controllers/gardens_controller_spec.rb b/spec/controllers/gardens_controller_spec.rb index 9253b5ddb..073d03d6b 100644 --- a/spec/controllers/gardens_controller_spec.rb +++ b/spec/controllers/gardens_controller_spec.rb @@ -4,9 +4,8 @@ RSpec.describe GardensController, type: :controller do include Devise::Test::ControllerHelpers let(:valid_params) { { name: 'My second Garden' } } + let(:garden) { FactoryBot.create :garden } context "when not signed in" do - let(:garden) { double('garden') } - describe 'GET new' do before { get :new, id: garden.to_param } it { expect(response).to redirect_to(new_member_session_path) } @@ -15,7 +14,10 @@ RSpec.describe GardensController, type: :controller do before { put :create, garden: valid_params } it { expect(response).to redirect_to(new_member_session_path) } end - + describe 'GET timeline' do + before { get :timeline, garden_id: garden.to_param } + it { expect(response).to be_success } + end describe 'changing existing records' do before do allow(Garden).to receive(:find).and_return(:garden) @@ -44,6 +46,11 @@ RSpec.describe GardensController, type: :controller do let!(:member) { FactoryBot.create(:member) } + describe 'GET timeline' do + before { get :timeline, garden_id: garden.to_param } + it { expect(response).to be_success } + end + describe "for another member's garden" do let(:not_my_garden) { double('garden') } From b6aef19be6543ce0b1179d697aa40913af44bfe9 Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Sat, 13 Jan 2018 22:49:36 +0000 Subject: [PATCH 095/267] Auto corrected by following RSpec/MultipleSubjects --- spec/features/crops/crop_detail_page_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 1ee9bae80..90ab42761 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' feature "crop detail page", js: true do let(:crop) { create :crop } - subject { visit crop_path(crop) } + context "varieties" do scenario "The crop DOES NOT have varieties" do From 273e4c07d8198d113d9f7188f8a7ee91e4a668e1 Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Sat, 13 Jan 2018 22:49:49 +0000 Subject: [PATCH 096/267] Auto corrected by following RSpec/NotToNot --- spec/features/crops/alternate_name_spec.rb | 2 +- spec/features/crops/crop_detail_page_spec.rb | 6 +++--- spec/features/following_spec.rb | 4 ++-- spec/features/member_profile_spec.rb | 6 +++--- spec/features/places/searching_a_place_spec.rb | 2 +- spec/features/plantings/planting_a_crop_spec.rb | 6 +++--- spec/features/scientific_name_spec.rb | 2 +- spec/features/shared_examples/crop_suggest.rb | 4 ++-- spec/models/crop_spec.rb | 2 +- spec/models/like_spec.rb | 10 +++++----- spec/models/post_spec.rb | 4 ++-- 11 files changed, 24 insertions(+), 24 deletions(-) diff --git a/spec/features/crops/alternate_name_spec.rb b/spec/features/crops/alternate_name_spec.rb index 319f4d7e1..e3b36c4a8 100644 --- a/spec/features/crops/alternate_name_spec.rb +++ b/spec/features/crops/alternate_name_spec.rb @@ -45,7 +45,7 @@ feature "Alternate names", js: true do href: alternate_name_path(alternate_eggplant) within('.alternate_names') { click_on "Delete" } expect(page.status_code).to equal 200 - expect(page).to_not have_content alternate_eggplant.name + expect(page).not_to have_content alternate_eggplant.name expect(page).to have_content 'Alternate name was successfully deleted' end diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 1ee9bae80..b155d6df5 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -149,9 +149,9 @@ feature "crop detail page", js: true do scenario "User not signed in" do visit crop_path(seed.crop) - expect(page).to_not have_content "You have 20 seeds of this crop" - expect(page).to_not have_content "You don't have any seeds of this crop" - expect(page).to_not have_link "View your seeds" + expect(page).not_to have_content "You have 20 seeds of this crop" + expect(page).not_to have_content "You don't have any seeds of this crop" + expect(page).not_to have_link "View your seeds" end scenario "User signed in" do diff --git a/spec/features/following_spec.rb b/spec/features/following_spec.rb index ac7a207be..735883e77 100644 --- a/spec/features/following_spec.rb +++ b/spec/features/following_spec.rb @@ -6,8 +6,8 @@ feature "follows", :js do scenario "follow buttons on member profile page" do visit member_path(member) - expect(page).to_not have_link "Follow" - expect(page).to_not have_link "Unfollow" + expect(page).not_to have_link "Follow" + expect(page).not_to have_link "Unfollow" end end diff --git a/spec/features/member_profile_spec.rb b/spec/features/member_profile_spec.rb index 0c27c7be2..32b11bda1 100644 --- a/spec/features/member_profile_spec.rb +++ b/spec/features/member_profile_spec.rb @@ -125,8 +125,8 @@ feature "member profile", js: true do scenario "ordinary user's page" do visit member_path(other_member) - expect(page).to_not have_text "Crop Wrangler" - expect(page).to_not have_text "Admin" + expect(page).not_to have_text "Crop Wrangler" + expect(page).not_to have_text "Admin" end context "your own profile page" do @@ -163,7 +163,7 @@ feature "member profile", js: true do end scenario "does not have a button to edit profile" do - expect(page).to_not have_link "Edit profile", href: edit_member_registration_path + expect(page).not_to have_link "Edit profile", href: edit_member_registration_path end end end diff --git a/spec/features/places/searching_a_place_spec.rb b/spec/features/places/searching_a_place_spec.rb index 10797d917..edbb06e59 100644 --- a/spec/features/places/searching_a_place_spec.rb +++ b/spec/features/places/searching_a_place_spec.rb @@ -13,7 +13,7 @@ feature "User searches" do expect(page).to have_content "community near Philippines" expect(page).to have_button "search_button" expect(page).to have_content "Nearby members" - expect(page).to_not have_content "No results found" + expect(page).not_to have_content "No results found" end scenario "with a blank search string" do diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index 51ff69be2..0e26d7078 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -110,8 +110,8 @@ feature "Planting a crop", :js, :elasticsearch do end expect(page).to have_content "planting was successfully created" - expect(page).to_not have_content "Progress: 0% - not planted yet" - expect(page).to_not have_content "Not enough data" + expect(page).not_to have_content "Progress: 0% - not planted yet" + expect(page).not_to have_content "Not enough data" end it "should show that planting is 100% complete (no date specified)" do @@ -178,7 +178,7 @@ feature "Planting a crop", :js, :elasticsearch do fill_in "Finished date", with: "2015-06-25" click_button "Save" expect(page).to have_content "planting was successfully updated" - expect(page).to_not have_content "Progress: Not enough data" + expect(page).not_to have_content "Progress: Not enough data" end scenario "Marking a planting as finished" do diff --git a/spec/features/scientific_name_spec.rb b/spec/features/scientific_name_spec.rb index d7205d263..d6daf709b 100644 --- a/spec/features/scientific_name_spec.rb +++ b/spec/features/scientific_name_spec.rb @@ -45,7 +45,7 @@ feature "Scientific names", js: true do href: scientific_name_path(zea_mays) within('.scientific_names') { click_on "Delete" } expect(page.status_code).to equal 200 - expect(page).to_not have_content zea_mays.name + expect(page).not_to have_content zea_mays.name expect(page).to have_content 'Scientific name was successfully deleted.' end diff --git a/spec/features/shared_examples/crop_suggest.rb b/spec/features/shared_examples/crop_suggest.rb index 8f45c1e96..0d2e688a1 100644 --- a/spec/features/shared_examples/crop_suggest.rb +++ b/spec/features/shared_examples/crop_suggest.rb @@ -17,8 +17,8 @@ shared_examples "crop suggest" do |resource| fill_autocomplete "crop", with: "pe" end - expect(page).to_not have_content("pear") - expect(page).to_not have_content("pea") + expect(page).not_to have_content("pear") + expect(page).not_to have_content("pea") within "form#new_#{resource}" do fill_autocomplete "crop", with: "pea" diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index 515d0160c..9e6173221 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -553,7 +553,7 @@ describe Crop do end it "should not delete the posts" do - expect(Post.find(post.id)).to_not eq nil + expect(Post.find(post.id)).not_to eq nil end end end diff --git a/spec/models/like_spec.rb b/spec/models/like_spec.rb index 50a2c1116..c92e3c389 100644 --- a/spec/models/like_spec.rb +++ b/spec/models/like_spec.rb @@ -26,31 +26,31 @@ describe 'like' do it 'is invalid without a member' do like = Like.new like.likeable = post - expect(like).to_not be_valid + expect(like).not_to be_valid end it 'is invalid without a likeable item' do like = Like.new like.member = member - expect(like).to_not be_valid + expect(like).not_to be_valid end end it 'does not allow duplicate likes by the same member' do Like.create(member: member, likeable: post) second_like = Like.new(member: member, likeable: post) - expect(second_like).to_not be_valid + expect(second_like).not_to be_valid end it 'destroys like if post no longer exists' do like = Like.create(member: member, likeable: post) post.destroy - expect(Like.all).to_not include like + expect(Like.all).not_to include like end it 'destroys like if member no longer exists' do like = Like.create(member: member, likeable: post) member.destroy - expect(Like.all).to_not include like + expect(Like.all).not_to include like end end diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 062aba487..98880ce2b 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -165,8 +165,8 @@ describe Post do end it "should not delete the crops" do - expect(Crop.find(tomato.id)).to_not eq nil - expect(Crop.find(maize.id)).to_not eq nil + expect(Crop.find(tomato.id)).not_to eq nil + expect(Crop.find(maize.id)).not_to eq nil end end end From 7fb2690306a449db2e11b4c21601f7595484e7b8 Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Sat, 13 Jan 2018 22:51:04 +0000 Subject: [PATCH 097/267] Auto corrected by following Style/MutableConstant --- app/models/planting.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index c51166264..6fd4aec17 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -4,12 +4,12 @@ class Planting < ActiveRecord::Base friendly_id :planting_slug, use: %i(slugged finders) # Constants - SUNNINESS_VALUES = %w(sun semi-shade shade) + SUNNINESS_VALUES = %w(sun semi-shade shade).freeze PLANTED_FROM_VALUES = [ 'seed', 'seedling', 'cutting', 'root division', 'runner', 'bulb', 'root/tuber', 'bare root plant', 'advanced plant', 'graft', 'layering' - ] + ].freeze ## ## Triggers From 4f0c004e50c9f9490bbd66095ba51145f07f1185 Mon Sep 17 00:00:00 2001 From: Shiny Date: Sun, 14 Jan 2018 12:04:32 +1300 Subject: [PATCH 098/267] Update crop_detail_page_spec.rb --- spec/features/crops/crop_detail_page_spec.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 90ab42761..03fb93ab8 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -3,8 +3,6 @@ require 'rails_helper' feature "crop detail page", js: true do let(:crop) { create :crop } - - context "varieties" do scenario "The crop DOES NOT have varieties" do visit crop_path(crop) From 8cdefb6fccce7804c22c50cb41c64a1ccccfad71 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 21 Jan 2018 18:36:23 +1300 Subject: [PATCH 099/267] Scope js variables so they are not global --- app/assets/javascripts/crops.js.erb | 26 +++++++++++++------------- app/assets/javascripts/members.js.erb | 19 +++++++++---------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/app/assets/javascripts/crops.js.erb b/app/assets/javascripts/crops.js.erb index 4e2a67e82..e4ee6d375 100644 --- a/app/assets/javascripts/crops.js.erb +++ b/app/assets/javascripts/crops.js.erb @@ -1,24 +1,27 @@ function showCropMap(cropmap) { + var mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>"; + var mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>"; + var mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token; L.tileLayer(mapbox_base_url, { attribution: 'Map data © OpenStreetMap contributors under ODbL | Map imagery © Mapbox', maxZoom: 18 }).addTo(cropmap); - markers = new L.MarkerClusterGroup({showCoverageOnHover: false, maxClusterRadius: 20 }); + var markers = new L.MarkerClusterGroup({showCoverageOnHover: false, maxClusterRadius: 20 }); - things_to_map = location.pathname + '.json'; + var things_to_map = location.pathname + '.json'; $.getJSON(things_to_map, function(crop) { $.each(crop.plantings, function(i, planting) { - owner = planting.owner; + var owner = planting.owner; if (owner.latitude && owner.longitude) { - marker = new L.Marker(new L.LatLng(owner.latitude, owner.longitude)); + var marker = new L.Marker(new L.LatLng(owner.latitude, owner.longitude)); - planting_url = "/plantings/" + planting.id; - planting_link = "" + owner.login_name + "'s " + crop.name + ""; + var planting_url = "/plantings/" + planting.id; + var planting_link = "" + owner.login_name + "'s " + crop.name + ""; - where = "

" + owner.location + "

"; + var where = "

" + owner.location + "

"; - details = "

"; + var details = "

"; if (planting.quantity) { details = details + "Quantity: " + planting.quantity + "
"; } @@ -41,13 +44,10 @@ function showCropMap(cropmap) { $(document).ready(function() { if (document.getElementById("cropmap") !== null) { - mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>"; - mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>"; - mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token; - L.Icon.Default.imagePath = '/assets' + L.Icon.Default.imagePath = '/assets'; - cropmap = L.map('cropmap').setView([0.0, -0.0], 2); + var cropmap = L.map('cropmap').setView([0.0, -0.0], 2); showCropMap(cropmap); } diff --git a/app/assets/javascripts/members.js.erb b/app/assets/javascripts/members.js.erb index 500e79b25..795387cc4 100644 --- a/app/assets/javascripts/members.js.erb +++ b/app/assets/javascripts/members.js.erb @@ -1,25 +1,24 @@ if (document.getElementById("membermap") !== null) { - mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>"; - mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>"; - mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token; - - L.Icon.Default.imagePath = '/assets' + var mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>"; + var mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>"; + var mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token; + L.Icon.Default.imagePath = '/assets'; $.getJSON(location.pathname + '.json', function(member) { if (member.latitude && member.longitude) { - membermap = L.map('membermap').setView([member.latitude, member.longitude], 4); + var membermap = L.map('membermap').setView([member.latitude, member.longitude], 4); L.tileLayer(mapbox_base_url, { attribution: 'Map data © OpenStreetMap contributors under ODbL | Map imagery © Mapbox', maxZoom: 18 }).addTo(membermap); - marker = new L.Marker(new L.LatLng(member.latitude, member.longitude)); + var marker = new L.Marker(new L.LatLng(member.latitude, member.longitude)); - member_url = "/members/" + member.slug; - member_link = "" + member.login_name + ""; + var member_url = "/members/" + member.slug; + var member_link = "" + member.login_name + ""; - where = "

" + member.location + "

"; + var where = "

" + member.location + "

"; marker.bindPopup(member_link + where).openPopup(); marker.addTo(membermap); From 700073e893d1923d7d75268a86c8f83603856399 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 11:02:22 +1200 Subject: [PATCH 100/267] Removed duplicate gardens/timeline code --- app/controllers/gardens_controller.rb | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index 862a00ba0..69e80f893 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -60,18 +60,6 @@ class GardensController < ApplicationController redirect_to(gardens_by_owner_path(owner: @garden.owner)) end - def timeline - @data = [] - @garden = Garden.find(params[:garden_id]) - @garden.plantings.where.not(planted_at: nil) - .order(finished_at: :desc).each do |p| - # use finished_at if we have it, otherwise use predictions - finish = p.finished_at.presence || p.finish_predicted_at - @data << [p.crop.name, p.planted_at, finish] if finish.present? - end - render json: @data - end - private def garden_params From 2e339ce45d8096eefdf2c90fd2eaaac6aa929ab3 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 11:04:31 +1200 Subject: [PATCH 101/267] Adding rails version to new migrations --- db/migrate/20180118112809_add_datetaken_to_photos.rb | 2 +- db/migrate/20180205000612_remove_shop.rb | 2 +- db/migrate/20180213005731_seed_usage.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/db/migrate/20180118112809_add_datetaken_to_photos.rb b/db/migrate/20180118112809_add_datetaken_to_photos.rb index 42afaf23b..03fae1075 100644 --- a/db/migrate/20180118112809_add_datetaken_to_photos.rb +++ b/db/migrate/20180118112809_add_datetaken_to_photos.rb @@ -1,4 +1,4 @@ -class AddDatetakenToPhotos < ActiveRecord::Migration +class AddDatetakenToPhotos < ActiveRecord::Migration[4.2] def change add_column :photos, :date_taken, :datetime end diff --git a/db/migrate/20180205000612_remove_shop.rb b/db/migrate/20180205000612_remove_shop.rb index fa0fc8793..6977f127b 100644 --- a/db/migrate/20180205000612_remove_shop.rb +++ b/db/migrate/20180205000612_remove_shop.rb @@ -1,4 +1,4 @@ -class RemoveShop < ActiveRecord::Migration +class RemoveShop < ActiveRecord::Migration[4.2] def up drop_table :order_items drop_table :orders diff --git a/db/migrate/20180213005731_seed_usage.rb b/db/migrate/20180213005731_seed_usage.rb index f768451d2..0a94cb71a 100644 --- a/db/migrate/20180213005731_seed_usage.rb +++ b/db/migrate/20180213005731_seed_usage.rb @@ -1,4 +1,4 @@ -class SeedUsage < ActiveRecord::Migration +class SeedUsage < ActiveRecord::Migration[4.2] def change # # seed can be all sown, meaning there is none left add_column(:seeds, :finished, :boolean, default: false) From 7cda0aacc5786d79ca5eca786963cdd27da195ff Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 11:16:50 +1200 Subject: [PATCH 102/267] Passing class_name as string in members.requested_crops --- app/models/member.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/member.rb b/app/models/member.rb index f2427d45d..97f376551 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -20,7 +20,7 @@ class Member < ApplicationRecord has_many :sent_notifications, foreign_key: 'sender_id' has_many :authentications has_many :photos - has_many :requested_crops, class_name: Crop, foreign_key: 'requester_id' + has_many :requested_crops, class_name: 'Crop', foreign_key: 'requester_id' has_many :likes, dependent: :destroy has_many :follows, class_name: "Follow", foreign_key: "follower_id", dependent: :destroy has_many :inverse_follows, class_name: "Follow", foreign_key: "followed_id", dependent: :destroy From 4d21e132b988585a6072e1116df6d8c87d8ea137 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 11:18:56 +1200 Subject: [PATCH 103/267] Timeline is in a different controller now --- app/controllers/gardens_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index 69e80f893..35efaf5d2 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -1,5 +1,5 @@ class GardensController < ApplicationController - before_action :authenticate_member!, except: %i(index show timeline) + before_action :authenticate_member!, except: %i(index show) after_action :expire_homepage, only: %i(create delete) load_and_authorize_resource respond_to :html, :json From 49d3f24ac8b01cd54b8c1de282c25034c186f09a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 11:19:40 +1200 Subject: [PATCH 104/267] [Corrected] Use the -> { ... } lambda literal syntax for single line lambdas. --- spec/controllers/member_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/member_controller_spec.rb b/spec/controllers/member_controller_spec.rb index dada0b013..f4bab7ff8 100644 --- a/spec/controllers/member_controller_spec.rb +++ b/spec/controllers/member_controller_spec.rb @@ -44,12 +44,12 @@ describe MembersController do end it "doesn't show completely nonsense members" do - lambda { get :show, params: { id: 9999 } }.should raise_error(ActiveRecord::RecordNotFound) + -> { get :show, params: { id: 9999 } }.should raise_error(ActiveRecord::RecordNotFound) end it "doesn't show unconfirmed members" do @member2 = FactoryBot.create(:unconfirmed_member) - lambda { get :show, params: { id: @member2.id } }.should raise_error(ActiveRecord::RecordNotFound) + -> { get :show, params: { id: @member2.id } }.should raise_error(ActiveRecord::RecordNotFound) end end From 41ea871c800071d2b66dc9131bb4e1283233f87c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 11:20:28 +1200 Subject: [PATCH 105/267] Comment out comfy admin for now --- config/routes.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/routes.rb b/config/routes.rb index 7ef095562..046c1b261 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -83,7 +83,7 @@ Rails.application.routes.draw do get 'auth/:provider/callback' => 'authentications#create' get 'members/auth/:provider/callback' => 'authentications#create' - comfy_route :cms_admin, path: '/admin/cms' + # comfy_route :cms_admin, path: '/admin/cms' namespace :admin do resources :members end From f061a1d9c7bc19f1e17000e7a38f74f8bb4444ac Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 11:33:43 +1200 Subject: [PATCH 106/267] Allow planting to have null parent_seed --- app/models/planting.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index f985565a7..75dd64fa2 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -23,7 +23,8 @@ class Planting < ApplicationRecord # # Ancestry of food - belongs_to :parent_seed, class_name: 'Seed', foreign_key: 'parent_seed_id' # parent + belongs_to :parent_seed, class_name: 'Seed', foreign_key: 'parent_seed_id', + allow_nil: true # parent has_many :child_seeds, class_name: 'Seed', foreign_key: 'parent_planting_id', dependent: :nullify # children From 84e47b721bf69db68ba8471dc891ce0c1f5affe6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 11:36:16 +1200 Subject: [PATCH 107/267] removed duplicate crop chart methods --- app/controllers/crops_controller.rb | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 67832c9b1..361e28031 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -106,30 +106,8 @@ class CropsController < ApplicationController respond_with @crop end - def sunniness - pie_chart_query 'sunniness' - end - - def planted_from - pie_chart_query 'planted_from' - end - - def harvested_for - @crop = Crop.find(params[:crop_id]) - render json: Harvest.joins(:plant_part).where(crop: @crop) - .group("plant_parts.name").count(:id) - end - private - def pie_chart_query(field) - @crop = Crop.find(params[:crop_id]) - render json: Planting.where(crop: @crop) - .where.not(field.to_sym => nil) - .where.not(field.to_sym => '') - .group(field.to_sym).count(:id) - end - def notifier case @crop.approval_status when "approved" From e43740bd3ddc5465969aa95f10369aa50b97297a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 15:05:46 +1200 Subject: [PATCH 108/267] Two more application name renames --- app/assets/javascripts/crops.js.erb | 4 ++-- app/views/layouts/application.html.haml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/crops.js.erb b/app/assets/javascripts/crops.js.erb index e4ee6d375..cac1804f1 100644 --- a/app/assets/javascripts/crops.js.erb +++ b/app/assets/javascripts/crops.js.erb @@ -1,6 +1,6 @@ function showCropMap(cropmap) { - var mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>"; - var mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>"; + var mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Rails.application.config.mapbox_map_id %>"; + var mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Rails.application.config.mapbox_access_token %>"; var mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token; L.tileLayer(mapbox_base_url, { diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 6eea27068..be43bb0c5 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -28,4 +28,4 @@ \================================================== / Placed at the end of the document so the pages load faster = javascript_include_tag "application" - != Growstuff::Application.config.analytics_code + != Rails.application.config.analytics_code From 6149d203902743e6ded40a0900861c9ea009827a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 15:09:02 +1200 Subject: [PATCH 109/267] Ignore highcharts.js --- .overcommit.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.overcommit.yml b/.overcommit.yml index d7899885f..a38401c1e 100644 --- a/.overcommit.yml +++ b/.overcommit.yml @@ -63,6 +63,7 @@ PreCommit: - 'app/assets/**' - 'spec/javascripts/support/vendor/**' - '**/bootstrap*' + - 'app/assets/javascripts/highcharts.js' command: ['./node_modules/.bin/eslint'] required_executable: 'npm' ScssLint: From 5683f1939d6a0a5c0ee33b160d25daac1a218595 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 15:17:28 +1200 Subject: [PATCH 110/267] Fixed up planting model, parent is not required --- app/models/planting.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/planting.rb b/app/models/planting.rb index 75dd64fa2..7b3c90901 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -24,7 +24,7 @@ class Planting < ApplicationRecord # # Ancestry of food belongs_to :parent_seed, class_name: 'Seed', foreign_key: 'parent_seed_id', - allow_nil: true # parent + required: false # parent has_many :child_seeds, class_name: 'Seed', foreign_key: 'parent_planting_id', dependent: :nullify # children From d19c9ab66996b890594844c4d57c4cf02e6964b3 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 15:30:21 +1200 Subject: [PATCH 111/267] Remove duplicate scripts yield in layout --- app/views/layouts/application.html.haml | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index be43bb0c5..f45392712 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -1,8 +1,6 @@ !!! 5 %html{ lang: "en", prefix: "og: http://ogp.me/ns#" } = yield :scripts - = javascript_include_tag "application" - = yield :script = render partial: "layouts/meta" %body = render partial: "layouts/header" From 91ee0150f1bef12deaeafe8a389419a1409f6abf Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 10:29:10 +1200 Subject: [PATCH 112/267] Adding dependent clauses to models --- app/models/crop.rb | 6 +++--- app/models/member.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 9f1ec6e59..3e8b3981b 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -11,10 +11,10 @@ class Crop < ApplicationRecord has_many :scientific_names, after_add: :update_index, after_remove: :update_index, dependent: :destroy accepts_nested_attributes_for :scientific_names, allow_destroy: true, reject_if: :all_blank has_many :alternate_names, after_add: :update_index, after_remove: :update_index, dependent: :destroy - has_many :plantings + has_many :plantings, dependent: :destroy + has_many :seeds, dependent: :destroy + has_many :harvests, dependent: :destroy has_many :photos, through: :plantings - has_many :seeds - has_many :harvests has_many :plant_parts, -> { distinct.reorder("plant_parts.name") }, through: :harvests belongs_to :creator, class_name: 'Member', optional: true belongs_to :requester, class_name: 'Member', optional: true diff --git a/app/models/member.rb b/app/models/member.rb index 97f376551..72bce256f 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -20,7 +20,7 @@ class Member < ApplicationRecord has_many :sent_notifications, foreign_key: 'sender_id' has_many :authentications has_many :photos - has_many :requested_crops, class_name: 'Crop', foreign_key: 'requester_id' + has_many :requested_crops, class_name: 'Crop', foreign_key: 'requester_id', dependent: :nullify has_many :likes, dependent: :destroy has_many :follows, class_name: "Follow", foreign_key: "follower_id", dependent: :destroy has_many :inverse_follows, class_name: "Follow", foreign_key: "followed_id", dependent: :destroy From 11fd95e2b859371da6452976fc30f2189c8c46bb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 15:45:06 +1200 Subject: [PATCH 113/267] Upgrading rubocop and haml_lint to match hound --- .rubocop.yml | 2 +- Gemfile | 5 ++--- Gemfile.lock | 17 ++++++++--------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 27309055f..9f6c64521 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -12,7 +12,7 @@ AllCops: Rails: Enabled: true -Style/FileName: +Naming/FileName: Exclude: - 'Guardfile' - 'Gemfile' diff --git a/Gemfile b/Gemfile index a6cb43608..42b698280 100644 --- a/Gemfile +++ b/Gemfile @@ -133,13 +133,12 @@ group :development, :test do gem 'faker' gem 'haml-i18n-extractor' gem 'haml-rails' # HTML templating language - gem 'haml_lint' # Checks haml files for goodness + gem 'haml_lint', '>= 0.25.1' # Checks haml files for goodness gem 'i18n-tasks' # adds tests for finding missing and unused translations gem 'poltergeist' # for headless JS testing - gem 'rainbow', '< 2.2.0' # See https://github.com/sickill/rainbow/issues/44 gem 'rspec-activemodel-mocks' gem 'rspec-rails' # unit testing framework - gem 'rubocop' + gem 'rubocop', '>= 0.54.0' gem 'selenium-webdriver' gem 'webrat' # provides HTML matchers for view tests end diff --git a/Gemfile.lock b/Gemfile.lock index cc5af9002..be1b6485e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -180,11 +180,11 @@ GEM haml (>= 4.0.6, < 6.0) html2haml (>= 1.0.1) railties (>= 4.0.1) - haml_lint (0.26.0) + haml_lint (0.27.0) haml (>= 4.0, < 5.1) rainbow rake (>= 10, < 13) - rubocop (>= 0.49.0) + rubocop (>= 0.50.0) sysexits (~> 1.1) hashie (3.5.7) heroics (0.0.24) @@ -348,7 +348,7 @@ GEM method_source rake (>= 0.8.7) thor (>= 0.18.1, < 2.0) - rainbow (2.1.0) + rainbow (3.0.0) raindrops (0.19.0) rake (12.3.1) rb-fsevent (0.10.3) @@ -379,11 +379,11 @@ GEM rspec-mocks (~> 3.7.0) rspec-support (~> 3.7.0) rspec-support (3.7.1) - rubocop (0.49.1) + rubocop (0.54.0) parallel (~> 1.10) - parser (>= 2.3.3.1, < 3.0) + parser (>= 2.5) powerpack (~> 0.1) - rainbow (>= 1.99.1, < 3.0) + rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) ruby-progressbar (1.9.0) @@ -504,7 +504,7 @@ DEPENDENCIES haml haml-i18n-extractor haml-rails - haml_lint + haml_lint (>= 0.25.1) hashie (>= 3.5.3) i18n-tasks jquery-rails @@ -531,12 +531,11 @@ DEPENDENCIES rails-assets-leaflet.markercluster! rails-controller-testing rails_12factor - rainbow (< 2.2.0) rake (>= 10.0.0) responders rspec-activemodel-mocks rspec-rails - rubocop + rubocop (>= 0.54.0) ruby-units sass-rails selenium-webdriver From a00237dfcba285aeaaf930684ca17f2001b973e0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 15:48:16 +1200 Subject: [PATCH 114/267] Style fixes after rubocop upgrade --- Rakefile | 2 +- app/controllers/likes_controller.rb | 4 ++-- app/controllers/robots_controller.rb | 2 +- app/helpers/application_helper.rb | 4 +--- app/helpers/plantings_helper.rb | 4 ++-- app/models/csv_importer.rb | 4 ++-- app/models/garden.rb | 2 +- app/models/harvest.rb | 4 ++-- app/models/member.rb | 4 +--- app/models/photo.rb | 2 +- app/models/planting.rb | 4 +--- bin/bundle | 2 +- bin/setup | 2 +- bin/update | 2 +- bin/yarn | 4 ++-- config/setup_load_paths.rb | 2 +- script/rails | 4 ++-- spec/models/member_spec.rb | 8 ++++---- spec/models/post_spec.rb | 2 +- spec/rails_helper.rb | 2 +- 20 files changed, 29 insertions(+), 35 deletions(-) diff --git a/Rakefile b/Rakefile index 22553c357..15ae3eb68 100755 --- a/Rakefile +++ b/Rakefile @@ -3,6 +3,6 @@ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. require 'rake/dsl_definition' -require File.expand_path('../config/application', __FILE__) +require File.expand_path('config/application', __dir__) Rails.application.load_tasks diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb index 5f7c5dac9..0fdc2f407 100644 --- a/app/controllers/likes_controller.rb +++ b/app/controllers/likes_controller.rb @@ -11,7 +11,7 @@ class LikesController < ApplicationController def destroy @like = Like.find_by(id: params[:id], member: current_member) - return failed(@like, message: 'Unable to unlike') unless @like && @like.destroy + return failed(@like, message: 'Unable to unlike') unless @like&.destroy success(@like, liked_by_member: false, status_code: :ok) end @@ -46,7 +46,7 @@ class LikesController < ApplicationController format.json { render(json: { 'error': message }, status: :forbidden) } format.html do flash[:error] = message - if like && like.likeable + if like&.likeable redirect_to like.likeable else redirect_to root_path diff --git a/app/controllers/robots_controller.rb b/app/controllers/robots_controller.rb index eb846d23d..84f77e906 100644 --- a/app/controllers/robots_controller.rb +++ b/app/controllers/robots_controller.rb @@ -10,6 +10,6 @@ class RobotsController < ApplicationController private def subdomain - request.subdomain.present? ? request.subdomain : nil + request.subdomain.presence end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 4e010cef1..ad63f37e2 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -61,9 +61,7 @@ module ApplicationHelper # http://graph.facebook.com/12345678/picture?width=150&height=150 uri = URI.parse(member.preferred_avatar_uri) - if uri.host == 'graph.facebook.com' - uri.query = "&width=#{size}&height=#{size}" - end + uri.query = "&width=#{size}&height=#{size}" if uri.host == 'graph.facebook.com' # TODO: Assess twitter - https://dev.twitter.com/overview/general/user-profile-images-and-banners # TODO: Assess flickr - https://www.flickr.com/services/api/misc.buddyicons.html diff --git a/app/helpers/plantings_helper.rb b/app/helpers/plantings_helper.rb index f71dc8158..26d0ec6c4 100644 --- a/app/helpers/plantings_helper.rb +++ b/app/helpers/plantings_helper.rb @@ -10,11 +10,11 @@ module PlantingsHelper end def display_planted_from(planting) - planting.planted_from.present? ? planting.planted_from : "not specified" + planting.planted_from.presence || "not specified" end def display_planting_quantity(planting) - planting.quantity.present? ? planting.quantity : "not specified" + planting.quantity.presence || "not specified" end def display_planting(planting) diff --git a/app/models/csv_importer.rb b/app/models/csv_importer.rb index 2f646b6ab..4205a6c13 100644 --- a/app/models/csv_importer.rb +++ b/app/models/csv_importer.rb @@ -9,7 +9,7 @@ class CsvImporter name, en_wikipedia_url, parent_name, scientific_names, alternate_names = row @crop = Crop.find_or_create_by(name: name) - @crop.update_attributes( + @crop.update( en_wikipedia_url: en_wikipedia_url, creator_id: cropbot.id ) @@ -26,7 +26,7 @@ class CsvImporter def add_parent(parent_name) parent = Crop.find_by(name: parent_name) if parent - @crop.update_attributes(parent_id: parent.id) + @crop.update(parent_id: parent.id) else @crop.logger.warn("Warning: parent crop #{parent_name} not found") end diff --git a/app/models/garden.rb b/app/models/garden.rb index 096647035..2946af1cf 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -48,7 +48,7 @@ class Garden < ApplicationRecord after_validation :cleanup_area def cleanup_area - self.area = nil if area && area.zero? + self.area = nil if area&.zero? self.area_unit = nil if area.blank? end diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 60a43ce44..3a96afdbb 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -82,9 +82,9 @@ class Harvest < ApplicationRecord end def cleanup_quantities - self.quantity = nil if quantity && quantity.zero? + self.quantity = nil if quantity&.zero? self.unit = nil if quantity.blank? - self.weight_quantity = nil if weight_quantity && weight_quantity.zero? + self.weight_quantity = nil if weight_quantity&.zero? self.weight_unit = nil if weight_quantity.blank? end diff --git a/app/models/member.rb b/app/models/member.rb index 72bce256f..d0ba369cc 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -157,9 +157,7 @@ class Member < ApplicationRecord nearby_members = [] if place latitude, longitude = Geocoder.coordinates(place, params: { limit: 1 }) - if latitude && longitude - nearby_members = Member.located.sort_by { |x| x.distance_from([latitude, longitude]) } - end + nearby_members = Member.located.sort_by { |x| x.distance_from([latitude, longitude]) } if latitude && longitude end nearby_members end diff --git a/app/models/photo.rb b/app/models/photo.rb index c9c8c6a94..67aac82f3 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -51,7 +51,7 @@ class Photo < ApplicationRecord end def set_flickr_metadata! - update_attributes(flickr_metadata) + update(flickr_metadata) end def to_s diff --git a/app/models/planting.rb b/app/models/planting.rb index 7b3c90901..a4521f6ca 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -95,9 +95,7 @@ class Planting < ApplicationRecord end def expected_lifespan - if planted_at.present? && finished_at.present? - return (finished_at - planted_at).to_i - end + return (finished_at - planted_at).to_i if planted_at.present? && finished_at.present? crop.median_lifespan end diff --git a/bin/bundle b/bin/bundle index 66e9889e8..f19acf5b5 100755 --- a/bin/bundle +++ b/bin/bundle @@ -1,3 +1,3 @@ #!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) load Gem.bin_path('bundler', 'bundle') diff --git a/bin/setup b/bin/setup index 78c4e861d..d5163f8c1 100755 --- a/bin/setup +++ b/bin/setup @@ -4,7 +4,7 @@ require 'fileutils' include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = Pathname.new File.expand_path('..', __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") diff --git a/bin/update b/bin/update index a8e4462f2..32326c74f 100755 --- a/bin/update +++ b/bin/update @@ -4,7 +4,7 @@ require 'fileutils' include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = Pathname.new File.expand_path('..', __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") diff --git a/bin/yarn b/bin/yarn index c2bacef83..ad111a882 100755 --- a/bin/yarn +++ b/bin/yarn @@ -4,8 +4,8 @@ Dir.chdir(VENDOR_PATH) do begin exec "yarnpkg #{ARGV.join(" ")}" rescue Errno::ENOENT - $stderr.puts "Yarn executable was not detected in the system." - $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + warn "Yarn executable was not detected in the system." + warn "Download Yarn at https://yarnpkg.com/en/docs/install" exit 1 end end diff --git a/config/setup_load_paths.rb b/config/setup_load_paths.rb index c1a0f95fd..b78f9aff0 100644 --- a/config/setup_load_paths.rb +++ b/config/setup_load_paths.rb @@ -1,4 +1,4 @@ -if ENV['MY_RUBY_HOME'] && ENV['MY_RUBY_HOME'].include?('rvm') +if ENV['MY_RUBY_HOME']&.include?('rvm') begin require 'rvm' RVM.use_from_path! File.dirname(File.dirname(__FILE__)) diff --git a/script/rails b/script/rails index 9092f9f3c..754b05caa 100755 --- a/script/rails +++ b/script/rails @@ -2,6 +2,6 @@ # This command will automatically be run when you run "rails" # with Rails 3 gems installed from the root of your application. -APP_PATH = File.expand_path('../../config/application', __FILE__) -require File.expand_path('../../config/boot', __FILE__) +APP_PATH = File.expand_path('../config/application', __dir__) +require File.expand_path('../config/boot', __dir__) require 'rails/commands' diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb index e02935d8e..f107ceb7f 100644 --- a/spec/models/member_spec.rb +++ b/spec/models/member_spec.rb @@ -67,22 +67,22 @@ describe 'member' do end it 'has location and lat/long fields' do - member.update_attributes(location: 'Greenwich, UK') + member.update(location: 'Greenwich, UK') member.location.should eq 'Greenwich, UK' member.latitude.round(2).should eq 51.48 member.longitude.round(2).should eq 0.00 end it 'empties the lat/long if location removed' do - member.update_attributes(location: 'Greenwich, UK') - member.update_attributes(location: '') + member.update(location: 'Greenwich, UK') + member.update(location: '') member.location.should eq '' member.latitude.should be_nil member.longitude.should be_nil end it 'fails gracefully for unfound locations' do - member.update_attributes(location: 'Tatooine') + member.update(location: 'Tatooine') member.location.should eq 'Tatooine' member.latitude.should be_nil member.longitude.should be_nil diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index c4fc3d020..7ae50f7f2 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -145,7 +145,7 @@ describe Post do end it "should be updated when post was modified" do - post.update_attributes(body: "[chard](crop)") + post.update(body: "[chard](crop)") expect(post.crops).to eq [chard] expect(chard.posts).to eq [post] diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index e28dd6e24..862b0316d 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -17,7 +17,7 @@ SimpleCov.start :rails do end require 'spec_helper' -require File.expand_path("../../config/environment", __FILE__) +require File.expand_path('../config/environment', __dir__) require 'rspec/rails' # Add additional requires below this line. Rails is not loaded until this point! Rails.application.eager_load! From 0235690f826748463016166c747fc4f823913c84 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 15:58:36 +1200 Subject: [PATCH 115/267] More dependent declared on relationships --- app/models/member.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/models/member.rb b/app/models/member.rb index d0ba369cc..e42d2f11c 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -8,17 +8,17 @@ class Member < ApplicationRecord # # Relationships - has_many :posts, foreign_key: 'author_id' - has_many :comments, foreign_key: 'author_id' - has_many :forums, foreign_key: 'owner_id' - has_many :gardens, foreign_key: 'owner_id' - has_many :plantings, foreign_key: 'owner_id' - has_many :seeds, foreign_key: 'owner_id' - has_many :harvests, foreign_key: 'owner_id' + has_many :posts, foreign_key: 'author_id', dependent: :destroy + has_many :comments, foreign_key: 'author_id', dependent: :destroy + has_many :forums, foreign_key: 'owner_id', dependent: :nullify + has_many :gardens, foreign_key: 'owner_id', dependent: :destroy + has_many :plantings, foreign_key: 'owner_id', dependent: :destroy + has_many :seeds, foreign_key: 'owner_id', dependent: :destroy + has_many :harvests, foreign_key: 'owner_id', dependent: :destroy has_and_belongs_to_many :roles # rubocop:disable Rails/HasAndBelongsToMany has_many :notifications, foreign_key: 'recipient_id' has_many :sent_notifications, foreign_key: 'sender_id' - has_many :authentications + has_many :authentications, dependent: :destroy has_many :photos has_many :requested_crops, class_name: 'Crop', foreign_key: 'requester_id', dependent: :nullify has_many :likes, dependent: :destroy From 5dbb3a1487b79592d277918b05c0cb4d46dcfa89 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 15:59:38 +1200 Subject: [PATCH 116/267] Mark cms specs as pending --- spec/features/cms_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/features/cms_spec.rb b/spec/features/cms_spec.rb index 176c531a8..fa6ace64a 100644 --- a/spec/features/cms_spec.rb +++ b/spec/features/cms_spec.rb @@ -4,13 +4,13 @@ feature "cms admin" do let(:member) { create :member } let(:admin_member) { create :admin_member } - scenario "can't view CMS admin if not signed in" do + pending "can't view CMS admin if not signed in" do visit comfy_admin_cms_path expect(current_path).to eq root_path expect(page).to have_content "Please sign in as an admin user" end - scenario "can't view CMS admin if not an admin member" do + pending "can't view CMS admin if not an admin member" do # sign in as an ordinary member login_as member visit comfy_admin_cms_path @@ -18,7 +18,7 @@ feature "cms admin" do expect(page).to have_content "Please sign in as an admin user" end - scenario "admin members can view CMS admin area" do + pending "admin members can view CMS admin area" do login_as admin_member visit comfy_admin_cms_path expect(current_path).to match(/#{comfy_admin_cms_path}/) # match any CMS admin page From c967f7432e545e258c6011ce5d320a436f2fae8b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 16:04:52 +1200 Subject: [PATCH 117/267] Seed's parent planting is optional --- app/models/seed.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/seed.rb b/app/models/seed.rb index dff707a5c..ff687a4eb 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -14,7 +14,8 @@ class Seed < ApplicationRecord belongs_to :crop belongs_to :owner, class_name: 'Member', foreign_key: 'owner_id', counter_cache: true - belongs_to :parent_planting, class_name: 'Planting', foreign_key: 'parent_planting_id' # parent + belongs_to :parent_planting, class_name: 'Planting', foreign_key: 'parent_planting_id', + required: false # parent has_many :child_plantings, class_name: 'Planting', foreign_key: 'parent_seed_id', dependent: :nullify # children From 7f8bdfe48f4d6c4d13c97a94707b409f8930ded8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 16:09:41 +1200 Subject: [PATCH 118/267] Updated rubocop todo --- .rubocop.yml | 8 ++--- .rubocop_todo.yml | 83 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 11 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 9f6c64521..9a8a0a405 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -62,10 +62,10 @@ Metrics/BlockLength: Metrics/MethodLength: Max: 34 Metrics/AbcSize: - Max: 31 + Max: 30 Metrics/ClassLength: - Max: 182 + Max: 172 Metrics/CyclomaticComplexity: - Max: 11 + Max: 7 Metrics/PerceivedComplexity: - Max: 9 + Max: 8 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 29056f7be..99782950a 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --no-offense-counts` -# on 2018-02-05 14:37:22 +1300 using RuboCop version 0.49.1. +# on 2018-04-02 16:07:34 +1200 using RuboCop version 0.54.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -15,6 +15,13 @@ Lint/HandleExceptions: Exclude: - 'lib/tasks/testing.rake' +# Configuration parameters: MaximumRangeSize. +Lint/MissingCopEnableDirective: + Exclude: + - 'config.rb' + - 'config/compass.rb' + - 'config/initializers/devise.rb' + # Cop supports --auto-correct. # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods. Lint/UnusedMethodArgument: @@ -24,10 +31,51 @@ Lint/UnusedMethodArgument: - 'app/controllers/registrations_controller.rb' - 'app/validators/approved_validator.rb' +Lint/UriEscapeUnescape: + Exclude: + - 'app/helpers/crops_helper.rb' + - 'spec/features/crops/crop_detail_page_spec.rb' + +# Configuration parameters: EnforcedStyle. +# SupportedStyles: lowercase, uppercase +Naming/HeredocDelimiterCase: + Exclude: + - 'config/environments/production.rb' + +# Configuration parameters: Include. +# Include: db/migrate/*.rb +Rails/CreateTableWithTimestamps: + Exclude: + - 'db/migrate/20130214034838_add_members_roles_table.rb' + - 'db/migrate/20130507113915_add_orders_products_table.rb' + - 'db/migrate/20130531110729_add_photos_plantings_table.rb' + - 'db/migrate/20140905001730_add_harvests_photos_table.rb' + - 'db/migrate/20140928044231_add_crops_posts_table.rb' + - 'db/migrate/20150127043022_add_gardens_photos_table.rb' + - 'db/migrate/20150201052245_create_cms.rb' + - 'db/migrate/20161201154922_add_photos_seeds_table.rb' + - 'db/migrate/20171022032108_all_the_predictions.rb' + Rails/FilePath: Exclude: - 'spec/rails_helper.rb' +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/HasManyOrHasOneDependent: + Exclude: + - 'app/models/member.rb' + +# Configuration parameters: Include. +# Include: app/controllers/**/*.rb +Rails/LexicallyScopedActionFilter: + Exclude: + - 'app/controllers/alternate_names_controller.rb' + - 'app/controllers/comments_controller.rb' + - 'app/controllers/gardens_controller.rb' + - 'app/controllers/members_controller.rb' + - 'app/controllers/photos_controller.rb' + Rails/OutputSafety: Exclude: - 'app/helpers/application_helper.rb' @@ -40,7 +88,7 @@ Rails/SkipsModelValidations: Exclude: - 'db/seeds.rb' -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Configuration parameters: EnforcedStyle. # SupportedStyles: strict, flexible Rails/TimeZone: Exclude: @@ -49,31 +97,52 @@ Rails/TimeZone: - 'spec/models/post_spec.rb' # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Configuration parameters: EnforcedStyle. # SupportedStyles: always, conditionals Style/AndOr: Exclude: - 'config/unicorn.rb' - 'lib/tasks/growstuff.rake' -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect, EnforcedStyle. # SupportedStyles: nested, compact Style/ClassAndModuleChildren: Exclude: - 'lib/actions/oauth_signup_action.rb' - 'lib/haml/filters/escaped_markdown.rb' +Style/CommentedKeyword: + Exclude: + - 'lib/tasks/growstuff.rake' + - 'spec/models/crop_spec.rb' + - 'spec/models/photo_spec.rb' + - 'spec/models/planting_spec.rb' + +# Configuration parameters: EnforcedStyle. +# SupportedStyles: annotated, template, unannotated +Style/FormatStringToken: + Exclude: + - 'app/helpers/application_helper.rb' + - 'spec/helpers/application_helper_spec.rb' + Style/IdenticalConditionalBranches: Exclude: - 'app/controllers/follows_controller.rb' +Style/MixinUsage: + Exclude: + - 'bin/setup' + - 'bin/update' + - 'spec/rails_helper.rb' + # Cop supports --auto-correct. Style/MultilineIfModifier: Exclude: - 'spec/rails_helper.rb' # Cop supports --auto-correct. -# Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles. +# Configuration parameters: AutoCorrect, EnforcedStyle. # SupportedStyles: predicate, comparison Style/NumericPredicate: Exclude: @@ -83,7 +152,7 @@ Style/NumericPredicate: - 'lib/tasks/growstuff.rake' # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes. +# Configuration parameters: EnforcedStyle, AllowInnerSlashes. # SupportedStyles: slashes, percent_r, mixed Style/RegexpLiteral: Exclude: @@ -94,7 +163,7 @@ Style/RegexpLiteral: - 'spec/views/posts/index.html.haml_spec.rb' # Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. +# Configuration parameters: EnforcedStyle. # SupportedStyles: single_quotes, double_quotes Style/StringLiteralsInInterpolation: Exclude: From 75e401162ee32ff999db9089ec1cc9e81a21803d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 16:12:40 +1200 Subject: [PATCH 119/267] More dependent declared on relationships --- app/models/crop.rb | 2 +- app/models/forum.rb | 2 +- app/models/member.rb | 10 +++++----- app/models/plant_part.rb | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 3e8b3981b..e41343253 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -19,7 +19,7 @@ class Crop < ApplicationRecord belongs_to :creator, class_name: 'Member', optional: true belongs_to :requester, class_name: 'Member', optional: true belongs_to :parent, class_name: 'Crop', optional: true - has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id' + has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id', dependent: :nullify has_and_belongs_to_many :posts # rubocop:disable Rails/HasAndBelongsToMany ## diff --git a/app/models/forum.rb b/app/models/forum.rb index 2579876ad..7dad73bc2 100644 --- a/app/models/forum.rb +++ b/app/models/forum.rb @@ -3,7 +3,7 @@ class Forum < ApplicationRecord validates :name, presence: true friendly_id :name, use: %i(slugged finders) - has_many :posts + has_many :posts, dependent: :destroy belongs_to :owner, class_name: "Member" def to_s diff --git a/app/models/member.rb b/app/models/member.rb index e42d2f11c..655f3c5aa 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -180,9 +180,9 @@ class Member < ApplicationRecord confirmed_at && will_save_change_to_attribute?(:newsletter) end - def newsletter_subscribe(gb = Gibbon::API.new, testing = false) + def newsletter_subscribe(gibbon = Gibbon::API.new, testing = false) return true if Rails.env.test? && !testing - gb.lists.subscribe( + gibbon.lists.subscribe( id: Rails.application.config.newsletter_list_id, email: { email: email }, merge_vars: { login_name: login_name }, @@ -190,10 +190,10 @@ class Member < ApplicationRecord ) end - def newsletter_unsubscribe(gb = Gibbon::API.new, testing = false) + def newsletter_unsubscribe(gibbon = Gibbon::API.new, testing = false) return true if Rails.env.test? && !testing - gb.lists.unsubscribe(id: Rails.application.config.newsletter_list_id, - email: { email: email }) + gibbon.lists.unsubscribe(id: Rails.application.config.newsletter_list_id, + email: { email: email }) end def already_following?(member) diff --git a/app/models/plant_part.rb b/app/models/plant_part.rb index bbdbae8d2..4cebaf79d 100644 --- a/app/models/plant_part.rb +++ b/app/models/plant_part.rb @@ -2,7 +2,7 @@ class PlantPart < ApplicationRecord extend FriendlyId friendly_id :name, use: %i(slugged finders) - has_many :harvests + has_many :harvests, dependent: :destroy has_many :crops, -> { distinct }, through: :harvests def to_s From 59cca1b8cb32836cdff0c349a020976af7e228dc Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 16:18:46 +1200 Subject: [PATCH 120/267] Upgraded controller specs for rails 5 --- ..._controller_spec => crops_controller_spec.rb} | 6 +++--- .../charts/gardens_controller_spec.rb | 4 ++-- spec/controllers/crops_controller_spec.rb | 16 ---------------- spec/controllers/gardens_controller_spec.rb | 9 --------- spec/controllers/plantings_controller_spec.rb | 2 +- spec/controllers/seeds_controller_spec.rb | 2 +- 6 files changed, 7 insertions(+), 32 deletions(-) rename spec/controllers/charts/{crops_controller_spec => crops_controller_spec.rb} (64%) diff --git a/spec/controllers/charts/crops_controller_spec b/spec/controllers/charts/crops_controller_spec.rb similarity index 64% rename from spec/controllers/charts/crops_controller_spec rename to spec/controllers/charts/crops_controller_spec.rb index 5a4aa6548..f487d4d37 100644 --- a/spec/controllers/charts/crops_controller_spec +++ b/spec/controllers/charts/crops_controller_spec.rb @@ -4,15 +4,15 @@ describe Charts::CropsController do describe 'GET charts' do let(:crop) { FactoryBot.create :crop } describe 'sunniness' do - before { get :sunniness, crop_id: crop.to_param } + before { get :sunniness, params: { crop_id: crop.to_param } } it { expect(response).to be_success } end describe 'planted_from' do - before { get :planted_from, crop_id: crop.to_param } + before { get :planted_from, params: { crop_id: crop.to_param } } it { expect(response).to be_success } end describe 'harvested_for' do - before { get :harvested_for, crop_id: crop.to_param } + before { get :harvested_for, params: { crop_id: crop.to_param } } it { expect(response).to be_success } end end diff --git a/spec/controllers/charts/gardens_controller_spec.rb b/spec/controllers/charts/gardens_controller_spec.rb index daa50a811..4230328d9 100644 --- a/spec/controllers/charts/gardens_controller_spec.rb +++ b/spec/controllers/charts/gardens_controller_spec.rb @@ -7,7 +7,7 @@ describe Charts::GardensController do let(:garden) { FactoryBot.create :garden } context "when not signed in" do describe 'GET timeline' do - before { get :timeline, garden_id: garden.to_param } + before { get :timeline, params: { garden_id: garden.to_param } } it { expect(response).to be_success } end end @@ -16,7 +16,7 @@ describe Charts::GardensController do let!(:member) { FactoryBot.create(:member) } describe 'GET timeline' do - before { get :timeline, garden_id: garden.to_param } + before { get :timeline, params: { garden_id: garden.to_param } } it { expect(response).to be_success } end end diff --git a/spec/controllers/crops_controller_spec.rb b/spec/controllers/crops_controller_spec.rb index 9e54307bf..5b682f6c2 100644 --- a/spec/controllers/crops_controller_spec.rb +++ b/spec/controllers/crops_controller_spec.rb @@ -46,20 +46,4 @@ describe CropsController do it { expect(response.content_type).to eq("application/rss+xml") } end end - - describe 'GET charts' do - let(:crop) { FactoryBot.create :crop } - describe 'sunniness' do - before { get :sunniness, crop_id: crop.to_param } - it { expect(response).to be_success } - end - describe 'planted_from' do - before { get :planted_from, crop_id: crop.to_param } - it { expect(response).to be_success } - end - describe 'harvested_for' do - before { get :harvested_for, crop_id: crop.to_param } - it { expect(response).to be_success } - end - end end diff --git a/spec/controllers/gardens_controller_spec.rb b/spec/controllers/gardens_controller_spec.rb index 22476bec6..931453907 100644 --- a/spec/controllers/gardens_controller_spec.rb +++ b/spec/controllers/gardens_controller_spec.rb @@ -14,10 +14,6 @@ RSpec.describe GardensController, type: :controller do before { put :create, params: { garden: valid_params } } it { expect(response).to redirect_to(new_member_session_path) } end - describe 'GET timeline' do - before { get :timeline, garden_id: garden.to_param } - it { expect(response).to be_success } - end describe 'changing existing records' do before do allow(Garden).to receive(:find).and_return(:garden) @@ -46,11 +42,6 @@ RSpec.describe GardensController, type: :controller do let!(:member) { FactoryBot.create(:member) } - describe 'GET timeline' do - before { get :timeline, garden_id: garden.to_param } - it { expect(response).to be_success } - end - describe "for another member's garden" do let(:not_my_garden) { double('garden') } diff --git a/spec/controllers/plantings_controller_spec.rb b/spec/controllers/plantings_controller_spec.rb index 8567a3386..8a0d5c7dc 100644 --- a/spec/controllers/plantings_controller_spec.rb +++ b/spec/controllers/plantings_controller_spec.rb @@ -87,7 +87,7 @@ describe PlantingsController do context 'with parent seed' do let(:seed) { FactoryBot.create :seed, owner: member } - before { get :new, seed_id: seed.to_param } + before { get :new, params: { seed_id: seed.to_param } } it { expect(assigns(:seed)).to eq(seed) } end end diff --git a/spec/controllers/seeds_controller_spec.rb b/spec/controllers/seeds_controller_spec.rb index 3ff8051f1..0a5fe45b4 100644 --- a/spec/controllers/seeds_controller_spec.rb +++ b/spec/controllers/seeds_controller_spec.rb @@ -22,7 +22,7 @@ describe SeedsController do context 'with parent planting' do let(:planting) { FactoryBot.create :planting, owner: owner } - before { get :new, planting_id: planting.to_param } + before { get :new, params: { planting_id: planting.to_param } } it { expect(assigns(:planting)).to eq(planting) } end end From af0c9a490b3ea58d41fcdbb29964c6df40fbd6eb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 2 Apr 2018 16:28:34 +1200 Subject: [PATCH 121/267] Redirect :back deprecated. updating follows controller --- app/controllers/follows_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/follows_controller.rb b/app/controllers/follows_controller.rb index 2c4b2daab..b97eb9e2b 100644 --- a/app/controllers/follows_controller.rb +++ b/app/controllers/follows_controller.rb @@ -9,10 +9,10 @@ class FollowsController < ApplicationController if @follow.save flash[:notice] = "Followed #{@follow.followed.login_name}" - redirect_to :back + redirect_back fallback_location: root_path else flash[:error] = "Already following or error while following." - redirect_to :back + redirect_back fallback_location: root_path end end From 90f8b9e042a31b4f882220b171608a04bb7a537d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 28 Apr 2018 21:30:08 +1200 Subject: [PATCH 122/267] Fixed last crop spec for rails5 ugprade --- app/models/crop.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index a099e8c64..84c69a30f 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -15,7 +15,7 @@ class Crop < ApplicationRecord has_many :seeds, dependent: :destroy has_many :harvests, dependent: :destroy has_many :photos, through: :plantings - has_many :plant_parts, -> { uniq.reorder("plant_parts.name") }, through: :harvests + has_many :plant_parts, -> { distinct.order("plant_parts.name") }, through: :harvests belongs_to :creator, class_name: 'Member', optional: true belongs_to :requester, class_name: 'Member', optional: true belongs_to :parent, class_name: 'Crop', optional: true From 9cfdb93aa3dd521225fe003048a1efe2321c75c8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 28 Apr 2018 21:35:00 +1200 Subject: [PATCH 123/267] Remove some old currency methods from application helper Conflicts: app/helpers/application_helper.rb --- app/helpers/application_helper.rb | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index dad3eab2b..7388445d5 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,26 +1,9 @@ module ApplicationHelper - def price_in_dollars(price) - format('%.2f', price / 100.0) - end - - # 999 cents becomes 9.99 AUD -- for products/orders/etc - def price_with_currency(price) - format('%.2f %s', price / 100.0, Rails.application.config.currency) - end - def parse_date(str) str ||= '' # Date.parse barfs on nil str == '' ? nil : Date.parse(str) end - def forex_link(price) - pid = price_in_dollars(price) - currency = Rails.application.config.currency - link = "http://www.wolframalpha.com/input/?i=#{pid}+#{currency}" - - link_to "(convert)", link, target: "_blank", rel: "noopener noreferrer" - end - def build_alert_classes(alert_type = :info) classes = 'alert alert-dismissable ' case alert_type.to_sym From cd910e74bcf89a6ccaf6aed60021a1dd83961842 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 28 Apr 2018 22:05:50 +1200 Subject: [PATCH 124/267] Don't need to throw exception on planting save error --- app/controllers/plantings_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index 192663c2e..fc3db888b 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -56,7 +56,7 @@ class PlantingsController < ApplicationController @planting = Planting.new(planting_params) @planting.owner = current_member @planting.crop = @planting.parent_seed.crop if @planting.parent_seed.present? - @planting.save! + @planting.save respond_with @planting end From 1bbf0a3c18ec283a1331f18f4301dc0f6d290cd9 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 28 Apr 2018 22:11:02 +1200 Subject: [PATCH 125/267] Simplifying show_inactive_tickbox_path method --- app/helpers/application_helper.rb | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7388445d5..ca4bc9429 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -67,16 +67,12 @@ module ApplicationHelper def show_inactive_tickbox_path(type, owner, show_all) all = show_all ? '' : 1 if owner - if type == 'plantings' - plantings_by_owner_path(owner: owner.slug, all: all) - elsif type == 'gardens' - gardens_by_owner_path(owner: owner.slug, all: all) - end - elsif type == 'plantings' - plantings_path(all: all) - elsif type == 'gardens' - gardens_path(all: all) + return plantings_by_owner_path(owner: owner.slug, all: all) if type == 'plantings' + return gardens_by_owner_path(owner: owner.slug, all: all) if type == 'gardens' end + + return plantings_path(all: all) if type == 'plantings' + return gardens_path(all: all) if type == 'gardens' end def title(type, owner, crop, planting) From 4e6ffc1a63d06f246ff837ee1514a6b509ae05f4 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 28 Apr 2018 22:21:35 +1200 Subject: [PATCH 126/267] Removed spec for currency helpers --- spec/helpers/application_helper_spec.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index dcc5e6145..d1eae5cf6 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -1,11 +1,6 @@ require 'rails_helper' describe ApplicationHelper do - it "formats prices" do - price_in_dollars(999).should eq '9.99' - price_with_currency(999).should eq format('9.99 %s', Rails.application.config.currency) - end - it "parses dates" do parse_date(nil).should eq nil parse_date('').should eq nil From cc838e19b5239b62803503a3c48e1d7d93b54e20 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 10:59:34 +1200 Subject: [PATCH 127/267] Show a 404 page on record not found --- app/controllers/application_controller.rb | 6 ++++ app/views/errors/404.html | 34 +++++++++++++++++++++++ app/views/errors/422.html | 34 +++++++++++++++++++++++ app/views/errors/500.html | 33 ++++++++++++++++++++++ 4 files changed, 107 insertions(+) create mode 100644 app/views/errors/404.html create mode 100644 app/views/errors/422.html create mode 100644 app/views/errors/500.html diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3e6221d06..eb775ee4a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -6,6 +6,8 @@ class ApplicationController < ActionController::Base after_action :store_location before_action :set_locale + rescue_from ActiveRecord::RecordNotFound, with: :not_found + # CanCan error handling def store_location unless request.path.in?(["/members/sign_in", "/members/sign_up", @@ -17,6 +19,10 @@ class ApplicationController < ActionController::Base end end + def not_found + render file: 'app/views/errors/404', status: :not_found, layout: false + end + def after_sign_in_path_for(resource) stored_location_for(:member) || root_path end diff --git a/app/views/errors/404.html b/app/views/errors/404.html new file mode 100644 index 000000000..9345cf4a2 --- /dev/null +++ b/app/views/errors/404.html @@ -0,0 +1,34 @@ + + + + + + The page you were looking for doesn't exist (404) + + + + + +
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+ + diff --git a/app/views/errors/422.html b/app/views/errors/422.html new file mode 100644 index 000000000..afc8eb76b --- /dev/null +++ b/app/views/errors/422.html @@ -0,0 +1,34 @@ + + + + + + The change you wanted was rejected (422) + + + + + +
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+ + diff --git a/app/views/errors/500.html b/app/views/errors/500.html new file mode 100644 index 000000000..af1052613 --- /dev/null +++ b/app/views/errors/500.html @@ -0,0 +1,33 @@ + + + + + + We're sorry, but something went wrong (500) + + + + + +
+

We're sorry, but something went wrong.

+
+ + From 02c5571a9a10f880b92c13184126d7cfc0c5571b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 11:38:15 +1200 Subject: [PATCH 128/267] Notifications need sender and reciever in factory --- spec/factories/notifications.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/factories/notifications.rb b/spec/factories/notifications.rb index b893fcc1b..8b6867a46 100644 --- a/spec/factories/notifications.rb +++ b/spec/factories/notifications.rb @@ -2,8 +2,8 @@ FactoryBot.define do factory :notification, aliases: [:message] do - sender - recipient + sender { FactoryBot.create :member } + recipient { FactoryBot.create :member } subject "MyString" body "MyText" read false From 6913233596b47102204860e916cc2a01bc021af3 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 11:39:22 +1200 Subject: [PATCH 129/267] Use factorybot in more tests --- spec/features/signin_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb index acd9f5295..82bec2068 100644 --- a/spec/features/signin_spec.rb +++ b/spec/features/signin_spec.rb @@ -1,10 +1,10 @@ require 'rails_helper' feature "signin", js: true do - let(:member) { create :member } - let(:recipient) { create :member } - let(:wrangler) { create :crop_wrangling_member } - let(:notification) { create :notification } + let(:member) { FactoryBot.create :member } + let(:recipient) { FactoryBot.create :member } + let(:wrangler) { FactoryBot.create :crop_wrangling_member } + let(:notification) { FactoryBot.create :notification } def login fill_in 'Login', with: member.login_name From b898d83d214d12d466552e754846a71636a7f189 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 11:49:30 +1200 Subject: [PATCH 130/267] Fix up notification redirect spec --- app/controllers/notifications_controller.rb | 2 +- spec/features/signin_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index 7c3c1f322..bbab48b43 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -20,7 +20,7 @@ class NotificationsController < ApplicationController def new @notification = Notification.new - @recipient = Member.find_by(id: params[:recipient_id]) + @recipient = Member.find_by(id: params[:recipient]) @subject = params[:subject] || "" end diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb index 82bec2068..e992d14e7 100644 --- a/spec/features/signin_spec.rb +++ b/spec/features/signin_spec.rb @@ -4,7 +4,7 @@ feature "signin", js: true do let(:member) { FactoryBot.create :member } let(:recipient) { FactoryBot.create :member } let(:wrangler) { FactoryBot.create :crop_wrangling_member } - let(:notification) { FactoryBot.create :notification } + let(:notification) { FactoryBot.create :notification, recipient: recipient } def login fill_in 'Login', with: member.login_name @@ -56,7 +56,7 @@ feature "signin", js: true do end scenario "after signin, redirect to new notifications page" do - visit new_notification_path(recipient: recipient) + visit new_notification_path(recipient: recipient.id) expect(current_path).to eq new_member_session_path login expect(current_path).to eq new_notification_path From a221f10113663c25a679c525e42dc45cefcf7749 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 12:03:11 +1200 Subject: [PATCH 131/267] Move photos owner validation to models --- app/controllers/photos_controller.rb | 2 +- app/models/photographing.rb | 8 ++++++++ spec/controllers/photos_controller_spec.rb | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 57b10e5d8..c9dd8886f 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -79,7 +79,7 @@ class PhotosController < ApplicationController raise "No item type provided" if item_type.nil? item_class = item_type.capitalize raise "Photos not supported" unless Photo::PHOTO_CAPABLE.include? item_class - item_class.constantize.find_by!(id: params[:id], owner_id: current_member.id) + item_class.constantize.find(params[:id]) end # diff --git a/app/models/photographing.rb b/app/models/photographing.rb index 5d1ab1073..e8999db43 100644 --- a/app/models/photographing.rb +++ b/app/models/photographing.rb @@ -2,6 +2,8 @@ class Photographing < ApplicationRecord belongs_to :photo belongs_to :photographable, polymorphic: true + validate :photo_and_item_have_same_owner + def self.item(item_id, item_type) find_by!(photographable_id: item_id, photographable_type: item_type).photographable end @@ -9,4 +11,10 @@ class Photographing < ApplicationRecord def item find_by!(photographable_id: photographable_id, photographable_type: photographable_type).photographable end + + private + + def photo_and_item_have_same_owner + errors.add(:photo, "must have same owner as item it links to") unless photographable.owner == photo.owner + end end diff --git a/spec/controllers/photos_controller_spec.rb b/spec/controllers/photos_controller_spec.rb index 41c43f572..a7cf6acb6 100644 --- a/spec/controllers/photos_controller_spec.rb +++ b/spec/controllers/photos_controller_spec.rb @@ -163,7 +163,7 @@ describe PhotosController do post :create, params: { photo: { flickr_photo_id: photo.flickr_photo_id }, type: "planting", id: another_planting.id } - end.to raise_error(ActiveRecord::RecordNotFound) + end.to raise_error(ActiveRecord::RecordInvalid) Photo.last.plantings.first.should_not eq another_planting end @@ -174,7 +174,7 @@ describe PhotosController do post :create, params: { photo: { flickr_photo_id: photo.flickr_photo_id }, type: "harvest", id: another_harvest.id } - end.to raise_error(ActiveRecord::RecordNotFound) + end.to raise_error(ActiveRecord::RecordInvalid) Photo.last.harvests.first.should_not eq another_harvest end end From 127b72b2790a01bdaf58827688b6284503736e2b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 12:09:31 +1200 Subject: [PATCH 132/267] Updated spec to look for 404 page instead of exception --- spec/controllers/member_controller_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spec/controllers/member_controller_spec.rb b/spec/controllers/member_controller_spec.rb index f4bab7ff8..8e6b91283 100644 --- a/spec/controllers/member_controller_spec.rb +++ b/spec/controllers/member_controller_spec.rb @@ -44,12 +44,14 @@ describe MembersController do end it "doesn't show completely nonsense members" do - -> { get :show, params: { id: 9999 } }.should raise_error(ActiveRecord::RecordNotFound) + get :show, params: { id: 9999 } + expect(response).to have_http_status(:not_found) end it "doesn't show unconfirmed members" do @member2 = FactoryBot.create(:unconfirmed_member) - -> { get :show, params: { id: @member2.id } }.should raise_error(ActiveRecord::RecordNotFound) + get :show, params: { id: @member2.id } + expect(response).to have_http_status(:not_found) end end From a590b89302dd65df53cec38d42b14cbe63cc2dd3 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 12:21:19 +1200 Subject: [PATCH 133/267] Photos in spec needs to have same owner as item they link to --- app/controllers/notifications_controller.rb | 2 +- .../photo_associations_controller.rb | 2 + app/models/photographing.rb | 2 +- app/models/planting.rb | 2 +- .../notifications_controller_spec.rb | 2 +- .../photo_associations_controller_spec.rb | 8 ++- spec/features/home/home_spec.rb | 4 +- spec/features/photos/show_photo_spec.rb | 6 +- spec/helpers/photos_helper_spec.rb | 15 ++-- spec/models/crop_spec.rb | 57 +++++++-------- spec/models/garden_spec.rb | 34 ++++----- spec/models/harvest_spec.rb | 49 +++++++------ spec/models/photo_spec.rb | 6 +- spec/models/planting_spec.rb | 71 ++++++++----------- spec/models/seed_spec.rb | 4 +- spec/views/crops/index.html.haml_spec.rb | 2 +- 16 files changed, 133 insertions(+), 133 deletions(-) diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb index bbab48b43..7c3c1f322 100644 --- a/app/controllers/notifications_controller.rb +++ b/app/controllers/notifications_controller.rb @@ -20,7 +20,7 @@ class NotificationsController < ApplicationController def new @notification = Notification.new - @recipient = Member.find_by(id: params[:recipient]) + @recipient = Member.find_by(id: params[:recipient_id]) @subject = params[:subject] || "" end diff --git a/app/controllers/photo_associations_controller.rb b/app/controllers/photo_associations_controller.rb index 126aaf9b3..c63cca398 100644 --- a/app/controllers/photo_associations_controller.rb +++ b/app/controllers/photo_associations_controller.rb @@ -11,6 +11,8 @@ class PhotoAssociationsController < ApplicationController respond_with(@photo) end + private + def item_class params[:type].capitalize end diff --git a/app/models/photographing.rb b/app/models/photographing.rb index e8999db43..040817611 100644 --- a/app/models/photographing.rb +++ b/app/models/photographing.rb @@ -15,6 +15,6 @@ class Photographing < ApplicationRecord private def photo_and_item_have_same_owner - errors.add(:photo, "must have same owner as item it links to") unless photographable.owner == photo.owner + errors.add(:photo, "must have same owner as item it links to") unless photographable.owner_id == photo.owner_id end end diff --git a/app/models/planting.rb b/app/models/planting.rb index 144d3ee42..f6966d94f 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -29,7 +29,7 @@ class Planting < ApplicationRecord ## ## Scopes default_scope { joins(:owner) } # Ensures the owner still exists - scope :interesting, -> { has_photos.one_per_owner } + scope :interesting, -> { has_photos.one_per_owner.order(planted_at: :desc) } scope :recent, -> { order(created_at: :desc) } scope :one_per_owner, lambda { joins("JOIN members m ON (m.id=plantings.owner_id) diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb index a7ed81ae5..30cf37ddd 100644 --- a/spec/controllers/notifications_controller_spec.rb +++ b/spec/controllers/notifications_controller_spec.rb @@ -76,7 +76,7 @@ describe NotificationsController do it "assigns a recipient" do @recipient = FactoryBot.create(:member) get :new, params: { recipient_id: @recipient.id } - assigns(:recipient).should be_an_instance_of(Member) + expect(assigns(:recipient)).to be_an_instance_of(Member) end end diff --git a/spec/controllers/photo_associations_controller_spec.rb b/spec/controllers/photo_associations_controller_spec.rb index bbac961fa..ffde9e1e3 100644 --- a/spec/controllers/photo_associations_controller_spec.rb +++ b/spec/controllers/photo_associations_controller_spec.rb @@ -24,7 +24,7 @@ describe PhotoAssociationsController do end describe "another member's harvest from another member's photo" do - let(:harvest) { FactoryBot.create :harvest } + let(:harvest) { FactoryBot.create :harvest, owner: photo.owner } let(:photo) { FactoryBot.create :photo } it do @@ -36,7 +36,11 @@ describe PhotoAssociationsController do end end.not_to change(photo.harvests, :count) end - it { expect { delete :destroy, params: valid_params }.to raise_error(ActiveRecord::RecordNotFound) } + + it do + delete :destroy, params: valid_params + expect(response).to have_http_response(:not_found) + end end end end diff --git a/spec/features/home/home_spec.rb b/spec/features/home/home_spec.rb index 4137b5e5a..ebbcb9fcb 100644 --- a/spec/features/home/home_spec.rb +++ b/spec/features/home/home_spec.rb @@ -2,8 +2,8 @@ require 'rails_helper' feature "home page" do let(:member) { FactoryBot.create :member } - # let(:seed_photo) { FactoryBot.create :photo } - let(:photo) { FactoryBot.create :photo } + + let(:photo) { FactoryBot.create :photo, owner: member } let(:crop) { FactoryBot.create :crop, created_at: 1.day.ago } let(:planting) { FactoryBot.create :planting, owner: member, crop: crop } diff --git a/spec/features/photos/show_photo_spec.rb b/spec/features/photos/show_photo_spec.rb index bac25b370..2fa9d7119 100644 --- a/spec/features/photos/show_photo_spec.rb +++ b/spec/features/photos/show_photo_spec.rb @@ -1,8 +1,6 @@ require 'rails_helper' feature "show photo page" do - let(:photo) { create :photo } - context "signed in member" do let(:member) { create :member } @@ -10,6 +8,7 @@ feature "show photo page" do context "linked to planting" do let(:planting) { create :planting } + let(:photo) { create :photo, owner: planting.owner } scenario "shows linkback to planting" do planting.photos << photo @@ -20,6 +19,7 @@ feature "show photo page" do end context "linked to harvest" do + let(:photo) { create :photo, owner: harvest.owner } let(:harvest) { create :harvest } scenario "shows linkback to harvest" do @@ -30,6 +30,7 @@ feature "show photo page" do end context "linked to garden" do + let(:photo) { create :photo, owner: garden.owner } let(:garden) { create :garden } scenario "shows linkback to garden" do @@ -40,6 +41,7 @@ feature "show photo page" do end context "linked to seed" do + let(:photo) { create :photo, owner: seed.owner } let(:seed) { create :seed } scenario "shows linkback to seed" do diff --git a/spec/helpers/photos_helper_spec.rb b/spec/helpers/photos_helper_spec.rb index 589cf8104..6a17ae4fd 100644 --- a/spec/helpers/photos_helper_spec.rb +++ b/spec/helpers/photos_helper_spec.rb @@ -4,13 +4,14 @@ describe PhotosHelper do let(:crop) { FactoryBot.create :crop } let(:garden) { FactoryBot.create :garden } - let(:garden_photo) { FactoryBot.create(:photo, thumbnail_url: 'garden.jpg') } - let(:planting) { FactoryBot.create :planting, crop: crop } - let(:planting_photo) { FactoryBot.create(:photo, thumbnail_url: 'planting.jpg') } - let(:harvest) { FactoryBot.create :harvest, crop: crop } - let(:harvest_photo) { FactoryBot.create(:photo, thumbnail_url: 'harvest.jpg') } - let(:seed) { FactoryBot.create :seed, crop: crop } - let(:seed_photo) { FactoryBot.create(:photo, thumbnail_url: 'seed.jpg') } + + let(:garden_photo) { FactoryBot.create(:photo, thumbnail_url: 'garden.jpg', owner: garden.owner) } + let(:planting) { FactoryBot.create :planting, crop: crop, owner: garden.owner } + let(:planting_photo) { FactoryBot.create(:photo, thumbnail_url: 'planting.jpg', owner: garden.owner) } + let(:harvest) { FactoryBot.create :harvest, crop: crop, owner: garden.owner } + let(:harvest_photo) { FactoryBot.create(:photo, thumbnail_url: 'harvest.jpg', owner: garden.owner) } + let(:seed) { FactoryBot.create :seed, crop: crop, owner: garden.owner } + let(:seed_photo) { FactoryBot.create(:photo, thumbnail_url: 'seed.jpg', owner: garden.owner) } describe "crops" do subject { crop_image_path(crop) } diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index 3f49a249d..415cf922a 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -55,26 +55,26 @@ describe Crop do end it "sorts by most plantings" do - Crop.popular.first.should eq maize + expect(Crop.popular.first).to eq maize FactoryBot.create_list(:planting, 10, crop: tomato) - Crop.popular.first.should eq tomato + expect(Crop.popular.first).to eq tomato end end it 'finds a default scientific name' do @crop = FactoryBot.create(:tomato) - @crop.default_scientific_name.should eq nil + expect(@crop.default_scientific_name).to eq nil @sn = FactoryBot.create(:solanum_lycopersicum, crop: @crop) @crop.reload - @crop.default_scientific_name.should eq @sn.name + expect(@crop.default_scientific_name).to eq @sn.name end it 'counts plantings' do @crop = FactoryBot.create(:tomato) - @crop.plantings.size.should eq 0 + expect(@crop.plantings.size).to eq 0 @planting = FactoryBot.create(:planting, crop: @crop) @crop.reload - @crop.plantings.size.should eq 1 + expect(@crop.plantings.size).to eq 1 end context "wikipedia url" do @@ -127,14 +127,14 @@ describe Crop do it 'has a crop hierarchy' do @tomato = FactoryBot.create(:tomato) @roma = FactoryBot.create(:roma, parent_id: @tomato.id) - @roma.parent.should eq @tomato - @tomato.varieties.should eq [@roma] + expect(@roma.parent).to eq @tomato + expect(@tomato.varieties).to eq [@roma] end it 'toplevel scope works' do @tomato = FactoryBot.create(:tomato) @roma = FactoryBot.create(:roma, parent_id: @tomato.id) - Crop.toplevel.should eq [@tomato] + expect(Crop.toplevel).to eq [@tomato] end end @@ -145,13 +145,13 @@ describe Crop do context 'with a planting photo' do before :each do @planting = FactoryBot.create(:planting, crop: @crop) - @photo = FactoryBot.create(:photo) + @photo = FactoryBot.create(:photo, owner: @planting.owner) @planting.photos << @photo end it 'has a default photo' do @crop.default_photo.should be_an_instance_of Photo - @crop.default_photo.id.should eq @photo.id + expect(@crop.default_photo.id).to eq @photo.id end it 'is found in has_photos scope' do @@ -162,31 +162,31 @@ describe Crop do context 'with a harvest photo' do before :each do @harvest = FactoryBot.create(:harvest, crop: @crop) - @photo = FactoryBot.create(:photo) + @photo = FactoryBot.create(:photo, owner: @harvest.owner) @harvest.photos << @photo end it 'has a default photo' do @crop.default_photo.should be_an_instance_of Photo - @crop.default_photo.id.should eq @photo.id + expect(@crop.default_photo.id).to eq @photo.id end context 'and planting photo' do before :each do @planting = FactoryBot.create(:planting, crop: @crop) - @planting_photo = FactoryBot.create(:photo) + @planting_photo = FactoryBot.create(:photo, owner: @planting.owner) @planting.photos << @planting_photo end it 'should prefer the planting photo' do - @crop.default_photo.id.should eq @planting_photo.id + expect(@crop.default_photo.id).to eq @planting_photo.id end end end context 'with no plantings or harvests' do it 'has no default photo' do - @crop.default_photo.should eq nil + expect(@crop.default_photo).to eq nil end end end @@ -285,14 +285,15 @@ describe Crop do let(:crop1_planting) { crop1.plantings.first } let(:crop2_planting) { crop2.plantings.first } + let(:member) { FactoryBot.create :member, login_name: 'pikachu' } describe 'lists interesting crops' do before do # they need 3+ plantings each to be interesting - FactoryBot.create_list(:planting, 3, crop: crop1) - FactoryBot.create_list(:planting, 3, crop: crop2) + FactoryBot.create_list(:planting, 3, crop: crop1, owner: member) + FactoryBot.create_list(:planting, 3, crop: crop2, owner: member) # crops need 3+ photos to be interesting - crop1_planting.photos = FactoryBot.create_list :photo, 3 - crop2_planting.photos = FactoryBot.create_list :photo, 3 + crop1_planting.photos = FactoryBot.create_list :photo, 3, owner: member + crop2_planting.photos = FactoryBot.create_list :photo, 3, owner: member end it { is_expected.to include crop1 } @@ -303,9 +304,9 @@ describe Crop do describe 'crops without plantings are not interesting' do before do # only crop1 has plantings - FactoryBot.create_list(:planting, 3, crop: crop1) + FactoryBot.create_list(:planting, 3, crop: crop1, owner: member) # ... and photos - crop1_planting.photos = FactoryBot.create_list(:photo, 3) + crop1_planting.photos = FactoryBot.create_list(:photo, 3, owner: member) end it { is_expected.to include crop1 } it { is_expected.not_to include crop2 } @@ -315,11 +316,11 @@ describe Crop do describe 'crops without photos are not interesting' do before do # both crops have plantings - FactoryBot.create_list(:planting, 3, crop: crop1) - FactoryBot.create_list(:planting, 3, crop: crop2) + FactoryBot.create_list(:planting, 3, crop: crop1, owner: member) + FactoryBot.create_list(:planting, 3, crop: crop2, owner: member) # but only crop1 has photos - crop1_planting.photos = FactoryBot.create_list(:photo, 3) + crop1_planting.photos = FactoryBot.create_list(:photo, 3, owner: member) end it { is_expected.to include crop1 } it { is_expected.not_to include crop2 } @@ -347,7 +348,7 @@ describe Crop do @pp1 = FactoryBot.create(:plant_part) @h1 = FactoryBot.create(:harvest, crop: @maize, plant_part: @pp1) @h2 = FactoryBot.create(:harvest, crop: @maize, plant_part: @pp1) - @maize.plant_parts.should eq [@pp1] + expect(@maize.plant_parts).to eq [@pp1] end context "search", :elasticsearch do @@ -356,10 +357,10 @@ describe Crop do before { sync_elasticsearch([mushroom]) } it "finds exact matches" do - Crop.search('mushroom').should eq [mushroom] + expect(Crop.search('mushroom')).to eq [mushroom] end it "finds approximate matches" do - Crop.search('mush').should eq [mushroom] + expect(Crop.search('mush')).to eq [mushroom] end it "doesn't find non-matches" do Crop.search('mush').should_not include @crop diff --git a/spec/models/garden_spec.rb b/spec/models/garden_spec.rb index baa8c001a..346e719b5 100644 --- a/spec/models/garden_spec.rb +++ b/spec/models/garden_spec.rb @@ -67,7 +67,7 @@ describe Garden do @p1 = FactoryBot.create(:planting, crop: tomato, garden: garden, owner: garden.owner) @p2 = FactoryBot.create(:planting, crop: maize, garden: garden, owner: garden.owner) - garden.featured_plantings.should eq [@p2, @p1] + expect(garden.featured_plantings).to eq [@p2, @p1] end it "should fetch most recent 4 featured plantings" do @@ -77,7 +77,7 @@ describe Garden do @p4 = FactoryBot.create(:planting, crop: apple, garden: garden, owner: garden.owner) @p5 = FactoryBot.create(:planting, crop: walnut, garden: garden, owner: garden.owner) - garden.featured_plantings.should eq [@p5, @p4, @p3, @p2] + expect(garden.featured_plantings).to eq [@p5, @p4, @p3, @p2] end it "should skip repeated plantings" do @@ -89,7 +89,7 @@ describe Garden do @p6 = FactoryBot.create(:planting, crop: apple, garden: garden, owner: garden.owner) @p7 = FactoryBot.create(:planting, crop: pear, garden: garden, owner: garden.owner) - garden.featured_plantings.should eq [@p7, @p6, @p5, @p3] + expect(garden.featured_plantings).to eq [@p7, @p6, @p5, @p3] end end @@ -97,10 +97,10 @@ describe Garden do garden = FactoryBot.create(:garden, owner: owner) @planting1 = FactoryBot.create(:planting, garden: garden, owner: garden.owner) @planting2 = FactoryBot.create(:planting, garden: garden, owner: garden.owner) - garden.plantings.size.should eq(2) + expect(garden.plantings.size).to eq(2) all = Planting.count garden.destroy - Planting.count.should eq(all - 2) + expect(Planting.count).to eq(all - 2) end context 'area' do @@ -157,7 +157,7 @@ describe Garden do it 'sets area unit to blank if area is blank' do garden = FactoryBot.build(:garden, area: '', area_unit: 'acre') garden.should be_valid - garden.area_unit.should eq nil + expect(garden.area_unit).to eq nil end end @@ -180,16 +180,16 @@ describe Garden do p1 = FactoryBot.create(:planting, garden: garden, owner: garden.owner) p2 = FactoryBot.create(:planting, garden: garden, owner: garden.owner) - p1.finished.should eq false - p2.finished.should eq false + expect(p1.finished).to eq false + expect(p2.finished).to eq false garden.active = false garden.save p1.reload - p1.finished.should eq true + expect(p1.finished).to eq true p2.reload - p2.finished.should eq true + expect(p2.finished).to eq true end it "doesn't mark the wrong plantings as finished" do @@ -204,23 +204,23 @@ describe Garden do # plantings in that garden should be "finished" p1.reload - p1.finished.should eq true + expect(p1.finished).to eq true # plantings in other gardens should not be. p2.reload - p2.finished.should eq false + expect(p2.finished).to eq false end context 'photos' do let(:garden) { FactoryBot.create(:garden) } - let(:photo) { FactoryBot.create(:photo) } + let(:photo) { FactoryBot.create(:photo, owner: garden.owner) } before do garden.photos << photo end it 'has a photo' do - garden.photos.first.should eq photo + expect(garden.photos.first).to eq photo end it 'deletes association with photos when photo is deleted' do @@ -230,13 +230,13 @@ describe Garden do end it 'has a default photo' do - garden.default_photo.should eq photo + expect(garden.default_photo).to eq photo end it 'chooses the most recent photo' do - @photo2 = FactoryBot.create(:photo) + @photo2 = FactoryBot.create(:photo, owner: garden.owner) garden.photos << @photo2 - garden.default_photo.should eq @photo2 + expect(garden.default_photo).to eq @photo2 end end diff --git a/spec/models/harvest_spec.rb b/spec/models/harvest_spec.rb index 1944c6365..455afeb9b 100644 --- a/spec/models/harvest_spec.rb +++ b/spec/models/harvest_spec.rb @@ -61,7 +61,7 @@ describe Harvest do it 'sets unit to blank if quantity is blank' do @harvest = FactoryBot.build(:harvest, quantity: '', unit: 'individual') @harvest.should be_valid - @harvest.unit.should eq nil + expect(@harvest.unit).to eq nil end end @@ -114,7 +114,7 @@ describe Harvest do it 'sets weight_unit to blank if quantity is blank' do @harvest = FactoryBot.build(:harvest, weight_quantity: '', weight_unit: 'kg') @harvest.should be_valid - @harvest.weight_unit.should eq nil + expect(@harvest.weight_unit).to eq nil end end @@ -122,19 +122,19 @@ describe Harvest do it 'converts from pounds' do @harvest = FactoryBot.create(:harvest, weight_quantity: 2, weight_unit: "lb") @harvest.should be_valid - @harvest.reload.si_weight.should eq 0.907 + expect(@harvest.reload.si_weight).to eq 0.907 end it 'converts from ounces' do @harvest = FactoryBot.create(:harvest, weight_quantity: 16, weight_unit: "oz") @harvest.should be_valid - @harvest.reload.si_weight.should eq 0.454 + expect(@harvest.reload.si_weight).to eq 0.454 end it 'leaves kg alone' do @harvest = FactoryBot.create(:harvest, weight_quantity: 2, weight_unit: "kg") @harvest.should be_valid - @harvest.reload.si_weight.should eq 2.0 + expect(@harvest.reload.si_weight).to eq 2.0 end end @@ -142,7 +142,7 @@ describe Harvest do it 'lists most recent harvests first' do @h1 = FactoryBot.create(:harvest, created_at: 1.day.ago) @h2 = FactoryBot.create(:harvest, created_at: 1.hour.ago) - Harvest.all.order(created_at: :desc).should eq [@h2, @h1] + expect(Harvest.all.order(created_at: :desc)).to eq [@h2, @h1] end end @@ -155,7 +155,7 @@ describe Harvest do unit: nil, weight_quantity: nil, weight_unit: nil) - @h.to_s.should eq "apricots" + expect(@h.to_s).to eq "apricots" end it "1 individual apricot" do @@ -164,7 +164,7 @@ describe Harvest do unit: 'individual', weight_quantity: nil, weight_unit: nil) - @h.to_s.should eq "1 individual apricot" + expect(@h.to_s).to eq "1 individual apricot" end it "10 individual apricots" do @@ -173,7 +173,7 @@ describe Harvest do unit: 'individual', weight_quantity: nil, weight_unit: nil) - @h.to_s.should eq "10 individual apricots" + expect(@h.to_s).to eq "10 individual apricots" end it "1 bushel of apricots" do @@ -182,7 +182,7 @@ describe Harvest do unit: 'bushel', weight_quantity: nil, weight_unit: nil) - @h.to_s.should eq "1 bushel of apricots" + expect(@h.to_s).to eq "1 bushel of apricots" end it "1.5 bushels of apricots" do @@ -191,7 +191,7 @@ describe Harvest do unit: 'bushel', weight_quantity: nil, weight_unit: nil) - @h.to_s.should eq "1.5 bushels of apricots" + expect(@h.to_s).to eq "1.5 bushels of apricots" end it "10 bushels of apricots" do @@ -200,7 +200,7 @@ describe Harvest do unit: 'bushel', weight_quantity: nil, weight_unit: nil) - @h.to_s.should eq "10 bushels of apricots" + expect(@h.to_s).to eq "10 bushels of apricots" end it "apricots weighing 1.2 kg" do @@ -209,7 +209,7 @@ describe Harvest do unit: nil, weight_quantity: 1.2, weight_unit: 'kg') - @h.to_s.should eq "apricots weighing 1.2 kg" + expect(@h.to_s).to eq "apricots weighing 1.2 kg" end it "10 bushels of apricots weighing 100 kg" do @@ -218,7 +218,7 @@ describe Harvest do unit: 'bushel', weight_quantity: 100, weight_unit: 'kg') - @h.to_s.should eq "10 bushels of apricots weighing 100 kg" + expect(@h.to_s).to eq "10 bushels of apricots weighing 100 kg" end end @@ -229,26 +229,25 @@ describe Harvest do context 'without a photo' do it 'should have no default photo' do - @harvest.default_photo.should eq nil + expect(@harvest.default_photo).to eq nil end context 'and with a crop(planting) photo' do before :each do - @photo = FactoryBot.create(:photo) @planting = FactoryBot.create(:planting, crop: @harvest.crop) + @photo = FactoryBot.create(:photo, owner: @planting.owner) @planting.photos << @photo end it 'should have a default photo' do - @harvest.default_photo.should eq @photo + expect(@harvest.default_photo).to eq @photo end end end context 'with a photo' do before do - @photo = FactoryBot.create(:photo) - + @photo = FactoryBot.create(:photo, owner: @harvest.owner) @harvest.photos << @photo end @@ -257,7 +256,7 @@ describe Harvest do end it 'has a photo' do - @harvest.photos.first.should eq @photo + expect(@harvest.photos.first).to eq @photo end it 'deletes association with photos when photo is deleted' do @@ -267,29 +266,29 @@ describe Harvest do end it 'has a default photo' do - @harvest.default_photo.should eq @photo + expect(@harvest.default_photo).to eq @photo end context 'and with a crop(planting) photo' do before :each do - @crop_photo = FactoryBot.create(:photo) @planting = FactoryBot.create(:planting, crop: @harvest.crop) + @crop_photo = FactoryBot.create(:photo, owner: @planting.owner) @planting.photos << @crop_photo end it 'should prefer the harvest photo' do - @harvest.default_photo.should eq @photo + expect(@harvest.default_photo).to eq @photo end end context 'and a second photo' do before :each do - @photo2 = FactoryBot.create(:photo) + @photo2 = FactoryBot.create(:photo, owner: @harvest.owner) @harvest.photos << @photo2 end it 'chooses the most recent photo' do - @harvest.default_photo.should eq @photo2 + expect(@harvest.default_photo).to eq @photo2 end end end diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index 5f07a3e29..0e2c45a11 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -5,9 +5,9 @@ describe Photo do let(:member) { FactoryBot.create(:member) } describe 'add/delete functionality' do - let(:planting) { FactoryBot.create(:planting) } - let(:harvest) { FactoryBot.create(:harvest) } - let(:garden) { FactoryBot.create(:garden) } + let(:planting) { FactoryBot.create(:planting, owner: member) } + let(:harvest) { FactoryBot.create(:harvest, owner: member) } + let(:garden) { FactoryBot.create(:garden, owner: member) } context "adds photos" do it 'to a planting' do diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 3c76d6ed6..194967bbd 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -313,81 +313,72 @@ describe Planting do # be done on this side, not on the photos side context 'photos' do let(:planting) { FactoryBot.create(:planting) } - let(:photo) { FactoryBot.create(:photo) } - - before do - planting.photos << photo - end + let(:photo) { FactoryBot.create(:photo, owner_id: planting.owner_id) } + before { planting.photos << photo } it 'has a photo' do - planting.photos.first.should eq photo + expect(planting.photos.first).to eq photo end it 'is found in has_photos scope' do - Planting.has_photos.should include(planting) + expect(Planting.has_photos).to include(planting) end it 'deletes association with photos when photo is deleted' do photo.destroy planting.reload - planting.photos.should be_empty + expect(planting.photos).to be_empty end it 'has a default photo' do - planting.default_photo.should eq photo + expect(planting.default_photo).to eq photo end it 'chooses the most recent photo' do - @photo2 = FactoryBot.create(:photo) + @photo2 = FactoryBot.create(:photo, owner: planting.owner) planting.photos << @photo2 - planting.default_photo.should eq @photo2 + expect(planting.default_photo).to eq @photo2 end end context 'interesting plantings' do - it 'picks up interesting plantings' do - # plantings have members created implicitly for them - # each member is different, hence these are all interesting - @planting1 = FactoryBot.create(:planting, created_at: 5.days.ago) - @planting2 = FactoryBot.create(:planting, created_at: 4.days.ago) - @planting3 = FactoryBot.create(:planting, created_at: 3.days.ago) - @planting4 = FactoryBot.create(:planting, created_at: 2.days.ago) + describe 'picks up interesting plantings' do + before do + # plantings have members created implicitly for them + # each member is different, hence these are all interesting + @planting1 = FactoryBot.create(:planting, planted_at: 5.days.ago) + @planting2 = FactoryBot.create(:planting, planted_at: 4.days.ago) + @planting3 = FactoryBot.create(:planting, planted_at: 3.days.ago) + @planting4 = FactoryBot.create(:planting, planted_at: 2.days.ago) - # plantings need photos to be interesting - @photo = FactoryBot.create(:photo) - [@planting1, @planting2, @planting3, @planting4].each do |p| - p.photos << @photo - p.save + # plantings need photos to be interesting + [@planting1, @planting2, @planting3, @planting4].each do |p| + p.photos << FactoryBot.create(:photo, owner_id: p.owner_id) + p.save + end end - [ - @planting4, - @planting3, - @planting2, - @planting1 - ].each do |p| - Planting.interesting.should include p - end + it { expect(Planting.interesting).to eq([@planting4, @planting3, @planting2, @planting1]) } end context "default arguments" do it 'ignores plantings without photos' do # first, an interesting planting @planting = FactoryBot.create(:planting) - @planting.photos << FactoryBot.create(:photo) + @planting.photos << FactoryBot.create(:photo, owner: @planting.owner) @planting.save # this one doesn't have a photo @no_photo_planting = FactoryBot.create(:planting) - Planting.interesting.should include @planting - Planting.interesting.should_not include @no_photo_planting + expect(Planting.interesting).to include @planting + expect(Planting.interesting).not_to include @no_photo_planting end it 'ignores plantings with the same owner' do # this planting is older @planting1 = FactoryBot.create(:planting, created_at: 1.day.ago) - @planting1.photos << FactoryBot.create(:photo) + @planting1.photos << FactoryBot.create(:photo, owner_id: @planting1.owner_id) @planting1.save # this one is newer, and has the same owner, through the garden @@ -395,12 +386,12 @@ describe Planting do created_at: 1.minute.ago, garden: @planting1.garden, owner: @planting1.owner) - @planting2.photos << FactoryBot.create(:photo) + @planting2.photos << FactoryBot.create(:photo, owner: @planting2.owner) @planting2.save # result: the newer one is interesting, the older one isn't - Planting.interesting.should include @planting2 - Planting.interesting.should_not include @planting1 + expect(Planting.interesting).to include @planting2 + expect(Planting.interesting).not_to include @planting1 end end @@ -408,9 +399,9 @@ describe Planting do it "only returns the number asked for" do @plantings = FactoryBot.create_list(:planting, 10) @plantings.each do |p| - p.photos << FactoryBot.create(:photo, owner: planting.owner) + p.photos << FactoryBot.create(:photo, owner: p.owner) end - Planting.interesting.limit(3).count.should eq 3 + expect(Planting.interesting.limit(3).count).to eq 3 end end end # interesting plantings diff --git a/spec/models/seed_spec.rb b/spec/models/seed_spec.rb index 690e8c75f..03634ced4 100644 --- a/spec/models/seed_spec.rb +++ b/spec/models/seed_spec.rb @@ -153,7 +153,7 @@ describe Seed do context 'photos' do let(:seed) { FactoryBot.create :seed } - before { seed.photos << FactoryBot.create(:photo) } + before { seed.photos << FactoryBot.create(:photo, owner: seed.owner) } it 'is found in has_photos scope' do Seed.has_photos.should include(seed) end @@ -161,7 +161,7 @@ describe Seed do context 'ancestry' do let(:parent_planting) { FactoryBot.create :planting } - let(:seed) { FactoryBot.create :seed, parent_planting: parent_planting } + let(:seed) { FactoryBot.create :seed, parent_planting: parent_planting, owner: parent_planting.owner } it "seed has a parent planting" do expect(seed.parent_planting).to eq(parent_planting) end diff --git a/spec/views/crops/index.html.haml_spec.rb b/spec/views/crops/index.html.haml_spec.rb index 9f2985035..7d05d18db 100644 --- a/spec/views/crops/index.html.haml_spec.rb +++ b/spec/views/crops/index.html.haml_spec.rb @@ -17,7 +17,7 @@ describe "crops/index" do it "shows photos where available" do @planting = FactoryBot.create(:planting, crop: @tomato) - @photo = FactoryBot.create(:photo) + @photo = FactoryBot.create(:photo, owner: @planting.owner) @planting.photos << @photo render assert_select "img", src: @photo.thumbnail_url From 517cfa3acd8579dc22562bfb0af32f94434195ca Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 15:34:50 +1200 Subject: [PATCH 134/267] spec fixes --- spec/controllers/photo_associations_controller_spec.rb | 2 +- spec/features/signin_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/photo_associations_controller_spec.rb b/spec/controllers/photo_associations_controller_spec.rb index ffde9e1e3..5ed022218 100644 --- a/spec/controllers/photo_associations_controller_spec.rb +++ b/spec/controllers/photo_associations_controller_spec.rb @@ -39,7 +39,7 @@ describe PhotoAssociationsController do it do delete :destroy, params: valid_params - expect(response).to have_http_response(:not_found) + expect(response).to have_http_status(:not_found) end end end diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb index e992d14e7..4f208f366 100644 --- a/spec/features/signin_spec.rb +++ b/spec/features/signin_spec.rb @@ -56,7 +56,7 @@ feature "signin", js: true do end scenario "after signin, redirect to new notifications page" do - visit new_notification_path(recipient: recipient.id) + visit new_notification_path(recipient_id: recipient.id) expect(current_path).to eq new_member_session_path login expect(current_path).to eq new_notification_path From 748da6c3e63105397510d2ad1d0660ab2e583cef Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:02:07 +1200 Subject: [PATCH 135/267] Comments from deleted members need to show --- app/models/comment.rb | 2 +- app/views/comments/_single.html.haml | 7 +++---- spec/features/members/deletion_spec.rb | 6 ++++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/app/models/comment.rb b/app/models/comment.rb index 59d7102ad..3eda14aa4 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,5 +1,5 @@ class Comment < ApplicationRecord - belongs_to :author, class_name: 'Member' + belongs_to :author, -> { with_deleted }, class_name: 'Member' belongs_to :post scope :post_order, -> { reorder("created_at ASC") } # for display on post page diff --git a/app/views/comments/_single.html.haml b/app/views/comments/_single.html.haml index 951df30bb..d3488f4f9 100644 --- a/app/views/comments/_single.html.haml +++ b/app/views/comments/_single.html.haml @@ -6,10 +6,10 @@ .col-md-11 .comment-meta Posted by - - if comment.author - = link_to comment.author.login_name, member_path(comment.author) - - else + - if comment.author.deleted? Member Deleted + - else + = link_to comment.author.login_name, member_path(comment.author) on = comment.created_at - if comment.updated_at > comment.created_at @@ -27,4 +27,3 @@ - if can? :destroy, comment = link_to 'Delete', comment, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-xs' - diff --git a/spec/features/members/deletion_spec.rb b/spec/features/members/deletion_spec.rb index 22b91a33b..3e5cb2e88 100644 --- a/spec/features/members/deletion_spec.rb +++ b/spec/features/members/deletion_spec.rb @@ -75,6 +75,10 @@ feature "member deletion" do logout end + describe 'member exists but is marked deleted' do + it { expect(Member.with_deleted.find(member.id)).to eq member } + end + scenario "removes plantings" do visit planting_path(planting) expect(page.status_code).to eq(404) @@ -108,6 +112,8 @@ feature "member deletion" do end scenario "replaces comments on others' posts with deletion note, leaving post intact" do + FactoryBot.create :comment, post: othermemberpost, author: member, body: 'i am deleting my account' + visit post_path(othermemberpost) expect(page).not_to have_content member.login_name expect(page).to have_content other_member.login_name From bcaf245e645676f6d1bb0b43a9afe3d57fa3037f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:10:24 +1200 Subject: [PATCH 136/267] photos#new doesn't redirect, needs item --- spec/features/signin_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/signin_spec.rb b/spec/features/signin_spec.rb index 4f208f366..7f362abf3 100644 --- a/spec/features/signin_spec.rb +++ b/spec/features/signin_spec.rb @@ -48,7 +48,7 @@ feature "signin", js: true do end describe "redirects to what you were trying to do" do - %w(plantings harvests posts photos gardens seeds).each do |m| + %w(plantings harvests posts gardens seeds).each do |m| it_behaves_like "redirects to what you were trying to do" do let(:model_name) { m } end From d7cc219569e087e69d212cf7d59cb56b66764cab Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:16:55 +1200 Subject: [PATCH 137/267] Unique login_name in member factory --- spec/factories/member.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/spec/factories/member.rb b/spec/factories/member.rb index ca63df4e2..d1b34a487 100644 --- a/spec/factories/member.rb +++ b/spec/factories/member.rb @@ -1,9 +1,7 @@ FactoryBot.define do - sequence(:email) { |n| "member#{n}@example.com" } - sequence(:login_name) { |n| "member#{n}" } - factory :member, aliases: %i(author owner sender recipient creator) do - login_name { "#{Faker::Name.first_name}_#{rand(1..1000)}" } + sequence(:login_name) { |n| "member#{n}" } + # login_name { "#{Faker::Internet.user_name}_#{rand(1..1000)}" } password 'password1' email { Faker::Internet.unique.email } tos_agreement true From 05bfbda5f56e1077c79b100ff6ee712ad1e98928 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:18:49 +1200 Subject: [PATCH 138/267] Rubocop style fix ups --- app/controllers/application_controller.rb | 4 ++-- app/controllers/passwords_controller.rb | 2 +- app/controllers/registrations_controller.rb | 2 +- app/validators/approved_validator.rb | 2 +- bin/setup | 1 - bin/yarn | 2 +- config/unicorn.rb | 4 ++-- 7 files changed, 8 insertions(+), 9 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index eb775ee4a..9ef6783e5 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -23,11 +23,11 @@ class ApplicationController < ActionController::Base render file: 'app/views/errors/404', status: :not_found, layout: false end - def after_sign_in_path_for(resource) + def after_sign_in_path_for(_resource) stored_location_for(:member) || root_path end - def after_sign_out_path_for(resource_or_scope) + def after_sign_out_path_for(_resource_or_scope) request.referer end diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb index c14a02b40..fb6852ea9 100644 --- a/app/controllers/passwords_controller.rb +++ b/app/controllers/passwords_controller.rb @@ -1,7 +1,7 @@ class PasswordsController < Devise::PasswordsController protected - def after_resetting_password_path_for(resource) + def after_resetting_password_path_for(_resource) root_path end end diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 72e92b9fd..b9ed73dfe 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -46,7 +46,7 @@ class RegistrationsController < Devise::RegistrationsController end # check if we need the current password to update fields -def needs_password?(member, params) +def needs_password?(_member, params) params[:member][:password].present? || params[:member][:password_confirmation].present? end diff --git a/app/validators/approved_validator.rb b/app/validators/approved_validator.rb index e845b9529..8a77fa2da 100644 --- a/app/validators/approved_validator.rb +++ b/app/validators/approved_validator.rb @@ -1,5 +1,5 @@ class ApprovedValidator < ActiveModel::EachValidator - def validate_each(record, attribute, value) + def validate_each(record, attribute, _value) record.errors[attribute] << (options[:message] || 'must be approved') unless record.crop.try(:approved?) end end diff --git a/bin/setup b/bin/setup index d5163f8c1..b2293a35a 100755 --- a/bin/setup +++ b/bin/setup @@ -21,7 +21,6 @@ chdir APP_ROOT do # Install JavaScript dependencies if using Yarn # system('bin/yarn') - # puts "\n== Copying sample files ==" # unless File.exist?('config/database.yml') # cp 'config/database.yml.sample', 'config/database.yml' diff --git a/bin/yarn b/bin/yarn index ad111a882..4d2c50e52 100755 --- a/bin/yarn +++ b/bin/yarn @@ -2,7 +2,7 @@ VENDOR_PATH = File.expand_path('..', __dir__) Dir.chdir(VENDOR_PATH) do begin - exec "yarnpkg #{ARGV.join(" ")}" + exec "yarnpkg #{ARGV.join(' ')}" rescue Errno::ENOENT warn "Yarn executable was not detected in the system." warn "Download Yarn at https://yarnpkg.com/en/docs/install" diff --git a/config/unicorn.rb b/config/unicorn.rb index 6a63af23f..fa76bae3a 100644 --- a/config/unicorn.rb +++ b/config/unicorn.rb @@ -9,7 +9,7 @@ before_fork do |_server, _worker| Process.kill 'QUIT', Process.pid end - defined?(ActiveRecord::Base) and + defined?(ActiveRecord::Base) && ActiveRecord::Base.connection.disconnect! end @@ -18,6 +18,6 @@ after_fork do |_server, _worker| puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to sent QUIT' end - defined?(ActiveRecord::Base) and + defined?(ActiveRecord::Base) && ActiveRecord::Base.establish_connection end From f58c6c8f54523cbc0e11f208da40f9667222eded Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:20:39 +1200 Subject: [PATCH 139/267] Regen rubocop todo --- .rubocop_todo.yml | 45 ++------------------------------------------- 1 file changed, 2 insertions(+), 43 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 99782950a..1bfd8efc6 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,16 +1,11 @@ # This configuration was generated by -# `rubocop --auto-gen-config --no-offense-counts` -# on 2018-04-02 16:07:34 +1200 using RuboCop version 0.54.0. +# `rubocop --auto-gen-config --no-offense-counts --no-auto-gen-timestamp` +# using RuboCop version 0.55.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Cop supports --auto-correct. -Layout/EmptyLines: - Exclude: - - 'bin/setup' - Lint/HandleExceptions: Exclude: - 'lib/tasks/testing.rake' @@ -22,15 +17,6 @@ Lint/MissingCopEnableDirective: - 'config/compass.rb' - 'config/initializers/devise.rb' -# Cop supports --auto-correct. -# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods. -Lint/UnusedMethodArgument: - Exclude: - - 'app/controllers/application_controller.rb' - - 'app/controllers/passwords_controller.rb' - - 'app/controllers/registrations_controller.rb' - - 'app/validators/approved_validator.rb' - Lint/UriEscapeUnescape: Exclude: - 'app/helpers/crops_helper.rb' @@ -96,14 +82,6 @@ Rails/TimeZone: - 'spec/factories/post.rb' - 'spec/models/post_spec.rb' -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: always, conditionals -Style/AndOr: - Exclude: - - 'config/unicorn.rb' - - 'lib/tasks/growstuff.rake' - # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, EnforcedStyle. # SupportedStyles: nested, compact @@ -119,13 +97,6 @@ Style/CommentedKeyword: - 'spec/models/photo_spec.rb' - 'spec/models/planting_spec.rb' -# Configuration parameters: EnforcedStyle. -# SupportedStyles: annotated, template, unannotated -Style/FormatStringToken: - Exclude: - - 'app/helpers/application_helper.rb' - - 'spec/helpers/application_helper_spec.rb' - Style/IdenticalConditionalBranches: Exclude: - 'app/controllers/follows_controller.rb' @@ -136,11 +107,6 @@ Style/MixinUsage: - 'bin/update' - 'spec/rails_helper.rb' -# Cop supports --auto-correct. -Style/MultilineIfModifier: - Exclude: - - 'spec/rails_helper.rb' - # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, EnforcedStyle. # SupportedStyles: predicate, comparison @@ -161,10 +127,3 @@ Style/RegexpLiteral: - 'spec/views/devise/registrations/edit_spec.rb' - 'spec/views/members/index.html.haml_spec.rb' - 'spec/views/posts/index.html.haml_spec.rb' - -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: single_quotes, double_quotes -Style/StringLiteralsInInterpolation: - Exclude: - - 'bin/yarn' From 4d937a1f91a2e99dbd270500fe98d1a9b5af52e9 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:29:38 +1200 Subject: [PATCH 140/267] Restoring Comfy mexican sofa --- Gemfile | 2 +- Gemfile.lock | 48 ++++++++++++++++++++++++++++- app/views/layouts/_footer.html.haml | 6 ++-- config/routes.rb | 2 +- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/Gemfile b/Gemfile index cecb3d65e..68925a470 100644 --- a/Gemfile +++ b/Gemfile @@ -42,7 +42,7 @@ gem 'pg', '< 1.0.0' # Upstream bug, see https://github.com/Growst gem 'ruby-units' # for unit conversion gem 'unicorn' # http server -# gem 'comfortable_mexican_sofa' # content management system +gem 'comfortable_mexican_sofa', git: 'https://github.com/comfy/comfortable-mexican-sofa', branch: 'rails5.1' gem 'bootstrap-kaminari-views' # bootstrap views for kaminari gem 'kaminari' # pagination diff --git a/Gemfile.lock b/Gemfile.lock index 3854a293b..f8dd95732 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,24 @@ +GIT + remote: https://github.com/comfy/comfortable-mexican-sofa + revision: dca0c7c3669872a00722bb57d3ff0f4995dc4f09 + branch: rails5.1 + specs: + comfortable_mexican_sofa (1.12.10) + active_link_to (>= 1.0.0) + bootstrap-sass (>= 3.2.0) + bootstrap_form (>= 2.2.0) + codemirror-rails (>= 3.0.0) + coffee-rails (>= 3.1.0) + haml-rails (>= 0.3.0) + jquery-rails (>= 3.0.0) + jquery-ui-rails (>= 5.0.0) + kramdown (>= 1.0.0) + paperclip (>= 4.0.0) + plupload-rails (>= 1.2.1) + rails (>= 5.0.0, < 5.2) + rails-i18n (>= 4.0.0) + sass-rails (>= 4.0.3) + GEM remote: https://rubygems.org/ remote: https://rails-assets.org/ @@ -25,6 +46,9 @@ GEM erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) + active_link_to (1.0.5) + actionpack + addressable active_median (0.1.4) activerecord active_utils (3.3.11) @@ -65,6 +89,7 @@ GEM bootstrap-sass (3.3.7) autoprefixer-rails (>= 5.2.1) sass (>= 3.3.4) + bootstrap_form (2.7.0) builder (3.2.3) bullet (5.7.5) activesupport (>= 3.0.0) @@ -87,9 +112,12 @@ GEM chartkick (2.3.4) childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) + climate_control (0.2.0) cliver (0.3.2) codeclimate-test-reporter (1.0.8) simplecov (<= 0.13) + codemirror-rails (5.16.0) + railties (>= 3.0, < 6.0) coderay (1.1.2) coffee-rails (4.2.2) coffee-script (>= 2.2.0) @@ -240,6 +268,7 @@ GEM kaminari-core (= 1.1.1) kaminari-core (1.1.1) kgio (2.11.2) + kramdown (1.17.0) launchy (2.4.3) addressable (~> 2.3) leaflet-rails (1.3.1) @@ -257,6 +286,10 @@ GEM mini_mime (>= 0.1.1) memcachier (0.0.2) method_source (0.9.0) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mimemagic (0.3.2) mini_mime (1.0.0) mini_portile2 (2.3.0) minitest (5.11.3) @@ -293,6 +326,12 @@ GEM omniauth-oauth (~> 1.1) rack orm_adapter (0.5.0) + paperclip (6.0.0) + activemodel (>= 4.2.0) + activesupport (>= 4.2.0) + mime-types + mimemagic (~> 0.3.0) + terrapin (~> 0.6.0) parallel (1.12.1) paranoia (2.4.1) activerecord (>= 4.0, < 5.3) @@ -302,6 +341,8 @@ GEM platform-api (2.1.0) heroics (~> 0.0.23) moneta (~> 0.8.1) + plupload-rails (1.2.1) + rails (>= 3.1) poltergeist (1.17.0) capybara (~> 2.1) cliver (~> 0.3.1) @@ -337,6 +378,9 @@ GEM nokogiri (>= 1.6) rails-html-sanitizer (1.0.4) loofah (~> 2.2, >= 2.2.2) + rails-i18n (5.1.1) + i18n (>= 0.7, < 2) + railties (>= 5.0, < 6) rails_12factor (0.0.3) rails_serve_static_assets rails_stdout_logging @@ -432,6 +476,8 @@ GEM tins (~> 1.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) + terrapin (0.6.0) + climate_control (>= 0.0.3, < 1.0) thor (0.19.4) thread (0.2.2) thread_safe (0.3.6) @@ -484,6 +530,7 @@ DEPENDENCIES chartkick codeclimate-test-reporter coffee-rails + comfortable_mexican_sofa! coveralls csv_shaper dalli @@ -548,7 +595,6 @@ DEPENDENCIES will_paginate xmlrpc - RUBY VERSION ruby 2.4.1p111 diff --git a/app/views/layouts/_footer.html.haml b/app/views/layouts/_footer.html.haml index b05b164d4..dcff23dd6 100644 --- a/app/views/layouts/_footer.html.haml +++ b/app/views/layouts/_footer.html.haml @@ -2,11 +2,11 @@ .container .row .col-md-4#footer1 - -# != cms_snippet_content(:footer1) + = cms_snippet_content(:footer1) .col-md-4#footer2 - -# != cms_snippet_content(:footer2) + = cms_snippet_content(:footer2) .col-md-4#footer3 - -# != cms_snippet_content(:footer3) + = cms_snippet_content(:footer3) %div{ style: "float: right;" } %a{ href: "http://opendefinition.org/ossd/" } %img{ src: "http://assets.okfn.org/images/ok_buttons/os_80x15_blue.png", alt: "" } diff --git a/config/routes.rb b/config/routes.rb index 046c1b261..e884b4d69 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -106,5 +106,5 @@ Rails.application.routes.draw do get '/.well-known/acme-challenge/:id' => 'pages#letsencrypt' # CMS stuff -- must remain LAST - # comfy_route :cms, path: '/', sitemap: false + comfy_route :cms, path: '/', sitemap: false end From 4be4e96a9f986ddce2485202a9e240077e52491c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:30:38 +1200 Subject: [PATCH 141/267] Fixed or => || --- lib/tasks/growstuff.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index e6ec0650d..9fe5202d3 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -29,7 +29,7 @@ namespace :growstuff do task import_crops: :environment do require 'csv' - @file = ENV['file'] or raise "Usage: rake growstuff:import_crops file=file.csv" + (@file = ENV['file']) || raise("Usage: rake growstuff:import_crops file=file.csv") puts "Loading crops from #{@file}..." CSV.foreach(@file) do |row| From fd405ccad0fac4ed11af11c3d2cdd29b8d0f5092 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:34:00 +1200 Subject: [PATCH 142/267] Added back link to CMS --- app/views/admin/index.html.haml | 2 +- config/routes.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/admin/index.html.haml b/app/views/admin/index.html.haml index f82c5c336..e7b164280 100644 --- a/app/views/admin/index.html.haml +++ b/app/views/admin/index.html.haml @@ -8,7 +8,7 @@ %ul#site_admin %li= link_to "Roles", roles_path %li= link_to "Forums", forums_path - -# %li= link_to "CMS", comfy_admin_cms_path + %li= link_to "CMS", comfy_admin_cms_path .col-md-4 %h2 Crop data admin diff --git a/config/routes.rb b/config/routes.rb index e884b4d69..a43de3f0c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -83,7 +83,7 @@ Rails.application.routes.draw do get 'auth/:provider/callback' => 'authentications#create' get 'members/auth/:provider/callback' => 'authentications#create' - # comfy_route :cms_admin, path: '/admin/cms' + comfy_route :cms_admin, path: '/admin/cms' namespace :admin do resources :members end From 7737f41b7f0579e1ced53d4e824ace77ea5afb95 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:39:51 +1200 Subject: [PATCH 143/267] Code style fixup --- spec/rails_helper.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 862b0316d..ec3f6af77 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -104,12 +104,14 @@ RSpec.configure do |config| # Prevent Poltergeist from fetching external URLs during feature tests config.before(:each, js: true) do - page.driver.browser.url_blacklist = [ - 'gravatar.com', - 'mapbox.com', - 'okfn.org', - 'googlecode.com' - ] if page.driver.browser.respond_to?(:url_blacklist) + if page.driver.browser.respond_to?(:url_blacklist) + page.driver.browser.url_blacklist = [ + 'gravatar.com', + 'mapbox.com', + 'okfn.org', + 'googlecode.com' + ] + end page.driver.browser.manage.window.maximize if page.driver.browser.respond_to?(:manage) end From f31ff5d508c27d9b195352088af73edf394d4e9f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:42:37 +1200 Subject: [PATCH 144/267] Removed commented out gems --- Gemfile | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Gemfile b/Gemfile index 68925a470..1cbd29839 100644 --- a/Gemfile +++ b/Gemfile @@ -82,7 +82,6 @@ gem "chartkick" # client for Elasticsearch. Elasticsearch is a flexible # and powerful, distributed, real-time search and analytics engine. # An example of the use in the project is fuzzy crop search. - # Project does not use semver, so we want to be in sync with the version of # elasticsearch we use # See https://github.com/elastic/elasticsearch-ruby#compatibility @@ -114,11 +113,6 @@ group :development do gem 'better_errors' gem 'letter_opener' gem 'listen' - # gem 'binding_of_caller' - # gem 'guard' - # gem 'guard-rspec' - # gem 'pry' - # gem 'quiet_assets' end group :development, :test do From a816ec2bbabfeb8cb9b800d9d5dc8622598d9ce8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:44:51 +1200 Subject: [PATCH 145/267] Fix up footer --- app/views/layouts/_footer.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/layouts/_footer.html.haml b/app/views/layouts/_footer.html.haml index dcff23dd6..e004bf69a 100644 --- a/app/views/layouts/_footer.html.haml +++ b/app/views/layouts/_footer.html.haml @@ -2,11 +2,11 @@ .container .row .col-md-4#footer1 - = cms_snippet_content(:footer1) + != cms_snippet_content(:footer1) .col-md-4#footer2 - = cms_snippet_content(:footer2) + != cms_snippet_content(:footer2) .col-md-4#footer3 - = cms_snippet_content(:footer3) + != cms_snippet_content(:footer3) %div{ style: "float: right;" } %a{ href: "http://opendefinition.org/ossd/" } %img{ src: "http://assets.okfn.org/images/ok_buttons/os_80x15_blue.png", alt: "" } From 1f6d76445e6f487054f54d73daaae5e40ee19f83 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:49:00 +1200 Subject: [PATCH 146/267] Added back CMS initialiser --- .../initializers/comfortable_mexican_sofa.rb | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 config/initializers/comfortable_mexican_sofa.rb diff --git a/config/initializers/comfortable_mexican_sofa.rb b/config/initializers/comfortable_mexican_sofa.rb new file mode 100644 index 000000000..1f47ac973 --- /dev/null +++ b/config/initializers/comfortable_mexican_sofa.rb @@ -0,0 +1,99 @@ +ComfortableMexicanSofa.configure do |config| + # Title of the admin area + # config.cms_title = 'ComfortableMexicanSofa CMS Engine' + + # Controller that is inherited from CmsAdmin::BaseController + # config.base_controller = 'ApplicationController' + + # Module responsible for authentication. You can replace it with your own. + # It simply needs to have #authenticate method. See http_auth.rb for reference. + config.admin_auth = 'CmsDeviseAuth' + + # Module responsible for authorization on admin side. It should have #authorize + # method that returns true or false based on params and loaded instance + # variables available for a given controller. + # config.admin_authorization = 'ComfyAdminAuthorization' + + # Module responsible for public authentication. Similar to the above. You also + # will have access to @cms_site, @cms_layout, @cms_page so you can use them in + # your logic. Default module doesn't do anything. + # config.public_auth = 'ComfyPublicAuthentication' + + # When arriving at /cms-admin you may chose to redirect to arbirtary path, + # for example '/cms-admin/users' + # config.admin_route_redirect = '' + + # File uploads use Paperclip and can support filesystem or s3 uploads. Override + # the upload method and appropriate settings based on Paperclip. For S3 see: + # http://rdoc.info/gems/paperclip/2.3.8/Paperclip/Storage/S3, and for + # filesystem see: http://rdoc.info/gems/paperclip/2.3.8/Paperclip/Storage/Filesystem + # If you are using S3 and HTTPS, pass :s3_protocol => '' to have URLs that use the protocol of the page + # config.upload_file_options = {:url => '/system/:class/:id/:attachment/:style/:filename'} + + # Sofa allows you to setup entire site from files. Database is updated with each + # request (if necessary). Please note that database entries are destroyed if there's + # no corresponding file. Fixtures are disabled by default. + # config.enable_fixtures = false + + # Path where fixtures can be located. + # config.fixtures_path = File.expand_path('db/cms_fixtures', Rails.root) + + # Importing fixtures into Database + # To load fixtures into the database just run this rake task: + # local: $ rake comfortable_mexican_sofa:fixtures:import FROM=example.local TO=localhost + # Heroku: $ heroku run rake comfortable_mexican_sofa:fixtures:import FROM=example.local TO=yourapp.herokuapp.com + # From indicates folder the fixtures are in and to is the Site hostname you have defined in the database. + + # Exporting fixtures into Files + # If you need to dump database contents into fixture files run: + # local: $ rake comfortable_mexican_sofa:fixtures:export FROM=localhost TO=example.local + # Heroku: $ heroku run rake comfortable_mexican_sofa:fixtures:export FROM=yourapp.herokuapp.com TO=example.local + # This will create example.local folder and dump all content from example.com Site. + + # Content for Layouts, Pages and Snippets has a revision history. You can revert + # a previous version using this system. You can control how many revisions per + # object you want to keep. Set it to 0 if you wish to turn this feature off. + # config.revisions_limit = 25 + + # Locale definitions. If you want to define your own locale merge + # {:locale => 'Locale Title'} with this. + # config.locales = {:en => 'English', :es => 'Español'} + + # Admin interface will respect the locale of the site being managed. However you can + # force it to English by setting this to `:en` + # config.admin_locale = nil + + # A class that is included as a sweeper to admin base controller if it's set + # config.admin_cache_sweeper = nil + + # By default you cannot have irb code inside your layouts/pages/snippets. + # Generally this is to prevent putting something like this: + # <% User.delete_all %> but if you really want to allow it... + # config.allow_irb = false + + # Whitelist of all helper methods that can be used via {{cms:helper}} tag. By default + # all helpers are allowed except `eval`, `send`, `call` and few others. Empty array + # will prevent rendering of all helpers. + # config.allowed_helpers = nil + + # Whitelist of partials paths that can be used via {{cms:partial}} tag. All partials + # are accessible by default. Empty array will prevent rendering of all partials. + # config.allowed_partials = nil + + # Site aliases, if you want to have aliases for your site. Good for harmonizing + # production env with dev/testing envs. + # e.g. config.hostname_aliases = {'host.com' => 'host.inv', 'host_a.com' => ['host.lvh.me', 'host.dev']} + # Default is nil (not used) + # config.hostname_aliases = nil + + # Reveal partials that can be overwritten in the admin area. + # Default is false. + # config.reveal_cms_partials = false +end + +module CmsDeviseAuth + def authenticate + return if current_member&.role?(:admin) + redirect_to root_path, alert: 'Permission denied. Please sign in as an admin user to use the CMS admin area.' + end +end From cf72bdc57da7eea76978f511a21756555573c623 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:49:41 +1200 Subject: [PATCH 147/267] Reinstate json response config --- config/initializers/wrap_parameters.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index bbfc3961b..bffab6c85 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -9,6 +9,6 @@ ActiveSupport.on_load(:action_controller) do end # To enable root element in JSON for ActiveRecord objects. -# ActiveSupport.on_load(:active_record) do -# self.include_root_in_json = true -# end +ActiveSupport.on_load(:active_record) do + self.include_root_in_json = false +end From 3399a794b2f739702c148015db5a5dbb44559efb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 16:55:29 +1200 Subject: [PATCH 148/267] Ignore one non-ascii comment --- config/initializers/comfortable_mexican_sofa.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/initializers/comfortable_mexican_sofa.rb b/config/initializers/comfortable_mexican_sofa.rb index 1f47ac973..314bc21fe 100644 --- a/config/initializers/comfortable_mexican_sofa.rb +++ b/config/initializers/comfortable_mexican_sofa.rb @@ -55,9 +55,11 @@ ComfortableMexicanSofa.configure do |config| # object you want to keep. Set it to 0 if you wish to turn this feature off. # config.revisions_limit = 25 + # rubocop:disable Style/AsciiComments # Locale definitions. If you want to define your own locale merge # {:locale => 'Locale Title'} with this. # config.locales = {:en => 'English', :es => 'Español'} + # rubocop:enable Style/AsciiComments # Admin interface will respect the locale of the site being managed. However you can # force it to English by setting this to `:en` From 0f8747f03de8a1202fa993da4bea6665c90ea019 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 4 Jun 2018 17:13:00 +1200 Subject: [PATCH 149/267] Turn on the CMS specs again --- spec/features/cms_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/features/cms_spec.rb b/spec/features/cms_spec.rb index fa6ace64a..176c531a8 100644 --- a/spec/features/cms_spec.rb +++ b/spec/features/cms_spec.rb @@ -4,13 +4,13 @@ feature "cms admin" do let(:member) { create :member } let(:admin_member) { create :admin_member } - pending "can't view CMS admin if not signed in" do + scenario "can't view CMS admin if not signed in" do visit comfy_admin_cms_path expect(current_path).to eq root_path expect(page).to have_content "Please sign in as an admin user" end - pending "can't view CMS admin if not an admin member" do + scenario "can't view CMS admin if not an admin member" do # sign in as an ordinary member login_as member visit comfy_admin_cms_path @@ -18,7 +18,7 @@ feature "cms admin" do expect(page).to have_content "Please sign in as an admin user" end - pending "admin members can view CMS admin area" do + scenario "admin members can view CMS admin area" do login_as admin_member visit comfy_admin_cms_path expect(current_path).to match(/#{comfy_admin_cms_path}/) # match any CMS admin page From 9a0fa34c0ad453d6118975b9fb0fd77d7bb21d22 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 9 Sep 2018 09:55:43 +1200 Subject: [PATCH 150/267] Style fix up --- spec/factories/member.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/factories/member.rb b/spec/factories/member.rb index 828c2f5aa..70aaaaab8 100644 --- a/spec/factories/member.rb +++ b/spec/factories/member.rb @@ -55,8 +55,8 @@ FactoryBot.define do factory :south_pole_member do sequence(:login_name) { |n| "ScottRF#{n}" } location 'Amundsen-Scott Base, Antarctica' - latitude -90 - longitude 0 + latitude { -90 } + longitude { 0 } end factory :admin_member do From f52acd528253f3585286d1ea2f910cbd8b85d76e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 13 Sep 2018 22:44:32 +1200 Subject: [PATCH 151/267] Adding puma to gem bundle --- Gemfile | 2 + Gemfile.lock | 125 ++++++++++++++++++++++++++------------------------- 2 files changed, 66 insertions(+), 61 deletions(-) diff --git a/Gemfile b/Gemfile index 942940db0..234304a0d 100644 --- a/Gemfile +++ b/Gemfile @@ -100,6 +100,8 @@ gem "paranoia", "~> 2.2" gem 'xmlrpc' # fixes rake error - can be removed if not needed later +gem 'puma' + group :production, :staging do gem 'bonsai-elasticsearch-rails' # Integration with Bonsa-Elasticsearch on heroku gem 'dalli' diff --git a/Gemfile.lock b/Gemfile.lock index 27dea9b08..f0592d19f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -72,15 +72,17 @@ GEM public_suffix (>= 2.0.2, < 4.0) arel (8.0.0) ast (2.4.0) - autoprefixer-rails (8.6.4) + autoprefixer-rails (9.1.4) execjs - bcrypt (3.1.11) - better_errors (2.4.0) + bcrypt (3.1.12) + better_errors (2.5.0) coderay (>= 1.0.0) erubi (>= 1.0.0) rack (>= 0.9.0) bluecloth (2.2.0) - bonsai-elasticsearch-rails (0.0.4) + bonsai-elasticsearch-rails (7.0.1) + elasticsearch-model (< 8) + elasticsearch-rails (< 8) bootstrap-datepicker-rails (1.8.0.1) railties (>= 3.0) bootstrap-kaminari-views (0.0.5) @@ -91,25 +93,25 @@ GEM sass (>= 3.3.4) bootstrap_form (2.7.0) builder (3.2.3) - bullet (5.7.5) + bullet (5.7.6) activesupport (>= 3.0.0) uniform_notifier (~> 1.11.0) byebug (10.0.2) cancancan (2.2.0) - capybara (2.18.0) + capybara (3.7.2) addressable mini_mime (>= 0.1.3) - nokogiri (>= 1.3.3) - rack (>= 1.0.0) - rack-test (>= 0.5.4) - xpath (>= 2.0, < 4.0) + nokogiri (~> 1.8) + rack (>= 1.6.0) + rack-test (>= 0.6.3) + xpath (~> 3.1) capybara-email (3.0.1) capybara (>= 2.4, < 4.0) mail capybara-screenshot (1.0.21) capybara (>= 1.0, < 4) launchy - chartkick (2.3.5) + chartkick (3.0.1) childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) climate_control (0.2.0) @@ -127,7 +129,7 @@ GEM execjs coffee-script-source (1.12.2) concurrent-ruby (1.0.5) - connection_pool (2.2.1) + connection_pool (2.2.2) coveralls (0.8.19) json (>= 1.8, < 3) simplecov (~> 0.12.0) @@ -139,7 +141,7 @@ GEM activesupport (>= 3.0.0) dalli (2.7.8) database_cleaner (1.7.0) - devise (4.4.3) + devise (4.5.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) railties (>= 4.1.0, < 6.0) @@ -147,9 +149,6 @@ GEM warden (~> 1.2.3) diff-lcs (1.3) docile (1.1.5) - easy_translate (0.5.1) - thread - thread_safe elasticsearch (6.1.0) elasticsearch-api (= 6.1.0) elasticsearch-transport (= 6.1.0) @@ -167,10 +166,10 @@ GEM erubis (2.7.0) excon (0.62.0) execjs (2.7.0) - factory_bot (4.10.0) + factory_bot (4.11.1) activesupport (>= 3.0.0) - factory_bot_rails (4.10.0) - factory_bot (~> 4.10.0) + factory_bot_rails (4.11.1) + factory_bot (~> 4.11.1) railties (>= 3.0.0) faker (1.9.1) i18n (>= 0.7) @@ -180,11 +179,11 @@ GEM figaro (1.1.1) thor (~> 0.14) flickraw (0.9.9) - font-awesome-sass (5.0.9) - sass (>= 3.2) + font-awesome-sass (5.3.1) + sassc (>= 1.11) friendly_id (5.2.4) activerecord (>= 4.0.0) - geocoder (1.4.9) + geocoder (1.5.0) gibbon (1.2.1) httparty multi_json (>= 1.9.0) @@ -208,7 +207,7 @@ GEM haml (>= 4.0.6, < 6.0) html2haml (>= 1.0.1) railties (>= 4.0.1) - haml_lint (0.27.0) + haml_lint (0.28.0) haml (>= 4.0, < 5.1) rainbow rake (>= 10, < 13) @@ -220,7 +219,7 @@ GEM excon moneta multi_json (>= 1.9.2) - highline (1.7.10) + highline (2.0.0) html2haml (2.2.0) erubis (~> 2.7.0) haml (>= 4.0, < 6) @@ -230,27 +229,27 @@ GEM multi_xml (>= 0.5.2) i18n (0.9.5) concurrent-ruby (~> 1.0) - i18n-tasks (0.9.21) + i18n-tasks (0.9.24) activesupport (>= 4.0.2) ast (>= 2.1.0) - easy_translate (>= 0.5.1) erubi - highline (>= 1.7.3) + highline (>= 2.0.0) i18n parser (>= 2.2.3.0) rainbow (>= 2.2.2, < 4.0) terminal-table (>= 1.5.1) + jaro_winkler (1.5.1) jquery-rails (4.3.3) rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) jquery-ui-rails (6.0.1) railties (>= 3.2.16) - js-routes (1.4.3) + js-routes (1.4.4) railties (>= 3.2) sprockets-rails json (2.1.0) - jsonapi-resources (0.9.0) + jsonapi-resources (0.9.3) activerecord (>= 4.1) concurrent-ruby railties (>= 4.1) @@ -286,20 +285,20 @@ GEM mini_mime (>= 0.1.1) memcachier (0.0.2) method_source (0.9.0) - mime-types (3.1) + mime-types (3.2.2) mime-types-data (~> 3.2015) - mime-types-data (3.2016.0521) + mime-types-data (3.2018.0812) mimemagic (0.3.2) - mini_mime (1.0.0) + mini_mime (1.0.1) mini_portile2 (2.3.0) minitest (5.11.3) moneta (0.8.1) multi_json (1.11.3) multi_xml (0.6.0) multipart-post (2.0.0) - newrelic_rpm (5.0.0.342) - nio4r (2.3.0) - nokogiri (1.8.2) + newrelic_rpm (5.4.0.347) + nio4r (2.3.1) + nokogiri (1.8.4) mini_portile2 (~> 2.3.0) oauth (0.5.4) oauth2 (1.4.0) @@ -335,7 +334,7 @@ GEM parallel (1.12.1) paranoia (2.4.1) activerecord (>= 4.0, < 5.3) - parser (2.5.1.0) + parser (2.5.1.2) ast (~> 2.4.0) pg (0.21.0) platform-api (2.1.0) @@ -343,16 +342,17 @@ GEM moneta (~> 0.8.1) plupload-rails (1.2.1) rails (>= 3.1) - poltergeist (1.17.0) - capybara (~> 2.1) + poltergeist (1.18.1) + capybara (>= 2.1, < 4) cliver (~> 0.3.1) websocket-driver (>= 0.2.0) - powerpack (0.1.1) - public_suffix (3.0.2) + powerpack (0.1.2) + public_suffix (3.0.3) + puma (3.12.0) rack (2.0.5) - rack-protection (2.0.1) + rack-protection (2.0.3) rack - rack-test (1.0.0) + rack-test (1.1.0) rack (>= 1.0, < 3) rails (5.1.4) actioncable (= 5.1.4) @@ -366,9 +366,9 @@ GEM bundler (>= 1.3.0) railties (= 5.1.4) sprockets-rails (>= 2.0.0) - rails-assets-leaflet (1.3.1) - rails-assets-leaflet.markercluster (1.3.0) - rails-assets-leaflet (>= 1.0.3) + rails-assets-leaflet (1.3.4) + rails-assets-leaflet.markercluster (1.4.0) + rails-assets-leaflet (>= 1.3.1) rails-controller-testing (1.0.2) actionpack (~> 5.x, >= 5.0.1) actionview (~> 5.x, >= 5.0.1) @@ -398,7 +398,7 @@ GEM rb-fsevent (0.10.3) rb-inotify (0.9.10) ffi (>= 0.5.0, < 2) - redis (4.0.1) + redis (4.0.2) responders (2.4.0) actionpack (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3) @@ -418,25 +418,26 @@ GEM actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.7.0) - rspec-expectations (~> 3.7.0) - rspec-mocks (~> 3.7.0) - rspec-support (~> 3.7.0) - rspec-support (3.7.1) - rubocop (0.55.0) + rspec-core (~> 3.8.0) + rspec-expectations (~> 3.8.0) + rspec-mocks (~> 3.8.0) + rspec-support (~> 3.8.0) + rspec-support (3.8.0) + rubocop (0.59.0) + jaro_winkler (~> 1.5.1) parallel (~> 1.10) - parser (>= 2.5) + parser (>= 2.5, != 2.5.1.1) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) - ruby-progressbar (1.9.0) + ruby-progressbar (1.10.0) ruby-units (2.3.0) ruby_dep (1.5.0) ruby_parser (3.11.0) sexp_processor (~> 4.9) rubyzip (1.2.2) - sass (3.5.6) + sass (3.5.7) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) @@ -447,13 +448,15 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) + sassc (1.12.1) + ffi (~> 1.9.6) + sass (>= 3.3.0) selenium-webdriver (3.14.0) childprocess (~> 0.5) rubyzip (~> 1.2) sexp_processor (4.11.0) - sidekiq (5.1.3) - concurrent-ruby (~> 1.0) - connection_pool (~> 2.2, >= 2.2.0) + sidekiq (5.2.1) + connection_pool (~> 2.2, >= 2.2.2) rack-protection (>= 1.5.0) redis (>= 3.3.5, < 5) simplecov (0.12.0) @@ -479,7 +482,6 @@ GEM terrapin (0.6.0) climate_control (>= 0.0.3, < 1.0) thor (0.19.4) - thread (0.2.2) thread_safe (0.3.6) tilt (2.0.8) timecop (0.9.1) @@ -487,9 +489,9 @@ GEM trollop (1.16.2) tzinfo (1.2.5) thread_safe (~> 0.1) - uglifier (4.1.15) + uglifier (4.1.19) execjs (>= 0.3.0, < 3) - unicode-display_width (1.3.2) + unicode-display_width (1.4.0) unicorn (5.4.1) kgio (~> 2.6) raindrops (~> 0.7) @@ -573,6 +575,7 @@ DEPENDENCIES pg (< 1.0.0) platform-api poltergeist + puma rack-protection (>= 2.0.1) rails (= 5.1.4) rails-assets-leaflet.markercluster! From aad7128a316c610cac2ee2d40ade77702b51ddd1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 13 Sep 2018 22:44:46 +1200 Subject: [PATCH 152/267] Fixed user name generation in member factorybot --- spec/factories/member.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/factories/member.rb b/spec/factories/member.rb index d293fc90b..a544e465a 100644 --- a/spec/factories/member.rb +++ b/spec/factories/member.rb @@ -1,6 +1,6 @@ FactoryBot.define do factory :member, aliases: %i(author owner sender recipient creator) do - login_name { generate(:login_name) } + login_name { (0...8).map { (65 + rand(26)).chr }.join } password { 'password1' } email { Faker::Internet.unique.email } tos_agreement { true } From 99a9c0817dbd06aadc6f88fecfbf390322b38720 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 13 Sep 2018 22:51:22 +1200 Subject: [PATCH 153/267] Lint fix --- lib/tasks/growstuff.rake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index 9fe5202d3..4a6234c4b 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -116,6 +116,7 @@ namespace :growstuff do task set_default_crop_creator: :environment do cropbot = Member.find_by(login_name: "cropbot") raise "cropbot not found: create cropbot member on site or run rake db:seed" unless cropbot + Crop.find_each do |crop| unless crop.creator crop.creator = cropbot @@ -150,6 +151,7 @@ namespace :growstuff do Member.located.find_each do |m| m.gardens.each do |g| next if g.location.present? + g.location = m.location g.latitude = m.latitude g.longitude = m.longitude @@ -218,6 +220,7 @@ namespace :growstuff do CSV.foreach(file) do |row| _crop_id, crop_name, alternate_names = row next if alternate_names.blank? + crop = Crop.find_by(name: crop_name) if crop alternate_names.split(/,\s*/).each do |an| From c16ee81c88561d06cdf3eba86de26844bd777b17 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 13 Sep 2018 22:51:42 +1200 Subject: [PATCH 154/267] Add rubocop-rspec --- Gemfile | 1 + Gemfile.lock | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Gemfile b/Gemfile index 234304a0d..80fc29b82 100644 --- a/Gemfile +++ b/Gemfile @@ -134,6 +134,7 @@ group :development, :test do gem 'poltergeist' # for headless JS testing gem 'rspec-activemodel-mocks' gem 'rspec-rails' # unit testing framework + gem 'rubocop-rspec' gem 'rubocop', '>= 0.54.0' gem 'selenium-webdriver' gem 'webrat' # provides HTML matchers for view tests diff --git a/Gemfile.lock b/Gemfile.lock index f0592d19f..0a7379bff 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -431,6 +431,8 @@ GEM rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.0, >= 1.0.1) + rubocop-rspec (1.29.1) + rubocop (>= 0.58.0) ruby-progressbar (1.10.0) ruby-units (2.3.0) ruby_dep (1.5.0) @@ -586,6 +588,7 @@ DEPENDENCIES rspec-activemodel-mocks rspec-rails rubocop (>= 0.54.0) + rubocop-rspec ruby-units sass-rails selenium-webdriver From ee49e8c5db9dfc2720031e97693dc3230ad3dfbe Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 13 Sep 2018 23:09:13 +1200 Subject: [PATCH 155/267] Fixing unneeded condition --- spec/features/rss/plantings_spec.rb | 2 +- spec/features/rss/posts_spec.rb | 2 +- spec/features/rss/seeds_spec.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/features/rss/plantings_spec.rb b/spec/features/rss/plantings_spec.rb index 59833eff1..c3f68fea6 100644 --- a/spec/features/rss/plantings_spec.rb +++ b/spec/features/rss/plantings_spec.rb @@ -9,6 +9,6 @@ feature 'Plantings RSS feed' do scenario 'The index title is what we expect' do visit plantings_path(format: 'rss') expect(page).to have_content "Recent plantings from "\ - "#{@owner ? @owner : 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" + "#{@owner || 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" end end diff --git a/spec/features/rss/posts_spec.rb b/spec/features/rss/posts_spec.rb index 445a50cca..668276fbb 100644 --- a/spec/features/rss/posts_spec.rb +++ b/spec/features/rss/posts_spec.rb @@ -9,6 +9,6 @@ feature 'Posts RSS feed' do scenario 'The index title is what we expect' do visit posts_path(format: 'rss') expect(page).to have_content "Recent posts from "\ - "#{@author ? @author : 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" + "#{@author || 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" end end diff --git a/spec/features/rss/seeds_spec.rb b/spec/features/rss/seeds_spec.rb index 888cc42ec..abb66e7e3 100644 --- a/spec/features/rss/seeds_spec.rb +++ b/spec/features/rss/seeds_spec.rb @@ -9,6 +9,6 @@ feature 'Seeds RSS feed' do scenario 'The index title is what we expect' do visit seeds_path(format: 'rss') expect(page).to have_content "Recent seeds from "\ - "#{@owner ? @owner : 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" + "#{@owner || 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" end end From 3ad048b7e85978db69fecaa0478b3bbb045ae73a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 13 Sep 2018 23:10:43 +1200 Subject: [PATCH 156/267] Fixed linter issue, empty line after guard clause --- app/controllers/crops_controller.rb | 2 ++ app/controllers/photo_associations_controller.rb | 1 + app/controllers/photos_controller.rb | 3 +++ app/helpers/application_helper.rb | 1 + app/helpers/harvests_helper.rb | 1 + app/helpers/plantings_helper.rb | 2 ++ app/models/concerns/predict_harvest.rb | 2 ++ app/models/concerns/predict_planting.rb | 1 + app/models/crop.rb | 5 +++++ app/models/csv_importer.rb | 1 + app/models/harvest.rb | 8 ++++++++ app/models/member.rb | 4 ++++ app/models/planting.rb | 1 + app/models/post.rb | 1 + config/initializers/comfortable_mexican_sofa.rb | 1 + lib/geocodable.rb | 1 + spec/lib/haml/filters/growstuff_markdown_spec.rb | 2 ++ spec/support/elasticsearch_helpers.rb | 1 + 18 files changed, 38 insertions(+) diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index 361e28031..c5b268f8b 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -128,6 +128,7 @@ class CropsController < ApplicationController def notify_wranglers return if current_member.role? :crop_wrangler + Role.crop_wranglers.each do |w| Notifier.new_crop_request(w, @crop).deliver_now! end @@ -135,6 +136,7 @@ class CropsController < ApplicationController def recreate_names(param_name, name_type) return if params[param_name].blank? + destroy_names(name_type) params[param_name].each do |_i, value| create_name!(name_type, value) unless value.empty? diff --git a/app/controllers/photo_associations_controller.rb b/app/controllers/photo_associations_controller.rb index c63cca398..743966d5d 100644 --- a/app/controllers/photo_associations_controller.rb +++ b/app/controllers/photo_associations_controller.rb @@ -4,6 +4,7 @@ class PhotoAssociationsController < ApplicationController def destroy raise "Photos not supported" unless Photo::PHOTO_CAPABLE.include? item_class + @photo = Photo.find_by!(id: params[:photo_id], owner: current_member) @item = Photographing.item(item_id, item_class) @item.photos.delete(@photo) diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index c9dd8886f..331a4e2c4 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -36,6 +36,7 @@ class PhotosController < ApplicationController @photo = find_or_create_photo_from_flickr_photo @item = item_to_link_to raise "Could not find this #{type} owned by you" unless @item + @item.photos << @photo unless @item.photos.include? @photo @photo.save! if @photo.present? end @@ -77,8 +78,10 @@ class PhotosController < ApplicationController def item_to_link_to raise "No item id provided" if item_id.nil? raise "No item type provided" if item_type.nil? + item_class = item_type.capitalize raise "Photos not supported" unless Photo::PHOTO_CAPABLE.include? item_class + item_class.constantize.find(params[:id]) end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index ca4bc9429..97ff16b76 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -39,6 +39,7 @@ module ApplicationHelper # def avatar_uri(member, size = 150) return unless member + if member.preferred_avatar_uri.present? # Some avatars support different sizes # http://graph.facebook.com/12345678/picture?width=150&height=150 diff --git a/app/helpers/harvests_helper.rb b/app/helpers/harvests_helper.rb index 10ed30888..ff1838ce4 100644 --- a/app/helpers/harvests_helper.rb +++ b/app/helpers/harvests_helper.rb @@ -24,6 +24,7 @@ module HarvestsHelper def display_weight(harvest) return if harvest.weight_quantity.blank? || harvest.weight_quantity <= 0 + "#{number_to_human(harvest.weight_quantity, strip_insignificant_zeros: true)} #{harvest.weight_unit}" end diff --git a/app/helpers/plantings_helper.rb b/app/helpers/plantings_helper.rb index 5f448975e..2ebe7569f 100644 --- a/app/helpers/plantings_helper.rb +++ b/app/helpers/plantings_helper.rb @@ -35,11 +35,13 @@ module PlantingsHelper def days_from_now_to_finished(planting) return unless planting.finish_is_predicatable? + (planting.finish_predicted_at - Time.zone.today).to_i end def days_from_now_to_first_harvest(planting) return unless planting.planted_at.present? && planting.first_harvest_predicted_at.present? + (planting.first_harvest_predicted_at - Time.zone.today).to_i end diff --git a/app/models/concerns/predict_harvest.rb b/app/models/concerns/predict_harvest.rb index d5422ee35..bc377f369 100644 --- a/app/models/concerns/predict_harvest.rb +++ b/app/models/concerns/predict_harvest.rb @@ -13,11 +13,13 @@ module PredictHarvest def first_harvest_predicted_at return unless crop.median_days_to_first_harvest.present? && planted_at.present? + planted_at + crop.median_days_to_first_harvest.days end def last_harvest_predicted_at return unless crop.median_days_to_last_harvest.present? && planted_at.present? + planted_at + crop.median_days_to_last_harvest.days end diff --git a/app/models/concerns/predict_planting.rb b/app/models/concerns/predict_planting.rb index ff66168d8..c7ca81d01 100644 --- a/app/models/concerns/predict_planting.rb +++ b/app/models/concerns/predict_planting.rb @@ -33,6 +33,7 @@ module PredictPlanting def actual_lifespan return unless planted_at.present? && finished_at.present? + (finished_at - planted_at).to_i end diff --git a/app/models/crop.rb b/app/models/crop.rb index 45df93ad2..3da542aee 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -156,6 +156,7 @@ class Crop < ApplicationRecord min_photos = 3 # needs this many photos to be interesting return false unless photos.size >= min_photos return false unless plantings_count >= min_plantings + true end @@ -181,6 +182,7 @@ class Crop < ApplicationRecord def rejection_explanation return rejection_notes if reason_for_rejection == "other" + reason_for_rejection end @@ -222,17 +224,20 @@ class Crop < ApplicationRecord def approval_status_cannot_be_changed_again previous = previous_changes.include?(:approval_status) ? previous_changes.approval_status : {} return unless previous.include?(:rejected) || previous.include?(:approved) + errors.add(:approval_status, "has already been set to #{approval_status}") end def must_be_rejected_if_rejected_reasons_present return if rejected? return unless reason_for_rejection.present? || rejection_notes.present? + errors.add(:approval_status, "must be rejected if a reason for rejection is present") end def must_have_meaningful_reason_for_rejection return unless reason_for_rejection == "other" && rejection_notes.blank? + errors.add(:rejection_notes, "must be added if the reason for rejection is \"other\"") end diff --git a/app/models/csv_importer.rb b/app/models/csv_importer.rb index 4205a6c13..d3b992aba 100644 --- a/app/models/csv_importer.rb +++ b/app/models/csv_importer.rb @@ -54,6 +54,7 @@ class CsvImporter def add_alternate_names(alternate_names) # i.e. we actually passed something in, which isn't a given return if alternate_names.blank? + alternate_names.split(/,\s*/).each do |name| altname = AlternateName.find_by(name: name, crop: @crop) altname ||= AlternateName.create! name: name, crop: @crop, creator: cropbot diff --git a/app/models/harvest.rb b/app/models/harvest.rb index c9829fed7..987c83d0b 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -70,6 +70,7 @@ class Harvest < ApplicationRecord def time_from_planting_to_harvest return if planting.blank? + harvested_at - planting.planted_at end @@ -77,6 +78,7 @@ class Harvest < ApplicationRecord # to make data manipulation easier def set_si_weight return if weight_unit.nil? + weight_string = "#{weight_quantity} #{weight_unit}" self.si_weight = Unit.new(weight_string).convert_to("kg").to_s("%0.3f").delete(" kg").to_f end @@ -101,11 +103,13 @@ class Harvest < ApplicationRecord def quantity_to_human return number_to_human(quantity.to_s, strip_insignificant_zeros: true) if quantity + "" end def unit_to_human return "" unless quantity + if unit == 'individual' 'individual' elsif quantity == 1 @@ -117,6 +121,7 @@ class Harvest < ApplicationRecord def weight_to_human return "" unless weight_quantity + "weighing #{number_to_human(weight_quantity, strip_insignificant_zeros: true)} #{weight_unit}" end @@ -138,17 +143,20 @@ class Harvest < ApplicationRecord def crop_must_match_planting return if planting.blank? # only check if we are linked to a planting + errors.add(:planting, "must be the same crop") unless crop == planting.crop end def owner_must_match_planting return if planting.blank? # only check if we are linked to a planting + errors.add(:owner, "of harvest must be the same as planting") unless owner == planting.owner end def harvest_must_be_after_planting # only check if we are linked to a planting return unless harvested_at.present? && planting.present? && planting.planted_at.present? + errors.add(:planting, "cannot be harvested before planting") unless harvested_at > planting.planted_at end end diff --git a/app/models/member.rb b/app/models/member.rb index 655f3c5aa..ec3414c77 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -85,6 +85,7 @@ class Member < ApplicationRecord conditions = warden_conditions.dup login = conditions.delete(:login) return where(conditions).login_name_or_email(login).first if login + find_by(conditions) end @@ -133,6 +134,7 @@ class Member < ApplicationRecord ) end return [result.photo, result.total] if result + [[], 0] end @@ -182,6 +184,7 @@ class Member < ApplicationRecord def newsletter_subscribe(gibbon = Gibbon::API.new, testing = false) return true if Rails.env.test? && !testing + gibbon.lists.subscribe( id: Rails.application.config.newsletter_list_id, email: { email: email }, @@ -192,6 +195,7 @@ class Member < ApplicationRecord def newsletter_unsubscribe(gibbon = Gibbon::API.new, testing = false) return true if Rails.env.test? && !testing + gibbon.lists.unsubscribe(id: Rails.application.config.newsletter_list_id, email: { email: email }) end diff --git a/app/models/planting.rb b/app/models/planting.rb index f6966d94f..61b75e326 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -101,6 +101,7 @@ class Planting < ApplicationRecord # check that any finished_at date occurs after planted_at def finished_must_be_after_planted return unless planted_at && finished_at # only check if we have both + errors.add(:finished_at, "must be after the planting date") unless planted_at < finished_at end diff --git a/app/models/post.rb b/app/models/post.rb index 2dc254741..bde34cfe3 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -77,6 +77,7 @@ class Post < ApplicationRecord # don't send notifications to yourself recipients.map(&:id).each do |recipient_id| next unless recipient_id != sender + Notification.create( recipient_id: recipient_id, sender_id: sender, diff --git a/config/initializers/comfortable_mexican_sofa.rb b/config/initializers/comfortable_mexican_sofa.rb index 314bc21fe..43630ef0a 100644 --- a/config/initializers/comfortable_mexican_sofa.rb +++ b/config/initializers/comfortable_mexican_sofa.rb @@ -96,6 +96,7 @@ end module CmsDeviseAuth def authenticate return if current_member&.role?(:admin) + redirect_to root_path, alert: 'Permission denied. Please sign in as an admin user to use the CMS admin area.' end end diff --git a/lib/geocodable.rb b/lib/geocodable.rb index 7e00c7566..f1bb243f6 100644 --- a/lib/geocodable.rb +++ b/lib/geocodable.rb @@ -7,6 +7,7 @@ module Geocodable def empty_unwanted_geocodes return if location.present? + self.latitude = nil self.longitude = nil end diff --git a/spec/lib/haml/filters/growstuff_markdown_spec.rb b/spec/lib/haml/filters/growstuff_markdown_spec.rb index 58626d036..e4dea52d9 100644 --- a/spec/lib/haml/filters/growstuff_markdown_spec.rb +++ b/spec/lib/haml/filters/growstuff_markdown_spec.rb @@ -9,6 +9,7 @@ end def output_link(crop, name = nil) url = Rails.application.routes.url_helpers.crop_url(crop, host: Rails.application.config.host) return "#{name}" if name + "#{crop.name}" end @@ -19,6 +20,7 @@ end def output_member_link(member, name = nil) url = Rails.application.routes.url_helpers.member_url(member, only_path: true) return "#{name}" if name + "#{member.login_name}" end diff --git a/spec/support/elasticsearch_helpers.rb b/spec/support/elasticsearch_helpers.rb index aaa4fd689..7cd3fe5f2 100644 --- a/spec/support/elasticsearch_helpers.rb +++ b/spec/support/elasticsearch_helpers.rb @@ -1,6 +1,7 @@ module ElasticsearchHelpers def sync_elasticsearch(crops) return unless ENV['GROWSTUFF_ELASTICSEARCH'] == "true" + crops.each { |crop| crop.__elasticsearch__.index_document } Crop.__elasticsearch__.refresh_index! end From 7c7d261e7e445ce0574fe113fba9caccb68f9250 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 13 Sep 2018 23:13:03 +1200 Subject: [PATCH 157/267] Fixed last static factorybot attribtue --- spec/factories/notifications.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/factories/notifications.rb b/spec/factories/notifications.rb index 32c4aad94..5b734ed28 100644 --- a/spec/factories/notifications.rb +++ b/spec/factories/notifications.rb @@ -5,7 +5,7 @@ FactoryBot.define do sender { FactoryBot.create :member } recipient { FactoryBot.create :member } - subject "MyString" + subject { "MyString" } body { "MyText" } read { false } post From e2874404e471fd80ace4883b50bea1618c774aa5 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 13 Sep 2018 23:15:01 +1200 Subject: [PATCH 158/267] Layout linter fix --- spec/factories/notifications.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/factories/notifications.rb b/spec/factories/notifications.rb index 5b734ed28..b0b3dce97 100644 --- a/spec/factories/notifications.rb +++ b/spec/factories/notifications.rb @@ -2,7 +2,6 @@ FactoryBot.define do factory :notification, aliases: [:message] do - sender { FactoryBot.create :member } recipient { FactoryBot.create :member } subject { "MyString" } From b3ecdb0ae533e025d6542e47790b8d0daa0fcffd Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 13 Sep 2018 23:16:16 +1200 Subject: [PATCH 159/267] Removed include in rubocop, was making rubocop not check files --- .rubocop.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 9a8a0a405..316ffcde7 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,13 +1,9 @@ inherit_from: .rubocop_todo.yml AllCops: - Include: - - 'Rakefile' - - 'config.ru' - - 'lib/**/*.rake' Exclude: - 'db/schema.rb' - 'vendor/**/*' - TargetRailsVersion: 4.0 + TargetRailsVersion: 5.0 Rails: Enabled: true @@ -21,7 +17,6 @@ Naming/FileName: Style/StringLiterals: Enabled: false -# Stop hound and codeclimate fighting Style/PercentLiteralDelimiters: PreferredDelimiters: default: () @@ -36,8 +31,6 @@ Layout/MultilineMethodCallIndentation: Layout/AlignParameters: EnforcedStyle: with_fixed_indentation -Metrics/LineLength: - Max: 120 Style/Documentation: Enabled: false @@ -58,6 +51,9 @@ Metrics/BlockLength: - '**/*.rake' - 'config/**/*.rb' +Metrics/LineLength: + Max: 120 + # Remove the following once the code style matches Metrics/MethodLength: Max: 34 From 5031b37232386d1c8d84592e5366c7af415871fd Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 29 Sep 2018 15:51:35 +1200 Subject: [PATCH 160/267] Adding \n into specs, because our output has it now --- .../plantings/planting_a_crop_spec.rb | 20 +++-- spec/features/seeds/adding_seeds_spec.rb | 85 ++++++++++--------- spec/features/shared_examples/append_date.rb | 2 +- 3 files changed, 56 insertions(+), 51 deletions(-) diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index 0e26d7078..bde169dd0 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -211,7 +211,7 @@ feature "Planting a crop", :js, :elasticsearch do click_button "Save" end expect(page).to have_content "planting was successfully created" - expect(page).to have_content "Finished: August 30, 2014" + expect(page).to have_content "Finished:\nAugust 30, 2014" # shouldn't be on the page visit plantings_path @@ -223,15 +223,17 @@ feature "Planting a crop", :js, :elasticsearch do end scenario "Marking a planting as finished without a date" do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" - within "form#new_planting" do - check "Mark as finished" - click_button "Save" + before do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + check "Mark as finished" + click_button "Save" + end end - expect(page).to have_content "planting was successfully created" - expect(page).to have_content "Finished: Yes (no date specified)" - expect(page).to have_content "100%" + it { expect(page).to have_content "planting was successfully created" } + it { expect(page).to have_content "Finished:\nYes (no date specified)" } + it { expect(page).to have_content "100%" } end describe "Planting sunniness" do diff --git a/spec/features/seeds/adding_seeds_spec.rb b/spec/features/seeds/adding_seeds_spec.rb index 4c183ae24..8a875cc85 100644 --- a/spec/features/seeds/adding_seeds_spec.rb +++ b/spec/features/seeds/adding_seeds_spec.rb @@ -17,53 +17,56 @@ feature "Seeds", :js, :elasticsearch do expect(page).to have_content "* denotes a required field" end - it "displays required and optional fields properly" do - expect(page).to have_selector ".form-group.required", text: "Crop:" - expect(page).to have_optional 'input#seed_quantity' - expect(page).to have_optional 'input#seed_plant_before' - expect(page).to have_optional 'input#seed_days_until_maturity_min' - expect(page).to have_optional 'input#seed_days_until_maturity_max' - expect(page).to have_selector '.form-group.required', text: 'Organic?' - expect(page).to have_selector '.form-group.required', text: 'GMO?' - expect(page).to have_selector '.form-group.required', text: 'Heirloom?' - expect(page).to have_optional 'textarea#seed_description' - expect(page).to have_selector '.form-group.required', text: 'Will trade:' + describe "displays required and optional fields properly" do + it { expect(page).to have_selector ".form-group.required", text: "Crop:" } + it { expect(page).to have_optional 'input#seed_quantity' } + it { expect(page).to have_optional 'input#seed_plant_before' } + it { expect(page).to have_optional 'input#seed_days_until_maturity_min' } + it { expect(page).to have_optional 'input#seed_days_until_maturity_max' } + it { expect(page).to have_selector '.form-group.required', text: 'Organic?' } + it { expect(page).to have_selector '.form-group.required', text: 'GMO?' } + it { expect(page).to have_selector '.form-group.required', text: 'Heirloom?' } + it { expect(page).to have_optional 'textarea#seed_description' } + it { expect(page).to have_selector '.form-group.required', text: 'Will trade:' } end - scenario "Adding a new seed", js: true do - fill_autocomplete "crop", with: "mai" - select_from_autocomplete "maize" - within "form#new_seed" do - fill_in "Quantity:", with: 42 - fill_in "Plant before:", with: "2014-06-15" - fill_in "Days until maturity:", with: 999 - fill_in "to", with: 1999 - select "certified organic", from: "Organic?" - select "non-certified GMO-free", from: "GMO?" - select "heirloom", from: "Heirloom?" - fill_in "Description", with: "It's killer." - select "internationally", from: "Will trade:" - click_button "Save" + describe "Adding a new seed", js: true do + before do + fill_autocomplete "crop", with: "mai" + select_from_autocomplete "maize" + within "form#new_seed" do + fill_in "Quantity:", with: 42 + fill_in "Plant before:", with: "2014-06-15" + fill_in "Days until maturity:", with: 999 + fill_in "to", with: 1999 + select "certified organic", from: "Organic?" + select "non-certified GMO-free", from: "GMO?" + select "heirloom", from: "Heirloom?" + fill_in "Description", with: "It's killer." + select "internationally", from: "Will trade:" + click_button "Save" + end end - - expect(page).to have_content "Successfully added maize seed to your stash" - expect(page).to have_content "Quantity: 42" - expect(page).to have_content "Days until maturity: 999–1999" - expect(page).to have_content "certified organic" - expect(page).to have_content "non-certified GMO-free" - expect(page).to have_content "Heirloom? heirloom" - expect(page).to have_content "It's killer." + it { expect(page).to have_content "Successfully added maize seed to your stash" } + it { expect(page).to have_content "Quantity:\n42" } + it { expect(page).to have_content "Days until maturity:\n999–1999" } + it { expect(page).to have_content "certified organic" } + it { expect(page).to have_content "non-certified GMO-free" } + it { expect(page).to have_content "Heirloom?\nheirloom" } + it { expect(page).to have_content "It's killer." } end - scenario "Adding a seed from crop page" do - visit crop_path(maize) - click_link "Add seeds to stash" - within "form#new_seed" do - expect(page).to have_selector "input[value='maize']" - click_button "Save" + describe "Adding a seed from crop page" do + before do + visit crop_path(maize) + click_link "Add seeds to stash" + within "form#new_seed" do + expect(page).to have_selector "input[value='maize']" + click_button "Save" + end end - expect(page).to have_content "Successfully added maize seed to your stash" - expect(page).to have_content "maize" + it { expect(page).to have_content "Successfully added maize seed to your stash" } + it { expect(page).to have_content "maize" } end end diff --git a/spec/features/shared_examples/append_date.rb b/spec/features/shared_examples/append_date.rb index 03e29c5f4..64de66e13 100644 --- a/spec/features/shared_examples/append_date.rb +++ b/spec/features/shared_examples/append_date.rb @@ -10,7 +10,7 @@ shared_examples "append date" do expect(page).to have_content this_month.to_s find(".datepicker-days td.day", text: "21").click end - expect(page).to have_content "Finished: #{this_month} 21, #{this_year}" + expect(page).to have_content "Finished:\n#{this_month} 21, #{this_year}" end scenario "Confirming without selecting date" do From d1d1a61be36e9d89ac2a3dfb9b01f6cba65aad73 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 29 Sep 2018 15:52:32 +1200 Subject: [PATCH 161/267] Added inverse to model --- app/models/comment.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/comment.rb b/app/models/comment.rb index 3eda14aa4..7c98a919a 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,5 +1,5 @@ class Comment < ApplicationRecord - belongs_to :author, -> { with_deleted }, class_name: 'Member' + belongs_to :author, -> { with_deleted }, class_name: 'Member', inverse_of: :comment belongs_to :post scope :post_order, -> { reorder("created_at ASC") } # for display on post page From 9694696570fc8f1971ff8d852b48343ffad70af0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 29 Sep 2018 15:52:42 +1200 Subject: [PATCH 162/267] Code style fix ups --- spec/controllers/plantings_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/plantings_controller_spec.rb b/spec/controllers/plantings_controller_spec.rb index ebe0e00eb..7f100d76b 100644 --- a/spec/controllers/plantings_controller_spec.rb +++ b/spec/controllers/plantings_controller_spec.rb @@ -19,7 +19,7 @@ describe PlantingsController do let!(:planting2) { FactoryBot.create :planting, crop: maize, owner: member2, created_at: 5.days.ago } describe "assigns all plantings as @plantings" do - before { get :index, {} } + before { get :index } it { expect(assigns(:plantings)).to match [planting1, planting2] } end @@ -82,7 +82,7 @@ describe PlantingsController do end describe "sets the date of the planting to today" do - before { get :new, {} } + before { get :new } it { expect(assigns(:planting).planted_at).to eq Time.zone.today } end From cd1bf8c2682ea92f0783f933aa6bc798d43223f2 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 29 Sep 2018 15:53:06 +1200 Subject: [PATCH 163/267] Code style fix up --- spec/factories/member.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/factories/member.rb b/spec/factories/member.rb index a544e465a..fcd72c05e 100644 --- a/spec/factories/member.rb +++ b/spec/factories/member.rb @@ -1,6 +1,6 @@ FactoryBot.define do factory :member, aliases: %i(author owner sender recipient creator) do - login_name { (0...8).map { (65 + rand(26)).chr }.join } + login_name { (0...8).map { rand(65..90).chr }.join } password { 'password1' } email { Faker::Internet.unique.email } tos_agreement { true } From 1bb70d4bcd19e6b2fc868e0b56adf911e58fa704 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 29 Sep 2018 15:55:07 +1200 Subject: [PATCH 164/267] Ordering gems --- Gemfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile b/Gemfile index 80fc29b82..31250e27a 100644 --- a/Gemfile +++ b/Gemfile @@ -134,8 +134,8 @@ group :development, :test do gem 'poltergeist' # for headless JS testing gem 'rspec-activemodel-mocks' gem 'rspec-rails' # unit testing framework - gem 'rubocop-rspec' gem 'rubocop', '>= 0.54.0' + gem 'rubocop-rspec' gem 'selenium-webdriver' gem 'webrat' # provides HTML matchers for view tests end From fb2f5f464a96c42809cf68fb3283122e0f0bdc6e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 8 Oct 2018 09:47:52 +1300 Subject: [PATCH 165/267] Change scenario to description --- spec/features/plantings/planting_a_crop_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index bde169dd0..3da396ee0 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -222,7 +222,7 @@ feature "Planting a crop", :js, :elasticsearch do expect(page).to have_content "August 30, 2014" end - scenario "Marking a planting as finished without a date" do + describe "Marking a planting as finished without a date" do before do fill_autocomplete "crop", with: "mai" select_from_autocomplete "maize" From 05da2de7e47fbdc85f41490786de492cb7a1a445 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 8 Oct 2018 09:48:49 +1300 Subject: [PATCH 166/267] Fix up text in checking appended date --- spec/features/shared_examples/append_date.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/shared_examples/append_date.rb b/spec/features/shared_examples/append_date.rb index 64de66e13..74c7f8497 100644 --- a/spec/features/shared_examples/append_date.rb +++ b/spec/features/shared_examples/append_date.rb @@ -16,6 +16,6 @@ shared_examples "append date" do scenario "Confirming without selecting date" do click_link link_text click_link "Confirm without date" - expect(page).to have_content("Finished: Yes (no date specified) ") + expect(page).to have_content("Finished:\nYes (no date specified) ") end end From 1e7e275684549846e11427427a8af93973e660d9 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 8 Oct 2018 13:43:09 +1300 Subject: [PATCH 167/267] Adding inverse relationships (except for photos) --- app/models/comment.rb | 2 +- app/models/crop.rb | 4 ++-- app/models/member.rb | 26 ++++++++++++++------------ app/models/seed.rb | 3 ++- 4 files changed, 19 insertions(+), 16 deletions(-) diff --git a/app/models/comment.rb b/app/models/comment.rb index 7c98a919a..3c9f3ce42 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,5 +1,5 @@ class Comment < ApplicationRecord - belongs_to :author, -> { with_deleted }, class_name: 'Member', inverse_of: :comment + belongs_to :author, -> { with_deleted }, class_name: 'Member', inverse_of: :comments belongs_to :post scope :post_order, -> { reorder("created_at ASC") } # for display on post page diff --git a/app/models/crop.rb b/app/models/crop.rb index 3da542aee..ba4787b97 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -19,8 +19,8 @@ class Crop < ApplicationRecord belongs_to :creator, class_name: 'Member', optional: true belongs_to :requester, class_name: 'Member', optional: true belongs_to :parent, class_name: 'Crop', optional: true - has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id', dependent: :nullify - has_and_belongs_to_many :posts # rubocop:disable Rails/HasAndBelongsToMany + has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id', dependent: :nullify, inverse_of: :parent + has_and_belongs_to_many :posts ## ## Scopes diff --git a/app/models/member.rb b/app/models/member.rb index ec3414c77..69f5e61b6 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -8,21 +8,23 @@ class Member < ApplicationRecord # # Relationships - has_many :posts, foreign_key: 'author_id', dependent: :destroy - has_many :comments, foreign_key: 'author_id', dependent: :destroy - has_many :forums, foreign_key: 'owner_id', dependent: :nullify - has_many :gardens, foreign_key: 'owner_id', dependent: :destroy - has_many :plantings, foreign_key: 'owner_id', dependent: :destroy - has_many :seeds, foreign_key: 'owner_id', dependent: :destroy - has_many :harvests, foreign_key: 'owner_id', dependent: :destroy + has_many :posts, foreign_key: 'author_id', dependent: :destroy, inverse_of: :author + has_many :comments, foreign_key: 'author_id', dependent: :destroy, inverse_of: :author + has_many :forums, foreign_key: 'owner_id', dependent: :nullify, inverse_of: :owner + has_many :gardens, foreign_key: 'owner_id', dependent: :destroy, inverse_of: :owner + has_many :plantings, foreign_key: 'owner_id', dependent: :destroy, inverse_of: :owner + has_many :seeds, foreign_key: 'owner_id', dependent: :destroy, inverse_of: :owner + has_many :harvests, foreign_key: 'owner_id', dependent: :destroy, inverse_of: :owner has_and_belongs_to_many :roles # rubocop:disable Rails/HasAndBelongsToMany - has_many :notifications, foreign_key: 'recipient_id' - has_many :sent_notifications, foreign_key: 'sender_id' + has_many :notifications, foreign_key: 'recipient_id', inverse_of: :recipient + has_many :sent_notifications, foreign_key: 'sender_id', inverse_of: :sender has_many :authentications, dependent: :destroy - has_many :photos - has_many :requested_crops, class_name: 'Crop', foreign_key: 'requester_id', dependent: :nullify + has_many :photos, inverse_of: :owner + has_many :requested_crops, class_name: 'Crop', foreign_key: 'requester_id', dependent: :nullify, + inverse_of: :requester has_many :likes, dependent: :destroy - has_many :follows, class_name: "Follow", foreign_key: "follower_id", dependent: :destroy + has_many :follows, class_name: "Follow", foreign_key: "follower_id", dependent: :destroy, + inverse_of: :follower has_many :inverse_follows, class_name: "Follow", foreign_key: "followed_id", dependent: :destroy has_many :followed, through: :follows has_many :followers, through: :inverse_follows, source: :follower diff --git a/app/models/seed.rb b/app/models/seed.rb index 8d33e7ff8..1eae0db62 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -16,7 +16,8 @@ class Seed < ApplicationRecord belongs_to :parent_planting, class_name: 'Planting', foreign_key: 'parent_planting_id', required: false # parent has_many :child_plantings, class_name: 'Planting', - foreign_key: 'parent_seed_id', dependent: :nullify # children + foreign_key: 'parent_seed_id', dependent: :nullify, + inverse_of: :parent_planting # children # # Validations From fe2536c864b62f575045f5d4239344a767f2e5b8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 8 Oct 2018 14:15:44 +1300 Subject: [PATCH 168/267] More spec updates --- spec/features/crops/crop_detail_page_spec.rb | 2 +- spec/features/seeds/misc_seeds_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 62f80d37f..e4e3d05e0 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -193,7 +193,7 @@ feature "crop detail page", js: true do end it "predicts harvest" do - is_expected.to have_text("First harvest expected 20 days after planting") + is_expected.to have_text("First harvest expected\n20 days after planting") end end end diff --git a/spec/features/seeds/misc_seeds_spec.rb b/spec/features/seeds/misc_seeds_spec.rb index ec1946d2c..c1172fcb2 100644 --- a/spec/features/seeds/misc_seeds_spec.rb +++ b/spec/features/seeds/misc_seeds_spec.rb @@ -50,7 +50,7 @@ feature "seeds", js: true do scenario "view seeds with max and min days until maturity" do seed = create :seed, days_until_maturity_min: 5, days_until_maturity_max: 7 visit seed_path(seed) - expect(page).to have_content "Days until maturity: 5–7" + expect(page).to have_content "Days until maturity:\n5–7" end scenario "view seeds with only max days until maturity" do From aded3c00fcf1e89eff6e3f14b26f63415a5d2f00 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 8 Oct 2018 14:17:28 +1300 Subject: [PATCH 169/267] More spec updates --- spec/views/seeds/show.html.haml_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/views/seeds/show.html.haml_spec.rb b/spec/views/seeds/show.html.haml_spec.rb index fd2848f97..b94804142 100644 --- a/spec/views/seeds/show.html.haml_spec.rb +++ b/spec/views/seeds/show.html.haml_spec.rb @@ -26,7 +26,7 @@ describe "seeds/show" do it "shows tradable attributes" do render - rendered.should have_content "Will trade: locally" + rendered.should have_content "Will trade:\nlocally" end it "shows location of seed owner" do From 7a44e9499d3edc7d3434e84ebcaa5f1fba502331 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Mon, 8 Oct 2018 14:18:19 +1300 Subject: [PATCH 170/267] More markup updates to fit specs --- app/views/crops/edit.html.haml | 3 ++- app/views/seeds/index.rss.haml | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/crops/edit.html.haml b/app/views/crops/edit.html.haml index 1c497d838..1d9963547 100644 --- a/app/views/crops/edit.html.haml +++ b/app/views/crops/edit.html.haml @@ -9,7 +9,8 @@ Approved by #{link_to @crop.creator, @crop.creator}. - else %p - Added by #{link_to @crop.creator, @crop.creator} + Added by + = link_to @crop.creator, @crop.creator #{distance_of_time_in_words(@crop.created_at, Time.zone.now)} ago. - elsif @crop.approval_status == "pending" .alert.alert-danger diff --git a/app/views/seeds/index.rss.haml b/app/views/seeds/index.rss.haml index 36d542706..b2044de6e 100644 --- a/app/views/seeds/index.rss.haml +++ b/app/views/seeds/index.rss.haml @@ -17,8 +17,7 @@

Heirloom? #{seed.heirloom}

- if seed.tradable? %p - Will trade #{seed.tradable_to} from - = seed.owner.location ? seed.owner.location : 'unknown location' + Will trade #{seed.tradable_to} from #{seed.owner.location ? seed.owner.location : 'unknown location'} :escaped_markdown #{ strip_tags seed.description } From 6c2afb28048236a03d652669eea53d727f06c326 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 10:16:45 +1300 Subject: [PATCH 171/267] Adding missing inverswe relationship alternatename.creator --- app/models/member.rb | 4 +++- spec/models/alternate_name_spec.rb | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/models/member.rb b/app/models/member.rb index 69f5e61b6..3bde53e53 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -22,10 +22,12 @@ class Member < ApplicationRecord has_many :photos, inverse_of: :owner has_many :requested_crops, class_name: 'Crop', foreign_key: 'requester_id', dependent: :nullify, inverse_of: :requester + has_many :created_alternate_names, class_name: 'AlternateName', foreign_key: 'creator_id', inverse_of: :creator has_many :likes, dependent: :destroy has_many :follows, class_name: "Follow", foreign_key: "follower_id", dependent: :destroy, inverse_of: :follower - has_many :inverse_follows, class_name: "Follow", foreign_key: "followed_id", dependent: :destroy + has_many :inverse_follows, class_name: "Follow", foreign_key: "followed_id", + dependent: :destroy, inverse_of: :followed has_many :followed, through: :follows has_many :followers, through: :inverse_follows, source: :follower diff --git a/spec/models/alternate_name_spec.rb b/spec/models/alternate_name_spec.rb index f358a9fca..a76749130 100644 --- a/spec/models/alternate_name_spec.rb +++ b/spec/models/alternate_name_spec.rb @@ -18,4 +18,14 @@ describe AlternateName do expect(crop.alternate_names).to include an expect(crop.alternate_names).to include an2 end + + describe 'relationships' do + let(:alternate_name) { FactoryBot.create :alternate_name, crop: crop, creator: member } + let(:crop) { FactoryBot.create :crop } + let(:member) { FactoryBot.create :member } + + it { expect(alternate_name.crop).to eq crop } + it { expect(alternate_name.creator).to eq member } + it { expect(member.created_alternate_names).to eq [alternate_name] } + end end From fc0a941fb6e9ed441b7b3c6d322829046051fff6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 11:32:03 +1300 Subject: [PATCH 172/267] Adding more inverse relationships --- app/models/crop.rb | 8 ++++---- app/models/follow.rb | 4 ++-- app/models/member.rb | 15 ++++++++++++--- app/models/notification.rb | 4 ++-- app/models/post.rb | 2 +- app/models/scientific_name.rb | 2 +- app/models/seed.rb | 2 +- 7 files changed, 23 insertions(+), 14 deletions(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index ba4787b97..829a3fc6a 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -16,11 +16,11 @@ class Crop < ApplicationRecord has_many :harvests, dependent: :destroy has_many :photos, through: :plantings has_many :plant_parts, -> { distinct.order("plant_parts.name") }, through: :harvests - belongs_to :creator, class_name: 'Member', optional: true - belongs_to :requester, class_name: 'Member', optional: true - belongs_to :parent, class_name: 'Crop', optional: true + belongs_to :creator, class_name: 'Member', optional: true, inverse_of: :created_crops + belongs_to :requester, class_name: 'Member', optional: true, inverse_of: :requestd_crops + belongs_to :parent, class_name: 'Crop', optional: true, inverse_of: :varieties has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id', dependent: :nullify, inverse_of: :parent - has_and_belongs_to_many :posts + has_and_belongs_to_many :posts # rubocop:disable Rails/HasAndBelongsToMany ## ## Scopes diff --git a/app/models/follow.rb b/app/models/follow.rb index 34028857b..a70fd15f6 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -1,6 +1,6 @@ class Follow < ApplicationRecord - belongs_to :follower, class_name: "Member" - belongs_to :followed, class_name: "Member" + belongs_to :follower, class_name: "Member", inverse_of: :follows + belongs_to :followed, class_name: "Member", inverse_of: :inverse_follows validates :follower_id, uniqueness: { scope: :followed_id } after_create do diff --git a/app/models/member.rb b/app/models/member.rb index 3bde53e53..3a997840d 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -20,10 +20,10 @@ class Member < ApplicationRecord has_many :sent_notifications, foreign_key: 'sender_id', inverse_of: :sender has_many :authentications, dependent: :destroy has_many :photos, inverse_of: :owner - has_many :requested_crops, class_name: 'Crop', foreign_key: 'requester_id', dependent: :nullify, - inverse_of: :requester - has_many :created_alternate_names, class_name: 'AlternateName', foreign_key: 'creator_id', inverse_of: :creator has_many :likes, dependent: :destroy + + # + # Following other members has_many :follows, class_name: "Follow", foreign_key: "follower_id", dependent: :destroy, inverse_of: :follower has_many :inverse_follows, class_name: "Follow", foreign_key: "followed_id", @@ -31,6 +31,15 @@ class Member < ApplicationRecord has_many :followed, through: :follows has_many :followers, through: :inverse_follows, source: :follower + # + # Global data records this member created + has_many :requested_crops, class_name: 'Crop', foreign_key: 'requester_id', dependent: :nullify, + inverse_of: :requester + has_many :created_crops, class_name: 'Crop', foreign_key: 'creator_id', dependent: :nullify, + inverse_of: :creator + has_many :created_alternate_names, class_name: 'AlternateName', foreign_key: 'creator_id', inverse_of: :creator + has_many :created_scientific_names, class_name: 'ScientificName', foreign_key: 'creator_id', inverse_of: :creator + # # Scopes scope :confirmed, -> { where.not(confirmed_at: nil) } diff --git a/app/models/notification.rb b/app/models/notification.rb index c9f915420..d4e8db676 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -1,6 +1,6 @@ class Notification < ApplicationRecord - belongs_to :sender, class_name: 'Member' - belongs_to :recipient, class_name: 'Member' + belongs_to :sender, class_name: 'Member', inverse_of: :sent_notifications + belongs_to :recipient, class_name: 'Member', inverse_of: :notifications belongs_to :post, optional: true validates :subject, length: { maximum: 255 } diff --git a/app/models/post.rb b/app/models/post.rb index bde34cfe3..9e570b845 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -5,7 +5,7 @@ class Post < ApplicationRecord # # Relationships - belongs_to :author, class_name: 'Member' + belongs_to :author, class_name: 'Member', inverse_of: :posts belongs_to :forum, optional: true has_many :comments, dependent: :destroy has_and_belongs_to_many :crops # rubocop:disable Rails/HasAndBelongsToMany diff --git a/app/models/scientific_name.rb b/app/models/scientific_name.rb index 812b696b8..7b20d2e9e 100644 --- a/app/models/scientific_name.rb +++ b/app/models/scientific_name.rb @@ -1,7 +1,7 @@ class ScientificName < ApplicationRecord after_commit { |sn| sn.crop.__elasticsearch__.index_document if sn.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == "true" } belongs_to :crop - belongs_to :creator, class_name: 'Member' + belongs_to :creator, class_name: 'Member', inverse_of: :created_scientific_names validates :name, presence: true validates :crop, presence: true end diff --git a/app/models/seed.rb b/app/models/seed.rb index 34c0d9e78..d9a2261d2 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -14,7 +14,7 @@ class Seed < ApplicationRecord # Relationships belongs_to :crop belongs_to :parent_planting, class_name: 'Planting', foreign_key: 'parent_planting_id', - required: false # parent + required: false, inverse_of: :child_seeds # parent has_many :child_plantings, class_name: 'Planting', foreign_key: 'parent_seed_id', dependent: :nullify, inverse_of: :parent_seed # children From 0a65e57d5378b5b617b3acc0077255642eea5e32 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 12:42:15 +1300 Subject: [PATCH 173/267] Fixed up text in spec --- spec/features/shared_examples/append_date.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/features/shared_examples/append_date.rb b/spec/features/shared_examples/append_date.rb index 74c7f8497..b2c19e5f1 100644 --- a/spec/features/shared_examples/append_date.rb +++ b/spec/features/shared_examples/append_date.rb @@ -16,6 +16,6 @@ shared_examples "append date" do scenario "Confirming without selecting date" do click_link link_text click_link "Confirm without date" - expect(page).to have_content("Finished:\nYes (no date specified) ") + expect(page).to have_content("Finished:\nYes (no date specified)") end end From c1dabfc3d33dcd870253eedd2f8ede369cb00aa8 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 12:42:49 +1300 Subject: [PATCH 174/267] Typo fix, requestd_crops to requested_crops --- app/models/crop.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/crop.rb b/app/models/crop.rb index 829a3fc6a..525e3fb8d 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -17,7 +17,7 @@ class Crop < ApplicationRecord has_many :photos, through: :plantings has_many :plant_parts, -> { distinct.order("plant_parts.name") }, through: :harvests belongs_to :creator, class_name: 'Member', optional: true, inverse_of: :created_crops - belongs_to :requester, class_name: 'Member', optional: true, inverse_of: :requestd_crops + belongs_to :requester, class_name: 'Member', optional: true, inverse_of: :requested_crops belongs_to :parent, class_name: 'Crop', optional: true, inverse_of: :varieties has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id', dependent: :nullify, inverse_of: :parent has_and_belongs_to_many :posts # rubocop:disable Rails/HasAndBelongsToMany From 03da26f949c11e54da79bac599e04a84c58b5774 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 12:45:18 +1300 Subject: [PATCH 175/267] Upgrade nokogiri --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0a7379bff..8155116a6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -298,7 +298,7 @@ GEM multipart-post (2.0.0) newrelic_rpm (5.4.0.347) nio4r (2.3.1) - nokogiri (1.8.4) + nokogiri (1.8.5) mini_portile2 (~> 2.3.0) oauth (0.5.4) oauth2 (1.4.0) From 0d3588a2b25f4680aa51ca0d44c30b78d7a82fc0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 12:47:05 +1300 Subject: [PATCH 176/267] Add another inverse_of created_alternate_names --- app/models/alternate_name.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/alternate_name.rb b/app/models/alternate_name.rb index 0d7f12198..94e404b49 100644 --- a/app/models/alternate_name.rb +++ b/app/models/alternate_name.rb @@ -1,7 +1,7 @@ class AlternateName < ApplicationRecord after_commit { |an| an.crop.__elasticsearch__.index_document if an.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == "true" } belongs_to :crop - belongs_to :creator, class_name: 'Member' + belongs_to :creator, class_name: 'Member', inverse_of: :created_alternate_names validates :name, presence: true validates :crop, presence: true end From de2175ce16242dd1b9f9e2dd95d01c018302fd7a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 13:20:03 +1300 Subject: [PATCH 177/267] More inverse relationships defined --- app/models/garden.rb | 2 +- app/models/photo.rb | 3 ++- app/models/photographing.rb | 2 +- app/models/planting.rb | 12 ++++++++---- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/app/models/garden.rb b/app/models/garden.rb index 9687982cb..01466120f 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -62,7 +62,7 @@ class Garden < ApplicationRecord unique_plantings = [] seen_crops = [] - plantings.order(created_at: :desc).includes(:garden, :crop, :owner, :harvests).each do |p| + plantings.includes(:garden, :crop, :owner, :harvests).order(created_at: :desc).each do |p| unless seen_crops.include?(p.crop) unique_plantings.push(p) seen_crops.push(p.crop) diff --git a/app/models/photo.rb b/app/models/photo.rb index 69a30d245..f3636760c 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -3,7 +3,8 @@ class Photo < ApplicationRecord PHOTO_CAPABLE = %w(Garden Planting Harvest Seed).freeze - has_many :photographings, foreign_key: :photo_id, dependent: :destroy + has_many :photographings, foreign_key: :photo_id, dependent: :destroy, inverse_of: :photo + # creates a relationship for each assignee type PHOTO_CAPABLE.each do |type| has_many type.downcase.pluralize.to_s.to_sym, diff --git a/app/models/photographing.rb b/app/models/photographing.rb index 040817611..b62ed10e6 100644 --- a/app/models/photographing.rb +++ b/app/models/photographing.rb @@ -1,5 +1,5 @@ class Photographing < ApplicationRecord - belongs_to :photo + belongs_to :photo, inverse_of: :photographings belongs_to :photographable, polymorphic: true validate :photo_and_item_have_same_owner diff --git a/app/models/planting.rb b/app/models/planting.rb index 61b75e326..27f99870b 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -21,10 +21,14 @@ class Planting < ApplicationRecord # # Ancestry of food - belongs_to :parent_seed, class_name: 'Seed', foreign_key: 'parent_seed_id', - required: false # parent - has_many :child_seeds, class_name: 'Seed', - foreign_key: 'parent_planting_id', dependent: :nullify # children + belongs_to :parent_seed, class_name: 'Seed', # parent + foreign_key: 'parent_seed_id', + required: false, + inverse_of: :child_plantings + has_many :child_seeds, class_name: 'Seed', # children + foreign_key: 'parent_planting_id', + inverse_of: :parent_planting, + dependent: :nullify ## ## Scopes From 510124758d50c1278f59c933abda7f54e3a53151 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 13:26:54 +1300 Subject: [PATCH 178/267] Inverse relation ships --- app/models/concerns/likeable.rb | 2 +- app/models/concerns/ownable.rb | 3 ++- app/models/concerns/photo_capable.rb | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/models/concerns/likeable.rb b/app/models/concerns/likeable.rb index e898b8bab..328cf3153 100644 --- a/app/models/concerns/likeable.rb +++ b/app/models/concerns/likeable.rb @@ -2,7 +2,7 @@ module Likeable extend ActiveSupport::Concern included do - has_many :likes, as: :likeable, dependent: :destroy + has_many :likes, as: :likeable, inverse_of: :likeable, dependent: :destroy has_many :members, through: :likes end end diff --git a/app/models/concerns/ownable.rb b/app/models/concerns/ownable.rb index b9f229973..eea4c9ac7 100644 --- a/app/models/concerns/ownable.rb +++ b/app/models/concerns/ownable.rb @@ -2,6 +2,7 @@ module Ownable extend ActiveSupport::Concern included do - belongs_to :owner, class_name: 'Member', foreign_key: 'owner_id', counter_cache: true + belongs_to :owner, class_name: 'Member', # rubocop:disable Rails/InverseOf + foreign_key: 'owner_id', counter_cache: true end end diff --git a/app/models/concerns/photo_capable.rb b/app/models/concerns/photo_capable.rb index 758569c35..3ae7303d9 100644 --- a/app/models/concerns/photo_capable.rb +++ b/app/models/concerns/photo_capable.rb @@ -2,7 +2,7 @@ module PhotoCapable extend ActiveSupport::Concern included do - has_many :photographings, as: :photographable, dependent: :destroy + has_many :photographings, as: :photographable, dependent: :destroy, inverse_of: :photographable has_many :photos, through: :photographings, as: :photographable scope :has_photos, -> { includes(:photos).where.not(photos: { id: nil }) } From ec4c6f13aa7754a35ef6755a0e80d3b5ae29a395 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 13:56:10 +1300 Subject: [PATCH 179/267] Updating new seed view specs --- spec/views/seeds/new.html.haml_spec.rb | 44 +++++++++++--------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/spec/views/seeds/new.html.haml_spec.rb b/spec/views/seeds/new.html.haml_spec.rb index 5c5cf3ae4..fdea300fe 100644 --- a/spec/views/seeds/new.html.haml_spec.rb +++ b/spec/views/seeds/new.html.haml_spec.rb @@ -1,16 +1,17 @@ require 'rails_helper' describe "seeds/new" do + let!(:seed) { FactoryBot.create(:seed, owner: member) } + let!(:member) { FactoryBot.create(:member) } + before(:each) do - @member = FactoryBot.create(:member) - sign_in @member + sign_in member controller.stub(:current_user) { @member } - @seed1 = FactoryBot.create(:seed, owner: @member) - assign(:seed, @seed1) + assign(:seed, seed) + render end it "renders new seed form" do - render assert_select "form", action: seeds_path, method: "post" do assert_select "input#crop", class: "ui-autocomplete-input" assert_select "input#seed_crop_id", name: "seed[crop_id]" @@ -20,30 +21,23 @@ describe "seeds/new" do end end - it 'reminds you to set your location' do - render - rendered.should have_content "Don't forget to set your location." - assert_select "a", text: "set your location" + context 'member has no location' do + describe 'reminds you to set your location' do + it { expect(rendered).to have_content "Don't forget to\nset your location." } + it { expect(rendered).to have_link "set your location" } + end end - context 'member has location' do - before(:each) do - @member = FactoryBot.create(:london_member) - sign_in @member - controller.stub(:current_user) { @member } - @seed1 = FactoryBot.create(:seed, owner: @member) - assign(:seed, @seed1) + context 'when member has location' do + let!(:member) { FactoryBot.create(:london_member) } + + describe 'shows the location' do + it { expect(rendered).to have_text "from\n#{member.location}." } + it { expect(rendered).to have_link(member.location, href: place_path(member.location)) } end - it 'shows the location' do - render - rendered.should have_content "from #{@member.location}." - assert_select 'a', href: place_path(@member.location) - end - - it 'links to change location' do - render - assert_select "a", text: "Change your location." + it 'link to change location' do + expect(rendered).to have_link("Change your location.") end end end From 92939ca2043a63f0f50a1667b8ca2824b4dace98 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 14:08:37 +1300 Subject: [PATCH 180/267] Spec updates --- app/views/alternate_names/edit.html.haml | 2 +- app/views/scientific_names/edit.html.haml | 2 +- spec/features/planting_reminder_spec.rb | 2 +- .../scientific_names/edit.html.haml_spec.rb | 16 +++++++++------- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/app/views/alternate_names/edit.html.haml b/app/views/alternate_names/edit.html.haml index 0818bb0ff..35728110a 100644 --- a/app/views/alternate_names/edit.html.haml +++ b/app/views/alternate_names/edit.html.haml @@ -2,7 +2,7 @@ %p Added by - = @alternate_name.creator + = link_to @alternate_name.creator, @alternate_name.creator = distance_of_time_in_words(@alternate_name.created_at, Time.zone.now) ago. diff --git a/app/views/scientific_names/edit.html.haml b/app/views/scientific_names/edit.html.haml index db7f9bf71..0cdebe6cf 100644 --- a/app/views/scientific_names/edit.html.haml +++ b/app/views/scientific_names/edit.html.haml @@ -2,7 +2,7 @@ %p Added by - = @scientific_name.creator + = link_to @scientific_name.creator, @scientific_name.creator = distance_of_time_in_words(@scientific_name.created_at, Time.zone.now) ago. diff --git a/spec/features/planting_reminder_spec.rb b/spec/features/planting_reminder_spec.rb index 3b407c3df..bcb86d576 100644 --- a/spec/features/planting_reminder_spec.rb +++ b/spec/features/planting_reminder_spec.rb @@ -41,7 +41,7 @@ feature "Planting reminder email", :js do context "when member has no harvests" do scenario "tells you to tracking plantings" do - expect(mail).to have_content "Get started now by tracking your first harvest" + expect(mail).to have_content "Get started now\nby tracking your first harvest" end scenario "doesn't list plantings" do diff --git a/spec/views/scientific_names/edit.html.haml_spec.rb b/spec/views/scientific_names/edit.html.haml_spec.rb index ecaa2056f..2d6fd73a5 100644 --- a/spec/views/scientific_names/edit.html.haml_spec.rb +++ b/spec/views/scientific_names/edit.html.haml_spec.rb @@ -2,21 +2,23 @@ require 'rails_helper' describe "scientific_names/edit" do context "logged in" do + let(:member) { FactoryBot.create(:member) } + let(:scientific_name) { FactoryBot.create(:zea_mays, creator: member) } + before(:each) do - @member = FactoryBot.create(:member) - sign_in @member - controller.stub(:current_user) { @member } - @scientific_name = assign(:scientific_name, - FactoryBot.create(:zea_mays)) + sign_in member + controller.stub(:current_user) { member } + assign(:scientific_name, scientific_name) render end it "shows the creator" do - rendered.should have_content "Added by #{@scientific_name.creator} less than a minute ago." + expect(rendered).to have_content "Added by\n#{member}\nless than a minute\nago." end + it { expect(rendered).to have_link member } it "renders the edit scientific_name form" do - assert_select "form", action: scientific_names_path(@scientific_name), method: "post" do + assert_select "form", action: scientific_names_path(scientific_name), method: "post" do assert_select "input#scientific_name_name", name: "scientific_name[scientific_name]" assert_select "select#scientific_name_crop_id", name: "scientific_name[crop_id]" end From fb156ec43894620d667cc127debaf92db1482497 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 14:20:15 +1300 Subject: [PATCH 181/267] Updating edit seeds spec --- spec/features/seeds/misc_seeds_spec.rb | 88 ++++++++++++++------------ 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/spec/features/seeds/misc_seeds_spec.rb b/spec/features/seeds/misc_seeds_spec.rb index c1172fcb2..3687ca630 100644 --- a/spec/features/seeds/misc_seeds_spec.rb +++ b/spec/features/seeds/misc_seeds_spec.rb @@ -1,31 +1,38 @@ require 'rails_helper' feature "seeds", js: true do + let(:member) { create :member } + context "signed in user" do - let(:member) { create :member } let(:crop) { create :crop } background { login_as member } - scenario "button on index to edit seed" do - seed = create :seed, owner: member - visit seeds_path - click_link "edit_seed_glyphicon" - expect(current_path).to eq edit_seed_path(seed) - expect(page).to have_content 'Editing seeds' + describe "button on index to edit seed" do + let!(:seed) { create :seed, owner: member } + before do + visit seeds_path + click_link "edit_seed_glyphicon" + end + it { expect(current_path).to eq edit_seed_path(seed) } + it { expect(page).to have_content 'Editing seeds' } end - scenario "button on front page to add seeds" do - visit root_path - click_link "Add seeds" - expect(current_path).to eq new_seed_path - expect(page).to have_content 'Add seeds' + describe "button on front page to add seeds" do + before do + visit root_path + click_link "Add seeds" + end + it { expect(current_path).to eq new_seed_path } + it { expect(page).to have_content 'Add seeds' } end - scenario "Clicking link to owner's profile" do - visit seeds_by_owner_path(member) - click_link "View #{member}'s profile >>" - expect(current_path).to eq member_path(member) + describe "Clicking link to owner's profile" do + before do + visit seeds_by_owner_path(member) + click_link "View #{member}'s profile >>" + end + it { expect(current_path).to eq member_path(member) } end # actually adding seeds is in spec/features/seeds_new_spec.rb @@ -40,35 +47,36 @@ feature "seeds", js: true do expect(current_path).to eq seed_path(seed) end - scenario "delete seeds" do - seed = create :seed, owner: member - visit seed_path(seed) - click_link 'Delete' - expect(current_path).to eq seeds_path + describe "delete seeds" do + let(:seed) { FactoryBot.create :seed, owner: member } + before do + visit seed_path(seed) + click_link 'Delete' + end + it { expect(current_path).to eq seeds_path } end - scenario "view seeds with max and min days until maturity" do - seed = create :seed, days_until_maturity_min: 5, days_until_maturity_max: 7 - visit seed_path(seed) - expect(page).to have_content "Days until maturity:\n5–7" - end + describe '#show' do + before { visit seed_path(seed) } + describe "view seeds with max and min days until maturity" do + let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5, days_until_maturity_max: 7 } + it { expect(page).to have_content "Days until maturity:\n5–7" } + end - scenario "view seeds with only max days until maturity" do - seed = create :seed, days_until_maturity_max: 7 - visit seed_path(seed) - expect(page).to have_content "Days until maturity: 7" - end + describe "view seeds with only max days until maturity" do + let(:seed) { FactoryBot.create :seed, days_until_maturity_max: 7 } + it { expect(page).to have_content "Days until maturity:\n7" } + end - scenario "view seeds with only min days until maturity" do - seed = create :seed, days_until_maturity_min: 5 - visit seed_path(seed) - expect(page).to have_content "Days until maturity: 5" - end + describe "view seeds with only min days until maturity" do + let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5 } + it { expect(page).to have_content "Days until maturity:\n5" } + end - scenario "view seeds with neither max nor min days until maturity" do - seed = create :seed - visit seed_path(seed) - expect(page).to have_content "Days until maturity: unknown" + describe "view seeds with neither max nor min days until maturity" do + let(:seed) { FactoryBot.create :seed } + it { expect(page).to have_content "Days until maturity:\nunknown" } + end end end end From 918f73d0f029942e26f9baaf6da205285bec4808 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 14:29:01 +1300 Subject: [PATCH 182/267] Update crop edit spec --- spec/views/crops/edit.html.haml_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/views/crops/edit.html.haml_spec.rb b/spec/views/crops/edit.html.haml_spec.rb index 19fac21af..6dbae67d4 100644 --- a/spec/views/crops/edit.html.haml_spec.rb +++ b/spec/views/crops/edit.html.haml_spec.rb @@ -14,6 +14,6 @@ describe "crops/edit" do end it "shows the creator" do - rendered.should have_content "Added by #{@crop.creator} less than a minute ago." + expect(rendered).to have_content "Added by\n#{@crop.creator}\nless than a minute\nago." end end From ac8dff2a28e2fb15c153f09874529bdc85365e9e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 14:29:44 +1300 Subject: [PATCH 183/267] Update new post spec --- spec/views/posts/new.html.haml_spec.rb | 44 ++++++++++++-------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/spec/views/posts/new.html.haml_spec.rb b/spec/views/posts/new.html.haml_spec.rb index fa344e55b..9bf53e563 100644 --- a/spec/views/posts/new.html.haml_spec.rb +++ b/spec/views/posts/new.html.haml_spec.rb @@ -1,16 +1,16 @@ require 'rails_helper' describe "posts/new" do + let(:author) { FactoryBot.create(:member) } before(:each) do - @author = FactoryBot.create(:member) - assign(:post, FactoryBot.create(:post, author: @author)) + assign(:post, FactoryBot.create(:post, author: author)) # assign(:forum, Forum.new) - sign_in @author - controller.stub(:current_user) { @author } + sign_in author + controller.stub(:current_user) { author } + render end it "renders new post form" do - render assert_select "form", action: posts_path, method: "post" do assert_select "input#post_subject", name: "post[subject]" assert_select "textarea#post_body", name: "post[body]" @@ -18,44 +18,42 @@ describe "posts/new" do end it 'no hidden forum field' do - render assert_select "input#post_forum_id[type=hidden]", false end it 'no forum mentioned' do - render - rendered.should_not have_content "This post will be posted in the forum" + expect(rendered).not_to have_content "This post will be posted in the forum" end it "asks what's going on in your garden" do - render - rendered.should have_content "What's going on in your food garden?" + expect(rendered).to have_content "What's going on in your food garden?" + end + + it 'shows markdown help' do + expect(rendered).to have_content 'Markdown' end context "forum specified" do + let(:forum) { FactoryBot.create(:forum) } + before(:each) do - @forum = assign(:forum, FactoryBot.create(:forum)) - assign(:post, FactoryBot.create(:post, forum: @forum)) + assign(:forum, forum) + assign(:post, FactoryBot.create(:post, forum: forum)) render end it 'creates a hidden field' do - assert_select "input#post_forum_id[type='hidden'][value='#{@forum.id}']" + assert_select "input#post_forum_id[type='hidden'][value='#{forum.id}']" end it 'tells the user what forum it will be posted in' do - rendered.should have_content "This post will be posted in the forum #{@forum.name}" + expect(rendered).to have_content "This post will be posted in the forum\n#{forum.name}" end + it { expect(rendered).to have_link forum.name } - it "asks what's going on generally" do - render - rendered.should_not have_content "What's going on in your food garden?" - rendered.should have_content "What's up?" + describe "asks what's going on generally" do + it { expect(rendered).to have_content "What's going on in your food garden?" } + it { expect(rendered).to have_content "What's up?" } end end - - it 'shows markdown help' do - render - rendered.should have_content 'Markdown' - end end From cf11cbd7d248cb4488e78df3599e0492febb8a3c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 16 Oct 2018 15:11:46 +1300 Subject: [PATCH 184/267] Update seeds specs --- spec/views/seeds/show.html.haml_spec.rb | 73 +++++++++++++------------ 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/spec/views/seeds/show.html.haml_spec.rb b/spec/views/seeds/show.html.haml_spec.rb index b94804142..7c7604001 100644 --- a/spec/views/seeds/show.html.haml_spec.rb +++ b/spec/views/seeds/show.html.haml_spec.rb @@ -1,62 +1,65 @@ require 'rails_helper' describe "seeds/show" do + let(:seed) { FactoryBot.create(:seed) } before(:each) do controller.stub(:current_user) { nil } - @seed = FactoryBot.create(:seed) - assign(:seed, @seed) - assign(:photos, @seed.photos.paginate(page: 1)) + assign(:seed, seed) + assign(:photos, seed.photos.paginate(page: 1)) + render end it "renders attributes in

" do - render - rendered.should have_content @seed.crop.name + expect(rendered).to have_content seed.crop.name end context "tradable" do - before(:each) do - @owner = FactoryBot.create(:london_member) - assign(:seed, FactoryBot.create(:tradable_seed, - owner: @owner)) - # note current_member is not the owner of this seed - @member = FactoryBot.create(:member) - sign_in @member - controller.stub(:current_user) { @member } - end + context 'with location' do + let!(:owner) { FactoryBot.create(:london_member) } + let!(:seed) { FactoryBot.create(:tradable_seed, owner: owner) } + let!(:member) { FactoryBot.create(:member) } - it "shows tradable attributes" do - render - rendered.should have_content "Will trade:\nlocally" - end + before(:each) do + assign(:seed, seed) + # note current_member is not the owner of this seed + sign_in member + controller.stub(:current_user) { member } + render + end - it "shows location of seed owner" do - render - rendered.should have_content @owner.location - assert_select 'a', href: place_path(@owner.location) + it "shows tradable attributes" do + expect(rendered).to have_content "Will trade:\n\nlocally" + end + + it "shows button to send message" do + expect(rendered).to have_content "Request seeds" + end + + describe "shows location of seed owner" do + it { expect(rendered).to have_content owner.location } + it { expect(rendered).to have_link seed.owner.location, href: place_path(seed.owner.location, anchor: "seeds") } + end end context 'with no location' do + # no location + let(:owner) { FactoryBot.create(:member) } + let!(:seed) { FactoryBot.create(:tradable_seed, owner: owner) } + before(:each) do - @owner = FactoryBot.create(:member) # no location - sign_in @owner - controller.stub(:current_user) { @owner } - assign(:seed, FactoryBot.create(:tradable_seed, owner: @owner)) + sign_in owner + controller.stub(:current_user) { owner } + assign(:seed, seed) + render end it 'says "from unspecified location"' do - render - rendered.should have_content "(from unspecified location)" + expect(rendered).to have_content "(from unspecified location)" end it "links to profile to set location" do - render - assert_select "a[href='#{url_for(edit_member_registration_path)}']", text: "Set Location" + expect(rendered).to have_link("Set Location") # , href: edit_member_registration_path) end end - - it "shows button to send message" do - render - rendered.should have_content "Request seeds" - end end end From ec22039fc16b4bd460844a2b16d3b99f1c944562 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Fri, 19 Oct 2018 07:47:05 +0000 Subject: [PATCH 185/267] Bump rack-protection from 2.0.3 to 2.0.4 Bumps [rack-protection](https://github.com/sinatra/sinatra) from 2.0.3 to 2.0.4. - [Release notes](https://github.com/sinatra/sinatra/releases) - [Changelog](https://github.com/sinatra/sinatra/blob/master/CHANGELOG.md) - [Commits](https://github.com/sinatra/sinatra/compare/v2.0.3...v2.0.4) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index ccbb8a1f0..18ad6f05d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -368,7 +368,7 @@ GEM quiet_assets (1.1.0) railties (>= 3.1, < 5.0) rack (1.6.10) - rack-protection (2.0.3) + rack-protection (2.0.4) rack rack-test (0.6.3) rack (>= 1.0) From ebe7cc3868ff226e3284572f2c842d3d50a5f52d Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Tue, 11 Sep 2018 03:03:12 +0000 Subject: [PATCH 186/267] Auto corrected by following Ruby Style/UnneededCondition --- spec/features/rss/plantings_spec.rb | 2 +- spec/features/rss/posts_spec.rb | 2 +- spec/features/rss/seeds_spec.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/features/rss/plantings_spec.rb b/spec/features/rss/plantings_spec.rb index 59833eff1..c3f68fea6 100644 --- a/spec/features/rss/plantings_spec.rb +++ b/spec/features/rss/plantings_spec.rb @@ -9,6 +9,6 @@ feature 'Plantings RSS feed' do scenario 'The index title is what we expect' do visit plantings_path(format: 'rss') expect(page).to have_content "Recent plantings from "\ - "#{@owner ? @owner : 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" + "#{@owner || 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" end end diff --git a/spec/features/rss/posts_spec.rb b/spec/features/rss/posts_spec.rb index 445a50cca..668276fbb 100644 --- a/spec/features/rss/posts_spec.rb +++ b/spec/features/rss/posts_spec.rb @@ -9,6 +9,6 @@ feature 'Posts RSS feed' do scenario 'The index title is what we expect' do visit posts_path(format: 'rss') expect(page).to have_content "Recent posts from "\ - "#{@author ? @author : 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" + "#{@author || 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" end end diff --git a/spec/features/rss/seeds_spec.rb b/spec/features/rss/seeds_spec.rb index 888cc42ec..abb66e7e3 100644 --- a/spec/features/rss/seeds_spec.rb +++ b/spec/features/rss/seeds_spec.rb @@ -9,6 +9,6 @@ feature 'Seeds RSS feed' do scenario 'The index title is what we expect' do visit seeds_path(format: 'rss') expect(page).to have_content "Recent seeds from "\ - "#{@owner ? @owner : 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" + "#{@owner || 'all members'} (#{ENV['GROWSTUFF_SITE_NAME']})" end end From 6be0486e598e9dce1d2963e574b0c08780dba2d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Fri, 19 Oct 2018 17:59:57 +0000 Subject: [PATCH 187/267] Bump selenium-webdriver from 3.14.0 to 3.14.1 Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 3.14.0 to 3.14.1. - [Release notes](https://github.com/SeleniumHQ/selenium/releases) - [Changelog](https://github.com/SeleniumHQ/selenium/blob/master/rb/CHANGES) - [Commits](https://github.com/SeleniumHQ/selenium/commits) Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 18ad6f05d..aea8b6a19 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -469,9 +469,9 @@ GEM sassc (2.0.0) ffi (~> 1.9.6) rake - selenium-webdriver (3.14.0) + selenium-webdriver (3.14.1) childprocess (~> 0.5) - rubyzip (~> 1.2) + rubyzip (~> 1.2, >= 1.2.2) sexp_processor (4.11.0) shellany (0.0.1) sidekiq (5.2.2) From c4849a2e3e42787f2be3b24891d9bf3cd147a244 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Fri, 19 Oct 2018 17:58:58 +0000 Subject: [PATCH 188/267] Bump platform-api from 2.1.0 to 2.2.0 Bumps [platform-api](https://github.com/heroku/platform-api) from 2.1.0 to 2.2.0. - [Release notes](https://github.com/heroku/platform-api/releases) - [Commits](https://github.com/heroku/platform-api/compare/v2.1.0...v2.2.0) Signed-off-by: dependabot[bot] --- Gemfile.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index aea8b6a19..c2a116f92 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -226,7 +226,7 @@ GEM rubocop (>= 0.49.0) sysexits (~> 1.1) hashie (3.5.7) - heroics (0.0.24) + heroics (0.0.25) erubis (~> 2.0) excon moneta @@ -305,7 +305,7 @@ GEM mini_mime (1.0.0) mini_portile2 (2.3.0) minitest (5.11.3) - moneta (0.8.1) + moneta (1.0.0) multi_json (1.11.3) multi_xml (0.6.0) multipart-post (2.0.0) @@ -351,9 +351,9 @@ GEM parser (2.5.1.0) ast (~> 2.4.0) pg (0.21.0) - platform-api (2.1.0) - heroics (~> 0.0.23) - moneta (~> 0.8.1) + platform-api (2.2.0) + heroics (~> 0.0.25) + moneta (~> 1.0.0) plupload-rails (1.2.1) rails (>= 3.1) poltergeist (1.17.0) From c5a58975e33938f41fc2bdd441a9a48fe85c19e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Fri, 19 Oct 2018 17:59:55 +0000 Subject: [PATCH 189/267] Bump cancancan from 2.2.0 to 2.3.0 Bumps [cancancan](https://github.com/CanCanCommunity/cancancan) from 2.2.0 to 2.3.0. - [Release notes](https://github.com/CanCanCommunity/cancancan/releases) - [Changelog](https://github.com/CanCanCommunity/cancancan/blob/develop/CHANGELOG.md) - [Commits](https://github.com/CanCanCommunity/cancancan/compare/2.2.0...2.3.0) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index c2a116f92..85148fa25 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -76,7 +76,7 @@ GEM activesupport (>= 3.0.0) uniform_notifier (~> 1.11.0) byebug (10.0.2) - cancancan (2.2.0) + cancancan (2.3.0) capybara (2.18.0) addressable mini_mime (>= 0.1.3) From 6aa77041ce1cbe854c6bff8e4ef08ad7e70d5460 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 11 Sep 2018 05:02:50 +0000 Subject: [PATCH 190/267] Bump jsonapi-resources from 0.9.0 to 0.9.3 Bumps [jsonapi-resources](https://github.com/cerebris/jsonapi-resources) from 0.9.0 to 0.9.3. - [Release notes](https://github.com/cerebris/jsonapi-resources/releases) - [Commits](https://github.com/cerebris/jsonapi-resources/compare/v0.9.0...v0.9.3) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 85148fa25..fdefdfbbe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -261,7 +261,7 @@ GEM railties (>= 3.2) sprockets-rails json (2.1.0) - jsonapi-resources (0.9.0) + jsonapi-resources (0.9.3) activerecord (>= 4.1) concurrent-ruby railties (>= 4.1) From 235136523e74a0c0ab510c848844373428a57d17 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Fri, 19 Oct 2018 19:21:31 +0000 Subject: [PATCH 191/267] Bump codeclimate-test-reporter from 1.0.8 to 1.0.9 Bumps [codeclimate-test-reporter](https://github.com/codeclimate/ruby-test-reporter) from 1.0.8 to 1.0.9. - [Release notes](https://github.com/codeclimate/ruby-test-reporter/releases) - [Changelog](https://github.com/codeclimate/ruby-test-reporter/blob/master/CHANGELOG.md) - [Commits](https://github.com/codeclimate/ruby-test-reporter/compare/v1.0.8...v1.0.9) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index fdefdfbbe..bc082dd74 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -95,7 +95,7 @@ GEM ffi (~> 1.0, >= 1.0.11) climate_control (0.2.0) cliver (0.3.2) - codeclimate-test-reporter (1.0.8) + codeclimate-test-reporter (1.0.9) simplecov (<= 0.13) codemirror-rails (5.16.0) railties (>= 3.0, < 6.0) From b80b6d21878507da864688d41ccbc138b523c06a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 22 Oct 2018 20:26:53 +0000 Subject: [PATCH 192/267] Bump capybara-screenshot from 1.0.21 to 1.0.22 Bumps [capybara-screenshot](https://github.com/mattheworiordan/capybara-screenshot) from 1.0.21 to 1.0.22. - [Release notes](https://github.com/mattheworiordan/capybara-screenshot/releases) - [Changelog](https://github.com/mattheworiordan/capybara-screenshot/blob/master/CHANGELOG.md) - [Commits](https://github.com/mattheworiordan/capybara-screenshot/compare/v1.0.21...v1.0.22) Signed-off-by: dependabot[bot] --- Gemfile.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index bc082dd74..4b2ad7d55 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -87,7 +87,7 @@ GEM capybara-email (3.0.1) capybara (>= 2.4, < 4.0) mail - capybara-screenshot (1.0.21) + capybara-screenshot (1.0.22) capybara (>= 1.0, < 4) launchy chartkick (3.0.1) @@ -302,7 +302,7 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) mimemagic (0.3.2) - mini_mime (1.0.0) + mini_mime (1.0.1) mini_portile2 (2.3.0) minitest (5.11.3) moneta (1.0.0) @@ -364,7 +364,7 @@ GEM pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) - public_suffix (3.0.2) + public_suffix (3.0.3) quiet_assets (1.1.0) railties (>= 3.1, < 5.0) rack (1.6.10) @@ -527,7 +527,7 @@ GEM websocket-extensions (0.1.3) will_paginate (3.1.6) xmlrpc (0.3.0) - xpath (3.1.0) + xpath (3.2.0) nokogiri (~> 1.8) PLATFORMS From 18b5792a3179d6bb9d4b60068264141d23a159e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 24 Oct 2018 07:22:58 +0000 Subject: [PATCH 193/267] Bump rspec-rails from 3.8.0 to 3.8.1 Bumps [rspec-rails](https://github.com/rspec/rspec-rails) from 3.8.0 to 3.8.1. - [Release notes](https://github.com/rspec/rspec-rails/releases) - [Changelog](https://github.com/rspec/rspec-rails/blob/master/Changelog.md) - [Commits](https://github.com/rspec/rspec-rails/compare/v3.8.0...v3.8.1) Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 4b2ad7d55..5029b777c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -427,13 +427,13 @@ GEM rspec-mocks (>= 2.99, < 4.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) - rspec-expectations (3.8.1) + rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) - rspec-rails (3.8.0) + rspec-rails (3.8.1) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) From 39d451240c8f7dab3cdb708cc30ca1cced90d87d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 30 Oct 2018 14:02:01 +0000 Subject: [PATCH 194/267] [Security] Bump loofah from 2.2.2 to 2.2.3 Bumps [loofah](https://github.com/flavorjones/loofah) from 2.2.2 to 2.2.3. **This update includes security fixes.** - [Release notes](https://github.com/flavorjones/loofah/releases) - [Changelog](https://github.com/flavorjones/loofah/blob/master/CHANGELOG.md) - [Commits](https://github.com/flavorjones/loofah/compare/v2.2.2...v2.2.3) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5029b777c..9e6e30c38 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -290,7 +290,7 @@ GEM rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) ruby_dep (~> 1.2) - loofah (2.2.2) + loofah (2.2.3) crass (~> 1.0.2) nokogiri (>= 1.5.9) lumberjack (1.0.13) From b45162caff824b14da4fc8dbf764919d357ed71a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 30 Oct 2018 20:58:09 +0000 Subject: [PATCH 195/267] Bump bullet from 5.7.6 to 5.8.1 Bumps [bullet](https://github.com/flyerhzm/bullet) from 5.7.6 to 5.8.1. - [Release notes](https://github.com/flyerhzm/bullet/releases) - [Changelog](https://github.com/flyerhzm/bullet/blob/master/CHANGELOG.md) - [Commits](https://github.com/flyerhzm/bullet/compare/5.7.6...5.8.1) Signed-off-by: dependabot[bot] --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 9e6e30c38..aa136214f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -72,9 +72,9 @@ GEM sass (>= 3.3.4) bootstrap_form (2.7.0) builder (3.2.3) - bullet (5.7.6) + bullet (5.8.1) activesupport (>= 3.0.0) - uniform_notifier (~> 1.11.0) + uniform_notifier (~> 1.11) byebug (10.0.2) cancancan (2.3.0) capybara (2.18.0) @@ -515,7 +515,7 @@ GEM unicorn (5.4.1) kgio (~> 2.6) raindrops (~> 0.7) - uniform_notifier (1.11.0) + uniform_notifier (1.12.1) warden (1.2.7) rack (>= 1.0) webrat (0.7.3) From c38f9d80478d74abf5eddaa77c07a1e2d91da8e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 31 Oct 2018 09:20:19 +0000 Subject: [PATCH 196/267] Bump rails-assets-leaflet.markercluster from 1.3.0 to 1.4.1 Bumps rails-assets-leaflet.markercluster from 1.3.0 to 1.4.1. Signed-off-by: dependabot[bot] --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index aa136214f..a1e185a5a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -383,9 +383,9 @@ GEM bundler (>= 1.3.0, < 2.0) railties (= 4.2.10) sprockets-rails - rails-assets-leaflet (1.3.1) - rails-assets-leaflet.markercluster (1.3.0) - rails-assets-leaflet (>= 1.0.3) + rails-assets-leaflet (1.3.4) + rails-assets-leaflet.markercluster (1.4.1) + rails-assets-leaflet (>= 1.3.1) rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) rails-dom-testing (1.0.9) From 977ddf301f7494a24409415e140deaa5f56736f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Wed, 31 Oct 2018 09:47:09 +0000 Subject: [PATCH 197/267] Bump dalli from 2.7.8 to 2.7.9 Bumps [dalli](https://github.com/petergoldstein/dalli) from 2.7.8 to 2.7.9. - [Release notes](https://github.com/petergoldstein/dalli/releases) - [Changelog](https://github.com/petergoldstein/dalli/blob/master/History.md) - [Commits](https://github.com/petergoldstein/dalli/compare/v2.7.8...v2.7.9) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index a1e185a5a..7b88061fc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -133,7 +133,7 @@ GEM crass (1.0.4) csv_shaper (1.3.0) activesupport (>= 3.0.0) - dalli (2.7.8) + dalli (2.7.9) database_cleaner (1.7.0) debug_inspector (0.0.3) devise (4.5.0) From a748fd9773da6d2a28ce845ef8feced72ca0bc87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Thu, 1 Nov 2018 07:24:57 +0000 Subject: [PATCH 198/267] Bump selenium-webdriver from 3.14.1 to 3.141.0 Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 3.14.1 to 3.141.0. - [Release notes](https://github.com/SeleniumHQ/selenium/releases) - [Changelog](https://github.com/SeleniumHQ/selenium/blob/master/rb/CHANGES) - [Commits](https://github.com/SeleniumHQ/selenium/commits/selenium-3.141.0) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7b88061fc..94bb2d1e7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -469,7 +469,7 @@ GEM sassc (2.0.0) ffi (~> 1.9.6) rake - selenium-webdriver (3.14.1) + selenium-webdriver (3.141.0) childprocess (~> 0.5) rubyzip (~> 1.2, >= 1.2.2) sexp_processor (4.11.0) From 2c81429e1eb0a26c8a843287f744aa8e5606e1d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 5 Nov 2018 07:56:14 +0000 Subject: [PATCH 199/267] Bump font-awesome-sass from 5.4.1 to 5.5.0 Bumps [font-awesome-sass](https://github.com/FortAwesome/font-awesome-sass) from 5.4.1 to 5.5.0. - [Release notes](https://github.com/FortAwesome/font-awesome-sass/releases) - [Commits](https://github.com/FortAwesome/font-awesome-sass/compare/5.4.1...5.5.0) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 94bb2d1e7..7452053c3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -176,7 +176,7 @@ GEM figaro (1.1.1) thor (~> 0.14) flickraw (0.9.9) - font-awesome-sass (5.4.1) + font-awesome-sass (5.5.0) sassc (>= 1.11) formatador (0.2.5) friendly_id (5.2.4) From a051f4e06d7c784aa6ff4c4daca1adcfd8e09b49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 6 Nov 2018 07:14:48 +0000 Subject: [PATCH 200/267] [Security] Bump rack from 1.6.10 to 1.6.11 Bumps [rack](https://github.com/rack/rack) from 1.6.10 to 1.6.11. **This update includes security fixes.** - [Release notes](https://github.com/rack/rack/releases) - [Changelog](https://github.com/rack/rack/blob/master/CHANGELOG.md) - [Commits](https://github.com/rack/rack/compare/1.6.10...1.6.11) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 7452053c3..a95da98be 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -367,7 +367,7 @@ GEM public_suffix (3.0.3) quiet_assets (1.1.0) railties (>= 3.1, < 5.0) - rack (1.6.10) + rack (1.6.11) rack-protection (2.0.4) rack rack-test (0.6.3) From 5c45beb54f43e58627dc375824f4ff59cf031166 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Thu, 8 Nov 2018 07:23:52 +0000 Subject: [PATCH 201/267] Bump font-awesome-sass from 5.5.0 to 5.5.0.1 Bumps [font-awesome-sass](https://github.com/FortAwesome/font-awesome-sass) from 5.5.0 to 5.5.0.1. - [Release notes](https://github.com/FortAwesome/font-awesome-sass/releases) - [Commits](https://github.com/FortAwesome/font-awesome-sass/compare/5.5.0...5.5.0.1) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index a95da98be..73c33fa63 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -176,7 +176,7 @@ GEM figaro (1.1.1) thor (~> 0.14) flickraw (0.9.9) - font-awesome-sass (5.5.0) + font-awesome-sass (5.5.0.1) sassc (>= 1.11) formatador (0.2.5) friendly_id (5.2.4) From 8348530e22e646e48a587b100cc4579552f06c5c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 12:58:22 +1300 Subject: [PATCH 202/267] Tell capybara to normalise whitespace --- config/environments/test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/environments/test.rb b/config/environments/test.rb index 617338127..cbf6101f0 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -98,6 +98,7 @@ Geocoder::Lookup::Test.add_stub("Tatooine", []) Capybara.configure do |config| config.always_include_port = true + config.default_normalize_ws = true end OmniAuth.config.test_mode = true From 0c78791d0198f49081cf17d2da8c4bd799415b8f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 13:22:42 +1300 Subject: [PATCH 203/267] Remove unnecesary whitesapce in specs --- spec/features/crops/crop_detail_page_spec.rb | 2 +- spec/features/planting_reminder_spec.rb | 2 +- spec/features/plantings/planting_a_crop_spec.rb | 4 ++-- spec/features/seeds/adding_seeds_spec.rb | 6 +++--- spec/features/seeds/misc_seeds_spec.rb | 8 ++++---- spec/features/shared_examples/append_date.rb | 4 ++-- spec/views/crops/edit.html.haml_spec.rb | 2 +- spec/views/posts/new.html.haml_spec.rb | 2 +- spec/views/scientific_names/edit.html.haml_spec.rb | 2 +- spec/views/seeds/new.html.haml_spec.rb | 4 ++-- spec/views/seeds/show.html.haml_spec.rb | 2 +- 11 files changed, 19 insertions(+), 19 deletions(-) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index e4e3d05e0..62f80d37f 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -193,7 +193,7 @@ feature "crop detail page", js: true do end it "predicts harvest" do - is_expected.to have_text("First harvest expected\n20 days after planting") + is_expected.to have_text("First harvest expected 20 days after planting") end end end diff --git a/spec/features/planting_reminder_spec.rb b/spec/features/planting_reminder_spec.rb index bcb86d576..3b407c3df 100644 --- a/spec/features/planting_reminder_spec.rb +++ b/spec/features/planting_reminder_spec.rb @@ -41,7 +41,7 @@ feature "Planting reminder email", :js do context "when member has no harvests" do scenario "tells you to tracking plantings" do - expect(mail).to have_content "Get started now\nby tracking your first harvest" + expect(mail).to have_content "Get started now by tracking your first harvest" end scenario "doesn't list plantings" do diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index 3da396ee0..1d8b7f745 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -211,7 +211,7 @@ feature "Planting a crop", :js, :elasticsearch do click_button "Save" end expect(page).to have_content "planting was successfully created" - expect(page).to have_content "Finished:\nAugust 30, 2014" + expect(page).to have_content "Finished: August 30, 2014" # shouldn't be on the page visit plantings_path @@ -232,7 +232,7 @@ feature "Planting a crop", :js, :elasticsearch do end end it { expect(page).to have_content "planting was successfully created" } - it { expect(page).to have_content "Finished:\nYes (no date specified)" } + it { expect(page).to have_content "Finished: Yes (no date specified)" } it { expect(page).to have_content "100%" } end diff --git a/spec/features/seeds/adding_seeds_spec.rb b/spec/features/seeds/adding_seeds_spec.rb index 8a875cc85..67a8b7717 100644 --- a/spec/features/seeds/adding_seeds_spec.rb +++ b/spec/features/seeds/adding_seeds_spec.rb @@ -48,11 +48,11 @@ feature "Seeds", :js, :elasticsearch do end end it { expect(page).to have_content "Successfully added maize seed to your stash" } - it { expect(page).to have_content "Quantity:\n42" } - it { expect(page).to have_content "Days until maturity:\n999–1999" } + it { expect(page).to have_content "Quantity: 42" } + it { expect(page).to have_content "Days until maturity: 999–1999" } it { expect(page).to have_content "certified organic" } it { expect(page).to have_content "non-certified GMO-free" } - it { expect(page).to have_content "Heirloom?\nheirloom" } + it { expect(page).to have_content "Heirloom? heirloom" } it { expect(page).to have_content "It's killer." } end diff --git a/spec/features/seeds/misc_seeds_spec.rb b/spec/features/seeds/misc_seeds_spec.rb index 3687ca630..e095ed390 100644 --- a/spec/features/seeds/misc_seeds_spec.rb +++ b/spec/features/seeds/misc_seeds_spec.rb @@ -60,22 +60,22 @@ feature "seeds", js: true do before { visit seed_path(seed) } describe "view seeds with max and min days until maturity" do let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5, days_until_maturity_max: 7 } - it { expect(page).to have_content "Days until maturity:\n5–7" } + it { expect(page).to have_content "Days until maturity: 5–7" } end describe "view seeds with only max days until maturity" do let(:seed) { FactoryBot.create :seed, days_until_maturity_max: 7 } - it { expect(page).to have_content "Days until maturity:\n7" } + it { expect(page).to have_content "Days until maturity: 7" } end describe "view seeds with only min days until maturity" do let(:seed) { FactoryBot.create :seed, days_until_maturity_min: 5 } - it { expect(page).to have_content "Days until maturity:\n5" } + it { expect(page).to have_content "Days until maturity: 5" } end describe "view seeds with neither max nor min days until maturity" do let(:seed) { FactoryBot.create :seed } - it { expect(page).to have_content "Days until maturity:\nunknown" } + it { expect(page).to have_content "Days until maturity: unknown" } end end end diff --git a/spec/features/shared_examples/append_date.rb b/spec/features/shared_examples/append_date.rb index b2c19e5f1..fcb6d515b 100644 --- a/spec/features/shared_examples/append_date.rb +++ b/spec/features/shared_examples/append_date.rb @@ -10,12 +10,12 @@ shared_examples "append date" do expect(page).to have_content this_month.to_s find(".datepicker-days td.day", text: "21").click end - expect(page).to have_content "Finished:\n#{this_month} 21, #{this_year}" + expect(page).to have_content "Finished: #{this_month} 21, #{this_year}" end scenario "Confirming without selecting date" do click_link link_text click_link "Confirm without date" - expect(page).to have_content("Finished:\nYes (no date specified)") + expect(page).to have_content("Finished: Yes (no date specified)") end end diff --git a/spec/views/crops/edit.html.haml_spec.rb b/spec/views/crops/edit.html.haml_spec.rb index 6dbae67d4..f0d8e9251 100644 --- a/spec/views/crops/edit.html.haml_spec.rb +++ b/spec/views/crops/edit.html.haml_spec.rb @@ -14,6 +14,6 @@ describe "crops/edit" do end it "shows the creator" do - expect(rendered).to have_content "Added by\n#{@crop.creator}\nless than a minute\nago." + expect(rendered).to have_content "Added by #{@crop.creator} less than a minute ago." end end diff --git a/spec/views/posts/new.html.haml_spec.rb b/spec/views/posts/new.html.haml_spec.rb index 9bf53e563..6c6a2ae68 100644 --- a/spec/views/posts/new.html.haml_spec.rb +++ b/spec/views/posts/new.html.haml_spec.rb @@ -47,7 +47,7 @@ describe "posts/new" do end it 'tells the user what forum it will be posted in' do - expect(rendered).to have_content "This post will be posted in the forum\n#{forum.name}" + expect(rendered).to have_content "This post will be posted in the forum #{forum.name}" end it { expect(rendered).to have_link forum.name } diff --git a/spec/views/scientific_names/edit.html.haml_spec.rb b/spec/views/scientific_names/edit.html.haml_spec.rb index 2d6fd73a5..249cd249b 100644 --- a/spec/views/scientific_names/edit.html.haml_spec.rb +++ b/spec/views/scientific_names/edit.html.haml_spec.rb @@ -13,7 +13,7 @@ describe "scientific_names/edit" do end it "shows the creator" do - expect(rendered).to have_content "Added by\n#{member}\nless than a minute\nago." + expect(rendered).to have_content "Added by #{member} less than a minute ago." end it { expect(rendered).to have_link member } diff --git a/spec/views/seeds/new.html.haml_spec.rb b/spec/views/seeds/new.html.haml_spec.rb index fdea300fe..3b33cc6c4 100644 --- a/spec/views/seeds/new.html.haml_spec.rb +++ b/spec/views/seeds/new.html.haml_spec.rb @@ -23,7 +23,7 @@ describe "seeds/new" do context 'member has no location' do describe 'reminds you to set your location' do - it { expect(rendered).to have_content "Don't forget to\nset your location." } + it { expect(rendered).to have_content "Don't forget to set your location." } it { expect(rendered).to have_link "set your location" } end end @@ -32,7 +32,7 @@ describe "seeds/new" do let!(:member) { FactoryBot.create(:london_member) } describe 'shows the location' do - it { expect(rendered).to have_text "from\n#{member.location}." } + it { expect(rendered).to have_text "from #{member.location}." } it { expect(rendered).to have_link(member.location, href: place_path(member.location)) } end diff --git a/spec/views/seeds/show.html.haml_spec.rb b/spec/views/seeds/show.html.haml_spec.rb index 7c7604001..2ad38bdcf 100644 --- a/spec/views/seeds/show.html.haml_spec.rb +++ b/spec/views/seeds/show.html.haml_spec.rb @@ -28,7 +28,7 @@ describe "seeds/show" do end it "shows tradable attributes" do - expect(rendered).to have_content "Will trade:\n\nlocally" + expect(rendered).to have_content "Will trade: locally" end it "shows button to send message" do From 7e8aa7a435cda99a9a27f6be6db332b15214b58c Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 13:22:52 +1300 Subject: [PATCH 204/267] bundle update --- Gemfile.lock | 129 ++++++++++++++++++++++++++------------------------- 1 file changed, 67 insertions(+), 62 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 952bcd2ab..be2ea990f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -49,9 +49,9 @@ GEM active_link_to (1.0.5) actionpack addressable - active_median (0.1.4) - activerecord - active_utils (3.3.15) + active_median (0.2.2) + activerecord (>= 4.2) + active_utils (3.3.16) activesupport (>= 4.2) i18n activejob (5.1.4) @@ -72,7 +72,7 @@ GEM public_suffix (>= 2.0.2, < 4.0) arel (8.0.0) ast (2.4.0) - autoprefixer-rails (9.1.4) + autoprefixer-rails (9.4.3) execjs bcrypt (3.1.12) better_errors (2.5.0) @@ -88,23 +88,25 @@ GEM bootstrap-kaminari-views (0.0.5) kaminari (>= 0.13) rails (>= 3.1) - bootstrap-sass (3.3.7) + bootstrap-sass (3.4.0) autoprefixer-rails (>= 5.2.1) - sass (>= 3.3.4) - bootstrap_form (2.7.0) + sassc (>= 2.0.0) + bootstrap_form (4.0.0) + rails (>= 5.0) builder (3.2.3) bullet (5.9.0) activesupport (>= 3.0.0) uniform_notifier (~> 1.11) byebug (10.0.2) - cancancan (2.2.0) - capybara (3.7.2) + cancancan (2.3.0) + capybara (3.12.0) addressable mini_mime (>= 0.1.3) nokogiri (~> 1.8) rack (>= 1.6.0) rack-test (>= 0.6.3) - xpath (~> 3.1) + regexp_parser (~> 1.2) + xpath (~> 3.2) capybara-email (3.0.1) capybara (>= 2.4, < 4.0) mail @@ -128,7 +130,7 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.0.5) + concurrent-ruby (1.1.4) connection_pool (2.2.2) coveralls (0.8.19) json (>= 1.8, < 3) @@ -162,7 +164,7 @@ GEM elasticsearch-transport (6.1.0) faraday multi_json - erubi (1.7.1) + erubi (1.8.0) erubis (2.7.0) excon (0.62.0) execjs (2.7.0) @@ -173,13 +175,13 @@ GEM railties (>= 3.0.0) faker (1.9.1) i18n (>= 0.7) - faraday (0.12.2) + faraday (0.15.4) multipart-post (>= 1.2, < 3) ffi (1.9.25) figaro (1.1.1) thor (~> 0.14) flickraw (0.9.9) - font-awesome-sass (5.3.1) + font-awesome-sass (5.6.1) sassc (>= 1.11) friendly_id (5.2.4) activerecord (>= 4.0.0) @@ -213,7 +215,7 @@ GEM rake (>= 10, < 13) rubocop (>= 0.50.0) sysexits (~> 1.1) - hashie (3.5.7) + hashie (3.6.0) heroics (0.0.25) erubis (~> 2.0) excon @@ -225,17 +227,19 @@ GEM haml (>= 4.0, < 6) nokogiri (>= 1.6.0) ruby_parser (~> 3.5) - httparty (0.16.2) + httparty (0.16.3) + mime-types (~> 3.0) multi_xml (>= 0.5.2) i18n (0.9.5) concurrent-ruby (~> 1.0) - i18n-tasks (0.9.24) + i18n-tasks (0.9.28) activesupport (>= 4.0.2) ast (>= 2.1.0) erubi highline (>= 2.0.0) i18n parser (>= 2.2.3.0) + rails-i18n rainbow (>= 2.2.2, < 4.0) terminal-table (>= 1.5.1) jaro_winkler (1.5.1) @@ -253,7 +257,7 @@ GEM activerecord (>= 4.1) concurrent-ruby railties (>= 4.1) - jwt (1.5.6) + jwt (2.1.0) kaminari (1.1.1) activesupport (>= 4.1.0) kaminari-actionview (= 1.1.1) @@ -281,34 +285,34 @@ GEM loofah (2.2.3) crass (~> 1.0.2) nokogiri (>= 1.5.9) - mail (2.7.0) + mail (2.7.1) mini_mime (>= 0.1.1) memcachier (0.0.2) - method_source (0.9.0) + method_source (0.9.2) mime-types (3.2.2) mime-types-data (~> 3.2015) mime-types-data (3.2018.0812) - mimemagic (0.3.2) + mimemagic (0.3.3) mini_mime (1.0.1) - mini_portile2 (2.3.0) + mini_portile2 (2.4.0) minitest (5.11.3) moneta (1.0.0) multi_json (1.11.3) multi_xml (0.6.0) multipart-post (2.0.0) - newrelic_rpm (5.4.0.347) + newrelic_rpm (5.6.0.349) nio4r (2.3.1) - nokogiri (1.8.5) - mini_portile2 (~> 2.3.0) + nokogiri (1.9.1) + mini_portile2 (~> 2.4.0) oauth (0.5.4) - oauth2 (1.4.0) - faraday (>= 0.8, < 0.13) - jwt (~> 1.0) + oauth2 (1.4.1) + faraday (>= 0.8, < 0.16.0) + jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) - omniauth (1.8.1) - hashie (>= 3.4.6, < 3.6.0) + omniauth (1.9.0) + hashie (>= 3.4.6, < 3.7.0) rack (>= 1.6.2, < 3) omniauth-facebook (5.0.0) omniauth-oauth2 (~> 1.2) @@ -318,9 +322,9 @@ GEM omniauth-oauth (1.1.0) oauth omniauth (~> 1.0) - omniauth-oauth2 (1.5.0) + omniauth-oauth2 (1.6.0) oauth2 (~> 1.1) - omniauth (~> 1.2) + omniauth (~> 1.9) omniauth-twitter (1.4.0) omniauth-oauth (~> 1.1) rack @@ -334,7 +338,7 @@ GEM parallel (1.12.1) paranoia (2.4.1) activerecord (>= 4.0, < 5.3) - parser (2.5.1.2) + parser (2.5.3.0) ast (~> 2.4.0) pg (0.21.0) platform-api (2.2.0) @@ -349,8 +353,8 @@ GEM powerpack (0.1.2) public_suffix (3.0.3) puma (3.12.0) - rack (2.0.5) - rack-protection (2.0.3) + rack (2.0.6) + rack-protection (2.0.5) rack rack-test (1.1.0) rack (>= 1.0, < 3) @@ -367,18 +371,18 @@ GEM railties (= 5.1.4) sprockets-rails (>= 2.0.0) rails-assets-leaflet (1.3.4) - rails-assets-leaflet.markercluster (1.4.0) + rails-assets-leaflet.markercluster (1.4.1) rails-assets-leaflet (>= 1.3.1) - rails-controller-testing (1.0.2) - actionpack (~> 5.x, >= 5.0.1) - actionview (~> 5.x, >= 5.0.1) - activesupport (~> 5.x) + rails-controller-testing (1.0.4) + actionpack (>= 5.0.1.x) + actionview (>= 5.0.1.x) + activesupport (>= 5.0.1.x) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-html-sanitizer (1.0.4) loofah (~> 2.2, >= 2.2.2) - rails-i18n (5.1.1) + rails-i18n (5.1.2) i18n (>= 0.7, < 2) railties (>= 5.0, < 6) rails_12factor (0.0.3) @@ -394,15 +398,16 @@ GEM thor (>= 0.18.1, < 2.0) rainbow (3.0.0) raindrops (0.19.0) - rake (12.3.1) + rake (12.3.2) rb-fsevent (0.10.3) - rb-inotify (0.9.10) - ffi (>= 0.5.0, < 2) - redis (4.0.2) + rb-inotify (0.10.0) + ffi (~> 1.0) + redis (4.1.0) + regexp_parser (1.3.0) responders (2.4.0) actionpack (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3) - rspec-activemodel-mocks (1.0.3) + rspec-activemodel-mocks (1.1.0) activemodel (>= 3.0) activesupport (>= 3.0) rspec-mocks (>= 2.99, < 4.0) @@ -423,23 +428,23 @@ GEM rspec-mocks (~> 3.8.0) rspec-support (~> 3.8.0) rspec-support (3.8.0) - rubocop (0.59.0) + rubocop (0.61.1) jaro_winkler (~> 1.5.1) parallel (~> 1.10) parser (>= 2.5, != 2.5.1.1) powerpack (~> 0.1) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) - unicode-display_width (~> 1.0, >= 1.0.1) - rubocop-rspec (1.29.1) - rubocop (>= 0.58.0) + unicode-display_width (~> 1.4.0) + rubocop-rspec (1.30.1) + rubocop (>= 0.60.0) ruby-progressbar (1.10.0) - ruby-units (2.3.0) + ruby-units (2.3.1) ruby_dep (1.5.0) - ruby_parser (3.11.0) + ruby_parser (3.12.0) sexp_processor (~> 4.9) rubyzip (1.2.2) - sass (3.5.7) + sass (3.7.2) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) @@ -450,14 +455,14 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) - sassc (1.12.1) + sassc (2.0.0) ffi (~> 1.9.6) rake selenium-webdriver (3.141.0) childprocess (~> 0.5) rubyzip (~> 1.2, >= 1.2.2) sexp_processor (4.11.0) - sidekiq (5.2.1) + sidekiq (5.2.3) connection_pool (~> 2.2, >= 2.2.2) rack-protection (>= 1.5.0) redis (>= 3.3.5, < 5) @@ -477,7 +482,7 @@ GEM sprockets (>= 3.0.0) sysexits (1.2.0) temple (0.8.0) - term-ansicolor (1.6.0) + term-ansicolor (1.7.0) tins (~> 1.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) @@ -485,21 +490,21 @@ GEM climate_control (>= 0.0.3, < 1.0) thor (0.19.4) thread_safe (0.3.6) - tilt (2.0.8) + tilt (2.0.9) timecop (0.9.1) - tins (1.16.3) + tins (1.20.2) trollop (1.16.2) tzinfo (1.2.5) thread_safe (~> 0.1) - uglifier (4.1.19) + uglifier (4.1.20) execjs (>= 0.3.0, < 3) - unicode-display_width (1.4.0) + unicode-display_width (1.4.1) unicorn (5.4.1) kgio (~> 2.6) raindrops (~> 0.7) uniform_notifier (1.12.1) - warden (1.2.7) - rack (>= 1.0) + warden (1.2.8) + rack (>= 2.0.6) webrat (0.7.3) nokogiri (>= 1.2.0) rack (>= 1.0) From 27e471b7b3835e52a9e1c734cef3327c63d5fc1a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 13:30:16 +1300 Subject: [PATCH 205/267] Set rubocop to 0.60 --- .codeclimate.yml | 1 + Gemfile | 2 +- Gemfile.lock | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.codeclimate.yml b/.codeclimate.yml index 32904c026..65de6c429 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,6 +1,7 @@ engines: rubocop: enabled: true + channel: rubocop-0-60 scss-lint: enabled: true shellcheck: diff --git a/Gemfile b/Gemfile index 31250e27a..7a6f3ff86 100644 --- a/Gemfile +++ b/Gemfile @@ -134,7 +134,7 @@ group :development, :test do gem 'poltergeist' # for headless JS testing gem 'rspec-activemodel-mocks' gem 'rspec-rails' # unit testing framework - gem 'rubocop', '>= 0.54.0' + gem 'rubocop', '~> 0.60' gem 'rubocop-rspec' gem 'selenium-webdriver' gem 'webrat' # provides HTML matchers for view tests diff --git a/Gemfile.lock b/Gemfile.lock index be2ea990f..8ebda85af 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -592,7 +592,7 @@ DEPENDENCIES responders rspec-activemodel-mocks rspec-rails - rubocop (>= 0.54.0) + rubocop (~> 0.60) rubocop-rspec ruby-units sass-rails From 2cc37464fc9bfe52f822cf9074086ff89e79fb0b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 13:31:33 +1300 Subject: [PATCH 206/267] Some rubocop ignores that we shouldn't ignore --- .rubocop_todo.yml | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 1bfd8efc6..da3279a42 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -52,36 +52,12 @@ Rails/HasManyOrHasOneDependent: Exclude: - 'app/models/member.rb' -# Configuration parameters: Include. -# Include: app/controllers/**/*.rb -Rails/LexicallyScopedActionFilter: - Exclude: - - 'app/controllers/alternate_names_controller.rb' - - 'app/controllers/comments_controller.rb' - - 'app/controllers/gardens_controller.rb' - - 'app/controllers/members_controller.rb' - - 'app/controllers/photos_controller.rb' - -Rails/OutputSafety: - Exclude: - - 'app/helpers/application_helper.rb' - - 'app/helpers/auto_suggest_helper.rb' - - 'app/helpers/gardens_helper.rb' - # Configuration parameters: Blacklist. # Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters Rails/SkipsModelValidations: Exclude: - 'db/seeds.rb' -# Configuration parameters: EnforcedStyle. -# SupportedStyles: strict, flexible -Rails/TimeZone: - Exclude: - - 'spec/factories/member.rb' - - 'spec/factories/post.rb' - - 'spec/models/post_spec.rb' - # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, EnforcedStyle. # SupportedStyles: nested, compact @@ -97,10 +73,6 @@ Style/CommentedKeyword: - 'spec/models/photo_spec.rb' - 'spec/models/planting_spec.rb' -Style/IdenticalConditionalBranches: - Exclude: - - 'app/controllers/follows_controller.rb' - Style/MixinUsage: Exclude: - 'bin/setup' From 9e6f0af373fa76619eecd593e6e4430792bcc41a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 13:33:34 +1300 Subject: [PATCH 207/267] More things detected by rubocop, that we shouldn't ignore --- .rubocop_todo.yml | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index da3279a42..eb05ad7ff 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -10,18 +10,6 @@ Lint/HandleExceptions: Exclude: - 'lib/tasks/testing.rake' -# Configuration parameters: MaximumRangeSize. -Lint/MissingCopEnableDirective: - Exclude: - - 'config.rb' - - 'config/compass.rb' - - 'config/initializers/devise.rb' - -Lint/UriEscapeUnescape: - Exclude: - - 'app/helpers/crops_helper.rb' - - 'spec/features/crops/crop_detail_page_spec.rb' - # Configuration parameters: EnforcedStyle. # SupportedStyles: lowercase, uppercase Naming/HeredocDelimiterCase: @@ -88,14 +76,3 @@ Style/NumericPredicate: - 'app/helpers/harvests_helper.rb' - 'app/helpers/plantings_helper.rb' - 'lib/tasks/growstuff.rake' - -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, AllowInnerSlashes. -# SupportedStyles: slashes, percent_r, mixed -Style/RegexpLiteral: - Exclude: - - 'spec/lib/haml/filters/growstuff_markdown_spec.rb' - - 'spec/rails_helper.rb' - - 'spec/views/devise/registrations/edit_spec.rb' - - 'spec/views/members/index.html.haml_spec.rb' - - 'spec/views/posts/index.html.haml_spec.rb' From 007e61e76a7d01c0b04f723722da7c5942129b87 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 13:36:32 +1300 Subject: [PATCH 208/267] Freeze mutable objects assigned to constants. --- lib/haml/filters/growstuff_markdown.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/haml/filters/growstuff_markdown.rb b/lib/haml/filters/growstuff_markdown.rb index 51d95d1fe..4e7617c15 100644 --- a/lib/haml/filters/growstuff_markdown.rb +++ b/lib/haml/filters/growstuff_markdown.rb @@ -13,10 +13,10 @@ module Haml::Filters # rubocop:disable Style/ClassAndModuleChildren private - CROP_REGEX = /(? Date: Sun, 30 Dec 2018 13:49:50 +1300 Subject: [PATCH 209/267] No longer need to create the active median function in a migration --- db/migrate/20171028230429_create_median_function.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20171028230429_create_median_function.rb b/db/migrate/20171028230429_create_median_function.rb index 5e57c01d1..77f8f76b6 100644 --- a/db/migrate/20171028230429_create_median_function.rb +++ b/db/migrate/20171028230429_create_median_function.rb @@ -1,6 +1,6 @@ class CreateMedianFunction < ActiveRecord::Migration[4.2] def up - ActiveMedian.create_function + # ActiveMedian.create_function end def down From c2b64ffbc0fbcc666de77fa91b4ee4bb13656751 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 14:19:33 +1300 Subject: [PATCH 210/267] pull elastic search version back --- Gemfile | 6 +++--- Gemfile.lock | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Gemfile b/Gemfile index 7a6f3ff86..1a61408bf 100644 --- a/Gemfile +++ b/Gemfile @@ -85,9 +85,9 @@ gem "chartkick" # Project does not use semver, so we want to be in sync with the version of # elasticsearch we use # See https://github.com/elastic/elasticsearch-ruby#compatibility -gem "elasticsearch-api", ">= 6.0.0" -gem "elasticsearch-model", ">= 6.0.0" -gem "elasticsearch-rails", ">= 6.0.0" +gem "elasticsearch-api", "~> 6.0.0" +gem "elasticsearch-model", "~> 6.0.0" +gem "elasticsearch-rails", "~> 6.0.0" gem "hashie", ">= 3.5.3" gem 'rake', '>= 10.0.0' diff --git a/Gemfile.lock b/Gemfile.lock index 8ebda85af..118c4bcdd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -151,17 +151,17 @@ GEM warden (~> 1.2.3) diff-lcs (1.3) docile (1.1.5) - elasticsearch (6.1.0) - elasticsearch-api (= 6.1.0) - elasticsearch-transport (= 6.1.0) - elasticsearch-api (6.1.0) + elasticsearch (6.0.3) + elasticsearch-api (= 6.0.3) + elasticsearch-transport (= 6.0.3) + elasticsearch-api (6.0.3) multi_json elasticsearch-model (6.0.0) activesupport (> 3) elasticsearch (> 1) hashie elasticsearch-rails (6.0.0) - elasticsearch-transport (6.1.0) + elasticsearch-transport (6.0.3) faraday multi_json erubi (1.8.0) @@ -545,9 +545,9 @@ DEPENDENCIES dalli database_cleaner devise - elasticsearch-api (>= 6.0.0) - elasticsearch-model (>= 6.0.0) - elasticsearch-rails (>= 6.0.0) + elasticsearch-api (~> 6.0.0) + elasticsearch-model (~> 6.0.0) + elasticsearch-rails (~> 6.0.0) factory_bot_rails faker figaro From 1574f4b90af1af7db67024657d2d53f19947afb6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 14:39:24 +1300 Subject: [PATCH 211/267] Downgrade active_median gem until we upgrade postgresql. see #1757 --- Gemfile | 3 ++- Gemfile.lock | 6 +++--- db/migrate/20171028230429_create_median_function.rb | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 1a61408bf..310b741bf 100644 --- a/Gemfile +++ b/Gemfile @@ -22,7 +22,8 @@ gem 'font-awesome-sass' gem 'uglifier' # JavaScript compressor # planting and harvest predictions -gem 'active_median' +# based on median values for the crop +gem 'active_median', '0.1.4' # needs postgresql update https://github.com/Growstuff/growstuff/issues/1757 gem 'flickraw' gem 'jquery-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 118c4bcdd..062eadd71 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -49,8 +49,8 @@ GEM active_link_to (1.0.5) actionpack addressable - active_median (0.2.2) - activerecord (>= 4.2) + active_median (0.1.4) + activerecord active_utils (3.3.16) activesupport (>= 4.2) i18n @@ -521,7 +521,7 @@ PLATFORMS ruby DEPENDENCIES - active_median + active_median (= 0.1.4) active_utils better_errors bluecloth diff --git a/db/migrate/20171028230429_create_median_function.rb b/db/migrate/20171028230429_create_median_function.rb index 77f8f76b6..5e57c01d1 100644 --- a/db/migrate/20171028230429_create_median_function.rb +++ b/db/migrate/20171028230429_create_median_function.rb @@ -1,6 +1,6 @@ class CreateMedianFunction < ActiveRecord::Migration[4.2] def up - # ActiveMedian.create_function + ActiveMedian.create_function end def down From 1e4cdc95116a1adc583e4f813fba3c719b1f888e Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 14:57:24 +1300 Subject: [PATCH 212/267] Change rake to rails --- CONTRIBUTING.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c8b53d513..2a6ab8b10 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,11 +10,11 @@ When you create a pull request, please include the following: All pull requests should pass our automatic continuous integration and style checks before being merged. You can run tests locally as follows: - - `rake spec` to run all Ruby tests - - `rake spec:models` to run Ruby model tests (or `rake spec:views` for view tests, etc) - - `rake static` to run all static checks (code style, unfixed Git conflicts, etc) - - `rake jasmine:ci` to run JavaScript unit tests in headless mode - - `rake jasmine` to start a server for running JavaScript unit tests in a + - `rails spec` to run all Ruby tests + - `rails spec:models` to run Ruby model tests (or `rails spec:views` for view tests, etc) + - `rails static` to run all static checks (code style, unfixed Git conflicts, etc) + - `rails jasmine:ci` to run JavaScript unit tests in headless mode + - `rails jasmine` to start a server for running JavaScript unit tests in a browser (eg for debugging). Point your browser at http://localhost:8888 to run the tests. - `rspec ./spec/path/to/my_spec.rb` to run all Ruby tests in the file `my_spec.rb` From b82b4fa64233f71884c742127b55daaf6b0dd17a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:04:38 +1300 Subject: [PATCH 213/267] Comments controller has no show --- app/controllers/comments_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 389efb825..f6bbc412c 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -1,5 +1,5 @@ class CommentsController < ApplicationController - before_action :authenticate_member!, except: %i(index show) + before_action :authenticate_member!, except: %i(index) load_and_authorize_resource respond_to :html, :json respond_to :rss, only: :index From 24b58c5ac234dde0cbc468398ded40ee77c2d2df Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:04:50 +1300 Subject: [PATCH 214/267] FIXED wrong method name --- app/controllers/gardens_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/gardens_controller.rb b/app/controllers/gardens_controller.rb index 35efaf5d2..132430976 100644 --- a/app/controllers/gardens_controller.rb +++ b/app/controllers/gardens_controller.rb @@ -1,6 +1,6 @@ class GardensController < ApplicationController before_action :authenticate_member!, except: %i(index show) - after_action :expire_homepage, only: %i(create delete) + after_action :expire_homepage, only: %i(create destroy) load_and_authorize_resource respond_to :html, :json From 8e160a4c9380d339af6fd90220bbb605c346b1d0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:05:00 +1300 Subject: [PATCH 215/267] Fixed another wrong method name --- app/controllers/photos_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 331a4e2c4..c74c89824 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -1,6 +1,6 @@ class PhotosController < ApplicationController before_action :authenticate_member!, except: %i(index show) - after_action :expire_homepage, only: %i(create delete) + after_action :expire_homepage, only: %i(create destroy) load_and_authorize_resource respond_to :html, :json responders :flash From 914e9ef3be633b12cc03c1d89878011722fbca64 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:05:10 +1300 Subject: [PATCH 216/267] photos needs a show method --- app/controllers/photos_controller.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index c74c89824..576373207 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -5,6 +5,9 @@ class PhotosController < ApplicationController respond_to :html, :json responders :flash + def show + end + def index if params[:crop_id] @crop = Crop.find params[:crop_id] From ac6a308ea05574ece27f8077c06c174b82b11908 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:05:41 +1300 Subject: [PATCH 217/267] Update URL -> CGI --- spec/features/crops/crop_detail_page_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index 62f80d37f..a194e8f1e 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -141,12 +141,12 @@ feature "crop detail page", js: true do scenario "has a link to OpenFarm" do expect(page).to have_link "OpenFarm - Growing guide", - href: "https://openfarm.cc/en/crops/#{URI.escape crop.name}" + href: "https://openfarm.cc/en/crops/#{CGI.escape crop.name}" end scenario "has a link to gardenate" do expect(page).to have_link "Gardenate - Planting reminders", - href: "http://www.gardenate.com/plant/#{URI.escape crop.name}" + href: "http://www.gardenate.com/plant/#{CGI.escape crop.name}" end end end From 9f90b0368b39f2847275e000dd6069c71fa8bded Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:06:06 +1300 Subject: [PATCH 218/267] Use %r for regexp --- spec/lib/haml/filters/growstuff_markdown_spec.rb | 2 +- spec/rails_helper.rb | 2 +- spec/views/devise/registrations/edit_spec.rb | 2 +- spec/views/members/index.html.haml_spec.rb | 2 +- spec/views/posts/index.html.haml_spec.rb | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/lib/haml/filters/growstuff_markdown_spec.rb b/spec/lib/haml/filters/growstuff_markdown_spec.rb index e4dea52d9..597137f6d 100644 --- a/spec/lib/haml/filters/growstuff_markdown_spec.rb +++ b/spec/lib/haml/filters/growstuff_markdown_spec.rb @@ -58,7 +58,7 @@ describe 'Haml::Filters::Growstuff_Markdown' do it "converts normal markdown" do string = "**foo**" rendered = Haml::Filters::GrowstuffMarkdown.render(string) - expect(rendered).to match(/foo<\/strong>/) + expect(rendered).to match(%r{foo}) end it "finds crops case insensitively" do diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index ec3f6af77..5b89cd26d 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -37,7 +37,7 @@ if ENV['GROWSTUFF_CAPYBARA_DRIVER'].present? end Capybara::Screenshot.register_filename_prefix_formatter(:rspec) do |example| - "screenshot_#{example.description.tr(' ', '-').gsub(/^.*\/spec\//, '')}" + "screenshot_#{example.description.tr(' ', '-').gsub(%r{^.*/spec/}, '')}" end Capybara.app_host = 'http://localhost' diff --git a/spec/views/devise/registrations/edit_spec.rb b/spec/views/devise/registrations/edit_spec.rb index 64af90017..85ee6588a 100644 --- a/spec/views/devise/registrations/edit_spec.rb +++ b/spec/views/devise/registrations/edit_spec.rb @@ -41,7 +41,7 @@ describe 'devise/registrations/edit.html.haml', type: "view" do end it "contains a gravatar icon" do - assert_select "img", src: /gravatar\.com\/avatar/ + assert_select "img", src: %r{gravatar\.com/avatar} end it 'contains a link to gravatar.com' do diff --git a/spec/views/members/index.html.haml_spec.rb b/spec/views/members/index.html.haml_spec.rb index 87dd3a285..9488fa5df 100644 --- a/spec/views/members/index.html.haml_spec.rb +++ b/spec/views/members/index.html.haml_spec.rb @@ -16,7 +16,7 @@ describe "members/index" do end it "contains two gravatar icons" do - assert_select "img", src: /gravatar\.com\/avatar/, count: 2 + assert_select "img", src: %r{gravatar\.com/avatar}, count: 2 end it 'contains member locations' do diff --git a/spec/views/posts/index.html.haml_spec.rb b/spec/views/posts/index.html.haml_spec.rb index eeebac8b6..b2f956904 100644 --- a/spec/views/posts/index.html.haml_spec.rb +++ b/spec/views/posts/index.html.haml_spec.rb @@ -25,7 +25,7 @@ describe "posts/index" do end it "contains two gravatar icons" do - assert_select "img", src: /gravatar\.com\/avatar/, count: 2 + assert_select "img", src: %r{gravatar\.com/avatar}, count: 2 end it "contains RSS feed links for posts and comments" do From d5676338d685f99521e304e6c6553dddefb55352 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:06:14 +1300 Subject: [PATCH 219/267] Use the expect syntax --- spec/controllers/comments_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/comments_controller_spec.rb b/spec/controllers/comments_controller_spec.rb index f61c28d81..4d9e9fc6b 100644 --- a/spec/controllers/comments_controller_spec.rb +++ b/spec/controllers/comments_controller_spec.rb @@ -36,13 +36,13 @@ describe CommentsController do before { get :new, params: { post_id: post.id } } it "picks up post from params" do - assigns(:post).should eq(post) + expect(assigns(:post)).to eq(post) end let(:old_comment) { FactoryBot.create(:comment, post: post) } it "assigns the old comments as @comments" do - assigns(:comments).should eq [old_comment] + expect(assigns(:comments)).to eq [old_comment] end end From 22e456f3af124440a4387ad307e54bbacbea14b0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:06:24 +1300 Subject: [PATCH 220/267] Time stamps need a timezone --- spec/models/post_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 7ae50f7f2..6c2d9b32e 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -60,7 +60,7 @@ describe Post do context "recent activity" do before do - Time.stub(now: Time.now) + Time.stub(now: Time.zone.now) end let!(:post) { FactoryBot.create(:post, created_at: 1.day.ago) } From 3fec343f2c16d39c1fc529d760fca4c79fd8a6b1 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:13:59 +1300 Subject: [PATCH 221/267] Rubocop for hash alignment --- .rubocop.yml | 4 ++++ config/environments/development.rb | 8 ++++---- config/environments/test.rb | 26 +++++++++++++------------- config/initializers/geocoder.rb | 8 ++++---- config/routes.rb | 6 +++--- 5 files changed, 28 insertions(+), 24 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 316ffcde7..7c61c6fd1 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -26,6 +26,10 @@ Style/PercentLiteralDelimiters: Layout/MultilineMethodCallIndentation: EnforcedStyle: indented +Layout/AlignHash: + EnforcedColonStyle: table + EnforcedHashRocketStyle: table + # Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth. # SupportedStyles: with_first_parameter, with_fixed_indentation Layout/AlignParameters: diff --git a/config/environments/development.rb b/config/environments/development.rb index 363c0e32a..7b04cf96c 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -57,10 +57,10 @@ Rails.application.configure do config.action_mailer.delivery_method = :letter_opener config.action_mailer.smtp_settings = { - port: '587', - address: 'smtp.mandrillapp.com', - user_name: ENV['GROWSTUFF_MANDRILL_USERNAME'], - password: ENV['GROWSTUFF_MANDRILL_APIKEY'], + port: '587', + address: 'smtp.mandrillapp.com', + user_name: ENV['GROWSTUFF_MANDRILL_USERNAME'], + password: ENV['GROWSTUFF_MANDRILL_APIKEY'], authentication: :login } diff --git a/config/environments/test.rb b/config/environments/test.rb index cbf6101f0..47fede3a8 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -55,8 +55,8 @@ Geocoder.configure(lookup: :test) Geocoder::Lookup::Test.add_stub( "Amundsen-Scott Base, Antarctica", [ { - 'latitude' => -90.0, - 'longitude' => 0.0 + 'latitude' => -90.0, + 'longitude' => 0.0 } ] ) @@ -78,8 +78,8 @@ Geocoder::Lookup::Test.add_stub( Geocoder::Lookup::Test.add_stub( "Greenwich, UK", [ { - 'latitude' => 51.483061, - 'longitude' => -0.004151 + 'latitude' => 51.483061, + 'longitude' => -0.004151 } ] ) @@ -87,8 +87,8 @@ Geocoder::Lookup::Test.add_stub( Geocoder::Lookup::Test.add_stub( "Edinburgh", [ { - 'latitude' => 55.953252, - 'longitude' => -3.188267 + 'latitude' => 55.953252, + 'longitude' => -3.188267 } ] ) @@ -103,15 +103,15 @@ end OmniAuth.config.test_mode = true # Fake the omniauth -OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new(provider: 'facebook', - uid: '123545', - info: { - name: "John Testerson", +OmniAuth.config.mock_auth[:facebook] = OmniAuth::AuthHash.new(provider: 'facebook', + uid: '123545', + info: { + name: "John Testerson", nickname: 'JohnnyT', - email: 'example.oauth.facebook@example.com', - image: 'http://findicons.com/files/icons/1072/face_avatars/300/i04.png' + email: 'example.oauth.facebook@example.com', + image: 'http://findicons.com/files/icons/1072/face_avatars/300/i04.png' }, credentials: { - token: "token", + token: "token", secret: "donttell" }) diff --git a/config/initializers/geocoder.rb b/config/initializers/geocoder.rb index b31f1edf3..7b0b683bb 100644 --- a/config/initializers/geocoder.rb +++ b/config/initializers/geocoder.rb @@ -1,12 +1,12 @@ require 'geocodable' Geocoder.configure( - units: :km, - timeout: 10, + units: :km, + timeout: 10, http_headers: { "User-Agent" => - "#{Rails.application.config.user_agent} #{Rails.application.config.user_agent_email}", - "From" => Rails.application.config.user_agent_email + "#{Rails.application.config.user_agent} #{Rails.application.config.user_agent_email}", + "From" => Rails.application.config.user_agent_email } ) # This configuration takes precedence over environment/test.rb diff --git a/config/routes.rb b/config/routes.rb index a43de3f0c..9f8918eed 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,9 +4,9 @@ Rails.application.routes.draw do resources :plant_parts devise_for :members, controllers: { - registrations: "registrations", - passwords: "passwords", - sessions: "sessions", + registrations: "registrations", + passwords: "passwords", + sessions: "sessions", omniauth_callbacks: "omniauth_callbacks" } devise_scope :member do From 0330809e4b2f54a023a8d217a51ed3ff64b44393 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:16:08 +1300 Subject: [PATCH 222/267] Re-enable rubocop cops --- config/compass.rb | 1 + config/initializers/devise.rb | 1 + 2 files changed, 2 insertions(+) diff --git a/config/compass.rb b/config/compass.rb index 306cdd02c..028c02792 100644 --- a/config/compass.rb +++ b/config/compass.rb @@ -1,3 +1,4 @@ # Require any additional compass plugins here. # rubocop:disable Lint/UselessAssignment project_type = :rails +# rubocop:enable Lint/UselessAssignment diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index ec28eb983..fcb4caecc 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -236,3 +236,4 @@ Devise.setup do |config| # Later we may wish to ask for user_photos,user_location, however this means we need to be reviewed by facebook config.omniauth :facebook, ENV['GROWSTUFF_FACEBOOK_KEY'], ENV['GROWSTUFF_FACEBOOK_SECRET'], scope: 'email,public_profile', display: 'page', info_fields: 'email,name,first_name,last_name,id' end +# rubocop:enable Metrics/LineLength From 7399346354903dc14c29549ecc33428e7651fa40 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:18:11 +1300 Subject: [PATCH 223/267] one line method --- app/controllers/photos_controller.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 576373207..5a9f0129b 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -5,8 +5,7 @@ class PhotosController < ApplicationController respond_to :html, :json responders :flash - def show - end + def show; end def index if params[:crop_id] From 7b01fcbd4b73745fa859d862b1e53bfc206171de Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:22:29 +1300 Subject: [PATCH 224/267] Align all the hashes --- Guardfile | 2 +- app/controllers/authentications_controller.rb | 8 +-- app/controllers/crops_controller.rb | 4 +- app/controllers/likes_controller.rb | 8 +-- app/controllers/members_controller.rb | 2 +- app/helpers/application_helper.rb | 2 +- app/mailers/notifier.rb | 2 +- app/models/comment.rb | 8 +-- app/models/crop.rb | 20 +++--- app/models/csv_importer.rb | 2 +- app/models/follow.rb | 6 +- app/models/garden.rb | 16 ++--- app/models/harvest.rb | 18 +++--- app/models/member.rb | 22 +++---- app/models/photo.rb | 16 ++--- app/models/planting.rb | 12 ++-- app/models/post.rb | 6 +- app/models/seed.rb | 6 +- app/services/crop_search_service.rb | 2 +- db/migrate/20150201052245_create_cms.rb | 4 +- db/migrate/20180213005731_seed_usage.rb | 12 ++-- db/seeds.rb | 34 +++++----- lib/actions/oauth_signup_action.rb | 10 +-- lib/tasks/growstuff.rake | 2 +- .../authentications_controller_spec.rb | 6 +- spec/controllers/crops_controller_spec.rb | 4 +- spec/controllers/forums_controller_spec.rb | 4 +- spec/controllers/harvests_controller_spec.rb | 8 +-- .../notifications_controller_spec.rb | 8 +-- .../photo_associations_controller_spec.rb | 4 +- spec/controllers/photos_controller_spec.rb | 22 +++---- spec/controllers/plantings_controller_spec.rb | 2 +- spec/features/crops/crop_detail_page_spec.rb | 4 +- spec/features/crops/crop_photos_spec.rb | 24 +++---- spec/features/gardens/gardens_index_spec.rb | 14 ++-- spec/features/notifications_spec.rb | 6 +- spec/helpers/harvests_helper_spec.rb | 32 +++++----- spec/helpers/plantings_helper_spec.rb | 24 +++---- spec/lib/actions/oauth_signup_action_spec.rb | 28 ++++---- spec/models/ability_spec.rb | 4 +- spec/models/alternate_name_spec.rb | 4 +- spec/models/crop_spec.rb | 22 +++---- spec/models/harvest_spec.rb | 64 +++++++++---------- spec/models/plant_part_spec.rb | 8 +-- spec/models/planting_spec.rb | 8 +-- spec/models/post_spec.rb | 2 +- spec/requests/api/v1/crop_request_spec.rb | 42 ++++++------ spec/requests/api/v1/gardens_request_spec.rb | 32 +++++----- spec/requests/api/v1/harvest_request_spec.rb | 44 ++++++------- spec/requests/api/v1/member_request_spec.rb | 40 ++++++------ spec/requests/api/v1/photos_request_spec.rb | 40 ++++++------ .../requests/api/v1/plantings_request_spec.rb | 60 ++++++++--------- spec/requests/api/v1/seeds_request_spec.rb | 32 +++++----- spec/views/crops/_grown_for.html.haml_spec.rb | 2 +- spec/views/forums/edit.html.haml_spec.rb | 4 +- spec/views/harvests/index.html.haml_spec.rb | 6 +- spec/views/harvests/index.rss.haml_spec.rb | 8 +-- .../notifications/index.html.haml_spec.rb | 2 +- spec/views/photos/edit.html.haml_spec.rb | 6 +- spec/views/plantings/_form.html.haml_spec.rb | 6 +- spec/views/plantings/edit.html.haml_spec.rb | 2 +- spec/views/plantings/index.html.haml_spec.rb | 22 +++---- spec/views/plantings/new.html.haml_spec.rb | 4 +- spec/views/posts/edit.html.haml_spec.rb | 2 +- spec/views/roles/edit.html.haml_spec.rb | 2 +- spec/views/roles/index.html.haml_spec.rb | 4 +- spec/views/roles/new.html.haml_spec.rb | 2 +- spec/views/roles/show.html.haml_spec.rb | 2 +- 68 files changed, 445 insertions(+), 445 deletions(-) diff --git a/Guardfile b/Guardfile index 4b5f3ccb5..0d6759dbf 100644 --- a/Guardfile +++ b/Guardfile @@ -1,5 +1,5 @@ guard :rspec, - cmd: 'bundle exec rspec --format documentation', + cmd: 'bundle exec rspec --format documentation', failed_mode: :keep do watch(%r{^spec/.+_spec\.rb$}) watch(%r{^lib/(.+)\.rb$}) { |m| "spec/libs/#{m[1]}_spec.rb" } diff --git a/app/controllers/authentications_controller.rb b/app/controllers/authentications_controller.rb index fc18ff4d7..f6bf1bb21 100644 --- a/app/controllers/authentications_controller.rb +++ b/app/controllers/authentications_controller.rb @@ -12,14 +12,14 @@ class AuthenticationsController < ApplicationController @authentication = current_member.authentications .create_with( - name: name, - token: auth['credentials']['token'], + name: name, + token: auth['credentials']['token'], secret: auth['credentials']['secret'] ) .find_or_create_by( provider: auth['provider'], - uid: auth['uid'], - name: name + uid: auth['uid'], + name: name ) flash[:notice] = "Authentication successful." diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb index c5b268f8b..abfb47a0e 100644 --- a/app/controllers/crops_controller.rb +++ b/app/controllers/crops_controller.rb @@ -173,13 +173,13 @@ class CropsController < ApplicationController def crop_json_fields { include: { - plantings: { + plantings: { include: { owner: { only: %i(id login_name location latitude longitude) } } }, scientific_names: { only: [:name] }, - alternate_names: { only: [:name] } + alternate_names: { only: [:name] } } } end diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb index 0fdc2f407..e942d5b1f 100644 --- a/app/controllers/likes_controller.rb +++ b/app/controllers/likes_controller.rb @@ -24,10 +24,10 @@ class LikesController < ApplicationController def render_json(like, liked_by_member: true) { - id: like.likeable.id, + id: like.likeable.id, liked_by_member: liked_by_member, - description: ActionController::Base.helpers.pluralize(like.likeable.likes.count, "like"), - url: like_path(like, format: :json) + description: ActionController::Base.helpers.pluralize(like.likeable.likes.count, "like"), + url: like_path(like, format: :json) } end @@ -35,7 +35,7 @@ class LikesController < ApplicationController respond_to do |format| format.html { redirect_to like.likeable } format.json do - render(json: render_json(like, liked_by_member: liked_by_member), + render(json: render_json(like, liked_by_member: liked_by_member), status: status_code) end end diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index ae720e57b..9576d6750 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -51,7 +51,7 @@ class MembersController < ApplicationController EMAIL_TYPE_STRING = { send_notification_email: "direct message notifications", - send_planting_reminder: "planting reminders" + send_planting_reminder: "planting reminders" }.freeze def unsubscribe diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 97ff16b76..9e65fc303 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -53,7 +53,7 @@ module ApplicationHelper return uri.to_s end - Gravatar.new(member.email).image_url(size: size, + Gravatar.new(member.email).image_url(size: size, default: :identicon) end diff --git a/app/mailers/notifier.rb b/app/mailers/notifier.rb index 6b7420cba..0d4ea407e 100644 --- a/app/mailers/notifier.rb +++ b/app/mailers/notifier.rb @@ -19,7 +19,7 @@ class Notifier < ApplicationMailer message = { member_id: @notification.recipient.id, type: :send_notification_email } @signed_message = verifier.generate(message) - mail(to: @notification.recipient.email, + mail(to: @notification.recipient.email, subject: @notification.subject) end diff --git a/app/models/comment.rb b/app/models/comment.rb index 3c9f3ce42..182e1e61f 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -11,10 +11,10 @@ class Comment < ApplicationRecord if recipient != sender Notification.create( recipient_id: recipient, - sender_id: sender, - subject: "#{author} commented on #{post.subject}", - body: body, - post_id: post.id + sender_id: sender, + subject: "#{author} commented on #{post.subject}", + body: body, + post_id: post.id ) end end diff --git a/app/models/crop.rb b/app/models/crop.rb index 525e3fb8d..2846b8a5f 100644 --- a/app/models/crop.rb +++ b/app/models/crop.rb @@ -44,10 +44,10 @@ class Crop < ApplicationRecord ## Wikipedia urls are only necessary when approving a crop validates :en_wikipedia_url, format: { - with: %r{\Ahttps?:\/\/en\.wikipedia\.org\/wiki\/[[:alnum:]%_\.()-]+\z}, + with: %r{\Ahttps?:\/\/en\.wikipedia\.org\/wiki\/[[:alnum:]%_\.()-]+\z}, message: 'is not a valid English Wikipedia URL' }, - if: :approved? + if: :approved? #################################### # Elastic search configuration @@ -57,22 +57,22 @@ class Crop < ApplicationRecord # In order to avoid clashing between different environments, # use Rails.env as a part of index name (eg. development_growstuff) index_name [Rails.env, "growstuff"].join('_') - settings index: { number_of_shards: 1 }, + settings index: { number_of_shards: 1 }, analysis: { tokenizer: { gs_edgeNGram_tokenizer: { - type: "edgeNGram", # edgeNGram: NGram match from the start of a token - min_gram: 3, - max_gram: 10, + type: "edgeNGram", # edgeNGram: NGram match from the start of a token + min_gram: 3, + max_gram: 10, # token_chars: Elasticsearch will split on characters # that don't belong to any of these classes token_chars: %w(letter digit) } }, - analyzer: { + analyzer: { gs_edgeNGram_analyzer: { tokenizer: "gs_edgeNGram_tokenizer", - filter: ["lowercase"] + filter: ["lowercase"] } } } do @@ -82,11 +82,11 @@ class Crop < ApplicationRecord indexes :approval_status, type: 'text' indexes :scientific_names do indexes :name, - type: 'text', + type: 'text', analyzer: 'gs_edgeNGram_analyzer', # Disabling field-length norm (norm). If the norm option is turned on(by default), # higher weigh would be given for shorter fields, which in our case is irrelevant. - norms: { enabled: false } + norms: { enabled: false } end indexes :alternate_names do indexes :name, type: 'text', analyzer: 'gs_edgeNGram_analyzer' diff --git a/app/models/csv_importer.rb b/app/models/csv_importer.rb index d3b992aba..d228bb3e1 100644 --- a/app/models/csv_importer.rb +++ b/app/models/csv_importer.rb @@ -11,7 +11,7 @@ class CsvImporter @crop = Crop.find_or_create_by(name: name) @crop.update( en_wikipedia_url: en_wikipedia_url, - creator_id: cropbot.id + creator_id: cropbot.id ) add_parent(parent_name) if parent_name diff --git a/app/models/follow.rb b/app/models/follow.rb index a70fd15f6..6562ca92c 100644 --- a/app/models/follow.rb +++ b/app/models/follow.rb @@ -6,9 +6,9 @@ class Follow < ApplicationRecord after_create do Notification.create( recipient_id: followed_id, - sender_id: follower_id, - subject: "#{follower.login_name} is now following you", - body: "#{follower.login_name} just followed you on #{ENV['GROWSTUFF_SITE_NAME']}. " + sender_id: follower_id, + subject: "#{follower.login_name} is now following you", + body: "#{follower.login_name} just followed you on #{ENV['GROWSTUFF_SITE_NAME']}. " ) end end diff --git a/app/models/garden.rb b/app/models/garden.rb index 01466120f..880dda91e 100644 --- a/app/models/garden.rb +++ b/app/models/garden.rb @@ -29,20 +29,20 @@ class Garden < ApplicationRecord validates :area, numericality: { - only_integer: false, + only_integer: false, greater_than_or_equal_to: 0 }, - allow_nil: true + allow_nil: true AREA_UNITS_VALUES = { "square metres" => "square metre", - "square feet" => "square foot", - "hectares" => "hectare", - "acres" => "acre" + "square feet" => "square foot", + "hectares" => "hectare", + "acres" => "acre" }.freeze - validates :area_unit, inclusion: { in: AREA_UNITS_VALUES.values, - message: "%s is not a valid area unit" }, - allow_nil: true, + validates :area_unit, inclusion: { in: AREA_UNITS_VALUES.values, + message: "%s is not a valid area unit" }, + allow_nil: true, allow_blank: true after_validation :cleanup_area diff --git a/app/models/harvest.rb b/app/models/harvest.rb index 987c83d0b..94b71d7b4 100644 --- a/app/models/harvest.rb +++ b/app/models/harvest.rb @@ -9,15 +9,15 @@ class Harvest < ApplicationRecord # Constants UNITS_VALUES = { "individual" => "individual", - "bunches" => "bunch", - "sprigs" => "sprig", - "handfuls" => "handful", - "litres" => "litre", - "pints" => "pint", - "quarts" => "quart", - "buckets" => "bucket", - "baskets" => "basket", - "bushels" => "bushel" + "bunches" => "bunch", + "sprigs" => "sprig", + "handfuls" => "handful", + "litres" => "litre", + "pints" => "pint", + "quarts" => "quart", + "buckets" => "bucket", + "baskets" => "basket", + "bushels" => "bushel" }.freeze WEIGHT_UNITS_VALUES = { diff --git a/app/models/member.rb b/app/models/member.rb index 3a997840d..2247bd038 100644 --- a/app/models/member.rb +++ b/app/models/member.rb @@ -69,13 +69,13 @@ class Member < ApplicationRecord # Requires acceptance of the Terms of Service validates :tos_agreement, acceptance: { allow_nil: true, accept: true } validates :login_name, - length: { + length: { minimum: 2, maximum: 25, message: "should be between 2 and 25 characters long" }, - exclusion: { + exclusion: { in: %w(growstuff admin moderator staff nearby), message: "name is reserved" }, - format: { + format: { with: /\A\w+\z/, message: "may only include letters, numbers, or underscores" }, uniqueness: { @@ -136,13 +136,13 @@ class Member < ApplicationRecord result = if set flickr.photosets.getPhotos( photoset_id: set, - page: page_num, - per_page: 30 + page: page_num, + per_page: 30 ) else flickr.people.getPhotos( - user_id: 'me', - page: page_num, + user_id: 'me', + page: page_num, per_page: 30 ) end @@ -199,9 +199,9 @@ class Member < ApplicationRecord return true if Rails.env.test? && !testing gibbon.lists.subscribe( - id: Rails.application.config.newsletter_list_id, - email: { email: email }, - merge_vars: { login_name: login_name }, + id: Rails.application.config.newsletter_list_id, + email: { email: email }, + merge_vars: { login_name: login_name }, double_optin: false # they already confirmed their email with us ) end @@ -209,7 +209,7 @@ class Member < ApplicationRecord def newsletter_unsubscribe(gibbon = Gibbon::API.new, testing = false) return true if Rails.env.test? && !testing - gibbon.lists.unsubscribe(id: Rails.application.config.newsletter_list_id, + gibbon.lists.unsubscribe(id: Rails.application.config.newsletter_list_id, email: { email: email }) end diff --git a/app/models/photo.rb b/app/models/photo.rb index f3636760c..87e9f9f4c 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -8,8 +8,8 @@ class Photo < ApplicationRecord # creates a relationship for each assignee type PHOTO_CAPABLE.each do |type| has_many type.downcase.pluralize.to_s.to_sym, - through: :photographings, - source: :photographable, + through: :photographings, + source: :photographable, source_type: type end @@ -23,13 +23,13 @@ class Photo < ApplicationRecord licenses = flickr.photos.licenses.getInfo license = licenses.find { |l| l.id == info.license } { - title: calculate_title(info), - license_name: license.name, - license_url: license.url, + title: calculate_title(info), + license_name: license.name, + license_url: license.url, thumbnail_url: FlickRaw.url_q(info), - fullsize_url: FlickRaw.url_z(info), - link_url: FlickRaw.url_photopage(info), - date_taken: info.dates.taken + fullsize_url: FlickRaw.url_z(info), + link_url: FlickRaw.url_photopage(info), + date_taken: info.dates.taken } end diff --git a/app/models/planting.rb b/app/models/planting.rb index 27f99870b..984b55c03 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -21,14 +21,14 @@ class Planting < ApplicationRecord # # Ancestry of food - belongs_to :parent_seed, class_name: 'Seed', # parent + belongs_to :parent_seed, class_name: 'Seed', # parent foreign_key: 'parent_seed_id', - required: false, - inverse_of: :child_plantings - has_many :child_seeds, class_name: 'Seed', # children + required: false, + inverse_of: :child_plantings + has_many :child_seeds, class_name: 'Seed', # children foreign_key: 'parent_planting_id', - inverse_of: :parent_planting, - dependent: :nullify + inverse_of: :parent_planting, + dependent: :nullify ## ## Scopes diff --git a/app/models/post.rb b/app/models/post.rb index 9e570b845..46efa2e45 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -80,9 +80,9 @@ class Post < ApplicationRecord Notification.create( recipient_id: recipient_id, - sender_id: sender, - subject: "#{author} mentioned you in their post #{subject}", - body: body + sender_id: sender, + subject: "#{author} mentioned you in their post #{subject}", + body: body ) end end diff --git a/app/models/seed.rb b/app/models/seed.rb index d9a2261d2..2075afba2 100644 --- a/app/models/seed.rb +++ b/app/models/seed.rb @@ -23,11 +23,11 @@ class Seed < ApplicationRecord # Validations validates :crop, approved: true validates :crop, presence: { message: "must be present and exist in our database" } - validates :quantity, allow_nil: true, + validates :quantity, allow_nil: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 } - validates :days_until_maturity_min, allow_nil: true, + validates :days_until_maturity_min, allow_nil: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 } - validates :days_until_maturity_max, allow_nil: true, + validates :days_until_maturity_max, allow_nil: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 } validates :tradable_to, allow_nil: false, allow_blank: false, inclusion: { in: TRADABLE_TO_VALUES, message: "You may only trade seed nowhere, "\ diff --git a/app/services/crop_search_service.rb b/app/services/crop_search_service.rb index fb7716019..8fce60b2d 100644 --- a/app/services/crop_search_service.rb +++ b/app/services/crop_search_service.rb @@ -9,7 +9,7 @@ class CropSearchService filter: { term: { "approval_status" => "approved" } }, - must: { + must: { query_string: { query: "*#{search_str}*" } diff --git a/db/migrate/20150201052245_create_cms.rb b/db/migrate/20150201052245_create_cms.rb index 91fea54e8..71ba20b11 100644 --- a/db/migrate/20150201052245_create_cms.rb +++ b/db/migrate/20150201052245_create_cms.rb @@ -113,7 +113,7 @@ class CreateCms < ActiveRecord::Migration[4.2] end add_index :comfy_cms_categories, %i(site_id categorized_type label), unique: true, - name: 'index_cms_categories_on_site_id_and_cat_type_and_label' + name: 'index_cms_categories_on_site_id_and_cat_type_and_label' create_table :comfy_cms_categorizations, force: true do |t| t.integer :category_id, null: false @@ -122,7 +122,7 @@ class CreateCms < ActiveRecord::Migration[4.2] end add_index :comfy_cms_categorizations, %i(category_id categorized_type categorized_id), unique: true, - name: 'index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id' + name: 'index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id' end def self.down diff --git a/db/migrate/20180213005731_seed_usage.rb b/db/migrate/20180213005731_seed_usage.rb index 0a94cb71a..0e1332ab3 100644 --- a/db/migrate/20180213005731_seed_usage.rb +++ b/db/migrate/20180213005731_seed_usage.rb @@ -7,16 +7,16 @@ class SeedUsage < ActiveRecord::Migration[4.2] # plantings can be grown from a seed add_column(:plantings, :parent_seed_id, :integer) add_foreign_key(:plantings, :seeds, - column: :parent_seed_id, + column: :parent_seed_id, primary_key: :id, - name: :parent_seed, - on_delete: :nullify) + name: :parent_seed, + on_delete: :nullify) # seeds can be harvest from planting add_column(:seeds, :parent_planting_id, :integer) add_foreign_key(:seeds, :plantings, - column: :parent_planting_id, + column: :parent_planting_id, primary_key: :id, - name: :parent_planting, - on_delete: :nullify) + name: :parent_planting, + on_delete: :nullify) end end diff --git a/db/seeds.rb b/db/seeds.rb index 4781bc80f..378b98875 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -57,9 +57,9 @@ def load_test_users # rubocop:disable Metrics/AbcSize (1..member_size).each do |i| @user = Member.new( - login_name: "test#{i}", - email: "test#{i}@example.com", - password: "password#{i}", + login_name: "test#{i}", + email: "test#{i}@example.com", + password: "password#{i}", tos_agreement: true ) @user.skip_confirmation! @@ -79,11 +79,11 @@ def load_test_users # rubocop:disable Metrics/AbcSize # Create a planting by the member Planting.create( - owner_id: @user.id, - garden_id: @user.gardens.first.id, - planted_at: Time.zone.today, - crop_id: Crop.find(i % Crop.all.size + 1).id, - sunniness: select_random_item(Planting::SUNNINESS_VALUES), + owner_id: @user.id, + garden_id: @user.gardens.first.id, + planted_at: Time.zone.today, + crop_id: Crop.find(i % Crop.all.size + 1).id, + sunniness: select_random_item(Planting::SUNNINESS_VALUES), planted_from: select_random_item(Planting::PLANTED_FROM_VALUES) ) end @@ -94,9 +94,9 @@ end def load_admin_users puts "Adding admin and crop wrangler members..." @admin_user = Member.new( - login_name: "admin1", - email: "admin1@example.com", - password: "password1", + login_name: "admin1", + email: "admin1@example.com", + password: "password1", tos_agreement: true ) @admin_user.skip_confirmation! @@ -104,9 +104,9 @@ def load_admin_users @admin_user.save! @wrangler_user = Member.new( - login_name: "wrangler1", - email: "wrangler1@example.com", - password: "password1", + login_name: "wrangler1", + email: "wrangler1@example.com", + password: "password1", tos_agreement: true ) @wrangler_user.skip_confirmation! @@ -116,9 +116,9 @@ end def create_cropbot @cropbot_user = Member.new( - login_name: "cropbot", - email: Rails.application.config.bot_email, - password: SecureRandom.urlsafe_base64(64), + login_name: "cropbot", + email: Rails.application.config.bot_email, + password: SecureRandom.urlsafe_base64(64), tos_agreement: true ) @cropbot_user.skip_confirmation! diff --git a/lib/actions/oauth_signup_action.rb b/lib/actions/oauth_signup_action.rb index de274dc35..3d80cee25 100644 --- a/lib/actions/oauth_signup_action.rb +++ b/lib/actions/oauth_signup_action.rb @@ -41,14 +41,14 @@ class Growstuff::OauthSignupAction authentication = member.authentications .create_with( - name: name, - token: auth['credentials']['token'], + name: name, + token: auth['credentials']['token'], secret: auth['credentials']['secret'] ) .find_or_create_by( - provider: auth['provider'], - uid: auth['uid'], - name: name, + provider: auth['provider'], + uid: auth['uid'], + name: name, member_id: member.id ) diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index 4a6234c4b..4f22214ea 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -225,7 +225,7 @@ namespace :growstuff do if crop alternate_names.split(/,\s*/).each do |an| AlternateName.where( - name: an, + name: an, crop_id: crop.id ).first_or_create do |x| x.creator = cropbot diff --git a/spec/controllers/authentications_controller_spec.rb b/spec/controllers/authentications_controller_spec.rb index 8b61bbddc..db4bec89a 100644 --- a/spec/controllers/authentications_controller_spec.rb +++ b/spec/controllers/authentications_controller_spec.rb @@ -7,9 +7,9 @@ describe AuthenticationsController do controller.stub(:current_member) { @member } @auth = FactoryBot.create(:authentication, member: @member) request.env['omniauth.auth'] = { - 'provider' => 'foo', - 'uid' => 'bar', - 'info' => { 'nickname' => 'blah' }, + 'provider' => 'foo', + 'uid' => 'bar', + 'info' => { 'nickname' => 'blah' }, 'credentials' => { 'token' => 'blah', 'secret' => 'blah' } } end diff --git a/spec/controllers/crops_controller_spec.rb b/spec/controllers/crops_controller_spec.rb index afdea715c..ad011da74 100644 --- a/spec/controllers/crops_controller_spec.rb +++ b/spec/controllers/crops_controller_spec.rb @@ -5,9 +5,9 @@ describe CropsController do def valid_attributes { - name: "Tomato", + name: "Tomato", en_wikipedia_url: 'http://en.wikipedia.org/wiki/Tomato', - approval_status: 'approved' + approval_status: 'approved' } end diff --git a/spec/controllers/forums_controller_spec.rb b/spec/controllers/forums_controller_spec.rb index 5c59473cb..aeca681c1 100644 --- a/spec/controllers/forums_controller_spec.rb +++ b/spec/controllers/forums_controller_spec.rb @@ -5,9 +5,9 @@ describe ForumsController do def valid_attributes { - "name" => "MyString", + "name" => "MyString", "description" => "Something", - "owner_id" => 1 + "owner_id" => 1 } end diff --git a/spec/controllers/harvests_controller_spec.rb b/spec/controllers/harvests_controller_spec.rb index 186782e88..aad371da5 100644 --- a/spec/controllers/harvests_controller_spec.rb +++ b/spec/controllers/harvests_controller_spec.rb @@ -5,10 +5,10 @@ describe HarvestsController do def valid_attributes { - owner_id: subject.current_member.id, - crop_id: FactoryBot.create(:crop).id, + owner_id: subject.current_member.id, + crop_id: FactoryBot.create(:crop).id, plant_part_id: FactoryBot.create(:plant_part).id, - harvested_at: '2017-01-01' + harvested_at: '2017-01-01' } end @@ -176,7 +176,7 @@ describe HarvestsController do describe "does not save planting_id" do before do - put :update, params: { id: harvest.to_param, + put :update, params: { id: harvest.to_param, harvest: valid_attributes.merge(planting_id: not_my_planting.id) } end diff --git a/spec/controllers/notifications_controller_spec.rb b/spec/controllers/notifications_controller_spec.rb index 30cf37ddd..55ba4b947 100644 --- a/spec/controllers/notifications_controller_spec.rb +++ b/spec/controllers/notifications_controller_spec.rb @@ -6,8 +6,8 @@ describe NotificationsController do def valid_attributes { "recipient_id" => subject.current_member.id, - "sender_id" => FactoryBot.create(:member).id, - "subject" => 'test' + "sender_id" => FactoryBot.create(:member).id, + "subject" => 'test' } end @@ -18,9 +18,9 @@ describe NotificationsController do # attributes. def valid_attributes_for_sender { - "sender_id" => subject.current_member.id, + "sender_id" => subject.current_member.id, "recipient_id" => FactoryBot.create(:member).id, - "subject" => 'test' + "subject" => 'test' } end diff --git a/spec/controllers/photo_associations_controller_spec.rb b/spec/controllers/photo_associations_controller_spec.rb index 5ed022218..a7c05f029 100644 --- a/spec/controllers/photo_associations_controller_spec.rb +++ b/spec/controllers/photo_associations_controller_spec.rb @@ -6,8 +6,8 @@ describe PhotoAssociationsController do describe "destroy" do let(:valid_params) do { - id: harvest.id, - type: 'harvest', + id: harvest.id, + type: 'harvest', photo_id: photo.id } end diff --git a/spec/controllers/photos_controller_spec.rb b/spec/controllers/photos_controller_spec.rb index 88ed6599b..e49d3b194 100644 --- a/spec/controllers/photos_controller_spec.rb +++ b/spec/controllers/photos_controller_spec.rb @@ -8,13 +8,13 @@ describe PhotosController do def valid_attributes member = FactoryBot.create(:member) { - "owner_id" => member.id, + "owner_id" => member.id, "flickr_photo_id" => 1, - "title" => "Photo", - "license_name" => "CC-BY", - "thumbnail_url" => 'http://example.com/thumb.jpg', - "fullsize_url" => 'http://example.com/full.jpg', - "link_url" => 'http://example.com' + "title" => "Photo", + "license_name" => "CC-BY", + "thumbnail_url" => 'http://example.com/thumb.jpg', + "fullsize_url" => 'http://example.com/full.jpg', + "link_url" => 'http://example.com' } end @@ -60,12 +60,12 @@ describe PhotosController do describe "POST create" do before(:each) do - Photo.any_instance.stub(:flickr_metadata).and_return(title: "A Heartbreaking work of staggering genius", - license_name: "CC-BY", - license_url: "http://example.com/aybpl", + Photo.any_instance.stub(:flickr_metadata).and_return(title: "A Heartbreaking work of staggering genius", + license_name: "CC-BY", + license_url: "http://example.com/aybpl", thumbnail_url: "http://example.com/thumb.jpg", - fullsize_url: "http://example.com/full.jpg", - link_url: "http://example.com") + fullsize_url: "http://example.com/full.jpg", + link_url: "http://example.com") end let(:member) { FactoryBot.create(:member) } diff --git a/spec/controllers/plantings_controller_spec.rb b/spec/controllers/plantings_controller_spec.rb index 7f100d76b..e2c6522be 100644 --- a/spec/controllers/plantings_controller_spec.rb +++ b/spec/controllers/plantings_controller_spec.rb @@ -6,7 +6,7 @@ describe PlantingsController do def valid_attributes { garden_id: FactoryBot.create(:garden, owner: subject.current_member).id, - crop_id: FactoryBot.create(:crop).id + crop_id: FactoryBot.create(:crop).id } end diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index a194e8f1e..cbc73cf9c 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -200,8 +200,8 @@ feature "crop detail page", js: true do context 'predictions' do let!(:planting) do - FactoryBot.create(:planting, crop: crop, - planted_at: 100.days.ago, + FactoryBot.create(:planting, crop: crop, + planted_at: 100.days.ago, finished_at: 1.day.ago) end diff --git a/spec/features/crops/crop_photos_spec.rb b/spec/features/crops/crop_photos_spec.rb index efefc6a36..36138fed6 100644 --- a/spec/features/crops/crop_photos_spec.rb +++ b/spec/features/crops/crop_photos_spec.rb @@ -10,27 +10,27 @@ feature "crop detail page", js: true do let(:harvest) { create :harvest, owner: member } let(:valid_server) { 'https://farm5.staticflickr.com/' } let(:photo1) do - create(:photo, owner: member, - title: 'photo 1', - fullsize_url: "#{valid_server}photo1.jpg", + create(:photo, owner: member, + title: 'photo 1', + fullsize_url: "#{valid_server}photo1.jpg", thumbnail_url: "#{valid_server}thumb1.jpg") end let(:photo2) do - create(:photo, owner: member, - title: 'photo 2', - fullsize_url: "#{valid_server}photo2.jpg", + create(:photo, owner: member, + title: 'photo 2', + fullsize_url: "#{valid_server}photo2.jpg", thumbnail_url: "#{valid_server}thumb2.jpg") end let(:photo3) do - create(:photo, owner: member, - title: 'photo 3', - fullsize_url: "#{valid_server}photo3.jpg", + create(:photo, owner: member, + title: 'photo 3', + fullsize_url: "#{valid_server}photo3.jpg", thumbnail_url: "#{valid_server}thumb3.jpg") end let(:photo4) do - create(:photo, owner: member, - title: 'photo 4', - fullsize_url: "#{valid_server}photo4.jpg", + create(:photo, owner: member, + title: 'photo 4', + fullsize_url: "#{valid_server}photo4.jpg", thumbnail_url: "#{valid_server}thumb4.jpg") end diff --git a/spec/features/gardens/gardens_index_spec.rb b/spec/features/gardens/gardens_index_spec.rb index 03fc28447..ebe5f5547 100644 --- a/spec/features/gardens/gardens_index_spec.rb +++ b/spec/features/gardens/gardens_index_spec.rb @@ -79,10 +79,10 @@ feature "Gardens#index", :js do # time to finished = 90 days FactoryBot.create(:harvest, harvested_at: 50.days.ago, - crop: crop, - planting: FactoryBot.create(:planting, - crop: crop, - planted_at: 100.days.ago, + crop: crop, + planting: FactoryBot.create(:planting, + crop: crop, + planted_at: 100.days.ago, finished_at: 10.days.ago)) crop.plantings.each(&:update_harvest_days!) crop.update_lifespan_medians @@ -96,9 +96,9 @@ feature "Gardens#index", :js do describe 'harvest still growing' do let!(:planting) do FactoryBot.create :planting, - crop: crop, - owner: member, - garden: garden, + crop: crop, + owner: member, + garden: garden, planted_at: Time.zone.today end diff --git a/spec/features/notifications_spec.rb b/spec/features/notifications_spec.rb index a3049a0c2..05e6e2b9a 100644 --- a/spec/features/notifications_spec.rb +++ b/spec/features/notifications_spec.rb @@ -7,10 +7,10 @@ feature "Notifications", :js do context "On existing notification" do let!(:notification) do create :notification, - sender: sender, + sender: sender, recipient: recipient, - body: "Notification body", - post_id: nil + body: "Notification body", + post_id: nil end background do diff --git a/spec/helpers/harvests_helper_spec.rb b/spec/helpers/harvests_helper_spec.rb index 1ba63810d..d720f1318 100644 --- a/spec/helpers/harvests_helper_spec.rb +++ b/spec/helpers/harvests_helper_spec.rb @@ -4,7 +4,7 @@ describe HarvestsHelper do describe "display_quantity" do it "blank" do harvest = FactoryBot.create(:harvest, - quantity: nil, + quantity: nil, weight_quantity: nil) result = helper.display_quantity(harvest) result.should eq 'not specified' @@ -12,8 +12,8 @@ describe HarvestsHelper do it '3 individual' do harvest = FactoryBot.create(:harvest, - quantity: 3, - unit: 'individual', + quantity: 3, + unit: 'individual', weight_quantity: nil) result = helper.display_quantity(harvest) result.should eq '3' @@ -21,8 +21,8 @@ describe HarvestsHelper do it '1 bunch' do harvest = FactoryBot.create(:harvest, - quantity: 1, - unit: 'bunch', + quantity: 1, + unit: 'bunch', weight_quantity: nil) result = helper.display_quantity(harvest) result.should eq '1 bunch' @@ -30,8 +30,8 @@ describe HarvestsHelper do it '3 bunches' do harvest = FactoryBot.create(:harvest, - quantity: 3, - unit: 'bunch', + quantity: 3, + unit: 'bunch', weight_quantity: nil) result = helper.display_quantity(harvest) result.should eq '3 bunches' @@ -39,30 +39,30 @@ describe HarvestsHelper do it '3 kg' do harvest = FactoryBot.create(:harvest, - quantity: nil, - unit: nil, + quantity: nil, + unit: nil, weight_quantity: 3, - weight_unit: 'kg') + weight_unit: 'kg') result = helper.display_quantity(harvest) result.should eq '3 kg' end it '3 individual weighing 3 kg' do harvest = FactoryBot.create(:harvest, - quantity: 3, - unit: 'individual', + quantity: 3, + unit: 'individual', weight_quantity: 3, - weight_unit: 'kg') + weight_unit: 'kg') result = helper.display_quantity(harvest) result.should eq '3, weighing 3 kg' end it '3 bunches weighing 3 kg' do harvest = FactoryBot.create(:harvest, - quantity: 3, - unit: 'bunch', + quantity: 3, + unit: 'bunch', weight_quantity: 3, - weight_unit: 'kg') + weight_unit: 'kg') result = helper.display_quantity(harvest) result.should eq '3 bunches, weighing 3 kg' end diff --git a/spec/helpers/plantings_helper_spec.rb b/spec/helpers/plantings_helper_spec.rb index 3af084d5a..f71fc6ef4 100644 --- a/spec/helpers/plantings_helper_spec.rb +++ b/spec/helpers/plantings_helper_spec.rb @@ -6,18 +6,18 @@ describe PlantingsHelper do it "does not have a quantity nor a planted from value provided" do planting = FactoryBot.build(:planting, - quantity: nil, + quantity: nil, planted_from: '', - owner: member) + owner: member) result = helper.display_planting(planting) expect(result).to eq "crop_lady." end it "does not have a quantity provided" do planting = FactoryBot.build(:planting, - quantity: nil, + quantity: nil, planted_from: 'seed', - owner: member) + owner: member) result = helper.display_planting(planting) expect(result).to eq "crop_lady planted seeds." end @@ -25,18 +25,18 @@ describe PlantingsHelper do context "when quantity is greater than 1" do it "does not have a planted from value provided" do planting = FactoryBot.build(:planting, - quantity: 10, + quantity: 10, planted_from: '', - owner: member) + owner: member) result = helper.display_planting(planting) expect(result).to eq "crop_lady planted 10 units." end it "does have a planted from value provided" do planting = FactoryBot.build(:planting, - quantity: 5, + quantity: 5, planted_from: 'seed', - owner: member) + owner: member) result = helper.display_planting(planting) expect(result).to eq "crop_lady planted 5 seeds." end @@ -45,18 +45,18 @@ describe PlantingsHelper do context "when quantity is 1" do it "does not have a planted from value provided" do planting = FactoryBot.build(:planting, - quantity: 1, + quantity: 1, planted_from: '', - owner: member) + owner: member) result = helper.display_planting(planting) expect(result).to eq "crop_lady planted 1 unit." end it "does have a planted from value provided" do planting = FactoryBot.build(:planting, - quantity: 1, + quantity: 1, planted_from: 'seed', - owner: member) + owner: member) result = helper.display_planting(planting) expect(result).to eq "crop_lady planted 1 seed." end diff --git a/spec/lib/actions/oauth_signup_action_spec.rb b/spec/lib/actions/oauth_signup_action_spec.rb index 1710428a4..3fc37c00e 100644 --- a/spec/lib/actions/oauth_signup_action_spec.rb +++ b/spec/lib/actions/oauth_signup_action_spec.rb @@ -8,16 +8,16 @@ describe 'Growstuff::OauthSignupAction' do context 'with a valid authentication' do before :each do - @auth = OmniAuth::AuthHash.new('provider' => 'facebook', - 'uid' => '123545', - 'info' => { - 'name' => "John Testerson's Brother", + @auth = OmniAuth::AuthHash.new('provider' => 'facebook', + 'uid' => '123545', + 'info' => { + 'name' => "John Testerson's Brother", 'nickname' => 'JohnnyB', - 'email' => 'example.oauth.facebook@example.com', - 'image' => 'http://findicons.com/files/icons/1072/face_avatars/300/i04.png' + 'email' => 'example.oauth.facebook@example.com', + 'image' => 'http://findicons.com/files/icons/1072/face_avatars/300/i04.png' }, 'credentials' => { - 'token' => "token", + 'token' => "token", 'secret' => "donttell" }) end @@ -74,8 +74,8 @@ describe 'Growstuff::OauthSignupAction' do @auth['info']['email'] = 'never.used.oauth@yahoo.com' Member.where(email: @auth['info']['email']).delete_all - @existing_member = create :member, email: @auth['info']['email'], - login_name: 'existing', + @existing_member = create :member, email: @auth['info']['email'], + login_name: 'existing', preferred_avatar_uri: 'http://cl.jroo.me/z3/W/H/K/e/a.baa-very-cool-hat-you-.jpg' @member = @action.find_or_create_from_authorization(@auth) @@ -118,13 +118,13 @@ describe 'Growstuff::OauthSignupAction' do Member.where(email: @auth['info']['email']).delete_all Authentication.delete_all - @existing_member = create :member, email: @auth['info']['email'], - login_name: 'schrodingerscat', + @existing_member = create :member, email: @auth['info']['email'], + login_name: 'schrodingerscat', preferred_avatar_uri: 'http://cl.jroo.me/z3/W/H/K/e/a.baa-very-cool-hat-you-.jpg' - @existing_authentication = @existing_member.authentications.create(provider: 'facebook', - uid: '123545', - name: "John Testerson's Brother", + @existing_authentication = @existing_member.authentications.create(provider: 'facebook', + uid: '123545', + name: "John Testerson's Brother", member_id: @existing_member.id) @member = @action.find_or_create_from_authorization(@auth) diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index e95dfbdc6..7891135c9 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -20,13 +20,13 @@ describe Ability do ability.should_not be_able_to(:create, FactoryBot.create(:notification, recipient: member, - sender: member)) + sender: member)) end it "member can send messages to someone else" do ability.should be_able_to(:create, FactoryBot.create(:notification, recipient: FactoryBot.create(:member), - sender: member)) + sender: member)) end end diff --git a/spec/models/alternate_name_spec.rb b/spec/models/alternate_name_spec.rb index a76749130..42b8aa9aa 100644 --- a/spec/models/alternate_name_spec.rb +++ b/spec/models/alternate_name_spec.rb @@ -10,8 +10,8 @@ describe AlternateName do it 'should be possible to add multiple alternate names to a crop' do crop = an.crop an2 = AlternateName.create( - name: "really alternative tomato", - crop_id: crop.id, + name: "really alternative tomato", + crop_id: crop.id, creator_id: an.creator.id ) crop.alternate_names << an2 diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb index a52e6c583..1b8de81ed 100644 --- a/spec/models/crop_spec.rb +++ b/spec/models/crop_spec.rb @@ -259,20 +259,20 @@ describe Crop do @root = FactoryBot.create(:plant_part, name: 'root') @bulb = FactoryBot.create(:plant_part, name: 'bulb') @harvest1 = FactoryBot.create(:harvest, - crop: crop, + crop: crop, plant_part: @fruit) @harvest2 = FactoryBot.create(:harvest, - crop: crop, + crop: crop, plant_part: @fruit) @harvest3 = FactoryBot.create(:harvest, - crop: crop, + crop: crop, plant_part: @seed) @harvest4 = FactoryBot.create(:harvest, - crop: crop, + crop: crop, plant_part: @root) crop.popular_plant_parts.should == { [@fruit.id, @fruit.name] => 2, - [@seed.id, @seed.name] => 1, - [@root.id, @root.name] => 1 } + [@seed.id, @seed.name] => 1, + [@root.id, @root.name] => 1 } end end @@ -564,15 +564,15 @@ describe Crop do context "crop rejections" do let!(:rejected_reason) do - FactoryBot.create(:crop, name: 'tomato', - approval_status: 'rejected', + FactoryBot.create(:crop, name: 'tomato', + approval_status: 'rejected', reason_for_rejection: 'not edible') end let!(:rejected_other) do - FactoryBot.create(:crop, name: 'tomato', - approval_status: 'rejected', + FactoryBot.create(:crop, name: 'tomato', + approval_status: 'rejected', reason_for_rejection: 'other', - rejection_notes: 'blah blah blah') + rejection_notes: 'blah blah blah') end describe "rejecting a crop" do diff --git a/spec/models/harvest_spec.rb b/spec/models/harvest_spec.rb index 455afeb9b..9711d2a59 100644 --- a/spec/models/harvest_spec.rb +++ b/spec/models/harvest_spec.rb @@ -150,74 +150,74 @@ describe Harvest do let(:crop) { FactoryBot.create(:crop, name: "apricot") } it "apricots" do - @h = FactoryBot.create(:harvest, crop: crop, - quantity: nil, - unit: nil, + @h = FactoryBot.create(:harvest, crop: crop, + quantity: nil, + unit: nil, weight_quantity: nil, - weight_unit: nil) + weight_unit: nil) expect(@h.to_s).to eq "apricots" end it "1 individual apricot" do - @h = FactoryBot.create(:harvest, crop: crop, - quantity: 1, - unit: 'individual', + @h = FactoryBot.create(:harvest, crop: crop, + quantity: 1, + unit: 'individual', weight_quantity: nil, - weight_unit: nil) + weight_unit: nil) expect(@h.to_s).to eq "1 individual apricot" end it "10 individual apricots" do - @h = FactoryBot.create(:harvest, crop: crop, - quantity: 10, - unit: 'individual', + @h = FactoryBot.create(:harvest, crop: crop, + quantity: 10, + unit: 'individual', weight_quantity: nil, - weight_unit: nil) + weight_unit: nil) expect(@h.to_s).to eq "10 individual apricots" end it "1 bushel of apricots" do - @h = FactoryBot.create(:harvest, crop: crop, - quantity: 1, - unit: 'bushel', + @h = FactoryBot.create(:harvest, crop: crop, + quantity: 1, + unit: 'bushel', weight_quantity: nil, - weight_unit: nil) + weight_unit: nil) expect(@h.to_s).to eq "1 bushel of apricots" end it "1.5 bushels of apricots" do - @h = FactoryBot.create(:harvest, crop: crop, - quantity: 1.5, - unit: 'bushel', + @h = FactoryBot.create(:harvest, crop: crop, + quantity: 1.5, + unit: 'bushel', weight_quantity: nil, - weight_unit: nil) + weight_unit: nil) expect(@h.to_s).to eq "1.5 bushels of apricots" end it "10 bushels of apricots" do - @h = FactoryBot.create(:harvest, crop: crop, - quantity: 10, - unit: 'bushel', + @h = FactoryBot.create(:harvest, crop: crop, + quantity: 10, + unit: 'bushel', weight_quantity: nil, - weight_unit: nil) + weight_unit: nil) expect(@h.to_s).to eq "10 bushels of apricots" end it "apricots weighing 1.2 kg" do - @h = FactoryBot.create(:harvest, crop: crop, - quantity: nil, - unit: nil, + @h = FactoryBot.create(:harvest, crop: crop, + quantity: nil, + unit: nil, weight_quantity: 1.2, - weight_unit: 'kg') + weight_unit: 'kg') expect(@h.to_s).to eq "apricots weighing 1.2 kg" end it "10 bushels of apricots weighing 100 kg" do - @h = FactoryBot.create(:harvest, crop: crop, - quantity: 10, - unit: 'bushel', + @h = FactoryBot.create(:harvest, crop: crop, + quantity: 10, + unit: 'bushel', weight_quantity: 100, - weight_unit: 'kg') + weight_unit: 'kg') expect(@h.to_s).to eq "10 bushels of apricots weighing 100 kg" end end diff --git a/spec/models/plant_part_spec.rb b/spec/models/plant_part_spec.rb index a6ec189dd..66612e5ad 100644 --- a/spec/models/plant_part_spec.rb +++ b/spec/models/plant_part_spec.rb @@ -11,10 +11,10 @@ describe PlantPart do @tomato = FactoryBot.create(:tomato) @pp1 = FactoryBot.create(:plant_part) @h1 = FactoryBot.create(:harvest, - crop: @tomato, + crop: @tomato, plant_part: @pp1) @h2 = FactoryBot.create(:harvest, - crop: @maize, + crop: @maize, plant_part: @pp1) @pp1.crops.should include @tomato @pp1.crops.should include @maize @@ -24,10 +24,10 @@ describe PlantPart do @maize = FactoryBot.create(:maize) @pp1 = FactoryBot.create(:plant_part) @h1 = FactoryBot.create(:harvest, - crop: @maize, + crop: @maize, plant_part: @pp1) @h2 = FactoryBot.create(:harvest, - crop: @maize, + crop: @maize, plant_part: @pp1) @pp1.crops.should eq [@maize] end diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb index 6647655ca..29241db3f 100644 --- a/spec/models/planting_spec.rb +++ b/spec/models/planting_spec.rb @@ -180,8 +180,8 @@ describe Planting do before do FactoryBot.create(:harvest, - planting: planting, - crop: planting.crop, + planting: planting, + crop: planting.crop, harvested_at: 10.days.ago) planting.update_harvest_days! planting.crop.update_harvest_medians @@ -402,8 +402,8 @@ describe Planting do # this one is newer, and has the same owner, through the garden @planting2 = FactoryBot.create(:planting, created_at: 1.minute.ago, - garden: @planting1.garden, - owner: @planting1.owner) + garden: @planting1.garden, + owner: @planting1.owner) @planting2.photos << FactoryBot.create(:photo, owner: @planting2.owner) @planting2.save diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index 6c2d9b32e..eeda089d2 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -70,7 +70,7 @@ describe Post do end it "sets recent activity to comment time" do - comment = FactoryBot.create(:comment, post: post, + comment = FactoryBot.create(:comment, post: post, created_at: 1.hour.ago) post.recent_activity.to_i.should eq comment.created_at.to_i end diff --git a/spec/requests/api/v1/crop_request_spec.rb b/spec/requests/api/v1/crop_request_spec.rb index d0f1948fa..31212ab2c 100644 --- a/spec/requests/api/v1/crop_request_spec.rb +++ b/spec/requests/api/v1/crop_request_spec.rb @@ -6,15 +6,15 @@ RSpec.describe 'Plantings', type: :request do let(:headers) { { 'Accept' => 'application/vnd.api+json' } } let!(:crop) { FactoryBot.create :crop } let(:crop_encoded_as_json_api) do - { "id" => crop.id.to_s, - "type" => "crops", - "links" => { "self" => resource_url }, - "attributes" => attributes, + { "id" => crop.id.to_s, + "type" => "crops", + "links" => { "self" => resource_url }, + "attributes" => attributes, "relationships" => { "plantings" => plantings_as_json_api, - "parent" => parent_as_json_api, - "photos" => photos_as_json_api, - "harvests" => harvests_as_json_api + "parent" => parent_as_json_api, + "photos" => photos_as_json_api, + "harvests" => harvests_as_json_api } } end @@ -22,37 +22,37 @@ RSpec.describe 'Plantings', type: :request do let(:harvests_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/harvests", - "related" => "#{resource_url}/harvests" } } + { "self" => "#{resource_url}/relationships/harvests", + "related" => "#{resource_url}/harvests" } } end let(:parent_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/parent", - "related" => "#{resource_url}/parent" } } + { "self" => "#{resource_url}/relationships/parent", + "related" => "#{resource_url}/parent" } } end let(:plantings_as_json_api) do { "links" => - { "self" => - "#{resource_url}/relationships/plantings", - "related" => "#{resource_url}/plantings" } } + { "self" => + "#{resource_url}/relationships/plantings", + "related" => "#{resource_url}/plantings" } } end let(:photos_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/photos", - "related" => "#{resource_url}/photos" } } + { "self" => "#{resource_url}/relationships/photos", + "related" => "#{resource_url}/photos" } } end let(:attributes) do { - "name" => crop.name, - "en-wikipedia-url" => crop.en_wikipedia_url, - "perennial" => false, - "median-lifespan" => nil, + "name" => crop.name, + "en-wikipedia-url" => crop.en_wikipedia_url, + "perennial" => false, + "median-lifespan" => nil, "median-days-to-first-harvest" => nil, - "median-days-to-last-harvest" => nil + "median-days-to-last-harvest" => nil } end diff --git a/spec/requests/api/v1/gardens_request_spec.rb b/spec/requests/api/v1/gardens_request_spec.rb index 60283f7b7..8426dfcb2 100644 --- a/spec/requests/api/v1/gardens_request_spec.rb +++ b/spec/requests/api/v1/gardens_request_spec.rb @@ -6,36 +6,36 @@ RSpec.describe 'Gardens', type: :request do let(:headers) { { 'Accept' => 'application/vnd.api+json' } } let!(:garden) { FactoryBot.create :garden } let(:garden_encoded_as_json_api) do - { "id" => garden.id.to_s, - "type" => "gardens", - "links" => { "self" => resource_url }, - "attributes" => { "name" => garden.name }, + { "id" => garden.id.to_s, + "type" => "gardens", + "links" => { "self" => resource_url }, + "attributes" => { "name" => garden.name }, "relationships" => - { - "owner" => owner_as_json_api, - "plantings" => plantings_as_json_api, - "photos" => photos_as_json_api - } } + { + "owner" => owner_as_json_api, + "plantings" => plantings_as_json_api, + "photos" => photos_as_json_api + } } end let(:resource_url) { "http://www.example.com/api/v1/gardens/#{garden.id}" } let(:plantings_as_json_api) do { "links" => - { "self" => - "#{resource_url}/relationships/plantings", - "related" => "#{resource_url}/plantings" } } + { "self" => + "#{resource_url}/relationships/plantings", + "related" => "#{resource_url}/plantings" } } end let(:owner_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/owner", - "related" => "#{resource_url}/owner" } } + { "self" => "#{resource_url}/relationships/owner", + "related" => "#{resource_url}/owner" } } end let(:photos_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/photos", - "related" => "#{resource_url}/photos" } } + { "self" => "#{resource_url}/relationships/photos", + "related" => "#{resource_url}/photos" } } end scenario '#index' do diff --git a/spec/requests/api/v1/harvest_request_spec.rb b/spec/requests/api/v1/harvest_request_spec.rb index 595774694..c4fddd350 100644 --- a/spec/requests/api/v1/harvest_request_spec.rb +++ b/spec/requests/api/v1/harvest_request_spec.rb @@ -6,15 +6,15 @@ RSpec.describe 'Harvests', type: :request do let(:headers) { { 'Accept' => 'application/vnd.api+json' } } let!(:harvest) { FactoryBot.create :harvest } let(:harvest_encoded_as_json_api) do - { "id" => harvest.id.to_s, - "type" => "harvests", - "links" => { "self" => resource_url }, - "attributes" => attributes, + { "id" => harvest.id.to_s, + "type" => "harvests", + "links" => { "self" => resource_url }, + "attributes" => attributes, "relationships" => { - "crop" => crop_as_json_api, + "crop" => crop_as_json_api, "planting" => planting_as_json_api, - "owner" => owner_as_json_api, - "photos" => photos_as_json_api + "owner" => owner_as_json_api, + "photos" => photos_as_json_api } } end @@ -22,38 +22,38 @@ RSpec.describe 'Harvests', type: :request do let(:crop_as_json_api) do { "links" => - { "self" => - "#{resource_url}/relationships/crop", - "related" => "#{resource_url}/crop" } } + { "self" => + "#{resource_url}/relationships/crop", + "related" => "#{resource_url}/crop" } } end let(:owner_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/owner", - "related" => "#{resource_url}/owner" } } + { "self" => "#{resource_url}/relationships/owner", + "related" => "#{resource_url}/owner" } } end let(:planting_as_json_api) do { "links" => - { "self" => - "#{resource_url}/relationships/planting", - "related" => "#{resource_url}/planting" } } + { "self" => + "#{resource_url}/relationships/planting", + "related" => "#{resource_url}/planting" } } end let(:photos_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/photos", - "related" => "#{resource_url}/photos" } } + { "self" => "#{resource_url}/relationships/photos", + "related" => "#{resource_url}/photos" } } end let(:attributes) do { - "harvested-at" => "2015-09-17", - "description" => harvest.description, - "unit" => harvest.unit, + "harvested-at" => "2015-09-17", + "description" => harvest.description, + "unit" => harvest.unit, "weight-quantity" => harvest.weight_quantity.to_s, - "weight-unit" => harvest.weight_unit, - "si-weight" => harvest.si_weight + "weight-unit" => harvest.weight_unit, + "si-weight" => harvest.si_weight } end diff --git a/spec/requests/api/v1/member_request_spec.rb b/spec/requests/api/v1/member_request_spec.rb index 334a18fd9..f44b2a4ae 100644 --- a/spec/requests/api/v1/member_request_spec.rb +++ b/spec/requests/api/v1/member_request_spec.rb @@ -6,16 +6,16 @@ RSpec.describe 'Members', type: :request do let(:headers) { { 'Accept' => 'application/vnd.api+json' } } let!(:member) { FactoryBot.create :member } let(:member_encoded_as_json_api) do - { "id" => member.id.to_s, - "type" => "members", - "links" => { "self" => resource_url }, - "attributes" => attributes, + { "id" => member.id.to_s, + "type" => "members", + "links" => { "self" => resource_url }, + "attributes" => attributes, "relationships" => { - "gardens" => gardens_as_json_api, - "harvests" => harvests_as_json_api, - "photos" => photos_as_json_api, + "gardens" => gardens_as_json_api, + "harvests" => harvests_as_json_api, + "photos" => photos_as_json_api, "plantings" => plantings_as_json_api, - "seeds" => seeds_as_json_api + "seeds" => seeds_as_json_api } } end @@ -23,32 +23,32 @@ RSpec.describe 'Members', type: :request do let(:harvests_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/harvests", - "related" => "#{resource_url}/harvests" } } + { "self" => "#{resource_url}/relationships/harvests", + "related" => "#{resource_url}/harvests" } } end let(:photos_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/photos", - "related" => "#{resource_url}/photos" } } + { "self" => "#{resource_url}/relationships/photos", + "related" => "#{resource_url}/photos" } } end let(:seeds_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/seeds", - "related" => "#{resource_url}/seeds" } } + { "self" => "#{resource_url}/relationships/seeds", + "related" => "#{resource_url}/seeds" } } end let(:plantings_as_json_api) do { "links" => - { "self" => - "#{resource_url}/relationships/plantings", - "related" => "#{resource_url}/plantings" } } + { "self" => + "#{resource_url}/relationships/plantings", + "related" => "#{resource_url}/plantings" } } end let(:gardens_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/gardens", - "related" => "#{resource_url}/gardens" } } + { "self" => "#{resource_url}/relationships/gardens", + "related" => "#{resource_url}/gardens" } } end let(:attributes) do @@ -80,7 +80,7 @@ RSpec.describe 'Members', type: :request do it '#update' do expect do - post "/api/v1/members/#{member.id}", params: { + post "/api/v1/members/#{member.id}", params: { 'member' => { 'login_name' => 'can i modify this' } }, headers: headers diff --git a/spec/requests/api/v1/photos_request_spec.rb b/spec/requests/api/v1/photos_request_spec.rb index 7ae939562..15fb8cd19 100644 --- a/spec/requests/api/v1/photos_request_spec.rb +++ b/spec/requests/api/v1/photos_request_spec.rb @@ -6,15 +6,15 @@ RSpec.describe 'Photos', type: :request do let(:headers) { { 'Accept' => 'application/vnd.api+json' } } let!(:photo) { FactoryBot.create :photo } let(:photo_encoded_as_json_api) do - { "id" => photo.id.to_s, - "type" => "photos", - "links" => { "self" => resource_url }, - "attributes" => attributes, + { "id" => photo.id.to_s, + "type" => "photos", + "links" => { "self" => resource_url }, + "attributes" => attributes, "relationships" => { - "owner" => owner_as_json_api, + "owner" => owner_as_json_api, "plantings" => plantings_as_json_api, - "harvests" => harvests_as_json_api, - "gardens" => gardens_as_json_api + "harvests" => harvests_as_json_api, + "gardens" => gardens_as_json_api } } end @@ -22,36 +22,36 @@ RSpec.describe 'Photos', type: :request do let(:owner_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/owner", - "related" => "#{resource_url}/owner" } } + { "self" => "#{resource_url}/relationships/owner", + "related" => "#{resource_url}/owner" } } end let(:harvests_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/harvests", - "related" => "#{resource_url}/harvests" } } + { "self" => "#{resource_url}/relationships/harvests", + "related" => "#{resource_url}/harvests" } } end let(:gardens_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/gardens", - "related" => "#{resource_url}/gardens" } } + { "self" => "#{resource_url}/relationships/gardens", + "related" => "#{resource_url}/gardens" } } end let(:plantings_as_json_api) do { "links" => - { "self" => - "#{resource_url}/relationships/plantings", - "related" => "#{resource_url}/plantings" } } + { "self" => + "#{resource_url}/relationships/plantings", + "related" => "#{resource_url}/plantings" } } end let(:attributes) do { "thumbnail-url" => photo.thumbnail_url, - "fullsize-url" => photo.fullsize_url, - "link-url" => photo.link_url, - "license-name" => photo.license_name, - "title" => photo.title + "fullsize-url" => photo.fullsize_url, + "link-url" => photo.link_url, + "license-name" => photo.license_name, + "title" => photo.title } end diff --git a/spec/requests/api/v1/plantings_request_spec.rb b/spec/requests/api/v1/plantings_request_spec.rb index 24085b00c..0291af4b2 100644 --- a/spec/requests/api/v1/plantings_request_spec.rb +++ b/spec/requests/api/v1/plantings_request_spec.rb @@ -6,15 +6,15 @@ RSpec.describe 'Plantings', type: :request do let(:headers) { { 'Accept' => 'application/vnd.api+json' } } let!(:planting) { FactoryBot.create :planting } let(:planting_encoded_as_json_api) do - { "id" => planting.id.to_s, - "type" => "plantings", - "links" => { "self" => resource_url }, - "attributes" => attributes, + { "id" => planting.id.to_s, + "type" => "plantings", + "links" => { "self" => resource_url }, + "attributes" => attributes, "relationships" => { - "garden" => garden_as_json_api, - "crop" => crop_as_json_api, - "owner" => owner_as_json_api, - "photos" => photos_as_json_api, + "garden" => garden_as_json_api, + "crop" => crop_as_json_api, + "owner" => owner_as_json_api, + "photos" => photos_as_json_api, "harvests" => harvests_as_json_api } } end @@ -23,48 +23,48 @@ RSpec.describe 'Plantings', type: :request do let(:harvests_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/harvests", - "related" => "#{resource_url}/harvests" } } + { "self" => "#{resource_url}/relationships/harvests", + "related" => "#{resource_url}/harvests" } } end let(:photos_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/photos", - "related" => "#{resource_url}/photos" } } + { "self" => "#{resource_url}/relationships/photos", + "related" => "#{resource_url}/photos" } } end let(:owner_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/owner", - "related" => "#{resource_url}/owner" } } + { "self" => "#{resource_url}/relationships/owner", + "related" => "#{resource_url}/owner" } } end let(:crop_as_json_api) do { "links" => - { "self" => - "#{resource_url}/relationships/crop", - "related" => "#{resource_url}/crop" } } + { "self" => + "#{resource_url}/relationships/crop", + "related" => "#{resource_url}/crop" } } end let(:garden_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/garden", - "related" => "#{resource_url}/garden" } } + { "self" => "#{resource_url}/relationships/garden", + "related" => "#{resource_url}/garden" } } end let(:attributes) do { - "planted-at" => "2014-07-30", - "finished-at" => nil, - "finished" => false, - "quantity" => 33, - "description" => planting.description, - "sunniness" => nil, - "planted-from" => nil, - "expected-lifespan" => nil, + "planted-at" => "2014-07-30", + "finished-at" => nil, + "finished" => false, + "quantity" => 33, + "description" => planting.description, + "sunniness" => nil, + "planted-from" => nil, + "expected-lifespan" => nil, "finish-predicted-at" => nil, - "percentage-grown" => nil, - "first-harvest-date" => nil, - "last-harvest-date" => nil + "percentage-grown" => nil, + "first-harvest-date" => nil, + "last-harvest-date" => nil } end diff --git a/spec/requests/api/v1/seeds_request_spec.rb b/spec/requests/api/v1/seeds_request_spec.rb index 92cafc0a4..909d08864 100644 --- a/spec/requests/api/v1/seeds_request_spec.rb +++ b/spec/requests/api/v1/seeds_request_spec.rb @@ -6,13 +6,13 @@ RSpec.describe 'Photos', type: :request do let(:headers) { { 'Accept' => 'application/vnd.api+json' } } let!(:seed) { FactoryBot.create :seed } let(:seed_encoded_as_json_api) do - { "id" => seed.id.to_s, - "type" => "seeds", - "links" => { "self" => resource_url }, - "attributes" => attributes, + { "id" => seed.id.to_s, + "type" => "seeds", + "links" => { "self" => resource_url }, + "attributes" => attributes, "relationships" => { "owner" => owner_as_json_api, - "crop" => crop_as_json_api + "crop" => crop_as_json_api } } end @@ -20,27 +20,27 @@ RSpec.describe 'Photos', type: :request do let(:owner_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/owner", - "related" => "#{resource_url}/owner" } } + { "self" => "#{resource_url}/relationships/owner", + "related" => "#{resource_url}/owner" } } end let(:crop_as_json_api) do { "links" => - { "self" => "#{resource_url}/relationships/crop", - "related" => "#{resource_url}/crop" } } + { "self" => "#{resource_url}/relationships/crop", + "related" => "#{resource_url}/crop" } } end let(:attributes) do { - "description" => seed.description, - "quantity" => seed.quantity, - "plant-before" => "2013-07-15", - "tradable-to" => seed.tradable_to, + "description" => seed.description, + "quantity" => seed.quantity, + "plant-before" => "2013-07-15", + "tradable-to" => seed.tradable_to, "days-until-maturity-min" => seed.days_until_maturity_min, "days-until-maturity-max" => seed.days_until_maturity_max, - "organic" => seed.organic, - "gmo" => seed.gmo, - "heirloom" => seed.heirloom + "organic" => seed.organic, + "gmo" => seed.gmo, + "heirloom" => seed.heirloom } end diff --git a/spec/views/crops/_grown_for.html.haml_spec.rb b/spec/views/crops/_grown_for.html.haml_spec.rb index c378c296c..ccb04b28d 100644 --- a/spec/views/crops/_grown_for.html.haml_spec.rb +++ b/spec/views/crops/_grown_for.html.haml_spec.rb @@ -5,7 +5,7 @@ describe "crops/_grown_for" do let(:plant_path) { FactoryBot.create(:plant_part) } let!(:harvest) do FactoryBot.create(:harvest, - crop: crop, + crop: crop, plant_part: plant_path) end diff --git a/spec/views/forums/edit.html.haml_spec.rb b/spec/views/forums/edit.html.haml_spec.rb index 44151170a..77f5cff31 100644 --- a/spec/views/forums/edit.html.haml_spec.rb +++ b/spec/views/forums/edit.html.haml_spec.rb @@ -3,9 +3,9 @@ require 'rails_helper' describe "forums/edit" do before(:each) do @forum = assign(:forum, stub_model(Forum, - name: "MyString", + name: "MyString", description: "MyText", - owner_id: 1)) + owner_id: 1)) end it "renders the edit forum form" do diff --git a/spec/views/harvests/index.html.haml_spec.rb b/spec/views/harvests/index.html.haml_spec.rb index fe205cda6..b5ebcfb67 100644 --- a/spec/views/harvests/index.html.haml_spec.rb +++ b/spec/views/harvests/index.html.haml_spec.rb @@ -13,12 +13,12 @@ describe "harvests/index" do harvests = WillPaginate::Collection.create(page, per_page, total_entries) do |pager| pager.replace([ FactoryBot.create(:harvest, - crop: @tomato, + crop: @tomato, owner: @member), FactoryBot.create(:harvest, - crop: @maize, + crop: @maize, plant_part: @pp, - owner: @member) + owner: @member) ]) end assign(:harvests, harvests) diff --git a/spec/views/harvests/index.rss.haml_spec.rb b/spec/views/harvests/index.rss.haml_spec.rb index aea1f7bc5..b0898cf78 100644 --- a/spec/views/harvests/index.rss.haml_spec.rb +++ b/spec/views/harvests/index.rss.haml_spec.rb @@ -13,13 +13,13 @@ describe 'harvests/index.rss.haml' do harvests = WillPaginate::Collection.create(page, per_page, total_entries) do |pager| pager.replace([ FactoryBot.create(:harvest, - crop: @tomato, + crop: @tomato, owner: @member), FactoryBot.create(:harvest, - crop: @maize, + crop: @maize, plant_part: @pp, - owner: @member, - quantity: 2) + owner: @member, + quantity: 2) ]) end assign(:harvests, harvests) diff --git a/spec/views/notifications/index.html.haml_spec.rb b/spec/views/notifications/index.html.haml_spec.rb index 2c8195069..0bb4257fa 100644 --- a/spec/views/notifications/index.html.haml_spec.rb +++ b/spec/views/notifications/index.html.haml_spec.rb @@ -8,7 +8,7 @@ describe "notifications/index" do context "ordinary notifications" do before(:each) do - @notification = FactoryBot.create(:notification, sender: @member, + @notification = FactoryBot.create(:notification, sender: @member, recipient: @member) assign(:notifications, Kaminari.paginate_array([@notification, @notification]).page(1)) render diff --git a/spec/views/photos/edit.html.haml_spec.rb b/spec/views/photos/edit.html.haml_spec.rb index a52b51a79..d83a1a911 100644 --- a/spec/views/photos/edit.html.haml_spec.rb +++ b/spec/views/photos/edit.html.haml_spec.rb @@ -3,9 +3,9 @@ require 'rails_helper' describe "photos/edit" do before(:each) do @photo = assign(:photo, stub_model(Photo, - owner_id: 1, + owner_id: 1, flickr_photo_id: 1, - thumbnail_url: "MyString", - fullsize_url: "MyString")) + thumbnail_url: "MyString", + fullsize_url: "MyString")) end end diff --git a/spec/views/plantings/_form.html.haml_spec.rb b/spec/views/plantings/_form.html.haml_spec.rb index 6371311ae..8da8f1bfe 100644 --- a/spec/views/plantings/_form.html.haml_spec.rb +++ b/spec/views/plantings/_form.html.haml_spec.rb @@ -9,9 +9,9 @@ describe "plantings/_form" do @crop = @lowercase # needed to render the form @planting = FactoryBot.create(:planting, - garden: @garden, - crop: @crop, - owner: @member, + garden: @garden, + crop: @crop, + owner: @member, planted_at: Date.new(2013, 3, 1)) sign_in @member diff --git a/spec/views/plantings/edit.html.haml_spec.rb b/spec/views/plantings/edit.html.haml_spec.rb index b83af0028..0afa1e829 100644 --- a/spec/views/plantings/edit.html.haml_spec.rb +++ b/spec/views/plantings/edit.html.haml_spec.rb @@ -4,7 +4,7 @@ describe "plantings/edit" do before(:each) do @member = FactoryBot.create(:member, login_name: 'right', - email: 'right@example.com') + email: 'right@example.com') # creating two crops to make sure that the correct one is selected # in the form. diff --git a/spec/views/plantings/index.html.haml_spec.rb b/spec/views/plantings/index.html.haml_spec.rb index a3a713100..3df5b20ff 100644 --- a/spec/views/plantings/index.html.haml_spec.rb +++ b/spec/views/plantings/index.html.haml_spec.rb @@ -15,21 +15,21 @@ describe "plantings/index" do pager.replace([ FactoryBot.create(:planting, garden: garden, - crop: tomato, - owner: member), + crop: tomato, + owner: member), FactoryBot.create(:planting, - garden: garden, - crop: maize, - owner: garden.owner, + garden: garden, + crop: maize, + owner: garden.owner, description: '', - planted_at: Time.zone.local(2013, 1, 13)), + planted_at: Time.zone.local(2013, 1, 13)), FactoryBot.create(:planting, - garden: garden, - owner: garden.owner, - crop: tomato, - planted_at: Time.zone.local(2013, 1, 13), + garden: garden, + owner: garden.owner, + crop: tomato, + planted_at: Time.zone.local(2013, 1, 13), finished_at: Time.zone.local(2013, 1, 20), - finished: true) + finished: true) ]) end assign(:plantings, plantings) diff --git a/spec/views/plantings/new.html.haml_spec.rb b/spec/views/plantings/new.html.haml_spec.rb index 6667a05ee..6b6b11f57 100644 --- a/spec/views/plantings/new.html.haml_spec.rb +++ b/spec/views/plantings/new.html.haml_spec.rb @@ -13,8 +13,8 @@ describe "plantings/new" do assign(:planting, FactoryBot.create(:planting, garden: @garden_a, - crop: @crop2, - owner: @member)) + crop: @crop2, + owner: @member)) end context "logged in" do diff --git a/spec/views/posts/edit.html.haml_spec.rb b/spec/views/posts/edit.html.haml_spec.rb index 48d64a267..8ec056aff 100644 --- a/spec/views/posts/edit.html.haml_spec.rb +++ b/spec/views/posts/edit.html.haml_spec.rb @@ -32,7 +32,7 @@ describe "posts/edit" do before(:each) do @forum = assign(:forum, FactoryBot.create(:forum)) assign(:post, FactoryBot.create(:post, - forum: @forum, + forum: @forum, author: @author)) render end diff --git a/spec/views/roles/edit.html.haml_spec.rb b/spec/views/roles/edit.html.haml_spec.rb index a86f67ceb..01def5033 100644 --- a/spec/views/roles/edit.html.haml_spec.rb +++ b/spec/views/roles/edit.html.haml_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe "roles/edit" do before(:each) do @role = assign(:role, stub_model(Role, - name: "MyString", + name: "MyString", description: "MyText")) end diff --git a/spec/views/roles/index.html.haml_spec.rb b/spec/views/roles/index.html.haml_spec.rb index e4b28e9ba..8338f3cd9 100644 --- a/spec/views/roles/index.html.haml_spec.rb +++ b/spec/views/roles/index.html.haml_spec.rb @@ -5,10 +5,10 @@ describe "roles/index" do controller.stub(:current_user) { nil } assign(:roles, [ stub_model(Role, - name: "Name", + name: "Name", description: "MyText"), stub_model(Role, - name: "Name", + name: "Name", description: "MyText") ]) end diff --git a/spec/views/roles/new.html.haml_spec.rb b/spec/views/roles/new.html.haml_spec.rb index 1cdce8c41..eab80fa36 100644 --- a/spec/views/roles/new.html.haml_spec.rb +++ b/spec/views/roles/new.html.haml_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe "roles/new" do before(:each) do assign(:role, stub_model(Role, - name: "MyString", + name: "MyString", description: "MyText").as_new_record) end diff --git a/spec/views/roles/show.html.haml_spec.rb b/spec/views/roles/show.html.haml_spec.rb index 56f1cc4fb..f6d0b10b3 100644 --- a/spec/views/roles/show.html.haml_spec.rb +++ b/spec/views/roles/show.html.haml_spec.rb @@ -3,7 +3,7 @@ require 'rails_helper' describe "roles/show" do before(:each) do @role = assign(:role, stub_model(Role, - name: "Name", + name: "Name", description: "MyText")) end From 468dded162576fbe0fc1e1fd73e2f3886f2cc9f5 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:32:59 +1300 Subject: [PATCH 225/267] Remove controller actions for method that don't exist --- app/controllers/alternate_names_controller.rb | 2 +- app/controllers/members_controller.rb | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/alternate_names_controller.rb b/app/controllers/alternate_names_controller.rb index 0f1471a8c..3466f72a9 100644 --- a/app/controllers/alternate_names_controller.rb +++ b/app/controllers/alternate_names_controller.rb @@ -1,5 +1,5 @@ class AlternateNamesController < ApplicationController - before_action :authenticate_member!, except: %i(index show) + before_action :authenticate_member!, except: %i(index) load_and_authorize_resource respond_to :html, :json responders :flash diff --git a/app/controllers/members_controller.rb b/app/controllers/members_controller.rb index 9576d6750..5ff82ab9f 100644 --- a/app/controllers/members_controller.rb +++ b/app/controllers/members_controller.rb @@ -2,7 +2,6 @@ class MembersController < ApplicationController load_and_authorize_resource except: %i(finish_signup unsubscribe view_follows view_followers show) skip_authorize_resource only: %i(nearby unsubscribe finish_signup) respond_to :html, :json, :rss - after_action :expire_homepage, only: :create def index @sort = params[:sort] From 98e492ad11d3e7627c9b868993aaa64071882730 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:33:10 +1300 Subject: [PATCH 226/267] DRY --- app/controllers/follows_controller.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/follows_controller.rb b/app/controllers/follows_controller.rb index b97eb9e2b..04853bb20 100644 --- a/app/controllers/follows_controller.rb +++ b/app/controllers/follows_controller.rb @@ -9,11 +9,10 @@ class FollowsController < ApplicationController if @follow.save flash[:notice] = "Followed #{@follow.followed.login_name}" - redirect_back fallback_location: root_path else flash[:error] = "Already following or error while following." - redirect_back fallback_location: root_path end + redirect_back fallback_location: root_path end # DELETE /follows/1 From 0083d1279afa6b53b73ba203817eb0d88d7edcfe Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:33:26 +1300 Subject: [PATCH 227/267] Marked htmlsafe as # rubocob:ignore Rails/OutputSafety --- app/helpers/application_helper.rb | 2 +- app/helpers/auto_suggest_helper.rb | 2 +- app/helpers/gardens_helper.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 9e65fc303..7ea7e26c2 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -29,7 +29,7 @@ module ApplicationHelper def required_field_help_text asterisk = content_tag :span, '*', class: ['red'] text = content_tag :em, 'denotes a required field' - content_tag :div, asterisk + ' '.html_safe + text, class: ['margin-bottom'] + content_tag :div, asterisk + ' '.html_safe + text, class: ['margin-bottom'] # rubocob:ignore Rails/OutputSafety end # diff --git a/app/helpers/auto_suggest_helper.rb b/app/helpers/auto_suggest_helper.rb index caa0cd7ff..cd410d86c 100644 --- a/app/helpers/auto_suggest_helper.rb +++ b/app/helpers/auto_suggest_helper.rb @@ -20,6 +20,6 @@ module AutoSuggestHelper - ).html_safe + ).html_safe # rubocob:ignore Rails/OutputSafety end end diff --git a/app/helpers/gardens_helper.rb b/app/helpers/gardens_helper.rb index a72505558..c1fdacb23 100644 --- a/app/helpers/gardens_helper.rb +++ b/app/helpers/gardens_helper.rb @@ -29,7 +29,7 @@ module GardensHelper output += ", planted on #{planting.planted_at}" end output += '' - output.html_safe + output.html_safe # rubocob:ignore Rails/OutputSafety end end end From b8fae99bde8a7482626abbea6c62c4887ceb762f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:34:24 +1300 Subject: [PATCH 228/267] Times with zone, in factories --- spec/factories/member.rb | 2 +- spec/factories/post.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/factories/member.rb b/spec/factories/member.rb index fcd72c05e..21eaf99f5 100644 --- a/spec/factories/member.rb +++ b/spec/factories/member.rb @@ -4,7 +4,7 @@ FactoryBot.define do password { 'password1' } email { Faker::Internet.unique.email } tos_agreement { true } - confirmed_at { Time.now } + confirmed_at { Time.zone.now } show_email { false } bio { 'I love seeds' } diff --git a/spec/factories/post.rb b/spec/factories/post.rb index f88a123be..8284ed393 100644 --- a/spec/factories/post.rb +++ b/spec/factories/post.rb @@ -4,7 +4,7 @@ FactoryBot.define do body { "This is some text." } author - created_at { Time.now } + created_at { Time.zone.now } # Markdown is allowed in posts factory :markdown_post do From b1d2c46cff8440f615efacd6bfd72e87be948334 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:34:31 +1300 Subject: [PATCH 229/267] Whitespace fixup --- app/helpers/auto_suggest_helper.rb | 2 +- app/helpers/gardens_helper.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/helpers/auto_suggest_helper.rb b/app/helpers/auto_suggest_helper.rb index cd410d86c..83ff0fe08 100644 --- a/app/helpers/auto_suggest_helper.rb +++ b/app/helpers/auto_suggest_helper.rb @@ -20,6 +20,6 @@ module AutoSuggestHelper - ).html_safe # rubocob:ignore Rails/OutputSafety + ).html_safe # rubocob:ignore Rails/OutputSafety end end diff --git a/app/helpers/gardens_helper.rb b/app/helpers/gardens_helper.rb index c1fdacb23..229d2bb84 100644 --- a/app/helpers/gardens_helper.rb +++ b/app/helpers/gardens_helper.rb @@ -29,7 +29,7 @@ module GardensHelper output += ", planted on #{planting.planted_at}" end output += '' - output.html_safe # rubocob:ignore Rails/OutputSafety + output.html_safe # rubocob:ignore Rails/OutputSafety end end end From 93e1c5e5fc42c78f54241c5f6e3ddc24fe238ebb Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:38:37 +1300 Subject: [PATCH 230/267] Disabled # rubocop:disable Rails/OutputSafety --- app/helpers/application_helper.rb | 4 +++- app/helpers/auto_suggest_helper.rb | 4 +++- app/helpers/gardens_helper.rb | 4 +++- config.rb | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7ea7e26c2..f9d821fc6 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -27,9 +27,11 @@ module ApplicationHelper end def required_field_help_text + # rubocop:disable Rails/OutputSafety asterisk = content_tag :span, '*', class: ['red'] text = content_tag :em, 'denotes a required field' - content_tag :div, asterisk + ' '.html_safe + text, class: ['margin-bottom'] # rubocob:ignore Rails/OutputSafety + content_tag :div, asterisk + ' '.html_safe + text, class: ['margin-bottom'] + # rubocop:enable Rails/OutputSafety end # diff --git a/app/helpers/auto_suggest_helper.rb b/app/helpers/auto_suggest_helper.rb index 83ff0fe08..efa2e9ab6 100644 --- a/app/helpers/auto_suggest_helper.rb +++ b/app/helpers/auto_suggest_helper.rb @@ -1,4 +1,5 @@ module AutoSuggestHelper + # rubocop:disable Rails/OutputSafety def auto_suggest(resource, source, options = {}) if options[:default] && !options[:default].new_record? default = options[:default] @@ -20,6 +21,7 @@ module AutoSuggestHelper - ).html_safe # rubocob:ignore Rails/OutputSafety + ).html_safe end + # rubocop:enable Rails/OutputSafety end diff --git a/app/helpers/gardens_helper.rb b/app/helpers/gardens_helper.rb index 229d2bb84..fd406431e 100644 --- a/app/helpers/gardens_helper.rb +++ b/app/helpers/gardens_helper.rb @@ -21,6 +21,7 @@ module GardensHelper if plantings.blank? "None" else + # rubocop:disable Rails/OutputSafety output = '

    ' plantings.each do |planting| output += "
  • " @@ -29,7 +30,8 @@ module GardensHelper output += ", planted on #{planting.planted_at}
  • " end output += '
' - output.html_safe # rubocob:ignore Rails/OutputSafety + output.html_safe + # rubocop:enable Rails/OutputSafety end end end diff --git a/config.rb b/config.rb index f816551c1..acd8ec0eb 100644 --- a/config.rb +++ b/config.rb @@ -21,3 +21,4 @@ images_dir = "app/assets/images" preferred_syntax = :sass # and then run: # sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass +# rubocop:enable Lint/UselessAssignment From 3f5c63eb04c527fb2ad3050cb379d544cc230922 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:39:06 +1300 Subject: [PATCH 231/267] URI.escape -> CGI.escape --- app/helpers/crops_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/crops_helper.rb b/app/helpers/crops_helper.rb index b99d687aa..86b83909f 100644 --- a/app/helpers/crops_helper.rb +++ b/app/helpers/crops_helper.rb @@ -18,6 +18,6 @@ module CropsHelper end def crop_ebay_seeds_url(crop) - "http://rover.ebay.com/rover/1/705-53470-19255-0/1?icep_ff3=9&pub=5575213277&toolid=10001&campid=5337940151&customid=&icep_uq=#{URI.escape crop.name}&icep_sellerId=&icep_ex_kw=&icep_sortBy=12&icep_catId=181003&icep_minPrice=&icep_maxPrice=&ipn=psmain&icep_vectorid=229515&kwid=902099&mtid=824&kw=lg" # rubocop:disable Metrics/LineLength + "http://rover.ebay.com/rover/1/705-53470-19255-0/1?icep_ff3=9&pub=5575213277&toolid=10001&campid=5337940151&customid=&icep_uq=#{CGI.escape crop.name}&icep_sellerId=&icep_ex_kw=&icep_sortBy=12&icep_catId=181003&icep_minPrice=&icep_maxPrice=&ipn=psmain&icep_vectorid=229515&kwid=902099&mtid=824&kw=lg" # rubocop:disable Metrics/LineLength end end From 2faa2fd6f0b71fe971a7f14a270b710c050a2a73 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:42:51 +1300 Subject: [PATCH 232/267] Content for other formats on photos#show --- app/controllers/photos_controller.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 5a9f0129b..b7f9e16b1 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -5,7 +5,9 @@ class PhotosController < ApplicationController respond_to :html, :json responders :flash - def show; end + def show + respond_with(@photo) + end def index if params[:crop_id] From 60f72652da36d88c2229278c601d6fdd3fa56e92 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 15:53:52 +1300 Subject: [PATCH 233/267] URI.escape -> CGI.escape --- app/views/crops/show.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml index 7700501fa..940cc814e 100644 --- a/app/views/crops/show.html.haml +++ b/app/views/crops/show.html.haml @@ -112,16 +112,16 @@ %ul %li= link_to 'Wikipedia (English)', @crop.en_wikipedia_url, target: "_blank", rel: "noopener noreferrer" %li - = link_to "OpenFarm - Growing guide", "https://openfarm.cc/en/crops/#{URI.escape @crop.name}", + = link_to "OpenFarm - Growing guide", "https://openfarm.cc/en/crops/#{CGI.escape @crop.name}", target: "_blank", rel: "noopener noreferrer" %li - = link_to "Gardenate - Planting reminders", "http://www.gardenate.com/plant/#{URI.escape @crop.name}", + = link_to "Gardenate - Planting reminders", "http://www.gardenate.com/plant/#{CGI.escape @crop.name}", target: "_blank", rel: "noopener noreferrer" - if current_member && current_member.location %li = link_to "Google", - 'http://www.google.com/search?q=' + URI.escape(['Growing', + 'http://www.google.com/search?q=' + CGI.escape(['Growing', @crop.name, current_member.location].join(' ')), target: "_blank", From c0f8c2397641b08d1ef33309115be9ed3fca6b21 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 16:00:45 +1300 Subject: [PATCH 234/267] Downgrade geocoder --- Gemfile | 2 +- Gemfile.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile b/Gemfile index 310b741bf..77af33e6a 100644 --- a/Gemfile +++ b/Gemfile @@ -67,7 +67,7 @@ gem 'friendly_id' gem 'gravatar-ultimate' # For geolocation -gem 'geocoder' +gem 'geocoder', '1.4.9' # TODO: Fails on version 1.5.0. Needs investigation # For easy calendar selection gem 'bootstrap-datepicker-rails' diff --git a/Gemfile.lock b/Gemfile.lock index 062eadd71..4fb2d4129 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -185,7 +185,7 @@ GEM sassc (>= 1.11) friendly_id (5.2.4) activerecord (>= 4.0.0) - geocoder (1.5.0) + geocoder (1.4.9) gibbon (1.2.1) httparty multi_json (>= 1.9.0) @@ -554,7 +554,7 @@ DEPENDENCIES flickraw font-awesome-sass friendly_id - geocoder + geocoder (= 1.4.9) gibbon (~> 1.2.0) gravatar-ultimate haml From ac660e986c36862b78cef850dddc0ad417e0c60b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 16:14:00 +1300 Subject: [PATCH 235/267] Wrap all action bar button groups in a div So we can find them in specs --- app/views/crops/_actions.html.haml | 13 +++++++------ app/views/harvests/_actions.html.haml | 13 +++++++------ app/views/photos/_actions.html.haml | 13 +++++++------ app/views/seeds/_actions.html.haml | 24 ++++++++++++------------ spec/features/photos/new_photo_spec.rb | 4 ++-- 5 files changed, 35 insertions(+), 32 deletions(-) diff --git a/app/views/crops/_actions.html.haml b/app/views/crops/_actions.html.haml index 26f083d7b..e15979f61 100644 --- a/app/views/crops/_actions.html.haml +++ b/app/views/crops/_actions.html.haml @@ -1,8 +1,9 @@ -- if can? :create, Planting - = link_to "Plant this", new_planting_path(crop_id: crop.id), class: 'btn btn-default' +.crop-actions + - if can? :create, Planting + = link_to "Plant this", new_planting_path(crop_id: crop.id), class: 'btn btn-default' -- if can? :create, Harvest - = link_to "Harvest this", new_harvest_path(crop_id: crop.id), class: 'btn btn-default' + - if can? :create, Harvest + = link_to "Harvest this", new_harvest_path(crop_id: crop.id), class: 'btn btn-default' -- if can? :create, Seed - = link_to 'Add seeds to stash', new_seed_path(params: { crop_id: crop.id }), class: 'btn btn-default' + - if can? :create, Seed + = link_to 'Add seeds to stash', new_seed_path(params: { crop_id: crop.id }), class: 'btn btn-default' diff --git a/app/views/harvests/_actions.html.haml b/app/views/harvests/_actions.html.haml index 5a2f1febc..2ebfbc8f9 100644 --- a/app/views/harvests/_actions.html.haml +++ b/app/views/harvests/_actions.html.haml @@ -1,6 +1,7 @@ -- if can?(:edit, harvest) || can?(:destroy, harvest) - .btn-group.harvest-actions - - if can? :edit, harvest - = render 'shared/buttons/edit', path: edit_harvest_path(harvest) - - if can? :destroy, harvest - .pull-right= render 'shared/buttons/delete', path: harvest_path(harvest) +.harvest-actions + - if can?(:edit, harvest) || can?(:destroy, harvest) + .btn-group + - if can? :edit, harvest + = render 'shared/buttons/edit', path: edit_harvest_path(harvest) + - if can? :destroy, harvest + .pull-right= render 'shared/buttons/delete', path: harvest_path(harvest) diff --git a/app/views/photos/_actions.html.haml b/app/views/photos/_actions.html.haml index 878d985ef..06fc37f0e 100644 --- a/app/views/photos/_actions.html.haml +++ b/app/views/photos/_actions.html.haml @@ -1,6 +1,7 @@ -- if can?(:edit, @photo) && can?(:destroy, @photo) - %p.photo-actions - - if can?(:edit, @photo) - = render 'shared/buttons/edit', path: edit_photo_path(@photo) - - if can?(:destroy, @photo) - = render 'shared/buttons/delete', path: photo_path(@photo) +.photo-actions + - if can?(:edit, @photo) && can?(:destroy, @photo) + %p + - if can?(:edit, @photo) + = render 'shared/buttons/edit', path: edit_photo_path(@photo) + - if can?(:destroy, @photo) + = render 'shared/buttons/delete', path: photo_path(@photo) diff --git a/app/views/seeds/_actions.html.haml b/app/views/seeds/_actions.html.haml index 803b63b2d..6e1cef334 100644 --- a/app/views/seeds/_actions.html.haml +++ b/app/views/seeds/_actions.html.haml @@ -1,15 +1,15 @@ +.seed-actions + - if can? :edit, seed + .btn-group + = render 'shared/buttons/edit', path: edit_seed_path(seed) + = render 'shared/buttons/add_photo', path: new_photo_path(id: seed.id, type: 'seed') -- if can? :edit, seed - .btn-group - = render 'shared/buttons/edit', path: edit_seed_path(seed) - = render 'shared/buttons/add_photo', path: new_photo_path(id: seed.id, type: 'seed') + - if can?(:create, Planting) && seed.active? + = link_to new_planting_path(seed_id: seed), class: 'btn btn-default btn-xs' do + %span.glyphicon.glyphicon-grain{ title: "Plant seeds" } + Plant seeds - - if can?(:create, Planting) && seed.active? - = link_to new_planting_path(seed_id: seed), class: 'btn btn-default btn-xs' do - %span.glyphicon.glyphicon-grain{ title: "Plant seeds" } - Plant seeds + = render 'shared/buttons/finish_seeds', seed: seed - = render 'shared/buttons/finish_seeds', seed: seed - -- if can? :destroy, seed - = render 'shared/buttons/delete', path: seed + - if can? :destroy, seed + = render 'shared/buttons/delete', path: seed diff --git a/spec/features/photos/new_photo_spec.rb b/spec/features/photos/new_photo_spec.rb index ee2a50691..0bf696f06 100644 --- a/spec/features/photos/new_photo_spec.rb +++ b/spec/features/photos/new_photo_spec.rb @@ -40,12 +40,12 @@ feature "new photo page" do end end - pending "viewing a seed" do + describe "viewing a seed" do let(:seed) { FactoryBot.create :seed, owner: member } scenario "add photo" do visit seed_path(seed) - click_link "Add photo" + first('.seed-actions').click_link('Add photo') expect(page).to have_text seed.to_s end end From b70dee50412ff4930cb918256f1a54310b11aa00 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 19:37:28 +1300 Subject: [PATCH 236/267] Update rubocop todo --- .rubocop_todo.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index eb05ad7ff..784aaf01f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --no-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 0.55.0. +# using RuboCop version 0.61.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -30,6 +30,8 @@ Rails/CreateTableWithTimestamps: - 'db/migrate/20161201154922_add_photos_seeds_table.rb' - 'db/migrate/20171022032108_all_the_predictions.rb' +# Configuration parameters: EnforcedStyle. +# SupportedStyles: slashes, arguments Rails/FilePath: Exclude: - 'spec/rails_helper.rb' @@ -40,7 +42,7 @@ Rails/HasManyOrHasOneDependent: Exclude: - 'app/models/member.rb' -# Configuration parameters: Blacklist. +# Configuration parameters: Blacklist, Whitelist. # Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters Rails/SkipsModelValidations: Exclude: @@ -68,7 +70,7 @@ Style/MixinUsage: - 'spec/rails_helper.rb' # Cop supports --auto-correct. -# Configuration parameters: AutoCorrect, EnforcedStyle. +# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods. # SupportedStyles: predicate, comparison Style/NumericPredicate: Exclude: From f2fc6b2a61ed2dcd09d07ff1c9dc32a11e732425 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 30 Dec 2018 19:41:08 +1300 Subject: [PATCH 237/267] Reduce max class complexity --- .rubocop.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.rubocop.yml b/.rubocop.yml index 7c61c6fd1..43e24f9c4 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -63,8 +63,9 @@ Metrics/MethodLength: Max: 34 Metrics/AbcSize: Max: 30 +# Configuration parameters: CountComments. Metrics/ClassLength: - Max: 172 + Max: 171 Metrics/CyclomaticComplexity: Max: 7 Metrics/PerceivedComplexity: From d6c9132049d1c19c6cf79ade19703886fe6ccb07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 31 Dec 2018 07:26:24 +0000 Subject: [PATCH 238/267] Bump friendly_id from 5.2.4 to 5.2.5 Bumps [friendly_id](https://github.com/norman/friendly_id) from 5.2.4 to 5.2.5. - [Release notes](https://github.com/norman/friendly_id/releases) - [Changelog](https://github.com/norman/friendly_id/blob/master/Changelog.md) - [Commits](https://github.com/norman/friendly_id/compare/5.2.4...5.2.5) Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3cfb31ca2..4bf828c6f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -122,7 +122,7 @@ GEM rails (>= 4.0.0, < 5.1) rails-i18n (>= 4.0.0) sass-rails (>= 4.0.3) - concurrent-ruby (1.1.3) + concurrent-ruby (1.1.4) connection_pool (2.2.2) coveralls (0.8.19) json (>= 1.8, < 3) @@ -179,7 +179,7 @@ GEM font-awesome-sass (5.5.0.1) sassc (>= 1.11) formatador (0.2.5) - friendly_id (5.2.4) + friendly_id (5.2.5) activerecord (>= 4.0.0) geocoder (1.4.9) gibbon (1.2.1) From a6a75050bb13a75649862714b60c26356dce7097 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 1 Jan 2019 09:55:29 +1300 Subject: [PATCH 239/267] Make mail sender host configurable --- config/environments/production.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/environments/production.rb b/config/environments/production.rb index 9d377db43..06fa8e690 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -80,7 +80,7 @@ Rails.application.configure do config.active_record.dump_schema_after_migration = false # Growstuff configuration - config.action_mailer.default_url_options = { host: 'growstuff.org' } + config.action_mailer.default_url_options = { host: ENV['MAIL_SENDER_HOST'] } ActionMailer::Base.smtp_settings = { port: ENV['SPARKPOST_SMTP_PORT'], From a43c2354233053d130d539050450ea0a6fce9505 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 1 Jan 2019 10:28:19 +1300 Subject: [PATCH 240/267] Upgrade to Rails 5.2 --- Gemfile | 4 +- Gemfile.lock | 139 ++++++++---------- bin/setup | 3 +- bin/update | 6 +- bin/yarn | 6 +- config/boot.rb | 1 + config/cable.yml | 2 +- config/environments/development.rb | 9 +- config/environments/production.rb | 9 ++ config/environments/test.rb | 6 +- .../initializers/content_security_policy.rb | 25 ++++ config/initializers/cookies_serializer.rb | 2 +- .../new_framework_defaults_5_2.rb | 38 +++++ config/locales/en.yml | 31 ++++ config/puma.rb | 24 +-- config/storage.yml | 34 +++++ 16 files changed, 226 insertions(+), 113 deletions(-) create mode 100644 config/initializers/content_security_policy.rb create mode 100644 config/initializers/new_framework_defaults_5_2.rb create mode 100644 config/storage.yml diff --git a/Gemfile b/Gemfile index 77af33e6a..5759564de 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ source 'https://rubygems.org' ruby '2.4.1' -gem 'rails', '5.1.4' +gem 'rails', '5.2.2' gem 'bundler', '>=1.1.5' @@ -43,7 +43,7 @@ gem 'pg', '< 1.0.0' # Upstream bug, see https://github.com/Growst gem 'ruby-units' # for unit conversion gem 'unicorn' # http server -gem 'comfortable_mexican_sofa', git: 'https://github.com/comfy/comfortable-mexican-sofa', branch: 'rails5.1' +gem "comfortable_mexican_sofa", "~> 2.0.0" gem 'bootstrap-kaminari-views' # bootstrap views for kaminari gem 'kaminari' # pagination diff --git a/Gemfile.lock b/Gemfile.lock index b7d1d6d19..0499cc5ec 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,47 +1,26 @@ -GIT - remote: https://github.com/comfy/comfortable-mexican-sofa - revision: dca0c7c3669872a00722bb57d3ff0f4995dc4f09 - branch: rails5.1 - specs: - comfortable_mexican_sofa (1.12.10) - active_link_to (>= 1.0.0) - bootstrap-sass (>= 3.2.0) - bootstrap_form (>= 2.2.0) - codemirror-rails (>= 3.0.0) - coffee-rails (>= 3.1.0) - haml-rails (>= 0.3.0) - jquery-rails (>= 3.0.0) - jquery-ui-rails (>= 5.0.0) - kramdown (>= 1.0.0) - paperclip (>= 4.0.0) - plupload-rails (>= 1.2.1) - rails (>= 5.0.0, < 5.2) - rails-i18n (>= 4.0.0) - sass-rails (>= 4.0.3) - GEM remote: https://rubygems.org/ remote: https://rails-assets.org/ specs: - actioncable (5.1.4) - actionpack (= 5.1.4) + actioncable (5.2.2) + actionpack (= 5.2.2) nio4r (~> 2.0) - websocket-driver (~> 0.6.1) - actionmailer (5.1.4) - actionpack (= 5.1.4) - actionview (= 5.1.4) - activejob (= 5.1.4) + websocket-driver (>= 0.6.1) + actionmailer (5.2.2) + actionpack (= 5.2.2) + actionview (= 5.2.2) + activejob (= 5.2.2) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.1.4) - actionview (= 5.1.4) - activesupport (= 5.1.4) + actionpack (5.2.2) + actionview (= 5.2.2) + activesupport (= 5.2.2) rack (~> 2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.1.4) - activesupport (= 5.1.4) + actionview (5.2.2) + activesupport (= 5.2.2) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) @@ -54,23 +33,27 @@ GEM active_utils (3.3.16) activesupport (>= 4.2) i18n - activejob (5.1.4) - activesupport (= 5.1.4) + activejob (5.2.2) + activesupport (= 5.2.2) globalid (>= 0.3.6) - activemodel (5.1.4) - activesupport (= 5.1.4) - activerecord (5.1.4) - activemodel (= 5.1.4) - activesupport (= 5.1.4) - arel (~> 8.0) - activesupport (5.1.4) + activemodel (5.2.2) + activesupport (= 5.2.2) + activerecord (5.2.2) + activemodel (= 5.2.2) + activesupport (= 5.2.2) + arel (>= 9.0) + activestorage (5.2.2) + actionpack (= 5.2.2) + activerecord (= 5.2.2) + marcel (~> 0.3.1) + activesupport (5.2.2) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (~> 0.7) + i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) - arel (8.0.0) + arel (9.0.0) ast (2.4.0) autoprefixer-rails (9.4.3) execjs @@ -91,8 +74,6 @@ GEM bootstrap-sass (3.4.0) autoprefixer-rails (>= 5.2.1) sassc (>= 2.0.0) - bootstrap_form (4.0.0) - rails (>= 5.0) builder (3.2.3) bullet (5.9.0) activesupport (>= 3.0.0) @@ -116,12 +97,9 @@ GEM chartkick (3.0.1) childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) - climate_control (0.2.0) cliver (0.3.2) codeclimate-test-reporter (1.0.9) simplecov (<= 0.13) - codemirror-rails (5.16.0) - railties (>= 3.0, < 6.0) coderay (1.1.2) coffee-rails (4.2.2) coffee-script (>= 2.2.0) @@ -130,6 +108,19 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) + comfortable_mexican_sofa (2.0.17) + active_link_to (>= 1.0.0) + comfy_bootstrap_form (>= 4.0.0) + haml-rails (>= 1.0.0) + jquery-rails (>= 4.3.1) + kramdown (>= 1.0.0) + mimemagic (>= 0.3.2) + mini_magick (>= 4.8.0) + rails (>= 5.2.0) + rails-i18n (>= 5.0.0) + sass-rails (>= 5.0.0) + comfy_bootstrap_form (4.0.6) + rails (>= 5.0.0) concurrent-ruby (1.1.4) connection_pool (2.2.2) coveralls (0.8.19) @@ -230,7 +221,7 @@ GEM httparty (0.16.3) mime-types (~> 3.0) multi_xml (>= 0.5.2) - i18n (0.9.5) + i18n (1.3.0) concurrent-ruby (~> 1.0) i18n-tasks (0.9.28) activesupport (>= 4.0.2) @@ -287,12 +278,15 @@ GEM nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) + marcel (0.3.3) + mimemagic (~> 0.3.2) memcachier (0.0.2) method_source (0.9.2) mime-types (3.2.2) mime-types-data (~> 3.2015) mime-types-data (3.2018.0812) mimemagic (0.3.3) + mini_magick (4.9.2) mini_mime (1.0.1) mini_portile2 (2.4.0) minitest (5.11.3) @@ -329,12 +323,6 @@ GEM omniauth-oauth (~> 1.1) rack orm_adapter (0.5.0) - paperclip (6.1.0) - activemodel (>= 4.2.0) - activesupport (>= 4.2.0) - mime-types - mimemagic (~> 0.3.0) - terrapin (~> 0.6.0) parallel (1.12.1) paranoia (2.4.1) activerecord (>= 4.0, < 5.3) @@ -344,8 +332,6 @@ GEM platform-api (2.2.0) heroics (~> 0.0.25) moneta (~> 1.0.0) - plupload-rails (1.2.1) - rails (>= 3.1) poltergeist (1.18.1) capybara (>= 2.1, < 4) cliver (~> 0.3.1) @@ -358,17 +344,18 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) - rails (5.1.4) - actioncable (= 5.1.4) - actionmailer (= 5.1.4) - actionpack (= 5.1.4) - actionview (= 5.1.4) - activejob (= 5.1.4) - activemodel (= 5.1.4) - activerecord (= 5.1.4) - activesupport (= 5.1.4) + rails (5.2.2) + actioncable (= 5.2.2) + actionmailer (= 5.2.2) + actionpack (= 5.2.2) + actionview (= 5.2.2) + activejob (= 5.2.2) + activemodel (= 5.2.2) + activerecord (= 5.2.2) + activestorage (= 5.2.2) + activesupport (= 5.2.2) bundler (>= 1.3.0) - railties (= 5.1.4) + railties (= 5.2.2) sprockets-rails (>= 2.0.0) rails-assets-leaflet (1.3.4) rails-assets-leaflet.markercluster (1.4.1) @@ -390,12 +377,12 @@ GEM rails_stdout_logging rails_serve_static_assets (0.0.5) rails_stdout_logging (0.0.5) - railties (5.1.4) - actionpack (= 5.1.4) - activesupport (= 5.1.4) + railties (5.2.2) + actionpack (= 5.2.2) + activesupport (= 5.2.2) method_source rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) + thor (>= 0.19.0, < 2.0) rainbow (3.0.0) raindrops (0.19.0) rake (12.3.2) @@ -486,8 +473,6 @@ GEM tins (~> 1.0) terminal-table (1.8.0) unicode-display_width (~> 1.1, >= 1.1.1) - terrapin (0.6.0) - climate_control (>= 0.0.3, < 1.0) thor (0.19.4) thread_safe (0.3.6) tilt (2.0.9) @@ -509,7 +494,7 @@ GEM nokogiri (>= 1.2.0) rack (>= 1.0) rack-test (>= 0.5.3) - websocket-driver (0.6.5) + websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) will_paginate (3.1.6) @@ -539,7 +524,7 @@ DEPENDENCIES chartkick codeclimate-test-reporter coffee-rails - comfortable_mexican_sofa! + comfortable_mexican_sofa (~> 2.0.0) coveralls csv_shaper dalli @@ -584,7 +569,7 @@ DEPENDENCIES poltergeist puma rack-protection (>= 2.0.1) - rails (= 5.1.4) + rails (= 5.2.2) rails-assets-leaflet.markercluster! rails-controller-testing rails_12factor diff --git a/bin/setup b/bin/setup index b2293a35a..94fd4d797 100755 --- a/bin/setup +++ b/bin/setup @@ -1,10 +1,9 @@ #!/usr/bin/env ruby -require 'pathname' require 'fileutils' include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('..', __dir__) +APP_ROOT = File.expand_path('..', __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") diff --git a/bin/update b/bin/update index 32326c74f..58bfaed51 100755 --- a/bin/update +++ b/bin/update @@ -1,10 +1,9 @@ #!/usr/bin/env ruby -require 'pathname' require 'fileutils' include FileUtils # path to your application root. -APP_ROOT = Pathname.new File.expand_path('..', __dir__) +APP_ROOT = File.expand_path('..', __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") @@ -18,6 +17,9 @@ chdir APP_ROOT do system! 'gem install bundler --conservative' system('bundle check') || system!('bundle install') + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + puts "\n== Updating database ==" system! 'bin/rails db:migrate' diff --git a/bin/yarn b/bin/yarn index 4d2c50e52..542c351ad 100755 --- a/bin/yarn +++ b/bin/yarn @@ -1,8 +1,8 @@ #!/usr/bin/env ruby -VENDOR_PATH = File.expand_path('..', __dir__) -Dir.chdir(VENDOR_PATH) do +APP_ROOT = File.expand_path('..', __dir__) +Dir.chdir(APP_ROOT) do begin - exec "yarnpkg #{ARGV.join(' ')}" + exec "yarnpkg", *ARGV rescue Errno::ENOENT warn "Yarn executable was not detected in the system." warn "Download Yarn at https://yarnpkg.com/en/docs/install" diff --git a/config/boot.rb b/config/boot.rb index 30f5120df..4423c97f2 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,3 +1,4 @@ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile. +# require 'bootsnap/setup' # Speed up boot time by caching expensive operations. diff --git a/config/cable.yml b/config/cable.yml index b6110a25b..fac21938e 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -6,5 +6,5 @@ test: production: adapter: redis - url: redis://localhost:6379/1 + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> channel_prefix: growstuff_production diff --git a/config/environments/development.rb b/config/environments/development.rb index 7b04cf96c..888bee353 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -13,12 +13,13 @@ Rails.application.configure do config.consider_all_requests_local = true # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. if Rails.root.join('tmp', 'caching-dev.txt').exist? config.action_controller.perform_caching = true config.cache_store = :memory_store config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}" + 'Cache-Control' => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = false @@ -26,6 +27,9 @@ Rails.application.configure do config.cache_store = :null_store end + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false @@ -37,6 +41,9 @@ Rails.application.configure do # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + # Debug mode disables concatenation and preprocessing of assets. # This option may cause significant delays in view rendering with a large # number of complex assets. diff --git a/config/environments/production.rb b/config/environments/production.rb index 9d377db43..1d8373560 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -105,6 +105,15 @@ Rails.application.configure do config.mapbox_access_token = 'pk.eyJ1IjoiZ3Jvd3N0dWZmIiwiYSI6IkdxMkx4alUifQ.n0igaBsw97s14zMa0lwKCA' config.active_job.queue_adapter = :sidekiq + # Use a different logger for distributed setups. + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false diff --git a/config/environments/test.rb b/config/environments/test.rb index 47fede3a8..fe03b6e1a 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -15,7 +15,7 @@ Rails.application.configure do # Configure public file server for tests with Cache-Control for performance. config.public_file_server.enabled = true config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{1.hour.seconds.to_i}" + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" } # Show full error reports and disable caching. @@ -27,6 +27,10 @@ Rails.application.configure do # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory + config.active_storage.service = :test + config.action_mailer.perform_caching = false # Tell Action Mailer not to deliver emails to the real world. diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb new file mode 100644 index 000000000..d3bcaa5ec --- /dev/null +++ b/config/initializers/content_security_policy.rb @@ -0,0 +1,25 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https + +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb index 1389e86a3..5a6a32d37 100644 --- a/config/initializers/cookies_serializer.rb +++ b/config/initializers/cookies_serializer.rb @@ -2,4 +2,4 @@ # Specify a serializer for the signed and encrypted cookie jars. # Valid options are :json, :marshal, and :hybrid. -Rails.application.config.action_dispatch.cookies_serializer = :marshal +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/initializers/new_framework_defaults_5_2.rb b/config/initializers/new_framework_defaults_5_2.rb new file mode 100644 index 000000000..c383d072b --- /dev/null +++ b/config/initializers/new_framework_defaults_5_2.rb @@ -0,0 +1,38 @@ +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.2 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +# Make Active Record use stable #cache_key alongside new #cache_version method. +# This is needed for recyclable cache keys. +# Rails.application.config.active_record.cache_versioning = true + +# Use AES-256-GCM authenticated encryption for encrypted cookies. +# Also, embed cookie expiry in signed or encrypted cookies for increased security. +# +# This option is not backwards compatible with earlier Rails versions. +# It's best enabled when your entire app is migrated and stable on 5.2. +# +# Existing cookies will be converted on read then written with the new scheme. +# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true + +# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages +# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true. +# Rails.application.config.active_support.use_authenticated_message_encryption = true + +# Add default protection from forgery to ActionController::Base instead of in +# ApplicationController. +# Rails.application.config.action_controller.default_protect_from_forgery = true + +# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and +# 'f' after migrating old data. +# Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true + +# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header. +# Rails.application.config.active_support.use_sha1_digests = true + +# Make `form_with` generate id attributes for any generated HTML tags. +# Rails.application.config.action_view.form_with_generates_ids = true diff --git a/config/locales/en.yml b/config/locales/en.yml index c494975e7..879d7c51c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,4 +1,35 @@ --- +# Files in the config/locales directory are used for internationalization +# and are automatically loaded by Rails. If you want to use locales other +# than English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t 'hello' +# +# In views, this is aliased to just `t`: +# +# <%= t('hello') %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# 'true': 'foo' +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. + en: activerecord: models: diff --git a/config/puma.rb b/config/puma.rb index 1e19380dc..a5eccf816 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -26,31 +26,9 @@ environment ENV.fetch("RAILS_ENV") { "development" } # Use the `preload_app!` method when specifying a `workers` number. # This directive tells Puma to first boot the application and load code # before forking the application. This takes advantage of Copy On Write -# process behavior so workers use less memory. If you use this option -# you need to make sure to reconnect any threads in the `on_worker_boot` -# block. +# process behavior so workers use less memory. # # preload_app! -# If you are preloading your application and using Active Record, it's -# recommended that you close any connections to the database before workers -# are forked to prevent connection leakage. -# -# before_fork do -# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) -# end - -# The code in the `on_worker_boot` will be called if you are using -# clustered mode by specifying a number of `workers`. After each worker -# process is booted, this block will be run. If you are using the `preload_app!` -# option, you will want to use this block to reconnect to any threads -# or connections that may have been created at application boot, as Ruby -# cannot share connections between processes. -# -# on_worker_boot do -# ActiveRecord::Base.establish_connection if defined?(ActiveRecord) -# end -# - # Allow puma to be restarted by `rails restart` command. plugin :tmp_restart diff --git a/config/storage.yml b/config/storage.yml new file mode 100644 index 000000000..d32f76e8f --- /dev/null +++ b/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket + +# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] From b7f876429ad18c7ed382e2aa4737875d530f44c6 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 1 Jan 2019 13:31:09 +1300 Subject: [PATCH 241/267] Upgrade to ruby 2.6.0 --- .ruby-version | 2 +- Gemfile | 2 +- Gemfile.lock | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ruby-version b/.ruby-version index 005119baa..e70b4523a 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.4.1 +2.6.0 diff --git a/Gemfile b/Gemfile index 5759564de..c0cd21aa5 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' -ruby '2.4.1' +ruby '2.6.0' gem 'rails', '5.2.2' diff --git a/Gemfile.lock b/Gemfile.lock index 0499cc5ec..ba44d8e7a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -592,7 +592,7 @@ DEPENDENCIES xmlrpc RUBY VERSION - ruby 2.4.1p111 + ruby 2.6.0p0 BUNDLED WITH - 1.16.4 + 1.17.2 From c7ad7bcc706d45fb74d39d9c7f3e33e4740bb9ea Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 1 Jan 2019 13:38:37 +1300 Subject: [PATCH 242/267] Fixed redundant begin block --- bin/yarn | 12 +++++------- .../photo_associations_controller_spec.rb | 8 +++----- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/bin/yarn b/bin/yarn index 542c351ad..b24854dce 100755 --- a/bin/yarn +++ b/bin/yarn @@ -1,11 +1,9 @@ #!/usr/bin/env ruby APP_ROOT = File.expand_path('..', __dir__) Dir.chdir(APP_ROOT) do - begin - exec "yarnpkg", *ARGV - rescue Errno::ENOENT - warn "Yarn executable was not detected in the system." - warn "Download Yarn at https://yarnpkg.com/en/docs/install" - exit 1 - end + exec "yarnpkg", *ARGV +rescue Errno::ENOENT + warn "Yarn executable was not detected in the system." + warn "Download Yarn at https://yarnpkg.com/en/docs/install" + exit 1 end diff --git a/spec/controllers/photo_associations_controller_spec.rb b/spec/controllers/photo_associations_controller_spec.rb index a7c05f029..269e90079 100644 --- a/spec/controllers/photo_associations_controller_spec.rb +++ b/spec/controllers/photo_associations_controller_spec.rb @@ -29,11 +29,9 @@ describe PhotoAssociationsController do it do expect do - begin - delete :destroy, params: valid_params - rescue StandardError - nil - end + delete :destroy, params: valid_params + rescue StandardError + nil end.not_to change(photo.harvests, :count) end From f4df42d136f2e5650608baed7aa0378fd75ab247 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 1 Jan 2019 13:42:53 +1300 Subject: [PATCH 243/267] Fixes not being able to find the 404 page file --- app/controllers/application_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 9ef6783e5..023603b33 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -20,7 +20,7 @@ class ApplicationController < ActionController::Base end def not_found - render file: 'app/views/errors/404', status: :not_found, layout: false + render file: 'app/views/errors/404.html', status: :not_found, layout: false end def after_sign_in_path_for(_resource) From a76f5d3a22d2ee47704ec7f245beb6af38aacf89 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 1 Jan 2019 13:56:08 +1300 Subject: [PATCH 244/267] More locations with production email addresses --- app/mailers/notifier.rb | 2 +- config/application.rb | 2 +- config/initializers/devise.rb | 2 +- spec/mailers/notifier_spec.rb | 20 ++++++++++---------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/mailers/notifier.rb b/app/mailers/notifier.rb index 0d4ea407e..0386450f1 100644 --- a/app/mailers/notifier.rb +++ b/app/mailers/notifier.rb @@ -1,6 +1,6 @@ class Notifier < ApplicationMailer include NotificationsHelper - default from: "Growstuff " + default from: "Growstuff <#{ENV['GROWSTUFF_EMAIL']}>" def verifier unless ENV['RAILS_SECRET_TOKEN'] diff --git a/config/application.rb b/config/application.rb index 0a00a917a..a42ae3bae 100644 --- a/config/application.rb +++ b/config/application.rb @@ -81,7 +81,7 @@ module Growstuff # Growstuff-specific configuration variables config.currency = 'AUD' - config.bot_email = "noreply@growstuff.org" + config.bot_email = ENV['GROWSTUFF_EMAIL'] config.user_agent = 'Growstuff' config.user_agent_email = "info@growstuff.org" diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index fcb4caecc..974551c93 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -5,7 +5,7 @@ Devise.setup do |config| # ==> Mailer Configuration # Configure the e-mail address which will be shown in Devise::Mailer, # note that it will be overwritten if you use your own mailer class with default "from" parameter. - config.mailer_sender = "Growstuff " + config.mailer_sender = "Growstuff <#{ENV['GROWSTUFF_EMAIL']}>" config.secret_key = ENV['RAILS_SECRET_TOKEN'] diff --git a/spec/mailers/notifier_spec.rb b/spec/mailers/notifier_spec.rb index e50682700..27677eab6 100644 --- a/spec/mailers/notifier_spec.rb +++ b/spec/mailers/notifier_spec.rb @@ -9,8 +9,8 @@ describe Notifier do mail.subject.should == notification.subject end - it 'comes from noreply@growstuff.org' do - mail.from.should == ['noreply@growstuff.org'] + it 'comes from noreply@test.growstuff.org' do + mail.from.should == ['noreply@test.growstuff.org'] end it 'sends the mail to the recipient of the notification' do @@ -26,8 +26,8 @@ describe Notifier do mail.subject.should == "What have you planted lately?" end - it 'comes from noreply@growstuff.org' do - mail.from.should == ['noreply@growstuff.org'] + it 'comes from noreply@test.growstuff.org' do + mail.from.should == ['noreply@test.growstuff.org'] end it 'sends the mail to the recipient of the notification' do @@ -52,8 +52,8 @@ describe Notifier do mail.subject.should == "#{crop.requester.login_name} has requested Ultra berry as a new crop" end - it 'comes from noreply@growstuff.org' do - mail.from.should == ['noreply@growstuff.org'] + it 'comes from noreply@test.growstuff.org' do + mail.from.should == ['noreply@test.growstuff.org'] end it 'sends the mail to the recipient of the notification' do @@ -74,8 +74,8 @@ describe Notifier do expect(mail.subject).to eq "Magic bean has been approved" end - it 'comes from noreply@growstuff.org' do - expect(mail.from).to eq ['noreply@growstuff.org'] + it 'comes from noreply@test.growstuff.org' do + expect(mail.from).to eq ['noreply@test.growstuff.org'] end it 'sends the mail to the recipient of the notification' do @@ -102,8 +102,8 @@ describe Notifier do expect(mail.subject).to eq "Fail bean has been rejected" end - it 'comes from noreply@growstuff.org' do - expect(mail.from).to eq ['noreply@growstuff.org'] + it 'comes from noreply@test.growstuff.org' do + expect(mail.from).to eq ['noreply@test.growstuff.org'] end it 'sends the mail to the recipient of the notification' do From 6df2d9272013c611ef752608da5c3846476bdce0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 1 Jan 2019 13:59:32 +1300 Subject: [PATCH 245/267] Adding from email to example application.yml --- config/application.yml.example | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config/application.yml.example b/config/application.yml.example index ba343b6d0..1ff6b5f99 100644 --- a/config/application.yml.example +++ b/config/application.yml.example @@ -75,9 +75,13 @@ GROWSTUFF_ELASTICSEARCH: "false" # To see current settings on Heroku, use "heroku config --app=whatever". ############################################################################## +### EMAil addres for notifier and mailers to use as from +GROWSTUFF_EMAIL: 'noreply@dev.growstuff.org' + test: GROWSTUFF_SITE_NAME: Growstuff (test) GROWSTUFF_CAPYBARA_DRIVER: poltergeist + GROWSTUFF_EMAIL: 'noreply@test.growstuff.org' # Note: there is no good way to deploy settings from Figaro to # Travis-CI. If you need env vars set there in order for tests to pass, @@ -86,7 +90,9 @@ test: staging: GROWSTUFF_SITE_NAME: Growstuff (staging) GROWSTUFF_ELASTICSEARCH: "true" + GROWSTUFF_EMAIL: 'noreply@staging.growstuff.org' production: GROWSTUFF_SITE_NAME: Growstuff GROWSTUFF_ELASTICSEARCH: "true" + GROWSTUFF_EMAIL: 'noreply@growstuff.org' From 1627c347e4efa5c601c60ef1c971134782647e2f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 1 Jan 2019 14:07:51 +1300 Subject: [PATCH 246/267] App.json to configure heroku --- app.json | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 app.json diff --git a/app.json b/app.json new file mode 100644 index 000000000..fc266aded --- /dev/null +++ b/app.json @@ -0,0 +1,51 @@ +{ + "name": "growstuff", + "stack": "heroku-18", + "description": "Open data project for small-scale food growers", + "scripts": { + "postdeploy": "bundle exec rails db:migrate db:seed" + }, + "env": { + "GROWSTUFF_ELASTICSEARCH": { + "required": true + }, + "GROWSTUFF_FACEBOOK_KEY": { + "required": true + }, + "GROWSTUFF_FACEBOOK_SECRET": { + "required": true + }, + "GROWSTUFF_FLICKR_KEY": { + "required": true + }, + "GROWSTUFF_FLICKR_SECRET": { + "required": true + }, + "GROWSTUFF_SITE_NAME": { + "required": true + }, + "GROWSTUFF_EMAIL": { + "required": true + }, + "MAIL_SENDER_HOST": { + "required": true + } + }, + "formation": { + "web": { + "quantity": 1 + } + }, + "addons": [ + "heroku-postgresql", + "bonsai-elasticsearch", + "memcachier", + "newrelic", + "sparkhost" + ], + "buildpacks": [ + { + "url": "heroku/ruby" + } + ] +} From 28dcc573076b767669620a3bb8cf10caa824b137 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Tue, 1 Jan 2019 14:10:04 +1300 Subject: [PATCH 247/267] Set email env on travis runs --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index cf2a27a7f..d8959f060 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ env: - STATIC_CHECKS=true global: - secure: "Z5TpM2jEX4UCvNePnk/LwltQX48U2u9BRc+Iypr1x9QW2o228QJhPIOH39a8RMUrepGnkQIq9q3ZRUn98RfrJz1yThtlNFL3NmzdQ57gKgjGwfpa0e4Dwj/ZJqV2D84tDGjvdVYLP7zzaYZxQcwk/cgNpzKf/jq97HLNP7CYuf4=" + - GROWSTUFF_EMAIL="noreply@test.growstuff.org" - GROWSTUFF_SITE_NAME="Growstuff (travis)" - RAILS_SECRET_TOKEN='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' before_install: From 0971f3b5f4f6176c27eb84d26cccd04530bfa70d Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 3 Jan 2019 12:50:19 +1300 Subject: [PATCH 248/267] Updated notification specs for Rails 5.2 --- spec/models/notification_spec.rb | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 4f04573d5..33f053bfd 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -4,56 +4,55 @@ describe Notification do let(:notification) { FactoryBot.create(:notification) } it "belongs to a post" do - notification.post.should be_an_instance_of Post + expect(notification.post).to be_an_instance_of Post end it "belongs to a recipient" do - notification.recipient.should be_an_instance_of Member + expect(notification.recipient).to be_an_instance_of Member end it "belongs to a sender" do - notification.sender.should be_an_instance_of Member + expect(notification.sender).to be_an_instance_of Member end it "has a scope for unread" do - Notification.unread.should eq [notification] + expect(Notification.unread).to eq [notification] @n2 = FactoryBot.create(:notification, read: true) - Notification.unread.should eq [notification] + expect(Notification.unread).to eq [notification] @n3 = FactoryBot.create(:notification, read: false) - Notification.unread.should include @n3 - Notification.unread.should include notification + expect(Notification.unread).to include @n3 + expect(Notification.unread).to include notification end it "counts unread" do @who = notification.recipient @n2 = FactoryBot.create(:notification, recipient: @who, read: false) - @who.notifications.unread_count.should eq 2 + expect(@who.notifications.unread_count).to eq 2 end it "sends email if asked" do @notification2 = FactoryBot.create(:notification) @notification2.send_email - ActionMailer::Base.deliveries.last.to.should == [@notification2.recipient.email] + expect(ActionMailer::Base.deliveries.last.to).to eq [@notification2.recipient.email] end it "doesn't send email to people who don't want it" do - notification = FactoryBot.create(:no_email_notification) - notification.send_email - ActionMailer::Base.deliveries.last.to.should_not == [notification.recipient.email] + FactoryBot.create(:no_email_notification).send_email + expect(ActionMailer::Base.deliveries.last.to).not_to eq [notification.recipient.email] end it "sends email on creation" do @notification2 = FactoryBot.create(:notification) - ActionMailer::Base.deliveries.last.to.should == [@notification2.recipient.email] + expect(ActionMailer::Base.deliveries.last.to).to eq [@notification2.recipient.email] end it "replaces missing subjects with (no subject)" do notification = FactoryBot.create(:notification, subject: nil) - notification.subject.should == "(no subject)" + expect(notification.subject).to eq "(no subject)" end it "replaces whitespace-only subjects with (no subject)" do notification = FactoryBot.create(:notification, subject: " ") - notification.subject.should == "(no subject)" + expect(notification.subject).to eq "(no subject)" end end From 3de23957a3b769bc84623556cc879e0d17b9fec2 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 3 Jan 2019 13:50:01 +1300 Subject: [PATCH 249/267] Updated package-lock for linters --- package-lock.json | 402 +++++++++++++++++++++++----------------------- 1 file changed, 201 insertions(+), 201 deletions(-) diff --git a/package-lock.json b/package-lock.json index baf5adb61..0aebca689 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", "dev": true, "requires": { - "acorn": "3.3.0" + "acorn": "^3.0.4" }, "dependencies": { "acorn": { @@ -33,10 +33,10 @@ "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } }, "ajv-keywords": { @@ -69,7 +69,7 @@ "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "array-union": { @@ -78,7 +78,7 @@ "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "1.0.3" + "array-uniq": "^1.0.1" } }, "array-uniq": { @@ -99,9 +99,9 @@ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", "dev": true, "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" }, "dependencies": { "chalk": { @@ -110,11 +110,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, "strip-ansi": { @@ -123,7 +123,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } } } @@ -140,7 +140,7 @@ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -150,7 +150,7 @@ "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", "dev": true, "requires": { - "callsites": "0.2.0" + "callsites": "^0.2.0" } }, "callsites": { @@ -165,9 +165,9 @@ "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", "dev": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "ansi-styles": "^3.1.0", + "escape-string-regexp": "^1.0.5", + "supports-color": "^4.0.0" }, "dependencies": { "ansi-styles": { @@ -176,7 +176,7 @@ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "^1.9.0" } }, "supports-color": { @@ -185,7 +185,7 @@ "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "^2.0.0" } } } @@ -209,7 +209,7 @@ "dev": true, "requires": { "exit": "0.1.2", - "glob": "7.1.2" + "glob": "^7.1.1" } }, "cli-cursor": { @@ -218,7 +218,7 @@ "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "dev": true, "requires": { - "restore-cursor": "2.0.0" + "restore-cursor": "^2.0.0" } }, "cli-width": { @@ -245,12 +245,12 @@ "integrity": "sha1-lg/VuXVrhFGU6fl6R1bmKGEha3Q=", "dev": true, "requires": { - "coffeescript": "2.0.3", - "glob": "7.1.2", - "ignore": "3.3.7", - "optimist": "0.6.1", - "resolve": "0.6.3", - "strip-json-comments": "1.0.4" + "coffeescript": "~2.0.x", + "glob": "^7.0.6", + "ignore": "^3.0.9", + "optimist": "^0.6.1", + "resolve": "^0.6.3", + "strip-json-comments": "^1.0.2" } }, "coffeescript": { @@ -265,7 +265,7 @@ "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "^1.1.1" } }, "color-name": { @@ -286,9 +286,9 @@ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "typedarray": "0.0.6" + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, "console-browserify": { @@ -297,7 +297,7 @@ "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", "dev": true, "requires": { - "date-now": "0.1.4" + "date-now": "^0.1.4" } }, "core-util-is": { @@ -312,9 +312,9 @@ "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.3.0" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, "csslint": { @@ -323,8 +323,8 @@ "integrity": "sha1-Gcw+2jIhYP0/cjKvHLKjYOiYouk=", "dev": true, "requires": { - "clone": "2.1.1", - "parserlib": "1.1.1" + "clone": "~2.1.0", + "parserlib": "~1.1.1" } }, "date-now": { @@ -354,13 +354,13 @@ "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", "dev": true, "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" } }, "doctrine": { @@ -369,7 +369,7 @@ "integrity": "sha512-y0tm5Pq6ywp3qSTZ1vPgVdAnbDEoeoc5wlOHXoY1c4Wug/a7JvqHIl7BTvwodaHmejWkK/9dSb3sCYfyo/om8A==", "dev": true, "requires": { - "esutils": "2.0.2" + "esutils": "^2.0.2" } }, "dom-serializer": { @@ -378,8 +378,8 @@ "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", "dev": true, "requires": { - "domelementtype": "1.1.3", - "entities": "1.1.1" + "domelementtype": "~1.1.1", + "entities": "~1.1.1" }, "dependencies": { "domelementtype": { @@ -408,7 +408,7 @@ "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", "dev": true, "requires": { - "domelementtype": "1.3.0" + "domelementtype": "1" } }, "domutils": { @@ -417,8 +417,8 @@ "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", "dev": true, "requires": { - "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" + "dom-serializer": "0", + "domelementtype": "1" } }, "entities": { @@ -439,43 +439,43 @@ "integrity": "sha512-Ul6CSGRjKscEyg0X/EeNs7o2XdnbTEOD1OM8cTjmx85RPcBJQrEhZLevhuJZNAE/vS2iVl5Uhgiqf3h5uLMCJQ==", "dev": true, "requires": { - "ajv": "5.5.2", - "babel-code-frame": "6.26.0", - "chalk": "2.3.0", - "concat-stream": "1.6.0", - "cross-spawn": "5.1.0", - "debug": "3.1.0", - "doctrine": "2.0.2", - "eslint-scope": "3.7.1", - "eslint-visitor-keys": "1.0.0", - "espree": "3.5.2", - "esquery": "1.0.0", - "esutils": "2.0.2", - "file-entry-cache": "2.0.0", - "functional-red-black-tree": "1.0.1", - "glob": "7.1.2", - "globals": "11.1.0", - "ignore": "3.3.7", - "imurmurhash": "0.1.4", - "inquirer": "3.3.0", - "is-resolvable": "1.0.1", - "js-yaml": "3.10.0", - "json-stable-stringify-without-jsonify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.4", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "7.0.0", - "progress": "2.0.0", - "require-uncached": "1.0.3", - "semver": "5.4.1", - "strip-ansi": "4.0.0", - "strip-json-comments": "2.0.1", - "table": "4.0.2", - "text-table": "0.2.0" + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.0.2", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.2", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "^4.0.1", + "text-table": "~0.2.0" }, "dependencies": { "strip-json-comments": { @@ -498,8 +498,8 @@ "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { - "esrecurse": "4.2.0", - "estraverse": "4.2.0" + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" } }, "eslint-visitor-keys": { @@ -514,8 +514,8 @@ "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", "dev": true, "requires": { - "acorn": "5.3.0", - "acorn-jsx": "3.0.1" + "acorn": "^5.2.1", + "acorn-jsx": "^3.0.0" } }, "esprima": { @@ -530,7 +530,7 @@ "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", "dev": true, "requires": { - "estraverse": "4.2.0" + "estraverse": "^4.0.0" } }, "esrecurse": { @@ -539,8 +539,8 @@ "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", "dev": true, "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" + "estraverse": "^4.1.0", + "object-assign": "^4.0.1" } }, "estraverse": { @@ -567,9 +567,9 @@ "integrity": "sha1-PQJqIbf5W1cmOH1CAKwWDTcsO0g=", "dev": true, "requires": { - "chardet": "0.4.2", - "iconv-lite": "0.4.19", - "tmp": "0.0.33" + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" } }, "fast-deep-equal": { @@ -596,7 +596,7 @@ "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "dev": true, "requires": { - "escape-string-regexp": "1.0.5" + "escape-string-regexp": "^1.0.5" } }, "file-entry-cache": { @@ -605,8 +605,8 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "1.3.0", - "object-assign": "4.1.1" + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" } }, "flat-cache": { @@ -615,10 +615,10 @@ "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" } }, "fs.realpath": { @@ -639,12 +639,12 @@ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "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" } }, "globals": { @@ -659,12 +659,12 @@ "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "graceful-fs": { @@ -679,7 +679,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-flag": { @@ -694,11 +694,11 @@ "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", "dev": true, "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.3.0", - "domutils": "1.5.1", - "entities": "1.0.0", - "readable-stream": "1.1.14" + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" }, "dependencies": { "isarray": { @@ -713,10 +713,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } }, "string_decoder": { @@ -751,8 +751,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -767,20 +767,20 @@ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "ansi-escapes": "3.0.0", - "chalk": "2.3.0", - "cli-cursor": "2.1.0", - "cli-width": "2.2.0", - "external-editor": "2.1.0", - "figures": "2.0.0", - "lodash": "4.17.4", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" } }, "is-fullwidth-code-point": { @@ -801,7 +801,7 @@ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", "dev": true, "requires": { - "is-path-inside": "1.0.1" + "is-path-inside": "^1.0.0" } }, "is-path-inside": { @@ -810,7 +810,7 @@ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "path-is-inside": "^1.0.1" } }, "is-promise": { @@ -849,8 +849,8 @@ "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", "dev": true, "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, "jshint": { @@ -859,14 +859,14 @@ "integrity": "sha1-HnJSkVzmgbQIJ+4UJIxG006apiw=", "dev": true, "requires": { - "cli": "1.0.1", - "console-browserify": "1.1.0", - "exit": "0.1.2", - "htmlparser2": "3.8.3", - "lodash": "3.7.0", - "minimatch": "3.0.4", - "shelljs": "0.3.0", - "strip-json-comments": "1.0.4" + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "3.7.x", + "minimatch": "~3.0.2", + "shelljs": "0.3.x", + "strip-json-comments": "1.0.x" }, "dependencies": { "lodash": { @@ -901,8 +901,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "lodash": { @@ -917,8 +917,8 @@ "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, "mimic-fn": { @@ -933,7 +933,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -989,7 +989,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "onetime": { @@ -998,7 +998,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "1.1.0" + "mimic-fn": "^1.0.0" } }, "optimist": { @@ -1007,8 +1007,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "0.0.10", - "wordwrap": "0.0.3" + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" } }, "optionator": { @@ -1017,12 +1017,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" }, "dependencies": { "wordwrap": { @@ -1075,7 +1075,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "pluralize": { @@ -1114,13 +1114,13 @@ "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "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" } }, "require-uncached": { @@ -1129,8 +1129,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" } }, "resolve": { @@ -1151,8 +1151,8 @@ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" } }, "rimraf": { @@ -1161,7 +1161,7 @@ "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "run-async": { @@ -1170,7 +1170,7 @@ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "is-promise": "2.1.0" + "is-promise": "^2.1.0" } }, "rx-lite": { @@ -1185,7 +1185,7 @@ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", "dev": true, "requires": { - "rx-lite": "4.0.8" + "rx-lite": "*" } }, "safe-buffer": { @@ -1206,7 +1206,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "1.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { @@ -1227,7 +1227,7 @@ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0" + "is-fullwidth-code-point": "^2.0.0" } }, "sprintf-js": { @@ -1242,8 +1242,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, "string_decoder": { @@ -1252,7 +1252,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "strip-ansi": { @@ -1261,7 +1261,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "3.0.0" + "ansi-regex": "^3.0.0" }, "dependencies": { "ansi-regex": { @@ -1290,12 +1290,12 @@ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "5.5.2", - "ajv-keywords": "2.1.1", - "chalk": "2.3.0", - "lodash": "4.17.4", + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", "slice-ansi": "1.0.0", - "string-width": "2.1.1" + "string-width": "^2.1.1" } }, "text-table": { @@ -1316,7 +1316,7 @@ "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", "dev": true, "requires": { - "os-tmpdir": "1.0.2" + "os-tmpdir": "~1.0.2" } }, "type-check": { @@ -1325,7 +1325,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "typedarray": { @@ -1346,7 +1346,7 @@ "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "wordwrap": { @@ -1367,7 +1367,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "0.5.1" + "mkdirp": "^0.5.1" } }, "yallist": { From 8229c7196cdae81980e06ae1f5fceef36b1181ab Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 3 Jan 2019 13:50:30 +1300 Subject: [PATCH 250/267] Don't install rubocop in linters. Use the one in the bundle --- script/install_linters.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/script/install_linters.sh b/script/install_linters.sh index 679a6b64a..159aaa05e 100755 --- a/script/install_linters.sh +++ b/script/install_linters.sh @@ -2,8 +2,11 @@ if [ "${STATIC_CHECKS}" = "true" ]; then set -euv - gem install --update overcommit rubocop haml-lint bundler-audit; npm install; + + gem install --update overcommit haml-lint bundler-audit; + + pip install --upgrade pip; pip install yamllint --user; overcommit --install; From 84201c4f55653b2d586b16771c65cb303fc75866 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 3 Jan 2019 14:12:27 +1300 Subject: [PATCH 251/267] Pin to ruby 2.5.3 on linting --- script/install_linters.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/script/install_linters.sh b/script/install_linters.sh index 159aaa05e..5df79654e 100755 --- a/script/install_linters.sh +++ b/script/install_linters.sh @@ -2,6 +2,8 @@ if [ "${STATIC_CHECKS}" = "true" ]; then set -euv + + rvm use 2.5.3; #overcommit doesn't support 2.6.0 npm install; gem install --update overcommit haml-lint bundler-audit; From 7d7ae1f0446e06f473da035d47b2653f8b8e953a Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 3 Jan 2019 14:19:45 +1300 Subject: [PATCH 252/267] Pin to older childprocess --- script/install_linters.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/script/install_linters.sh b/script/install_linters.sh index 5df79654e..2deb87c82 100755 --- a/script/install_linters.sh +++ b/script/install_linters.sh @@ -7,6 +7,7 @@ if [ "${STATIC_CHECKS}" = "true" ]; then npm install; gem install --update overcommit haml-lint bundler-audit; + gem install childprocess 0.7.0 pip install --upgrade pip; pip install yamllint --user; From 12472d3762336bfc61bf1908d53a1bccce7300d2 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 3 Jan 2019 14:41:11 +1300 Subject: [PATCH 253/267] Return to previous version --- script/install_linters.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/script/install_linters.sh b/script/install_linters.sh index 2deb87c82..159aaa05e 100755 --- a/script/install_linters.sh +++ b/script/install_linters.sh @@ -2,12 +2,9 @@ if [ "${STATIC_CHECKS}" = "true" ]; then set -euv - - rvm use 2.5.3; #overcommit doesn't support 2.6.0 npm install; gem install --update overcommit haml-lint bundler-audit; - gem install childprocess 0.7.0 pip install --upgrade pip; pip install yamllint --user; From 4374a4800be24bedc780768a579adcfaa5dcac01 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Thu, 3 Jan 2019 14:44:35 +1300 Subject: [PATCH 254/267] Commenting out linter checks until overcommit is fixed --- .travis.yml | 4 ++-- script/check_static.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d8959f060..20b9a58a0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ env: matrix: - GROWSTUFF_ELASTICSEARCH=true RSPEC_TAG=elasticsearch COVERAGE=true - GROWSTUFF_ELASTICSEARCH=false RSPEC_TAG=~elasticsearch COVERAGE=false - - STATIC_CHECKS=true + # - STATIC_CHECKS=true global: - secure: "Z5TpM2jEX4UCvNePnk/LwltQX48U2u9BRc+Iypr1x9QW2o228QJhPIOH39a8RMUrepGnkQIq9q3ZRUn98RfrJz1yThtlNFL3NmzdQ57gKgjGwfpa0e4Dwj/ZJqV2D84tDGjvdVYLP7zzaYZxQcwk/cgNpzKf/jq97HLNP7CYuf4=" - GROWSTUFF_EMAIL="noreply@test.growstuff.org" @@ -19,7 +19,7 @@ before_install: - ./script/install_phantomjs.sh - export PATH=$PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64/bin:$PATH - ./script/install_codeclimate.sh - - ./script/install_linters.sh + # - ./script/install_linters.sh - VERSION="6.2.3" ./script/install_elasticsearch.sh before_script: - > diff --git a/script/check_static.rb b/script/check_static.rb index 137c97f7f..e747599f8 100755 --- a/script/check_static.rb +++ b/script/check_static.rb @@ -1,7 +1,7 @@ #!/usr/bin/env ruby checks = [ - 'overcommit -r', + # 'overcommit -r', 'bundle exec script/check_contributors_md.rb' ] From 273da44406d3458c5b753b386049a04a30f3fc7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Thu, 3 Jan 2019 07:31:04 +0000 Subject: [PATCH 255/267] Bump rubocop-rspec from 1.30.1 to 1.31.0 Bumps [rubocop-rspec](https://github.com/rubocop-hq/rubocop-rspec) from 1.30.1 to 1.31.0. - [Release notes](https://github.com/rubocop-hq/rubocop-rspec/releases) - [Changelog](https://github.com/rubocop-hq/rubocop-rspec/blob/master/CHANGELOG.md) - [Commits](https://github.com/rubocop-hq/rubocop-rspec/compare/v1.30.1...v1.31.0) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index b7d1d6d19..5d4caeb33 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -436,7 +436,7 @@ GEM rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (~> 1.4.0) - rubocop-rspec (1.30.1) + rubocop-rspec (1.31.0) rubocop (>= 0.60.0) ruby-progressbar (1.10.0) ruby-units (2.3.1) From f83a2b639730d985dc8fb38dd0caa6646404bee7 Mon Sep 17 00:00:00 2001 From: Awesome Code Date: Thu, 3 Jan 2019 10:00:13 +0000 Subject: [PATCH 256/267] Auto corrected by following Format Javascript Code --- app/assets/javascripts/highcharts.js | 11651 ++++++++++++++++++++++++- 1 file changed, 11269 insertions(+), 382 deletions(-) diff --git a/app/assets/javascripts/highcharts.js b/app/assets/javascripts/highcharts.js index 9554ef58b..c7136bafe 100644 --- a/app/assets/javascripts/highcharts.js +++ b/app/assets/javascripts/highcharts.js @@ -5,385 +5,11272 @@ License: www.highcharts.com/license */ -(function(S,M){"object"===typeof module&&module.exports?module.exports=S.document?M(S):M:S.Highcharts=M(S)})("undefined"!==typeof window?window:this,function(S){var M=function(){var a="undefined"===typeof S?window:S,E=a.document,D=a.navigator&&a.navigator.userAgent||"",H=E&&E.createElementNS&&!!E.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,p=/(edge|msie|trident)/i.test(D)&&!a.opera,f=/Firefox/.test(D),l=f&&4>parseInt(D.split("Firefox/")[1],10);return a.Highcharts?a.Highcharts.error(16, -!0):{product:"Highcharts",version:"6.0.4",deg2rad:2*Math.PI/360,doc:E,hasBidiBug:l,hasTouch:E&&void 0!==E.documentElement.ontouchstart,isMS:p,isWebKit:/AppleWebKit/.test(D),isFirefox:f,isTouchDevice:/(Mobile|Android|Windows Phone)/.test(D),SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:H,win:a,marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){},charts:[]}}();(function(a){a.timers=[];var E=a.charts,D=a.doc,H=a.win;a.error=function(p, -f){p=a.isNumber(p)?"Highcharts error #"+p+": www.highcharts.com/errors/"+p:p;if(f)throw Error(p);H.console&&console.log(p)};a.Fx=function(a,f,l){this.options=f;this.elem=a;this.prop=l};a.Fx.prototype={dSetter:function(){var a=this.paths[0],f=this.paths[1],l=[],r=this.now,n=a.length,w;if(1===r)l=this.toD;else if(n===f.length&&1>r)for(;n--;)w=parseFloat(a[n]),l[n]=isNaN(w)?f[n]:r*parseFloat(f[n]-w)+w;else l=f;this.elem.attr("d",l,null,!0)},update:function(){var a=this.elem,f=this.prop,l=this.now,r= -this.options.step;if(this[f+"Setter"])this[f+"Setter"]();else a.attr?a.element&&a.attr(f,l,null,!0):a.style[f]=l+this.unit;r&&r.call(a,l,this)},run:function(p,f,l){var r=this,n=r.options,w=function(a){return w.stopped?!1:r.step(a)},u=H.requestAnimationFrame||function(a){setTimeout(a,13)},e=function(){for(var h=0;h=u+this.startTime?(this.now=this.end,this.pos=1,this.update(),l=e[this.prop]=!0,a.objectEach(e,function(a){!0!==a&&(l=!1)}),l&&w&&w.call(n),p=!1):(this.pos=r.easing((f-this.startTime)/u),this.now=this.start+(this.end- -this.start)*this.pos,this.update(),p=!0);return p},initPath:function(p,f,l){function r(a){var b,c;for(k=a.length;k--;)b="M"===a[k]||"L"===a[k],c=/[a-zA-Z]/.test(a[k+3]),b&&c&&a.splice(k+1,0,a[k+1],a[k+2],a[k+1],a[k+2])}function n(a,b){for(;a.lengtha&&-Infinityw?"AM":"PM",P:12>w?"am":"pm",S:k(n.getSeconds()),L:k(Math.round(f%1E3),3)},a.dateFormats);a.objectEach(r,function(a,b){for(;-1!==p.indexOf("%"+b);)p=p.replace("%"+b,"function"===typeof a?a(f):a)});return l?p.substr(0,1).toUpperCase()+p.substr(1):p};a.formatSingle=function(p,f){var l=/\.([0-9])/,r=a.defaultOptions.lang;/f$/.test(p)?(l=(l=p.match(l))?l[1]:-1,null!==f&&(f=a.numberFormat(f,l,r.decimalPoint,-1=l&&(f=[1/l])));for(r=0;r=p||!n&&w<=(f[r]+(f[r+1]||f[r]))/2);r++);return u=a.correctFloat(u*l,-Math.round(Math.log(.001)/Math.LN10))};a.stableSort=function(a,f){var l=a.length,p,n;for(n=0;nl&&(l=a[f]);return l};a.destroyObjectProperties=function(p,f){a.objectEach(p,function(a,r){a&&a!==f&&a.destroy&&a.destroy();delete p[r]})};a.discardElement=function(p){var f=a.garbageBin;f||(f=a.createElement("div"));p&&f.appendChild(p);f.innerHTML=""};a.correctFloat=function(a,f){return parseFloat(a.toPrecision(f||14))};a.setAnimation=function(p,f){f.renderer.globalAnimation=a.pick(p,f.options.chart.animation, -!0)};a.animObject=function(p){return a.isObject(p)?a.merge(p):{duration:p?500:0}};a.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5,month:24192E5,year:314496E5};a.numberFormat=function(p,f,l,r){p=+p||0;f=+f;var n=a.defaultOptions.lang,w=(p.toString().split(".")[1]||"").split("e")[0].length,u,e,h=p.toString().split("e");-1===f?f=Math.min(w,20):a.isNumber(f)?f&&h[1]&&0>h[1]&&(u=f+ +h[1],0<=u?(h[0]=(+h[0]).toExponential(u).split("e")[0],f=u):(h[0]=h[0].split(".")[0]||0, -p=20>f?(h[0]*Math.pow(10,h[1])).toFixed(f):0,h[1]=0)):f=2;e=(Math.abs(h[1]?h[0]:p)+Math.pow(10,-Math.max(f,w)-1)).toFixed(f);w=String(a.pInt(e));u=3p?"-":"")+(u?w.substr(0,u)+r:"");p+=w.substr(u).replace(/(\d{3})(?=\d)/g,"$1"+r);f&&(p+=l+e.slice(-f));h[1]&&0!==+p&&(p+="e"+h[1]);return p};Math.easeInOutSine=function(a){return-.5*(Math.cos(Math.PI*a)-1)};a.getStyle=function(p,f,l){if("width"===f)return Math.min(p.offsetWidth, -p.scrollWidth)-a.getStyle(p,"padding-left")-a.getStyle(p,"padding-right");if("height"===f)return Math.min(p.offsetHeight,p.scrollHeight)-a.getStyle(p,"padding-top")-a.getStyle(p,"padding-bottom");H.getComputedStyle||a.error(27,!0);if(p=H.getComputedStyle(p,void 0))p=p.getPropertyValue(f),a.pick(l,"opacity"!==f)&&(p=a.pInt(p));return p};a.inArray=function(p,f){return(a.indexOfPolyfill||Array.prototype.indexOf).call(f,p)};a.grep=function(p,f){return(a.filterPolyfill||Array.prototype.filter).call(p, -f)};a.find=Array.prototype.find?function(a,f){return a.find(f)}:function(a,f){var l,r=a.length;for(l=0;l>16,(l&65280)>> -8,l&255,1]:4===f&&(n=[(l&3840)>>4|(l&3840)>>8,(l&240)>>4|l&240,(l&15)<<4|l&15,1])),!n)for(w=this.parsers.length;w--&&!n;)u=this.parsers[w],(f=u.regex.exec(l))&&(n=u.parse(f));this.rgba=n||[]},get:function(a){var f=this.input,n=this.rgba,l;this.stops?(l=p(f),l.stops=[].concat(l.stops),E(this.stops,function(n,e){l.stops[e]=[l.stops[e][0],n.get(a)]})):l=n&&D(n[0])?"rgb"===a||!a&&1===n[3]?"rgb("+n[0]+","+n[1]+","+n[2]+")":"a"===a?n[3]:"rgba("+n.join(",")+")":f;return l},brighten:function(a){var l,n=this.rgba; -if(this.stops)E(this.stops,function(n){n.brighten(a)});else if(D(a)&&0!==a)for(l=0;3>l;l++)n[l]+=f(255*a),0>n[l]&&(n[l]=0),255y.width)y={width:0,height:0}}else y=this.htmlGetBBox();b.isSVG&& -(a=y.width,b=y.height,q&&"11px"===q.fontSize&&17===Math.round(b)&&(y.height=b=14),g&&(y.width=Math.abs(b*Math.sin(v))+Math.abs(a*Math.cos(v)),y.height=Math.abs(b*Math.cos(v))+Math.abs(a*Math.sin(v))));if(A&&0]*>/g,"")))},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,g,b){"string"===typeof a?b.setAttribute(g,a):a&&this.colorGradient(a,g,b)},visibilitySetter:function(a,g,b){"inherit"===a?b.removeAttribute(g):this[g]!==a&&b.setAttribute(g,a);this[g]=a},zIndexSetter:function(a,b){var v=this.renderer,y=this.parentGroup,c=(y||v).element||v.box,k,d=this.element,q,e,v=c===v.box;k=this.added;var z;u(a)&& -(d.zIndex=a,a=+a,this[b]===a&&(k=!1),this[b]=a);if(k){(a=this.zIndex)&&y&&(y.handleZ=!0);b=c.childNodes;for(z=b.length-1;0<=z&&!q;z--)if(y=b[z],k=y.zIndex,e=!u(k),y!==d)if(0>a&&e&&!v&&!z)c.insertBefore(d,b[z]),q=!0;else if(g(k)<=a||e&&(!u(a)||0<=a))c.insertBefore(d,b[z+1]||null),q=!0;q||(c.insertBefore(d,b[v?3:0]||null),q=!0)}return q},_defaultSetter:function(a,g,b){b.setAttribute(g,a)}});E.prototype.yGetter=E.prototype.xGetter;E.prototype.translateXSetter=E.prototype.translateYSetter=E.prototype.rotationSetter= -E.prototype.verticalAlignSetter=E.prototype.rotationOriginXSetter=E.prototype.rotationOriginYSetter=E.prototype.scaleXSetter=E.prototype.scaleYSetter=E.prototype.matrixSetter=function(a,g){this[g]=a;this.doTransform=!0};E.prototype["stroke-widthSetter"]=E.prototype.strokeSetter=function(a,g,b){this[g]=a;this.stroke&&this["stroke-width"]?(E.prototype.fillSetter.call(this,this.stroke,"stroke",b),b.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0):"stroke-width"===g&&0===a&&this.hasStroke&& -(b.removeAttribute("stroke"),this.hasStroke=!1)};D=a.SVGRenderer=function(){this.init.apply(this,arguments)};c(D.prototype,{Element:E,SVG_NS:P,init:function(a,g,b,v,c,k){var y;v=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"}).css(this.getStyle(v));y=v.element;a.appendChild(y);f(a,"dir","ltr");-1===a.innerHTML.indexOf("xmlns")&&f(y,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=y;this.boxWrapper=v;this.alignedObjects=[];this.url=(x||N)&&m.getElementsByTagName("base").length? -R.location.href.replace(/#.*?$/,"").replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(m.createTextNode("Created with Highcharts 6.0.4"));this.defs=this.createElement("defs").add();this.allowHTML=k;this.forExport=c;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(g,b,!1);var d;x&&a.getBoundingClientRect&&(g=function(){n(a,{left:0,top:0});d=a.getBoundingClientRect();n(a,{left:Math.ceil(d.left)- -d.left+"px",top:Math.ceil(d.top)-d.top+"px"})},g(),this.unSubPixelFix=H(R,"resize",g))},getStyle:function(a){return this.style=c({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},setStyle:function(a){this.boxWrapper.css(this.getStyle(a))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();h(this.gradients||{});this.gradients=null;a&&(this.defs=a.destroy()); -this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(a){var g=new this.Element;g.init(this,a);return g},draw:A,getRadialAttr:function(a,g){return{cx:a[0]-a[2]/2+g.cx*a[2],cy:a[1]-a[2]/2+g.cy*a[2],r:g.r*a[2]}},getSpanWidth:function(a,g){var b=a.getBBox(!0).width;!L&&this.forExport&&(b=this.measureSpanWidth(g.firstChild.data,a.styles));return b},applyEllipsis:function(a,g,b,v){var c=a.rotation,y=b,k,d=0,q=b.length,e=function(a){g.removeChild(g.firstChild); -a&&g.appendChild(m.createTextNode(a))},z;a.rotation=0;y=this.getSpanWidth(a,g);if(z=y>v){for(;d<=q;)k=Math.ceil((d+q)/2),y=b.substring(0,k)+"\u2026",e(y),y=this.getSpanWidth(a,g),d===q?d=q+1:y>v?q=k-1:d=k;0===q&&e("")}a.rotation=c;return z},escapes:{"\x26":"\x26amp;","\x3c":"\x26lt;","\x3e":"\x26gt;","'":"\x26#39;",'"':"\x26quot;"},buildText:function(a){var b=a.element,v=this,c=v.forExport,y=G(a.textStr,"").toString(),q=-1!==y.indexOf("\x3c"),e=b.childNodes,z,h,A,J,t=f(b,"x"),x=a.styles,B=a.textWidth, -l=x&&x.lineHeight,C=x&&x.textOutline,u=x&&"ellipsis"===x.textOverflow,Q=x&&"nowrap"===x.whiteSpace,w=x&&x.fontSize,R,I,r=e.length,x=B&&!a.added&&this.box,p=function(a){var c;c=/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:w||v.style.fontSize||12;return l?g(l):v.fontMetrics(c,a.getAttribute("style")?a:b).h},K=function(a){F(v.escapes,function(g,b){a=a.replace(new RegExp(g,"g"),b)});return a};R=[y,u,Q,l,C,w,B].join();if(R!==a.textCache){for(a.textCache=R;r--;)b.removeChild(e[r]);q||C||u||B|| --1!==y.indexOf(" ")?(z=/<.*class="([^"]+)".*>/,h=/<.*style="([^"]+)".*>/,A=/<.*href="([^"]+)".*>/,x&&x.appendChild(b),y=q?y.replace(/<(b|strong)>/g,'\x3cspan style\x3d"font-weight:bold"\x3e').replace(/<(i|em)>/g,'\x3cspan style\x3d"font-style:italic"\x3e').replace(//g,"\x3c/span\x3e").split(//g):[y],y=k(y,function(a){return""!==a}),d(y,function(g,y){var k,q=0;g=g.replace(/^\s+|\s+$/g,"").replace(//g,"\x3c/span\x3e|||"); -k=g.split("|||");d(k,function(g){if(""!==g||1===k.length){var d={},e=m.createElementNS(v.SVG_NS,"tspan"),x,F;z.test(g)&&(x=g.match(z)[1],f(e,"class",x));h.test(g)&&(F=g.match(h)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),f(e,"style",F));A.test(g)&&!c&&(f(e,"onclick",'location.href\x3d"'+g.match(A)[1]+'"'),f(e,"class","highcharts-anchor"),n(e,{cursor:"pointer"}));g=K(g.replace(/<[a-zA-Z\/](.|\n)*?>/g,"")||" ");if(" "!==g){e.appendChild(m.createTextNode(g));q?d.dx=0:y&&null!==t&&(d.x=t);f(e,d);b.appendChild(e); -!q&&I&&(!L&&c&&n(e,{display:"block"}),f(e,"dy",p(e)));if(B){d=g.replace(/([^\^])-/g,"$1- ").split(" ");x=1B,void 0===J&&(J=g),g&&1!==d.length?(e.removeChild(e.firstChild),O.unshift(d.pop())):(d=O,O=[],d.length&&!Q&&(e=m.createElementNS(P,"tspan"),f(e,{dy:C,x:t}),F&&f(e,"style",F),b.appendChild(e)),l>B&&(B=l)),d.length&&e.appendChild(m.createTextNode(d.join(" ").replace(/- /g, -"-")));a.rotation=G}q++}}});I=I||b.childNodes.length}),J&&a.attr("title",a.textStr),x&&x.removeChild(b),C&&a.applyTextOutline&&a.applyTextOutline(C)):b.appendChild(m.createTextNode(K(y)))}},getContrast:function(a){a=r(a).rgba;return 510Math.abs(c.end-c.start-2*Math.PI));var y=Math.cos(k),z=Math.sin(k),h=Math.cos(e),e=Math.sin(e);c=.001>c.end-k-Math.PI?0:1;d=["M",a+d*y,g+q*z,"A",d,q,0,c,1,a+d*h,g+q*e];u(b)&&d.push(v?"M":"L",a+b* -h,g+b*e,"A",b,b,0,c,0,a+b*y,g+b*z);d.push(v?"":"Z");return d},callout:function(a,g,b,v,c){var d=Math.min(c&&c.r||0,b,v),k=d+6,q=c&&c.anchorX;c=c&&c.anchorY;var e;e=["M",a+d,g,"L",a+b-d,g,"C",a+b,g,a+b,g,a+b,g+d,"L",a+b,g+v-d,"C",a+b,g+v,a+b,g+v,a+b-d,g+v,"L",a+d,g+v,"C",a,g+v,a,g+v,a,g+v-d,"L",a,g+d,"C",a,g,a,g,a+d,g];q&&q>b?c>g+k&&cq?c>g+k&&cv&&q>a+k&&qc&&q>a+k&&qa?a+3:Math.round(1.2*a);return{h:b,b:Math.round(.8* -b),f:a}},rotCorr:function(a,g,b){var v=a;g&&b&&(v=Math.max(v*Math.cos(g*e),4));return{x:-a/3*Math.sin(g*e),y:v}},label:function(g,b,k,e,z,h,m,A,L){var y=this,J=y.g("button"!==L&&"label"),t=J.text=y.text("",0,0,m).attr({zIndex:1}),x,F,n=0,B=3,l=0,C,f,Q,G,w,R={},I,P,r=/^url\((.*?)\)$/.test(e),p=r,K,O,N,T;L&&J.addClass("highcharts-"+L);p=r;K=function(){return(I||0)%2/2};O=function(){var a=t.element.style,g={};F=(void 0===C||void 0===f||w)&&u(t.textStr)&&t.getBBox();J.width=(C||F.width||0)+2*B+l;J.height= -(f||F.height||0)+2*B;P=B+y.fontMetrics(a&&a.fontSize,t).b;p&&(x||(J.box=x=y.symbols[e]||r?y.symbol(e):y.rect(),x.addClass(("button"===L?"":"highcharts-label-box")+(L?" highcharts-"+L+"-box":"")),x.add(J),a=K(),g.x=a,g.y=(A?-P:0)+a),g.width=Math.round(J.width),g.height=Math.round(J.height),x.attr(c(g,R)),R={})};N=function(){var a=l+B,g;g=A?0:P;u(C)&&F&&("center"===w||"right"===w)&&(a+={center:.5,right:1}[w]*(C-F.width));if(a!==t.x||g!==t.y)t.attr("x",a),void 0!==g&&t.attr("y",g);t.x=a;t.y=g};T=function(a, -g){x?x.attr(a,g):R[a]=g};J.onAdd=function(){t.add(J);J.attr({text:g||0===g?g:"",x:b,y:k});x&&u(z)&&J.attr({anchorX:z,anchorY:h})};J.widthSetter=function(g){C=a.isNumber(g)?g:null};J.heightSetter=function(a){f=a};J["text-alignSetter"]=function(a){w=a};J.paddingSetter=function(a){u(a)&&a!==B&&(B=J.padding=a,N())};J.paddingLeftSetter=function(a){u(a)&&a!==l&&(l=a,N())};J.alignSetter=function(a){a={left:0,center:.5,right:1}[a];a!==n&&(n=a,F&&J.attr({x:Q}))};J.textSetter=function(a){void 0!==a&&t.textSetter(a); -O();N()};J["stroke-widthSetter"]=function(a,g){a&&(p=!0);I=this["stroke-width"]=a;T(g,a)};J.strokeSetter=J.fillSetter=J.rSetter=function(a,g){"r"!==g&&("fill"===g&&a&&(p=!0),J[g]=a);T(g,a)};J.anchorXSetter=function(a,g){z=J.anchorX=a;T(g,Math.round(a)-K()-Q)};J.anchorYSetter=function(a,g){h=J.anchorY=a;T(g,a-G)};J.xSetter=function(a){J.x=a;n&&(a-=n*((C||F.width)+2*B));Q=Math.round(a);J.attr("translateX",Q)};J.ySetter=function(a){G=J.y=Math.round(a);J.attr("translateY",G)};var U=J.css;return c(J,{css:function(a){if(a){var g= -{};a=q(a);d(J.textProps,function(b){void 0!==a[b]&&(g[b]=a[b],delete a[b])});t.css(g)}return U.call(J,a)},getBBox:function(){return{width:F.width+2*B,height:F.height+2*B,x:F.x-B,y:F.y-B}},shadow:function(a){a&&(O(),x&&x.shadow(a));return J},destroy:function(){v(J.element,"mouseenter");v(J.element,"mouseleave");t&&(t=t.destroy());x&&(x=x.destroy());E.prototype.destroy.call(J);J=y=O=N=T=null}})}});a.Renderer=D})(M);(function(a){var E=a.attr,D=a.createElement,H=a.css,p=a.defined,f=a.each,l=a.extend, -r=a.isFirefox,n=a.isMS,w=a.isWebKit,u=a.pick,e=a.pInt,h=a.SVGRenderer,m=a.win,d=a.wrap;l(a.SVGElement.prototype,{htmlCss:function(a){var b=this.element;if(b=a&&"SPAN"===b.tagName&&a.width)delete a.width,this.textWidth=b,this.updateTransform();a&&"ellipsis"===a.textOverflow&&(a.whiteSpace="nowrap",a.overflow="hidden");this.styles=l(this.styles,a);H(this.element,a);return this},htmlGetBBox:function(){var a=this.element;return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}, -htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,d=this.translateX||0,z=this.translateY||0,h=this.x||0,m=this.y||0,x=this.textAlign||"left",n={left:0,center:.5,right:1}[x],t=this.styles;H(b,{marginLeft:d,marginTop:z});this.shadows&&f(this.shadows,function(a){H(a,{marginLeft:d+1,marginTop:z+1})});this.inverted&&f(b.childNodes,function(c){a.invertChild(c,b)});if("SPAN"===b.tagName){var l=this.rotation,u=e(this.textWidth),q=t&&t.whiteSpace,A=[l,x,b.innerHTML,this.textWidth, -this.textAlign].join();A!==this.cTT&&(t=a.fontMetrics(b.style.fontSize).b,p(l)&&this.setSpanRotation(l,n,t),H(b,{width:"",whiteSpace:q||"nowrap"}),b.offsetWidth>u&&/[ \-]/.test(b.textContent||b.innerText)&&H(b,{width:u+"px",display:"block",whiteSpace:q||"normal"}),this.getSpanCorrection(b.offsetWidth,t,n,l,x));H(b,{left:h+(this.xCorr||0)+"px",top:m+(this.yCorr||0)+"px"});w&&(t=b.offsetHeight);this.cTT=A}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,d){var c={},k=this.renderer.getTransformKey(); -c[k]=c.transform="rotate("+a+"deg)";c[k+(r?"Origin":"-origin")]=c.transformOrigin=100*b+"% "+d+"px";H(this.element,c)},getSpanCorrection:function(a,b,d){this.xCorr=-a*d;this.yCorr=-b}});l(h.prototype,{getTransformKey:function(){return n&&!/Edge/.test(m.navigator.userAgent)?"-ms-transform":w?"-webkit-transform":r?"MozTransform":m.opera?"-o-transform":""},html:function(a,b,k){var c=this.createElement("span"),e=c.element,h=c.renderer,m=h.isSVG,w=function(a,b){f(["opacity","visibility"],function(c){d(a, -c+"Setter",function(a,c,d,k){a.call(this,c,d,k);b[d]=c})})};c.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;this.textStr=a;e.innerHTML=u(a,"");c.htmlUpdateTransform()};m&&w(c,c.element.style);c.xSetter=c.ySetter=c.alignSetter=c.rotationSetter=function(a,b){"align"===b&&(b="textAlign");c[b]=a;c.htmlUpdateTransform()};c.attr({text:a,x:Math.round(b),y:Math.round(k)}).css({fontFamily:this.style.fontFamily,fontSize:this.style.fontSize,position:"absolute"});e.style.whiteSpace="nowrap";c.css= -c.htmlCss;m&&(c.add=function(a){var b,d=h.box.parentNode,k=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)k.push(a),a=a.parentGroup;f(k.reverse(),function(a){function e(g,b){a[b]=g;n?q[h.getTransformKey()]="translate("+(a.x||a.translateX)+"px,"+(a.y||a.translateY)+"px)":"translateX"===b?q.left=g+"px":q.top=g+"px";a.doTransform=!0}var q,g=E(a.element,"class");g&&(g={className:g});b=a.div=a.div||D("div",g,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px",display:a.display, -opacity:a.opacity,pointerEvents:a.styles&&a.styles.pointerEvents},b||d);q=b.style;l(a,{classSetter:function(a){return function(g){this.element.setAttribute("class",g);a.className=g}}(b),on:function(){k[0].div&&c.on.apply({element:k[0].div},arguments);return a},translateXSetter:e,translateYSetter:e});w(a,q)})}}else b=d;b.appendChild(e);c.added=!0;c.alignOnAdd&&c.htmlUpdateTransform();return c});return c}})})(M);(function(a){function E(){var n=a.defaultOptions.global,l=r.moment;if(n.timezone){if(l)return function(a){return-l.tz(a, -n.timezone).utcOffset()};a.error(25)}return n.useUTC&&n.getTimezoneOffset}function D(){var n=a.defaultOptions.global,f,u=n.useUTC,e=u?"getUTC":"get",h=u?"setUTC":"set",m="Minutes Hours Day Date Month FullYear".split(" "),d=m.concat(["Milliseconds","Seconds"]);a.Date=f=n.Date||r.Date;f.hcTimezoneOffset=u&&n.timezoneOffset;f.hcGetTimezoneOffset=E();f.hcHasTimeZone=!(!f.hcTimezoneOffset&&!f.hcGetTimezoneOffset);f.hcMakeTime=function(a,b,d,e,h,m){var c;u?(c=f.UTC.apply(0,arguments),c+=p(c)):c=(new f(a, -b,l(d,1),l(e,0),l(h,0),l(m,0))).getTime();return c};for(n=0;nb&&e-k*zm&&(p=Math.round((h-e)/Math.cos(b*r)));else if(h=e+(1-k)*z,e-k*zm&&(I=m-a.x+I*k,x=-1),I=Math.min(B,I),II||f.autoRotation&&(c.styles||{}).width)p=I;p&&(t.width=p,(n.style||{}).textOverflow||(t.textOverflow="ellipsis"),c.css(t))},getPosition:function(a,f,l,e){var h=this.axis,m=h.chart,d=e&&m.oldChartHeight||m.chartHeight;return{x:a?h.translate(f+l,null,null,e)+h.transB:h.left+h.offset+(h.opposite?(e&&m.oldChartWidth||m.chartWidth)-h.right-h.left:0),y:a?d-h.bottom+h.offset-(h.opposite?h.height:0):d-h.translate(f+l,null,null,e)-h.transB}},getLabelPosition:function(a, -f,l,e,h,m,d,c){var b=this.axis,k=b.transA,z=b.reversed,B=b.staggerLines,n=b.tickRotCorr||{x:0,y:0},x=h.y,u=e||b.reserveSpaceDefault?0:-b.labelOffset*("center"===b.labelAlign?.5:1);D(x)||(x=0===b.side?l.rotation?-8:-l.getBBox().height:2===b.side?n.y+8:Math.cos(l.rotation*r)*(n.y-l.getBBox(!1,0).height/2));a=a+h.x+u+n.x-(m&&e?m*k*(z?-1:1):0);f=f+x-(m&&!e?m*k*(z?1:-1):0);B&&(l=d/(c||1)%B,b.opposite&&(l=B-l-1),f+=b.labelOffset/B*l);return{x:a,y:Math.round(f)}},getMarkPath:function(a,f,l,e,h,m){return m.crispLine(["M", -a,f,"L",a+(h?0:-l),f+(h?l:0)],e)},renderGridLine:function(a,f,l){var e=this.axis,h=e.options,m=this.gridLine,d={},c=this.pos,b=this.type,k=e.tickmarkOffset,z=e.chart.renderer,B=b?b+"Grid":"grid",n=h[B+"LineWidth"],x=h[B+"LineColor"],h=h[B+"LineDashStyle"];m||(d.stroke=x,d["stroke-width"]=n,h&&(d.dashstyle=h),b||(d.zIndex=1),a&&(d.opacity=0),this.gridLine=m=z.path().attr(d).addClass("highcharts-"+(b?b+"-":"")+"grid-line").add(e.gridGroup));if(!a&&m&&(a=e.getPlotLinePath(c+k,m.strokeWidth()*l,a,!0)))m[this.isNew? -"attr":"animate"]({d:a,opacity:f})},renderMark:function(a,f,u){var e=this.axis,h=e.options,m=e.chart.renderer,d=this.type,c=d?d+"Tick":"tick",b=e.tickSize(c),k=this.mark,z=!k,B=a.x;a=a.y;var n=l(h[c+"Width"],!d&&e.isXAxis?1:0),h=h[c+"Color"];b&&(e.opposite&&(b[0]=-b[0]),z&&(this.mark=k=m.path().addClass("highcharts-"+(d?d+"-":"")+"tick").add(e.axisGroup),k.attr({stroke:h,"stroke-width":n})),k[z?"attr":"animate"]({d:this.getMarkPath(B,a,b[0],k.strokeWidth()*u,e.horiz,m),opacity:f}))},renderLabel:function(a, -f,u,e){var h=this.axis,m=h.horiz,d=h.options,c=this.label,b=d.labels,k=b.step,h=h.tickmarkOffset,z=!0,B=a.x;a=a.y;c&&p(B)&&(c.xy=a=this.getLabelPosition(B,a,c,m,b,h,e,k),this.isFirst&&!this.isLast&&!l(d.showFirstLabel,1)||this.isLast&&!this.isFirst&&!l(d.showLastLabel,1)?z=!1:!m||b.step||b.rotation||f||0===u||this.handleOverflow(a),k&&e%k&&(z=!1),z&&p(a.y)?(a.opacity=u,c[this.isNewLabel?"attr":"animate"](a),this.isNewLabel=!1):(c.attr("y",-9999),this.isNewLabel=!0))},render:function(a,f,u){var e= -this.axis,h=e.horiz,m=this.getPosition(h,this.pos,e.tickmarkOffset,f),d=m.x,c=m.y,e=h&&d===e.pos+e.len||!h&&c===e.pos?-1:1;u=l(u,1);this.isActive=!0;this.renderGridLine(f,u,e);this.renderMark(m,u,e);this.renderLabel(m,f,u,a);this.isNew=!1},destroy:function(){H(this,this.axis)}}})(M);var V=function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.color,l=a.correctFloat,r=a.defaultOptions,n=a.defined,w=a.deg2rad,u=a.destroyObjectProperties,e=a.each,h=a.extend,m=a.fireEvent,d=a.format, -c=a.getMagnitude,b=a.grep,k=a.inArray,z=a.isArray,B=a.isNumber,I=a.isString,x=a.merge,K=a.normalizeTickInterval,t=a.objectEach,C=a.pick,N=a.removeEvent,q=a.splat,A=a.syncTimeout,F=a.Tick,G=function(){this.init.apply(this,arguments)};a.extend(G.prototype,{defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,labels:{enabled:!0,style:{color:"#666666",cursor:"default",fontSize:"11px"}, -x:0},maxPadding:.01,minorTickLength:2,minorTickPosition:"outside",minPadding:.01,startOfWeek:1,startOnTick:!1,tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",title:{align:"middle",style:{color:"#666666"}},type:"linear",minorGridLineColor:"#f2f2f2",minorGridLineWidth:1,minorTickColor:"#999999",lineColor:"#ccd6eb",lineWidth:1,gridLineColor:"#e6e6e6",tickColor:"#ccd6eb"},defaultYAxisOptions:{endOnTick:!0,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8},maxPadding:.05, -minPadding:.05,startOnTick:!0,title:{rotation:270,text:"Values"},stackLabels:{allowOverlap:!1,enabled:!1,formatter:function(){return a.numberFormat(this.total,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"#000000",textOutline:"1px contrast"}},gridLineWidth:1,lineWidth:0},defaultLeftAxisOptions:{labels:{x:-15},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45], -x:0},title:{rotation:0}},init:function(a,b){var g=b.isX,v=this;v.chart=a;v.horiz=a.inverted&&!v.isZAxis?!g:g;v.isXAxis=g;v.coll=v.coll||(g?"xAxis":"yAxis");v.opposite=b.opposite;v.side=b.side||(v.horiz?v.opposite?0:2:v.opposite?1:3);v.setOptions(b);var c=this.options,d=c.type;v.labelFormatter=c.labels.formatter||v.defaultLabelFormatter;v.userOptions=b;v.minPixelPadding=0;v.reversed=c.reversed;v.visible=!1!==c.visible;v.zoomEnabled=!1!==c.zoomEnabled;v.hasNames="category"===d||!0===c.categories;v.categories= -c.categories||v.hasNames;v.names=v.names||[];v.plotLinesAndBandsGroups={};v.isLog="logarithmic"===d;v.isDatetimeAxis="datetime"===d;v.positiveValuesOnly=v.isLog&&!v.allowNegativeLog;v.isLinked=n(c.linkedTo);v.ticks={};v.labelEdge=[];v.minorTicks={};v.plotLinesAndBands=[];v.alternateBands={};v.len=0;v.minRange=v.userMinRange=c.minRange||c.maxZoom;v.range=c.range;v.offset=c.offset||0;v.stacks={};v.oldStacks={};v.stacksTouched=0;v.max=null;v.min=null;v.crosshair=C(c.crosshair,q(a.options.tooltip.crosshairs)[g? -0:1],!1);b=v.options.events;-1===k(v,a.axes)&&(g?a.axes.splice(a.xAxis.length,0,v):a.axes.push(v),a[v.coll].push(v));v.series=v.series||[];a.inverted&&!v.isZAxis&&g&&void 0===v.reversed&&(v.reversed=!0);t(b,function(a,g){E(v,g,a)});v.lin2log=c.linearToLogConverter||v.lin2log;v.isLog&&(v.val2lin=v.log2lin,v.lin2val=v.lin2log)},setOptions:function(a){this.options=x(this.defaultOptions,"yAxis"===this.coll&&this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions, -this.defaultLeftAxisOptions][this.side],x(r[this.coll],a))},defaultLabelFormatter:function(){var g=this.axis,b=this.value,c=g.categories,k=this.dateTimeLabelFormat,e=r.lang,q=e.numericSymbols,e=e.numericSymbolMagnitude||1E3,h=q&&q.length,m,z=g.options.labels.format,g=g.isLog?Math.abs(b):g.tickInterval;if(z)m=d(z,this);else if(c)m=b;else if(k)m=a.dateFormat(k,b);else if(h&&1E3<=g)for(;h--&&void 0===m;)c=Math.pow(e,h+1),g>=c&&0===10*b%c&&null!==q[h]&&0!==b&&(m=a.numberFormat(b/c,-1)+q[h]);void 0=== -m&&(m=1E4<=Math.abs(b)?a.numberFormat(b,-1):a.numberFormat(b,-1,void 0,""));return m},getSeriesExtremes:function(){var a=this,v=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.threshold=null;a.softThreshold=!a.isXAxis;a.buildStacks&&a.buildStacks();e(a.series,function(g){if(g.visible||!v.options.chart.ignoreHiddenSeries){var c=g.options,d=c.threshold,k;a.hasVisibleSeries=!0;a.positiveValuesOnly&&0>=d&&(d=null);if(a.isXAxis)c=g.xData,c.length&&(g=p(c),k=H(c),B(g)||g instanceof Date||(c=b(c,B), -g=p(c)),a.dataMin=Math.min(C(a.dataMin,c[0],g),g),a.dataMax=Math.max(C(a.dataMax,c[0],k),k));else if(g.getExtremes(),k=g.dataMax,g=g.dataMin,n(g)&&n(k)&&(a.dataMin=Math.min(C(a.dataMin,g),g),a.dataMax=Math.max(C(a.dataMax,k),k)),n(d)&&(a.threshold=d),!c.softThreshold||a.positiveValuesOnly)a.softThreshold=!1}})},translate:function(a,b,c,d,k,e){var g=this.linkedParent||this,v=1,q=0,h=d?g.oldTransA:g.transA;d=d?g.oldMin:g.min;var m=g.minPixelPadding;k=(g.isOrdinal||g.isBroken||g.isLog&&k)&&g.lin2val; -h||(h=g.transA);c&&(v*=-1,q=g.len);g.reversed&&(v*=-1,q-=v*(g.sector||g.len));b?(a=(a*v+q-m)/h+d,k&&(a=g.lin2val(a))):(k&&(a=g.val2lin(a)),a=B(d)?v*(a-d)*h+q+v*m+(B(e)?h*e:0):void 0);return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d,k){var g=this.chart,v=this.left,q=this.top,e,h,m=c&&g.oldChartHeight||g.chartHeight,z=c&&g.oldChartWidth|| -g.chartWidth,A;e=this.transB;var t=function(a,g,b){if(ab)d?a=Math.min(Math.max(g,a),b):A=!0;return a};k=C(k,this.translate(a,null,null,c));a=c=Math.round(k+e);e=h=Math.round(m-k-e);B(k)?this.horiz?(e=q,h=m-this.bottom,a=c=t(a,v,v+this.width)):(a=v,c=z-this.right,e=h=t(e,q,q+this.height)):(A=!0,d=!1);return A&&!d?null:g.renderer.crispLine(["M",a,e,"L",c,h],b||1)},getLinearTickPositions:function(a,b,c){var g,v=l(Math.floor(b/a)*a);c=l(Math.ceil(c/a)*a);var d=[],k;l(v+a)===v&&(k=20);if(this.single)return[b]; -for(b=v;b<=c;){d.push(b);b=l(b+a,k);if(b===g)break;g=b}return d},getMinorTickInterval:function(){var a=this.options;return!0===a.minorTicks?C(a.minorTickInterval,"auto"):!1===a.minorTicks?null:a.minorTickInterval},getMinorTickPositions:function(){var a=this,b=a.options,c=a.tickPositions,d=a.minorTickInterval,k=[],q=a.pointRangePadding||0,h=a.min-q,q=a.max+q,m=q-h;if(m&&m/d=this.minRange,t=this.minRange,d=(t-c+b)/2,d=[b-d,C(a.min,b-d)],k&&(d[2]=this.isLog?this.log2lin(this.dataMin):this.dataMin),b=H(d),c=[b+t,C(a.max,b+t)],k&&(c[2]=this.isLog?this.log2lin(this.dataMax):this.dataMax),c=p(c),c-b=p?(r=p,f=0):b.dataMax<=p&&(w=p,x=0)),b.min= -C(N,r,b.dataMin),b.max=C(D,w,b.dataMax));q&&(b.positiveValuesOnly&&!g&&0>=Math.min(b.min,C(b.dataMin,b.min))&&a.error(10,1),b.min=l(h(b.min),15),b.max=l(h(b.max),15));b.range&&n(b.max)&&(b.userMin=b.min=N=Math.max(b.dataMin,b.minFromRange()),b.userMax=D=b.max,b.range=null);m(b,"foundExtremes");b.beforePadding&&b.beforePadding();b.adjustForMinRange();!(G||b.axisPointRange||b.usePercentage||t)&&n(b.min)&&n(b.max)&&(h=b.max-b.min)&&(!n(N)&&f&&(b.min-=h*f),!n(D)&&x&&(b.max+=h*x));B(k.softMin)&&!B(b.userMin)&& -(b.min=Math.min(b.min,k.softMin));B(k.softMax)&&!B(b.userMax)&&(b.max=Math.max(b.max,k.softMax));B(k.floor)&&(b.min=Math.max(b.min,k.floor));B(k.ceiling)&&(b.max=Math.min(b.max,k.ceiling));I&&n(b.dataMin)&&(p=p||0,!n(N)&&b.min=p?b.min=p:!n(D)&&b.max>p&&b.dataMax<=p&&(b.max=p));b.tickInterval=b.min===b.max||void 0===b.min||void 0===b.max?1:t&&!F&&u===b.linkedParent.options.tickPixelInterval?F=b.linkedParent.tickInterval:C(F,this.tickAmount?(b.max-b.min)/Math.max(this.tickAmount-1,1): -void 0,G?1:(b.max-b.min)*u/Math.max(b.len,u));A&&!g&&e(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();b.postProcessTickInterval&&(b.tickInterval=b.postProcessTickInterval(b.tickInterval));b.pointRange&&!F&&(b.tickInterval=Math.max(b.pointRange,b.tickInterval));g=C(k.minTickInterval,b.isDatetimeAxis&&b.closestPointRange);!F&&b.tickIntervalb.tickInterval&&1E3b.max)),!!this.tickAmount));this.tickAmount||(b.tickInterval=b.unsquish());this.setTickPositions()},setTickPositions:function(){var a=this.options,b,c=a.tickPositions;b=this.getMinorTickInterval();var d=a.tickPositioner,k=a.startOnTick,q=a.endOnTick;this.tickmarkOffset=this.categories&&"between"===a.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===b&&this.tickInterval?this.tickInterval/ -5:b;this.single=this.min===this.max&&n(this.min)&&!this.tickAmount&&(parseInt(this.min,10)===this.min||!1!==a.allowDecimals);this.tickPositions=b=c&&c.slice();!b&&(b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),b.length>this.len&&(b= -[b[0],b.pop()],b[0]===b[1]&&(b.length=1)),this.tickPositions=b,d&&(d=d.apply(this,[this.min,this.max])))&&(this.tickPositions=b=d);this.paddedTicks=b.slice(0);this.trimTicks(b,k,q);this.isLinked||(this.single&&2>b.length&&(this.min-=.5,this.max+=.5),c||d||this.adjustTickAmount())},trimTicks:function(a,b,c){var g=a[0],d=a[a.length-1],k=this.minPointOffset||0;if(!this.isLinked){if(b&&-Infinity!==g)this.min=g;else for(;this.min-k>a[0];)a.shift();if(c)this.max=d;else for(;this.max+kb&&(this.finalTickAmt=b,b=5);this.tickAmount=b},adjustTickAmount:function(){var a=this.tickInterval,b=this.tickPositions,c=this.tickAmount,d=this.finalTickAmt,k=b&&b.length,q=C(this.threshold,this.softThreshold?0:null);if(this.hasData()){if(kc&&(this.tickInterval*= -2,this.setTickPositions());if(n(d)){for(a=c=b.length;a--;)(3===d&&1===a%2||2>=d&&0d&&(a=d)),n(c)&&(bd&&(b=d))),this.displayBtn=void 0!==a||void 0!==b,this.setExtremes(a,b,!1,void 0,{trigger:"zoom"});return!0},setAxisSize:function(){var b=this.chart,c=this.options,d=c.offsets||[0,0,0,0],k=this.horiz,q=this.width=Math.round(a.relativeLength(C(c.width,b.plotWidth-d[3]+d[1]),b.plotWidth)),e=this.height=Math.round(a.relativeLength(C(c.height, -b.plotHeight-d[0]+d[2]),b.plotHeight)),h=this.top=Math.round(a.relativeLength(C(c.top,b.plotTop+d[0]),b.plotHeight,b.plotTop)),c=this.left=Math.round(a.relativeLength(C(c.left,b.plotLeft+d[3]),b.plotWidth,b.plotLeft));this.bottom=b.chartHeight-e-h;this.right=b.chartWidth-q-c;this.len=Math.max(k?q:e,0);this.pos=k?c:h},getExtremes:function(){var a=this.isLog,b=this.lin2log;return{min:a?l(b(this.min)):this.min,max:a?l(b(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin, -userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,g=this.lin2log,c=b?g(this.min):this.min,b=b?g(this.max):this.max;null===a?a=c:c>a?a=c:ba?"right":195a?"left":"center"},tickSize:function(a){var b=this.options,g=b[a+"Length"],c=C(b[a+"Width"],"tick"===a&&this.isXAxis?1:0);if(c&&g)return"inside"===b[a+"Position"]&&(g=-g),[g,c]},labelMetrics:function(){var a= -this.tickPositions&&this.tickPositions[0]||0;return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize,this.ticks[a]&&this.ticks[a].label)},unsquish:function(){var a=this.options.labels,b=this.horiz,c=this.tickInterval,d=c,k=this.len/(((this.categories?1:0)+this.max-this.min)/c),q,h=a.rotation,m=this.labelMetrics(),z,A=Number.MAX_VALUE,t,x=function(a){a/=k||1;a=1=a)z=x(Math.abs(m.h/Math.sin(w*a))),b=z+Math.abs(a/360),b(c.step||0)&&!c.rotation&&(this.staggerLines||1)*this.len/d||!b&&(c.style&&parseInt(c.style.width,10)||k&&k-a.spacing[3]|| -.33*a.chartWidth)},renderUnsquish:function(){var a=this.chart,b=a.renderer,c=this.tickPositions,d=this.ticks,k=this.options.labels,q=this.horiz,h=this.getSlotWidth(),m=Math.max(1,Math.round(h-2*(k.padding||5))),z={},A=this.labelMetrics(),t=k.style&&k.style.textOverflow,f,F=0,l,B;I(k.rotation)||(z.rotation=k.rotation||0);e(c,function(a){(a=d[a])&&a.labelLength>F&&(F=a.labelLength)});this.maxLabelLength=F;if(this.autoRotation)F>m&&F>A.h?z.rotation=this.labelRotation:this.labelRotation=0;else if(h&& -(f={width:m+"px"},!t))for(f.textOverflow="clip",l=c.length;!q&&l--;)if(B=c[l],m=d[B].label)m.styles&&"ellipsis"===m.styles.textOverflow?m.css({textOverflow:"clip"}):d[B].labelLength>h&&m.css({width:h+"px"}),m.getBBox().height>this.len/c.length-(A.h-A.f)&&(m.specCss={textOverflow:"ellipsis"});z.rotation&&(f={width:(F>.5*a.chartHeight?.33*a.chartHeight:a.chartHeight)+"px"},t||(f.textOverflow="ellipsis"));if(this.labelAlign=k.align||this.autoLabelAlign(this.labelRotation))z.align=this.labelAlign;e(c, -function(a){var b=(a=d[a])&&a.label;b&&(b.attr(z),f&&b.css(x(f,b.specCss)),delete b.specCss,a.rotation=z.rotation)});this.tickRotCorr=b.rotCorr(A.b,this.labelRotation||0,0!==this.side)},hasData:function(){return this.hasVisibleSeries||n(this.min)&&n(this.max)&&this.tickPositions&&0=this.min&&a<=this.max)g[a]||(g[a]=new F(this,a)),d&&g[a].isNew&&g[a].render(b,!0,.1),g[a].render(b)},render:function(){var b= -this,c=b.chart,d=b.options,k=b.isLog,q=b.lin2log,h=b.isLinked,m=b.tickPositions,z=b.axisTitle,x=b.ticks,f=b.minorTicks,l=b.alternateBands,C=d.stackLabels,n=d.alternateGridColor,u=b.tickmarkOffset,G=b.axisLine,p=b.showAxis,I=D(c.renderer.globalAnimation),r,w;b.labelEdge.length=0;b.overlap=!1;e([x,f,l],function(a){t(a,function(a){a.isActive=!1})});if(b.hasData()||h)b.minorTickInterval&&!b.categories&&e(b.getMinorTickPositions(),function(a){b.renderMinorTick(a)}),m.length&&(e(m,function(a,c){b.renderTick(a, -c)}),u&&(0===b.min||b.single)&&(x[-1]||(x[-1]=new F(b,-1,null,!0)),x[-1].render(-1))),n&&e(m,function(d,g){w=void 0!==m[g+1]?m[g+1]+u:b.max-u;0===g%2&&d=h.second?0:C*Math.floor(x.getMilliseconds()/C));if(t>=h.second)x[D.hcSetSeconds](t>=h.minute? -0:C*Math.floor(x.getSeconds()/C));if(t>=h.minute)x[D.hcSetMinutes](t>=h.hour?0:C*Math.floor(x[D.hcGetMinutes]()/C));if(t>=h.hour)x[D.hcSetHours](t>=h.day?0:C*Math.floor(x[D.hcGetHours]()/C));if(t>=h.day)x[D.hcSetDate](t>=h.month?1:C*Math.floor(x[D.hcGetDate]()/C));t>=h.month&&(x[D.hcSetMonth](t>=h.year?0:C*Math.floor(x[D.hcGetMonth]()/C)),n=x[D.hcGetFullYear]());if(t>=h.year)x[D.hcSetFullYear](n-n%C);if(t===h.week)x[D.hcSetDate](x[D.hcGetDate]()-x[D.hcGetDay]()+e(b,1));n=x[D.hcGetFullYear]();b=x[D.hcGetMonth](); -var A=x[D.hcGetDate](),F=x[D.hcGetHours]();d=x.getTime();D.hcHasTimeZone&&(q=(!B||!!D.hcGetTimezoneOffset)&&(c-d>4*h.month||w(d)!==w(c)),N=w(x),x=new D(d+N));B=x.getTime();for(d=1;Bk.length&&l(k,function(a){0===a%18E5&&"000000000"===H("%H%M%S%L",a)&&(m[a]="day")})}k.info=r(a,{higherRanks:m,totalRange:t*C});return k}; -E.prototype.normalizeTimeTickInterval=function(a,d){var c=d||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2,3,4,6]],["year",null]];d=c[c.length-1];var b=h[d[0]],k=d[1],e;for(e=0;er&&(!w||z<=n)&&void 0!==z&&d.push(z),z>n&& -(B=!0),z=k;else r=h(r),n=h(n),a=w?this.getMinorTickInterval():l.tickInterval,a=f("auto"===a?null:a,this._minorAutoInterval,l.tickPixelInterval/(w?5:1)*(n-r)/((w?e/this.tickPositions.length:e)||1)),a=p(a,null,D(a)),d=H(this.getLinearTickPositions(a,r,n),m),w||(this._minorAutoInterval=a/5);w||(this.tickInterval=a);return d};E.prototype.log2lin=function(a){return Math.log(a)/Math.LN10};E.prototype.lin2log=function(a){return Math.pow(10,a)}})(M);(function(a,E){var D=a.arrayMax,H=a.arrayMin,p=a.defined, -f=a.destroyObjectProperties,l=a.each,r=a.erase,n=a.merge,w=a.pick;a.PlotLineOrBand=function(a,e){this.axis=a;e&&(this.options=e,this.id=e.id)};a.PlotLineOrBand.prototype={render:function(){var f=this,e=f.axis,h=e.horiz,m=f.options,d=m.label,c=f.label,b=m.to,k=m.from,z=m.value,l=p(k)&&p(b),r=p(z),x=f.svgElem,K=!x,t=[],C=m.color,N=w(m.zIndex,0),q=m.events,t={"class":"highcharts-plot-"+(l?"band ":"line ")+(m.className||"")},A={},F=e.chart.renderer,G=l?"bands":"lines",g=e.log2lin;e.isLog&&(k=g(k),b=g(b), -z=g(z));r?(t={stroke:C,"stroke-width":m.width},m.dashStyle&&(t.dashstyle=m.dashStyle)):l&&(C&&(t.fill=C),m.borderWidth&&(t.stroke=m.borderColor,t["stroke-width"]=m.borderWidth));A.zIndex=N;G+="-"+N;(C=e.plotLinesAndBandsGroups[G])||(e.plotLinesAndBandsGroups[G]=C=F.g("plot-"+G).attr(A).add());K&&(f.svgElem=x=F.path().attr(t).add(C));if(r)t=e.getPlotLinePath(z,x.strokeWidth());else if(l)t=e.getPlotBandPath(k,b,m);else return;K&&t&&t.length?(x.attr({d:t}),q&&a.objectEach(q,function(a,b){x.on(b,function(a){q[b].apply(f, -[a])})})):x&&(t?(x.show(),x.animate({d:t})):(x.hide(),c&&(f.label=c=c.destroy())));d&&p(d.text)&&t&&t.length&&0this.max&& -e>this.max;if(m&&h)for(a&&(k=m.toString()===h.toString(),b=0),a=0;aA-h?A:A-h);else if(z)k[a]=Math.max(e,g+h+d>c?g:g+h);else return!1},C=function(a,c,d,g){var e;gc-b?e=!1:k[a]=gc-d/2?c-d-2:g-d/2;return e},p=function(a){var b=f;f=x;x=b;m=a},q=function(){!1!==t.apply(0,f)?!1!==C.apply(0,x)||m||(p(!0),q()):m?k.x=k.y=0:(p(!0),q())};(c.inverted||1q&&(h=!1);a=(e.series&& -e.series.yAxis&&e.series.yAxis.pos)+(e.plotY||0);a-=b.plotTop;c.push({target:e.isHeader?b.plotHeight+l:a,rank:e.isHeader?1:0,size:z.tt.getBBox().height+1,point:e,x:q,tt:t})}});this.cleanSplit();a.distribute(c,b.plotHeight+l);D(c,function(a){var c=a.point,d=c.series;a.tt.attr({visibility:void 0===a.pos?"hidden":"inherit",x:h||c.isHeader?a.x:c.plotX+b.plotLeft+n(f.distance,16),y:a.pos+b.plotTop,anchorX:c.isHeader?c.plotX+b.plotLeft:c.plotX+d.xAxis.pos,anchorY:c.isHeader?a.pos+b.plotTop-15:c.plotY+d.yAxis.pos})})}, -updatePosition:function(a){var e=this.chart,d=this.getLabel(),d=(this.options.positioner||this.getPosition).call(this,d.width,d.height,a);this.move(Math.round(d.x),Math.round(d.y||0),a.plotX+e.plotLeft,a.plotY+e.plotTop)},getDateFormat:function(a,m,d,c){var b=E("%m-%d %H:%M:%S.%L",m),k,h,f={millisecond:15,second:12,minute:9,hour:6,day:3},l="millisecond";for(h in e){if(a===e.week&&+E("%w",m)===d&&"00:00:00.000"===b.substr(6)){h="week";break}if(e[h]>a){h=l;break}if(f[h]&&b.substr(f[h])!=="01-01 00:00:00.000".substr(f[h]))break; -"week"!==h&&(l=h)}h&&(k=c[h]);return k},getXDateFormat:function(a,e,d){e=e.dateTimeLabelFormats;var c=d&&d.closestPointRange;return(c?this.getDateFormat(c,a.x,d.options.startOfWeek,e):e.day)||e.year},tooltipFooterHeaderFormatter:function(a,e){e=e?"footer":"header";var d=a.series,c=d.tooltipOptions,b=c.xDateFormat,k=d.xAxis,h=k&&"datetime"===k.options.type&&f(a.key),m=c[e+"Format"];h&&!b&&(b=this.getXDateFormat(a,c,k));h&&b&&D(a.point&&a.point.tooltipDateKeys||["key"],function(a){m=m.replace("{point."+ -a+"}","{point."+a+":"+b+"}")});return p(m,{point:a,series:d})},bodyFormatter:function(a){return l(a,function(a){var d=a.series.tooltipOptions;return(d[(a.point.formatPrefix||"point")+"Formatter"]||a.point.tooltipFormatter).call(a.point,d[(a.point.formatPrefix||"point")+"Format"])})}}})(M);(function(a){var E=a.addEvent,D=a.attr,H=a.charts,p=a.color,f=a.css,l=a.defined,r=a.each,n=a.extend,w=a.find,u=a.fireEvent,e=a.isObject,h=a.offset,m=a.pick,d=a.splat,c=a.Tooltip;a.Pointer=function(a,c){this.init(a, -c)};a.Pointer.prototype={init:function(a,d){this.options=d;this.chart=a;this.runChartClick=d.chart.events&&!!d.chart.events.click;this.pinchDown=[];this.lastValidTouch={};c&&(a.tooltip=new c(a,d.tooltip),this.followTouchMove=m(d.tooltip.followTouchMove,!0));this.setDOMEvents()},zoomOption:function(a){var b=this.chart,c=b.options.chart,d=c.zoomType||"",b=b.inverted;/touch/.test(a.type)&&(d=m(c.pinchType,d));this.zoomX=a=/x/.test(d);this.zoomY=d=/y/.test(d);this.zoomHor=a&&!b||d&&b;this.zoomVert=d&& -!b||a&&b;this.hasZoom=a||d},normalize:function(a,c){var b;b=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:a;c||(this.chartPosition=c=h(this.chart.container));return n(a,{chartX:Math.round(b.pageX-c.left),chartY:Math.round(b.pageY-c.top)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};r(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},findNearestKDPoint:function(a,c,d){var b;r(a,function(a){var k= -!(a.noSharedTooltip&&c)&&0>a.options.findNearestPointBy.indexOf("y");a=a.searchPoint(d,k);if((k=e(a,!0))&&!(k=!e(b,!0)))var k=b.distX-a.distX,h=b.dist-a.dist,m=(a.series.group&&a.series.group.zIndex)-(b.series.group&&b.series.group.zIndex),k=0<(0!==k&&c?k:0!==h?h:0!==m?m:b.series.index>a.series.index?-1:1);k&&(b=a)});return b},getPointFromEvent:function(a){a=a.target;for(var b;a&&!b;)b=a.point,a=a.parentNode;return b},getChartCoordinatesFromPoint:function(a,c){var b=a.series,d=b.xAxis,b=b.yAxis,k= -m(a.clientX,a.plotX);if(d&&b)return c?{chartX:d.len+d.pos-k,chartY:b.len+b.pos-a.plotY}:{chartX:k+d.pos,chartY:a.plotY+b.pos}},getHoverData:function(b,c,d,h,f,l,n){var k,z=[],x=n&&n.isBoosting;h=!(!h||!b);n=c&&!c.stickyTracking?[c]:a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking,!0)&&a.stickyTracking});c=(k=h?b:this.findNearestKDPoint(n,f,l))&&k.series;k&&(f&&!c.noSharedTooltip?(n=a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking, -!0)&&!a.noSharedTooltip}),r(n,function(a){var b=w(a.points,function(a){return a.x===k.x&&!a.isNull});e(b)&&(x&&(b=a.getPoint(b)),z.push(b))})):z.push(k));return{hoverPoint:k,hoverSeries:c,hoverPoints:z}},runPointActions:function(b,c){var d=this.chart,k=d.tooltip&&d.tooltip.options.enabled?d.tooltip:void 0,e=k?k.shared:!1,h=c||d.hoverPoint,f=h&&h.series||d.hoverSeries,f=this.getHoverData(h,f,d.series,!!c||f&&f.directTouch&&this.isDirectTouch,e,b,{isBoosting:d.isBoosting}),l,h=f.hoverPoint;l=f.hoverPoints; -c=(f=f.hoverSeries)&&f.tooltipOptions.followPointer;e=e&&f&&!f.noSharedTooltip;if(h&&(h!==d.hoverPoint||k&&k.isHidden)){r(d.hoverPoints||[],function(b){-1===a.inArray(b,l)&&b.setState()});r(l||[],function(a){a.setState("hover")});if(d.hoverSeries!==f)f.onMouseOver();d.hoverPoint&&d.hoverPoint.firePointEvent("mouseOut");if(!h.series)return;h.firePointEvent("mouseOver");d.hoverPoints=l;d.hoverPoint=h;k&&k.refresh(e?l:h,b)}else c&&k&&!k.isHidden&&(h=k.getAnchor([{}],b),k.updatePosition({plotX:h[0],plotY:h[1]})); -this.unDocMouseMove||(this.unDocMouseMove=E(d.container.ownerDocument,"mousemove",function(b){var c=H[a.hoverChartIndex];if(c)c.pointer.onDocumentMouseMove(b)}));r(d.axes,function(c){var d=m(c.crosshair.snap,!0),k=d?a.find(l,function(a){return a.series[c.coll]===c}):void 0;k||!d?c.drawCrosshair(b,k):c.hideCrosshair()})},reset:function(a,c){var b=this.chart,k=b.hoverSeries,e=b.hoverPoint,h=b.hoverPoints,m=b.tooltip,f=m&&m.shared?h:e;a&&f&&r(d(f),function(b){b.series.isCartesian&&void 0===b.plotX&& -(a=!1)});if(a)m&&f&&(m.refresh(f),e&&(e.setState(e.state,!0),r(b.axes,function(a){a.crosshair&&a.drawCrosshair(null,e)})));else{if(e)e.onMouseOut();h&&r(h,function(a){a.setState()});if(k)k.onMouseOut();m&&m.hide(c);this.unDocMouseMove&&(this.unDocMouseMove=this.unDocMouseMove());r(b.axes,function(a){a.hideCrosshair()});this.hoverX=b.hoverPoints=b.hoverPoint=null}},scaleGroups:function(a,c){var b=this.chart,d;r(b.series,function(k){d=a||k.getPlotBox();k.xAxis&&k.xAxis.zoomEnabled&&k.group&&(k.group.attr(d), -k.markerGroup&&(k.markerGroup.attr(d),k.markerGroup.clip(c?b.clipRect:null)),k.dataLabelsGroup&&k.dataLabelsGroup.attr(d))});b.clipRect.attr(c||b.clipBox)},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,h=this.zoomHor,m=this.zoomVert,f=b.plotLeft,l=b.plotTop,n=b.plotWidth,q=b.plotHeight,A,F=this.selectionMarker,G=this.mouseDownX, -g=this.mouseDownY,v=c.panKey&&a[c.panKey+"Key"];F&&F.touch||(df+n&&(d=f+n),el+q&&(e=l+q),this.hasDragged=Math.sqrt(Math.pow(G-d,2)+Math.pow(g-e,2)),10u.max&&(f=u.max-x,v=!0);v?(F-=.8*(F-m[b][0]),q||(g-=.8*(g-m[b][1])),l()):m[b]=[F,g];C||(h[b]=w-r,h[n]=x);h=C?1/t:t;e[n]=x;e[b]=f;p[C?a?"scaleY":"scaleX":"scale"+k]=t;p["translate"+k]=h*r+(F-h*A)},pinch:function(a){var n=this,r=n.chart,u=n.pinchDown,e=a.touches,h=e.length,m=n.lastValidTouch, -d=n.hasZoom,c=n.selectionMarker,b={},k=1===h&&(n.inClass(a.target,"highcharts-tracker")&&r.runTrackerClick||n.runChartClick),z={};1c-6&&h(q||c.spacingBox.width-2*t-d.x)&&(this.itemX=t,this.itemY+=F+this.lastLineHeight+A,this.lastLineHeight=0);this.maxItemWidth=Math.max(this.maxItemWidth,m);this.lastItemY=F+this.itemY+A;this.lastLineHeight=Math.max(b,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=m:(this.itemY+=F+b+A,this.lastLineHeight=b);this.offsetWidth=q||Math.max((e?this.itemX-t-(a.checkbox?0:p):m)+t,this.offsetWidth)}, -getAllItems:function(){var a=[];f(this.chart.series,function(c){var b=c&&c.options;c&&w(b.showInLegend,p(b.linkedTo)?!1:void 0,!0)&&(a=a.concat(c.legendItems||("point"===b.legendType?c.data:c)))});return a},getAlignment:function(){var a=this.options;return a.floating?"":a.align.charAt(0)+a.verticalAlign.charAt(0)+a.layout.charAt(0)},adjustMargins:function(a,c){var b=this.chart,d=this.options,e=this.getAlignment();e&&f([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(k,h){k.test(e)&& -!p(a[h])&&(b[r[h]]=Math.max(b[r[h]],b.legend[(h+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][h]*d[h%2?"x":"y"]+w(d.margin,12)+c[h]+(0===h?b.titleOffset+b.options.title.margin:0)))})},render:function(){var a=this,c=a.chart,b=c.renderer,k=a.group,h,m,l,x,p=a.box,t=a.options,C=a.padding;a.itemX=C;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;k||(a.group=k=b.g("legend").attr({zIndex:7}).add(),a.contentGroup=b.g().attr({zIndex:1}).add(k),a.scrollGroup=b.g().add(a.contentGroup));a.renderTitle(); -h=a.getAllItems();e(h,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});t.reversed&&h.reverse();a.allItems=h;a.display=m=!!h.length;a.lastLineHeight=0;f(h,function(b){a.renderItem(b)});l=(t.width||a.offsetWidth)+C;x=a.lastItemY+a.lastLineHeight+a.titleHeight;x=a.handleOverflow(x);x+=C;p||(a.box=p=b.rect().addClass("highcharts-legend-box").attr({r:t.borderRadius}).add(k),p.isNew=!0);p.attr({stroke:t.borderColor,"stroke-width":t.borderWidth||0,fill:t.backgroundColor|| -"none"}).shadow(t.shadow);0b&&!1!==t.enabled?(this.clipHeight=l=Math.max(b-20-this.titleHeight-m,0),this.currentPage=w(this.currentPage,1),this.fullHeight=a,f(G,function(a,b){var c=a._legendItemPos[1],d=Math.round(a.legendItem.getBBox().height),g=A.length;if(!g||c-A[g-1]>l&&(F||c)!==A[g-1])A.push(F||c),g++;a.pageIx=g-1;F&&(G[b-1].pageIx=g-1);b===G.length-1&&c+d-A[g-1]>l&&(A.push(c),a.pageIx=g);c!==F&&(F=c)}),n||(n=c.clipRect=d.clipRect(0,m,9999,0),c.contentGroup.clip(n)),g(l),q||(this.nav=q=d.g().attr({zIndex:1}).add(this.group), -this.up=d.symbol("triangle",0,0,r,r).on("click",function(){c.scroll(-1,p)}).add(q),this.pager=d.text("",15,10).addClass("highcharts-legend-navigation").css(t.style).add(q),this.down=d.symbol("triangle-down",0,0,r,r).on("click",function(){c.scroll(1,p)}).add(q)),c.scroll(0),a=b):q&&(g(),this.nav=q.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return a},scroll:function(a,c){var b=this.pages,d=b.length;a=this.currentPage+a;var e=this.clipHeight,h=this.options.navigation,f=this.pager, -m=this.padding;a>d&&(a=d);0b&&(f=typeof a[0],"string"===f?e.name=a[0]:"number"===f&&(e.x=a[0]),k++);l=d.value;)d=h[++f];d&&d.color&&!this.options.color&&(this.color=d.color);return d},destroy:function(){var a=this.series.chart,h=a.hoverPoints,f;a.pointCount--;h&&(this.setState(),p(h,this),h.length||(a.hoverPoints=null));if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)u(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(f in this)this[f]=null},destroyElements:function(){for(var a=["graphic","dataLabel", -"dataLabelUpper","connector","shadowGroup"],h,f=6;f--;)h=a[f],this[h]&&(this[h]=this[h].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,color:this.color,colorIndex:this.colorIndex,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},tooltipFormatter:function(a){var e=this.series,f=e.tooltipOptions,d=w(f.valueDecimals,""),c=f.valuePrefix||"",b=f.valueSuffix||"";D(e.pointArrayMap||["y"],function(e){e="{point."+ -e;if(c||b)a=a.replace(e+"}",c+e+"}"+b);a=a.replace(e+"}",e+":,."+d+"f}")});return l(a,{point:this,series:this.series})},firePointEvent:function(a,h,m){var d=this,c=this.series.options;(c.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents();"click"===a&&c.allowPointSelect&&(m=function(a){d.select&&d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});f(this,a,h,m)},visible:!0}})(M);(function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.correctFloat, -l=a.Date,r=a.defaultOptions,n=a.defaultPlotOptions,w=a.defined,u=a.each,e=a.erase,h=a.extend,m=a.fireEvent,d=a.grep,c=a.isArray,b=a.isNumber,k=a.isString,z=a.merge,B=a.objectEach,I=a.pick,x=a.removeEvent,K=a.splat,t=a.SVGElement,C=a.syncTimeout,N=a.win;a.Series=a.seriesType("line",null,{lineWidth:2,allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},marker:{lineWidth:0,lineColor:"#ffffff",radius:4,states:{hover:{animation:{duration:50},enabled:!0,radiusPlus:2,lineWidthPlus:1},select:{fillColor:"#cccccc", -lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:{align:"center",formatter:function(){return null===this.y?"":a.numberFormat(this.y,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"contrast",textOutline:"1px contrast"},verticalAlign:"bottom",x:0,y:0,padding:5},cropThreshold:300,pointRange:0,softThreshold:!0,states:{hover:{animation:{duration:50},lineWidthPlus:1,marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1E3,findNearestPointBy:"x"}, -{isCartesian:!0,pointClass:a.Point,sorted:!0,requireSorting:!0,directTouch:!1,axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],coll:"series",init:function(a,b){var c=this,d,g=a.series,e;c.chart=a;c.options=b=c.setOptions(b);c.linkedSeries=[];c.bindAxes();h(c,{name:b.name,state:"",visible:!1!==b.visible,selected:!0===b.selected});d=b.events;B(d,function(a,b){E(c,b,a)});if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;c.getColor(); -c.getSymbol();u(c.parallelArrays,function(a){c[a+"Data"]=[]});c.setData(b.data,!1);c.isCartesian&&(a.hasCartesianSeries=!0);g.length&&(e=g[g.length-1]);c._i=I(e&&e._i,-1)+1;a.orderSeries(this.insert(g))},insert:function(a){var c=this.options.index,d;if(b(c)){for(d=a.length;d--;)if(c>=I(a[d].options.index,a[d]._i)){a.splice(d+1,0,this);break}-1===d&&a.unshift(this);d+=1}else a.push(this);return I(d,a.length-1)},bindAxes:function(){var b=this,c=b.options,d=b.chart,e;u(b.axisTypes||[],function(g){u(d[g], -function(a){e=a.options;if(c[g]===e.index||void 0!==c[g]&&c[g]===e.id||void 0===c[g]&&0===e.index)b.insert(a.series),b[g]=a,a.isDirty=!0});b[g]||b.optionalAxis===g||a.error(18,!0)})},updateParallelArrays:function(a,c){var d=a.series,e=arguments,g=b(c)?function(b){var g="y"===b&&d.toYData?d.toYData(a):a[b];d[b+"Data"][c]=g}:function(a){Array.prototype[c].apply(d[a+"Data"],Array.prototype.slice.call(e,2))};u(d.parallelArrays,g)},autoIncrement:function(){var b=this.options,c=this.xIncrement,d,e=b.pointIntervalUnit, -g=0,c=I(c,b.pointStart,0);this.pointInterval=d=I(this.pointInterval,b.pointInterval,1);e&&(b=new l(c),"day"===e?b=+b[l.hcSetDate](b[l.hcGetDate]()+d):"month"===e?b=+b[l.hcSetMonth](b[l.hcGetMonth]()+d):"year"===e&&(b=+b[l.hcSetFullYear](b[l.hcGetFullYear]()+d)),l.hcHasTimeZone&&(g=a.getTZOffset(b)-a.getTZOffset(c)),d=b-c+g);this.xIncrement=c+d;return c},setOptions:function(a){var b=this.chart,c=b.options,d=c.plotOptions,g=(b.userOptions||{}).plotOptions||{},e=d[this.type];this.userOptions=a;b=z(e, -d.series,a);this.tooltipOptions=z(r.tooltip,r.plotOptions.series&&r.plotOptions.series.tooltip,r.plotOptions[this.type].tooltip,c.tooltip.userOptions,d.series&&d.series.tooltip,d[this.type].tooltip,a.tooltip);this.stickyTracking=I(a.stickyTracking,g[this.type]&&g[this.type].stickyTracking,g.series&&g.series.stickyTracking,this.tooltipOptions.shared&&!this.noSharedTooltip?!0:b.stickyTracking);null===e.marker&&delete b.marker;this.zoneAxis=b.zoneAxis;a=this.zones=(b.zones||[]).slice();!b.negativeColor&& -!b.negativeFillColor||b.zones||a.push({value:b[this.zoneAxis+"Threshold"]||b.threshold||0,className:"highcharts-negative",color:b.negativeColor,fillColor:b.negativeFillColor});a.length&&w(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return b},getCyclic:function(a,b,c){var d,g=this.chart,e=this.userOptions,k=a+"Index",h=a+"Counter",q=c?c.length:I(g.options.chart[a+"Count"],g[a+"Count"]);b||(d=I(e[k],e["_"+k]),w(d)||(g.series.length||(g[h]=0),e["_"+k]=d=g[h]%q,g[h]+=1), -c&&(b=c[d]));void 0!==d&&(this[k]=d);this[a]=b},getColor:function(){this.options.colorByPoint?this.options.color=null:this.getCyclic("color",this.options.color||n[this.type].color,this.chart.options.colors)},getSymbol:function(){this.getCyclic("symbol",this.options.marker.symbol,this.chart.options.symbols)},drawLegendSymbol:a.LegendSymbolMixin.drawLineMarker,setData:function(d,e,h,f){var g=this,q=g.points,m=q&&q.length||0,l,A=g.options,t=g.chart,x=null,n=g.xAxis,p=A.turboThreshold,z=this.xData,F= -this.yData,C=(l=g.pointArrayMap)&&l.length;d=d||[];l=d.length;e=I(e,!0);if(!1!==f&&l&&m===l&&!g.cropped&&!g.hasGroupedData&&g.visible)u(d,function(a,b){q[b].update&&a!==A.data[b]&&q[b].update(a,!1,null,!1)});else{g.xIncrement=null;g.colorCounter=0;u(this.parallelArrays,function(a){g[a+"Data"].length=0});if(p&&l>p){for(h=0;null===x&&hf||this.forceCrop))if(c[e-1]z)c=[],d=[];else if(c[0]z)g=this.cropData(this.xData,this.yData,p,z),c=g.xData,d=g.yData,g=g.start,k=!0;for(f=c.length|| -1;--f;)e=x?m(c[f])-m(c[f-1]):c[f]-c[f-1],0e&&n&&(a.error(15),n=!1);this.cropped=k;this.cropStart=g;this.processedXData=c;this.processedYData=d;this.closestPointRange=h},cropData:function(a,b,c,d){var g=a.length,e=0,k=g,h=I(this.cropShoulder,1),f;for(f=0;f=c){e=Math.max(0,f-h);break}for(c=f;cd){k=c+h;break}return{xData:a.slice(e,k),yData:b.slice(e,k),start:e,end:k}},generatePoints:function(){var a=this.options,b=a.data,c=this.data,d,g=this.processedXData, -e=this.processedYData,k=this.pointClass,h=g.length,f=this.cropStart||0,m,l=this.hasGroupedData,a=a.keys,t,x=[],n;c||l||(c=[],c.length=b.length,c=this.data=c);a&&l&&(this.options.keys=!1);for(n=0;n=f&&(e[n-1]||l)<=q,m&&l)if(m=t.length)for(;m--;)"number"===typeof t[m]&&(g[h++]=t[m]);else g[h++]=t;this.dataMin= -p(g);this.dataMax=H(g)},translate:function(){this.processedXData||this.processData();this.generatePoints();var a=this.options,c=a.stacking,d=this.xAxis,e=d.categories,g=this.yAxis,k=this.points,h=k.length,m=!!this.modifyValue,l=a.pointPlacement,t="between"===l||b(l),n=a.threshold,x=a.startFromThreshold?n:0,p,z,C,r,u=Number.MAX_VALUE;"between"===l&&(l=.5);b(l)&&(l*=I(a.pointRange||d.pointRange));for(a=0;a=K&&(B.isNull=!0);B.plotX=p=f(Math.min(Math.max(-1E5,d.translate(N,0,0,0,1,l,"flags"===this.type)),1E5));c&&this.visible&&!B.isNull&&D&&D[N]&&(r=this.getStackIndicator(r,N,this.index),E=D[N],K=E.points[r.key],z=K[0],K=K[1],z===x&&r.key===D[N].base&&(z=I(n,g.min)),g.positiveValuesOnly&&0>=z&&(z=null),B.total=B.stackTotal=E.total,B.percentage=E.total&&B.y/E.total*100,B.stackY=K,E.setOffset(this.pointXOffset||0,this.barW||0));B.yBottom=w(z)?g.translate(z,0,1,0,1): -null;m&&(K=this.modifyValue(K,B));B.plotY=z="number"===typeof K&&Infinity!==K?Math.min(Math.max(-1E5,g.translate(K,0,1,0,1)),1E5):void 0;B.isInside=void 0!==z&&0<=z&&z<=g.len&&0<=p&&p<=d.len;B.clientX=t?f(d.translate(N,0,0,0,1,l)):p;B.negative=B.y<(n||0);B.category=e&&void 0!==e[B.x]?e[B.x]:B.x;B.isNull||(void 0!==C&&(u=Math.min(u,Math.abs(p-C))),C=p);B.zone=this.zones.length&&B.getZone()}this.closestPointRangePx=u},getValidPoints:function(a,b){var c=this.chart;return d(a||this.points||[],function(a){return b&& -!c.isInsidePlot(a.plotX,a.plotY,c.inverted)?!1:!a.isNull})},setClip:function(a){var b=this.chart,c=this.options,d=b.renderer,g=b.inverted,e=this.clipBox,k=e||b.clipBox,h=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,k.height,c.xAxis,c.yAxis].join(),f=b[h],q=b[h+"m"];f||(a&&(k.width=0,g&&(k.x=b.plotSizeX),b[h+"m"]=q=d.clipRect(g?b.plotSizeX+99:-99,g?-b.plotLeft:-b.plotTop,99,g?b.chartWidth:b.chartHeight)),b[h]=f=d.clipRect(k),f.count={length:0});a&&!f.count[this.index]&&(f.count[this.index]= -!0,f.count.length+=1);!1!==c.clip&&(this.group.clip(a||e?f:b.clipRect),this.markerGroup.clip(q),this.sharedClipKey=h);a||(f.count[this.index]&&(delete f.count[this.index],--f.count.length),0===f.count.length&&h&&b[h]&&(e||(b[h]=b[h].destroy()),b[h+"m"]&&(b[h+"m"]=b[h+"m"].destroy())))},animate:function(a){var b=this.chart,c=D(this.options.animation),d;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX,x:0},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99,x:0},c),this.animate= -null)},afterAnimate:function(){this.setClip();m(this,"afterAnimate");this.finishedAnimating=!0},drawPoints:function(){var a=this.points,b=this.chart,c,d,g,e,k=this.options.marker,h,f,l,m=this[this.specialGroup]||this.markerGroup,t,n=I(k.enabled,this.xAxis.isRadial?!0:null,this.closestPointRangePx>=2*k.radius);if(!1!==k.enabled||this._hasPointMarkers)for(c=0;ce&&b.shadow));k&&(k.startX=c.xMap,k.isArea=c.isArea)})}, -applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,e,k,h=this.clips||[],f,m=this.graph,l=this.area,t=Math.max(b.chartWidth,b.chartHeight),n=this[(this.zoneAxis||"y")+"Axis"],x,p,z=b.inverted,C,r,w,B,K=!1;d.length&&(m||l)&&n&&void 0!==n.min&&(p=n.reversed,C=n.horiz,m&&m.hide(),l&&l.hide(),x=n.getExtremes(),u(d,function(d,g){e=p?C?b.plotWidth:0:C?0:n.toPixels(x.min);e=Math.min(Math.max(I(k,e),0),t);k=Math.min(Math.max(Math.round(n.toPixels(I(d.value,x.max),!0)),0),t);K&&(e=k=n.toPixels(x.max)); -r=Math.abs(e-k);w=Math.min(e,k);B=Math.max(e,k);n.isXAxis?(f={x:z?B:w,y:0,width:r,height:t},C||(f.x=b.plotHeight-f.x)):(f={x:0,y:z?B:w,width:t,height:r},C&&(f.y=b.plotWidth-f.y));z&&c.isVML&&(f=n.isXAxis?{x:0,y:p?w:B,height:f.width,width:b.chartWidth}:{x:f.y-b.plotLeft-b.spacingBox.x,y:0,width:f.height,height:b.chartHeight});h[g]?h[g].animate(f):(h[g]=c.clipRect(f),m&&a["zone-graph-"+g].clip(h[g]),l&&a["zone-area-"+g].clip(h[g]));K=d.value>x.max}),this.clips=h)},invertGroups:function(a){function b(){u(["group", -"markerGroup"],function(b){c[b]&&(d.renderer.isVML&&c[b].attr({width:c.yAxis.len,height:c.xAxis.len}),c[b].width=c.yAxis.len,c[b].height=c.xAxis.len,c[b].invert(a))})}var c=this,d=c.chart,e;c.xAxis&&(e=E(d,"resize",b),E(c,"destroy",e),b(a),c.invertGroups=b)},plotGroup:function(a,b,c,d,e){var g=this[a],k=!g;k&&(this[a]=g=this.chart.renderer.g().attr({zIndex:d||.1}).add(e));g.addClass("highcharts-"+b+" highcharts-series-"+this.index+" highcharts-"+this.type+"-series "+(w(this.colorIndex)?"highcharts-color-"+ -this.colorIndex+" ":"")+(this.options.className||"")+(g.hasClass("highcharts-tracker")?" highcharts-tracker":""),!0);g.attr({visibility:c})[k?"attr":"animate"](this.getPlotBox());return g},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;a.inverted&&(b=c,c=this.xAxis);return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this,b=a.chart,c,d=a.options,e=!!a.animate&&b.renderer.isSVG&&D(d.animation).duration,k=a.visible?"inherit": -"hidden",h=d.zIndex,f=a.hasRendered,m=b.seriesGroup,l=b.inverted;c=a.plotGroup("group","series",k,h,m);a.markerGroup=a.plotGroup("markerGroup","markers",k,h,m);e&&a.animate(!0);c.inverted=a.isCartesian?l:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(l);!1===d.clip||a.sharedClipKey||f||c.clip(b.clipRect);e&&a.animate();f||(a.animationTimeout=C(function(){a.afterAnimate()}, -e));a.isDirty=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirty||this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:I(d&&d.left,a.plotLeft),translateY:I(e&&e.top,a.plotTop)}));this.translate();this.render();b&&delete this.kdTree},kdAxisArray:["clientX","plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,e=this.chart.inverted;return this.searchKDTree({clientX:e?c.len-a.chartY+ -c.pos:a.chartX-c.pos,plotY:e?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(c,d,e){var g,k;if(k=c&&c.length)return g=b.kdAxisArray[d%e],c.sort(function(a,b){return a[g]-b[g]}),k=Math.floor(k/2),{point:c[k],left:a(c.slice(0,k),d+1,e),right:a(c.slice(k+1),d+1,e)}}this.buildingKdTree=!0;var b=this,c=-1l?"left":"right";t=0>l?"right":"left";b[q]&&(q=c(a,b[q],g+1,f),n=q[h]x;)q--;this.updateParallelArrays(m,"splice",q,0,0);this.updateParallelArrays(m,q);g&&m.name&&(g[x]=m.name);l.splice(q,0,a);n&&(this.data.splice(q,0,null),this.processData());"point"===e.legendType&&this.generatePoints();c&&(h[0]&&h[0].remove?h[0].remove(!1):(h.shift(),this.updateParallelArrays(m,"shift"),l.shift()));this.isDirtyData=this.isDirty=!0;b&&f.redraw(d)},removePoint:function(a,b,c){var d=this,e=d.data,h=e[a],f=d.points,g=d.chart,l=function(){f&&f.length===e.length&& -f.splice(a,1);e.splice(a,1);d.options.data.splice(a,1);d.updateParallelArrays(h||{series:d},"splice",a,1);h&&h.destroy();d.isDirty=!0;d.isDirtyData=!0;b&&g.redraw()};x(c,g);b=k(b,!0);h?h.firePointEvent("remove",null,l):l()},remove:function(a,b,c){function d(){e.destroy();h.isDirtyLegend=h.isDirtyBox=!0;h.linkSeries();k(a,!0)&&h.redraw(b)}var e=this,h=e.chart;!1!==c?u(e,"remove",null,d):d()},update:function(a,b){var d=this,e=d.chart,h=d.userOptions,f=d.oldType||d.type,l=a.type||h.type||e.options.chart.type, -g=I[f].prototype,m,n=["group","markerGroup","dataLabelsGroup"],t=["navigatorSeries","baseSeries"],x=d.finishedAnimating&&{animation:!1};if(Object.keys&&"data"===Object.keys(a).toString())return this.setData(a.data,b);t=n.concat(t);r(t,function(a){t[a]=d[a];delete d[a]});a=c(h,x,{index:d.index,pointStart:d.xData[0]},{data:d.options.data},a);d.remove(!1,null,!1);for(m in g)d[m]=void 0;w(d,I[l||f].prototype);r(t,function(a){d[a]=t[a]});d.init(e,a);a.zIndex!==h.zIndex&&r(n,function(b){d[b]&&d[b].attr({zIndex:a.zIndex})}); -d.oldType=f;e.linkSeries();k(b,!0)&&e.redraw(!1)}});w(H.prototype,{update:function(a,b){var d=this.chart;a=d.options[this.coll][this.options.index]=c(this.userOptions,a);this.destroy(!0);this.init(d,w(a,{events:void 0}));d.isDirtyBox=!0;k(b,!0)&&d.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,e=this.series,h=e.length;h--;)e[h]&&e[h].remove(!1);n(b.axes,this);n(b[c],this);d(b.options[c])?b.options[c].splice(this.options.index,1):delete b.options[c];r(b[c],function(a,b){a.options.index= -b});this.destroy();b.isDirtyBox=!0;k(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}})})(M);(function(a){var E=a.color,D=a.each,H=a.map,p=a.pick,f=a.Series,l=a.seriesType;l("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(f){var l=[],r=[],u=this.xAxis,e=this.yAxis,h=e.stacks[this.stackKey],m={},d=this.index,c=e.series,b=c.length,k,z=p(e.options.reversedStacks,!0)?1:-1,B;f=f||this.points; -if(this.options.stacking){for(B=0;Ba&&w>l?(w=Math.max(a,l),e=2*l-w):wp&&e>l?(e=Math.max(p,l),w=2*l-e):e=Math.abs(h)&&.5a.closestPointRange*a.xAxis.transA,d=a.borderWidth=r(f.borderWidth,d?0:1),c=a.yAxis,b=f.threshold,k=a.translatedThreshold=c.getThreshold(b),l=r(f.minPointLength,5),p=a.getColumnMetrics(),u=p.width,x=a.barW=Math.max(u,1+2*d),w=a.pointXOffset=p.offset;h.inverted&&(k-=.5);f.pointPadding&&(x=Math.ceil(x));n.prototype.translate.apply(a);H(a.points,function(d){var e=r(d.yBottom,k),f=999+Math.abs(e),f=Math.min(Math.max(-f,d.plotY),c.len+f),m=d.plotX+w,n=x,t=Math.min(f,e),p,g=Math.max(f,e)-t;l&& -Math.abs(g)l?e-l:k-(p?l:0));d.barX=m;d.pointWidth=u;d.tooltipPos=h.inverted?[c.len+c.pos-h.plotLeft-f,a.xAxis.len-m-n/2,g]:[m+n/2,f+c.pos-h.plotTop,g];d.shapeType="rect";d.shapeArgs=a.crispCol.apply(a,d.isNull?[m,k,n,0]:[m,t,n,g])})},getSymbol:a.noop,drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")}, -pointAttribs:function(a,f){var e=this.options,d,c=this.pointAttrToOptions||{};d=c.stroke||"borderColor";var b=c["stroke-width"]||"borderWidth",k=a&&a.color||this.color,h=a&&a[d]||e[d]||this.color||k,n=a&&a[b]||e[b]||this[b]||0,c=e.dashStyle;a&&this.zones.length&&(k=a.getZone(),k=a.options.color||k&&k.color||this.color);f&&(a=l(e.states[f],a.options.states&&a.options.states[f]||{}),f=a.brightness,k=a.color||void 0!==f&&D(k).brighten(a.brightness).get()||k,h=a[d]||h,n=a[b]||n,c=a.dashStyle||c);d={fill:k, -stroke:h,"stroke-width":n};c&&(d.dashstyle=c);return d},drawPoints:function(){var a=this,h=this.chart,m=a.options,d=h.renderer,c=m.animationLimit||250,b;H(a.points,function(e){var k=e.graphic;if(f(e.plotY)&&null!==e.y){b=e.shapeArgs;if(k)k[h.pointCounte;++e)h=w[e],a=2>e||2===e&&/%$/.test(h),w[e]=p(h,[n,l,u,w[2]][e])+(a?r:0);w[3]>w[2]&&(w[3]=w[2]);return w},getStartAndEndRadians:function(a,l){a=D(a)?a:0;l=D(l)&&l>a&&360>l-a?l:a+360;return{start:E*(a+-90),end:E*(l+-90)}}}})(M);(function(a){var E=a.addEvent,D=a.CenteredSeriesMixin,H=a.defined,p=a.each,f=a.extend,l=D.getStartAndEndRadians,r=a.inArray,n=a.noop,w=a.pick,u=a.Point,e=a.Series,h=a.seriesType,m=a.setAnimation;h("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30, -enabled:!0,formatter:function(){return this.point.isNull?void 0:this.point.name},x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff",borderWidth:1,states:{hover:{brightness:.1,shadow:!1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:a.seriesTypes.column.prototype.pointAttribs,animate:function(a){var c= -this,b=c.points,d=c.startAngleRad;a||(p(b,function(a){var b=a.graphic,e=a.shapeArgs;b&&(b.attr({r:a.startR||c.center[3]/2,start:d,end:d}),b.animate({r:e.r,start:e.start,end:e.end},c.options.animation))}),c.animate=null)},updateTotals:function(){var a,c=0,b=this.points,e=b.length,f,h=this.options.ignoreHiddenPoint;for(a=0;a1.5*Math.PI?m-=2*Math.PI:m<-Math.PI/2&&(m+=2*Math.PI);G.slicedTranslation={translateX:Math.round(Math.cos(m)*d),translateY:Math.round(Math.sin(m)*d)};h=Math.cos(m)*a[2]/ -2;u=Math.sin(m)*a[2]/2;G.tooltipPos=[a[0]+.7*h,a[1]+.7*u];G.half=m<-Math.PI/2||m>Math.PI/2?1:0;G.angle=m;f=Math.min(e,G.labelDistance/5);G.labelPos=[a[0]+h+Math.cos(m)*G.labelDistance,a[1]+u+Math.sin(m)*G.labelDistance,a[0]+h+Math.cos(m)*f,a[1]+u+Math.sin(m)*f,a[0]+h,a[1]+u,0>G.labelDistance?"center":G.half?"right":"left",m]}},drawGraph:null,drawPoints:function(){var a=this,c=a.chart.renderer,b,e,h,l,m=a.options.shadow;m&&!a.shadowGroup&&(a.shadowGroup=c.g("shadow").add(a.group));p(a.points,function(d){e= -d.graphic;if(d.isNull)e&&(d.graphic=e.destroy());else{l=d.shapeArgs;b=d.getTranslate();var k=d.shadowGroup;m&&!k&&(k=d.shadowGroup=c.g("shadow").add(a.shadowGroup));k&&k.attr(b);h=a.pointAttribs(d,d.selected&&"select");e?e.setRadialReference(a.center).attr(h).animate(f(l,b)):(d.graphic=e=c[d.shapeType](l).setRadialReference(a.center).attr(b).add(a.group),d.visible||e.attr({visibility:"hidden"}),e.attr(h).attr({"stroke-linejoin":"round"}).shadow(m,k));e.addClass(d.getClassName())}})},searchPoint:n, -sortByAngle:function(a,c){a.sort(function(a,d){return void 0!==a.angle&&(d.angle-a.angle)*c})},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,getCenter:D.getCenter,getSymbol:n},{init:function(){u.prototype.init.apply(this,arguments);var a=this,c;a.name=w(a.name,"Slice");c=function(b){a.slice("select"===b.type)};E(a,"select",c);E(a,"unselect",c);return a},isValid:function(){return a.isNumber(this.y,!0)&&0<=this.y},setVisible:function(a,c){var b=this,d=b.series,e=d.chart,f=d.options.ignoreHiddenPoint; -c=w(c,f);a!==b.visible&&(b.visible=b.options.visible=a=void 0===a?!b.visible:a,d.options.data[r(b,d.data)]=b.options,p(["graphic","dataLabel","connector","shadowGroup"],function(c){if(b[c])b[c][a?"show":"hide"](!0)}),b.legendItem&&e.legend.colorizeItem(b,a),a||"hover"!==b.state||b.setState(""),f&&(d.isDirty=!0),c&&e.redraw())},slice:function(a,c,b){var d=this.series;m(b,d.chart);w(c,!0);this.sliced=this.options.sliced=H(a)?a:!this.sliced;d.options.data[r(this,d.data)]=this.options;this.graphic.animate(this.getTranslate()); -this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())},getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(a){var c=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.x,c.y,c.r+a,c.r+a,{innerR:this.shapeArgs.r-1,start:c.start,end:c.end})}})})(M);(function(a){var E=a.addEvent,D=a.arrayMax,H=a.defined,p=a.each,f=a.extend,l=a.format,r=a.map,n=a.merge,w=a.noop,u=a.pick,e=a.relativeLength,h= -a.Series,m=a.seriesTypes,d=a.stableSort;a.distribute=function(a,b){function c(a,b){return a.target-b.target}var e,f=!0,h=a,l=[],m;m=0;for(e=a.length;e--;)m+=a[e].size;if(m>b){d(a,function(a,b){return(b.rank||0)-(a.rank||0)});for(m=e=0;m<=b;)m+=a[e].size,e++;l=a.splice(e-1,a.length)}d(a,c);for(a=r(a,function(a){return{size:a.size,targets:[a.target],align:u(a.align,.5)}});f;){for(e=a.length;e--;)f=a[e],m=(Math.min.apply(0,f.targets)+Math.max.apply(0,f.targets))/2,f.pos=Math.min(Math.max(0,m-f.size* -f.align),b-f.size);e=a.length;for(f=!1;e--;)0a[e].pos&&(a[e-1].size+=a[e].size,a[e-1].targets=a[e-1].targets.concat(a[e].targets),a[e-1].align=.5,a[e-1].pos+a[e-1].size>b&&(a[e-1].pos=b-a[e-1].size),a.splice(e,1),f=!0)}e=0;p(a,function(a){var b=0;p(a.targets,function(){h[e].pos=a.pos+b;b+=h[e].size;e++})});h.push.apply(h,l);d(h,c)};h.prototype.drawDataLabels=function(){function c(a,b){var c=b.filter;return c?(b=c.operator,a=a[c.property],c=c.value,"\x3e"===b&&a>c||"\x3c"=== -b&&a=c||"\x3c\x3d"===b&&a<=c||"\x3d\x3d"===b&&a==c||"\x3d\x3d\x3d"===b&&a===c?!0:!1):!0}var b=this,d=b.options,e=d.dataLabels,f=b.points,h,m,r=b.hasRendered||0,t,w,D=u(e.defer,!!d.animation),q=b.chart.renderer;if(e.enabled||b._hasPointLabels)b.dlProcessOptions&&b.dlProcessOptions(e),w=b.plotGroup("dataLabelsGroup","data-labels",D&&!r?"hidden":"visible",e.zIndex||6),D&&(w.attr({opacity:+r}),r||E(b,"afterAnimate",function(){b.visible&&w.show(!0);w[d.animation?"animate":"attr"]({opacity:1}, -{duration:200})})),m=e,p(f,function(f){var k,p=f.dataLabel,g,x,r=f.connector,z=!p,C;h=f.dlOptions||f.options&&f.options.dataLabels;(k=u(h&&h.enabled,m.enabled)&&!f.isNull)&&(k=!0===c(f,h||e));k&&(e=n(m,h),g=f.getLabelConfig(),C=e[f.formatPrefix+"Format"]||e.format,t=H(C)?l(C,g):(e[f.formatPrefix+"Formatter"]||e.formatter).call(g,e),C=e.style,g=e.rotation,C.color=u(e.color,C.color,b.color,"#000000"),"contrast"===C.color&&(f.contrastColor=q.getContrast(f.color||b.color),C.color=e.inside||0>u(f.labelDistance, -e.distance)||d.stacking?f.contrastColor:"#000000"),d.cursor&&(C.cursor=d.cursor),x={fill:e.backgroundColor,stroke:e.borderColor,"stroke-width":e.borderWidth,r:e.borderRadius||0,rotation:g,padding:e.padding,zIndex:1},a.objectEach(x,function(a,b){void 0===a&&delete x[b]}));!p||k&&H(t)?k&&H(t)&&(p?x.text=t:(p=f.dataLabel=g?q.text(t,0,-9999).addClass("highcharts-data-label"):q.label(t,0,-9999,e.shape,null,null,e.useHTML,null,"data-label"),p.addClass(" highcharts-data-label-color-"+f.colorIndex+" "+(e.className|| -"")+(e.useHTML?"highcharts-tracker":""))),p.attr(x),p.css(C).shadow(e.shadow),p.added||p.add(w),b.alignDataLabel(f,p,e,null,z)):(f.dataLabel=p=p.destroy(),r&&(f.connector=r.destroy()))})};h.prototype.alignDataLabel=function(a,b,d,e,h){var c=this.chart,k=c.inverted,l=u(a.dlBox&&a.dlBox.centerX,a.plotX,-9999),m=u(a.plotY,-9999),n=b.getBBox(),p,q=d.rotation,r=d.align,w=this.visible&&(a.series.forceDL||c.isInsidePlot(l,Math.round(m),k)||e&&c.isInsidePlot(l,k?e.x+1:e.y+e.height-1,k)),z="justify"===u(d.overflow, -"justify");if(w&&(p=d.style.fontSize,p=c.renderer.fontMetrics(p,b).b,e=f({x:k?this.yAxis.len-m:l,y:Math.round(k?this.xAxis.len-l:m),width:0,height:0},e),f(d,{width:n.width,height:n.height}),q?(z=!1,l=c.renderer.rotCorr(p,q),l={x:e.x+d.x+e.width/2+l.x,y:e.y+d.y+{top:0,middle:.5,bottom:1}[d.verticalAlign]*e.height},b[h?"attr":"animate"](l).attr({align:r}),m=(q+720)%360,m=180m,"left"===r?l.y-=m?n.height:0:"center"===r?(l.x-=n.width/2,l.y-=n.height/2):"right"===r&&(l.x-=n.width,l.y-=m?0:n.height)): -(b.align(d,null,e),l=b.alignAttr),z?a.isLabelJustified=this.justifyDataLabel(b,d,l,n,e,h):u(d.crop,!0)&&(w=c.isInsidePlot(l.x,l.y)&&c.isInsidePlot(l.x+n.width,l.y+n.height)),d.shape&&!q))b[h?"attr":"animate"]({anchorX:k?c.plotWidth-a.plotY:a.plotX,anchorY:k?c.plotHeight-a.plotX:a.plotY});w||(b.attr({y:-9999}),b.placed=!1)};h.prototype.justifyDataLabel=function(a,b,d,e,f,h){var c=this.chart,k=b.align,l=b.verticalAlign,m,n,p=a.box?0:a.padding||0;m=d.x+p;0>m&&("right"===k?b.align="left":b.x=-m,n=!0); -m=d.x+e.width-p;m>c.plotWidth&&("left"===k?b.align="right":b.x=c.plotWidth-m,n=!0);m=d.y+p;0>m&&("bottom"===l?b.verticalAlign="top":b.y=-m,n=!0);m=d.y+e.height-p;m>c.plotHeight&&("top"===l?b.verticalAlign="bottom":b.y=c.plotHeight-m,n=!0);n&&(a.placed=!h,a.align(b,null,f));return n};m.pie&&(m.pie.prototype.drawDataLabels=function(){var c=this,b=c.data,d,e=c.chart,f=c.options.dataLabels,l=u(f.connectorPadding,10),m=u(f.connectorWidth,1),n=e.plotWidth,t=e.plotHeight,r,w=c.center,q=w[2]/2,A=w[1],F,G, -g,v,E=[[],[]],L,P,J,M,y=[0,0,0,0];c.visible&&(f.enabled||c._hasPointLabels)&&(p(b,function(a){a.dataLabel&&a.visible&&a.dataLabel.shortened&&(a.dataLabel.attr({width:"auto"}).css({width:"auto",textOverflow:"clip"}),a.dataLabel.shortened=!1)}),h.prototype.drawDataLabels.apply(c),p(b,function(a){a.dataLabel&&a.visible&&(E[a.half].push(a),a.dataLabel._pos=null)}),p(E,function(b,h){var k,m,x=b.length,r=[],z;if(x)for(c.sortByAngle(b,h-.5),0d.bottom-2?k:P,h,d),F._attr={visibility:J,align:g[6]},F._pos={x:L+f.x+({left:l,right:-l}[g[6]]||0),y:P+f.y-10},g.x=L,g.y=P,u(f.crop,!0)&&(G=F.getBBox().width,k=null,L-Gn-l&&(k=Math.round(L+G-n+l),y[1]=Math.max(k,y[1])),0>P-v/2?y[0]=Math.max(Math.round(-P+v/2),y[0]):P+v/2>t&&(y[2]=Math.max(Math.round(P+v/2-t),y[2])),F.sideOverflow=k)}),0===D(y)||this.verifyDataLabelOverflow(y))&&(this.placeDataLabels(), -m&&p(this.points,function(a){var b;r=a.connector;if((F=a.dataLabel)&&F._pos&&a.visible&&0u(this.translatedThreshold,k.yAxis.len)),p=u(d.inside,!!this.options.stacking);l&&(e=n(l),0>e.y&&(e.height+=e.y,e.y=0),l=e.y+e.height-k.yAxis.len,0a+c||e+hb+d||f+lthis.pointCount))},pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&r(d,function(a){a.setState()});r("xy"===b?[1,0]:[1],function(b){b= -c[b?"xAxis":"yAxis"][0];var d=b.horiz,f=a[d?"chartX":"chartY"],d=d?"mouseDownX":"mouseDownY",h=c[d],g=(b.pointRange||0)/2,k=b.getExtremes(),l=b.toValue(h-f,!0)+g,m=b.toValue(h+b.len-f,!0)-g,n=m=l(n.minWidth,0)&&this.chartHeight>=l(n.minHeight,0)}).call(this)&&f.push(a._id)};E.prototype.currentOptions=function(l){function n(e,h,l,d){var c;a.objectEach(e,function(a,e){if(!d&&-1 parseInt(D.split('Firefox/')[1], 10); + return a.Highcharts + ? a.Highcharts.error(16, !0) + : { + product: 'Highcharts', + version: '6.0.4', + deg2rad: (2 * Math.PI) / 360, + doc: E, + hasBidiBug: l, + hasTouch: E && void 0 !== E.documentElement.ontouchstart, + isMS: p, + isWebKit: /AppleWebKit/.test(D), + isFirefox: f, + isTouchDevice: /(Mobile|Android|Windows Phone)/.test(D), + SVG_NS: 'http://www.w3.org/2000/svg', + chartCount: 0, + seriesTypes: {}, + symbolSizes: {}, + svg: H, + win: a, + marginNames: ['plotTop', 'marginRight', 'marginBottom', 'plotLeft'], + noop: function() {}, + charts: [], + }; + })(); + (function(a) { + a.timers = []; + var E = a.charts, + D = a.doc, + H = a.win; + a.error = function(p, f) { + p = a.isNumber(p) + ? 'Highcharts error #' + p + ': www.highcharts.com/errors/' + p + : p; + if (f) throw Error(p); + H.console && console.log(p); + }; + a.Fx = function(a, f, l) { + this.options = f; + this.elem = a; + this.prop = l; + }; + a.Fx.prototype = { + dSetter: function() { + var a = this.paths[0], + f = this.paths[1], + l = [], + r = this.now, + n = a.length, + w; + if (1 === r) l = this.toD; + else if (n === f.length && 1 > r) + for (; n--; ) + (w = parseFloat(a[n])), + (l[n] = isNaN(w) ? f[n] : r * parseFloat(f[n] - w) + w); + else l = f; + this.elem.attr('d', l, null, !0); + }, + update: function() { + var a = this.elem, + f = this.prop, + l = this.now, + r = this.options.step; + if (this[f + 'Setter']) this[f + 'Setter'](); + else + a.attr + ? a.element && a.attr(f, l, null, !0) + : (a.style[f] = l + this.unit); + r && r.call(a, l, this); + }, + run: function(p, f, l) { + var r = this, + n = r.options, + w = function(a) { + return w.stopped ? !1 : r.step(a); + }, + u = + H.requestAnimationFrame || + function(a) { + setTimeout(a, 13); + }, + e = function() { + for (var h = 0; h < a.timers.length; h++) + a.timers[h]() || a.timers.splice(h--, 1); + a.timers.length && u(e); + }; + p === f + ? (delete n.curAnim[this.prop], + n.complete && + 0 === a.keys(n.curAnim).length && + n.complete.call(this.elem)) + : ((this.startTime = +new Date()), + (this.start = p), + (this.end = f), + (this.unit = l), + (this.now = this.start), + (this.pos = 0), + (w.elem = this.elem), + (w.prop = this.prop), + w() && 1 === a.timers.push(w) && u(e)); + }, + step: function(p) { + var f = +new Date(), + l, + r = this.options, + n = this.elem, + w = r.complete, + u = r.duration, + e = r.curAnim; + n.attr && !n.element + ? (p = !1) + : p || f >= u + this.startTime + ? ((this.now = this.end), + (this.pos = 1), + this.update(), + (l = e[this.prop] = !0), + a.objectEach(e, function(a) { + !0 !== a && (l = !1); + }), + l && w && w.call(n), + (p = !1)) + : ((this.pos = r.easing((f - this.startTime) / u)), + (this.now = this.start + (this.end - this.start) * this.pos), + this.update(), + (p = !0)); + return p; + }, + initPath: function(p, f, l) { + function r(a) { + var b, c; + for (k = a.length; k--; ) + (b = 'M' === a[k] || 'L' === a[k]), + (c = /[a-zA-Z]/.test(a[k + 3])), + b && + c && + a.splice(k + 1, 0, a[k + 1], a[k + 2], a[k + 1], a[k + 2]); + } + function n(a, b) { + for (; a.length < c; ) { + a[0] = b[c - a.length]; + var e = a.slice(0, d); + [].splice.apply(a, [0, 0].concat(e)); + z && + ((e = a.slice(a.length - d)), + [].splice.apply(a, [a.length, 0].concat(e)), + k--); + } + a[0] = 'M'; + } + function w(a, k) { + for (var e = (c - a.length) / d; 0 < e && e--; ) + (b = a.slice().splice(a.length / B - d, d * B)), + (b[0] = k[c - d - e * d]), + m && ((b[d - 6] = b[d - 2]), (b[d - 5] = b[d - 1])), + [].splice.apply(a, [a.length / B, 0].concat(b)), + z && e--; + } + f = f || ''; + var u, + e = p.startX, + h = p.endX, + m = -1 < f.indexOf('C'), + d = m ? 7 : 3, + c, + b, + k; + f = f.split(' '); + l = l.slice(); + var z = p.isArea, + B = z ? 2 : 1, + I; + m && (r(f), r(l)); + if (e && h) { + for (k = 0; k < e.length; k++) + if (e[k] === h[0]) { + u = k; + break; + } else if (e[0] === h[h.length - e.length + k]) { + u = k; + I = !0; + break; + } + void 0 === u && (f = []); + } + f.length && + a.isNumber(u) && + ((c = l.length + u * B * d), + I ? (n(f, l), w(l, f)) : (n(l, f), w(f, l))); + return [f, l]; + }, + }; + a.Fx.prototype.fillSetter = a.Fx.prototype.strokeSetter = function() { + this.elem.attr( + this.prop, + a.color(this.start).tweenTo(a.color(this.end), this.pos), + null, + !0, + ); + }; + a.extend = function(a, f) { + var l; + a || (a = {}); + for (l in f) a[l] = f[l]; + return a; + }; + a.merge = function() { + var p, + f = arguments, + l, + r = {}, + n = function(l, p) { + 'object' !== typeof l && (l = {}); + a.objectEach(p, function(e, h) { + !a.isObject(e, !0) || a.isClass(e) || a.isDOMElement(e) + ? (l[h] = p[h]) + : (l[h] = n(l[h] || {}, e)); + }); + return l; + }; + !0 === f[0] && ((r = f[1]), (f = Array.prototype.slice.call(f, 2))); + l = f.length; + for (p = 0; p < l; p++) r = n(r, f[p]); + return r; + }; + a.pInt = function(a, f) { + return parseInt(a, f || 10); + }; + a.isString = function(a) { + return 'string' === typeof a; + }; + a.isArray = function(a) { + a = Object.prototype.toString.call(a); + return '[object Array]' === a || '[object Array Iterator]' === a; + }; + a.isObject = function(p, f) { + return !!p && 'object' === typeof p && (!f || !a.isArray(p)); + }; + a.isDOMElement = function(p) { + return a.isObject(p) && 'number' === typeof p.nodeType; + }; + a.isClass = function(p) { + var f = p && p.constructor; + return !( + !a.isObject(p, !0) || + a.isDOMElement(p) || + !f || + !f.name || + 'Object' === f.name + ); + }; + a.isNumber = function(a) { + return ( + 'number' === typeof a && !isNaN(a) && Infinity > a && -Infinity < a + ); + }; + a.erase = function(a, f) { + for (var l = a.length; l--; ) + if (a[l] === f) { + a.splice(l, 1); + break; + } + }; + a.defined = function(a) { + return void 0 !== a && null !== a; + }; + a.attr = function(p, f, l) { + var r; + a.isString(f) + ? a.defined(l) + ? p.setAttribute(f, l) + : p && p.getAttribute && (r = p.getAttribute(f)) + : a.defined(f) && + a.isObject(f) && + a.objectEach(f, function(a, l) { + p.setAttribute(l, a); + }); + return r; + }; + a.splat = function(p) { + return a.isArray(p) ? p : [p]; + }; + a.syncTimeout = function(a, f, l) { + if (f) return setTimeout(a, f, l); + a.call(0, l); + }; + a.pick = function() { + var a = arguments, + f, + l, + r = a.length; + for (f = 0; f < r; f++) + if (((l = a[f]), void 0 !== l && null !== l)) return l; + }; + a.css = function(p, f) { + a.isMS && + !a.svg && + f && + void 0 !== f.opacity && + (f.filter = 'alpha(opacity\x3d' + 100 * f.opacity + ')'); + a.extend(p.style, f); + }; + a.createElement = function(p, f, l, r, n) { + p = D.createElement(p); + var w = a.css; + f && a.extend(p, f); + n && w(p, { padding: 0, border: 'none', margin: 0 }); + l && w(p, l); + r && r.appendChild(p); + return p; + }; + a.extendClass = function(p, f) { + var l = function() {}; + l.prototype = new p(); + a.extend(l.prototype, f); + return l; + }; + a.pad = function(a, f, l) { + return Array((f || 2) + 1 - String(a).length).join(l || 0) + a; + }; + a.relativeLength = function(a, f, l) { + return /%$/.test(a) + ? (f * parseFloat(a)) / 100 + (l || 0) + : parseFloat(a); + }; + a.wrap = function(a, f, l) { + var p = a[f]; + a[f] = function() { + var a = Array.prototype.slice.call(arguments), + f = arguments, + u = this; + u.proceed = function() { + p.apply(u, arguments.length ? arguments : f); + }; + a.unshift(p); + a = l.apply(this, a); + u.proceed = null; + return a; + }; + }; + a.getTZOffset = function(p) { + var f = a.Date; + return ( + 6e4 * + ((f.hcGetTimezoneOffset && f.hcGetTimezoneOffset(p)) || + f.hcTimezoneOffset || + 0) + ); + }; + a.dateFormat = function(p, f, l) { + if (!a.defined(f) || isNaN(f)) + return a.defaultOptions.lang.invalidDate || ''; + p = a.pick(p, '%Y-%m-%d %H:%M:%S'); + var r = a.Date, + n = new r(f - a.getTZOffset(f)), + w = n[r.hcGetHours](), + u = n[r.hcGetDay](), + e = n[r.hcGetDate](), + h = n[r.hcGetMonth](), + m = n[r.hcGetFullYear](), + d = a.defaultOptions.lang, + c = d.weekdays, + b = d.shortWeekdays, + k = a.pad, + r = a.extend( + { + a: b ? b[u] : c[u].substr(0, 3), + A: c[u], + d: k(e), + e: k(e, 2, ' '), + w: u, + b: d.shortMonths[h], + B: d.months[h], + m: k(h + 1), + y: m.toString().substr(2, 2), + Y: m, + H: k(w), + k: w, + I: k(w % 12 || 12), + l: w % 12 || 12, + M: k(n[r.hcGetMinutes]()), + p: 12 > w ? 'AM' : 'PM', + P: 12 > w ? 'am' : 'pm', + S: k(n.getSeconds()), + L: k(Math.round(f % 1e3), 3), + }, + a.dateFormats, + ); + a.objectEach(r, function(a, b) { + for (; -1 !== p.indexOf('%' + b); ) + p = p.replace('%' + b, 'function' === typeof a ? a(f) : a); + }); + return l ? p.substr(0, 1).toUpperCase() + p.substr(1) : p; + }; + a.formatSingle = function(p, f) { + var l = /\.([0-9])/, + r = a.defaultOptions.lang; + /f$/.test(p) + ? ((l = (l = p.match(l)) ? l[1] : -1), + null !== f && + (f = a.numberFormat( + f, + l, + r.decimalPoint, + -1 < p.indexOf(',') ? r.thousandsSep : '', + ))) + : (f = a.dateFormat(p, f)); + return f; + }; + a.format = function(p, f) { + for (var l = '{', r = !1, n, w, u, e, h = [], m; p; ) { + l = p.indexOf(l); + if (-1 === l) break; + n = p.slice(0, l); + if (r) { + n = n.split(':'); + w = n.shift().split('.'); + e = w.length; + m = f; + for (u = 0; u < e; u++) m && (m = m[w[u]]); + n.length && (m = a.formatSingle(n.join(':'), m)); + h.push(m); + } else h.push(n); + p = p.slice(l + 1); + l = (r = !r) ? '}' : '{'; + } + h.push(p); + return h.join(''); + }; + a.getMagnitude = function(a) { + return Math.pow(10, Math.floor(Math.log(a) / Math.LN10)); + }; + a.normalizeTickInterval = function(p, f, l, r, n) { + var w, + u = p; + l = a.pick(l, 1); + w = p / l; + f || + ((f = n + ? [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] + : [1, 2, 2.5, 5, 10]), + !1 === r && + (1 === l + ? (f = a.grep(f, function(a) { + return 0 === a % 1; + })) + : 0.1 >= l && (f = [1 / l]))); + for ( + r = 0; + r < f.length && + !((u = f[r]), + (n && u * l >= p) || (!n && w <= (f[r] + (f[r + 1] || f[r])) / 2)); + r++ + ); + return (u = a.correctFloat( + u * l, + -Math.round(Math.log(0.001) / Math.LN10), + )); + }; + a.stableSort = function(a, f) { + var l = a.length, + p, + n; + for (n = 0; n < l; n++) a[n].safeI = n; + a.sort(function(a, n) { + p = f(a, n); + return 0 === p ? a.safeI - n.safeI : p; + }); + for (n = 0; n < l; n++) delete a[n].safeI; + }; + a.arrayMin = function(a) { + for (var f = a.length, l = a[0]; f--; ) a[f] < l && (l = a[f]); + return l; + }; + a.arrayMax = function(a) { + for (var f = a.length, l = a[0]; f--; ) a[f] > l && (l = a[f]); + return l; + }; + a.destroyObjectProperties = function(p, f) { + a.objectEach(p, function(a, r) { + a && a !== f && a.destroy && a.destroy(); + delete p[r]; + }); + }; + a.discardElement = function(p) { + var f = a.garbageBin; + f || (f = a.createElement('div')); + p && f.appendChild(p); + f.innerHTML = ''; + }; + a.correctFloat = function(a, f) { + return parseFloat(a.toPrecision(f || 14)); + }; + a.setAnimation = function(p, f) { + f.renderer.globalAnimation = a.pick(p, f.options.chart.animation, !0); + }; + a.animObject = function(p) { + return a.isObject(p) ? a.merge(p) : { duration: p ? 500 : 0 }; + }; + a.timeUnits = { + millisecond: 1, + second: 1e3, + minute: 6e4, + hour: 36e5, + day: 864e5, + week: 6048e5, + month: 24192e5, + year: 314496e5, + }; + a.numberFormat = function(p, f, l, r) { + p = +p || 0; + f = +f; + var n = a.defaultOptions.lang, + w = (p.toString().split('.')[1] || '').split('e')[0].length, + u, + e, + h = p.toString().split('e'); + -1 === f + ? (f = Math.min(w, 20)) + : a.isNumber(f) + ? f && + h[1] && + 0 > h[1] && + ((u = f + +h[1]), + 0 <= u + ? ((h[0] = (+h[0]).toExponential(u).split('e')[0]), (f = u)) + : ((h[0] = h[0].split('.')[0] || 0), + (p = 20 > f ? (h[0] * Math.pow(10, h[1])).toFixed(f) : 0), + (h[1] = 0))) + : (f = 2); + e = ( + Math.abs(h[1] ? h[0] : p) + Math.pow(10, -Math.max(f, w) - 1) + ).toFixed(f); + w = String(a.pInt(e)); + u = 3 < w.length ? w.length % 3 : 0; + l = a.pick(l, n.decimalPoint); + r = a.pick(r, n.thousandsSep); + p = (0 > p ? '-' : '') + (u ? w.substr(0, u) + r : ''); + p += w.substr(u).replace(/(\d{3})(?=\d)/g, '$1' + r); + f && (p += l + e.slice(-f)); + h[1] && 0 !== +p && (p += 'e' + h[1]); + return p; + }; + Math.easeInOutSine = function(a) { + return -0.5 * (Math.cos(Math.PI * a) - 1); + }; + a.getStyle = function(p, f, l) { + if ('width' === f) + return ( + Math.min(p.offsetWidth, p.scrollWidth) - + a.getStyle(p, 'padding-left') - + a.getStyle(p, 'padding-right') + ); + if ('height' === f) + return ( + Math.min(p.offsetHeight, p.scrollHeight) - + a.getStyle(p, 'padding-top') - + a.getStyle(p, 'padding-bottom') + ); + H.getComputedStyle || a.error(27, !0); + if ((p = H.getComputedStyle(p, void 0))) + (p = p.getPropertyValue(f)), + a.pick(l, 'opacity' !== f) && (p = a.pInt(p)); + return p; + }; + a.inArray = function(p, f) { + return (a.indexOfPolyfill || Array.prototype.indexOf).call(f, p); + }; + a.grep = function(p, f) { + return (a.filterPolyfill || Array.prototype.filter).call(p, f); + }; + a.find = Array.prototype.find + ? function(a, f) { + return a.find(f); + } + : function(a, f) { + var l, + r = a.length; + for (l = 0; l < r; l++) if (f(a[l], l)) return a[l]; + }; + a.map = function(a, f) { + for (var l = [], r = 0, n = a.length; r < n; r++) + l[r] = f.call(a[r], a[r], r, a); + return l; + }; + a.keys = function(p) { + return (a.keysPolyfill || Object.keys).call(void 0, p); + }; + a.reduce = function(p, f, l) { + return (a.reducePolyfill || Array.prototype.reduce).call(p, f, l); + }; + a.offset = function(a) { + var f = D.documentElement; + a = a.parentElement ? a.getBoundingClientRect() : { top: 0, left: 0 }; + return { + top: a.top + (H.pageYOffset || f.scrollTop) - (f.clientTop || 0), + left: a.left + (H.pageXOffset || f.scrollLeft) - (f.clientLeft || 0), + }; + }; + a.stop = function(p, f) { + for (var l = a.timers.length; l--; ) + a.timers[l].elem !== p || + (f && f !== a.timers[l].prop) || + (a.timers[l].stopped = !0); + }; + a.each = function(p, f, l) { + return (a.forEachPolyfill || Array.prototype.forEach).call(p, f, l); + }; + a.objectEach = function(a, f, l) { + for (var r in a) a.hasOwnProperty(r) && f.call(l, a[r], r, a); + }; + a.addEvent = function(p, f, l) { + var r, + n, + w = p.addEventListener || a.addEventListenerPolyfill; + p.hcEvents && + !Object.prototype.hasOwnProperty.call(p, 'hcEvents') && + ((n = {}), + a.objectEach(p.hcEvents, function(a, e) { + n[e] = a.slice(0); + }), + (p.hcEvents = n)); + r = p.hcEvents = p.hcEvents || {}; + w && w.call(p, f, l, !1); + r[f] || (r[f] = []); + r[f].push(l); + return function() { + a.removeEvent(p, f, l); + }; + }; + a.removeEvent = function(p, f, l) { + function r(e, m) { + var d = p.removeEventListener || a.removeEventListenerPolyfill; + d && d.call(p, e, m, !1); + } + function n() { + var e, m; + p.nodeName && + (f ? ((e = {}), (e[f] = !0)) : (e = u), + a.objectEach(e, function(a, c) { + if (u[c]) for (m = u[c].length; m--; ) r(c, u[c][m]); + })); + } + var w, + u = p.hcEvents, + e; + u && + (f + ? ((w = u[f] || []), + l + ? ((e = a.inArray(l, w)), + -1 < e && (w.splice(e, 1), (u[f] = w)), + r(f, l)) + : (n(), (u[f] = []))) + : (n(), (p.hcEvents = {}))); + }; + a.fireEvent = function(p, f, l, r) { + var n; + n = p.hcEvents; + var w, u; + l = l || {}; + if (D.createEvent && (p.dispatchEvent || p.fireEvent)) + (n = D.createEvent('Events')), + n.initEvent(f, !0, !0), + a.extend(n, l), + p.dispatchEvent ? p.dispatchEvent(n) : p.fireEvent(f, n); + else if (n) + for ( + n = n[f] || [], + w = n.length, + l.target || + a.extend(l, { + preventDefault: function() { + l.defaultPrevented = !0; + }, + target: p, + type: f, + }), + f = 0; + f < w; + f++ + ) + (u = n[f]) && !1 === u.call(p, l) && l.preventDefault(); + r && !l.defaultPrevented && r(l); + }; + a.animate = function(p, f, l) { + var r, + n = '', + w, + u, + e; + a.isObject(l) || + ((e = arguments), + (l = { duration: e[2], easing: e[3], complete: e[4] })); + a.isNumber(l.duration) || (l.duration = 400); + l.easing = + 'function' === typeof l.easing + ? l.easing + : Math[l.easing] || Math.easeInOutSine; + l.curAnim = a.merge(f); + a.objectEach(f, function(e, m) { + a.stop(p, m); + u = new a.Fx(p, l, m); + w = null; + 'd' === m + ? ((u.paths = u.initPath(p, p.d, f.d)), + (u.toD = f.d), + (r = 0), + (w = 1)) + : p.attr + ? (r = p.attr(m)) + : ((r = parseFloat(a.getStyle(p, m)) || 0), + 'opacity' !== m && (n = 'px')); + w || (w = e); + w && w.match && w.match('px') && (w = w.replace(/px/g, '')); + u.run(r, w, n); + }); + }; + a.seriesType = function(p, f, l, r, n) { + var w = a.getOptions(), + u = a.seriesTypes; + w.plotOptions[p] = a.merge(w.plotOptions[f], l); + u[p] = a.extendClass(u[f] || function() {}, r); + u[p].prototype.type = p; + n && (u[p].prototype.pointClass = a.extendClass(a.Point, n)); + return u[p]; + }; + a.uniqueKey = (function() { + var a = Math.random() + .toString(36) + .substring(2, 9), + f = 0; + return function() { + return 'highcharts-' + a + '-' + f++; + }; + })(); + H.jQuery && + (H.jQuery.fn.highcharts = function() { + var p = [].slice.call(arguments); + if (this[0]) + return p[0] + ? (new a[a.isString(p[0]) ? p.shift() : 'Chart']( + this[0], + p[0], + p[1], + ), + this) + : E[a.attr(this[0], 'data-highcharts-chart')]; + }); + })(M); + (function(a) { + var E = a.each, + D = a.isNumber, + H = a.map, + p = a.merge, + f = a.pInt; + a.Color = function(l) { + if (!(this instanceof a.Color)) return new a.Color(l); + this.init(l); + }; + a.Color.prototype = { + parsers: [ + { + regex: /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/, + parse: function(a) { + return [f(a[1]), f(a[2]), f(a[3]), parseFloat(a[4], 10)]; + }, + }, + { + regex: /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/, + parse: function(a) { + return [f(a[1]), f(a[2]), f(a[3]), 1]; + }, + }, + ], + names: { + none: 'rgba(255,255,255,0)', + white: '#ffffff', + black: '#000000', + }, + init: function(l) { + var f, n, w, u; + if ( + (this.input = l = + this.names[l && l.toLowerCase ? l.toLowerCase() : ''] || l) && + l.stops + ) + this.stops = H(l.stops, function(e) { + return new a.Color(e[1]); + }); + else if ( + (l && + l.charAt && + '#' === l.charAt() && + ((f = l.length), + (l = parseInt(l.substr(1), 16)), + 7 === f + ? (n = [(l & 16711680) >> 16, (l & 65280) >> 8, l & 255, 1]) + : 4 === f && + (n = [ + ((l & 3840) >> 4) | ((l & 3840) >> 8), + ((l & 240) >> 4) | (l & 240), + ((l & 15) << 4) | (l & 15), + 1, + ])), + !n) + ) + for (w = this.parsers.length; w-- && !n; ) + (u = this.parsers[w]), (f = u.regex.exec(l)) && (n = u.parse(f)); + this.rgba = n || []; + }, + get: function(a) { + var f = this.input, + n = this.rgba, + l; + this.stops + ? ((l = p(f)), + (l.stops = [].concat(l.stops)), + E(this.stops, function(n, e) { + l.stops[e] = [l.stops[e][0], n.get(a)]; + })) + : (l = + n && D(n[0]) + ? 'rgb' === a || (!a && 1 === n[3]) + ? 'rgb(' + n[0] + ',' + n[1] + ',' + n[2] + ')' + : 'a' === a + ? n[3] + : 'rgba(' + n.join(',') + ')' + : f); + return l; + }, + brighten: function(a) { + var l, + n = this.rgba; + if (this.stops) + E(this.stops, function(n) { + n.brighten(a); + }); + else if (D(a) && 0 !== a) + for (l = 0; 3 > l; l++) + (n[l] += f(255 * a)), + 0 > n[l] && (n[l] = 0), + 255 < n[l] && (n[l] = 255); + return this; + }, + setOpacity: function(a) { + this.rgba[3] = a; + return this; + }, + tweenTo: function(a, f) { + var n = this.rgba, + l = a.rgba; + l.length && n && n.length + ? ((a = 1 !== l[3] || 1 !== n[3]), + (f = + (a ? 'rgba(' : 'rgb(') + + Math.round(l[0] + (n[0] - l[0]) * (1 - f)) + + ',' + + Math.round(l[1] + (n[1] - l[1]) * (1 - f)) + + ',' + + Math.round(l[2] + (n[2] - l[2]) * (1 - f)) + + (a ? ',' + (l[3] + (n[3] - l[3]) * (1 - f)) : '') + + ')')) + : (f = a.input || 'none'); + return f; + }, + }; + a.color = function(l) { + return new a.Color(l); + }; + })(M); + (function(a) { + var E, + D, + H = a.addEvent, + p = a.animate, + f = a.attr, + l = a.charts, + r = a.color, + n = a.css, + w = a.createElement, + u = a.defined, + e = a.deg2rad, + h = a.destroyObjectProperties, + m = a.doc, + d = a.each, + c = a.extend, + b = a.erase, + k = a.grep, + z = a.hasTouch, + B = a.inArray, + I = a.isArray, + x = a.isFirefox, + K = a.isMS, + t = a.isObject, + C = a.isString, + N = a.isWebKit, + q = a.merge, + A = a.noop, + F = a.objectEach, + G = a.pick, + g = a.pInt, + v = a.removeEvent, + Q = a.stop, + L = a.svg, + P = a.SVG_NS, + J = a.symbolSizes, + R = a.win; + E = a.SVGElement = function() { + return this; + }; + c(E.prototype, { + opacity: 1, + SVG_NS: P, + textProps: 'direction fontSize fontWeight fontFamily fontStyle color lineHeight width textAlign textDecoration textOverflow textOutline'.split( + ' ', + ), + init: function(a, g) { + this.element = 'span' === g ? w(g) : m.createElementNS(this.SVG_NS, g); + this.renderer = a; + }, + animate: function(y, g, b) { + g = a.animObject(G(g, this.renderer.globalAnimation, !0)); + 0 !== g.duration + ? (b && (g.complete = b), p(this, y, g)) + : (this.attr(y, null, b), g.step && g.step.call(this)); + return this; + }, + colorGradient: function(y, g, b) { + var v = this.renderer, + c, + O, + k, + e, + z, + h, + m, + L, + A, + J, + t = [], + x; + y.radialGradient + ? (O = 'radialGradient') + : y.linearGradient && (O = 'linearGradient'); + O && + ((k = y[O]), + (z = v.gradients), + (m = y.stops), + (J = b.radialReference), + I(k) && + (y[O] = k = { + x1: k[0], + y1: k[1], + x2: k[2], + y2: k[3], + gradientUnits: 'userSpaceOnUse', + }), + 'radialGradient' === O && + J && + !u(k.gradientUnits) && + ((e = k), + (k = q(k, v.getRadialAttr(J, e), { + gradientUnits: 'userSpaceOnUse', + }))), + F(k, function(a, y) { + 'id' !== y && t.push(y, a); + }), + F(m, function(a) { + t.push(a); + }), + (t = t.join(',')), + z[t] + ? (J = z[t].attr('id')) + : ((k.id = J = a.uniqueKey()), + (z[t] = h = v + .createElement(O) + .attr(k) + .add(v.defs)), + (h.radAttr = e), + (h.stops = []), + d(m, function(y) { + 0 === y[1].indexOf('rgba') + ? ((c = a.color(y[1])), (L = c.get('rgb')), (A = c.get('a'))) + : ((L = y[1]), (A = 1)); + y = v + .createElement('stop') + .attr({ offset: y[0], 'stop-color': L, 'stop-opacity': A }) + .add(h); + h.stops.push(y); + })), + (x = 'url(' + v.url + '#' + J + ')'), + b.setAttribute(g, x), + (b.gradient = t), + (y.toString = function() { + return x; + })); + }, + applyTextOutline: function(y) { + var g = this.element, + v, + c, + k, + q, + e; + -1 !== y.indexOf('contrast') && + (y = y.replace(/contrast/g, this.renderer.getContrast(g.style.fill))); + y = y.split(' '); + c = y[y.length - 1]; + if ((k = y[0]) && 'none' !== k && a.svg) { + this.fakeTS = !0; + y = [].slice.call(g.getElementsByTagName('tspan')); + this.ySetter = this.xSetter; + k = k.replace(/(^[\d\.]+)(.*?)$/g, function(a, y, g) { + return 2 * y + g; + }); + for (e = y.length; e--; ) + (v = y[e]), + 'highcharts-text-outline' === v.getAttribute('class') && + b(y, g.removeChild(v)); + q = g.firstChild; + d(y, function(a, y) { + 0 === y && + (a.setAttribute('x', g.getAttribute('x')), + (y = g.getAttribute('y')), + a.setAttribute('y', y || 0), + null === y && g.setAttribute('y', 0)); + a = a.cloneNode(1); + f(a, { + class: 'highcharts-text-outline', + fill: c, + stroke: c, + 'stroke-width': k, + 'stroke-linejoin': 'round', + }); + g.insertBefore(a, q); + }); + } + }, + attr: function(a, g, b, v) { + var y, + c = this.element, + k, + d = this, + O, + q; + 'string' === typeof a && + void 0 !== g && + ((y = a), (a = {}), (a[y] = g)); + 'string' === typeof a + ? (d = (this[a + 'Getter'] || this._defaultGetter).call(this, a, c)) + : (F( + a, + function(y, g) { + O = !1; + v || Q(this, g); + this.symbolName && + /^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)$/.test( + g, + ) && + (k || (this.symbolAttr(a), (k = !0)), (O = !0)); + !this.rotation || + ('x' !== g && 'y' !== g) || + (this.doTransform = !0); + O || + ((q = this[g + 'Setter'] || this._defaultSetter), + q.call(this, y, g, c), + this.shadows && + /^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test( + g, + ) && + this.updateShadows(g, y, q)); + }, + this, + ), + this.afterSetters()); + b && b(); + return d; + }, + afterSetters: function() { + this.doTransform && (this.updateTransform(), (this.doTransform = !1)); + }, + updateShadows: function(a, g, b) { + for (var y = this.shadows, v = y.length; v--; ) + b.call( + y[v], + 'height' === a + ? Math.max(g - (y[v].cutHeight || 0), 0) + : 'd' === a + ? this.d + : g, + a, + y[v], + ); + }, + addClass: function(a, g) { + var y = this.attr('class') || ''; + -1 === y.indexOf(a) && + (g || (a = (y + (y ? ' ' : '') + a).replace(' ', ' ')), + this.attr('class', a)); + return this; + }, + hasClass: function(a) { + return -1 !== B(a, (this.attr('class') || '').split(' ')); + }, + removeClass: function(a) { + return this.attr('class', (this.attr('class') || '').replace(a, '')); + }, + symbolAttr: function(a) { + var y = this; + d( + 'x y r start end width height innerR anchorX anchorY'.split(' '), + function(g) { + y[g] = G(a[g], y[g]); + }, + ); + y.attr({ + d: y.renderer.symbols[y.symbolName](y.x, y.y, y.width, y.height, y), + }); + }, + clip: function(a) { + return this.attr( + 'clip-path', + a ? 'url(' + this.renderer.url + '#' + a.id + ')' : 'none', + ); + }, + crisp: function(a, g) { + var y; + g = g || a.strokeWidth || 0; + y = (Math.round(g) % 2) / 2; + a.x = Math.floor(a.x || this.x || 0) + y; + a.y = Math.floor(a.y || this.y || 0) + y; + a.width = Math.floor((a.width || this.width || 0) - 2 * y); + a.height = Math.floor((a.height || this.height || 0) - 2 * y); + u(a.strokeWidth) && (a.strokeWidth = g); + return a; + }, + css: function(a) { + var y = this.styles, + b = {}, + v = this.element, + k, + d = '', + q, + e = !y, + z = ['textOutline', 'textOverflow', 'width']; + a && a.color && (a.fill = a.color); + y && + F(a, function(a, g) { + a !== y[g] && ((b[g] = a), (e = !0)); + }); + e && + (y && (a = c(y, b)), + (k = this.textWidth = + a && + a.width && + 'auto' !== a.width && + 'text' === v.nodeName.toLowerCase() && + g(a.width)), + (this.styles = a), + k && !L && this.renderer.forExport && delete a.width, + K && !L + ? n(this.element, a) + : ((q = function(a, y) { + return '-' + y.toLowerCase(); + }), + F(a, function(a, y) { + -1 === B(y, z) && + (d += y.replace(/([A-Z])/g, q) + ':' + a + ';'); + }), + d && f(v, 'style', d)), + this.added && + ('text' === this.element.nodeName && this.renderer.buildText(this), + a && a.textOutline && this.applyTextOutline(a.textOutline))); + return this; + }, + strokeWidth: function() { + return this['stroke-width'] || 0; + }, + on: function(a, g) { + var y = this, + b = y.element; + z && 'click' === a + ? ((b.ontouchstart = function(a) { + y.touchEventFired = Date.now(); + a.preventDefault(); + g.call(b, a); + }), + (b.onclick = function(a) { + (-1 === R.navigator.userAgent.indexOf('Android') || + 1100 < Date.now() - (y.touchEventFired || 0)) && + g.call(b, a); + })) + : (b['on' + a] = g); + return this; + }, + setRadialReference: function(a) { + var y = this.renderer.gradients[this.element.gradient]; + this.element.radialReference = a; + y && y.radAttr && y.animate(this.renderer.getRadialAttr(a, y.radAttr)); + return this; + }, + translate: function(a, g) { + return this.attr({ translateX: a, translateY: g }); + }, + invert: function(a) { + this.inverted = a; + this.updateTransform(); + return this; + }, + updateTransform: function() { + var a = this.translateX || 0, + g = this.translateY || 0, + b = this.scaleX, + v = this.scaleY, + c = this.inverted, + k = this.rotation, + d = this.matrix, + q = this.element; + c && ((a += this.width), (g += this.height)); + a = ['translate(' + a + ',' + g + ')']; + u(d) && a.push('matrix(' + d.join(',') + ')'); + c + ? a.push('rotate(90) scale(-1,1)') + : k && + a.push( + 'rotate(' + + k + + ' ' + + G(this.rotationOriginX, q.getAttribute('x'), 0) + + ' ' + + G(this.rotationOriginY, q.getAttribute('y') || 0) + + ')', + ); + (u(b) || u(v)) && a.push('scale(' + G(b, 1) + ' ' + G(v, 1) + ')'); + a.length && q.setAttribute('transform', a.join(' ')); + }, + toFront: function() { + var a = this.element; + a.parentNode.appendChild(a); + return this; + }, + align: function(a, g, v) { + var y, + c, + k, + d, + q = {}; + c = this.renderer; + k = c.alignedObjects; + var e, O; + if (a) { + if ( + ((this.alignOptions = a), (this.alignByTranslate = g), !v || C(v)) + ) + (this.alignTo = y = v || 'renderer'), + b(k, this), + k.push(this), + (v = null); + } else + (a = this.alignOptions), + (g = this.alignByTranslate), + (y = this.alignTo); + v = G(v, c[y], c); + y = a.align; + c = a.verticalAlign; + k = (v.x || 0) + (a.x || 0); + d = (v.y || 0) + (a.y || 0); + 'right' === y ? (e = 1) : 'center' === y && (e = 2); + e && (k += (v.width - (a.width || 0)) / e); + q[g ? 'translateX' : 'x'] = Math.round(k); + 'bottom' === c ? (O = 1) : 'middle' === c && (O = 2); + O && (d += (v.height - (a.height || 0)) / O); + q[g ? 'translateY' : 'y'] = Math.round(d); + this[this.placed ? 'animate' : 'attr'](q); + this.placed = !0; + this.alignAttr = q; + return this; + }, + getBBox: function(a, g) { + var y, + b = this.renderer, + v, + k = this.element, + q = this.styles, + O, + z = this.textStr, + h, + m = b.cache, + L = b.cacheKeys, + A; + g = G(g, this.rotation); + v = g * e; + O = q && q.fontSize; + u(z) && + ((A = z.toString()), + -1 === A.indexOf('\x3c') && (A = A.replace(/[0-9]/g, '0')), + (A += ['', g || 0, O, q && q.width, q && q.textOverflow].join())); + A && !a && (y = m[A]); + if (!y) { + if (k.namespaceURI === this.SVG_NS || b.forExport) { + try { + (h = + this.fakeTS && + function(a) { + d(k.querySelectorAll('.highcharts-text-outline'), function( + y, + ) { + y.style.display = a; + }); + }) && h('none'), + (y = k.getBBox + ? c({}, k.getBBox()) + : { width: k.offsetWidth, height: k.offsetHeight }), + h && h(''); + } catch (W) {} + if (!y || 0 > y.width) y = { width: 0, height: 0 }; + } else y = this.htmlGetBBox(); + b.isSVG && + ((a = y.width), + (b = y.height), + q && + '11px' === q.fontSize && + 17 === Math.round(b) && + (y.height = b = 14), + g && + ((y.width = + Math.abs(b * Math.sin(v)) + Math.abs(a * Math.cos(v))), + (y.height = + Math.abs(b * Math.cos(v)) + Math.abs(a * Math.sin(v))))); + if (A && 0 < y.height) { + for (; 250 < L.length; ) delete m[L.shift()]; + m[A] || L.push(A); + m[A] = y; + } + } + return y; + }, + show: function(a) { + return this.attr({ visibility: a ? 'inherit' : 'visible' }); + }, + hide: function() { + return this.attr({ visibility: 'hidden' }); + }, + fadeOut: function(a) { + var y = this; + y.animate( + { opacity: 0 }, + { + duration: a || 150, + complete: function() { + y.attr({ y: -9999 }); + }, + }, + ); + }, + add: function(a) { + var y = this.renderer, + g = this.element, + b; + a && (this.parentGroup = a); + this.parentInverted = a && a.inverted; + void 0 !== this.textStr && y.buildText(this); + this.added = !0; + if (!a || a.handleZ || this.zIndex) b = this.zIndexSetter(); + b || (a ? a.element : y.box).appendChild(g); + if (this.onAdd) this.onAdd(); + return this; + }, + safeRemoveChild: function(a) { + var y = a.parentNode; + y && y.removeChild(a); + }, + destroy: function() { + var a = this, + g = a.element || {}, + v = a.renderer.isSVG && 'SPAN' === g.nodeName && a.parentGroup, + c = g.ownerSVGElement; + g.onclick = g.onmouseout = g.onmouseover = g.onmousemove = g.point = null; + Q(a); + a.clipPath && + c && + (d(c.querySelectorAll('[clip-path],[CLIP-PATH]'), function(g) { + g + .getAttribute('clip-path') + .match(RegExp('[("]#' + a.clipPath.element.id + '[)"]')) && + g.removeAttribute('clip-path'); + }), + (a.clipPath = a.clipPath.destroy())); + if (a.stops) { + for (c = 0; c < a.stops.length; c++) + a.stops[c] = a.stops[c].destroy(); + a.stops = null; + } + a.safeRemoveChild(g); + for (a.destroyShadows(); v && v.div && 0 === v.div.childNodes.length; ) + (g = v.parentGroup), a.safeRemoveChild(v.div), delete v.div, (v = g); + a.alignTo && b(a.renderer.alignedObjects, a); + F(a, function(g, y) { + delete a[y]; + }); + return null; + }, + shadow: function(a, g, b) { + var y = [], + v, + c, + k = this.element, + d, + q, + e, + z; + if (!a) this.destroyShadows(); + else if (!this.shadows) { + q = G(a.width, 3); + e = (a.opacity || 0.15) / q; + z = this.parentInverted + ? '(-1,-1)' + : '(' + G(a.offsetX, 1) + ', ' + G(a.offsetY, 1) + ')'; + for (v = 1; v <= q; v++) + (c = k.cloneNode(0)), + (d = 2 * q + 1 - 2 * v), + f(c, { + isShadow: 'true', + stroke: a.color || '#000000', + 'stroke-opacity': e * v, + 'stroke-width': d, + transform: 'translate' + z, + fill: 'none', + }), + b && + (f(c, 'height', Math.max(f(c, 'height') - d, 0)), + (c.cutHeight = d)), + g + ? g.element.appendChild(c) + : k.parentNode && k.parentNode.insertBefore(c, k), + y.push(c); + this.shadows = y; + } + return this; + }, + destroyShadows: function() { + d( + this.shadows || [], + function(a) { + this.safeRemoveChild(a); + }, + this, + ); + this.shadows = void 0; + }, + xGetter: function(a) { + 'circle' === this.element.nodeName && + ('x' === a ? (a = 'cx') : 'y' === a && (a = 'cy')); + return this._defaultGetter(a); + }, + _defaultGetter: function(a) { + a = G( + this[a + 'Value'], + this[a], + this.element ? this.element.getAttribute(a) : null, + 0, + ); + /^[\-0-9\.]+$/.test(a) && (a = parseFloat(a)); + return a; + }, + dSetter: function(a, g, b) { + a && a.join && (a = a.join(' ')); + /(NaN| {2}|^$)/.test(a) && (a = 'M 0 0'); + this[g] !== a && (b.setAttribute(g, a), (this[g] = a)); + }, + dashstyleSetter: function(a) { + var b, + v = this['stroke-width']; + 'inherit' === v && (v = 1); + if ((a = a && a.toLowerCase())) { + a = a + .replace('shortdashdotdot', '3,1,1,1,1,1,') + .replace('shortdashdot', '3,1,1,1') + .replace('shortdot', '1,1,') + .replace('shortdash', '3,1,') + .replace('longdash', '8,3,') + .replace(/dot/g, '1,3,') + .replace('dash', '4,3,') + .replace(/,$/, '') + .split(','); + for (b = a.length; b--; ) a[b] = g(a[b]) * v; + a = a.join(',').replace(/NaN/g, 'none'); + this.element.setAttribute('stroke-dasharray', a); + } + }, + alignSetter: function(a) { + this.alignValue = a; + this.element.setAttribute( + 'text-anchor', + { left: 'start', center: 'middle', right: 'end' }[a], + ); + }, + opacitySetter: function(a, g, b) { + this[g] = a; + b.setAttribute(g, a); + }, + titleSetter: function(a) { + var g = this.element.getElementsByTagName('title')[0]; + g || + ((g = m.createElementNS(this.SVG_NS, 'title')), + this.element.appendChild(g)); + g.firstChild && g.removeChild(g.firstChild); + g.appendChild( + m.createTextNode(String(G(a), '').replace(/<[^>]*>/g, '')), + ); + }, + textSetter: function(a) { + a !== this.textStr && + (delete this.bBox, + (this.textStr = a), + this.added && this.renderer.buildText(this)); + }, + fillSetter: function(a, g, b) { + 'string' === typeof a + ? b.setAttribute(g, a) + : a && this.colorGradient(a, g, b); + }, + visibilitySetter: function(a, g, b) { + 'inherit' === a + ? b.removeAttribute(g) + : this[g] !== a && b.setAttribute(g, a); + this[g] = a; + }, + zIndexSetter: function(a, b) { + var v = this.renderer, + y = this.parentGroup, + c = (y || v).element || v.box, + k, + d = this.element, + q, + e, + v = c === v.box; + k = this.added; + var z; + u(a) && + ((d.zIndex = a), (a = +a), this[b] === a && (k = !1), (this[b] = a)); + if (k) { + (a = this.zIndex) && y && (y.handleZ = !0); + b = c.childNodes; + for (z = b.length - 1; 0 <= z && !q; z--) + if (((y = b[z]), (k = y.zIndex), (e = !u(k)), y !== d)) + if (0 > a && e && !v && !z) c.insertBefore(d, b[z]), (q = !0); + else if (g(k) <= a || (e && (!u(a) || 0 <= a))) + c.insertBefore(d, b[z + 1] || null), (q = !0); + q || (c.insertBefore(d, b[v ? 3 : 0] || null), (q = !0)); + } + return q; + }, + _defaultSetter: function(a, g, b) { + b.setAttribute(g, a); + }, + }); + E.prototype.yGetter = E.prototype.xGetter; + E.prototype.translateXSetter = E.prototype.translateYSetter = E.prototype.rotationSetter = E.prototype.verticalAlignSetter = E.prototype.rotationOriginXSetter = E.prototype.rotationOriginYSetter = E.prototype.scaleXSetter = E.prototype.scaleYSetter = E.prototype.matrixSetter = function( + a, + g, + ) { + this[g] = a; + this.doTransform = !0; + }; + E.prototype['stroke-widthSetter'] = E.prototype.strokeSetter = function( + a, + g, + b, + ) { + this[g] = a; + this.stroke && this['stroke-width'] + ? (E.prototype.fillSetter.call(this, this.stroke, 'stroke', b), + b.setAttribute('stroke-width', this['stroke-width']), + (this.hasStroke = !0)) + : 'stroke-width' === g && + 0 === a && + this.hasStroke && + (b.removeAttribute('stroke'), (this.hasStroke = !1)); + }; + D = a.SVGRenderer = function() { + this.init.apply(this, arguments); + }; + c(D.prototype, { + Element: E, + SVG_NS: P, + init: function(a, g, b, v, c, k) { + var y; + v = this.createElement('svg') + .attr({ version: '1.1', class: 'highcharts-root' }) + .css(this.getStyle(v)); + y = v.element; + a.appendChild(y); + f(a, 'dir', 'ltr'); + -1 === a.innerHTML.indexOf('xmlns') && f(y, 'xmlns', this.SVG_NS); + this.isSVG = !0; + this.box = y; + this.boxWrapper = v; + this.alignedObjects = []; + this.url = + (x || N) && m.getElementsByTagName('base').length + ? R.location.href + .replace(/#.*?$/, '') + .replace(/<[^>]*>/g, '') + .replace(/([\('\)])/g, '\\$1') + .replace(/ /g, '%20') + : ''; + this.createElement('desc') + .add() + .element.appendChild( + m.createTextNode('Created with Highcharts 6.0.4'), + ); + this.defs = this.createElement('defs').add(); + this.allowHTML = k; + this.forExport = c; + this.gradients = {}; + this.cache = {}; + this.cacheKeys = []; + this.imgCount = 0; + this.setSize(g, b, !1); + var d; + x && + a.getBoundingClientRect && + ((g = function() { + n(a, { left: 0, top: 0 }); + d = a.getBoundingClientRect(); + n(a, { + left: Math.ceil(d.left) - d.left + 'px', + top: Math.ceil(d.top) - d.top + 'px', + }); + }), + g(), + (this.unSubPixelFix = H(R, 'resize', g))); + }, + getStyle: function(a) { + return (this.style = c( + { + fontFamily: + '"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif', + fontSize: '12px', + }, + a, + )); + }, + setStyle: function(a) { + this.boxWrapper.css(this.getStyle(a)); + }, + isHidden: function() { + return !this.boxWrapper.getBBox().width; + }, + destroy: function() { + var a = this.defs; + this.box = null; + this.boxWrapper = this.boxWrapper.destroy(); + h(this.gradients || {}); + this.gradients = null; + a && (this.defs = a.destroy()); + this.unSubPixelFix && this.unSubPixelFix(); + return (this.alignedObjects = null); + }, + createElement: function(a) { + var g = new this.Element(); + g.init(this, a); + return g; + }, + draw: A, + getRadialAttr: function(a, g) { + return { + cx: a[0] - a[2] / 2 + g.cx * a[2], + cy: a[1] - a[2] / 2 + g.cy * a[2], + r: g.r * a[2], + }; + }, + getSpanWidth: function(a, g) { + var b = a.getBBox(!0).width; + !L && + this.forExport && + (b = this.measureSpanWidth(g.firstChild.data, a.styles)); + return b; + }, + applyEllipsis: function(a, g, b, v) { + var c = a.rotation, + y = b, + k, + d = 0, + q = b.length, + e = function(a) { + g.removeChild(g.firstChild); + a && g.appendChild(m.createTextNode(a)); + }, + z; + a.rotation = 0; + y = this.getSpanWidth(a, g); + if ((z = y > v)) { + for (; d <= q; ) + (k = Math.ceil((d + q) / 2)), + (y = b.substring(0, k) + '\u2026'), + e(y), + (y = this.getSpanWidth(a, g)), + d === q ? (d = q + 1) : y > v ? (q = k - 1) : (d = k); + 0 === q && e(''); + } + a.rotation = c; + return z; + }, + escapes: { + '\x26': '\x26amp;', + '\x3c': '\x26lt;', + '\x3e': '\x26gt;', + "'": '\x26#39;', + '"': '\x26quot;', + }, + buildText: function(a) { + var b = a.element, + v = this, + c = v.forExport, + y = G(a.textStr, '').toString(), + q = -1 !== y.indexOf('\x3c'), + e = b.childNodes, + z, + h, + A, + J, + t = f(b, 'x'), + x = a.styles, + B = a.textWidth, + l = x && x.lineHeight, + C = x && x.textOutline, + u = x && 'ellipsis' === x.textOverflow, + Q = x && 'nowrap' === x.whiteSpace, + w = x && x.fontSize, + R, + I, + r = e.length, + x = B && !a.added && this.box, + p = function(a) { + var c; + c = /(px|em)$/.test(a && a.style.fontSize) + ? a.style.fontSize + : w || v.style.fontSize || 12; + return l + ? g(l) + : v.fontMetrics(c, a.getAttribute('style') ? a : b).h; + }, + K = function(a) { + F(v.escapes, function(g, b) { + a = a.replace(new RegExp(g, 'g'), b); + }); + return a; + }; + R = [y, u, Q, l, C, w, B].join(); + if (R !== a.textCache) { + for (a.textCache = R; r--; ) b.removeChild(e[r]); + q || C || u || B || -1 !== y.indexOf(' ') + ? ((z = /<.*class="([^"]+)".*>/), + (h = /<.*style="([^"]+)".*>/), + (A = /<.*href="([^"]+)".*>/), + x && x.appendChild(b), + (y = q + ? y + .replace( + /<(b|strong)>/g, + '\x3cspan style\x3d"font-weight:bold"\x3e', + ) + .replace( + /<(i|em)>/g, + '\x3cspan style\x3d"font-style:italic"\x3e', + ) + .replace(//g, '\x3c/span\x3e') + .split(//g) + : [y]), + (y = k(y, function(a) { + return '' !== a; + })), + d(y, function(g, y) { + var k, + q = 0; + g = g + .replace(/^\s+|\s+$/g, '') + .replace(//g, '\x3c/span\x3e|||'); + k = g.split('|||'); + d(k, function(g) { + if ('' !== g || 1 === k.length) { + var d = {}, + e = m.createElementNS(v.SVG_NS, 'tspan'), + x, + F; + z.test(g) && ((x = g.match(z)[1]), f(e, 'class', x)); + h.test(g) && + ((F = g + .match(h)[1] + .replace(/(;| |^)color([ :])/, '$1fill$2')), + f(e, 'style', F)); + A.test(g) && + !c && + (f( + e, + 'onclick', + 'location.href\x3d"' + g.match(A)[1] + '"', + ), + f(e, 'class', 'highcharts-anchor'), + n(e, { cursor: 'pointer' })); + g = K(g.replace(/<[a-zA-Z\/](.|\n)*?>/g, '') || ' '); + if (' ' !== g) { + e.appendChild(m.createTextNode(g)); + q ? (d.dx = 0) : y && null !== t && (d.x = t); + f(e, d); + b.appendChild(e); + !q && + I && + (!L && c && n(e, { display: 'block' }), + f(e, 'dy', p(e))); + if (B) { + d = g.replace(/([^\^])-/g, '$1- ').split(' '); + x = 1 < k.length || y || (1 < d.length && !Q); + var O = [], + l, + C = p(e), + G = a.rotation; + for ( + u && (J = v.applyEllipsis(a, e, g, B)); + !u && x && (d.length || O.length); + + ) + (a.rotation = 0), + (l = v.getSpanWidth(a, e)), + (g = l > B), + void 0 === J && (J = g), + g && 1 !== d.length + ? (e.removeChild(e.firstChild), + O.unshift(d.pop())) + : ((d = O), + (O = []), + d.length && + !Q && + ((e = m.createElementNS(P, 'tspan')), + f(e, { dy: C, x: t }), + F && f(e, 'style', F), + b.appendChild(e)), + l > B && (B = l)), + d.length && + e.appendChild( + m.createTextNode( + d.join(' ').replace(/- /g, '-'), + ), + ); + a.rotation = G; + } + q++; + } + } + }); + I = I || b.childNodes.length; + }), + J && a.attr('title', a.textStr), + x && x.removeChild(b), + C && a.applyTextOutline && a.applyTextOutline(C)) + : b.appendChild(m.createTextNode(K(y))); + } + }, + getContrast: function(a) { + a = r(a).rgba; + return 510 < a[0] + a[1] + a[2] ? '#000000' : '#FFFFFF'; + }, + button: function(a, g, b, v, d, k, e, z, h) { + var y = this.label(a, g, b, h, null, null, null, null, 'button'), + m = 0; + y.attr(q({ padding: 8, r: 2 }, d)); + var A, L, J, t; + d = q( + { + fill: '#f7f7f7', + stroke: '#cccccc', + 'stroke-width': 1, + style: { + color: '#333333', + cursor: 'pointer', + fontWeight: 'normal', + }, + }, + d, + ); + A = d.style; + delete d.style; + k = q(d, { fill: '#e6e6e6' }, k); + L = k.style; + delete k.style; + e = q( + d, + { fill: '#e6ebf5', style: { color: '#000000', fontWeight: 'bold' } }, + e, + ); + J = e.style; + delete e.style; + z = q(d, { style: { color: '#cccccc' } }, z); + t = z.style; + delete z.style; + H(y.element, K ? 'mouseover' : 'mouseenter', function() { + 3 !== m && y.setState(1); + }); + H(y.element, K ? 'mouseout' : 'mouseleave', function() { + 3 !== m && y.setState(m); + }); + y.setState = function(a) { + 1 !== a && (y.state = m = a); + y.removeClass( + /highcharts-button-(normal|hover|pressed|disabled)/, + ).addClass( + 'highcharts-button-' + + ['normal', 'hover', 'pressed', 'disabled'][a || 0], + ); + y.attr([d, k, e, z][a || 0]).css([A, L, J, t][a || 0]); + }; + y.attr(d).css(c({ cursor: 'default' }, A)); + return y.on('click', function(a) { + 3 !== m && v.call(y, a); + }); + }, + crispLine: function(a, g) { + a[1] === a[4] && (a[1] = a[4] = Math.round(a[1]) - (g % 2) / 2); + a[2] === a[5] && (a[2] = a[5] = Math.round(a[2]) + (g % 2) / 2); + return a; + }, + path: function(a) { + var g = { fill: 'none' }; + I(a) ? (g.d = a) : t(a) && c(g, a); + return this.createElement('path').attr(g); + }, + circle: function(a, g, b) { + a = t(a) ? a : { x: a, y: g, r: b }; + g = this.createElement('circle'); + g.xSetter = g.ySetter = function(a, g, b) { + b.setAttribute('c' + g, a); + }; + return g.attr(a); + }, + arc: function(a, g, b, v, c, d) { + t(a) + ? ((v = a), (g = v.y), (b = v.r), (a = v.x)) + : (v = { innerR: v, start: c, end: d }); + a = this.symbol('arc', a, g, b, b, v); + a.r = b; + return a; + }, + rect: function(a, g, b, v, c, d) { + c = t(a) ? a.r : c; + var k = this.createElement('rect'); + a = t(a) + ? a + : void 0 === a + ? {} + : { x: a, y: g, width: Math.max(b, 0), height: Math.max(v, 0) }; + void 0 !== d && ((a.strokeWidth = d), (a = k.crisp(a))); + a.fill = 'none'; + c && (a.r = c); + k.rSetter = function(a, g, b) { + f(b, { rx: a, ry: a }); + }; + return k.attr(a); + }, + setSize: function(a, g, b) { + var v = this.alignedObjects, + c = v.length; + this.width = a; + this.height = g; + for ( + this.boxWrapper.animate( + { width: a, height: g }, + { + step: function() { + this.attr({ + viewBox: + '0 0 ' + this.attr('width') + ' ' + this.attr('height'), + }); + }, + duration: G(b, !0) ? void 0 : 0, + }, + ); + c--; + + ) + v[c].align(); + }, + g: function(a) { + var g = this.createElement('g'); + return a ? g.attr({ class: 'highcharts-' + a }) : g; + }, + image: function(a, g, b, v, d) { + var k = { preserveAspectRatio: 'none' }; + 1 < arguments.length && c(k, { x: g, y: b, width: v, height: d }); + k = this.createElement('image').attr(k); + k.element.setAttributeNS + ? k.element.setAttributeNS('http://www.w3.org/1999/xlink', 'href', a) + : k.element.setAttribute('hc-svg-href', a); + return k; + }, + symbol: function(a, g, b, v, k, q) { + var e = this, + y, + z = /^url\((.*?)\)$/, + h = z.test(a), + A = !h && (this.symbols[a] ? a : 'circle'), + L = A && this.symbols[A], + t = + u(g) && + L && + L.call(this.symbols, Math.round(g), Math.round(b), v, k, q), + x, + F; + L + ? ((y = this.path(t)), + y.attr('fill', 'none'), + c(y, { symbolName: A, x: g, y: b, width: v, height: k }), + q && c(y, q)) + : h && + ((x = a.match(z)[1]), + (y = this.image(x)), + (y.imgwidth = G(J[x] && J[x].width, q && q.width)), + (y.imgheight = G(J[x] && J[x].height, q && q.height)), + (F = function() { + y.attr({ width: y.width, height: y.height }); + }), + d(['width', 'height'], function(a) { + y[a + 'Setter'] = function(a, g) { + var b = {}, + v = this['img' + g], + c = 'width' === g ? 'translateX' : 'translateY'; + this[g] = a; + u(v) && + (this.element && this.element.setAttribute(g, v), + this.alignByTranslate || + ((b[c] = ((this[g] || 0) - v) / 2), this.attr(b))); + }; + }), + u(g) && y.attr({ x: g, y: b }), + (y.isImg = !0), + u(y.imgwidth) && u(y.imgheight) + ? F() + : (y.attr({ width: 0, height: 0 }), + w('img', { + onload: function() { + var a = l[e.chartIndex]; + 0 === this.width && + (n(this, { position: 'absolute', top: '-999em' }), + m.body.appendChild(this)); + J[x] = { width: this.width, height: this.height }; + y.imgwidth = this.width; + y.imgheight = this.height; + y.element && F(); + this.parentNode && this.parentNode.removeChild(this); + e.imgCount--; + if (!e.imgCount && a && a.onload) a.onload(); + }, + src: x, + }), + this.imgCount++)); + return y; + }, + symbols: { + circle: function(a, g, b, v) { + return this.arc(a + b / 2, g + v / 2, b / 2, v / 2, { + start: 0, + end: 2 * Math.PI, + open: !1, + }); + }, + square: function(a, g, b, v) { + return ['M', a, g, 'L', a + b, g, a + b, g + v, a, g + v, 'Z']; + }, + triangle: function(a, g, b, v) { + return ['M', a + b / 2, g, 'L', a + b, g + v, a, g + v, 'Z']; + }, + 'triangle-down': function(a, g, b, v) { + return ['M', a, g, 'L', a + b, g, a + b / 2, g + v, 'Z']; + }, + diamond: function(a, g, b, v) { + return [ + 'M', + a + b / 2, + g, + 'L', + a + b, + g + v / 2, + a + b / 2, + g + v, + a, + g + v / 2, + 'Z', + ]; + }, + arc: function(a, g, b, v, c) { + var k = c.start, + d = c.r || b, + q = c.r || v || b, + e = c.end - 0.001; + b = c.innerR; + v = G(c.open, 0.001 > Math.abs(c.end - c.start - 2 * Math.PI)); + var y = Math.cos(k), + z = Math.sin(k), + h = Math.cos(e), + e = Math.sin(e); + c = 0.001 > c.end - k - Math.PI ? 0 : 1; + d = [ + 'M', + a + d * y, + g + q * z, + 'A', + d, + q, + 0, + c, + 1, + a + d * h, + g + q * e, + ]; + u(b) && + d.push( + v ? 'M' : 'L', + a + b * h, + g + b * e, + 'A', + b, + b, + 0, + c, + 0, + a + b * y, + g + b * z, + ); + d.push(v ? '' : 'Z'); + return d; + }, + callout: function(a, g, b, v, c) { + var d = Math.min((c && c.r) || 0, b, v), + k = d + 6, + q = c && c.anchorX; + c = c && c.anchorY; + var e; + e = [ + 'M', + a + d, + g, + 'L', + a + b - d, + g, + 'C', + a + b, + g, + a + b, + g, + a + b, + g + d, + 'L', + a + b, + g + v - d, + 'C', + a + b, + g + v, + a + b, + g + v, + a + b - d, + g + v, + 'L', + a + d, + g + v, + 'C', + a, + g + v, + a, + g + v, + a, + g + v - d, + 'L', + a, + g + d, + 'C', + a, + g, + a, + g, + a + d, + g, + ]; + q && q > b + ? c > g + k && c < g + v - k + ? e.splice( + 13, + 3, + 'L', + a + b, + c - 6, + a + b + 6, + c, + a + b, + c + 6, + a + b, + g + v - d, + ) + : e.splice( + 13, + 3, + 'L', + a + b, + v / 2, + q, + c, + a + b, + v / 2, + a + b, + g + v - d, + ) + : q && 0 > q + ? c > g + k && c < g + v - k + ? e.splice(33, 3, 'L', a, c + 6, a - 6, c, a, c - 6, a, g + d) + : e.splice(33, 3, 'L', a, v / 2, q, c, a, v / 2, a, g + d) + : c && c > v && q > a + k && q < a + b - k + ? e.splice( + 23, + 3, + 'L', + q + 6, + g + v, + q, + g + v + 6, + q - 6, + g + v, + a + d, + g + v, + ) + : c && + 0 > c && + q > a + k && + q < a + b - k && + e.splice(3, 3, 'L', q - 6, g, q, g - 6, q + 6, g, b - d, g); + return e; + }, + }, + clipRect: function(g, b, v, c) { + var d = a.uniqueKey(), + k = this.createElement('clipPath') + .attr({ id: d }) + .add(this.defs); + g = this.rect(g, b, v, c, 0).add(k); + g.id = d; + g.clipPath = k; + g.count = 0; + return g; + }, + text: function(a, g, b, v) { + var c = {}; + if (v && (this.allowHTML || !this.forExport)) return this.html(a, g, b); + c.x = Math.round(g || 0); + b && (c.y = Math.round(b)); + if (a || 0 === a) c.text = a; + a = this.createElement('text').attr(c); + v || + (a.xSetter = function(a, g, b) { + var v = b.getElementsByTagName('tspan'), + c, + d = b.getAttribute(g), + k; + for (k = 0; k < v.length; k++) + (c = v[k]), c.getAttribute(g) === d && c.setAttribute(g, a); + b.setAttribute(g, a); + }); + return a; + }, + fontMetrics: function(a, b) { + a = + a || + (b && b.style && b.style.fontSize) || + (this.style && this.style.fontSize); + a = /px/.test(a) + ? g(a) + : /em/.test(a) + ? parseFloat(a) * (b ? this.fontMetrics(null, b.parentNode).f : 16) + : 12; + b = 24 > a ? a + 3 : Math.round(1.2 * a); + return { h: b, b: Math.round(0.8 * b), f: a }; + }, + rotCorr: function(a, g, b) { + var v = a; + g && b && (v = Math.max(v * Math.cos(g * e), 4)); + return { x: (-a / 3) * Math.sin(g * e), y: v }; + }, + label: function(g, b, k, e, z, h, m, A, L) { + var y = this, + J = y.g('button' !== L && 'label'), + t = (J.text = y.text('', 0, 0, m).attr({ zIndex: 1 })), + x, + F, + n = 0, + B = 3, + l = 0, + C, + f, + Q, + G, + w, + R = {}, + I, + P, + r = /^url\((.*?)\)$/.test(e), + p = r, + K, + O, + N, + T; + L && J.addClass('highcharts-' + L); + p = r; + K = function() { + return ((I || 0) % 2) / 2; + }; + O = function() { + var a = t.element.style, + g = {}; + F = + (void 0 === C || void 0 === f || w) && u(t.textStr) && t.getBBox(); + J.width = (C || F.width || 0) + 2 * B + l; + J.height = (f || F.height || 0) + 2 * B; + P = B + y.fontMetrics(a && a.fontSize, t).b; + p && + (x || + ((J.box = x = y.symbols[e] || r ? y.symbol(e) : y.rect()), + x.addClass( + ('button' === L ? '' : 'highcharts-label-box') + + (L ? ' highcharts-' + L + '-box' : ''), + ), + x.add(J), + (a = K()), + (g.x = a), + (g.y = (A ? -P : 0) + a)), + (g.width = Math.round(J.width)), + (g.height = Math.round(J.height)), + x.attr(c(g, R)), + (R = {})); + }; + N = function() { + var a = l + B, + g; + g = A ? 0 : P; + u(C) && + F && + ('center' === w || 'right' === w) && + (a += { center: 0.5, right: 1 }[w] * (C - F.width)); + if (a !== t.x || g !== t.y) + t.attr('x', a), void 0 !== g && t.attr('y', g); + t.x = a; + t.y = g; + }; + T = function(a, g) { + x ? x.attr(a, g) : (R[a] = g); + }; + J.onAdd = function() { + t.add(J); + J.attr({ text: g || 0 === g ? g : '', x: b, y: k }); + x && u(z) && J.attr({ anchorX: z, anchorY: h }); + }; + J.widthSetter = function(g) { + C = a.isNumber(g) ? g : null; + }; + J.heightSetter = function(a) { + f = a; + }; + J['text-alignSetter'] = function(a) { + w = a; + }; + J.paddingSetter = function(a) { + u(a) && a !== B && ((B = J.padding = a), N()); + }; + J.paddingLeftSetter = function(a) { + u(a) && a !== l && ((l = a), N()); + }; + J.alignSetter = function(a) { + a = { left: 0, center: 0.5, right: 1 }[a]; + a !== n && ((n = a), F && J.attr({ x: Q })); + }; + J.textSetter = function(a) { + void 0 !== a && t.textSetter(a); + O(); + N(); + }; + J['stroke-widthSetter'] = function(a, g) { + a && (p = !0); + I = this['stroke-width'] = a; + T(g, a); + }; + J.strokeSetter = J.fillSetter = J.rSetter = function(a, g) { + 'r' !== g && ('fill' === g && a && (p = !0), (J[g] = a)); + T(g, a); + }; + J.anchorXSetter = function(a, g) { + z = J.anchorX = a; + T(g, Math.round(a) - K() - Q); + }; + J.anchorYSetter = function(a, g) { + h = J.anchorY = a; + T(g, a - G); + }; + J.xSetter = function(a) { + J.x = a; + n && (a -= n * ((C || F.width) + 2 * B)); + Q = Math.round(a); + J.attr('translateX', Q); + }; + J.ySetter = function(a) { + G = J.y = Math.round(a); + J.attr('translateY', G); + }; + var U = J.css; + return c(J, { + css: function(a) { + if (a) { + var g = {}; + a = q(a); + d(J.textProps, function(b) { + void 0 !== a[b] && ((g[b] = a[b]), delete a[b]); + }); + t.css(g); + } + return U.call(J, a); + }, + getBBox: function() { + return { + width: F.width + 2 * B, + height: F.height + 2 * B, + x: F.x - B, + y: F.y - B, + }; + }, + shadow: function(a) { + a && (O(), x && x.shadow(a)); + return J; + }, + destroy: function() { + v(J.element, 'mouseenter'); + v(J.element, 'mouseleave'); + t && (t = t.destroy()); + x && (x = x.destroy()); + E.prototype.destroy.call(J); + J = y = O = N = T = null; + }, + }); + }, + }); + a.Renderer = D; + })(M); + (function(a) { + var E = a.attr, + D = a.createElement, + H = a.css, + p = a.defined, + f = a.each, + l = a.extend, + r = a.isFirefox, + n = a.isMS, + w = a.isWebKit, + u = a.pick, + e = a.pInt, + h = a.SVGRenderer, + m = a.win, + d = a.wrap; + l(a.SVGElement.prototype, { + htmlCss: function(a) { + var b = this.element; + if ((b = a && 'SPAN' === b.tagName && a.width)) + delete a.width, (this.textWidth = b), this.updateTransform(); + a && + 'ellipsis' === a.textOverflow && + ((a.whiteSpace = 'nowrap'), (a.overflow = 'hidden')); + this.styles = l(this.styles, a); + H(this.element, a); + return this; + }, + htmlGetBBox: function() { + var a = this.element; + return { + x: a.offsetLeft, + y: a.offsetTop, + width: a.offsetWidth, + height: a.offsetHeight, + }; + }, + htmlUpdateTransform: function() { + if (this.added) { + var a = this.renderer, + b = this.element, + d = this.translateX || 0, + z = this.translateY || 0, + h = this.x || 0, + m = this.y || 0, + x = this.textAlign || 'left', + n = { left: 0, center: 0.5, right: 1 }[x], + t = this.styles; + H(b, { marginLeft: d, marginTop: z }); + this.shadows && + f(this.shadows, function(a) { + H(a, { marginLeft: d + 1, marginTop: z + 1 }); + }); + this.inverted && + f(b.childNodes, function(c) { + a.invertChild(c, b); + }); + if ('SPAN' === b.tagName) { + var l = this.rotation, + u = e(this.textWidth), + q = t && t.whiteSpace, + A = [l, x, b.innerHTML, this.textWidth, this.textAlign].join(); + A !== this.cTT && + ((t = a.fontMetrics(b.style.fontSize).b), + p(l) && this.setSpanRotation(l, n, t), + H(b, { width: '', whiteSpace: q || 'nowrap' }), + b.offsetWidth > u && + /[ \-]/.test(b.textContent || b.innerText) && + H(b, { + width: u + 'px', + display: 'block', + whiteSpace: q || 'normal', + }), + this.getSpanCorrection(b.offsetWidth, t, n, l, x)); + H(b, { + left: h + (this.xCorr || 0) + 'px', + top: m + (this.yCorr || 0) + 'px', + }); + w && (t = b.offsetHeight); + this.cTT = A; + } + } else this.alignOnAdd = !0; + }, + setSpanRotation: function(a, b, d) { + var c = {}, + k = this.renderer.getTransformKey(); + c[k] = c.transform = 'rotate(' + a + 'deg)'; + c[k + (r ? 'Origin' : '-origin')] = c.transformOrigin = + 100 * b + '% ' + d + 'px'; + H(this.element, c); + }, + getSpanCorrection: function(a, b, d) { + this.xCorr = -a * d; + this.yCorr = -b; + }, + }); + l(h.prototype, { + getTransformKey: function() { + return n && !/Edge/.test(m.navigator.userAgent) + ? '-ms-transform' + : w + ? '-webkit-transform' + : r + ? 'MozTransform' + : m.opera + ? '-o-transform' + : ''; + }, + html: function(a, b, k) { + var c = this.createElement('span'), + e = c.element, + h = c.renderer, + m = h.isSVG, + w = function(a, b) { + f(['opacity', 'visibility'], function(c) { + d(a, c + 'Setter', function(a, c, d, k) { + a.call(this, c, d, k); + b[d] = c; + }); + }); + }; + c.textSetter = function(a) { + a !== e.innerHTML && delete this.bBox; + this.textStr = a; + e.innerHTML = u(a, ''); + c.htmlUpdateTransform(); + }; + m && w(c, c.element.style); + c.xSetter = c.ySetter = c.alignSetter = c.rotationSetter = function( + a, + b, + ) { + 'align' === b && (b = 'textAlign'); + c[b] = a; + c.htmlUpdateTransform(); + }; + c.attr({ text: a, x: Math.round(b), y: Math.round(k) }).css({ + fontFamily: this.style.fontFamily, + fontSize: this.style.fontSize, + position: 'absolute', + }); + e.style.whiteSpace = 'nowrap'; + c.css = c.htmlCss; + m && + (c.add = function(a) { + var b, + d = h.box.parentNode, + k = []; + if ((this.parentGroup = a)) { + if (((b = a.div), !b)) { + for (; a; ) k.push(a), (a = a.parentGroup); + f(k.reverse(), function(a) { + function e(g, b) { + a[b] = g; + n + ? (q[h.getTransformKey()] = + 'translate(' + + (a.x || a.translateX) + + 'px,' + + (a.y || a.translateY) + + 'px)') + : 'translateX' === b + ? (q.left = g + 'px') + : (q.top = g + 'px'); + a.doTransform = !0; + } + var q, + g = E(a.element, 'class'); + g && (g = { className: g }); + b = a.div = + a.div || + D( + 'div', + g, + { + position: 'absolute', + left: (a.translateX || 0) + 'px', + top: (a.translateY || 0) + 'px', + display: a.display, + opacity: a.opacity, + pointerEvents: a.styles && a.styles.pointerEvents, + }, + b || d, + ); + q = b.style; + l(a, { + classSetter: (function(a) { + return function(g) { + this.element.setAttribute('class', g); + a.className = g; + }; + })(b), + on: function() { + k[0].div && c.on.apply({ element: k[0].div }, arguments); + return a; + }, + translateXSetter: e, + translateYSetter: e, + }); + w(a, q); + }); + } + } else b = d; + b.appendChild(e); + c.added = !0; + c.alignOnAdd && c.htmlUpdateTransform(); + return c; + }); + return c; + }, + }); + })(M); + (function(a) { + function E() { + var n = a.defaultOptions.global, + l = r.moment; + if (n.timezone) { + if (l) + return function(a) { + return -l.tz(a, n.timezone).utcOffset(); + }; + a.error(25); + } + return n.useUTC && n.getTimezoneOffset; + } + function D() { + var n = a.defaultOptions.global, + f, + u = n.useUTC, + e = u ? 'getUTC' : 'get', + h = u ? 'setUTC' : 'set', + m = 'Minutes Hours Day Date Month FullYear'.split(' '), + d = m.concat(['Milliseconds', 'Seconds']); + a.Date = f = n.Date || r.Date; + f.hcTimezoneOffset = u && n.timezoneOffset; + f.hcGetTimezoneOffset = E(); + f.hcHasTimeZone = !(!f.hcTimezoneOffset && !f.hcGetTimezoneOffset); + f.hcMakeTime = function(a, b, d, e, h, m) { + var c; + u + ? ((c = f.UTC.apply(0, arguments)), (c += p(c))) + : (c = new f(a, b, l(d, 1), l(e, 0), l(h, 0), l(m, 0)).getTime()); + return c; + }; + for (n = 0; n < m.length; n++) f['hcGet' + m[n]] = e + m[n]; + for (n = 0; n < d.length; n++) f['hcSet' + d[n]] = h + d[n]; + } + var H = a.color, + p = a.getTZOffset, + f = a.merge, + l = a.pick, + r = a.win; + a.defaultOptions = { + colors: '#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1'.split( + ' ', + ), + symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'], + lang: { + loading: 'Loading...', + months: 'January February March April May June July August September October November December'.split( + ' ', + ), + shortMonths: 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split( + ' ', + ), + weekdays: 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split( + ' ', + ), + decimalPoint: '.', + numericSymbols: 'kMGTPE'.split(''), + resetZoom: 'Reset zoom', + resetZoomTitle: 'Reset zoom level 1:1', + thousandsSep: ' ', + }, + global: { useUTC: !0 }, + chart: { + borderRadius: 0, + defaultSeriesType: 'line', + ignoreHiddenSeries: !0, + spacing: [10, 10, 15, 10], + resetZoomButton: { + theme: { zIndex: 6 }, + position: { align: 'right', x: -10, y: 10 }, + }, + width: null, + height: null, + borderColor: '#335cad', + backgroundColor: '#ffffff', + plotBorderColor: '#cccccc', + }, + title: { + text: 'Chart title', + align: 'center', + margin: 15, + widthAdjust: -44, + }, + subtitle: { text: '', align: 'center', widthAdjust: -44 }, + plotOptions: {}, + labels: { style: { position: 'absolute', color: '#333333' } }, + legend: { + enabled: !0, + align: 'center', + layout: 'horizontal', + labelFormatter: function() { + return this.name; + }, + borderColor: '#999999', + borderRadius: 0, + navigation: { activeColor: '#003399', inactiveColor: '#cccccc' }, + itemStyle: { + color: '#333333', + fontSize: '12px', + fontWeight: 'bold', + textOverflow: 'ellipsis', + }, + itemHoverStyle: { color: '#000000' }, + itemHiddenStyle: { color: '#cccccc' }, + shadow: !1, + itemCheckboxStyle: { + position: 'absolute', + width: '13px', + height: '13px', + }, + squareSymbol: !0, + symbolPadding: 5, + verticalAlign: 'bottom', + x: 0, + y: 0, + title: { style: { fontWeight: 'bold' } }, + }, + loading: { + labelStyle: { fontWeight: 'bold', position: 'relative', top: '45%' }, + style: { + position: 'absolute', + backgroundColor: '#ffffff', + opacity: 0.5, + textAlign: 'center', + }, + }, + tooltip: { + enabled: !0, + animation: a.svg, + borderRadius: 3, + dateTimeLabelFormats: { + millisecond: '%A, %b %e, %H:%M:%S.%L', + second: '%A, %b %e, %H:%M:%S', + minute: '%A, %b %e, %H:%M', + hour: '%A, %b %e, %H:%M', + day: '%A, %b %e, %Y', + week: 'Week from %A, %b %e, %Y', + month: '%B %Y', + year: '%Y', + }, + footerFormat: '', + padding: 8, + snap: a.isTouchDevice ? 25 : 10, + backgroundColor: H('#f7f7f7') + .setOpacity(0.85) + .get(), + borderWidth: 1, + headerFormat: + '\x3cspan style\x3d"font-size: 10px"\x3e{point.key}\x3c/span\x3e\x3cbr/\x3e', + pointFormat: + '\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e {series.name}: \x3cb\x3e{point.y}\x3c/b\x3e\x3cbr/\x3e', + shadow: !0, + style: { + color: '#333333', + cursor: 'default', + fontSize: '12px', + pointerEvents: 'none', + whiteSpace: 'nowrap', + }, + }, + credits: { + enabled: !0, + href: 'http://www.highcharts.com', + position: { align: 'right', x: -10, verticalAlign: 'bottom', y: -5 }, + style: { cursor: 'pointer', color: '#999999', fontSize: '9px' }, + text: 'Highcharts.com', + }, + }; + a.setOptions = function(n) { + a.defaultOptions = f(!0, a.defaultOptions, n); + D(); + return a.defaultOptions; + }; + a.getOptions = function() { + return a.defaultOptions; + }; + a.defaultPlotOptions = a.defaultOptions.plotOptions; + D(); + })(M); + (function(a) { + var E = a.correctFloat, + D = a.defined, + H = a.destroyObjectProperties, + p = a.isNumber, + f = a.merge, + l = a.pick, + r = a.deg2rad; + a.Tick = function(a, l, f, e) { + this.axis = a; + this.pos = l; + this.type = f || ''; + this.isNewLabel = this.isNew = !0; + f || e || this.addLabel(); + }; + a.Tick.prototype = { + addLabel: function() { + var a = this.axis, + w = a.options, + u = a.chart, + e = a.categories, + h = a.names, + m = this.pos, + d = w.labels, + c = a.tickPositions, + b = m === c[0], + k = m === c[c.length - 1], + h = e ? l(e[m], h[m], m) : m, + e = this.label, + c = c.info, + z; + a.isDatetimeAxis && + c && + (z = w.dateTimeLabelFormats[c.higherRanks[m] || c.unitName]); + this.isFirst = b; + this.isLast = k; + w = a.labelFormatter.call({ + axis: a, + chart: u, + isFirst: b, + isLast: k, + dateTimeLabelFormat: z, + value: a.isLog ? E(a.lin2log(h)) : h, + pos: m, + }); + D(e) + ? e && e.attr({ text: w }) + : ((this.labelLength = + (this.label = e = + D(w) && d.enabled + ? u.renderer + .text(w, 0, 0, d.useHTML) + .css(f(d.style)) + .add(a.labelGroup) + : null) && e.getBBox().width), + (this.rotation = 0)); + }, + getLabelSize: function() { + return this.label + ? this.label.getBBox()[this.axis.horiz ? 'height' : 'width'] + : 0; + }, + handleOverflow: function(a) { + var f = this.axis, + n = f.options.labels, + e = a.x, + h = f.chart.chartWidth, + m = f.chart.spacing, + d = l(f.labelLeft, Math.min(f.pos, m[3])), + m = l( + f.labelRight, + Math.max(f.isRadial ? 0 : f.pos + f.len, h - m[1]), + ), + c = this.label, + b = this.rotation, + k = { left: 0, center: 0.5, right: 1 }[ + f.labelAlign || c.attr('align') + ], + z = c.getBBox().width, + B = f.getSlotWidth(), + I = B, + x = 1, + p, + t = {}; + if (b || !1 === n.overflow) + 0 > b && e - k * z < d + ? (p = Math.round(e / Math.cos(b * r) - d)) + : 0 < b && + e + k * z > m && + (p = Math.round((h - e) / Math.cos(b * r))); + else if ( + ((h = e + (1 - k) * z), + e - k * z < d + ? (I = a.x + I * (1 - k) - d) + : h > m && ((I = m - a.x + I * k), (x = -1)), + (I = Math.min(B, I)), + I < B && + 'center' === f.labelAlign && + (a.x += x * (B - I - k * (B - Math.min(z, I)))), + z > I || (f.autoRotation && (c.styles || {}).width)) + ) + p = I; + p && + ((t.width = p), + (n.style || {}).textOverflow || (t.textOverflow = 'ellipsis'), + c.css(t)); + }, + getPosition: function(a, f, l, e) { + var h = this.axis, + m = h.chart, + d = (e && m.oldChartHeight) || m.chartHeight; + return { + x: a + ? h.translate(f + l, null, null, e) + h.transB + : h.left + + h.offset + + (h.opposite + ? ((e && m.oldChartWidth) || m.chartWidth) - h.right - h.left + : 0), + y: a + ? d - h.bottom + h.offset - (h.opposite ? h.height : 0) + : d - h.translate(f + l, null, null, e) - h.transB, + }; + }, + getLabelPosition: function(a, f, l, e, h, m, d, c) { + var b = this.axis, + k = b.transA, + z = b.reversed, + B = b.staggerLines, + n = b.tickRotCorr || { x: 0, y: 0 }, + x = h.y, + u = + e || b.reserveSpaceDefault + ? 0 + : -b.labelOffset * ('center' === b.labelAlign ? 0.5 : 1); + D(x) || + (x = + 0 === b.side + ? l.rotation + ? -8 + : -l.getBBox().height + : 2 === b.side + ? n.y + 8 + : Math.cos(l.rotation * r) * (n.y - l.getBBox(!1, 0).height / 2)); + a = a + h.x + u + n.x - (m && e ? m * k * (z ? -1 : 1) : 0); + f = f + x - (m && !e ? m * k * (z ? 1 : -1) : 0); + B && + ((l = (d / (c || 1)) % B), + b.opposite && (l = B - l - 1), + (f += (b.labelOffset / B) * l)); + return { x: a, y: Math.round(f) }; + }, + getMarkPath: function(a, f, l, e, h, m) { + return m.crispLine( + ['M', a, f, 'L', a + (h ? 0 : -l), f + (h ? l : 0)], + e, + ); + }, + renderGridLine: function(a, f, l) { + var e = this.axis, + h = e.options, + m = this.gridLine, + d = {}, + c = this.pos, + b = this.type, + k = e.tickmarkOffset, + z = e.chart.renderer, + B = b ? b + 'Grid' : 'grid', + n = h[B + 'LineWidth'], + x = h[B + 'LineColor'], + h = h[B + 'LineDashStyle']; + m || + ((d.stroke = x), + (d['stroke-width'] = n), + h && (d.dashstyle = h), + b || (d.zIndex = 1), + a && (d.opacity = 0), + (this.gridLine = m = z + .path() + .attr(d) + .addClass('highcharts-' + (b ? b + '-' : '') + 'grid-line') + .add(e.gridGroup))); + if ( + !a && + m && + (a = e.getPlotLinePath(c + k, m.strokeWidth() * l, a, !0)) + ) + m[this.isNew ? 'attr' : 'animate']({ d: a, opacity: f }); + }, + renderMark: function(a, f, u) { + var e = this.axis, + h = e.options, + m = e.chart.renderer, + d = this.type, + c = d ? d + 'Tick' : 'tick', + b = e.tickSize(c), + k = this.mark, + z = !k, + B = a.x; + a = a.y; + var n = l(h[c + 'Width'], !d && e.isXAxis ? 1 : 0), + h = h[c + 'Color']; + b && + (e.opposite && (b[0] = -b[0]), + z && + ((this.mark = k = m + .path() + .addClass('highcharts-' + (d ? d + '-' : '') + 'tick') + .add(e.axisGroup)), + k.attr({ stroke: h, 'stroke-width': n })), + k[z ? 'attr' : 'animate']({ + d: this.getMarkPath(B, a, b[0], k.strokeWidth() * u, e.horiz, m), + opacity: f, + })); + }, + renderLabel: function(a, f, u, e) { + var h = this.axis, + m = h.horiz, + d = h.options, + c = this.label, + b = d.labels, + k = b.step, + h = h.tickmarkOffset, + z = !0, + B = a.x; + a = a.y; + c && + p(B) && + ((c.xy = a = this.getLabelPosition(B, a, c, m, b, h, e, k)), + (this.isFirst && !this.isLast && !l(d.showFirstLabel, 1)) || + (this.isLast && !this.isFirst && !l(d.showLastLabel, 1)) + ? (z = !1) + : !m || + b.step || + b.rotation || + f || + 0 === u || + this.handleOverflow(a), + k && e % k && (z = !1), + z && p(a.y) + ? ((a.opacity = u), + c[this.isNewLabel ? 'attr' : 'animate'](a), + (this.isNewLabel = !1)) + : (c.attr('y', -9999), (this.isNewLabel = !0))); + }, + render: function(a, f, u) { + var e = this.axis, + h = e.horiz, + m = this.getPosition(h, this.pos, e.tickmarkOffset, f), + d = m.x, + c = m.y, + e = (h && d === e.pos + e.len) || (!h && c === e.pos) ? -1 : 1; + u = l(u, 1); + this.isActive = !0; + this.renderGridLine(f, u, e); + this.renderMark(m, u, e); + this.renderLabel(m, f, u, a); + this.isNew = !1; + }, + destroy: function() { + H(this, this.axis); + }, + }; + })(M); + var V = (function(a) { + var E = a.addEvent, + D = a.animObject, + H = a.arrayMax, + p = a.arrayMin, + f = a.color, + l = a.correctFloat, + r = a.defaultOptions, + n = a.defined, + w = a.deg2rad, + u = a.destroyObjectProperties, + e = a.each, + h = a.extend, + m = a.fireEvent, + d = a.format, + c = a.getMagnitude, + b = a.grep, + k = a.inArray, + z = a.isArray, + B = a.isNumber, + I = a.isString, + x = a.merge, + K = a.normalizeTickInterval, + t = a.objectEach, + C = a.pick, + N = a.removeEvent, + q = a.splat, + A = a.syncTimeout, + F = a.Tick, + G = function() { + this.init.apply(this, arguments); + }; + a.extend(G.prototype, { + defaultOptions: { + dateTimeLabelFormats: { + millisecond: '%H:%M:%S.%L', + second: '%H:%M:%S', + minute: '%H:%M', + hour: '%H:%M', + day: '%e. %b', + week: '%e. %b', + month: "%b '%y", + year: '%Y', + }, + endOnTick: !1, + labels: { + enabled: !0, + style: { color: '#666666', cursor: 'default', fontSize: '11px' }, + x: 0, + }, + maxPadding: 0.01, + minorTickLength: 2, + minorTickPosition: 'outside', + minPadding: 0.01, + startOfWeek: 1, + startOnTick: !1, + tickLength: 10, + tickmarkPlacement: 'between', + tickPixelInterval: 100, + tickPosition: 'outside', + title: { align: 'middle', style: { color: '#666666' } }, + type: 'linear', + minorGridLineColor: '#f2f2f2', + minorGridLineWidth: 1, + minorTickColor: '#999999', + lineColor: '#ccd6eb', + lineWidth: 1, + gridLineColor: '#e6e6e6', + tickColor: '#ccd6eb', + }, + defaultYAxisOptions: { + endOnTick: !0, + tickPixelInterval: 72, + showLastLabel: !0, + labels: { x: -8 }, + maxPadding: 0.05, + minPadding: 0.05, + startOnTick: !0, + title: { rotation: 270, text: 'Values' }, + stackLabels: { + allowOverlap: !1, + enabled: !1, + formatter: function() { + return a.numberFormat(this.total, -1); + }, + style: { + fontSize: '11px', + fontWeight: 'bold', + color: '#000000', + textOutline: '1px contrast', + }, + }, + gridLineWidth: 1, + lineWidth: 0, + }, + defaultLeftAxisOptions: { labels: { x: -15 }, title: { rotation: 270 } }, + defaultRightAxisOptions: { labels: { x: 15 }, title: { rotation: 90 } }, + defaultBottomAxisOptions: { + labels: { autoRotation: [-45], x: 0 }, + title: { rotation: 0 }, + }, + defaultTopAxisOptions: { + labels: { autoRotation: [-45], x: 0 }, + title: { rotation: 0 }, + }, + init: function(a, b) { + var g = b.isX, + v = this; + v.chart = a; + v.horiz = a.inverted && !v.isZAxis ? !g : g; + v.isXAxis = g; + v.coll = v.coll || (g ? 'xAxis' : 'yAxis'); + v.opposite = b.opposite; + v.side = + b.side || (v.horiz ? (v.opposite ? 0 : 2) : v.opposite ? 1 : 3); + v.setOptions(b); + var c = this.options, + d = c.type; + v.labelFormatter = c.labels.formatter || v.defaultLabelFormatter; + v.userOptions = b; + v.minPixelPadding = 0; + v.reversed = c.reversed; + v.visible = !1 !== c.visible; + v.zoomEnabled = !1 !== c.zoomEnabled; + v.hasNames = 'category' === d || !0 === c.categories; + v.categories = c.categories || v.hasNames; + v.names = v.names || []; + v.plotLinesAndBandsGroups = {}; + v.isLog = 'logarithmic' === d; + v.isDatetimeAxis = 'datetime' === d; + v.positiveValuesOnly = v.isLog && !v.allowNegativeLog; + v.isLinked = n(c.linkedTo); + v.ticks = {}; + v.labelEdge = []; + v.minorTicks = {}; + v.plotLinesAndBands = []; + v.alternateBands = {}; + v.len = 0; + v.minRange = v.userMinRange = c.minRange || c.maxZoom; + v.range = c.range; + v.offset = c.offset || 0; + v.stacks = {}; + v.oldStacks = {}; + v.stacksTouched = 0; + v.max = null; + v.min = null; + v.crosshair = C( + c.crosshair, + q(a.options.tooltip.crosshairs)[g ? 0 : 1], + !1, + ); + b = v.options.events; + -1 === k(v, a.axes) && + (g ? a.axes.splice(a.xAxis.length, 0, v) : a.axes.push(v), + a[v.coll].push(v)); + v.series = v.series || []; + a.inverted && + !v.isZAxis && + g && + void 0 === v.reversed && + (v.reversed = !0); + t(b, function(a, g) { + E(v, g, a); + }); + v.lin2log = c.linearToLogConverter || v.lin2log; + v.isLog && ((v.val2lin = v.log2lin), (v.lin2val = v.lin2log)); + }, + setOptions: function(a) { + this.options = x( + this.defaultOptions, + 'yAxis' === this.coll && this.defaultYAxisOptions, + [ + this.defaultTopAxisOptions, + this.defaultRightAxisOptions, + this.defaultBottomAxisOptions, + this.defaultLeftAxisOptions, + ][this.side], + x(r[this.coll], a), + ); + }, + defaultLabelFormatter: function() { + var g = this.axis, + b = this.value, + c = g.categories, + k = this.dateTimeLabelFormat, + e = r.lang, + q = e.numericSymbols, + e = e.numericSymbolMagnitude || 1e3, + h = q && q.length, + m, + z = g.options.labels.format, + g = g.isLog ? Math.abs(b) : g.tickInterval; + if (z) m = d(z, this); + else if (c) m = b; + else if (k) m = a.dateFormat(k, b); + else if (h && 1e3 <= g) + for (; h-- && void 0 === m; ) + (c = Math.pow(e, h + 1)), + g >= c && + 0 === (10 * b) % c && + null !== q[h] && + 0 !== b && + (m = a.numberFormat(b / c, -1) + q[h]); + void 0 === m && + (m = + 1e4 <= Math.abs(b) + ? a.numberFormat(b, -1) + : a.numberFormat(b, -1, void 0, '')); + return m; + }, + getSeriesExtremes: function() { + var a = this, + v = a.chart; + a.hasVisibleSeries = !1; + a.dataMin = a.dataMax = a.threshold = null; + a.softThreshold = !a.isXAxis; + a.buildStacks && a.buildStacks(); + e(a.series, function(g) { + if (g.visible || !v.options.chart.ignoreHiddenSeries) { + var c = g.options, + d = c.threshold, + k; + a.hasVisibleSeries = !0; + a.positiveValuesOnly && 0 >= d && (d = null); + if (a.isXAxis) + (c = g.xData), + c.length && + ((g = p(c)), + (k = H(c)), + B(g) || g instanceof Date || ((c = b(c, B)), (g = p(c))), + (a.dataMin = Math.min(C(a.dataMin, c[0], g), g)), + (a.dataMax = Math.max(C(a.dataMax, c[0], k), k))); + else if ( + (g.getExtremes(), + (k = g.dataMax), + (g = g.dataMin), + n(g) && + n(k) && + ((a.dataMin = Math.min(C(a.dataMin, g), g)), + (a.dataMax = Math.max(C(a.dataMax, k), k))), + n(d) && (a.threshold = d), + !c.softThreshold || a.positiveValuesOnly) + ) + a.softThreshold = !1; + } + }); + }, + translate: function(a, b, c, d, k, e) { + var g = this.linkedParent || this, + v = 1, + q = 0, + h = d ? g.oldTransA : g.transA; + d = d ? g.oldMin : g.min; + var m = g.minPixelPadding; + k = (g.isOrdinal || g.isBroken || (g.isLog && k)) && g.lin2val; + h || (h = g.transA); + c && ((v *= -1), (q = g.len)); + g.reversed && ((v *= -1), (q -= v * (g.sector || g.len))); + b + ? ((a = (a * v + q - m) / h + d), k && (a = g.lin2val(a))) + : (k && (a = g.val2lin(a)), + (a = B(d) + ? v * (a - d) * h + q + v * m + (B(e) ? h * e : 0) + : void 0)); + return a; + }, + toPixels: function(a, b) { + return ( + this.translate(a, !1, !this.horiz, null, !0) + (b ? 0 : this.pos) + ); + }, + toValue: function(a, b) { + return this.translate( + a - (b ? 0 : this.pos), + !0, + !this.horiz, + null, + !0, + ); + }, + getPlotLinePath: function(a, b, c, d, k) { + var g = this.chart, + v = this.left, + q = this.top, + e, + h, + m = (c && g.oldChartHeight) || g.chartHeight, + z = (c && g.oldChartWidth) || g.chartWidth, + A; + e = this.transB; + var t = function(a, g, b) { + if (a < g || a > b) d ? (a = Math.min(Math.max(g, a), b)) : (A = !0); + return a; + }; + k = C(k, this.translate(a, null, null, c)); + a = c = Math.round(k + e); + e = h = Math.round(m - k - e); + B(k) + ? this.horiz + ? ((e = q), + (h = m - this.bottom), + (a = c = t(a, v, v + this.width))) + : ((a = v), + (c = z - this.right), + (e = h = t(e, q, q + this.height))) + : ((A = !0), (d = !1)); + return A && !d + ? null + : g.renderer.crispLine(['M', a, e, 'L', c, h], b || 1); + }, + getLinearTickPositions: function(a, b, c) { + var g, + v = l(Math.floor(b / a) * a); + c = l(Math.ceil(c / a) * a); + var d = [], + k; + l(v + a) === v && (k = 20); + if (this.single) return [b]; + for (b = v; b <= c; ) { + d.push(b); + b = l(b + a, k); + if (b === g) break; + g = b; + } + return d; + }, + getMinorTickInterval: function() { + var a = this.options; + return !0 === a.minorTicks + ? C(a.minorTickInterval, 'auto') + : !1 === a.minorTicks + ? null + : a.minorTickInterval; + }, + getMinorTickPositions: function() { + var a = this, + b = a.options, + c = a.tickPositions, + d = a.minorTickInterval, + k = [], + q = a.pointRangePadding || 0, + h = a.min - q, + q = a.max + q, + m = q - h; + if (m && m / d < a.len / 3) + if (a.isLog) + e(this.paddedTicks, function(g, b, v) { + b && + k.push.apply(k, a.getLogTickPositions(d, v[b - 1], v[b], !0)); + }); + else if (a.isDatetimeAxis && 'auto' === this.getMinorTickInterval()) + k = k.concat( + a.getTimeTicks( + a.normalizeTimeTickInterval(d), + h, + q, + b.startOfWeek, + ), + ); + else + for (b = h + ((c[0] - h) % d); b <= q && b !== k[0]; b += d) + k.push(b); + 0 !== k.length && a.trimTicks(k); + return k; + }, + adjustForMinRange: function() { + var a = this.options, + b = this.min, + c = this.max, + d, + k, + q, + h, + m, + z, + A, + t; + this.isXAxis && + void 0 === this.minRange && + !this.isLog && + (n(a.min) || n(a.max) + ? (this.minRange = null) + : (e(this.series, function(a) { + z = a.xData; + for (h = A = a.xIncrement ? 1 : z.length - 1; 0 < h; h--) + if (((m = z[h] - z[h - 1]), void 0 === q || m < q)) q = m; + }), + (this.minRange = Math.min(5 * q, this.dataMax - this.dataMin)))); + c - b < this.minRange && + ((k = this.dataMax - this.dataMin >= this.minRange), + (t = this.minRange), + (d = (t - c + b) / 2), + (d = [b - d, C(a.min, b - d)]), + k && (d[2] = this.isLog ? this.log2lin(this.dataMin) : this.dataMin), + (b = H(d)), + (c = [b + t, C(a.max, b + t)]), + k && (c[2] = this.isLog ? this.log2lin(this.dataMax) : this.dataMax), + (c = p(c)), + c - b < t && ((d[0] = c - t), (d[1] = C(a.min, c - t)), (b = H(d)))); + this.min = b; + this.max = c; + }, + getClosest: function() { + var a; + this.categories + ? (a = 1) + : e(this.series, function(g) { + var b = g.closestPointRange, + v = g.visible || !g.chart.options.chart.ignoreHiddenSeries; + !g.noSharedTooltip && + n(b) && + v && + (a = n(a) ? Math.min(a, b) : b); + }); + return a; + }, + nameToX: function(a) { + var g = z(this.categories), + b = g ? this.categories : this.names, + c = a.options.x, + d; + a.series.requireSorting = !1; + n(c) || + (c = + !1 === this.options.uniqueNames + ? a.series.autoIncrement() + : k(a.name, b)); + -1 === c ? g || (d = b.length) : (d = c); + void 0 !== d && (this.names[d] = a.name); + return d; + }, + updateNames: function() { + var a = this; + 0 < this.names.length && + ((this.names.length = 0), + (this.minRange = this.userMinRange), + e(this.series || [], function(g) { + g.xIncrement = null; + if (!g.points || g.isDirtyData) g.processData(), g.generatePoints(); + e(g.points, function(b, v) { + var c; + b.options && + ((c = a.nameToX(b)), + void 0 !== c && c !== b.x && ((b.x = c), (g.xData[v] = c))); + }); + })); + }, + setAxisTranslation: function(a) { + var g = this, + b = g.max - g.min, + c = g.axisPointRange || 0, + d, + k = 0, + q = 0, + h = g.linkedParent, + m = !!g.categories, + z = g.transA, + A = g.isXAxis; + if (A || m || c) + (d = g.getClosest()), + h + ? ((k = h.minPointOffset), (q = h.pointRangePadding)) + : e(g.series, function(a) { + var b = m + ? 1 + : A + ? C(a.options.pointRange, d, 0) + : g.axisPointRange || 0; + a = a.options.pointPlacement; + c = Math.max(c, b); + g.single || + ((k = Math.max(k, I(a) ? 0 : b / 2)), + (q = Math.max(q, 'on' === a ? 0 : b))); + }), + (h = g.ordinalSlope && d ? g.ordinalSlope / d : 1), + (g.minPointOffset = k *= h), + (g.pointRangePadding = q *= h), + (g.pointRange = Math.min(c, b)), + A && (g.closestPointRange = d); + a && (g.oldTransA = z); + g.translationSlope = g.transA = z = + g.options.staticScale || g.len / (b + q || 1); + g.transB = g.horiz ? g.left : g.bottom; + g.minPixelPadding = z * k; + }, + minFromRange: function() { + return this.max - this.range; + }, + setTickInterval: function(g) { + var b = this, + d = b.chart, + k = b.options, + q = b.isLog, + h = b.log2lin, + z = b.isDatetimeAxis, + A = b.isXAxis, + t = b.isLinked, + x = k.maxPadding, + f = k.minPadding, + F = k.tickInterval, + u = k.tickPixelInterval, + G = b.categories, + p = b.threshold, + I = b.softThreshold, + r, + w, + N, + D; + z || G || t || this.getTickAmount(); + N = C(b.userMin, k.min); + D = C(b.userMax, k.max); + t + ? ((b.linkedParent = d[b.coll][k.linkedTo]), + (d = b.linkedParent.getExtremes()), + (b.min = C(d.min, d.dataMin)), + (b.max = C(d.max, d.dataMax)), + k.type !== b.linkedParent.options.type && a.error(11, 1)) + : (!I && + n(p) && + (b.dataMin >= p + ? ((r = p), (f = 0)) + : b.dataMax <= p && ((w = p), (x = 0))), + (b.min = C(N, r, b.dataMin)), + (b.max = C(D, w, b.dataMax))); + q && + (b.positiveValuesOnly && + !g && + 0 >= Math.min(b.min, C(b.dataMin, b.min)) && + a.error(10, 1), + (b.min = l(h(b.min), 15)), + (b.max = l(h(b.max), 15))); + b.range && + n(b.max) && + ((b.userMin = b.min = N = Math.max(b.dataMin, b.minFromRange())), + (b.userMax = D = b.max), + (b.range = null)); + m(b, 'foundExtremes'); + b.beforePadding && b.beforePadding(); + b.adjustForMinRange(); + !(G || b.axisPointRange || b.usePercentage || t) && + n(b.min) && + n(b.max) && + (h = b.max - b.min) && + (!n(N) && f && (b.min -= h * f), !n(D) && x && (b.max += h * x)); + B(k.softMin) && !B(b.userMin) && (b.min = Math.min(b.min, k.softMin)); + B(k.softMax) && !B(b.userMax) && (b.max = Math.max(b.max, k.softMax)); + B(k.floor) && (b.min = Math.max(b.min, k.floor)); + B(k.ceiling) && (b.max = Math.min(b.max, k.ceiling)); + I && + n(b.dataMin) && + ((p = p || 0), + !n(N) && b.min < p && b.dataMin >= p + ? (b.min = p) + : !n(D) && b.max > p && b.dataMax <= p && (b.max = p)); + b.tickInterval = + b.min === b.max || void 0 === b.min || void 0 === b.max + ? 1 + : t && !F && u === b.linkedParent.options.tickPixelInterval + ? (F = b.linkedParent.tickInterval) + : C( + F, + this.tickAmount + ? (b.max - b.min) / Math.max(this.tickAmount - 1, 1) + : void 0, + G ? 1 : ((b.max - b.min) * u) / Math.max(b.len, u), + ); + A && + !g && + e(b.series, function(a) { + a.processData(b.min !== b.oldMin || b.max !== b.oldMax); + }); + b.setAxisTranslation(!0); + b.beforeSetTickPositions && b.beforeSetTickPositions(); + b.postProcessTickInterval && + (b.tickInterval = b.postProcessTickInterval(b.tickInterval)); + b.pointRange && + !F && + (b.tickInterval = Math.max(b.pointRange, b.tickInterval)); + g = C(k.minTickInterval, b.isDatetimeAxis && b.closestPointRange); + !F && b.tickInterval < g && (b.tickInterval = g); + z || + q || + F || + (b.tickInterval = K( + b.tickInterval, + null, + c(b.tickInterval), + C( + k.allowDecimals, + !( + 0.5 < b.tickInterval && + 5 > b.tickInterval && + 1e3 < b.max && + 9999 > b.max + ), + ), + !!this.tickAmount, + )); + this.tickAmount || (b.tickInterval = b.unsquish()); + this.setTickPositions(); + }, + setTickPositions: function() { + var a = this.options, + b, + c = a.tickPositions; + b = this.getMinorTickInterval(); + var d = a.tickPositioner, + k = a.startOnTick, + q = a.endOnTick; + this.tickmarkOffset = + this.categories && + 'between' === a.tickmarkPlacement && + 1 === this.tickInterval + ? 0.5 + : 0; + this.minorTickInterval = + 'auto' === b && this.tickInterval ? this.tickInterval / 5 : b; + this.single = + this.min === this.max && + n(this.min) && + !this.tickAmount && + (parseInt(this.min, 10) === this.min || !1 !== a.allowDecimals); + this.tickPositions = b = c && c.slice(); + !b && + ((b = this.isDatetimeAxis + ? this.getTimeTicks( + this.normalizeTimeTickInterval(this.tickInterval, a.units), + this.min, + this.max, + a.startOfWeek, + this.ordinalPositions, + this.closestPointRange, + !0, + ) + : this.isLog + ? this.getLogTickPositions(this.tickInterval, this.min, this.max) + : this.getLinearTickPositions( + this.tickInterval, + this.min, + this.max, + )), + b.length > this.len && + ((b = [b[0], b.pop()]), b[0] === b[1] && (b.length = 1)), + (this.tickPositions = b), + d && (d = d.apply(this, [this.min, this.max]))) && + (this.tickPositions = b = d); + this.paddedTicks = b.slice(0); + this.trimTicks(b, k, q); + this.isLinked || + (this.single && + 2 > b.length && + ((this.min -= 0.5), (this.max += 0.5)), + c || d || this.adjustTickAmount()); + }, + trimTicks: function(a, b, c) { + var g = a[0], + d = a[a.length - 1], + k = this.minPointOffset || 0; + if (!this.isLinked) { + if (b && -Infinity !== g) this.min = g; + else for (; this.min - k > a[0]; ) a.shift(); + if (c) this.max = d; + else for (; this.max + k < a[a.length - 1]; ) a.pop(); + 0 === a.length && + n(g) && + !this.options.tickPositions && + a.push((d + g) / 2); + } + }, + alignToOthers: function() { + var a = {}, + b, + c = this.options; + !1 === this.chart.options.chart.alignTicks || + !1 === c.alignTicks || + this.isLog || + e(this.chart[this.coll], function(g) { + var c = g.options, + c = [g.horiz ? c.left : c.top, c.width, c.height, c.pane].join(); + g.series.length && (a[c] ? (b = !0) : (a[c] = 1)); + }); + return b; + }, + getTickAmount: function() { + var a = this.options, + b = a.tickAmount, + c = a.tickPixelInterval; + !n(a.tickInterval) && + this.len < c && + !this.isRadial && + !this.isLog && + a.startOnTick && + a.endOnTick && + (b = 2); + !b && this.alignToOthers() && (b = Math.ceil(this.len / c) + 1); + 4 > b && ((this.finalTickAmt = b), (b = 5)); + this.tickAmount = b; + }, + adjustTickAmount: function() { + var a = this.tickInterval, + b = this.tickPositions, + c = this.tickAmount, + d = this.finalTickAmt, + k = b && b.length, + q = C(this.threshold, this.softThreshold ? 0 : null); + if (this.hasData()) { + if (k < c) { + for (; b.length < c; ) + b.length % 2 || this.min === q + ? b.push(l(b[b.length - 1] + a)) + : b.unshift(l(b[0] - a)); + this.transA *= (k - 1) / (c - 1); + this.min = b[0]; + this.max = b[b.length - 1]; + } else k > c && ((this.tickInterval *= 2), this.setTickPositions()); + if (n(d)) { + for (a = c = b.length; a--; ) + ((3 === d && 1 === a % 2) || (2 >= d && 0 < a && a < c - 1)) && + b.splice(a, 1); + this.finalTickAmt = void 0; + } + } + }, + setScale: function() { + var a, b; + this.oldMin = this.min; + this.oldMax = this.max; + this.oldAxisLength = this.len; + this.setAxisSize(); + b = this.len !== this.oldAxisLength; + e(this.series, function(b) { + if (b.isDirtyData || b.isDirty || b.xAxis.isDirty) a = !0; + }); + b || + a || + this.isLinked || + this.forceRedraw || + this.userMin !== this.oldUserMin || + this.userMax !== this.oldUserMax || + this.alignToOthers() + ? (this.resetStacks && this.resetStacks(), + (this.forceRedraw = !1), + this.getSeriesExtremes(), + this.setTickInterval(), + (this.oldUserMin = this.userMin), + (this.oldUserMax = this.userMax), + this.isDirty || + (this.isDirty = + b || this.min !== this.oldMin || this.max !== this.oldMax)) + : this.cleanStacks && this.cleanStacks(); + }, + setExtremes: function(a, b, c, d, k) { + var g = this, + q = g.chart; + c = C(c, !0); + e(g.series, function(a) { + delete a.kdTree; + }); + k = h(k, { min: a, max: b }); + m(g, 'setExtremes', k, function() { + g.userMin = a; + g.userMax = b; + g.eventArgs = k; + c && q.redraw(d); + }); + }, + zoom: function(a, b) { + var g = this.dataMin, + c = this.dataMax, + d = this.options, + k = Math.min(g, C(d.min, g)), + d = Math.max(c, C(d.max, c)); + if (a !== this.min || b !== this.max) + this.allowZoomOutside || + (n(g) && (a < k && (a = k), a > d && (a = d)), + n(c) && (b < k && (b = k), b > d && (b = d))), + (this.displayBtn = void 0 !== a || void 0 !== b), + this.setExtremes(a, b, !1, void 0, { trigger: 'zoom' }); + return !0; + }, + setAxisSize: function() { + var b = this.chart, + c = this.options, + d = c.offsets || [0, 0, 0, 0], + k = this.horiz, + q = (this.width = Math.round( + a.relativeLength( + C(c.width, b.plotWidth - d[3] + d[1]), + b.plotWidth, + ), + )), + e = (this.height = Math.round( + a.relativeLength( + C(c.height, b.plotHeight - d[0] + d[2]), + b.plotHeight, + ), + )), + h = (this.top = Math.round( + a.relativeLength( + C(c.top, b.plotTop + d[0]), + b.plotHeight, + b.plotTop, + ), + )), + c = (this.left = Math.round( + a.relativeLength( + C(c.left, b.plotLeft + d[3]), + b.plotWidth, + b.plotLeft, + ), + )); + this.bottom = b.chartHeight - e - h; + this.right = b.chartWidth - q - c; + this.len = Math.max(k ? q : e, 0); + this.pos = k ? c : h; + }, + getExtremes: function() { + var a = this.isLog, + b = this.lin2log; + return { + min: a ? l(b(this.min)) : this.min, + max: a ? l(b(this.max)) : this.max, + dataMin: this.dataMin, + dataMax: this.dataMax, + userMin: this.userMin, + userMax: this.userMax, + }; + }, + getThreshold: function(a) { + var b = this.isLog, + g = this.lin2log, + c = b ? g(this.min) : this.min, + b = b ? g(this.max) : this.max; + null === a ? (a = c) : c > a ? (a = c) : b < a && (a = b); + return this.translate(a, 0, 1, 0, 1); + }, + autoLabelAlign: function(a) { + a = (C(a, 0) - 90 * this.side + 720) % 360; + return 15 < a && 165 > a + ? 'right' + : 195 < a && 345 > a + ? 'left' + : 'center'; + }, + tickSize: function(a) { + var b = this.options, + g = b[a + 'Length'], + c = C(b[a + 'Width'], 'tick' === a && this.isXAxis ? 1 : 0); + if (c && g) return 'inside' === b[a + 'Position'] && (g = -g), [g, c]; + }, + labelMetrics: function() { + var a = (this.tickPositions && this.tickPositions[0]) || 0; + return this.chart.renderer.fontMetrics( + this.options.labels.style && this.options.labels.style.fontSize, + this.ticks[a] && this.ticks[a].label, + ); + }, + unsquish: function() { + var a = this.options.labels, + b = this.horiz, + c = this.tickInterval, + d = c, + k = + this.len / (((this.categories ? 1 : 0) + this.max - this.min) / c), + q, + h = a.rotation, + m = this.labelMetrics(), + z, + A = Number.MAX_VALUE, + t, + x = function(a) { + a /= k || 1; + a = 1 < a ? Math.ceil(a) : 1; + return a * c; + }; + b + ? (t = + !a.staggerLines && + !a.step && + (n(h) + ? [h] + : k < C(a.autoRotationLimit, 80) && a.autoRotation)) && + e(t, function(a) { + var b; + if (a === h || (a && -90 <= a && 90 >= a)) + (z = x(Math.abs(m.h / Math.sin(w * a)))), + (b = z + Math.abs(a / 360)), + b < A && ((A = b), (q = a), (d = z)); + }) + : a.step || (d = x(m.h)); + this.autoRotation = t; + this.labelRotation = C(q, h); + return d; + }, + getSlotWidth: function() { + var a = this.chart, + b = this.horiz, + c = this.options.labels, + d = Math.max( + this.tickPositions.length - (this.categories ? 0 : 1), + 1, + ), + k = a.margin[3]; + return ( + (b && + 2 > (c.step || 0) && + !c.rotation && + ((this.staggerLines || 1) * this.len) / d) || + (!b && + ((c.style && parseInt(c.style.width, 10)) || + (k && k - a.spacing[3]) || + 0.33 * a.chartWidth)) + ); + }, + renderUnsquish: function() { + var a = this.chart, + b = a.renderer, + c = this.tickPositions, + d = this.ticks, + k = this.options.labels, + q = this.horiz, + h = this.getSlotWidth(), + m = Math.max(1, Math.round(h - 2 * (k.padding || 5))), + z = {}, + A = this.labelMetrics(), + t = k.style && k.style.textOverflow, + f, + F = 0, + l, + B; + I(k.rotation) || (z.rotation = k.rotation || 0); + e(c, function(a) { + (a = d[a]) && a.labelLength > F && (F = a.labelLength); + }); + this.maxLabelLength = F; + if (this.autoRotation) + F > m && F > A.h + ? (z.rotation = this.labelRotation) + : (this.labelRotation = 0); + else if (h && ((f = { width: m + 'px' }), !t)) + for (f.textOverflow = 'clip', l = c.length; !q && l--; ) + if (((B = c[l]), (m = d[B].label))) + m.styles && 'ellipsis' === m.styles.textOverflow + ? m.css({ textOverflow: 'clip' }) + : d[B].labelLength > h && m.css({ width: h + 'px' }), + m.getBBox().height > this.len / c.length - (A.h - A.f) && + (m.specCss = { textOverflow: 'ellipsis' }); + z.rotation && + ((f = { + width: + (F > 0.5 * a.chartHeight ? 0.33 * a.chartHeight : a.chartHeight) + + 'px', + }), + t || (f.textOverflow = 'ellipsis')); + if ( + (this.labelAlign = k.align || this.autoLabelAlign(this.labelRotation)) + ) + z.align = this.labelAlign; + e(c, function(a) { + var b = (a = d[a]) && a.label; + b && + (b.attr(z), + f && b.css(x(f, b.specCss)), + delete b.specCss, + (a.rotation = z.rotation)); + }); + this.tickRotCorr = b.rotCorr( + A.b, + this.labelRotation || 0, + 0 !== this.side, + ); + }, + hasData: function() { + return ( + this.hasVisibleSeries || + (n(this.min) && + n(this.max) && + this.tickPositions && + 0 < this.tickPositions.length) + ); + }, + addTitle: function(a) { + var b = this.chart.renderer, + g = this.horiz, + c = this.opposite, + d = this.options.title, + k; + this.axisTitle || + ((k = d.textAlign) || + (k = (g + ? { low: 'left', middle: 'center', high: 'right' } + : { + low: c ? 'right' : 'left', + middle: 'center', + high: c ? 'left' : 'right', + })[d.align]), + (this.axisTitle = b + .text(d.text, 0, 0, d.useHTML) + .attr({ zIndex: 7, rotation: d.rotation || 0, align: k }) + .addClass('highcharts-axis-title') + .css(d.style) + .add(this.axisGroup)), + (this.axisTitle.isNew = !0)); + d.style.width || + this.isRadial || + this.axisTitle.css({ width: this.len }); + this.axisTitle[a ? 'show' : 'hide'](!0); + }, + generateTick: function(a) { + var b = this.ticks; + b[a] ? b[a].addLabel() : (b[a] = new F(this, a)); + }, + getOffset: function() { + var a = this, + b = a.chart, + c = b.renderer, + d = a.options, + k = a.tickPositions, + q = a.ticks, + h = a.horiz, + m = a.side, + z = b.inverted && !a.isZAxis ? [1, 0, 3, 2][m] : m, + A, + x, + f = 0, + F, + l = 0, + B = d.title, + u = d.labels, + G = 0, + p = b.axisOffset, + b = b.clipOffset, + I = [-1, 1, 1, -1][m], + r = d.className, + w = a.axisParent, + K = this.tickSize('tick'); + A = a.hasData(); + a.showAxis = x = A || C(d.showEmpty, !0); + a.staggerLines = a.horiz && u.staggerLines; + a.axisGroup || + ((a.gridGroup = c + .g('grid') + .attr({ zIndex: d.gridZIndex || 1 }) + .addClass( + 'highcharts-' + this.coll.toLowerCase() + '-grid ' + (r || ''), + ) + .add(w)), + (a.axisGroup = c + .g('axis') + .attr({ zIndex: d.zIndex || 2 }) + .addClass('highcharts-' + this.coll.toLowerCase() + ' ' + (r || '')) + .add(w)), + (a.labelGroup = c + .g('axis-labels') + .attr({ zIndex: u.zIndex || 7 }) + .addClass( + 'highcharts-' + a.coll.toLowerCase() + '-labels ' + (r || ''), + ) + .add(w))); + A || a.isLinked + ? (e(k, function(b, c) { + a.generateTick(b, c); + }), + a.renderUnsquish(), + (a.reserveSpaceDefault = + 0 === m || + 2 === m || + { 1: 'left', 3: 'right' }[m] === a.labelAlign), + C( + u.reserveSpace, + 'center' === a.labelAlign ? !0 : null, + a.reserveSpaceDefault, + ) && + e(k, function(a) { + G = Math.max(q[a].getLabelSize(), G); + }), + a.staggerLines && (G *= a.staggerLines), + (a.labelOffset = G * (a.opposite ? -1 : 1))) + : t(q, function(a, b) { + a.destroy(); + delete q[b]; + }); + B && + B.text && + !1 !== B.enabled && + (a.addTitle(x), + x && + !1 !== B.reserveSpace && + ((a.titleOffset = f = a.axisTitle.getBBox()[ + h ? 'height' : 'width' + ]), + (F = B.offset), + (l = n(F) ? 0 : C(B.margin, h ? 5 : 10)))); + a.renderLine(); + a.offset = I * C(d.offset, p[m]); + a.tickRotCorr = a.tickRotCorr || { x: 0, y: 0 }; + c = 0 === m ? -a.labelMetrics().h : 2 === m ? a.tickRotCorr.y : 0; + l = Math.abs(G) + l; + G && (l = l - c + I * (h ? C(u.y, a.tickRotCorr.y + 8 * I) : u.x)); + a.axisTitleMargin = C(F, l); + p[m] = Math.max( + p[m], + a.axisTitleMargin + f + I * a.offset, + l, + A && k.length && K ? K[0] + I * a.offset : 0, + ); + d = d.offset ? 0 : 2 * Math.floor(a.axisLine.strokeWidth() / 2); + b[z] = Math.max(b[z], d); + }, + getLinePath: function(a) { + var b = this.chart, + c = this.opposite, + g = this.offset, + d = this.horiz, + k = this.left + (c ? this.width : 0) + g, + g = b.chartHeight - this.bottom - (c ? this.height : 0) + g; + c && (a *= -1); + return b.renderer.crispLine( + [ + 'M', + d ? this.left : k, + d ? g : this.top, + 'L', + d ? b.chartWidth - this.right : k, + d ? g : b.chartHeight - this.bottom, + ], + a, + ); + }, + renderLine: function() { + this.axisLine || + ((this.axisLine = this.chart.renderer + .path() + .addClass('highcharts-axis-line') + .add(this.axisGroup)), + this.axisLine.attr({ + stroke: this.options.lineColor, + 'stroke-width': this.options.lineWidth, + zIndex: 7, + })); + }, + getTitlePosition: function() { + var a = this.horiz, + b = this.left, + c = this.top, + d = this.len, + k = this.options.title, + q = a ? b : c, + e = this.opposite, + h = this.offset, + m = k.x || 0, + z = k.y || 0, + A = this.axisTitle, + t = this.chart.renderer.fontMetrics(k.style && k.style.fontSize, A), + A = Math.max(A.getBBox(null, 0).height - t.h - 1, 0), + d = { + low: q + (a ? 0 : d), + middle: q + d / 2, + high: q + (a ? d : 0), + }[k.align], + b = + (a ? c + this.height : b) + + (a ? 1 : -1) * (e ? -1 : 1) * this.axisTitleMargin + + [-A, A, t.f, -A][this.side]; + return { + x: a ? d + m : b + (e ? this.width : 0) + h + m, + y: a ? b + z - (e ? this.height : 0) + h : d + z, + }; + }, + renderMinorTick: function(a) { + var b = this.chart.hasRendered && B(this.oldMin), + c = this.minorTicks; + c[a] || (c[a] = new F(this, a, 'minor')); + b && c[a].isNew && c[a].render(null, !0); + c[a].render(null, !1, 1); + }, + renderTick: function(a, b) { + var c = this.isLinked, + g = this.ticks, + d = this.chart.hasRendered && B(this.oldMin); + if (!c || (a >= this.min && a <= this.max)) + g[a] || (g[a] = new F(this, a)), + d && g[a].isNew && g[a].render(b, !0, 0.1), + g[a].render(b); + }, + render: function() { + var b = this, + c = b.chart, + d = b.options, + k = b.isLog, + q = b.lin2log, + h = b.isLinked, + m = b.tickPositions, + z = b.axisTitle, + x = b.ticks, + f = b.minorTicks, + l = b.alternateBands, + C = d.stackLabels, + n = d.alternateGridColor, + u = b.tickmarkOffset, + G = b.axisLine, + p = b.showAxis, + I = D(c.renderer.globalAnimation), + r, + w; + b.labelEdge.length = 0; + b.overlap = !1; + e([x, f, l], function(a) { + t(a, function(a) { + a.isActive = !1; + }); + }); + if (b.hasData() || h) + b.minorTickInterval && + !b.categories && + e(b.getMinorTickPositions(), function(a) { + b.renderMinorTick(a); + }), + m.length && + (e(m, function(a, c) { + b.renderTick(a, c); + }), + u && + (0 === b.min || b.single) && + (x[-1] || (x[-1] = new F(b, -1, null, !0)), x[-1].render(-1))), + n && + e(m, function(d, g) { + w = void 0 !== m[g + 1] ? m[g + 1] + u : b.max - u; + 0 === g % 2 && + d < b.max && + w <= b.max + (c.polar ? -u : u) && + (l[d] || (l[d] = new a.PlotLineOrBand(b)), + (r = d + u), + (l[d].options = { + from: k ? q(r) : r, + to: k ? q(w) : w, + color: n, + }), + l[d].render(), + (l[d].isActive = !0)); + }), + b._addedPlotLB || + (e((d.plotLines || []).concat(d.plotBands || []), function(a) { + b.addPlotBandOrLine(a); + }), + (b._addedPlotLB = !0)); + e([x, f, l], function(a) { + var b, + d = [], + g = I.duration; + t(a, function(a, b) { + a.isActive || (a.render(b, !1, 0), (a.isActive = !1), d.push(b)); + }); + A( + function() { + for (b = d.length; b--; ) + a[d[b]] && + !a[d[b]].isActive && + (a[d[b]].destroy(), delete a[d[b]]); + }, + a !== l && c.hasRendered && g ? g : 0, + ); + }); + G && + (G[G.isPlaced ? 'animate' : 'attr']({ + d: this.getLinePath(G.strokeWidth()), + }), + (G.isPlaced = !0), + G[p ? 'show' : 'hide'](!0)); + z && + p && + ((d = b.getTitlePosition()), + B(d.y) + ? (z[z.isNew ? 'attr' : 'animate'](d), (z.isNew = !1)) + : (z.attr('y', -9999), (z.isNew = !0))); + C && C.enabled && b.renderStackTotals(); + b.isDirty = !1; + }, + redraw: function() { + this.visible && + (this.render(), + e(this.plotLinesAndBands, function(a) { + a.render(); + })); + e(this.series, function(a) { + a.isDirty = !0; + }); + }, + keepProps: 'extKey hcEvents names series userMax userMin'.split(' '), + destroy: function(a) { + var b = this, + c = b.stacks, + d = b.plotLinesAndBands, + g; + a || N(b); + t(c, function(a, b) { + u(a); + c[b] = null; + }); + e([b.ticks, b.minorTicks, b.alternateBands], function(a) { + u(a); + }); + if (d) for (a = d.length; a--; ) d[a].destroy(); + e( + 'stackTotalGroup axisLine axisTitle axisGroup gridGroup labelGroup cross'.split( + ' ', + ), + function(a) { + b[a] && (b[a] = b[a].destroy()); + }, + ); + for (g in b.plotLinesAndBandsGroups) + b.plotLinesAndBandsGroups[g] = b.plotLinesAndBandsGroups[g].destroy(); + t(b, function(a, c) { + -1 === k(c, b.keepProps) && delete b[c]; + }); + }, + drawCrosshair: function(a, b) { + var c, + d = this.crosshair, + g = C(d.snap, !0), + k, + q = this.cross; + a || (a = this.cross && this.cross.e); + this.crosshair && !1 !== (n(b) || !g) + ? (g + ? n(b) && (k = this.isXAxis ? b.plotX : this.len - b.plotY) + : (k = + a && + (this.horiz + ? a.chartX - this.pos + : this.len - a.chartY + this.pos)), + n(k) && + (c = + this.getPlotLinePath( + b && (this.isXAxis ? b.x : C(b.stackY, b.y)), + null, + null, + null, + k, + ) || null), + n(c) + ? ((b = this.categories && !this.isRadial), + q || + ((this.cross = q = this.chart.renderer + .path() + .addClass( + 'highcharts-crosshair highcharts-crosshair-' + + (b ? 'category ' : 'thin ') + + d.className, + ) + .attr({ zIndex: C(d.zIndex, 2) }) + .add()), + q + .attr({ + stroke: + d.color || + (b + ? f('#ccd6eb') + .setOpacity(0.25) + .get() + : '#cccccc'), + 'stroke-width': C(d.width, 1), + }) + .css({ 'pointer-events': 'none' }), + d.dashStyle && q.attr({ dashstyle: d.dashStyle })), + q.show().attr({ d: c }), + b && !d.width && q.attr({ 'stroke-width': this.transA }), + (this.cross.e = a)) + : this.hideCrosshair()) + : this.hideCrosshair(); + }, + hideCrosshair: function() { + this.cross && this.cross.hide(); + }, + }); + return (a.Axis = G); + })(M); + (function(a) { + var E = a.Axis, + D = a.Date, + H = a.dateFormat, + p = a.defaultOptions, + f = a.defined, + l = a.each, + r = a.extend, + n = a.getMagnitude, + w = a.getTZOffset, + u = a.normalizeTickInterval, + e = a.pick, + h = a.timeUnits; + E.prototype.getTimeTicks = function(a, d, c, b) { + var k = [], + m = {}, + B = p.global.useUTC, + n, + x = new D(d - Math.max(w(d), w(c))), + u = D.hcMakeTime, + t = a.unitRange, + C = a.count, + N, + q; + if (f(d)) { + x[D.hcSetMilliseconds]( + t >= h.second ? 0 : C * Math.floor(x.getMilliseconds() / C), + ); + if (t >= h.second) + x[D.hcSetSeconds]( + t >= h.minute ? 0 : C * Math.floor(x.getSeconds() / C), + ); + if (t >= h.minute) + x[D.hcSetMinutes]( + t >= h.hour ? 0 : C * Math.floor(x[D.hcGetMinutes]() / C), + ); + if (t >= h.hour) + x[D.hcSetHours]( + t >= h.day ? 0 : C * Math.floor(x[D.hcGetHours]() / C), + ); + if (t >= h.day) + x[D.hcSetDate]( + t >= h.month ? 1 : C * Math.floor(x[D.hcGetDate]() / C), + ); + t >= h.month && + (x[D.hcSetMonth]( + t >= h.year ? 0 : C * Math.floor(x[D.hcGetMonth]() / C), + ), + (n = x[D.hcGetFullYear]())); + if (t >= h.year) x[D.hcSetFullYear](n - (n % C)); + if (t === h.week) + x[D.hcSetDate](x[D.hcGetDate]() - x[D.hcGetDay]() + e(b, 1)); + n = x[D.hcGetFullYear](); + b = x[D.hcGetMonth](); + var A = x[D.hcGetDate](), + F = x[D.hcGetHours](); + d = x.getTime(); + D.hcHasTimeZone && + ((q = + (!B || !!D.hcGetTimezoneOffset) && + (c - d > 4 * h.month || w(d) !== w(c))), + (N = w(x)), + (x = new D(d + N))); + B = x.getTime(); + for (d = 1; B < c; ) + k.push(B), + (B = + t === h.year + ? u(n + d * C, 0) + : t === h.month + ? u(n, b + d * C) + : !q || (t !== h.day && t !== h.week) + ? q && t === h.hour + ? u(n, b, A, F + d * C, 0, 0, N) - N + : B + t * C + : u(n, b, A + d * C * (t === h.day ? 1 : 7))), + d++; + k.push(B); + t <= h.hour && + 1e4 > k.length && + l(k, function(a) { + 0 === a % 18e5 && + '000000000' === H('%H%M%S%L', a) && + (m[a] = 'day'); + }); + } + k.info = r(a, { higherRanks: m, totalRange: t * C }); + return k; + }; + E.prototype.normalizeTimeTickInterval = function(a, d) { + var c = d || [ + ['millisecond', [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]], + ['second', [1, 2, 5, 10, 15, 30]], + ['minute', [1, 2, 5, 10, 15, 30]], + ['hour', [1, 2, 3, 4, 6, 8, 12]], + ['day', [1, 2]], + ['week', [1, 2]], + ['month', [1, 2, 3, 4, 6]], + ['year', null], + ]; + d = c[c.length - 1]; + var b = h[d[0]], + k = d[1], + e; + for ( + e = 0; + e < c.length && + !((d = c[e]), + (b = h[d[0]]), + (k = d[1]), + c[e + 1] && a <= (b * k[k.length - 1] + h[c[e + 1][0]]) / 2); + e++ + ); + b === h.year && a < 5 * b && (k = [1, 2, 5]); + a = u(a / b, k, 'year' === d[0] ? Math.max(n(a / b), 1) : 1); + return { unitRange: b, count: a, unitName: d[0] }; + }; + })(M); + (function(a) { + var E = a.Axis, + D = a.getMagnitude, + H = a.map, + p = a.normalizeTickInterval, + f = a.pick; + E.prototype.getLogTickPositions = function(a, r, n, w) { + var l = this.options, + e = this.len, + h = this.lin2log, + m = this.log2lin, + d = []; + w || (this._minorAutoInterval = null); + if (0.5 <= a) + (a = Math.round(a)), (d = this.getLinearTickPositions(a, r, n)); + else if (0.08 <= a) + for ( + var e = Math.floor(r), + c, + b, + k, + z, + B, + l = + 0.3 < a + ? [1, 2, 4] + : 0.15 < a + ? [1, 2, 4, 6, 8] + : [1, 2, 3, 4, 5, 6, 7, 8, 9]; + e < n + 1 && !B; + e++ + ) + for (b = l.length, c = 0; c < b && !B; c++) + (k = m(h(e) * l[c])), + k > r && (!w || z <= n) && void 0 !== z && d.push(z), + z > n && (B = !0), + (z = k); + else + (r = h(r)), + (n = h(n)), + (a = w ? this.getMinorTickInterval() : l.tickInterval), + (a = f( + 'auto' === a ? null : a, + this._minorAutoInterval, + ((l.tickPixelInterval / (w ? 5 : 1)) * (n - r)) / + ((w ? e / this.tickPositions.length : e) || 1), + )), + (a = p(a, null, D(a))), + (d = H(this.getLinearTickPositions(a, r, n), m)), + w || (this._minorAutoInterval = a / 5); + w || (this.tickInterval = a); + return d; + }; + E.prototype.log2lin = function(a) { + return Math.log(a) / Math.LN10; + }; + E.prototype.lin2log = function(a) { + return Math.pow(10, a); + }; + })(M); + (function(a, E) { + var D = a.arrayMax, + H = a.arrayMin, + p = a.defined, + f = a.destroyObjectProperties, + l = a.each, + r = a.erase, + n = a.merge, + w = a.pick; + a.PlotLineOrBand = function(a, e) { + this.axis = a; + e && ((this.options = e), (this.id = e.id)); + }; + a.PlotLineOrBand.prototype = { + render: function() { + var f = this, + e = f.axis, + h = e.horiz, + m = f.options, + d = m.label, + c = f.label, + b = m.to, + k = m.from, + z = m.value, + l = p(k) && p(b), + r = p(z), + x = f.svgElem, + K = !x, + t = [], + C = m.color, + N = w(m.zIndex, 0), + q = m.events, + t = { + class: + 'highcharts-plot-' + + (l ? 'band ' : 'line ') + + (m.className || ''), + }, + A = {}, + F = e.chart.renderer, + G = l ? 'bands' : 'lines', + g = e.log2lin; + e.isLog && ((k = g(k)), (b = g(b)), (z = g(z))); + r + ? ((t = { stroke: C, 'stroke-width': m.width }), + m.dashStyle && (t.dashstyle = m.dashStyle)) + : l && + (C && (t.fill = C), + m.borderWidth && + ((t.stroke = m.borderColor), + (t['stroke-width'] = m.borderWidth))); + A.zIndex = N; + G += '-' + N; + (C = e.plotLinesAndBandsGroups[G]) || + (e.plotLinesAndBandsGroups[G] = C = F.g('plot-' + G) + .attr(A) + .add()); + K && + (f.svgElem = x = F.path() + .attr(t) + .add(C)); + if (r) t = e.getPlotLinePath(z, x.strokeWidth()); + else if (l) t = e.getPlotBandPath(k, b, m); + else return; + K && t && t.length + ? (x.attr({ d: t }), + q && + a.objectEach(q, function(a, b) { + x.on(b, function(a) { + q[b].apply(f, [a]); + }); + })) + : x && + (t + ? (x.show(), x.animate({ d: t })) + : (x.hide(), c && (f.label = c = c.destroy()))); + d && + p(d.text) && + t && + t.length && + 0 < e.width && + 0 < e.height && + !t.flat + ? ((d = n( + { + align: h && l && 'center', + x: h ? !l && 4 : 10, + verticalAlign: !h && l && 'middle', + y: h ? (l ? 16 : 10) : l ? 6 : -4, + rotation: h && !l && 90, + }, + d, + )), + this.renderLabel(d, t, l, N)) + : c && c.hide(); + return f; + }, + renderLabel: function(a, e, h, m) { + var d = this.label, + c = this.axis.chart.renderer; + d || + ((d = { + align: a.textAlign || a.align, + rotation: a.rotation, + class: + 'highcharts-plot-' + + (h ? 'band' : 'line') + + '-label ' + + (a.className || ''), + }), + (d.zIndex = m), + (this.label = d = c + .text(a.text, 0, 0, a.useHTML) + .attr(d) + .add()), + d.css(a.style)); + m = e.xBounds || [e[1], e[4], h ? e[6] : e[1]]; + e = e.yBounds || [e[2], e[5], h ? e[7] : e[2]]; + h = H(m); + c = H(e); + d.align(a, !1, { x: h, y: c, width: D(m) - h, height: D(e) - c }); + d.show(); + }, + destroy: function() { + r(this.axis.plotLinesAndBands, this); + delete this.axis; + f(this); + }, + }; + a.extend(E.prototype, { + getPlotBandPath: function(a, e) { + var h = this.getPlotLinePath(e, null, null, !0), + m = this.getPlotLinePath(a, null, null, !0), + d = [], + c = this.horiz, + b = 1, + k; + a = (a < this.min && e < this.min) || (a > this.max && e > this.max); + if (m && h) + for ( + a && ((k = m.toString() === h.toString()), (b = 0)), a = 0; + a < m.length; + a += 6 + ) + c && h[a + 1] === m[a + 1] + ? ((h[a + 1] += b), (h[a + 4] += b)) + : c || + h[a + 2] !== m[a + 2] || + ((h[a + 2] += b), (h[a + 5] += b)), + d.push( + 'M', + m[a + 1], + m[a + 2], + 'L', + m[a + 4], + m[a + 5], + h[a + 4], + h[a + 5], + h[a + 1], + h[a + 2], + 'z', + ), + (d.flat = k); + return d; + }, + addPlotBand: function(a) { + return this.addPlotBandOrLine(a, 'plotBands'); + }, + addPlotLine: function(a) { + return this.addPlotBandOrLine(a, 'plotLines'); + }, + addPlotBandOrLine: function(f, e) { + var h = new a.PlotLineOrBand(this, f).render(), + m = this.userOptions; + h && + (e && ((m[e] = m[e] || []), m[e].push(f)), + this.plotLinesAndBands.push(h)); + return h; + }, + removePlotBandOrLine: function(a) { + for ( + var e = this.plotLinesAndBands, + h = this.options, + m = this.userOptions, + d = e.length; + d--; + + ) + e[d].id === a && e[d].destroy(); + l( + [ + h.plotLines || [], + m.plotLines || [], + h.plotBands || [], + m.plotBands || [], + ], + function(c) { + for (d = c.length; d--; ) c[d].id === a && r(c, c[d]); + }, + ); + }, + removePlotBand: function(a) { + this.removePlotBandOrLine(a); + }, + removePlotLine: function(a) { + this.removePlotBandOrLine(a); + }, + }); + })(M, V); + (function(a) { + var E = a.dateFormat, + D = a.each, + H = a.extend, + p = a.format, + f = a.isNumber, + l = a.map, + r = a.merge, + n = a.pick, + w = a.splat, + u = a.syncTimeout, + e = a.timeUnits; + a.Tooltip = function() { + this.init.apply(this, arguments); + }; + a.Tooltip.prototype = { + init: function(a, e) { + this.chart = a; + this.options = e; + this.crosshairs = []; + this.now = { x: 0, y: 0 }; + this.isHidden = !0; + this.split = e.split && !a.inverted; + this.shared = e.shared || this.split; + }, + cleanSplit: function(a) { + D(this.chart.series, function(e) { + var d = e && e.tt; + d && (!d.isActive || a ? (e.tt = d.destroy()) : (d.isActive = !1)); + }); + }, + getLabel: function() { + var a = this.chart.renderer, + e = this.options; + this.label || + (this.split + ? (this.label = a.g('tooltip')) + : ((this.label = a + .label( + '', + 0, + 0, + e.shape || 'callout', + null, + null, + e.useHTML, + null, + 'tooltip', + ) + .attr({ padding: e.padding, r: e.borderRadius })), + this.label + .attr({ + fill: e.backgroundColor, + 'stroke-width': e.borderWidth, + }) + .css(e.style) + .shadow(e.shadow)), + this.label.attr({ zIndex: 8 }).add()); + return this.label; + }, + update: function(a) { + this.destroy(); + r(!0, this.chart.options.tooltip.userOptions, a); + this.init(this.chart, r(!0, this.options, a)); + }, + destroy: function() { + this.label && (this.label = this.label.destroy()); + this.split && + this.tt && + (this.cleanSplit(this.chart, !0), (this.tt = this.tt.destroy())); + clearTimeout(this.hideTimer); + clearTimeout(this.tooltipTimeout); + }, + move: function(a, e, d, c) { + var b = this, + k = b.now, + h = + !1 !== b.options.animation && + !b.isHidden && + (1 < Math.abs(a - k.x) || 1 < Math.abs(e - k.y)), + m = b.followPointer || 1 < b.len; + H(k, { + x: h ? (2 * k.x + a) / 3 : a, + y: h ? (k.y + e) / 2 : e, + anchorX: m ? void 0 : h ? (2 * k.anchorX + d) / 3 : d, + anchorY: m ? void 0 : h ? (k.anchorY + c) / 2 : c, + }); + b.getLabel().attr(k); + h && + (clearTimeout(this.tooltipTimeout), + (this.tooltipTimeout = setTimeout(function() { + b && b.move(a, e, d, c); + }, 32))); + }, + hide: function(a) { + var e = this; + clearTimeout(this.hideTimer); + a = n(a, this.options.hideDelay, 500); + this.isHidden || + (this.hideTimer = u(function() { + e.getLabel()[a ? 'fadeOut' : 'hide'](); + e.isHidden = !0; + }, a)); + }, + getAnchor: function(a, e) { + var d, + c = this.chart, + b = c.inverted, + k = c.plotTop, + h = c.plotLeft, + m = 0, + f = 0, + x, + n; + a = w(a); + d = a[0].tooltipPos; + this.followPointer && + e && + (void 0 === e.chartX && (e = c.pointer.normalize(e)), + (d = [e.chartX - c.plotLeft, e.chartY - k])); + d || + (D(a, function(a) { + x = a.series.yAxis; + n = a.series.xAxis; + m += a.plotX + (!b && n ? n.left - h : 0); + f += + (a.plotLow ? (a.plotLow + a.plotHigh) / 2 : a.plotY) + + (!b && x ? x.top - k : 0); + }), + (m /= a.length), + (f /= a.length), + (d = [ + b ? c.plotWidth - f : m, + this.shared && !b && 1 < a.length && e + ? e.chartY - k + : b + ? c.plotHeight - m + : f, + ])); + return l(d, Math.round); + }, + getPosition: function(a, e, d) { + var c = this.chart, + b = this.distance, + k = {}, + h = (c.inverted && d.h) || 0, + m, + f = [ + 'y', + c.chartHeight, + e, + d.plotY + c.plotTop, + c.plotTop, + c.plotTop + c.plotHeight, + ], + x = [ + 'x', + c.chartWidth, + a, + d.plotX + c.plotLeft, + c.plotLeft, + c.plotLeft + c.plotWidth, + ], + l = !this.followPointer && n(d.ttBelow, !c.inverted === !!d.negative), + t = function(a, c, d, g, e, q) { + var m = d < g - b, + z = g + b + d < c, + A = g - b - d; + g += b; + if (l && z) k[a] = g; + else if (!l && m) k[a] = A; + else if (m) k[a] = Math.min(q - d, 0 > A - h ? A : A - h); + else if (z) k[a] = Math.max(e, g + h + d > c ? g : g + h); + else return !1; + }, + C = function(a, c, d, g) { + var e; + g < b || g > c - b + ? (e = !1) + : (k[a] = g < d / 2 ? 1 : g > c - d / 2 ? c - d - 2 : g - d / 2); + return e; + }, + p = function(a) { + var b = f; + f = x; + x = b; + m = a; + }, + q = function() { + !1 !== t.apply(0, f) + ? !1 !== C.apply(0, x) || m || (p(!0), q()) + : m + ? (k.x = k.y = 0) + : (p(!0), q()); + }; + (c.inverted || 1 < this.len) && p(); + q(); + return k; + }, + defaultFormatter: function(a) { + var e = this.points || w(this), + d; + d = [a.tooltipFooterHeaderFormatter(e[0])]; + d = d.concat(a.bodyFormatter(e)); + d.push(a.tooltipFooterHeaderFormatter(e[0], !0)); + return d; + }, + refresh: function(a, e) { + var d, + c = this.options, + b, + k = a, + h, + m = {}, + f = []; + d = c.formatter || this.defaultFormatter; + var m = this.shared, + x; + c.enabled && + (clearTimeout(this.hideTimer), + (this.followPointer = w(k)[0].series.tooltipOptions.followPointer), + (h = this.getAnchor(k, e)), + (e = h[0]), + (b = h[1]), + !m || (k.series && k.series.noSharedTooltip) + ? (m = k.getLabelConfig()) + : (D(k, function(a) { + a.setState('hover'); + f.push(a.getLabelConfig()); + }), + (m = { x: k[0].category, y: k[0].y }), + (m.points = f), + (k = k[0])), + (this.len = f.length), + (m = d.call(m, this)), + (x = k.series), + (this.distance = n(x.tooltipOptions.distance, 16)), + !1 === m + ? this.hide() + : ((d = this.getLabel()), + this.isHidden && d.attr({ opacity: 1 }).show(), + this.split + ? this.renderSplit(m, w(a)) + : (c.style.width || + d.css({ width: this.chart.spacingBox.width }), + d.attr({ text: m && m.join ? m.join('') : m }), + d + .removeClass(/highcharts-color-[\d]+/g) + .addClass( + 'highcharts-color-' + n(k.colorIndex, x.colorIndex), + ), + d.attr({ + stroke: c.borderColor || k.color || x.color || '#666666', + }), + this.updatePosition({ + plotX: e, + plotY: b, + negative: k.negative, + ttBelow: k.ttBelow, + h: h[2] || 0, + })), + (this.isHidden = !1))); + }, + renderSplit: function(e, m) { + var d = this, + c = [], + b = this.chart, + k = b.renderer, + h = !0, + f = this.options, + l = 0, + x = this.getLabel(); + a.isString(e) && (e = [!1, e]); + D(e.slice(0, m.length + 1), function(a, e) { + if (!1 !== a) { + e = m[e - 1] || { isHeader: !0, plotX: m[0].plotX }; + var z = e.series || d, + t = z.tt, + q = e.series || {}, + A = 'highcharts-color-' + n(e.colorIndex, q.colorIndex, 'none'); + t || + (z.tt = t = k + .label(null, null, null, 'callout', null, null, f.useHTML) + .addClass('highcharts-tooltip-box ' + A) + .attr({ + padding: f.padding, + r: f.borderRadius, + fill: f.backgroundColor, + stroke: f.borderColor || e.color || q.color || '#333333', + 'stroke-width': f.borderWidth, + }) + .add(x)); + t.isActive = !0; + t.attr({ text: a }); + t.css(f.style).shadow(f.shadow); + a = t.getBBox(); + q = a.width + t.strokeWidth(); + e.isHeader + ? ((l = a.height), + (q = Math.max( + 0, + Math.min(e.plotX + b.plotLeft - q / 2, b.chartWidth - q), + ))) + : (q = e.plotX + b.plotLeft - n(f.distance, 16) - q); + 0 > q && (h = !1); + a = + (e.series && e.series.yAxis && e.series.yAxis.pos) + + (e.plotY || 0); + a -= b.plotTop; + c.push({ + target: e.isHeader ? b.plotHeight + l : a, + rank: e.isHeader ? 1 : 0, + size: z.tt.getBBox().height + 1, + point: e, + x: q, + tt: t, + }); + } + }); + this.cleanSplit(); + a.distribute(c, b.plotHeight + l); + D(c, function(a) { + var c = a.point, + d = c.series; + a.tt.attr({ + visibility: void 0 === a.pos ? 'hidden' : 'inherit', + x: h || c.isHeader ? a.x : c.plotX + b.plotLeft + n(f.distance, 16), + y: a.pos + b.plotTop, + anchorX: c.isHeader ? c.plotX + b.plotLeft : c.plotX + d.xAxis.pos, + anchorY: c.isHeader + ? a.pos + b.plotTop - 15 + : c.plotY + d.yAxis.pos, + }); + }); + }, + updatePosition: function(a) { + var e = this.chart, + d = this.getLabel(), + d = (this.options.positioner || this.getPosition).call( + this, + d.width, + d.height, + a, + ); + this.move( + Math.round(d.x), + Math.round(d.y || 0), + a.plotX + e.plotLeft, + a.plotY + e.plotTop, + ); + }, + getDateFormat: function(a, m, d, c) { + var b = E('%m-%d %H:%M:%S.%L', m), + k, + h, + f = { millisecond: 15, second: 12, minute: 9, hour: 6, day: 3 }, + l = 'millisecond'; + for (h in e) { + if ( + a === e.week && + +E('%w', m) === d && + '00:00:00.000' === b.substr(6) + ) { + h = 'week'; + break; + } + if (e[h] > a) { + h = l; + break; + } + if (f[h] && b.substr(f[h]) !== '01-01 00:00:00.000'.substr(f[h])) + break; + 'week' !== h && (l = h); + } + h && (k = c[h]); + return k; + }, + getXDateFormat: function(a, e, d) { + e = e.dateTimeLabelFormats; + var c = d && d.closestPointRange; + return ( + (c ? this.getDateFormat(c, a.x, d.options.startOfWeek, e) : e.day) || + e.year + ); + }, + tooltipFooterHeaderFormatter: function(a, e) { + e = e ? 'footer' : 'header'; + var d = a.series, + c = d.tooltipOptions, + b = c.xDateFormat, + k = d.xAxis, + h = k && 'datetime' === k.options.type && f(a.key), + m = c[e + 'Format']; + h && !b && (b = this.getXDateFormat(a, c, k)); + h && + b && + D((a.point && a.point.tooltipDateKeys) || ['key'], function(a) { + m = m.replace('{point.' + a + '}', '{point.' + a + ':' + b + '}'); + }); + return p(m, { point: a, series: d }); + }, + bodyFormatter: function(a) { + return l(a, function(a) { + var d = a.series.tooltipOptions; + return ( + d[(a.point.formatPrefix || 'point') + 'Formatter'] || + a.point.tooltipFormatter + ).call(a.point, d[(a.point.formatPrefix || 'point') + 'Format']); + }); + }, + }; + })(M); + (function(a) { + var E = a.addEvent, + D = a.attr, + H = a.charts, + p = a.color, + f = a.css, + l = a.defined, + r = a.each, + n = a.extend, + w = a.find, + u = a.fireEvent, + e = a.isObject, + h = a.offset, + m = a.pick, + d = a.splat, + c = a.Tooltip; + a.Pointer = function(a, c) { + this.init(a, c); + }; + a.Pointer.prototype = { + init: function(a, d) { + this.options = d; + this.chart = a; + this.runChartClick = d.chart.events && !!d.chart.events.click; + this.pinchDown = []; + this.lastValidTouch = {}; + c && + ((a.tooltip = new c(a, d.tooltip)), + (this.followTouchMove = m(d.tooltip.followTouchMove, !0))); + this.setDOMEvents(); + }, + zoomOption: function(a) { + var b = this.chart, + c = b.options.chart, + d = c.zoomType || '', + b = b.inverted; + /touch/.test(a.type) && (d = m(c.pinchType, d)); + this.zoomX = a = /x/.test(d); + this.zoomY = d = /y/.test(d); + this.zoomHor = (a && !b) || (d && b); + this.zoomVert = (d && !b) || (a && b); + this.hasZoom = a || d; + }, + normalize: function(a, c) { + var b; + b = a.touches + ? a.touches.length + ? a.touches.item(0) + : a.changedTouches[0] + : a; + c || (this.chartPosition = c = h(this.chart.container)); + return n(a, { + chartX: Math.round(b.pageX - c.left), + chartY: Math.round(b.pageY - c.top), + }); + }, + getCoordinates: function(a) { + var b = { xAxis: [], yAxis: [] }; + r(this.chart.axes, function(c) { + b[c.isXAxis ? 'xAxis' : 'yAxis'].push({ + axis: c, + value: c.toValue(a[c.horiz ? 'chartX' : 'chartY']), + }); + }); + return b; + }, + findNearestKDPoint: function(a, c, d) { + var b; + r(a, function(a) { + var k = + !(a.noSharedTooltip && c) && + 0 > a.options.findNearestPointBy.indexOf('y'); + a = a.searchPoint(d, k); + if ((k = e(a, !0)) && !(k = !e(b, !0))) + var k = b.distX - a.distX, + h = b.dist - a.dist, + m = + (a.series.group && a.series.group.zIndex) - + (b.series.group && b.series.group.zIndex), + k = + 0 < + (0 !== k && c + ? k + : 0 !== h + ? h + : 0 !== m + ? m + : b.series.index > a.series.index + ? -1 + : 1); + k && (b = a); + }); + return b; + }, + getPointFromEvent: function(a) { + a = a.target; + for (var b; a && !b; ) (b = a.point), (a = a.parentNode); + return b; + }, + getChartCoordinatesFromPoint: function(a, c) { + var b = a.series, + d = b.xAxis, + b = b.yAxis, + k = m(a.clientX, a.plotX); + if (d && b) + return c + ? { chartX: d.len + d.pos - k, chartY: b.len + b.pos - a.plotY } + : { chartX: k + d.pos, chartY: a.plotY + b.pos }; + }, + getHoverData: function(b, c, d, h, f, l, n) { + var k, + z = [], + x = n && n.isBoosting; + h = !(!h || !b); + n = + c && !c.stickyTracking + ? [c] + : a.grep(d, function(a) { + return ( + a.visible && + !(!f && a.directTouch) && + m(a.options.enableMouseTracking, !0) && + a.stickyTracking + ); + }); + c = (k = h ? b : this.findNearestKDPoint(n, f, l)) && k.series; + k && + (f && !c.noSharedTooltip + ? ((n = a.grep(d, function(a) { + return ( + a.visible && + !(!f && a.directTouch) && + m(a.options.enableMouseTracking, !0) && + !a.noSharedTooltip + ); + })), + r(n, function(a) { + var b = w(a.points, function(a) { + return a.x === k.x && !a.isNull; + }); + e(b) && (x && (b = a.getPoint(b)), z.push(b)); + })) + : z.push(k)); + return { hoverPoint: k, hoverSeries: c, hoverPoints: z }; + }, + runPointActions: function(b, c) { + var d = this.chart, + k = d.tooltip && d.tooltip.options.enabled ? d.tooltip : void 0, + e = k ? k.shared : !1, + h = c || d.hoverPoint, + f = (h && h.series) || d.hoverSeries, + f = this.getHoverData( + h, + f, + d.series, + !!c || (f && f.directTouch && this.isDirectTouch), + e, + b, + { isBoosting: d.isBoosting }, + ), + l, + h = f.hoverPoint; + l = f.hoverPoints; + c = (f = f.hoverSeries) && f.tooltipOptions.followPointer; + e = e && f && !f.noSharedTooltip; + if (h && (h !== d.hoverPoint || (k && k.isHidden))) { + r(d.hoverPoints || [], function(b) { + -1 === a.inArray(b, l) && b.setState(); + }); + r(l || [], function(a) { + a.setState('hover'); + }); + if (d.hoverSeries !== f) f.onMouseOver(); + d.hoverPoint && d.hoverPoint.firePointEvent('mouseOut'); + if (!h.series) return; + h.firePointEvent('mouseOver'); + d.hoverPoints = l; + d.hoverPoint = h; + k && k.refresh(e ? l : h, b); + } else + c && + k && + !k.isHidden && + ((h = k.getAnchor([{}], b)), + k.updatePosition({ plotX: h[0], plotY: h[1] })); + this.unDocMouseMove || + (this.unDocMouseMove = E( + d.container.ownerDocument, + 'mousemove', + function(b) { + var c = H[a.hoverChartIndex]; + if (c) c.pointer.onDocumentMouseMove(b); + }, + )); + r(d.axes, function(c) { + var d = m(c.crosshair.snap, !0), + k = d + ? a.find(l, function(a) { + return a.series[c.coll] === c; + }) + : void 0; + k || !d ? c.drawCrosshair(b, k) : c.hideCrosshair(); + }); + }, + reset: function(a, c) { + var b = this.chart, + k = b.hoverSeries, + e = b.hoverPoint, + h = b.hoverPoints, + m = b.tooltip, + f = m && m.shared ? h : e; + a && + f && + r(d(f), function(b) { + b.series.isCartesian && void 0 === b.plotX && (a = !1); + }); + if (a) + m && + f && + (m.refresh(f), + e && + (e.setState(e.state, !0), + r(b.axes, function(a) { + a.crosshair && a.drawCrosshair(null, e); + }))); + else { + if (e) e.onMouseOut(); + h && + r(h, function(a) { + a.setState(); + }); + if (k) k.onMouseOut(); + m && m.hide(c); + this.unDocMouseMove && (this.unDocMouseMove = this.unDocMouseMove()); + r(b.axes, function(a) { + a.hideCrosshair(); + }); + this.hoverX = b.hoverPoints = b.hoverPoint = null; + } + }, + scaleGroups: function(a, c) { + var b = this.chart, + d; + r(b.series, function(k) { + d = a || k.getPlotBox(); + k.xAxis && + k.xAxis.zoomEnabled && + k.group && + (k.group.attr(d), + k.markerGroup && + (k.markerGroup.attr(d), + k.markerGroup.clip(c ? b.clipRect : null)), + k.dataLabelsGroup && k.dataLabelsGroup.attr(d)); + }); + b.clipRect.attr(c || b.clipBox); + }, + dragStart: function(a) { + var b = this.chart; + b.mouseIsDown = a.type; + b.cancelClick = !1; + b.mouseDownX = this.mouseDownX = a.chartX; + b.mouseDownY = this.mouseDownY = a.chartY; + }, + drag: function(a) { + var b = this.chart, + c = b.options.chart, + d = a.chartX, + e = a.chartY, + h = this.zoomHor, + m = this.zoomVert, + f = b.plotLeft, + l = b.plotTop, + n = b.plotWidth, + q = b.plotHeight, + A, + F = this.selectionMarker, + G = this.mouseDownX, + g = this.mouseDownY, + v = c.panKey && a[c.panKey + 'Key']; + (F && F.touch) || + (d < f ? (d = f) : d > f + n && (d = f + n), + e < l ? (e = l) : e > l + q && (e = l + q), + (this.hasDragged = Math.sqrt( + Math.pow(G - d, 2) + Math.pow(g - e, 2), + )), + 10 < this.hasDragged && + ((A = b.isInsidePlot(G - f, g - l)), + b.hasCartesianSeries && + (this.zoomX || this.zoomY) && + A && + !v && + !F && + (this.selectionMarker = F = b.renderer + .rect(f, l, h ? 1 : n, m ? 1 : q, 0) + .attr({ + fill: + c.selectionMarkerFill || + p('#335cad') + .setOpacity(0.25) + .get(), + class: 'highcharts-selection-marker', + zIndex: 7, + }) + .add()), + F && + h && + ((d -= G), + F.attr({ width: Math.abs(d), x: (0 < d ? 0 : d) + G })), + F && + m && + ((d = e - g), + F.attr({ height: Math.abs(d), y: (0 < d ? 0 : d) + g })), + A && !F && c.panning && b.pan(a, c.panning))); + }, + drop: function(a) { + var b = this, + c = this.chart, + d = this.hasPinched; + if (this.selectionMarker) { + var e = { originalEvent: a, xAxis: [], yAxis: [] }, + h = this.selectionMarker, + m = h.attr ? h.attr('x') : h.x, + t = h.attr ? h.attr('y') : h.y, + p = h.attr ? h.attr('width') : h.width, + w = h.attr ? h.attr('height') : h.height, + q; + if (this.hasDragged || d) + r(c.axes, function(c) { + if ( + c.zoomEnabled && + l(c.min) && + (d || b[{ xAxis: 'zoomX', yAxis: 'zoomY' }[c.coll]]) + ) { + var k = c.horiz, + h = 'touchend' === a.type ? c.minPixelPadding : 0, + g = c.toValue((k ? m : t) + h), + k = c.toValue((k ? m + p : t + w) - h); + e[c.coll].push({ + axis: c, + min: Math.min(g, k), + max: Math.max(g, k), + }); + q = !0; + } + }), + q && + u(c, 'selection', e, function(a) { + c.zoom(n(a, d ? { animation: !1 } : null)); + }); + this.selectionMarker = this.selectionMarker.destroy(); + d && this.scaleGroups(); + } + c && + (f(c.container, { cursor: c._cursor }), + (c.cancelClick = 10 < this.hasDragged), + (c.mouseIsDown = this.hasDragged = this.hasPinched = !1), + (this.pinchDown = [])); + }, + onContainerMouseDown: function(a) { + 2 !== a.button && + ((a = this.normalize(a)), + this.zoomOption(a), + a.preventDefault && a.preventDefault(), + this.dragStart(a)); + }, + onDocumentMouseUp: function(b) { + H[a.hoverChartIndex] && H[a.hoverChartIndex].pointer.drop(b); + }, + onDocumentMouseMove: function(a) { + var b = this.chart, + c = this.chartPosition; + a = this.normalize(a, c); + !c || + this.inClass(a.target, 'highcharts-tracker') || + b.isInsidePlot(a.chartX - b.plotLeft, a.chartY - b.plotTop) || + this.reset(); + }, + onContainerMouseLeave: function(b) { + var c = H[a.hoverChartIndex]; + c && + (b.relatedTarget || b.toElement) && + (c.pointer.reset(), (c.pointer.chartPosition = null)); + }, + onContainerMouseMove: function(b) { + var c = this.chart; + (l(a.hoverChartIndex) && + H[a.hoverChartIndex] && + H[a.hoverChartIndex].mouseIsDown) || + (a.hoverChartIndex = c.index); + b = this.normalize(b); + b.returnValue = !1; + 'mousedown' === c.mouseIsDown && this.drag(b); + (!this.inClass(b.target, 'highcharts-tracker') && + !c.isInsidePlot(b.chartX - c.plotLeft, b.chartY - c.plotTop)) || + c.openMenu || + this.runPointActions(b); + }, + inClass: function(a, c) { + for (var b; a; ) { + if ((b = D(a, 'class'))) { + if (-1 !== b.indexOf(c)) return !0; + if (-1 !== b.indexOf('highcharts-container')) return !1; + } + a = a.parentNode; + } + }, + onTrackerMouseOut: function(a) { + var b = this.chart.hoverSeries; + a = a.relatedTarget || a.toElement; + this.isDirectTouch = !1; + if ( + !( + !b || + !a || + b.stickyTracking || + this.inClass(a, 'highcharts-tooltip') || + (this.inClass(a, 'highcharts-series-' + b.index) && + this.inClass(a, 'highcharts-tracker')) + ) + ) + b.onMouseOut(); + }, + onContainerClick: function(a) { + var b = this.chart, + c = b.hoverPoint, + d = b.plotLeft, + e = b.plotTop; + a = this.normalize(a); + b.cancelClick || + (c && this.inClass(a.target, 'highcharts-tracker') + ? (u(c.series, 'click', n(a, { point: c })), + b.hoverPoint && c.firePointEvent('click', a)) + : (n(a, this.getCoordinates(a)), + b.isInsidePlot(a.chartX - d, a.chartY - e) && u(b, 'click', a))); + }, + setDOMEvents: function() { + var b = this, + c = b.chart.container, + d = c.ownerDocument; + c.onmousedown = function(a) { + b.onContainerMouseDown(a); + }; + c.onmousemove = function(a) { + b.onContainerMouseMove(a); + }; + c.onclick = function(a) { + b.onContainerClick(a); + }; + this.unbindContainerMouseLeave = E( + c, + 'mouseleave', + b.onContainerMouseLeave, + ); + a.unbindDocumentMouseUp || + (a.unbindDocumentMouseUp = E(d, 'mouseup', b.onDocumentMouseUp)); + a.hasTouch && + ((c.ontouchstart = function(a) { + b.onContainerTouchStart(a); + }), + (c.ontouchmove = function(a) { + b.onContainerTouchMove(a); + }), + a.unbindDocumentTouchEnd || + (a.unbindDocumentTouchEnd = E( + d, + 'touchend', + b.onDocumentTouchEnd, + ))); + }, + destroy: function() { + var b = this; + b.unDocMouseMove && b.unDocMouseMove(); + this.unbindContainerMouseLeave(); + a.chartCount || + (a.unbindDocumentMouseUp && + (a.unbindDocumentMouseUp = a.unbindDocumentMouseUp()), + a.unbindDocumentTouchEnd && + (a.unbindDocumentTouchEnd = a.unbindDocumentTouchEnd())); + clearInterval(b.tooltipTimeout); + a.objectEach(b, function(a, c) { + b[c] = null; + }); + }, + }; + })(M); + (function(a) { + var E = a.charts, + D = a.each, + H = a.extend, + p = a.map, + f = a.noop, + l = a.pick; + H(a.Pointer.prototype, { + pinchTranslate: function(a, f, l, p, e, h) { + this.zoomHor && this.pinchTranslateDirection(!0, a, f, l, p, e, h); + this.zoomVert && this.pinchTranslateDirection(!1, a, f, l, p, e, h); + }, + pinchTranslateDirection: function(a, f, l, p, e, h, m, d) { + var c = this.chart, + b = a ? 'x' : 'y', + k = a ? 'X' : 'Y', + z = 'chart' + k, + n = a ? 'width' : 'height', + r = c['plot' + (a ? 'Left' : 'Top')], + x, + w, + t = d || 1, + C = c.inverted, + u = c.bounds[a ? 'h' : 'v'], + q = 1 === f.length, + A = f[0][z], + F = l[0][z], + G = !q && f[1][z], + g = !q && l[1][z], + v; + l = function() { + !q && + 20 < Math.abs(A - G) && + (t = d || Math.abs(F - g) / Math.abs(A - G)); + w = (r - F) / t + A; + x = c['plot' + (a ? 'Width' : 'Height')] / t; + }; + l(); + f = w; + f < u.min + ? ((f = u.min), (v = !0)) + : f + x > u.max && ((f = u.max - x), (v = !0)); + v + ? ((F -= 0.8 * (F - m[b][0])), q || (g -= 0.8 * (g - m[b][1])), l()) + : (m[b] = [F, g]); + C || ((h[b] = w - r), (h[n] = x)); + h = C ? 1 / t : t; + e[n] = x; + e[b] = f; + p[C ? (a ? 'scaleY' : 'scaleX') : 'scale' + k] = t; + p['translate' + k] = h * r + (F - h * A); + }, + pinch: function(a) { + var n = this, + r = n.chart, + u = n.pinchDown, + e = a.touches, + h = e.length, + m = n.lastValidTouch, + d = n.hasZoom, + c = n.selectionMarker, + b = {}, + k = + 1 === h && + ((n.inClass(a.target, 'highcharts-tracker') && r.runTrackerClick) || + n.runChartClick), + z = {}; + 1 < h && (n.initiated = !0); + d && n.initiated && !k && a.preventDefault(); + p(e, function(a) { + return n.normalize(a); + }); + 'touchstart' === a.type + ? (D(e, function(a, b) { + u[b] = { chartX: a.chartX, chartY: a.chartY }; + }), + (m.x = [u[0].chartX, u[1] && u[1].chartX]), + (m.y = [u[0].chartY, u[1] && u[1].chartY]), + D(r.axes, function(a) { + if (a.zoomEnabled) { + var b = r.bounds[a.horiz ? 'h' : 'v'], + c = a.minPixelPadding, + d = a.toPixels(l(a.options.min, a.dataMin)), + e = a.toPixels(l(a.options.max, a.dataMax)), + k = Math.max(d, e); + b.min = Math.min(a.pos, Math.min(d, e) - c); + b.max = Math.max(a.pos + a.len, k + c); + } + }), + (n.res = !0)) + : n.followTouchMove && 1 === h + ? this.runPointActions(n.normalize(a)) + : u.length && + (c || + (n.selectionMarker = c = H({ destroy: f, touch: !0 }, r.plotBox)), + n.pinchTranslate(u, e, b, c, z, m), + (n.hasPinched = d), + n.scaleGroups(b, z), + n.res && ((n.res = !1), this.reset(!1, 0))); + }, + touch: function(f, n) { + var p = this.chart, + r, + e; + if (p.index !== a.hoverChartIndex) + this.onContainerMouseLeave({ relatedTarget: !0 }); + a.hoverChartIndex = p.index; + 1 === f.touches.length + ? ((f = this.normalize(f)), + (e = p.isInsidePlot(f.chartX - p.plotLeft, f.chartY - p.plotTop)) && + !p.openMenu + ? (n && this.runPointActions(f), + 'touchmove' === f.type && + ((n = this.pinchDown), + (r = n[0] + ? 4 <= + Math.sqrt( + Math.pow(n[0].chartX - f.chartX, 2) + + Math.pow(n[0].chartY - f.chartY, 2), + ) + : !1)), + l(r, !0) && this.pinch(f)) + : n && this.reset()) + : 2 === f.touches.length && this.pinch(f); + }, + onContainerTouchStart: function(a) { + this.zoomOption(a); + this.touch(a, !0); + }, + onContainerTouchMove: function(a) { + this.touch(a); + }, + onDocumentTouchEnd: function(f) { + E[a.hoverChartIndex] && E[a.hoverChartIndex].pointer.drop(f); + }, + }); + })(M); + (function(a) { + var E = a.addEvent, + D = a.charts, + H = a.css, + p = a.doc, + f = a.extend, + l = a.noop, + r = a.Pointer, + n = a.removeEvent, + w = a.win, + u = a.wrap; + if (!a.hasTouch && (w.PointerEvent || w.MSPointerEvent)) { + var e = {}, + h = !!w.PointerEvent, + m = function() { + var c = []; + c.item = function(a) { + return this[a]; + }; + a.objectEach(e, function(a) { + c.push({ pageX: a.pageX, pageY: a.pageY, target: a.target }); + }); + return c; + }, + d = function(c, b, d, e) { + ('touch' !== c.pointerType && + c.pointerType !== c.MSPOINTER_TYPE_TOUCH) || + !D[a.hoverChartIndex] || + (e(c), + (e = D[a.hoverChartIndex].pointer), + e[b]({ + type: d, + target: c.currentTarget, + preventDefault: l, + touches: m(), + })); + }; + f(r.prototype, { + onContainerPointerDown: function(a) { + d(a, 'onContainerTouchStart', 'touchstart', function(a) { + e[a.pointerId] = { + pageX: a.pageX, + pageY: a.pageY, + target: a.currentTarget, + }; + }); + }, + onContainerPointerMove: function(a) { + d(a, 'onContainerTouchMove', 'touchmove', function(a) { + e[a.pointerId] = { pageX: a.pageX, pageY: a.pageY }; + e[a.pointerId].target || (e[a.pointerId].target = a.currentTarget); + }); + }, + onDocumentPointerUp: function(a) { + d(a, 'onDocumentTouchEnd', 'touchend', function(a) { + delete e[a.pointerId]; + }); + }, + batchMSEvents: function(a) { + a( + this.chart.container, + h ? 'pointerdown' : 'MSPointerDown', + this.onContainerPointerDown, + ); + a( + this.chart.container, + h ? 'pointermove' : 'MSPointerMove', + this.onContainerPointerMove, + ); + a(p, h ? 'pointerup' : 'MSPointerUp', this.onDocumentPointerUp); + }, + }); + u(r.prototype, 'init', function(a, b, d) { + a.call(this, b, d); + this.hasZoom && + H(b.container, { + '-ms-touch-action': 'none', + 'touch-action': 'none', + }); + }); + u(r.prototype, 'setDOMEvents', function(a) { + a.apply(this); + (this.hasZoom || this.followTouchMove) && this.batchMSEvents(E); + }); + u(r.prototype, 'destroy', function(a) { + this.batchMSEvents(n); + a.call(this); + }); + } + })(M); + (function(a) { + var E = a.addEvent, + D = a.css, + H = a.discardElement, + p = a.defined, + f = a.each, + l = a.isFirefox, + r = a.marginNames, + n = a.merge, + w = a.pick, + u = a.setAnimation, + e = a.stableSort, + h = a.win, + m = a.wrap; + a.Legend = function(a, c) { + this.init(a, c); + }; + a.Legend.prototype = { + init: function(a, c) { + this.chart = a; + this.setOptions(c); + c.enabled && + (this.render(), + E(this.chart, 'endResize', function() { + this.legend.positionCheckboxes(); + })); + }, + setOptions: function(a) { + var c = w(a.padding, 8); + this.options = a; + this.itemStyle = a.itemStyle; + this.itemHiddenStyle = n(this.itemStyle, a.itemHiddenStyle); + this.itemMarginTop = a.itemMarginTop || 0; + this.padding = c; + this.initialItemY = c - 5; + this.itemHeight = this.maxItemWidth = 0; + this.symbolWidth = w(a.symbolWidth, 16); + this.pages = []; + }, + update: function(a, c) { + var b = this.chart; + this.setOptions(n(!0, this.options, a)); + this.destroy(); + b.isDirtyLegend = b.isDirtyBox = !0; + w(c, !0) && b.redraw(); + }, + colorizeItem: function(a, c) { + a.legendGroup[c ? 'removeClass' : 'addClass']( + 'highcharts-legend-item-hidden', + ); + var b = this.options, + d = a.legendItem, + e = a.legendLine, + h = a.legendSymbol, + f = this.itemHiddenStyle.color, + b = c ? b.itemStyle.color : f, + m = c ? a.color || f : f, + l = a.options && a.options.marker, + t = { fill: m }; + d && d.css({ fill: b, color: b }); + e && e.attr({ stroke: m }); + h && + (l && + h.isMarker && + ((t = a.pointAttribs()), c || (t.stroke = t.fill = f)), + h.attr(t)); + }, + positionItem: function(a) { + var c = this.options, + b = c.symbolPadding, + c = !c.rtl, + d = a._legendItemPos, + e = d[0], + d = d[1], + h = a.checkbox; + (a = a.legendGroup) && + a.element && + a.translate(c ? e : this.legendWidth - e - 2 * b - 4, d); + h && ((h.x = e), (h.y = d)); + }, + destroyItem: function(a) { + var c = a.checkbox; + f(['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'], function( + b, + ) { + a[b] && (a[b] = a[b].destroy()); + }); + c && H(a.checkbox); + }, + destroy: function() { + function a(a) { + this[a] && (this[a] = this[a].destroy()); + } + f(this.getAllItems(), function(c) { + f(['legendItem', 'legendGroup'], a, c); + }); + f('clipRect up down pager nav box title group'.split(' '), a, this); + this.display = null; + }, + positionCheckboxes: function() { + var a = this.group && this.group.alignAttr, + c, + b = this.clipHeight || this.legendHeight, + e = this.titleHeight; + a && + ((c = a.translateY), + f( + this.allItems, + function(d) { + var k = d.checkbox, + h; + k && + ((h = c + e + k.y + (this.scrollOffset || 0) + 3), + D(k, { + left: a.translateX + d.checkboxOffset + k.x - 20 + 'px', + top: h + 'px', + display: h > c - 6 && h < c + b - 6 ? '' : 'none', + })); + }, + this, + )); + }, + renderTitle: function() { + var a = this.options, + c = this.padding, + b = a.title, + e = 0; + b.text && + (this.title || + (this.title = this.chart.renderer + .label( + b.text, + c - 3, + c - 4, + null, + null, + null, + a.useHTML, + null, + 'legend-title', + ) + .attr({ zIndex: 1 }) + .css(b.style) + .add(this.group)), + (a = this.title.getBBox()), + (e = a.height), + (this.offsetWidth = a.width), + this.contentGroup.attr({ translateY: e })); + this.titleHeight = e; + }, + setText: function(d) { + var c = this.options; + d.legendItem.attr({ + text: c.labelFormat + ? a.format(c.labelFormat, d) + : c.labelFormatter.call(d), + }); + }, + renderItem: function(a) { + var c = this.chart, + b = c.renderer, + d = this.options, + e = 'horizontal' === d.layout, + h = this.symbolWidth, + f = d.symbolPadding, + m = this.itemStyle, + l = this.itemHiddenStyle, + t = this.padding, + p = e ? w(d.itemDistance, 20) : 0, + r = !d.rtl, + q = d.width, + A = d.itemMarginBottom || 0, + F = this.itemMarginTop, + G = a.legendItem, + g = !a.series, + v = !g && a.series.drawLegendSymbol ? a.series : a, + u = v.options, + L = this.createCheckboxForItem && u && u.showCheckbox, + u = h + f + p + (L ? 20 : 0), + P = d.useHTML, + J = a.options.className; + G || + ((a.legendGroup = b + .g('legend-item') + .addClass( + 'highcharts-' + + v.type + + '-series highcharts-color-' + + a.colorIndex + + (J ? ' ' + J : '') + + (g ? ' highcharts-series-' + a.index : ''), + ) + .attr({ zIndex: 1 }) + .add(this.scrollGroup)), + (a.legendItem = G = b + .text('', r ? h + f : -f, this.baseline || 0, P) + .css(n(a.visible ? m : l)) + .attr({ align: r ? 'left' : 'right', zIndex: 2 }) + .add(a.legendGroup)), + this.baseline || + ((h = m.fontSize), + (this.fontMetrics = b.fontMetrics(h, G)), + (this.baseline = this.fontMetrics.f + 3 + F), + G.attr('y', this.baseline)), + (this.symbolHeight = d.symbolHeight || this.fontMetrics.f), + v.drawLegendSymbol(this, a), + this.setItemEvents && this.setItemEvents(a, G, P), + L && this.createCheckboxForItem(a)); + this.colorizeItem(a, a.visible); + m.width || + G.css({ width: (d.itemWidth || d.width || c.spacingBox.width) - u }); + this.setText(a); + b = G.getBBox(); + m = a.checkboxOffset = d.itemWidth || a.legendItemWidth || b.width + u; + this.itemHeight = b = Math.round( + a.legendItemHeight || b.height || this.symbolHeight, + ); + e && + this.itemX - t + m > (q || c.spacingBox.width - 2 * t - d.x) && + ((this.itemX = t), + (this.itemY += F + this.lastLineHeight + A), + (this.lastLineHeight = 0)); + this.maxItemWidth = Math.max(this.maxItemWidth, m); + this.lastItemY = F + this.itemY + A; + this.lastLineHeight = Math.max(b, this.lastLineHeight); + a._legendItemPos = [this.itemX, this.itemY]; + e + ? (this.itemX += m) + : ((this.itemY += F + b + A), (this.lastLineHeight = b)); + this.offsetWidth = + q || + Math.max( + (e ? this.itemX - t - (a.checkbox ? 0 : p) : m) + t, + this.offsetWidth, + ); + }, + getAllItems: function() { + var a = []; + f(this.chart.series, function(c) { + var b = c && c.options; + c && + w(b.showInLegend, p(b.linkedTo) ? !1 : void 0, !0) && + (a = a.concat( + c.legendItems || ('point' === b.legendType ? c.data : c), + )); + }); + return a; + }, + getAlignment: function() { + var a = this.options; + return a.floating + ? '' + : a.align.charAt(0) + a.verticalAlign.charAt(0) + a.layout.charAt(0); + }, + adjustMargins: function(a, c) { + var b = this.chart, + d = this.options, + e = this.getAlignment(); + e && + f( + [/(lth|ct|rth)/, /(rtv|rm|rbv)/, /(rbh|cb|lbh)/, /(lbv|lm|ltv)/], + function(k, h) { + k.test(e) && + !p(a[h]) && + (b[r[h]] = Math.max( + b[r[h]], + b.legend[(h + 1) % 2 ? 'legendHeight' : 'legendWidth'] + + [1, -1, -1, 1][h] * d[h % 2 ? 'x' : 'y'] + + w(d.margin, 12) + + c[h] + + (0 === h ? b.titleOffset + b.options.title.margin : 0), + )); + }, + ); + }, + render: function() { + var a = this, + c = a.chart, + b = c.renderer, + k = a.group, + h, + m, + l, + x, + p = a.box, + t = a.options, + C = a.padding; + a.itemX = C; + a.itemY = a.initialItemY; + a.offsetWidth = 0; + a.lastItemY = 0; + k || + ((a.group = k = b + .g('legend') + .attr({ zIndex: 7 }) + .add()), + (a.contentGroup = b + .g() + .attr({ zIndex: 1 }) + .add(k)), + (a.scrollGroup = b.g().add(a.contentGroup))); + a.renderTitle(); + h = a.getAllItems(); + e(h, function(a, b) { + return ( + ((a.options && a.options.legendIndex) || 0) - + ((b.options && b.options.legendIndex) || 0) + ); + }); + t.reversed && h.reverse(); + a.allItems = h; + a.display = m = !!h.length; + a.lastLineHeight = 0; + f(h, function(b) { + a.renderItem(b); + }); + l = (t.width || a.offsetWidth) + C; + x = a.lastItemY + a.lastLineHeight + a.titleHeight; + x = a.handleOverflow(x); + x += C; + p || + ((a.box = p = b + .rect() + .addClass('highcharts-legend-box') + .attr({ r: t.borderRadius }) + .add(k)), + (p.isNew = !0)); + p.attr({ + stroke: t.borderColor, + 'stroke-width': t.borderWidth || 0, + fill: t.backgroundColor || 'none', + }).shadow(t.shadow); + 0 < l && + 0 < x && + (p[p.isNew ? 'attr' : 'animate']( + p.crisp.call( + {}, + { x: 0, y: 0, width: l, height: x }, + p.strokeWidth(), + ), + ), + (p.isNew = !1)); + p[m ? 'show' : 'hide'](); + a.legendWidth = l; + a.legendHeight = x; + f(h, function(b) { + a.positionItem(b); + }); + m && + ((b = c.spacingBox), + /(lth|ct|rth)/.test(a.getAlignment()) && + (b = n(b, { y: b.y + c.titleOffset + c.options.title.margin })), + k.align(n(t, { width: l, height: x }), !0, b)); + c.isResizing || this.positionCheckboxes(); + }, + handleOverflow: function(a) { + var c = this, + b = this.chart, + d = b.renderer, + e = this.options, + h = e.y, + m = this.padding, + b = b.spacingBox.height + ('top' === e.verticalAlign ? -h : h) - m, + h = e.maxHeight, + l, + n = this.clipRect, + t = e.navigation, + p = w(t.animation, !0), + r = t.arrowSize || 12, + q = this.nav, + A = this.pages, + F, + G = this.allItems, + g = function(a) { + 'number' === typeof a + ? n.attr({ height: a }) + : n && ((c.clipRect = n.destroy()), c.contentGroup.clip()); + c.contentGroup.div && + (c.contentGroup.div.style.clip = a + ? 'rect(' + m + 'px,9999px,' + (m + a) + 'px,0)' + : 'auto'); + }; + 'horizontal' !== e.layout || + 'middle' === e.verticalAlign || + e.floating || + (b /= 2); + h && (b = Math.min(b, h)); + A.length = 0; + a > b && !1 !== t.enabled + ? ((this.clipHeight = l = Math.max(b - 20 - this.titleHeight - m, 0)), + (this.currentPage = w(this.currentPage, 1)), + (this.fullHeight = a), + f(G, function(a, b) { + var c = a._legendItemPos[1], + d = Math.round(a.legendItem.getBBox().height), + g = A.length; + if (!g || (c - A[g - 1] > l && (F || c) !== A[g - 1])) + A.push(F || c), g++; + a.pageIx = g - 1; + F && (G[b - 1].pageIx = g - 1); + b === G.length - 1 && + c + d - A[g - 1] > l && + (A.push(c), (a.pageIx = g)); + c !== F && (F = c); + }), + n || + ((n = c.clipRect = d.clipRect(0, m, 9999, 0)), + c.contentGroup.clip(n)), + g(l), + q || + ((this.nav = q = d + .g() + .attr({ zIndex: 1 }) + .add(this.group)), + (this.up = d + .symbol('triangle', 0, 0, r, r) + .on('click', function() { + c.scroll(-1, p); + }) + .add(q)), + (this.pager = d + .text('', 15, 10) + .addClass('highcharts-legend-navigation') + .css(t.style) + .add(q)), + (this.down = d + .symbol('triangle-down', 0, 0, r, r) + .on('click', function() { + c.scroll(1, p); + }) + .add(q))), + c.scroll(0), + (a = b)) + : q && + (g(), + (this.nav = q.destroy()), + this.scrollGroup.attr({ translateY: 1 }), + (this.clipHeight = 0)); + return a; + }, + scroll: function(a, c) { + var b = this.pages, + d = b.length; + a = this.currentPage + a; + var e = this.clipHeight, + h = this.options.navigation, + f = this.pager, + m = this.padding; + a > d && (a = d); + 0 < a && + (void 0 !== c && u(c, this.chart), + this.nav.attr({ + translateX: m, + translateY: e + this.padding + 7 + this.titleHeight, + visibility: 'visible', + }), + this.up.attr({ + class: + 1 === a + ? 'highcharts-legend-nav-inactive' + : 'highcharts-legend-nav-active', + }), + f.attr({ text: a + '/' + d }), + this.down.attr({ + x: 18 + this.pager.getBBox().width, + class: + a === d + ? 'highcharts-legend-nav-inactive' + : 'highcharts-legend-nav-active', + }), + this.up + .attr({ fill: 1 === a ? h.inactiveColor : h.activeColor }) + .css({ cursor: 1 === a ? 'default' : 'pointer' }), + this.down + .attr({ fill: a === d ? h.inactiveColor : h.activeColor }) + .css({ cursor: a === d ? 'default' : 'pointer' }), + (this.scrollOffset = -b[a - 1] + this.initialItemY), + this.scrollGroup.animate({ translateY: this.scrollOffset }), + (this.currentPage = a), + this.positionCheckboxes()); + }, + }; + a.LegendSymbolMixin = { + drawRectangle: function(a, c) { + var b = a.symbolHeight, + d = a.options.squareSymbol; + c.legendSymbol = this.chart.renderer + .rect( + d ? (a.symbolWidth - b) / 2 : 0, + a.baseline - b + 1, + d ? b : a.symbolWidth, + b, + w(a.options.symbolRadius, b / 2), + ) + .addClass('highcharts-point') + .attr({ zIndex: 3 }) + .add(c.legendGroup); + }, + drawLineMarker: function(a) { + var c = this.options, + b = c.marker, + d = a.symbolWidth, + e = a.symbolHeight, + h = e / 2, + f = this.chart.renderer, + m = this.legendGroup; + a = a.baseline - Math.round(0.3 * a.fontMetrics.b); + var l; + l = { 'stroke-width': c.lineWidth || 0 }; + c.dashStyle && (l.dashstyle = c.dashStyle); + this.legendLine = f + .path(['M', 0, a, 'L', d, a]) + .addClass('highcharts-graph') + .attr(l) + .add(m); + b && + !1 !== b.enabled && + ((c = Math.min(w(b.radius, h), h)), + 0 === this.symbol.indexOf('url') && + ((b = n(b, { width: e, height: e })), (c = 0)), + (this.legendSymbol = b = f + .symbol(this.symbol, d / 2 - c, a - c, 2 * c, 2 * c, b) + .addClass('highcharts-point') + .add(m)), + (b.isMarker = !0)); + }, + }; + (/Trident\/7\.0/.test(h.navigator.userAgent) || l) && + m(a.Legend.prototype, 'positionItem', function(a, c) { + var b = this, + d = function() { + c._legendItemPos && a.call(b, c); + }; + d(); + setTimeout(d); + }); + })(M); + (function(a) { + var E = a.addEvent, + D = a.animate, + H = a.animObject, + p = a.attr, + f = a.doc, + l = a.Axis, + r = a.createElement, + n = a.defaultOptions, + w = a.discardElement, + u = a.charts, + e = a.css, + h = a.defined, + m = a.each, + d = a.extend, + c = a.find, + b = a.fireEvent, + k = a.grep, + z = a.isNumber, + B = a.isObject, + I = a.isString, + x = a.Legend, + K = a.marginNames, + t = a.merge, + C = a.objectEach, + N = a.Pointer, + q = a.pick, + A = a.pInt, + F = a.removeEvent, + G = a.seriesTypes, + g = a.splat, + v = a.svg, + Q = a.syncTimeout, + L = a.win, + P = (a.Chart = function() { + this.getArgs.apply(this, arguments); + }); + a.chart = function(a, b, c) { + return new P(a, b, c); + }; + d(P.prototype, { + callbacks: [], + getArgs: function() { + var a = [].slice.call(arguments); + if (I(a[0]) || a[0].nodeName) this.renderTo = a.shift(); + this.init(a[0], a[1]); + }, + init: function(b, c) { + var d, + g, + e = b.series, + k = b.plotOptions || {}; + b.series = null; + d = t(n, b); + for (g in d.plotOptions) + d.plotOptions[g].tooltip = (k[g] && t(k[g].tooltip)) || void 0; + d.tooltip.userOptions = + (b.chart && b.chart.forExport && b.tooltip.userOptions) || b.tooltip; + d.series = b.series = e; + this.userOptions = b; + b = d.chart; + g = b.events; + this.margin = []; + this.spacing = []; + this.bounds = { h: {}, v: {} }; + this.labelCollectors = []; + this.callback = c; + this.isResizing = 0; + this.options = d; + this.axes = []; + this.series = []; + this.hasCartesianSeries = b.showAxes; + var q = this; + q.index = u.length; + u.push(q); + a.chartCount++; + g && + C(g, function(a, b) { + E(q, b, a); + }); + q.xAxis = []; + q.yAxis = []; + q.pointCount = q.colorCounter = q.symbolCounter = 0; + q.firstRender(); + }, + initSeries: function(b) { + var c = this.options.chart; + (c = G[b.type || c.type || c.defaultSeriesType]) || a.error(17, !0); + c = new c(); + c.init(this, b); + return c; + }, + orderSeries: function(a) { + var b = this.series; + for (a = a || 0; a < b.length; a++) + b[a] && + ((b[a].index = a), + (b[a].name = b[a].name || 'Series ' + (b[a].index + 1))); + }, + isInsidePlot: function(a, b, c) { + var d = c ? b : a; + a = c ? a : b; + return 0 <= d && d <= this.plotWidth && 0 <= a && a <= this.plotHeight; + }, + redraw: function(c) { + var g = this.axes, + e = this.series, + k = this.pointer, + q = this.legend, + h = this.isDirtyLegend, + f, + l, + v = this.hasCartesianSeries, + A = this.isDirtyBox, + F, + t = this.renderer, + x = t.isHidden(), + n = []; + this.setResponsive && this.setResponsive(!1); + a.setAnimation(c, this); + x && this.temporaryDisplay(); + this.layOutTitles(); + for (c = e.length; c--; ) + if (((F = e[c]), F.options.stacking && ((f = !0), F.isDirty))) { + l = !0; + break; + } + if (l) + for (c = e.length; c--; ) + (F = e[c]), F.options.stacking && (F.isDirty = !0); + m(e, function(a) { + a.isDirty && + 'point' === a.options.legendType && + (a.updateTotals && a.updateTotals(), (h = !0)); + a.isDirtyData && b(a, 'updatedData'); + }); + h && q.options.enabled && (q.render(), (this.isDirtyLegend = !1)); + f && this.getStacks(); + v && + m(g, function(a) { + a.updateNames(); + a.setScale(); + }); + this.getMargins(); + v && + (m(g, function(a) { + a.isDirty && (A = !0); + }), + m(g, function(a) { + var c = a.min + ',' + a.max; + a.extKey !== c && + ((a.extKey = c), + n.push(function() { + b(a, 'afterSetExtremes', d(a.eventArgs, a.getExtremes())); + delete a.eventArgs; + })); + (A || f) && a.redraw(); + })); + A && this.drawChartBox(); + b(this, 'predraw'); + m(e, function(a) { + (A || a.isDirty) && a.visible && a.redraw(); + a.isDirtyData = !1; + }); + k && k.reset(!0); + t.draw(); + b(this, 'redraw'); + b(this, 'render'); + x && this.temporaryDisplay(!0); + m(n, function(a) { + a.call(); + }); + }, + get: function(a) { + function b(b) { + return b.id === a || (b.options && b.options.id === a); + } + var d, + g = this.series, + e; + d = c(this.axes, b) || c(this.series, b); + for (e = 0; !d && e < g.length; e++) d = c(g[e].points || [], b); + return d; + }, + getAxes: function() { + var a = this, + b = this.options, + c = (b.xAxis = g(b.xAxis || {})), + b = (b.yAxis = g(b.yAxis || {})); + m(c, function(a, b) { + a.index = b; + a.isX = !0; + }); + m(b, function(a, b) { + a.index = b; + }); + c = c.concat(b); + m(c, function(b) { + new l(a, b); + }); + }, + getSelectedPoints: function() { + var a = []; + m(this.series, function(b) { + a = a.concat( + k(b.data || [], function(a) { + return a.selected; + }), + ); + }); + return a; + }, + getSelectedSeries: function() { + return k(this.series, function(a) { + return a.selected; + }); + }, + setTitle: function(a, b, c) { + var d = this, + g = d.options, + e; + e = g.title = t( + { + style: { color: '#333333', fontSize: g.isStock ? '16px' : '18px' }, + }, + g.title, + a, + ); + g = g.subtitle = t({ style: { color: '#666666' } }, g.subtitle, b); + m([['title', a, e], ['subtitle', b, g]], function(a, b) { + var c = a[0], + g = d[c], + e = a[1]; + a = a[2]; + g && e && (d[c] = g = g.destroy()); + a && + !g && + ((d[c] = d.renderer + .text(a.text, 0, 0, a.useHTML) + .attr({ + align: a.align, + class: 'highcharts-' + c, + zIndex: a.zIndex || 4, + }) + .add()), + (d[c].update = function(a) { + d.setTitle(!b && a, b && a); + }), + d[c].css(a.style)); + }); + d.layOutTitles(c); + }, + layOutTitles: function(a) { + var b = 0, + c, + g = this.renderer, + e = this.spacingBox; + m( + ['title', 'subtitle'], + function(a) { + var c = this[a], + k = this.options[a]; + a = 'title' === a ? -3 : k.verticalAlign ? 0 : b + 2; + var q; + c && + ((q = k.style.fontSize), + (q = g.fontMetrics(q, c).b), + c + .css({ width: (k.width || e.width + k.widthAdjust) + 'px' }) + .align(d({ y: a + q }, k), !1, 'spacingBox'), + k.floating || + k.verticalAlign || + (b = Math.ceil(b + c.getBBox(k.useHTML).height))); + }, + this, + ); + c = this.titleOffset !== b; + this.titleOffset = b; + !this.isDirtyBox && + c && + ((this.isDirtyBox = c), + this.hasRendered && q(a, !0) && this.isDirtyBox && this.redraw()); + }, + getChartSize: function() { + var b = this.options.chart, + c = b.width, + b = b.height, + d = this.renderTo; + h(c) || (this.containerWidth = a.getStyle(d, 'width')); + h(b) || (this.containerHeight = a.getStyle(d, 'height')); + this.chartWidth = Math.max(0, c || this.containerWidth || 600); + this.chartHeight = Math.max( + 0, + a.relativeLength(b, this.chartWidth) || + (1 < this.containerHeight ? this.containerHeight : 400), + ); + }, + temporaryDisplay: function(b) { + var c = this.renderTo; + if (b) + for (; c && c.style; ) + c.hcOrigStyle && (a.css(c, c.hcOrigStyle), delete c.hcOrigStyle), + c.hcOrigDetached && + (f.body.removeChild(c), (c.hcOrigDetached = !1)), + (c = c.parentNode); + else + for (; c && c.style; ) { + f.body.contains(c) || + c.parentNode || + ((c.hcOrigDetached = !0), f.body.appendChild(c)); + if ('none' === a.getStyle(c, 'display', !1) || c.hcOricDetached) + (c.hcOrigStyle = { + display: c.style.display, + height: c.style.height, + overflow: c.style.overflow, + }), + (b = { display: 'block', overflow: 'hidden' }), + c !== this.renderTo && (b.height = 0), + a.css(c, b), + c.offsetWidth || + c.style.setProperty('display', 'block', 'important'); + c = c.parentNode; + if (c === f.body) break; + } + }, + setClassName: function(a) { + this.container.className = 'highcharts-container ' + (a || ''); + }, + getContainer: function() { + var b, + c = this.options, + g = c.chart, + e, + k; + b = this.renderTo; + var q = a.uniqueKey(), + h; + b || (this.renderTo = b = g.renderTo); + I(b) && (this.renderTo = b = f.getElementById(b)); + b || a.error(13, !0); + e = A(p(b, 'data-highcharts-chart')); + z(e) && u[e] && u[e].hasRendered && u[e].destroy(); + p(b, 'data-highcharts-chart', this.index); + b.innerHTML = ''; + g.skipClone || b.offsetWidth || this.temporaryDisplay(); + this.getChartSize(); + e = this.chartWidth; + k = this.chartHeight; + h = d( + { + position: 'relative', + overflow: 'hidden', + width: e + 'px', + height: k + 'px', + textAlign: 'left', + lineHeight: 'normal', + zIndex: 0, + '-webkit-tap-highlight-color': 'rgba(0,0,0,0)', + }, + g.style, + ); + this.container = b = r('div', { id: q }, h, b); + this._cursor = b.style.cursor; + this.renderer = new (a[g.renderer] || a.Renderer)( + b, + e, + k, + null, + g.forExport, + c.exporting && c.exporting.allowHTML, + ); + this.setClassName(g.className); + this.renderer.setStyle(g.style); + this.renderer.chartIndex = this.index; + }, + getMargins: function(a) { + var b = this.spacing, + c = this.margin, + d = this.titleOffset; + this.resetMargins(); + d && + !h(c[0]) && + (this.plotTop = Math.max( + this.plotTop, + d + this.options.title.margin + b[0], + )); + this.legend && this.legend.display && this.legend.adjustMargins(c, b); + this.extraMargin && + (this[this.extraMargin.type] = + (this[this.extraMargin.type] || 0) + this.extraMargin.value); + this.adjustPlotArea && this.adjustPlotArea(); + a || this.getAxisMargins(); + }, + getAxisMargins: function() { + var a = this, + b = (a.axisOffset = [0, 0, 0, 0]), + c = a.margin; + a.hasCartesianSeries && + m(a.axes, function(a) { + a.visible && a.getOffset(); + }); + m(K, function(d, g) { + h(c[g]) || (a[d] += b[g]); + }); + a.setChartSize(); + }, + reflow: function(b) { + var c = this, + d = c.options.chart, + g = c.renderTo, + e = h(d.width) && h(d.height), + k = d.width || a.getStyle(g, 'width'), + d = d.height || a.getStyle(g, 'height'), + g = b ? b.target : L; + if (!e && !c.isPrinting && k && d && (g === L || g === f)) { + if (k !== c.containerWidth || d !== c.containerHeight) + clearTimeout(c.reflowTimeout), + (c.reflowTimeout = Q( + function() { + c.container && c.setSize(void 0, void 0, !1); + }, + b ? 100 : 0, + )); + c.containerWidth = k; + c.containerHeight = d; + } + }, + initReflow: function() { + var a = this, + b; + b = E(L, 'resize', function(b) { + a.reflow(b); + }); + E(a, 'destroy', b); + }, + setSize: function(c, d, g) { + var k = this, + q = k.renderer; + k.isResizing += 1; + a.setAnimation(g, k); + k.oldChartHeight = k.chartHeight; + k.oldChartWidth = k.chartWidth; + void 0 !== c && (k.options.chart.width = c); + void 0 !== d && (k.options.chart.height = d); + k.getChartSize(); + c = q.globalAnimation; + (c ? D : e)( + k.container, + { width: k.chartWidth + 'px', height: k.chartHeight + 'px' }, + c, + ); + k.setChartSize(!0); + q.setSize(k.chartWidth, k.chartHeight, g); + m(k.axes, function(a) { + a.isDirty = !0; + a.setScale(); + }); + k.isDirtyLegend = !0; + k.isDirtyBox = !0; + k.layOutTitles(); + k.getMargins(); + k.redraw(g); + k.oldChartHeight = null; + b(k, 'resize'); + Q(function() { + k && + b(k, 'endResize', null, function() { + --k.isResizing; + }); + }, H(c).duration); + }, + setChartSize: function(a) { + var b = this.inverted, + c = this.renderer, + d = this.chartWidth, + g = this.chartHeight, + e = this.options.chart, + k = this.spacing, + q = this.clipOffset, + h, + f, + l, + v; + this.plotLeft = h = Math.round(this.plotLeft); + this.plotTop = f = Math.round(this.plotTop); + this.plotWidth = l = Math.max(0, Math.round(d - h - this.marginRight)); + this.plotHeight = v = Math.max( + 0, + Math.round(g - f - this.marginBottom), + ); + this.plotSizeX = b ? v : l; + this.plotSizeY = b ? l : v; + this.plotBorderWidth = e.plotBorderWidth || 0; + this.spacingBox = c.spacingBox = { + x: k[3], + y: k[0], + width: d - k[3] - k[1], + height: g - k[0] - k[2], + }; + this.plotBox = c.plotBox = { x: h, y: f, width: l, height: v }; + d = 2 * Math.floor(this.plotBorderWidth / 2); + b = Math.ceil(Math.max(d, q[3]) / 2); + c = Math.ceil(Math.max(d, q[0]) / 2); + this.clipBox = { + x: b, + y: c, + width: Math.floor(this.plotSizeX - Math.max(d, q[1]) / 2 - b), + height: Math.max( + 0, + Math.floor(this.plotSizeY - Math.max(d, q[2]) / 2 - c), + ), + }; + a || + m(this.axes, function(a) { + a.setAxisSize(); + a.setAxisTranslation(); + }); + }, + resetMargins: function() { + var a = this, + b = a.options.chart; + m(['margin', 'spacing'], function(c) { + var d = b[c], + g = B(d) ? d : [d, d, d, d]; + m(['Top', 'Right', 'Bottom', 'Left'], function(d, e) { + a[c][e] = q(b[c + d], g[e]); + }); + }); + m(K, function(b, c) { + a[b] = q(a.margin[c], a.spacing[c]); + }); + a.axisOffset = [0, 0, 0, 0]; + a.clipOffset = [0, 0, 0, 0]; + }, + drawChartBox: function() { + var a = this.options.chart, + b = this.renderer, + c = this.chartWidth, + d = this.chartHeight, + g = this.chartBackground, + e = this.plotBackground, + k = this.plotBorder, + q, + h = this.plotBGImage, + f = a.backgroundColor, + m = a.plotBackgroundColor, + l = a.plotBackgroundImage, + v, + A = this.plotLeft, + F = this.plotTop, + t = this.plotWidth, + x = this.plotHeight, + n = this.plotBox, + p = this.clipRect, + z = this.clipBox, + G = 'animate'; + g || + ((this.chartBackground = g = b + .rect() + .addClass('highcharts-background') + .add()), + (G = 'attr')); + q = a.borderWidth || 0; + v = q + (a.shadow ? 8 : 0); + f = { fill: f || 'none' }; + if (q || g['stroke-width']) + (f.stroke = a.borderColor), (f['stroke-width'] = q); + g.attr(f).shadow(a.shadow); + g[G]({ + x: v / 2, + y: v / 2, + width: c - v - (q % 2), + height: d - v - (q % 2), + r: a.borderRadius, + }); + G = 'animate'; + e || + ((G = 'attr'), + (this.plotBackground = e = b + .rect() + .addClass('highcharts-plot-background') + .add())); + e[G](n); + e.attr({ fill: m || 'none' }).shadow(a.plotShadow); + l && + (h + ? h.animate(n) + : (this.plotBGImage = b.image(l, A, F, t, x).add())); + p + ? p.animate({ width: z.width, height: z.height }) + : (this.clipRect = b.clipRect(z)); + G = 'animate'; + k || + ((G = 'attr'), + (this.plotBorder = k = b + .rect() + .addClass('highcharts-plot-border') + .attr({ zIndex: 1 }) + .add())); + k.attr({ + stroke: a.plotBorderColor, + 'stroke-width': a.plotBorderWidth || 0, + fill: 'none', + }); + k[G](k.crisp({ x: A, y: F, width: t, height: x }, -k.strokeWidth())); + this.isDirtyBox = !1; + }, + propFromSeries: function() { + var a = this, + b = a.options.chart, + c, + d = a.options.series, + g, + e; + m(['inverted', 'angular', 'polar'], function(k) { + c = G[b.type || b.defaultSeriesType]; + e = b[k] || (c && c.prototype[k]); + for (g = d && d.length; !e && g--; ) + (c = G[d[g].type]) && c.prototype[k] && (e = !0); + a[k] = e; + }); + }, + linkSeries: function() { + var a = this, + b = a.series; + m(b, function(a) { + a.linkedSeries.length = 0; + }); + m(b, function(b) { + var c = b.options.linkedTo; + I(c) && + (c = ':previous' === c ? a.series[b.index - 1] : a.get(c)) && + c.linkedParent !== b && + (c.linkedSeries.push(b), + (b.linkedParent = c), + (b.visible = q(b.options.visible, c.options.visible, b.visible))); + }); + }, + renderSeries: function() { + m(this.series, function(a) { + a.translate(); + a.render(); + }); + }, + renderLabels: function() { + var a = this, + b = a.options.labels; + b.items && + m(b.items, function(c) { + var g = d(b.style, c.style), + e = A(g.left) + a.plotLeft, + k = A(g.top) + a.plotTop + 12; + delete g.left; + delete g.top; + a.renderer + .text(c.html, e, k) + .attr({ zIndex: 2 }) + .css(g) + .add(); + }); + }, + render: function() { + var a = this.axes, + b = this.renderer, + c = this.options, + d, + g, + e; + this.setTitle(); + this.legend = new x(this, c.legend); + this.getStacks && this.getStacks(); + this.getMargins(!0); + this.setChartSize(); + c = this.plotWidth; + d = this.plotHeight = Math.max(this.plotHeight - 21, 0); + m(a, function(a) { + a.setScale(); + }); + this.getAxisMargins(); + g = 1.1 < c / this.plotWidth; + e = 1.05 < d / this.plotHeight; + if (g || e) + m(a, function(a) { + ((a.horiz && g) || (!a.horiz && e)) && a.setTickInterval(!0); + }), + this.getMargins(); + this.drawChartBox(); + this.hasCartesianSeries && + m(a, function(a) { + a.visible && a.render(); + }); + this.seriesGroup || + (this.seriesGroup = b + .g('series-group') + .attr({ zIndex: 3 }) + .add()); + this.renderSeries(); + this.renderLabels(); + this.addCredits(); + this.setResponsive && this.setResponsive(); + this.hasRendered = !0; + }, + addCredits: function(a) { + var b = this; + a = t(!0, this.options.credits, a); + a.enabled && + !this.credits && + ((this.credits = this.renderer + .text(a.text + (this.mapCredits || ''), 0, 0) + .addClass('highcharts-credits') + .on('click', function() { + a.href && (L.location.href = a.href); + }) + .attr({ align: a.position.align, zIndex: 8 }) + .css(a.style) + .add() + .align(a.position)), + (this.credits.update = function(a) { + b.credits = b.credits.destroy(); + b.addCredits(a); + })); + }, + destroy: function() { + var c = this, + d = c.axes, + g = c.series, + e = c.container, + k, + q = e && e.parentNode; + b(c, 'destroy'); + c.renderer.forExport ? a.erase(u, c) : (u[c.index] = void 0); + a.chartCount--; + c.renderTo.removeAttribute('data-highcharts-chart'); + F(c); + for (k = d.length; k--; ) d[k] = d[k].destroy(); + this.scroller && this.scroller.destroy && this.scroller.destroy(); + for (k = g.length; k--; ) g[k] = g[k].destroy(); + m( + 'title subtitle chartBackground plotBackground plotBGImage plotBorder seriesGroup clipRect credits pointer rangeSelector legend resetZoomButton tooltip renderer'.split( + ' ', + ), + function(a) { + var b = c[a]; + b && b.destroy && (c[a] = b.destroy()); + }, + ); + e && ((e.innerHTML = ''), F(e), q && w(e)); + C(c, function(a, b) { + delete c[b]; + }); + }, + isReadyToRender: function() { + var a = this; + return v || L != L.top || 'complete' === f.readyState + ? !0 + : (f.attachEvent('onreadystatechange', function() { + f.detachEvent('onreadystatechange', a.firstRender); + 'complete' === f.readyState && a.firstRender(); + }), + !1); + }, + firstRender: function() { + var a = this, + c = a.options; + if (a.isReadyToRender()) { + a.getContainer(); + b(a, 'init'); + a.resetMargins(); + a.setChartSize(); + a.propFromSeries(); + a.getAxes(); + m(c.series || [], function(b) { + a.initSeries(b); + }); + a.linkSeries(); + b(a, 'beforeRender'); + N && (a.pointer = new N(a, c)); + a.render(); + if (!a.renderer.imgCount && a.onload) a.onload(); + a.temporaryDisplay(!0); + } + }, + onload: function() { + m( + [this.callback].concat(this.callbacks), + function(a) { + a && void 0 !== this.index && a.apply(this, [this]); + }, + this, + ); + b(this, 'load'); + b(this, 'render'); + h(this.index) && !1 !== this.options.chart.reflow && this.initReflow(); + this.onload = null; + }, + }); + })(M); + (function(a) { + var E, + D = a.each, + H = a.extend, + p = a.erase, + f = a.fireEvent, + l = a.format, + r = a.isArray, + n = a.isNumber, + w = a.pick, + u = a.removeEvent; + a.Point = E = function() {}; + a.Point.prototype = { + init: function(a, h, f) { + this.series = a; + this.color = a.color; + this.applyOptions(h, f); + a.options.colorByPoint + ? ((h = a.options.colors || a.chart.options.colors), + (this.color = this.color || h[a.colorCounter]), + (h = h.length), + (f = a.colorCounter), + a.colorCounter++, + a.colorCounter === h && (a.colorCounter = 0)) + : (f = a.colorIndex); + this.colorIndex = w(this.colorIndex, f); + a.chart.pointCount++; + return this; + }, + applyOptions: function(a, h) { + var e = this.series, + d = e.options.pointValKey || e.pointValKey; + a = E.prototype.optionsToObject.call(this, a); + H(this, a); + this.options = this.options ? H(this.options, a) : a; + a.group && delete this.group; + d && (this.y = this[d]); + this.isNull = w( + this.isValid && !this.isValid(), + null === this.x || !n(this.y, !0), + ); + this.selected && (this.state = 'select'); + 'name' in this && + void 0 === h && + e.xAxis && + e.xAxis.hasNames && + (this.x = e.xAxis.nameToX(this)); + void 0 === this.x && + e && + (this.x = void 0 === h ? e.autoIncrement(this) : h); + return this; + }, + optionsToObject: function(a) { + var e = {}, + f = this.series, + d = f.options.keys, + c = d || f.pointArrayMap || ['y'], + b = c.length, + k = 0, + l = 0; + if (n(a) || null === a) e[c[0]] = a; + else if (r(a)) + for ( + !d && + a.length > b && + ((f = typeof a[0]), + 'string' === f ? (e.name = a[0]) : 'number' === f && (e.x = a[0]), + k++); + l < b; + + ) + (d && void 0 === a[k]) || (e[c[l]] = a[k]), k++, l++; + else + 'object' === typeof a && + ((e = a), + a.dataLabels && (f._hasPointLabels = !0), + a.marker && (f._hasPointMarkers = !0)); + return e; + }, + getClassName: function() { + return ( + 'highcharts-point' + + (this.selected ? ' highcharts-point-select' : '') + + (this.negative ? ' highcharts-negative' : '') + + (this.isNull ? ' highcharts-null-point' : '') + + (void 0 !== this.colorIndex + ? ' highcharts-color-' + this.colorIndex + : '') + + (this.options.className ? ' ' + this.options.className : '') + + (this.zone && this.zone.className + ? ' ' + this.zone.className.replace('highcharts-negative', '') + : '') + ); + }, + getZone: function() { + var a = this.series, + h = a.zones, + a = a.zoneAxis || 'y', + f = 0, + d; + for (d = h[f]; this[a] >= d.value; ) d = h[++f]; + d && d.color && !this.options.color && (this.color = d.color); + return d; + }, + destroy: function() { + var a = this.series.chart, + h = a.hoverPoints, + f; + a.pointCount--; + h && (this.setState(), p(h, this), h.length || (a.hoverPoints = null)); + if (this === a.hoverPoint) this.onMouseOut(); + if (this.graphic || this.dataLabel) u(this), this.destroyElements(); + this.legendItem && a.legend.destroyItem(this); + for (f in this) this[f] = null; + }, + destroyElements: function() { + for ( + var a = [ + 'graphic', + 'dataLabel', + 'dataLabelUpper', + 'connector', + 'shadowGroup', + ], + h, + f = 6; + f--; + + ) + (h = a[f]), this[h] && (this[h] = this[h].destroy()); + }, + getLabelConfig: function() { + return { + x: this.category, + y: this.y, + color: this.color, + colorIndex: this.colorIndex, + key: this.name || this.category, + series: this.series, + point: this, + percentage: this.percentage, + total: this.total || this.stackTotal, + }; + }, + tooltipFormatter: function(a) { + var e = this.series, + f = e.tooltipOptions, + d = w(f.valueDecimals, ''), + c = f.valuePrefix || '', + b = f.valueSuffix || ''; + D(e.pointArrayMap || ['y'], function(e) { + e = '{point.' + e; + if (c || b) a = a.replace(e + '}', c + e + '}' + b); + a = a.replace(e + '}', e + ':,.' + d + 'f}'); + }); + return l(a, { point: this, series: this.series }); + }, + firePointEvent: function(a, h, m) { + var d = this, + c = this.series.options; + (c.point.events[a] || + (d.options && d.options.events && d.options.events[a])) && + this.importEvents(); + 'click' === a && + c.allowPointSelect && + (m = function(a) { + d.select && d.select(null, a.ctrlKey || a.metaKey || a.shiftKey); + }); + f(this, a, h, m); + }, + visible: !0, + }; + })(M); + (function(a) { + var E = a.addEvent, + D = a.animObject, + H = a.arrayMax, + p = a.arrayMin, + f = a.correctFloat, + l = a.Date, + r = a.defaultOptions, + n = a.defaultPlotOptions, + w = a.defined, + u = a.each, + e = a.erase, + h = a.extend, + m = a.fireEvent, + d = a.grep, + c = a.isArray, + b = a.isNumber, + k = a.isString, + z = a.merge, + B = a.objectEach, + I = a.pick, + x = a.removeEvent, + K = a.splat, + t = a.SVGElement, + C = a.syncTimeout, + N = a.win; + a.Series = a.seriesType( + 'line', + null, + { + lineWidth: 2, + allowPointSelect: !1, + showCheckbox: !1, + animation: { duration: 1e3 }, + events: {}, + marker: { + lineWidth: 0, + lineColor: '#ffffff', + radius: 4, + states: { + hover: { + animation: { duration: 50 }, + enabled: !0, + radiusPlus: 2, + lineWidthPlus: 1, + }, + select: { + fillColor: '#cccccc', + lineColor: '#000000', + lineWidth: 2, + }, + }, + }, + point: { events: {} }, + dataLabels: { + align: 'center', + formatter: function() { + return null === this.y ? '' : a.numberFormat(this.y, -1); + }, + style: { + fontSize: '11px', + fontWeight: 'bold', + color: 'contrast', + textOutline: '1px contrast', + }, + verticalAlign: 'bottom', + x: 0, + y: 0, + padding: 5, + }, + cropThreshold: 300, + pointRange: 0, + softThreshold: !0, + states: { + hover: { + animation: { duration: 50 }, + lineWidthPlus: 1, + marker: {}, + halo: { size: 10, opacity: 0.25 }, + }, + select: { marker: {} }, + }, + stickyTracking: !0, + turboThreshold: 1e3, + findNearestPointBy: 'x', + }, + { + isCartesian: !0, + pointClass: a.Point, + sorted: !0, + requireSorting: !0, + directTouch: !1, + axisTypes: ['xAxis', 'yAxis'], + colorCounter: 0, + parallelArrays: ['x', 'y'], + coll: 'series', + init: function(a, b) { + var c = this, + d, + g = a.series, + e; + c.chart = a; + c.options = b = c.setOptions(b); + c.linkedSeries = []; + c.bindAxes(); + h(c, { + name: b.name, + state: '', + visible: !1 !== b.visible, + selected: !0 === b.selected, + }); + d = b.events; + B(d, function(a, b) { + E(c, b, a); + }); + if ( + (d && d.click) || + (b.point && b.point.events && b.point.events.click) || + b.allowPointSelect + ) + a.runTrackerClick = !0; + c.getColor(); + c.getSymbol(); + u(c.parallelArrays, function(a) { + c[a + 'Data'] = []; + }); + c.setData(b.data, !1); + c.isCartesian && (a.hasCartesianSeries = !0); + g.length && (e = g[g.length - 1]); + c._i = I(e && e._i, -1) + 1; + a.orderSeries(this.insert(g)); + }, + insert: function(a) { + var c = this.options.index, + d; + if (b(c)) { + for (d = a.length; d--; ) + if (c >= I(a[d].options.index, a[d]._i)) { + a.splice(d + 1, 0, this); + break; + } + -1 === d && a.unshift(this); + d += 1; + } else a.push(this); + return I(d, a.length - 1); + }, + bindAxes: function() { + var b = this, + c = b.options, + d = b.chart, + e; + u(b.axisTypes || [], function(g) { + u(d[g], function(a) { + e = a.options; + if ( + c[g] === e.index || + (void 0 !== c[g] && c[g] === e.id) || + (void 0 === c[g] && 0 === e.index) + ) + b.insert(a.series), (b[g] = a), (a.isDirty = !0); + }); + b[g] || b.optionalAxis === g || a.error(18, !0); + }); + }, + updateParallelArrays: function(a, c) { + var d = a.series, + e = arguments, + g = b(c) + ? function(b) { + var g = 'y' === b && d.toYData ? d.toYData(a) : a[b]; + d[b + 'Data'][c] = g; + } + : function(a) { + Array.prototype[c].apply( + d[a + 'Data'], + Array.prototype.slice.call(e, 2), + ); + }; + u(d.parallelArrays, g); + }, + autoIncrement: function() { + var b = this.options, + c = this.xIncrement, + d, + e = b.pointIntervalUnit, + g = 0, + c = I(c, b.pointStart, 0); + this.pointInterval = d = I(this.pointInterval, b.pointInterval, 1); + e && + ((b = new l(c)), + 'day' === e + ? (b = +b[l.hcSetDate](b[l.hcGetDate]() + d)) + : 'month' === e + ? (b = +b[l.hcSetMonth](b[l.hcGetMonth]() + d)) + : 'year' === e && + (b = +b[l.hcSetFullYear](b[l.hcGetFullYear]() + d)), + l.hcHasTimeZone && (g = a.getTZOffset(b) - a.getTZOffset(c)), + (d = b - c + g)); + this.xIncrement = c + d; + return c; + }, + setOptions: function(a) { + var b = this.chart, + c = b.options, + d = c.plotOptions, + g = (b.userOptions || {}).plotOptions || {}, + e = d[this.type]; + this.userOptions = a; + b = z(e, d.series, a); + this.tooltipOptions = z( + r.tooltip, + r.plotOptions.series && r.plotOptions.series.tooltip, + r.plotOptions[this.type].tooltip, + c.tooltip.userOptions, + d.series && d.series.tooltip, + d[this.type].tooltip, + a.tooltip, + ); + this.stickyTracking = I( + a.stickyTracking, + g[this.type] && g[this.type].stickyTracking, + g.series && g.series.stickyTracking, + this.tooltipOptions.shared && !this.noSharedTooltip + ? !0 + : b.stickyTracking, + ); + null === e.marker && delete b.marker; + this.zoneAxis = b.zoneAxis; + a = this.zones = (b.zones || []).slice(); + (!b.negativeColor && !b.negativeFillColor) || + b.zones || + a.push({ + value: b[this.zoneAxis + 'Threshold'] || b.threshold || 0, + className: 'highcharts-negative', + color: b.negativeColor, + fillColor: b.negativeFillColor, + }); + a.length && + w(a[a.length - 1].value) && + a.push({ color: this.color, fillColor: this.fillColor }); + return b; + }, + getCyclic: function(a, b, c) { + var d, + g = this.chart, + e = this.userOptions, + k = a + 'Index', + h = a + 'Counter', + q = c ? c.length : I(g.options.chart[a + 'Count'], g[a + 'Count']); + b || + ((d = I(e[k], e['_' + k])), + w(d) || + (g.series.length || (g[h] = 0), + (e['_' + k] = d = g[h] % q), + (g[h] += 1)), + c && (b = c[d])); + void 0 !== d && (this[k] = d); + this[a] = b; + }, + getColor: function() { + this.options.colorByPoint + ? (this.options.color = null) + : this.getCyclic( + 'color', + this.options.color || n[this.type].color, + this.chart.options.colors, + ); + }, + getSymbol: function() { + this.getCyclic( + 'symbol', + this.options.marker.symbol, + this.chart.options.symbols, + ); + }, + drawLegendSymbol: a.LegendSymbolMixin.drawLineMarker, + setData: function(d, e, h, f) { + var g = this, + q = g.points, + m = (q && q.length) || 0, + l, + A = g.options, + t = g.chart, + x = null, + n = g.xAxis, + p = A.turboThreshold, + z = this.xData, + F = this.yData, + C = (l = g.pointArrayMap) && l.length; + d = d || []; + l = d.length; + e = I(e, !0); + if ( + !1 !== f && + l && + m === l && + !g.cropped && + !g.hasGroupedData && + g.visible + ) + u(d, function(a, b) { + q[b].update && a !== A.data[b] && q[b].update(a, !1, null, !1); + }); + else { + g.xIncrement = null; + g.colorCounter = 0; + u(this.parallelArrays, function(a) { + g[a + 'Data'].length = 0; + }); + if (p && l > p) { + for (h = 0; null === x && h < l; ) (x = d[h]), h++; + if (b(x)) + for (h = 0; h < l; h++) + (z[h] = this.autoIncrement()), (F[h] = d[h]); + else if (c(x)) + if (C) + for (h = 0; h < l; h++) + (x = d[h]), (z[h] = x[0]), (F[h] = x.slice(1, C + 1)); + else + for (h = 0; h < l; h++) + (x = d[h]), (z[h] = x[0]), (F[h] = x[1]); + else a.error(12); + } else + for (h = 0; h < l; h++) + void 0 !== d[h] && + ((x = { series: g }), + g.pointClass.prototype.applyOptions.apply(x, [d[h]]), + g.updateParallelArrays(x, h)); + F && k(F[0]) && a.error(14, !0); + g.data = []; + g.options.data = g.userOptions.data = d; + for (h = m; h--; ) q[h] && q[h].destroy && q[h].destroy(); + n && (n.minRange = n.userMinRange); + g.isDirty = t.isDirtyBox = !0; + g.isDirtyData = !!q; + h = !1; + } + 'point' === A.legendType && + (this.processData(), this.generatePoints()); + e && t.redraw(h); + }, + processData: function(b) { + var c = this.xData, + d = this.yData, + e = c.length, + g; + g = 0; + var k, + h, + q = this.xAxis, + f, + m = this.options; + f = m.cropThreshold; + var l = this.getExtremesFromAll || m.getExtremesFromAll, + t = this.isCartesian, + m = q && q.val2lin, + x = q && q.isLog, + n = this.requireSorting, + p, + z; + if (t && !this.isDirty && !q.isDirty && !this.yAxis.isDirty && !b) + return !1; + q && ((b = q.getExtremes()), (p = b.min), (z = b.max)); + if (t && this.sorted && !l && (!f || e > f || this.forceCrop)) + if (c[e - 1] < p || c[0] > z) (c = []), (d = []); + else if (c[0] < p || c[e - 1] > z) + (g = this.cropData(this.xData, this.yData, p, z)), + (c = g.xData), + (d = g.yData), + (g = g.start), + (k = !0); + for (f = c.length || 1; --f; ) + (e = x ? m(c[f]) - m(c[f - 1]) : c[f] - c[f - 1]), + 0 < e && (void 0 === h || e < h) + ? (h = e) + : 0 > e && n && (a.error(15), (n = !1)); + this.cropped = k; + this.cropStart = g; + this.processedXData = c; + this.processedYData = d; + this.closestPointRange = h; + }, + cropData: function(a, b, c, d) { + var g = a.length, + e = 0, + k = g, + h = I(this.cropShoulder, 1), + f; + for (f = 0; f < g; f++) + if (a[f] >= c) { + e = Math.max(0, f - h); + break; + } + for (c = f; c < g; c++) + if (a[c] > d) { + k = c + h; + break; + } + return { + xData: a.slice(e, k), + yData: b.slice(e, k), + start: e, + end: k, + }; + }, + generatePoints: function() { + var a = this.options, + b = a.data, + c = this.data, + d, + g = this.processedXData, + e = this.processedYData, + k = this.pointClass, + h = g.length, + f = this.cropStart || 0, + m, + l = this.hasGroupedData, + a = a.keys, + t, + x = [], + n; + c || l || ((c = []), (c.length = b.length), (c = this.data = c)); + a && l && (this.options.keys = !1); + for (n = 0; n < h; n++) + (m = f + n), + l + ? ((t = new k().init(this, [g[n]].concat(K(e[n])))), + (t.dataGroup = this.groupMap[n])) + : (t = c[m]) || + void 0 === b[m] || + (c[m] = t = new k().init(this, b[m], g[n])), + t && ((t.index = m), (x[n] = t)); + this.options.keys = a; + if (c && (h !== (d = c.length) || l)) + for (n = 0; n < d; n++) + n !== f || l || (n += h), + c[n] && (c[n].destroyElements(), (c[n].plotX = void 0)); + this.data = c; + this.points = x; + }, + getExtremes: function(a) { + var d = this.yAxis, + e = this.processedXData, + k, + g = [], + h = 0; + k = this.xAxis.getExtremes(); + var f = k.min, + q = k.max, + m, + l, + t, + n; + a = a || this.stackedYData || this.processedYData || []; + k = a.length; + for (n = 0; n < k; n++) + if ( + ((l = e[n]), + (t = a[n]), + (m = + (b(t, !0) || c(t)) && + (!d.positiveValuesOnly || t.length || 0 < t)), + (l = + this.getExtremesFromAll || + this.options.getExtremesFromAll || + this.cropped || + ((e[n + 1] || l) >= f && (e[n - 1] || l) <= q)), + m && l) + ) + if ((m = t.length)) + for (; m--; ) 'number' === typeof t[m] && (g[h++] = t[m]); + else g[h++] = t; + this.dataMin = p(g); + this.dataMax = H(g); + }, + translate: function() { + this.processedXData || this.processData(); + this.generatePoints(); + var a = this.options, + c = a.stacking, + d = this.xAxis, + e = d.categories, + g = this.yAxis, + k = this.points, + h = k.length, + m = !!this.modifyValue, + l = a.pointPlacement, + t = 'between' === l || b(l), + n = a.threshold, + x = a.startFromThreshold ? n : 0, + p, + z, + C, + r, + u = Number.MAX_VALUE; + 'between' === l && (l = 0.5); + b(l) && (l *= I(a.pointRange || d.pointRange)); + for (a = 0; a < h; a++) { + var B = k[a], + N = B.x, + K = B.y; + z = B.low; + var D = + c && + g.stacks[ + (this.negStacks && K < (x ? 0 : n) ? '-' : '') + this.stackKey + ], + E; + g.positiveValuesOnly && null !== K && 0 >= K && (B.isNull = !0); + B.plotX = p = f( + Math.min( + Math.max( + -1e5, + d.translate(N, 0, 0, 0, 1, l, 'flags' === this.type), + ), + 1e5, + ), + ); + c && + this.visible && + !B.isNull && + D && + D[N] && + ((r = this.getStackIndicator(r, N, this.index)), + (E = D[N]), + (K = E.points[r.key]), + (z = K[0]), + (K = K[1]), + z === x && r.key === D[N].base && (z = I(n, g.min)), + g.positiveValuesOnly && 0 >= z && (z = null), + (B.total = B.stackTotal = E.total), + (B.percentage = E.total && (B.y / E.total) * 100), + (B.stackY = K), + E.setOffset(this.pointXOffset || 0, this.barW || 0)); + B.yBottom = w(z) ? g.translate(z, 0, 1, 0, 1) : null; + m && (K = this.modifyValue(K, B)); + B.plotY = z = + 'number' === typeof K && Infinity !== K + ? Math.min(Math.max(-1e5, g.translate(K, 0, 1, 0, 1)), 1e5) + : void 0; + B.isInside = + void 0 !== z && 0 <= z && z <= g.len && 0 <= p && p <= d.len; + B.clientX = t ? f(d.translate(N, 0, 0, 0, 1, l)) : p; + B.negative = B.y < (n || 0); + B.category = e && void 0 !== e[B.x] ? e[B.x] : B.x; + B.isNull || + (void 0 !== C && (u = Math.min(u, Math.abs(p - C))), (C = p)); + B.zone = this.zones.length && B.getZone(); + } + this.closestPointRangePx = u; + }, + getValidPoints: function(a, b) { + var c = this.chart; + return d(a || this.points || [], function(a) { + return b && !c.isInsidePlot(a.plotX, a.plotY, c.inverted) + ? !1 + : !a.isNull; + }); + }, + setClip: function(a) { + var b = this.chart, + c = this.options, + d = b.renderer, + g = b.inverted, + e = this.clipBox, + k = e || b.clipBox, + h = + this.sharedClipKey || + [ + '_sharedClip', + a && a.duration, + a && a.easing, + k.height, + c.xAxis, + c.yAxis, + ].join(), + f = b[h], + q = b[h + 'm']; + f || + (a && + ((k.width = 0), + g && (k.x = b.plotSizeX), + (b[h + 'm'] = q = d.clipRect( + g ? b.plotSizeX + 99 : -99, + g ? -b.plotLeft : -b.plotTop, + 99, + g ? b.chartWidth : b.chartHeight, + ))), + (b[h] = f = d.clipRect(k)), + (f.count = { length: 0 })); + a && + !f.count[this.index] && + ((f.count[this.index] = !0), (f.count.length += 1)); + !1 !== c.clip && + (this.group.clip(a || e ? f : b.clipRect), + this.markerGroup.clip(q), + (this.sharedClipKey = h)); + a || + (f.count[this.index] && + (delete f.count[this.index], --f.count.length), + 0 === f.count.length && + h && + b[h] && + (e || (b[h] = b[h].destroy()), + b[h + 'm'] && (b[h + 'm'] = b[h + 'm'].destroy()))); + }, + animate: function(a) { + var b = this.chart, + c = D(this.options.animation), + d; + a + ? this.setClip(c) + : ((d = this.sharedClipKey), + (a = b[d]) && a.animate({ width: b.plotSizeX, x: 0 }, c), + b[d + 'm'] && + b[d + 'm'].animate({ width: b.plotSizeX + 99, x: 0 }, c), + (this.animate = null)); + }, + afterAnimate: function() { + this.setClip(); + m(this, 'afterAnimate'); + this.finishedAnimating = !0; + }, + drawPoints: function() { + var a = this.points, + b = this.chart, + c, + d, + g, + e, + k = this.options.marker, + h, + f, + l, + m = this[this.specialGroup] || this.markerGroup, + t, + n = I( + k.enabled, + this.xAxis.isRadial ? !0 : null, + this.closestPointRangePx >= 2 * k.radius, + ); + if (!1 !== k.enabled || this._hasPointMarkers) + for (c = 0; c < a.length; c++) + (d = a[c]), + (e = d.graphic), + (h = d.marker || {}), + (f = !!d.marker), + (g = (n && void 0 === h.enabled) || h.enabled), + (l = d.isInside), + g && !d.isNull + ? ((g = I(h.symbol, this.symbol)), + (d.hasImage = 0 === g.indexOf('url')), + (t = this.markerAttribs(d, d.selected && 'select')), + e + ? e[l ? 'show' : 'hide'](!0).animate(t) + : l && + (0 < t.width || d.hasImage) && + (d.graphic = e = b.renderer + .symbol(g, t.x, t.y, t.width, t.height, f ? h : k) + .add(m)), + e && e.attr(this.pointAttribs(d, d.selected && 'select')), + e && e.addClass(d.getClassName(), !0)) + : e && (d.graphic = e.destroy()); + }, + markerAttribs: function(a, b) { + var c = this.options.marker, + d = a.marker || {}, + g = I(d.radius, c.radius); + b && + ((c = c.states[b]), + (b = d.states && d.states[b]), + (g = I( + b && b.radius, + c && c.radius, + g + ((c && c.radiusPlus) || 0), + ))); + a.hasImage && (g = 0); + a = { x: Math.floor(a.plotX) - g, y: a.plotY - g }; + g && (a.width = a.height = 2 * g); + return a; + }, + pointAttribs: function(a, b) { + var c = this.options.marker, + d = a && a.options, + g = (d && d.marker) || {}, + e = this.color, + k = d && d.color, + h = a && a.color, + d = I(g.lineWidth, c.lineWidth); + a = a && a.zone && a.zone.color; + e = k || a || h || e; + a = g.fillColor || c.fillColor || e; + e = g.lineColor || c.lineColor || e; + b && + ((c = c.states[b]), + (b = (g.states && g.states[b]) || {}), + (d = I( + b.lineWidth, + c.lineWidth, + d + I(b.lineWidthPlus, c.lineWidthPlus, 0), + )), + (a = b.fillColor || c.fillColor || a), + (e = b.lineColor || c.lineColor || e)); + return { stroke: e, 'stroke-width': d, fill: a }; + }, + destroy: function() { + var a = this, + b = a.chart, + c = /AppleWebKit\/533/.test(N.navigator.userAgent), + d, + g, + k = a.data || [], + h, + f; + m(a, 'destroy'); + x(a); + u(a.axisTypes || [], function(b) { + (f = a[b]) && + f.series && + (e(f.series, a), (f.isDirty = f.forceRedraw = !0)); + }); + a.legendItem && a.chart.legend.destroyItem(a); + for (g = k.length; g--; ) (h = k[g]) && h.destroy && h.destroy(); + a.points = null; + clearTimeout(a.animationTimeout); + B(a, function(a, b) { + a instanceof t && + !a.survive && + ((d = c && 'group' === b ? 'hide' : 'destroy'), a[d]()); + }); + b.hoverSeries === a && (b.hoverSeries = null); + e(b.series, a); + b.orderSeries(); + B(a, function(b, c) { + delete a[c]; + }); + }, + getGraphPath: function(a, b, c) { + var d = this, + g = d.options, + e = g.step, + k, + h = [], + f = [], + l; + a = a || d.points; + (k = a.reversed) && a.reverse(); + (e = { right: 1, center: 2 }[e] || (e && 3)) && k && (e = 4 - e); + !g.connectNulls || b || c || (a = this.getValidPoints(a)); + u(a, function(k, m) { + var q = k.plotX, + t = k.plotY, + n = a[m - 1]; + (k.leftCliff || (n && n.rightCliff)) && !c && (l = !0); + k.isNull && !w(b) && 0 < m + ? (l = !g.connectNulls) + : k.isNull && !b + ? (l = !0) + : (0 === m || l + ? (m = ['M', k.plotX, k.plotY]) + : d.getPointSpline + ? (m = d.getPointSpline(a, k, m)) + : e + ? ((m = + 1 === e + ? ['L', n.plotX, t] + : 2 === e + ? [ + 'L', + (n.plotX + q) / 2, + n.plotY, + 'L', + (n.plotX + q) / 2, + t, + ] + : ['L', q, n.plotY]), + m.push('L', q, t)) + : (m = ['L', q, t]), + f.push(k.x), + e && f.push(k.x), + h.push.apply(h, m), + (l = !1)); + }); + h.xMap = f; + return (d.graphPath = h); + }, + drawGraph: function() { + var a = this, + b = this.options, + c = (this.gappedPath || this.getGraphPath).call(this), + d = [ + [ + 'graph', + 'highcharts-graph', + b.lineColor || this.color, + b.dashStyle, + ], + ]; + u(this.zones, function(c, e) { + d.push([ + 'zone-graph-' + e, + 'highcharts-graph highcharts-zone-graph-' + + e + + ' ' + + (c.className || ''), + c.color || a.color, + c.dashStyle || b.dashStyle, + ]); + }); + u(d, function(d, e) { + var g = d[0], + k = a[g]; + k + ? ((k.endX = a.preventGraphAnimation ? null : c.xMap), + k.animate({ d: c })) + : c.length && + ((a[g] = a.chart.renderer + .path(c) + .addClass(d[1]) + .attr({ zIndex: 1 }) + .add(a.group)), + (k = { + stroke: d[2], + 'stroke-width': b.lineWidth, + fill: (a.fillGraph && a.color) || 'none', + }), + d[3] + ? (k.dashstyle = d[3]) + : 'square' !== b.linecap && + (k['stroke-linecap'] = k['stroke-linejoin'] = 'round'), + (k = a[g].attr(k).shadow(2 > e && b.shadow))); + k && ((k.startX = c.xMap), (k.isArea = c.isArea)); + }); + }, + applyZones: function() { + var a = this, + b = this.chart, + c = b.renderer, + d = this.zones, + e, + k, + h = this.clips || [], + f, + m = this.graph, + l = this.area, + t = Math.max(b.chartWidth, b.chartHeight), + n = this[(this.zoneAxis || 'y') + 'Axis'], + x, + p, + z = b.inverted, + C, + r, + w, + B, + K = !1; + d.length && + (m || l) && + n && + void 0 !== n.min && + ((p = n.reversed), + (C = n.horiz), + m && m.hide(), + l && l.hide(), + (x = n.getExtremes()), + u(d, function(d, g) { + e = p ? (C ? b.plotWidth : 0) : C ? 0 : n.toPixels(x.min); + e = Math.min(Math.max(I(k, e), 0), t); + k = Math.min( + Math.max(Math.round(n.toPixels(I(d.value, x.max), !0)), 0), + t, + ); + K && (e = k = n.toPixels(x.max)); + r = Math.abs(e - k); + w = Math.min(e, k); + B = Math.max(e, k); + n.isXAxis + ? ((f = { x: z ? B : w, y: 0, width: r, height: t }), + C || (f.x = b.plotHeight - f.x)) + : ((f = { x: 0, y: z ? B : w, width: t, height: r }), + C && (f.y = b.plotWidth - f.y)); + z && + c.isVML && + (f = n.isXAxis + ? { x: 0, y: p ? w : B, height: f.width, width: b.chartWidth } + : { + x: f.y - b.plotLeft - b.spacingBox.x, + y: 0, + width: f.height, + height: b.chartHeight, + }); + h[g] + ? h[g].animate(f) + : ((h[g] = c.clipRect(f)), + m && a['zone-graph-' + g].clip(h[g]), + l && a['zone-area-' + g].clip(h[g])); + K = d.value > x.max; + }), + (this.clips = h)); + }, + invertGroups: function(a) { + function b() { + u(['group', 'markerGroup'], function(b) { + c[b] && + (d.renderer.isVML && + c[b].attr({ width: c.yAxis.len, height: c.xAxis.len }), + (c[b].width = c.yAxis.len), + (c[b].height = c.xAxis.len), + c[b].invert(a)); + }); + } + var c = this, + d = c.chart, + e; + c.xAxis && + ((e = E(d, 'resize', b)), + E(c, 'destroy', e), + b(a), + (c.invertGroups = b)); + }, + plotGroup: function(a, b, c, d, e) { + var g = this[a], + k = !g; + k && + (this[a] = g = this.chart.renderer + .g() + .attr({ zIndex: d || 0.1 }) + .add(e)); + g.addClass( + 'highcharts-' + + b + + ' highcharts-series-' + + this.index + + ' highcharts-' + + this.type + + '-series ' + + (w(this.colorIndex) + ? 'highcharts-color-' + this.colorIndex + ' ' + : '') + + (this.options.className || '') + + (g.hasClass('highcharts-tracker') ? ' highcharts-tracker' : ''), + !0, + ); + g.attr({ visibility: c })[k ? 'attr' : 'animate'](this.getPlotBox()); + return g; + }, + getPlotBox: function() { + var a = this.chart, + b = this.xAxis, + c = this.yAxis; + a.inverted && ((b = c), (c = this.xAxis)); + return { + translateX: b ? b.left : a.plotLeft, + translateY: c ? c.top : a.plotTop, + scaleX: 1, + scaleY: 1, + }; + }, + render: function() { + var a = this, + b = a.chart, + c, + d = a.options, + e = !!a.animate && b.renderer.isSVG && D(d.animation).duration, + k = a.visible ? 'inherit' : 'hidden', + h = d.zIndex, + f = a.hasRendered, + m = b.seriesGroup, + l = b.inverted; + c = a.plotGroup('group', 'series', k, h, m); + a.markerGroup = a.plotGroup('markerGroup', 'markers', k, h, m); + e && a.animate(!0); + c.inverted = a.isCartesian ? l : !1; + a.drawGraph && (a.drawGraph(), a.applyZones()); + a.drawDataLabels && a.drawDataLabels(); + a.visible && a.drawPoints(); + a.drawTracker && + !1 !== a.options.enableMouseTracking && + a.drawTracker(); + a.invertGroups(l); + !1 === d.clip || a.sharedClipKey || f || c.clip(b.clipRect); + e && a.animate(); + f || + (a.animationTimeout = C(function() { + a.afterAnimate(); + }, e)); + a.isDirty = !1; + a.hasRendered = !0; + }, + redraw: function() { + var a = this.chart, + b = this.isDirty || this.isDirtyData, + c = this.group, + d = this.xAxis, + e = this.yAxis; + c && + (a.inverted && c.attr({ width: a.plotWidth, height: a.plotHeight }), + c.animate({ + translateX: I(d && d.left, a.plotLeft), + translateY: I(e && e.top, a.plotTop), + })); + this.translate(); + this.render(); + b && delete this.kdTree; + }, + kdAxisArray: ['clientX', 'plotY'], + searchPoint: function(a, b) { + var c = this.xAxis, + d = this.yAxis, + e = this.chart.inverted; + return this.searchKDTree( + { + clientX: e ? c.len - a.chartY + c.pos : a.chartX - c.pos, + plotY: e ? d.len - a.chartX + d.pos : a.chartY - d.pos, + }, + b, + ); + }, + buildKDTree: function() { + function a(c, d, e) { + var g, k; + if ((k = c && c.length)) + return ( + (g = b.kdAxisArray[d % e]), + c.sort(function(a, b) { + return a[g] - b[g]; + }), + (k = Math.floor(k / 2)), + { + point: c[k], + left: a(c.slice(0, k), d + 1, e), + right: a(c.slice(k + 1), d + 1, e), + } + ); + } + this.buildingKdTree = !0; + var b = this, + c = -1 < b.options.findNearestPointBy.indexOf('y') ? 2 : 1; + delete b.kdTree; + C( + function() { + b.kdTree = a(b.getValidPoints(null, !b.directTouch), c, c); + b.buildingKdTree = !1; + }, + b.options.kdNow ? 0 : 1, + ); + }, + searchKDTree: function(a, b) { + function c(a, b, g, f) { + var m = b.point, + l = d.kdAxisArray[g % f], + q, + t, + n = m; + t = w(a[e]) && w(m[e]) ? Math.pow(a[e] - m[e], 2) : null; + q = w(a[k]) && w(m[k]) ? Math.pow(a[k] - m[k], 2) : null; + q = (t || 0) + (q || 0); + m.dist = w(q) ? Math.sqrt(q) : Number.MAX_VALUE; + m.distX = w(t) ? Math.sqrt(t) : Number.MAX_VALUE; + l = a[l] - m[l]; + q = 0 > l ? 'left' : 'right'; + t = 0 > l ? 'right' : 'left'; + b[q] && ((q = c(a, b[q], g + 1, f)), (n = q[h] < n[h] ? q : m)); + b[t] && + Math.sqrt(l * l) < n[h] && + ((a = c(a, b[t], g + 1, f)), (n = a[h] < n[h] ? a : n)); + return n; + } + var d = this, + e = this.kdAxisArray[0], + k = this.kdAxisArray[1], + h = b ? 'distX' : 'dist'; + b = -1 < d.options.findNearestPointBy.indexOf('y') ? 2 : 1; + this.kdTree || this.buildingKdTree || this.buildKDTree(); + if (this.kdTree) return c(a, this.kdTree, b, b); + }, + }, + ); + })(M); + (function(a) { + var E = a.Axis, + D = a.Chart, + H = a.correctFloat, + p = a.defined, + f = a.destroyObjectProperties, + l = a.each, + r = a.format, + n = a.objectEach, + w = a.pick, + u = a.Series; + a.StackItem = function(a, h, f, d, c) { + var b = a.chart.inverted; + this.axis = a; + this.isNegative = f; + this.options = h; + this.x = d; + this.total = null; + this.points = {}; + this.stack = c; + this.rightCliff = this.leftCliff = 0; + this.alignOptions = { + align: h.align || (b ? (f ? 'left' : 'right') : 'center'), + verticalAlign: h.verticalAlign || (b ? 'middle' : f ? 'bottom' : 'top'), + y: w(h.y, b ? 4 : f ? 14 : -6), + x: w(h.x, b ? (f ? -6 : 6) : 0), + }; + this.textAlign = h.textAlign || (b ? (f ? 'right' : 'left') : 'center'); + }; + a.StackItem.prototype = { + destroy: function() { + f(this, this.axis); + }, + render: function(a) { + var e = this.options, + f = e.format, + f = f ? r(f, this) : e.formatter.call(this); + this.label + ? this.label.attr({ text: f, visibility: 'hidden' }) + : (this.label = this.axis.chart.renderer + .text(f, null, null, e.useHTML) + .css(e.style) + .attr({ + align: this.textAlign, + rotation: e.rotation, + visibility: 'hidden', + }) + .add(a)); + }, + setOffset: function(a, h) { + var e = this.axis, + d = e.chart, + c = e.translate(e.usePercentage ? 100 : this.total, 0, 0, 0, 1), + e = e.translate(0), + e = Math.abs(c - e); + a = d.xAxis[0].translate(this.x) + a; + c = this.getStackBox(d, this, a, c, h, e); + if ((h = this.label)) + h.align(this.alignOptions, null, c), + (c = h.alignAttr), + h[ + !1 === this.options.crop || d.isInsidePlot(c.x, c.y) + ? 'show' + : 'hide' + ](!0); + }, + getStackBox: function(a, h, f, d, c, b) { + var e = h.axis.reversed, + l = a.inverted; + a = a.plotHeight; + h = (h.isNegative && !e) || (!h.isNegative && e); + return { + x: l ? (h ? d : d - b) : f, + y: l ? a - f - c : h ? a - d - b : a - d, + width: l ? b : c, + height: l ? c : b, + }; + }, + }; + D.prototype.getStacks = function() { + var a = this; + l(a.yAxis, function(a) { + a.stacks && a.hasVisibleSeries && (a.oldStacks = a.stacks); + }); + l(a.series, function(e) { + !e.options.stacking || + (!0 !== e.visible && !1 !== a.options.chart.ignoreHiddenSeries) || + (e.stackKey = e.type + w(e.options.stack, '')); + }); + }; + E.prototype.buildStacks = function() { + var a = this.series, + h = w(this.options.reversedStacks, !0), + f = a.length, + d; + if (!this.isXAxis) { + this.usePercentage = !1; + for (d = f; d--; ) a[h ? d : f - d - 1].setStackedPoints(); + for (d = 0; d < f; d++) a[d].modifyStacks(); + } + }; + E.prototype.renderStackTotals = function() { + var a = this.chart, + h = a.renderer, + f = this.stacks, + d = this.stackTotalGroup; + d || + (this.stackTotalGroup = d = h + .g('stack-labels') + .attr({ visibility: 'visible', zIndex: 6 }) + .add()); + d.translate(a.plotLeft, a.plotTop); + n(f, function(a) { + n(a, function(a) { + a.render(d); + }); + }); + }; + E.prototype.resetStacks = function() { + var a = this, + h = a.stacks; + a.isXAxis || + n(h, function(e) { + n(e, function(d, c) { + d.touched < a.stacksTouched + ? (d.destroy(), delete e[c]) + : ((d.total = null), (d.cumulative = null)); + }); + }); + }; + E.prototype.cleanStacks = function() { + var a; + this.isXAxis || + (this.oldStacks && (a = this.stacks = this.oldStacks), + n(a, function(a) { + n(a, function(a) { + a.cumulative = a.total; + }); + })); + }; + u.prototype.setStackedPoints = function() { + if ( + this.options.stacking && + (!0 === this.visible || + !1 === this.chart.options.chart.ignoreHiddenSeries) + ) { + var e = this.processedXData, + h = this.processedYData, + f = [], + d = h.length, + c = this.options, + b = c.threshold, + k = w(c.startFromThreshold && b, 0), + l = c.stack, + c = c.stacking, + n = this.stackKey, + r = '-' + n, + x = this.negStacks, + u = this.yAxis, + t = u.stacks, + C = u.oldStacks, + N, + q, + A, + F, + G, + g, + v; + u.stacksTouched += 1; + for (G = 0; G < d; G++) + (g = e[G]), + (v = h[G]), + (N = this.getStackIndicator(N, g, this.index)), + (F = N.key), + (A = (q = x && v < (k ? 0 : b)) ? r : n), + t[A] || (t[A] = {}), + t[A][g] || + (C[A] && C[A][g] + ? ((t[A][g] = C[A][g]), (t[A][g].total = null)) + : (t[A][g] = new a.StackItem( + u, + u.options.stackLabels, + q, + g, + l, + ))), + (A = t[A][g]), + null !== v + ? ((A.points[F] = A.points[this.index] = [w(A.cumulative, k)]), + p(A.cumulative) || (A.base = F), + (A.touched = u.stacksTouched), + 0 < N.index && + !1 === this.singleStacks && + (A.points[F][0] = A.points[this.index + ',' + g + ',0'][0])) + : (A.points[F] = A.points[this.index] = null), + 'percent' === c + ? ((q = q ? n : r), + x && t[q] && t[q][g] + ? ((q = t[q][g]), + (A.total = q.total = + Math.max(q.total, A.total) + Math.abs(v) || 0)) + : (A.total = H(A.total + (Math.abs(v) || 0)))) + : (A.total = H(A.total + (v || 0))), + (A.cumulative = w(A.cumulative, k) + (v || 0)), + null !== v && + (A.points[F].push(A.cumulative), (f[G] = A.cumulative)); + 'percent' === c && (u.usePercentage = !0); + this.stackedYData = f; + u.oldStacks = {}; + } + }; + u.prototype.modifyStacks = function() { + var a = this, + h = a.stackKey, + f = a.yAxis.stacks, + d = a.processedXData, + c, + b = a.options.stacking; + a[b + 'Stacker'] && + l([h, '-' + h], function(e) { + for (var k = d.length, h, l; k--; ) + if ( + ((h = d[k]), + (c = a.getStackIndicator(c, h, a.index, e)), + (l = (h = f[e] && f[e][h]) && h.points[c.key])) + ) + a[b + 'Stacker'](l, h, k); + }); + }; + u.prototype.percentStacker = function(a, h, f) { + h = h.total ? 100 / h.total : 0; + a[0] = H(a[0] * h); + a[1] = H(a[1] * h); + this.stackedYData[f] = a[1]; + }; + u.prototype.getStackIndicator = function(a, h, f, d) { + !p(a) || a.x !== h || (d && a.key !== d) + ? (a = { x: h, index: 0, key: d }) + : a.index++; + a.key = [f, h, a.index].join(); + return a; + }; + })(M); + (function(a) { + var E = a.addEvent, + D = a.animate, + H = a.Axis, + p = a.createElement, + f = a.css, + l = a.defined, + r = a.each, + n = a.erase, + w = a.extend, + u = a.fireEvent, + e = a.inArray, + h = a.isNumber, + m = a.isObject, + d = a.isArray, + c = a.merge, + b = a.objectEach, + k = a.pick, + z = a.Point, + B = a.Series, + I = a.seriesTypes, + x = a.setAnimation, + K = a.splat; + w(a.Chart.prototype, { + addSeries: function(a, b, c) { + var d, + e = this; + a && + ((b = k(b, !0)), + u(e, 'addSeries', { options: a }, function() { + d = e.initSeries(a); + e.isDirtyLegend = !0; + e.linkSeries(); + b && e.redraw(c); + })); + return d; + }, + addAxis: function(a, b, d, e) { + var h = b ? 'xAxis' : 'yAxis', + f = this.options; + a = c(a, { index: this[h].length, isX: b }); + b = new H(this, a); + f[h] = K(f[h] || {}); + f[h].push(a); + k(d, !0) && this.redraw(e); + return b; + }, + showLoading: function(a) { + var b = this, + c = b.options, + d = b.loadingDiv, + e = c.loading, + k = function() { + d && + f(d, { + left: b.plotLeft + 'px', + top: b.plotTop + 'px', + width: b.plotWidth + 'px', + height: b.plotHeight + 'px', + }); + }; + d || + ((b.loadingDiv = d = p( + 'div', + { className: 'highcharts-loading highcharts-loading-hidden' }, + null, + b.container, + )), + (b.loadingSpan = p( + 'span', + { className: 'highcharts-loading-inner' }, + null, + d, + )), + E(b, 'redraw', k)); + d.className = 'highcharts-loading'; + b.loadingSpan.innerHTML = a || c.lang.loading; + f(d, w(e.style, { zIndex: 10 })); + f(b.loadingSpan, e.labelStyle); + b.loadingShown || + (f(d, { opacity: 0, display: '' }), + D( + d, + { opacity: e.style.opacity || 0.5 }, + { duration: e.showDuration || 0 }, + )); + b.loadingShown = !0; + k(); + }, + hideLoading: function() { + var a = this.options, + b = this.loadingDiv; + b && + ((b.className = 'highcharts-loading highcharts-loading-hidden'), + D( + b, + { opacity: 0 }, + { + duration: a.loading.hideDuration || 100, + complete: function() { + f(b, { display: 'none' }); + }, + }, + )); + this.loadingShown = !1; + }, + propsRequireDirtyBox: 'backgroundColor borderColor borderWidth margin marginTop marginRight marginBottom marginLeft spacing spacingTop spacingRight spacingBottom spacingLeft borderRadius plotBackgroundColor plotBackgroundImage plotBorderColor plotBorderWidth plotShadow shadow'.split( + ' ', + ), + propsRequireUpdateSeries: 'chart.inverted chart.polar chart.ignoreHiddenSeries chart.type colors plotOptions tooltip'.split( + ' ', + ), + update: function(a, d, f) { + var m = this, + n = { + credits: 'addCredits', + title: 'setTitle', + subtitle: 'setSubtitle', + }, + t = a.chart, + x, + g, + p = []; + if (t) { + c(!0, m.options.chart, t); + 'className' in t && m.setClassName(t.className); + if ('inverted' in t || 'polar' in t) m.propFromSeries(), (x = !0); + 'alignTicks' in t && (x = !0); + b(t, function(a, b) { + -1 !== e('chart.' + b, m.propsRequireUpdateSeries) && (g = !0); + -1 !== e(b, m.propsRequireDirtyBox) && (m.isDirtyBox = !0); + }); + 'style' in t && m.renderer.setStyle(t.style); + } + a.colors && (this.options.colors = a.colors); + a.plotOptions && c(!0, this.options.plotOptions, a.plotOptions); + b(a, function(a, b) { + if (m[b] && 'function' === typeof m[b].update) m[b].update(a, !1); + else if ('function' === typeof m[n[b]]) m[n[b]](a); + 'chart' !== b && -1 !== e(b, m.propsRequireUpdateSeries) && (g = !0); + }); + r('xAxis yAxis zAxis series colorAxis pane'.split(' '), function(b) { + a[b] && + (r(K(a[b]), function(a, c) { + (c = (l(a.id) && m.get(a.id)) || m[b][c]) && + c.coll === b && + (c.update(a, !1), f && (c.touched = !0)); + if (!c && f) + if ('series' === b) m.addSeries(a, !1).touched = !0; + else if ('xAxis' === b || 'yAxis' === b) + m.addAxis(a, 'xAxis' === b, !1).touched = !0; + }), + f && + r(m[b], function(a) { + a.touched ? delete a.touched : p.push(a); + })); + }); + r(p, function(a) { + a.remove(!1); + }); + x && + r(m.axes, function(a) { + a.update({}, !1); + }); + g && + r(m.series, function(a) { + a.update({}, !1); + }); + a.loading && c(!0, m.options.loading, a.loading); + x = t && t.width; + t = t && t.height; + (h(x) && x !== m.chartWidth) || (h(t) && t !== m.chartHeight) + ? m.setSize(x, t) + : k(d, !0) && m.redraw(); + }, + setSubtitle: function(a) { + this.setTitle(void 0, a); + }, + }); + w(z.prototype, { + update: function(a, b, c, d) { + function e() { + h.applyOptions(a); + null === h.y && g && (h.graphic = g.destroy()); + m(a, !0) && + (g && + g.element && + a && + a.marker && + void 0 !== a.marker.symbol && + (h.graphic = g.destroy()), + a && + a.dataLabels && + h.dataLabel && + (h.dataLabel = h.dataLabel.destroy()), + h.connector && (h.connector = h.connector.destroy())); + l = h.index; + f.updateParallelArrays(h, l); + t.data[l] = m(t.data[l], !0) || m(a, !0) ? h.options : a; + f.isDirty = f.isDirtyData = !0; + !f.fixedBox && f.hasCartesianSeries && (n.isDirtyBox = !0); + 'point' === t.legendType && (n.isDirtyLegend = !0); + b && n.redraw(c); + } + var h = this, + f = h.series, + g = h.graphic, + l, + n = f.chart, + t = f.options; + b = k(b, !0); + !1 === d ? e() : h.firePointEvent('update', { options: a }, e); + }, + remove: function(a, b) { + this.series.removePoint(e(this, this.series.data), a, b); + }, + }); + w(B.prototype, { + addPoint: function(a, b, c, d) { + var e = this.options, + h = this.data, + f = this.chart, + g = this.xAxis, + g = g && g.hasNames && g.names, + l = e.data, + m, + n, + t = this.xData, + q, + x; + b = k(b, !0); + m = { series: this }; + this.pointClass.prototype.applyOptions.apply(m, [a]); + x = m.x; + q = t.length; + if (this.requireSorting && x < t[q - 1]) + for (n = !0; q && t[q - 1] > x; ) q--; + this.updateParallelArrays(m, 'splice', q, 0, 0); + this.updateParallelArrays(m, q); + g && m.name && (g[x] = m.name); + l.splice(q, 0, a); + n && (this.data.splice(q, 0, null), this.processData()); + 'point' === e.legendType && this.generatePoints(); + c && + (h[0] && h[0].remove + ? h[0].remove(!1) + : (h.shift(), this.updateParallelArrays(m, 'shift'), l.shift())); + this.isDirtyData = this.isDirty = !0; + b && f.redraw(d); + }, + removePoint: function(a, b, c) { + var d = this, + e = d.data, + h = e[a], + f = d.points, + g = d.chart, + l = function() { + f && f.length === e.length && f.splice(a, 1); + e.splice(a, 1); + d.options.data.splice(a, 1); + d.updateParallelArrays(h || { series: d }, 'splice', a, 1); + h && h.destroy(); + d.isDirty = !0; + d.isDirtyData = !0; + b && g.redraw(); + }; + x(c, g); + b = k(b, !0); + h ? h.firePointEvent('remove', null, l) : l(); + }, + remove: function(a, b, c) { + function d() { + e.destroy(); + h.isDirtyLegend = h.isDirtyBox = !0; + h.linkSeries(); + k(a, !0) && h.redraw(b); + } + var e = this, + h = e.chart; + !1 !== c ? u(e, 'remove', null, d) : d(); + }, + update: function(a, b) { + var d = this, + e = d.chart, + h = d.userOptions, + f = d.oldType || d.type, + l = a.type || h.type || e.options.chart.type, + g = I[f].prototype, + m, + n = ['group', 'markerGroup', 'dataLabelsGroup'], + t = ['navigatorSeries', 'baseSeries'], + x = d.finishedAnimating && { animation: !1 }; + if (Object.keys && 'data' === Object.keys(a).toString()) + return this.setData(a.data, b); + t = n.concat(t); + r(t, function(a) { + t[a] = d[a]; + delete d[a]; + }); + a = c( + h, + x, + { index: d.index, pointStart: d.xData[0] }, + { data: d.options.data }, + a, + ); + d.remove(!1, null, !1); + for (m in g) d[m] = void 0; + w(d, I[l || f].prototype); + r(t, function(a) { + d[a] = t[a]; + }); + d.init(e, a); + a.zIndex !== h.zIndex && + r(n, function(b) { + d[b] && d[b].attr({ zIndex: a.zIndex }); + }); + d.oldType = f; + e.linkSeries(); + k(b, !0) && e.redraw(!1); + }, + }); + w(H.prototype, { + update: function(a, b) { + var d = this.chart; + a = d.options[this.coll][this.options.index] = c(this.userOptions, a); + this.destroy(!0); + this.init(d, w(a, { events: void 0 })); + d.isDirtyBox = !0; + k(b, !0) && d.redraw(); + }, + remove: function(a) { + for ( + var b = this.chart, c = this.coll, e = this.series, h = e.length; + h--; + + ) + e[h] && e[h].remove(!1); + n(b.axes, this); + n(b[c], this); + d(b.options[c]) + ? b.options[c].splice(this.options.index, 1) + : delete b.options[c]; + r(b[c], function(a, b) { + a.options.index = b; + }); + this.destroy(); + b.isDirtyBox = !0; + k(a, !0) && b.redraw(); + }, + setTitle: function(a, b) { + this.update({ title: a }, b); + }, + setCategories: function(a, b) { + this.update({ categories: a }, b); + }, + }); + })(M); + (function(a) { + var E = a.color, + D = a.each, + H = a.map, + p = a.pick, + f = a.Series, + l = a.seriesType; + l( + 'area', + 'line', + { softThreshold: !1, threshold: 0 }, + { + singleStacks: !1, + getStackPoints: function(f) { + var l = [], + r = [], + u = this.xAxis, + e = this.yAxis, + h = e.stacks[this.stackKey], + m = {}, + d = this.index, + c = e.series, + b = c.length, + k, + z = p(e.options.reversedStacks, !0) ? 1 : -1, + B; + f = f || this.points; + if (this.options.stacking) { + for (B = 0; B < f.length; B++) + (f[B].leftNull = f[B].rightNull = null), (m[f[B].x] = f[B]); + a.objectEach(h, function(a, b) { + null !== a.total && r.push(b); + }); + r.sort(function(a, b) { + return a - b; + }); + k = H(c, function() { + return this.visible; + }); + D(r, function(a, c) { + var f = 0, + n, + x; + if (m[a] && !m[a].isNull) + l.push(m[a]), + D([-1, 1], function(e) { + var f = 1 === e ? 'rightNull' : 'leftNull', + l = 0, + t = h[r[c + e]]; + if (t) + for (B = d; 0 <= B && B < b; ) + (n = t.points[B]), + n || + (B === d + ? (m[a][f] = !0) + : k[B] && + (x = h[a].points[B]) && + (l -= x[1] - x[0])), + (B += z); + m[a][1 === e ? 'rightCliff' : 'leftCliff'] = l; + }); + else { + for (B = d; 0 <= B && B < b; ) { + if ((n = h[a].points[B])) { + f = n[1]; + break; + } + B += z; + } + f = e.translate(f, 0, 1, 0, 1); + l.push({ + isNull: !0, + plotX: u.translate(a, 0, 0, 0, 1), + x: a, + plotY: f, + yBottom: f, + }); + } + }); + } + return l; + }, + getGraphPath: function(a) { + var l = f.prototype.getGraphPath, + r = this.options, + u = r.stacking, + e = this.yAxis, + h, + m, + d = [], + c = [], + b = this.index, + k, + z = e.stacks[this.stackKey], + B = r.threshold, + I = e.getThreshold(r.threshold), + x, + r = r.connectNulls || 'percent' === u, + K = function(h, f, l) { + var m = a[h]; + h = u && z[m.x].points[b]; + var n = m[l + 'Null'] || 0; + l = m[l + 'Cliff'] || 0; + var x, + t, + m = !0; + l || n + ? ((x = (n ? h[0] : h[1]) + l), (t = h[0] + l), (m = !!n)) + : !u && a[f] && a[f].isNull && (x = t = B); + void 0 !== x && + (c.push({ + plotX: k, + plotY: null === x ? I : e.getThreshold(x), + isNull: m, + isCliff: !0, + }), + d.push({ + plotX: k, + plotY: null === t ? I : e.getThreshold(t), + doCurve: !1, + })); + }; + a = a || this.points; + u && (a = this.getStackPoints(a)); + for (h = 0; h < a.length; h++) + if ( + ((m = a[h].isNull), + (k = p(a[h].rectPlotX, a[h].plotX)), + (x = p(a[h].yBottom, I)), + !m || r) + ) + r || K(h, h - 1, 'left'), + (m && !u && r) || + (c.push(a[h]), d.push({ x: h, plotX: k, plotY: x })), + r || K(h, h + 1, 'right'); + h = l.call(this, c, !0, !0); + d.reversed = !0; + m = l.call(this, d, !0, !0); + m.length && (m[0] = 'L'); + m = h.concat(m); + l = l.call(this, c, !1, r); + m.xMap = h.xMap; + this.areaPath = m; + return l; + }, + drawGraph: function() { + this.areaPath = []; + f.prototype.drawGraph.apply(this); + var a = this, + l = this.areaPath, + w = this.options, + u = [['area', 'highcharts-area', this.color, w.fillColor]]; + D(this.zones, function(e, h) { + u.push([ + 'zone-area-' + h, + 'highcharts-area highcharts-zone-area-' + h + ' ' + e.className, + e.color || a.color, + e.fillColor || w.fillColor, + ]); + }); + D(u, function(e) { + var h = e[0], + f = a[h]; + f + ? ((f.endX = a.preventGraphAnimation ? null : l.xMap), + f.animate({ d: l })) + : ((f = a[h] = a.chart.renderer + .path(l) + .addClass(e[1]) + .attr({ + fill: p( + e[3], + E(e[2]) + .setOpacity(p(w.fillOpacity, 0.75)) + .get(), + ), + zIndex: 0, + }) + .add(a.group)), + (f.isArea = !0)); + f.startX = l.xMap; + f.shiftUnit = w.step ? 2 : 1; + }); + }, + drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, + }, + ); + })(M); + (function(a) { + var E = a.pick; + a = a.seriesType; + a( + 'spline', + 'line', + {}, + { + getPointSpline: function(a, H, p) { + var f = H.plotX, + l = H.plotY, + r = a[p - 1]; + p = a[p + 1]; + var n, w, u, e; + if ( + r && + !r.isNull && + !1 !== r.doCurve && + !H.isCliff && + p && + !p.isNull && + !1 !== p.doCurve && + !H.isCliff + ) { + a = r.plotY; + u = p.plotX; + p = p.plotY; + var h = 0; + n = (1.5 * f + r.plotX) / 2.5; + w = (1.5 * l + a) / 2.5; + u = (1.5 * f + u) / 2.5; + e = (1.5 * l + p) / 2.5; + u !== n && (h = ((e - w) * (u - f)) / (u - n) + l - e); + w += h; + e += h; + w > a && w > l + ? ((w = Math.max(a, l)), (e = 2 * l - w)) + : w < a && w < l && ((w = Math.min(a, l)), (e = 2 * l - w)); + e > p && e > l + ? ((e = Math.max(p, l)), (w = 2 * l - e)) + : e < p && e < l && ((e = Math.min(p, l)), (w = 2 * l - e)); + H.rightContX = u; + H.rightContY = e; + } + H = [ + 'C', + E(r.rightContX, r.plotX), + E(r.rightContY, r.plotY), + E(n, f), + E(w, l), + f, + l, + ]; + r.rightContX = r.rightContY = null; + return H; + }, + }, + ); + })(M); + (function(a) { + var E = a.seriesTypes.area.prototype, + D = a.seriesType; + D('areaspline', 'spline', a.defaultPlotOptions.area, { + getStackPoints: E.getStackPoints, + getGraphPath: E.getGraphPath, + drawGraph: E.drawGraph, + drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, + }); + })(M); + (function(a) { + var E = a.animObject, + D = a.color, + H = a.each, + p = a.extend, + f = a.isNumber, + l = a.merge, + r = a.pick, + n = a.Series, + w = a.seriesType, + u = a.svg; + w( + 'column', + 'line', + { + borderRadius: 0, + crisp: !0, + groupPadding: 0.2, + marker: null, + pointPadding: 0.1, + minPointLength: 0, + cropThreshold: 50, + pointRange: null, + states: { + hover: { halo: !1, brightness: 0.1 }, + select: { color: '#cccccc', borderColor: '#000000' }, + }, + dataLabels: { align: null, verticalAlign: null, y: null }, + softThreshold: !1, + startFromThreshold: !0, + stickyTracking: !1, + tooltip: { distance: 6 }, + threshold: 0, + borderColor: '#ffffff', + }, + { + cropShoulder: 0, + directTouch: !0, + trackerGroups: ['group', 'dataLabelsGroup'], + negStacks: !0, + init: function() { + n.prototype.init.apply(this, arguments); + var a = this, + h = a.chart; + h.hasRendered && + H(h.series, function(e) { + e.type === a.type && (e.isDirty = !0); + }); + }, + getColumnMetrics: function() { + var a = this, + h = a.options, + f = a.xAxis, + d = a.yAxis, + c = f.reversed, + b, + k = {}, + l = 0; + !1 === h.grouping + ? (l = 1) + : H(a.chart.series, function(c) { + var e = c.options, + h = c.yAxis, + f; + c.type !== a.type || + (!c.visible && a.chart.options.chart.ignoreHiddenSeries) || + d.len !== h.len || + d.pos !== h.pos || + (e.stacking + ? ((b = c.stackKey), + void 0 === k[b] && (k[b] = l++), + (f = k[b])) + : !1 !== e.grouping && (f = l++), + (c.columnIndex = f)); + }); + var n = Math.min( + Math.abs(f.transA) * + (f.ordinalSlope || + h.pointRange || + f.closestPointRange || + f.tickInterval || + 1), + f.len, + ), + p = n * h.groupPadding, + x = (n - 2 * p) / (l || 1), + h = Math.min( + h.maxPointWidth || f.len, + r(h.pointWidth, x * (1 - 2 * h.pointPadding)), + ); + a.columnMetrics = { + width: h, + offset: + (x - h) / 2 + + (p + ((a.columnIndex || 0) + (c ? 1 : 0)) * x - n / 2) * + (c ? -1 : 1), + }; + return a.columnMetrics; + }, + crispCol: function(a, h, f, d) { + var c = this.chart, + b = this.borderWidth, + e = -(b % 2 ? 0.5 : 0), + b = b % 2 ? 0.5 : 1; + c.inverted && c.renderer.isVML && (b += 1); + this.options.crisp && + ((f = Math.round(a + f) + e), (a = Math.round(a) + e), (f -= a)); + d = Math.round(h + d) + b; + e = 0.5 >= Math.abs(h) && 0.5 < d; + h = Math.round(h) + b; + d -= h; + e && d && (--h, (d += 1)); + return { x: a, y: h, width: f, height: d }; + }, + translate: function() { + var a = this, + h = a.chart, + f = a.options, + d = (a.dense = 2 > a.closestPointRange * a.xAxis.transA), + d = (a.borderWidth = r(f.borderWidth, d ? 0 : 1)), + c = a.yAxis, + b = f.threshold, + k = (a.translatedThreshold = c.getThreshold(b)), + l = r(f.minPointLength, 5), + p = a.getColumnMetrics(), + u = p.width, + x = (a.barW = Math.max(u, 1 + 2 * d)), + w = (a.pointXOffset = p.offset); + h.inverted && (k -= 0.5); + f.pointPadding && (x = Math.ceil(x)); + n.prototype.translate.apply(a); + H(a.points, function(d) { + var e = r(d.yBottom, k), + f = 999 + Math.abs(e), + f = Math.min(Math.max(-f, d.plotY), c.len + f), + m = d.plotX + w, + n = x, + t = Math.min(f, e), + p, + g = Math.max(f, e) - t; + l && + Math.abs(g) < l && + ((g = l), + (p = (!c.reversed && !d.negative) || (c.reversed && d.negative)), + d.y === b && a.dataMax <= b && c.min < b && (p = !p), + (t = Math.abs(t - k) > l ? e - l : k - (p ? l : 0))); + d.barX = m; + d.pointWidth = u; + d.tooltipPos = h.inverted + ? [c.len + c.pos - h.plotLeft - f, a.xAxis.len - m - n / 2, g] + : [m + n / 2, f + c.pos - h.plotTop, g]; + d.shapeType = 'rect'; + d.shapeArgs = a.crispCol.apply( + a, + d.isNull ? [m, k, n, 0] : [m, t, n, g], + ); + }); + }, + getSymbol: a.noop, + drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, + drawGraph: function() { + this.group[this.dense ? 'addClass' : 'removeClass']( + 'highcharts-dense-data', + ); + }, + pointAttribs: function(a, f) { + var e = this.options, + d, + c = this.pointAttrToOptions || {}; + d = c.stroke || 'borderColor'; + var b = c['stroke-width'] || 'borderWidth', + k = (a && a.color) || this.color, + h = (a && a[d]) || e[d] || this.color || k, + n = (a && a[b]) || e[b] || this[b] || 0, + c = e.dashStyle; + a && + this.zones.length && + ((k = a.getZone()), + (k = a.options.color || (k && k.color) || this.color)); + f && + ((a = l( + e.states[f], + (a.options.states && a.options.states[f]) || {}, + )), + (f = a.brightness), + (k = + a.color || + (void 0 !== f && + D(k) + .brighten(a.brightness) + .get()) || + k), + (h = a[d] || h), + (n = a[b] || n), + (c = a.dashStyle || c)); + d = { fill: k, stroke: h, 'stroke-width': n }; + c && (d.dashstyle = c); + return d; + }, + drawPoints: function() { + var a = this, + h = this.chart, + m = a.options, + d = h.renderer, + c = m.animationLimit || 250, + b; + H(a.points, function(e) { + var k = e.graphic; + if (f(e.plotY) && null !== e.y) { + b = e.shapeArgs; + if (k) k[h.pointCount < c ? 'animate' : 'attr'](l(b)); + else e.graphic = k = d[e.shapeType](b).add(e.group || a.group); + m.borderRadius && k.attr({ r: m.borderRadius }); + k.attr(a.pointAttribs(e, e.selected && 'select')).shadow( + m.shadow, + null, + m.stacking && !m.borderRadius, + ); + k.addClass(e.getClassName(), !0); + } else k && (e.graphic = k.destroy()); + }); + }, + animate: function(a) { + var e = this, + f = this.yAxis, + d = e.options, + c = this.chart.inverted, + b = {}, + k = c ? 'translateX' : 'translateY', + l; + u && + (a + ? ((b.scaleY = 0.001), + (a = Math.min( + f.pos + f.len, + Math.max(f.pos, f.toPixels(d.threshold)), + )), + c ? (b.translateX = a - f.len) : (b.translateY = a), + e.group.attr(b)) + : ((l = e.group.attr(k)), + e.group.animate( + { scaleY: 1 }, + p(E(e.options.animation), { + step: function(a, c) { + b[k] = l + c.pos * (f.pos - l); + e.group.attr(b); + }, + }), + ), + (e.animate = null))); + }, + remove: function() { + var a = this, + f = a.chart; + f.hasRendered && + H(f.series, function(e) { + e.type === a.type && (e.isDirty = !0); + }); + n.prototype.remove.apply(a, arguments); + }, + }, + ); + })(M); + (function(a) { + a = a.seriesType; + a('bar', 'column', null, { inverted: !0 }); + })(M); + (function(a) { + var E = a.Series; + a = a.seriesType; + a( + 'scatter', + 'line', + { + lineWidth: 0, + findNearestPointBy: 'xy', + marker: { enabled: !0 }, + tooltip: { + headerFormat: + '\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e \x3cspan style\x3d"font-size: 0.85em"\x3e {series.name}\x3c/span\x3e\x3cbr/\x3e', + pointFormat: + 'x: \x3cb\x3e{point.x}\x3c/b\x3e\x3cbr/\x3ey: \x3cb\x3e{point.y}\x3c/b\x3e\x3cbr/\x3e', + }, + }, + { + sorted: !1, + requireSorting: !1, + noSharedTooltip: !0, + trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], + takeOrdinalPosition: !1, + drawGraph: function() { + this.options.lineWidth && E.prototype.drawGraph.call(this); + }, + }, + ); + })(M); + (function(a) { + var E = a.deg2rad, + D = a.isNumber, + H = a.pick, + p = a.relativeLength; + a.CenteredSeriesMixin = { + getCenter: function() { + var a = this.options, + l = this.chart, + r = 2 * (a.slicedOffset || 0), + n = l.plotWidth - 2 * r, + l = l.plotHeight - 2 * r, + w = a.center, + w = [ + H(w[0], '50%'), + H(w[1], '50%'), + a.size || '100%', + a.innerSize || 0, + ], + u = Math.min(n, l), + e, + h; + for (e = 0; 4 > e; ++e) + (h = w[e]), + (a = 2 > e || (2 === e && /%$/.test(h))), + (w[e] = p(h, [n, l, u, w[2]][e]) + (a ? r : 0)); + w[3] > w[2] && (w[3] = w[2]); + return w; + }, + getStartAndEndRadians: function(a, l) { + a = D(a) ? a : 0; + l = D(l) && l > a && 360 > l - a ? l : a + 360; + return { start: E * (a + -90), end: E * (l + -90) }; + }, + }; + })(M); + (function(a) { + var E = a.addEvent, + D = a.CenteredSeriesMixin, + H = a.defined, + p = a.each, + f = a.extend, + l = D.getStartAndEndRadians, + r = a.inArray, + n = a.noop, + w = a.pick, + u = a.Point, + e = a.Series, + h = a.seriesType, + m = a.setAnimation; + h( + 'pie', + 'line', + { + center: [null, null], + clip: !1, + colorByPoint: !0, + dataLabels: { + distance: 30, + enabled: !0, + formatter: function() { + return this.point.isNull ? void 0 : this.point.name; + }, + x: 0, + }, + ignoreHiddenPoint: !0, + legendType: 'point', + marker: null, + size: null, + showInLegend: !1, + slicedOffset: 10, + stickyTracking: !1, + tooltip: { followPointer: !0 }, + borderColor: '#ffffff', + borderWidth: 1, + states: { hover: { brightness: 0.1, shadow: !1 } }, + }, + { + isCartesian: !1, + requireSorting: !1, + directTouch: !0, + noSharedTooltip: !0, + trackerGroups: ['group', 'dataLabelsGroup'], + axisTypes: [], + pointAttribs: a.seriesTypes.column.prototype.pointAttribs, + animate: function(a) { + var c = this, + b = c.points, + d = c.startAngleRad; + a || + (p(b, function(a) { + var b = a.graphic, + e = a.shapeArgs; + b && + (b.attr({ r: a.startR || c.center[3] / 2, start: d, end: d }), + b.animate( + { r: e.r, start: e.start, end: e.end }, + c.options.animation, + )); + }), + (c.animate = null)); + }, + updateTotals: function() { + var a, + c = 0, + b = this.points, + e = b.length, + f, + h = this.options.ignoreHiddenPoint; + for (a = 0; a < e; a++) + (f = b[a]), (c += h && !f.visible ? 0 : f.isNull ? 0 : f.y); + this.total = c; + for (a = 0; a < e; a++) + (f = b[a]), + (f.percentage = 0 < c && (f.visible || !h) ? (f.y / c) * 100 : 0), + (f.total = c); + }, + generatePoints: function() { + e.prototype.generatePoints.call(this); + this.updateTotals(); + }, + translate: function(a) { + this.generatePoints(); + var c = 0, + b = this.options, + d = b.slicedOffset, + e = d + (b.borderWidth || 0), + f, + h, + m, + n = l(b.startAngle, b.endAngle), + t = (this.startAngleRad = n.start), + n = (this.endAngleRad = n.end) - t, + p = this.points, + u, + q = b.dataLabels.distance, + b = b.ignoreHiddenPoint, + r, + F = p.length, + G; + a || (this.center = a = this.getCenter()); + this.getX = function(b, c, d) { + m = Math.asin( + Math.min((b - a[1]) / (a[2] / 2 + d.labelDistance), 1), + ); + return ( + a[0] + (c ? -1 : 1) * Math.cos(m) * (a[2] / 2 + d.labelDistance) + ); + }; + for (r = 0; r < F; r++) { + G = p[r]; + G.labelDistance = w( + G.options.dataLabels && G.options.dataLabels.distance, + q, + ); + this.maxLabelDistance = Math.max( + this.maxLabelDistance || 0, + G.labelDistance, + ); + f = t + c * n; + if (!b || G.visible) c += G.percentage / 100; + h = t + c * n; + G.shapeType = 'arc'; + G.shapeArgs = { + x: a[0], + y: a[1], + r: a[2] / 2, + innerR: a[3] / 2, + start: Math.round(1e3 * f) / 1e3, + end: Math.round(1e3 * h) / 1e3, + }; + m = (h + f) / 2; + m > 1.5 * Math.PI + ? (m -= 2 * Math.PI) + : m < -Math.PI / 2 && (m += 2 * Math.PI); + G.slicedTranslation = { + translateX: Math.round(Math.cos(m) * d), + translateY: Math.round(Math.sin(m) * d), + }; + h = (Math.cos(m) * a[2]) / 2; + u = (Math.sin(m) * a[2]) / 2; + G.tooltipPos = [a[0] + 0.7 * h, a[1] + 0.7 * u]; + G.half = m < -Math.PI / 2 || m > Math.PI / 2 ? 1 : 0; + G.angle = m; + f = Math.min(e, G.labelDistance / 5); + G.labelPos = [ + a[0] + h + Math.cos(m) * G.labelDistance, + a[1] + u + Math.sin(m) * G.labelDistance, + a[0] + h + Math.cos(m) * f, + a[1] + u + Math.sin(m) * f, + a[0] + h, + a[1] + u, + 0 > G.labelDistance ? 'center' : G.half ? 'right' : 'left', + m, + ]; + } + }, + drawGraph: null, + drawPoints: function() { + var a = this, + c = a.chart.renderer, + b, + e, + h, + l, + m = a.options.shadow; + m && !a.shadowGroup && (a.shadowGroup = c.g('shadow').add(a.group)); + p(a.points, function(d) { + e = d.graphic; + if (d.isNull) e && (d.graphic = e.destroy()); + else { + l = d.shapeArgs; + b = d.getTranslate(); + var k = d.shadowGroup; + m && !k && (k = d.shadowGroup = c.g('shadow').add(a.shadowGroup)); + k && k.attr(b); + h = a.pointAttribs(d, d.selected && 'select'); + e + ? e + .setRadialReference(a.center) + .attr(h) + .animate(f(l, b)) + : ((d.graphic = e = c[d.shapeType](l) + .setRadialReference(a.center) + .attr(b) + .add(a.group)), + d.visible || e.attr({ visibility: 'hidden' }), + e + .attr(h) + .attr({ 'stroke-linejoin': 'round' }) + .shadow(m, k)); + e.addClass(d.getClassName()); + } + }); + }, + searchPoint: n, + sortByAngle: function(a, c) { + a.sort(function(a, d) { + return void 0 !== a.angle && (d.angle - a.angle) * c; + }); + }, + drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, + getCenter: D.getCenter, + getSymbol: n, + }, + { + init: function() { + u.prototype.init.apply(this, arguments); + var a = this, + c; + a.name = w(a.name, 'Slice'); + c = function(b) { + a.slice('select' === b.type); + }; + E(a, 'select', c); + E(a, 'unselect', c); + return a; + }, + isValid: function() { + return a.isNumber(this.y, !0) && 0 <= this.y; + }, + setVisible: function(a, c) { + var b = this, + d = b.series, + e = d.chart, + f = d.options.ignoreHiddenPoint; + c = w(c, f); + a !== b.visible && + ((b.visible = b.options.visible = a = + void 0 === a ? !b.visible : a), + (d.options.data[r(b, d.data)] = b.options), + p(['graphic', 'dataLabel', 'connector', 'shadowGroup'], function( + c, + ) { + if (b[c]) b[c][a ? 'show' : 'hide'](!0); + }), + b.legendItem && e.legend.colorizeItem(b, a), + a || 'hover' !== b.state || b.setState(''), + f && (d.isDirty = !0), + c && e.redraw()); + }, + slice: function(a, c, b) { + var d = this.series; + m(b, d.chart); + w(c, !0); + this.sliced = this.options.sliced = H(a) ? a : !this.sliced; + d.options.data[r(this, d.data)] = this.options; + this.graphic.animate(this.getTranslate()); + this.shadowGroup && this.shadowGroup.animate(this.getTranslate()); + }, + getTranslate: function() { + return this.sliced + ? this.slicedTranslation + : { translateX: 0, translateY: 0 }; + }, + haloPath: function(a) { + var c = this.shapeArgs; + return this.sliced || !this.visible + ? [] + : this.series.chart.renderer.symbols.arc( + c.x, + c.y, + c.r + a, + c.r + a, + { innerR: this.shapeArgs.r - 1, start: c.start, end: c.end }, + ); + }, + }, + ); + })(M); + (function(a) { + var E = a.addEvent, + D = a.arrayMax, + H = a.defined, + p = a.each, + f = a.extend, + l = a.format, + r = a.map, + n = a.merge, + w = a.noop, + u = a.pick, + e = a.relativeLength, + h = a.Series, + m = a.seriesTypes, + d = a.stableSort; + a.distribute = function(a, b) { + function c(a, b) { + return a.target - b.target; + } + var e, + f = !0, + h = a, + l = [], + m; + m = 0; + for (e = a.length; e--; ) m += a[e].size; + if (m > b) { + d(a, function(a, b) { + return (b.rank || 0) - (a.rank || 0); + }); + for (m = e = 0; m <= b; ) (m += a[e].size), e++; + l = a.splice(e - 1, a.length); + } + d(a, c); + for ( + a = r(a, function(a) { + return { size: a.size, targets: [a.target], align: u(a.align, 0.5) }; + }); + f; + + ) { + for (e = a.length; e--; ) + (f = a[e]), + (m = + (Math.min.apply(0, f.targets) + Math.max.apply(0, f.targets)) / + 2), + (f.pos = Math.min(Math.max(0, m - f.size * f.align), b - f.size)); + e = a.length; + for (f = !1; e--; ) + 0 < e && + a[e - 1].pos + a[e - 1].size > a[e].pos && + ((a[e - 1].size += a[e].size), + (a[e - 1].targets = a[e - 1].targets.concat(a[e].targets)), + (a[e - 1].align = 0.5), + a[e - 1].pos + a[e - 1].size > b && + (a[e - 1].pos = b - a[e - 1].size), + a.splice(e, 1), + (f = !0)); + } + e = 0; + p(a, function(a) { + var b = 0; + p(a.targets, function() { + h[e].pos = a.pos + b; + b += h[e].size; + e++; + }); + }); + h.push.apply(h, l); + d(h, c); + }; + h.prototype.drawDataLabels = function() { + function c(a, b) { + var c = b.filter; + return c + ? ((b = c.operator), + (a = a[c.property]), + (c = c.value), + ('\x3e' === b && a > c) || + ('\x3c' === b && a < c) || + ('\x3e\x3d' === b && a >= c) || + ('\x3c\x3d' === b && a <= c) || + ('\x3d\x3d' === b && a == c) || + ('\x3d\x3d\x3d' === b && a === c) + ? !0 + : !1) + : !0; + } + var b = this, + d = b.options, + e = d.dataLabels, + f = b.points, + h, + m, + r = b.hasRendered || 0, + t, + w, + D = u(e.defer, !!d.animation), + q = b.chart.renderer; + if (e.enabled || b._hasPointLabels) + b.dlProcessOptions && b.dlProcessOptions(e), + (w = b.plotGroup( + 'dataLabelsGroup', + 'data-labels', + D && !r ? 'hidden' : 'visible', + e.zIndex || 6, + )), + D && + (w.attr({ opacity: +r }), + r || + E(b, 'afterAnimate', function() { + b.visible && w.show(!0); + w[d.animation ? 'animate' : 'attr']( + { opacity: 1 }, + { duration: 200 }, + ); + })), + (m = e), + p(f, function(f) { + var k, + p = f.dataLabel, + g, + x, + r = f.connector, + z = !p, + C; + h = f.dlOptions || (f.options && f.options.dataLabels); + (k = u(h && h.enabled, m.enabled) && !f.isNull) && + (k = !0 === c(f, h || e)); + k && + ((e = n(m, h)), + (g = f.getLabelConfig()), + (C = e[f.formatPrefix + 'Format'] || e.format), + (t = H(C) + ? l(C, g) + : (e[f.formatPrefix + 'Formatter'] || e.formatter).call(g, e)), + (C = e.style), + (g = e.rotation), + (C.color = u(e.color, C.color, b.color, '#000000')), + 'contrast' === C.color && + ((f.contrastColor = q.getContrast(f.color || b.color)), + (C.color = + e.inside || 0 > u(f.labelDistance, e.distance) || d.stacking + ? f.contrastColor + : '#000000')), + d.cursor && (C.cursor = d.cursor), + (x = { + fill: e.backgroundColor, + stroke: e.borderColor, + 'stroke-width': e.borderWidth, + r: e.borderRadius || 0, + rotation: g, + padding: e.padding, + zIndex: 1, + }), + a.objectEach(x, function(a, b) { + void 0 === a && delete x[b]; + })); + !p || (k && H(t)) + ? k && + H(t) && + (p + ? (x.text = t) + : ((p = f.dataLabel = g + ? q.text(t, 0, -9999).addClass('highcharts-data-label') + : q.label( + t, + 0, + -9999, + e.shape, + null, + null, + e.useHTML, + null, + 'data-label', + )), + p.addClass( + ' highcharts-data-label-color-' + + f.colorIndex + + ' ' + + (e.className || '') + + (e.useHTML ? 'highcharts-tracker' : ''), + )), + p.attr(x), + p.css(C).shadow(e.shadow), + p.added || p.add(w), + b.alignDataLabel(f, p, e, null, z)) + : ((f.dataLabel = p = p.destroy()), + r && (f.connector = r.destroy())); + }); + }; + h.prototype.alignDataLabel = function(a, b, d, e, h) { + var c = this.chart, + k = c.inverted, + l = u(a.dlBox && a.dlBox.centerX, a.plotX, -9999), + m = u(a.plotY, -9999), + n = b.getBBox(), + p, + q = d.rotation, + r = d.align, + w = + this.visible && + (a.series.forceDL || + c.isInsidePlot(l, Math.round(m), k) || + (e && c.isInsidePlot(l, k ? e.x + 1 : e.y + e.height - 1, k))), + z = 'justify' === u(d.overflow, 'justify'); + if ( + w && + ((p = d.style.fontSize), + (p = c.renderer.fontMetrics(p, b).b), + (e = f( + { + x: k ? this.yAxis.len - m : l, + y: Math.round(k ? this.xAxis.len - l : m), + width: 0, + height: 0, + }, + e, + )), + f(d, { width: n.width, height: n.height }), + q + ? ((z = !1), + (l = c.renderer.rotCorr(p, q)), + (l = { + x: e.x + d.x + e.width / 2 + l.x, + y: + e.y + + d.y + + { top: 0, middle: 0.5, bottom: 1 }[d.verticalAlign] * e.height, + }), + b[h ? 'attr' : 'animate'](l).attr({ align: r }), + (m = (q + 720) % 360), + (m = 180 < m && 360 > m), + 'left' === r + ? (l.y -= m ? n.height : 0) + : 'center' === r + ? ((l.x -= n.width / 2), (l.y -= n.height / 2)) + : 'right' === r && ((l.x -= n.width), (l.y -= m ? 0 : n.height))) + : (b.align(d, null, e), (l = b.alignAttr)), + z + ? (a.isLabelJustified = this.justifyDataLabel(b, d, l, n, e, h)) + : u(d.crop, !0) && + (w = + c.isInsidePlot(l.x, l.y) && + c.isInsidePlot(l.x + n.width, l.y + n.height)), + d.shape && !q) + ) + b[h ? 'attr' : 'animate']({ + anchorX: k ? c.plotWidth - a.plotY : a.plotX, + anchorY: k ? c.plotHeight - a.plotX : a.plotY, + }); + w || (b.attr({ y: -9999 }), (b.placed = !1)); + }; + h.prototype.justifyDataLabel = function(a, b, d, e, f, h) { + var c = this.chart, + k = b.align, + l = b.verticalAlign, + m, + n, + p = a.box ? 0 : a.padding || 0; + m = d.x + p; + 0 > m && ('right' === k ? (b.align = 'left') : (b.x = -m), (n = !0)); + m = d.x + e.width - p; + m > c.plotWidth && + ('left' === k ? (b.align = 'right') : (b.x = c.plotWidth - m), + (n = !0)); + m = d.y + p; + 0 > m && + ('bottom' === l ? (b.verticalAlign = 'top') : (b.y = -m), (n = !0)); + m = d.y + e.height - p; + m > c.plotHeight && + ('top' === l ? (b.verticalAlign = 'bottom') : (b.y = c.plotHeight - m), + (n = !0)); + n && ((a.placed = !h), a.align(b, null, f)); + return n; + }; + m.pie && + ((m.pie.prototype.drawDataLabels = function() { + var c = this, + b = c.data, + d, + e = c.chart, + f = c.options.dataLabels, + l = u(f.connectorPadding, 10), + m = u(f.connectorWidth, 1), + n = e.plotWidth, + t = e.plotHeight, + r, + w = c.center, + q = w[2] / 2, + A = w[1], + F, + G, + g, + v, + E = [[], []], + L, + P, + J, + M, + y = [0, 0, 0, 0]; + c.visible && + (f.enabled || c._hasPointLabels) && + (p(b, function(a) { + a.dataLabel && + a.visible && + a.dataLabel.shortened && + (a.dataLabel + .attr({ width: 'auto' }) + .css({ width: 'auto', textOverflow: 'clip' }), + (a.dataLabel.shortened = !1)); + }), + h.prototype.drawDataLabels.apply(c), + p(b, function(a) { + a.dataLabel && + a.visible && + (E[a.half].push(a), (a.dataLabel._pos = null)); + }), + p(E, function(b, h) { + var k, + m, + x = b.length, + r = [], + z; + if (x) + for ( + c.sortByAngle(b, h - 0.5), + 0 < c.maxLabelDistance && + ((k = Math.max(0, A - q - c.maxLabelDistance)), + (m = Math.min(A + q + c.maxLabelDistance, e.plotHeight)), + p(b, function(a) { + 0 < a.labelDistance && + a.dataLabel && + ((a.top = Math.max(0, A - q - a.labelDistance)), + (a.bottom = Math.min( + A + q + a.labelDistance, + e.plotHeight, + )), + (z = a.dataLabel.getBBox().height || 21), + (a.positionsIndex = + r.push({ + target: a.labelPos[1] - a.top + z / 2, + size: z, + rank: a.y, + }) - 1)); + }), + a.distribute(r, m + z - k)), + M = 0; + M < x; + M++ + ) + (d = b[M]), + (m = d.positionsIndex), + (g = d.labelPos), + (F = d.dataLabel), + (J = !1 === d.visible ? 'hidden' : 'inherit'), + (P = k = g[1]), + r && + H(r[m]) && + (void 0 === r[m].pos + ? (J = 'hidden') + : ((v = r[m].size), (P = d.top + r[m].pos))), + delete d.positionIndex, + (L = f.justify + ? w[0] + (h ? -1 : 1) * (q + d.labelDistance) + : c.getX(P < d.top + 2 || P > d.bottom - 2 ? k : P, h, d)), + (F._attr = { visibility: J, align: g[6] }), + (F._pos = { + x: L + f.x + ({ left: l, right: -l }[g[6]] || 0), + y: P + f.y - 10, + }), + (g.x = L), + (g.y = P), + u(f.crop, !0) && + ((G = F.getBBox().width), + (k = null), + L - G < l + ? ((k = Math.round(G - L + l)), + (y[3] = Math.max(k, y[3]))) + : L + G > n - l && + ((k = Math.round(L + G - n + l)), + (y[1] = Math.max(k, y[1]))), + 0 > P - v / 2 + ? (y[0] = Math.max(Math.round(-P + v / 2), y[0])) + : P + v / 2 > t && + (y[2] = Math.max(Math.round(P + v / 2 - t), y[2])), + (F.sideOverflow = k)); + }), + 0 === D(y) || this.verifyDataLabelOverflow(y)) && + (this.placeDataLabels(), + m && + p(this.points, function(a) { + var b; + r = a.connector; + if ( + (F = a.dataLabel) && + F._pos && + a.visible && + 0 < a.labelDistance + ) { + J = F._attr.visibility; + if ((b = !r)) + (a.connector = r = e.renderer + .path() + .addClass( + 'highcharts-data-label-connector highcharts-color-' + + a.colorIndex, + ) + .add(c.dataLabelsGroup)), + r.attr({ + 'stroke-width': m, + stroke: f.connectorColor || a.color || '#666666', + }); + r[b ? 'attr' : 'animate']({ d: c.connectorPath(a.labelPos) }); + r.attr('visibility', J); + } else r && (a.connector = r.destroy()); + })); + }), + (m.pie.prototype.connectorPath = function(a) { + var b = a.x, + c = a.y; + return u(this.options.dataLabels.softConnector, !0) + ? [ + 'M', + b + ('left' === a[6] ? 5 : -5), + c, + 'C', + b, + c, + 2 * a[2] - a[4], + 2 * a[3] - a[5], + a[2], + a[3], + 'L', + a[4], + a[5], + ] + : [ + 'M', + b + ('left' === a[6] ? 5 : -5), + c, + 'L', + a[2], + a[3], + 'L', + a[4], + a[5], + ]; + }), + (m.pie.prototype.placeDataLabels = function() { + p( + this.points, + function(a) { + var b = a.dataLabel; + b && + a.visible && + ((a = b._pos) + ? (b.sideOverflow && + ((b._attr.width = b.getBBox().width - b.sideOverflow), + b.css({ + width: b._attr.width + 'px', + textOverflow: 'ellipsis', + }), + (b.shortened = !0)), + b.attr(b._attr), + b[b.moved ? 'animate' : 'attr'](a), + (b.moved = !0)) + : b && b.attr({ y: -9999 })); + }, + this, + ); + }), + (m.pie.prototype.alignDataLabel = w), + (m.pie.prototype.verifyDataLabelOverflow = function(a) { + var b = this.center, + c = this.options, + d = c.center, + f = c.minSize || 80, + h, + l = null !== c.size; + l || + (null !== d[0] + ? (h = Math.max(b[2] - Math.max(a[1], a[3]), f)) + : ((h = Math.max(b[2] - a[1] - a[3], f)), + (b[0] += (a[3] - a[1]) / 2)), + null !== d[1] + ? (h = Math.max(Math.min(h, b[2] - Math.max(a[0], a[2])), f)) + : ((h = Math.max(Math.min(h, b[2] - a[0] - a[2]), f)), + (b[1] += (a[0] - a[2]) / 2)), + h < b[2] + ? ((b[2] = h), + (b[3] = Math.min(e(c.innerSize || 0, h), h)), + this.translate(b), + this.drawDataLabels && this.drawDataLabels()) + : (l = !0)); + return l; + })); + m.column && + (m.column.prototype.alignDataLabel = function(a, b, d, e, f) { + var c = this.chart.inverted, + k = a.series, + l = a.dlBox || a.shapeArgs, + m = u(a.below, a.plotY > u(this.translatedThreshold, k.yAxis.len)), + p = u(d.inside, !!this.options.stacking); + l && + ((e = n(l)), + 0 > e.y && ((e.height += e.y), (e.y = 0)), + (l = e.y + e.height - k.yAxis.len), + 0 < l && (e.height -= l), + c && + (e = { + x: k.yAxis.len - e.y - e.height, + y: k.xAxis.len - e.x - e.width, + width: e.height, + height: e.width, + }), + p || + (c + ? ((e.x += m ? 0 : e.width), (e.width = 0)) + : ((e.y += m ? e.height : 0), (e.height = 0)))); + d.align = u(d.align, !c || p ? 'center' : m ? 'right' : 'left'); + d.verticalAlign = u( + d.verticalAlign, + c || p ? 'middle' : m ? 'top' : 'bottom', + ); + h.prototype.alignDataLabel.call(this, a, b, d, e, f); + a.isLabelJustified && + a.contrastColor && + a.dataLabel.css({ color: a.contrastColor }); + }); + })(M); + (function(a) { + var E = a.Chart, + D = a.each, + H = a.objectEach, + p = a.pick; + a = a.addEvent; + a(E.prototype, 'render', function() { + var a = []; + D(this.labelCollectors || [], function(f) { + a = a.concat(f()); + }); + D(this.yAxis || [], function(f) { + f.options.stackLabels && + !f.options.stackLabels.allowOverlap && + H(f.stacks, function(f) { + H(f, function(f) { + a.push(f.label); + }); + }); + }); + D(this.series || [], function(f) { + var l = f.options.dataLabels, + n = f.dataLabelCollections || ['dataLabel']; + (l.enabled || f._hasPointLabels) && + !l.allowOverlap && + f.visible && + D(n, function(l) { + D(f.points, function(f) { + f[l] && + ((f[l].labelrank = p( + f.labelrank, + f.shapeArgs && f.shapeArgs.height, + )), + a.push(f[l])); + }); + }); + }); + this.hideOverlappingLabels(a); + }); + E.prototype.hideOverlappingLabels = function(a) { + var f = a.length, + p, + n, + w, + u, + e, + h, + m, + d, + c, + b = function(a, b, c, d, e, f, h, l) { + return !(e > a + c || e + h < a || f > b + d || f + l < b); + }; + for (n = 0; n < f; n++) + if ((p = a[n])) + (p.oldOpacity = p.opacity), + (p.newOpacity = 1), + p.width || + ((w = p.getBBox()), (p.width = w.width), (p.height = w.height)); + a.sort(function(a, b) { + return (b.labelrank || 0) - (a.labelrank || 0); + }); + for (n = 0; n < f; n++) + for (w = a[n], p = n + 1; p < f; ++p) + if ( + ((u = a[p]), + w && + u && + w !== u && + w.placed && + u.placed && + 0 !== w.newOpacity && + 0 !== u.newOpacity && + ((e = w.alignAttr), + (h = u.alignAttr), + (m = w.parentGroup), + (d = u.parentGroup), + (c = 2 * (w.box ? 0 : w.padding || 0)), + (e = b( + e.x + m.translateX, + e.y + m.translateY, + w.width - c, + w.height - c, + h.x + d.translateX, + h.y + d.translateY, + u.width - c, + u.height - c, + )))) + ) + (w.labelrank < u.labelrank ? w : u).newOpacity = 0; + D(a, function(a) { + var b, c; + a && + ((c = a.newOpacity), + a.oldOpacity !== c && + a.placed && + (c + ? a.show(!0) + : (b = function() { + a.hide(); + }), + (a.alignAttr.opacity = c), + a[a.isOld ? 'animate' : 'attr'](a.alignAttr, null, b)), + (a.isOld = !0)); + }); + }; + })(M); + (function(a) { + var E = a.addEvent, + D = a.Chart, + H = a.createElement, + p = a.css, + f = a.defaultOptions, + l = a.defaultPlotOptions, + r = a.each, + n = a.extend, + w = a.fireEvent, + u = a.hasTouch, + e = a.inArray, + h = a.isObject, + m = a.Legend, + d = a.merge, + c = a.pick, + b = a.Point, + k = a.Series, + z = a.seriesTypes, + B = a.svg, + I; + I = a.TrackerMixin = { + drawTrackerPoint: function() { + var a = this, + b = a.chart.pointer, + c = function(a) { + var c = b.getPointFromEvent(a); + void 0 !== c && ((b.isDirectTouch = !0), c.onMouseOver(a)); + }; + r(a.points, function(a) { + a.graphic && (a.graphic.element.point = a); + a.dataLabel && + (a.dataLabel.div + ? (a.dataLabel.div.point = a) + : (a.dataLabel.element.point = a)); + }); + a._hasTracking || + (r(a.trackerGroups, function(d) { + if (a[d]) { + a[d] + .addClass('highcharts-tracker') + .on('mouseover', c) + .on('mouseout', function(a) { + b.onTrackerMouseOut(a); + }); + if (u) a[d].on('touchstart', c); + a.options.cursor && a[d].css(p).css({ cursor: a.options.cursor }); + } + }), + (a._hasTracking = !0)); + }, + drawTrackerGraph: function() { + var a = this, + b = a.options, + c = b.trackByArea, + d = [].concat(c ? a.areaPath : a.graphPath), + e = d.length, + f = a.chart, + h = f.pointer, + k = f.renderer, + l = f.options.tooltip.snap, + g = a.tracker, + m, + n = function() { + if (f.hoverSeries !== a) a.onMouseOver(); + }, + p = 'rgba(192,192,192,' + (B ? 0.0001 : 0.002) + ')'; + if (e && !c) + for (m = e + 1; m--; ) + 'M' === d[m] && d.splice(m + 1, 0, d[m + 1] - l, d[m + 2], 'L'), + ((m && 'M' === d[m]) || m === e) && + d.splice(m, 0, 'L', d[m - 2] + l, d[m - 1]); + g + ? g.attr({ d: d }) + : a.graph && + ((a.tracker = k + .path(d) + .attr({ + 'stroke-linejoin': 'round', + visibility: a.visible ? 'visible' : 'hidden', + stroke: p, + fill: c ? p : 'none', + 'stroke-width': a.graph.strokeWidth() + (c ? 0 : 2 * l), + zIndex: 2, + }) + .add(a.group)), + r([a.tracker, a.markerGroup], function(a) { + a.addClass('highcharts-tracker') + .on('mouseover', n) + .on('mouseout', function(a) { + h.onTrackerMouseOut(a); + }); + b.cursor && a.css({ cursor: b.cursor }); + if (u) a.on('touchstart', n); + })); + }, + }; + z.column && (z.column.prototype.drawTracker = I.drawTrackerPoint); + z.pie && (z.pie.prototype.drawTracker = I.drawTrackerPoint); + z.scatter && (z.scatter.prototype.drawTracker = I.drawTrackerPoint); + n(m.prototype, { + setItemEvents: function(a, c, e) { + var f = this, + h = f.chart.renderer.boxWrapper, + k = + 'highcharts-legend-' + + (a instanceof b ? 'point' : 'series') + + '-active'; + (e ? c : a.legendGroup) + .on('mouseover', function() { + a.setState('hover'); + h.addClass(k); + c.css(f.options.itemHoverStyle); + }) + .on('mouseout', function() { + c.css(d(a.visible ? f.itemStyle : f.itemHiddenStyle)); + h.removeClass(k); + a.setState(); + }) + .on('click', function(b) { + var c = function() { + a.setVisible && a.setVisible(); + }; + h.removeClass(k); + b = { browserEvent: b }; + a.firePointEvent + ? a.firePointEvent('legendItemClick', b, c) + : w(a, 'legendItemClick', b, c); + }); + }, + createCheckboxForItem: function(a) { + a.checkbox = H( + 'input', + { type: 'checkbox', checked: a.selected, defaultChecked: a.selected }, + this.options.itemCheckboxStyle, + this.chart.container, + ); + E(a.checkbox, 'click', function(b) { + w( + a.series || a, + 'checkboxClick', + { checked: b.target.checked, item: a }, + function() { + a.select(); + }, + ); + }); + }, + }); + f.legend.itemStyle.cursor = 'pointer'; + n(D.prototype, { + showResetZoom: function() { + var a = this, + b = f.lang, + c = a.options.chart.resetZoomButton, + d = c.theme, + e = d.states, + h = 'chart' === c.relativeTo ? null : 'plotBox'; + this.resetZoomButton = a.renderer + .button( + b.resetZoom, + null, + null, + function() { + a.zoomOut(); + }, + d, + e && e.hover, + ) + .attr({ align: c.position.align, title: b.resetZoomTitle }) + .addClass('highcharts-reset-zoom') + .add() + .align(c.position, !1, h); + }, + zoomOut: function() { + var a = this; + w(a, 'selection', { resetSelection: !0 }, function() { + a.zoom(); + }); + }, + zoom: function(a) { + var b, + d = this.pointer, + e = !1, + f; + !a || a.resetSelection + ? (r(this.axes, function(a) { + b = a.zoom(); + }), + (d.initiated = !1)) + : r(a.xAxis.concat(a.yAxis), function(a) { + var c = a.axis; + d[c.isXAxis ? 'zoomX' : 'zoomY'] && + ((b = c.zoom(a.min, a.max)), c.displayBtn && (e = !0)); + }); + f = this.resetZoomButton; + e && !f + ? this.showResetZoom() + : !e && h(f) && (this.resetZoomButton = f.destroy()); + b && + this.redraw( + c( + this.options.chart.animation, + a && a.animation, + 100 > this.pointCount, + ), + ); + }, + pan: function(a, b) { + var c = this, + d = c.hoverPoints, + e; + d && + r(d, function(a) { + a.setState(); + }); + r('xy' === b ? [1, 0] : [1], function(b) { + b = c[b ? 'xAxis' : 'yAxis'][0]; + var d = b.horiz, + f = a[d ? 'chartX' : 'chartY'], + d = d ? 'mouseDownX' : 'mouseDownY', + h = c[d], + g = (b.pointRange || 0) / 2, + k = b.getExtremes(), + l = b.toValue(h - f, !0) + g, + m = b.toValue(h + b.len - f, !0) - g, + n = m < l, + h = n ? m : l, + l = n ? l : m, + m = Math.min( + k.dataMin, + g ? k.min : b.toValue(b.toPixels(k.min) - b.minPixelPadding), + ), + g = Math.max( + k.dataMax, + g ? k.max : b.toValue(b.toPixels(k.max) + b.minPixelPadding), + ), + n = m - h; + 0 < n && ((l += n), (h = m)); + n = l - g; + 0 < n && ((l = g), (h -= n)); + b.series.length && + h !== k.min && + l !== k.max && + (b.setExtremes(h, l, !1, !1, { trigger: 'pan' }), (e = !0)); + c[d] = f; + }); + e && c.redraw(!1); + p(c.container, { cursor: 'move' }); + }, + }); + n(b.prototype, { + select: function(a, b) { + var d = this, + f = d.series, + h = f.chart; + a = c(a, !d.selected); + d.firePointEvent( + a ? 'select' : 'unselect', + { accumulate: b }, + function() { + d.selected = d.options.selected = a; + f.options.data[e(d, f.data)] = d.options; + d.setState(a && 'select'); + b || + r(h.getSelectedPoints(), function(a) { + a.selected && + a !== d && + ((a.selected = a.options.selected = !1), + (f.options.data[e(a, f.data)] = a.options), + a.setState(''), + a.firePointEvent('unselect')); + }); + }, + ); + }, + onMouseOver: function(a) { + var b = this.series.chart, + c = b.pointer; + a = a + ? c.normalize(a) + : c.getChartCoordinatesFromPoint(this, b.inverted); + c.runPointActions(a, this); + }, + onMouseOut: function() { + var a = this.series.chart; + this.firePointEvent('mouseOut'); + r(a.hoverPoints || [], function(a) { + a.setState(); + }); + a.hoverPoints = a.hoverPoint = null; + }, + importEvents: function() { + if (!this.hasImportedEvents) { + var b = this, + c = d(b.series.options.point, b.options).events; + b.events = c; + a.objectEach(c, function(a, c) { + E(b, c, a); + }); + this.hasImportedEvents = !0; + } + }, + setState: function(a, b) { + var d = Math.floor(this.plotX), + e = this.plotY, + f = this.series, + h = f.options.states[a] || {}, + k = l[f.type].marker && f.options.marker, + m = k && !1 === k.enabled, + p = (k && k.states && k.states[a]) || {}, + g = !1 === p.enabled, + r = f.stateMarkerGraphic, + u = this.marker || {}, + w = f.chart, + x = f.halo, + z, + B = k && f.markerAttribs; + a = a || ''; + if ( + !( + (a === this.state && !b) || + (this.selected && 'select' !== a) || + !1 === h.enabled || + (a && (g || (m && !1 === p.enabled))) || + (a && u.states && u.states[a] && !1 === u.states[a].enabled) + ) + ) { + B && (z = f.markerAttribs(this, a)); + if (this.graphic) + this.state && + this.graphic.removeClass('highcharts-point-' + this.state), + a && this.graphic.addClass('highcharts-point-' + a), + this.graphic.animate( + f.pointAttribs(this, a), + c(w.options.chart.animation, h.animation), + ), + z && + this.graphic.animate( + z, + c(w.options.chart.animation, p.animation, k.animation), + ), + r && r.hide(); + else { + if (a && p) { + k = u.symbol || f.symbol; + r && r.currentSymbol !== k && (r = r.destroy()); + if (r) r[b ? 'animate' : 'attr']({ x: z.x, y: z.y }); + else + k && + ((f.stateMarkerGraphic = r = w.renderer + .symbol(k, z.x, z.y, z.width, z.height) + .add(f.markerGroup)), + (r.currentSymbol = k)); + r && r.attr(f.pointAttribs(this, a)); + } + r && + (r[a && w.isInsidePlot(d, e, w.inverted) ? 'show' : 'hide'](), + (r.element.point = this)); + } + (d = h.halo) && d.size + ? (x || + (f.halo = x = w.renderer + .path() + .add((this.graphic || r).parentGroup)), + x[b ? 'animate' : 'attr']({ d: this.haloPath(d.size) }), + x.attr({ + class: + 'highcharts-halo highcharts-color-' + + c(this.colorIndex, f.colorIndex), + }), + (x.point = this), + x.attr( + n( + { + fill: this.color || f.color, + 'fill-opacity': d.opacity, + zIndex: -1, + }, + d.attributes, + ), + )) + : x && + x.point && + x.point.haloPath && + x.animate({ d: x.point.haloPath(0) }); + this.state = a; + } + }, + haloPath: function(a) { + return this.series.chart.renderer.symbols.circle( + Math.floor(this.plotX) - a, + this.plotY - a, + 2 * a, + 2 * a, + ); + }, + }); + n(k.prototype, { + onMouseOver: function() { + var a = this.chart, + b = a.hoverSeries; + if (b && b !== this) b.onMouseOut(); + this.options.events.mouseOver && w(this, 'mouseOver'); + this.setState('hover'); + a.hoverSeries = this; + }, + onMouseOut: function() { + var a = this.options, + b = this.chart, + c = b.tooltip, + d = b.hoverPoint; + b.hoverSeries = null; + if (d) d.onMouseOut(); + this && a.events.mouseOut && w(this, 'mouseOut'); + !c || + this.stickyTracking || + (c.shared && !this.noSharedTooltip) || + c.hide(); + this.setState(); + }, + setState: function(a) { + var b = this, + d = b.options, + e = b.graph, + f = d.states, + h = d.lineWidth, + d = 0; + a = a || ''; + if ( + b.state !== a && + (r([b.group, b.markerGroup, b.dataLabelsGroup], function(c) { + c && + (b.state && c.removeClass('highcharts-series-' + b.state), + a && c.addClass('highcharts-series-' + a)); + }), + (b.state = a), + !f[a] || !1 !== f[a].enabled) && + (a && (h = f[a].lineWidth || h + (f[a].lineWidthPlus || 0)), + e && !e.dashstyle) + ) + for ( + h = { 'stroke-width': h }, + e.animate( + h, + c(b.chart.options.chart.animation, f[a] && f[a].animation), + ); + b['zone-graph-' + d]; + + ) + b['zone-graph-' + d].attr(h), (d += 1); + }, + setVisible: function(a, b) { + var c = this, + d = c.chart, + e = c.legendItem, + f, + h = d.options.chart.ignoreHiddenSeries, + k = c.visible; + f = (c.visible = a = c.options.visible = c.userOptions.visible = + void 0 === a ? !k : a) + ? 'show' + : 'hide'; + r( + ['group', 'dataLabelsGroup', 'markerGroup', 'tracker', 'tt'], + function(a) { + if (c[a]) c[a][f](); + }, + ); + if (d.hoverSeries === c || (d.hoverPoint && d.hoverPoint.series) === c) + c.onMouseOut(); + e && d.legend.colorizeItem(c, a); + c.isDirty = !0; + c.options.stacking && + r(d.series, function(a) { + a.options.stacking && a.visible && (a.isDirty = !0); + }); + r(c.linkedSeries, function(b) { + b.setVisible(a, !1); + }); + h && (d.isDirtyBox = !0); + !1 !== b && d.redraw(); + w(c, f); + }, + show: function() { + this.setVisible(!0); + }, + hide: function() { + this.setVisible(!1); + }, + select: function(a) { + this.selected = a = void 0 === a ? !this.selected : a; + this.checkbox && (this.checkbox.checked = a); + w(this, a ? 'select' : 'unselect'); + }, + drawTracker: I.drawTrackerGraph, + }); + })(M); + (function(a) { + var E = a.Chart, + D = a.each, + H = a.inArray, + p = a.isArray, + f = a.isObject, + l = a.pick, + r = a.splat; + E.prototype.setResponsive = function(f) { + var l = this.options.responsive, + n = [], + e = this.currentResponsive; + l && + l.rules && + D( + l.rules, + function(e) { + void 0 === e._id && (e._id = a.uniqueKey()); + this.matchResponsiveRule(e, n, f); + }, + this, + ); + var h = a.merge.apply( + 0, + a.map(n, function(e) { + return a.find(l.rules, function(a) { + return a._id === e; + }).chartOptions; + }), + ), + n = n.toString() || void 0; + n !== (e && e.ruleIds) && + (e && this.update(e.undoOptions, f), + n + ? ((this.currentResponsive = { + ruleIds: n, + mergedOptions: h, + undoOptions: this.currentOptions(h), + }), + this.update(h, f)) + : (this.currentResponsive = void 0)); + }; + E.prototype.matchResponsiveRule = function(a, f) { + var n = a.condition; + ( + n.callback || + function() { + return ( + this.chartWidth <= l(n.maxWidth, Number.MAX_VALUE) && + this.chartHeight <= l(n.maxHeight, Number.MAX_VALUE) && + this.chartWidth >= l(n.minWidth, 0) && + this.chartHeight >= l(n.minHeight, 0) + ); + } + ).call(this) && f.push(a._id); + }; + E.prototype.currentOptions = function(l) { + function n(e, h, l, d) { + var c; + a.objectEach(e, function(a, e) { + if (!d && -1 < H(e, ['series', 'xAxis', 'yAxis'])) + for (a = r(a), l[e] = [], c = 0; c < a.length; c++) + h[e][c] && ((l[e][c] = {}), n(a[c], h[e][c], l[e][c], d + 1)); + else + f(a) + ? ((l[e] = p(a) ? [] : {}), n(a, h[e] || {}, l[e], d + 1)) + : (l[e] = h[e] || null); + }); + } + var u = {}; + n(l, this.options, u, 0); + return u; + }; + })(M); + return M; +}); From 4218688d8e1c197690a2b629cb68d71d1399d8c0 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Fri, 4 Jan 2019 18:14:36 +1300 Subject: [PATCH 257/267] Revert "Auto corrected by following Format Javascript Code" This reverts commit f83a2b639730d985dc8fb38dd0caa6646404bee7. --- app/assets/javascripts/highcharts.js | 11651 +------------------------ 1 file changed, 382 insertions(+), 11269 deletions(-) diff --git a/app/assets/javascripts/highcharts.js b/app/assets/javascripts/highcharts.js index c7136bafe..9554ef58b 100644 --- a/app/assets/javascripts/highcharts.js +++ b/app/assets/javascripts/highcharts.js @@ -5,11272 +5,385 @@ License: www.highcharts.com/license */ -(function(S, M) { - 'object' === typeof module && module.exports - ? (module.exports = S.document ? M(S) : M) - : (S.Highcharts = M(S)); -})('undefined' !== typeof window ? window : this, function(S) { - var M = (function() { - var a = 'undefined' === typeof S ? window : S, - E = a.document, - D = (a.navigator && a.navigator.userAgent) || '', - H = - E && - E.createElementNS && - !!E.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect, - p = /(edge|msie|trident)/i.test(D) && !a.opera, - f = /Firefox/.test(D), - l = f && 4 > parseInt(D.split('Firefox/')[1], 10); - return a.Highcharts - ? a.Highcharts.error(16, !0) - : { - product: 'Highcharts', - version: '6.0.4', - deg2rad: (2 * Math.PI) / 360, - doc: E, - hasBidiBug: l, - hasTouch: E && void 0 !== E.documentElement.ontouchstart, - isMS: p, - isWebKit: /AppleWebKit/.test(D), - isFirefox: f, - isTouchDevice: /(Mobile|Android|Windows Phone)/.test(D), - SVG_NS: 'http://www.w3.org/2000/svg', - chartCount: 0, - seriesTypes: {}, - symbolSizes: {}, - svg: H, - win: a, - marginNames: ['plotTop', 'marginRight', 'marginBottom', 'plotLeft'], - noop: function() {}, - charts: [], - }; - })(); - (function(a) { - a.timers = []; - var E = a.charts, - D = a.doc, - H = a.win; - a.error = function(p, f) { - p = a.isNumber(p) - ? 'Highcharts error #' + p + ': www.highcharts.com/errors/' + p - : p; - if (f) throw Error(p); - H.console && console.log(p); - }; - a.Fx = function(a, f, l) { - this.options = f; - this.elem = a; - this.prop = l; - }; - a.Fx.prototype = { - dSetter: function() { - var a = this.paths[0], - f = this.paths[1], - l = [], - r = this.now, - n = a.length, - w; - if (1 === r) l = this.toD; - else if (n === f.length && 1 > r) - for (; n--; ) - (w = parseFloat(a[n])), - (l[n] = isNaN(w) ? f[n] : r * parseFloat(f[n] - w) + w); - else l = f; - this.elem.attr('d', l, null, !0); - }, - update: function() { - var a = this.elem, - f = this.prop, - l = this.now, - r = this.options.step; - if (this[f + 'Setter']) this[f + 'Setter'](); - else - a.attr - ? a.element && a.attr(f, l, null, !0) - : (a.style[f] = l + this.unit); - r && r.call(a, l, this); - }, - run: function(p, f, l) { - var r = this, - n = r.options, - w = function(a) { - return w.stopped ? !1 : r.step(a); - }, - u = - H.requestAnimationFrame || - function(a) { - setTimeout(a, 13); - }, - e = function() { - for (var h = 0; h < a.timers.length; h++) - a.timers[h]() || a.timers.splice(h--, 1); - a.timers.length && u(e); - }; - p === f - ? (delete n.curAnim[this.prop], - n.complete && - 0 === a.keys(n.curAnim).length && - n.complete.call(this.elem)) - : ((this.startTime = +new Date()), - (this.start = p), - (this.end = f), - (this.unit = l), - (this.now = this.start), - (this.pos = 0), - (w.elem = this.elem), - (w.prop = this.prop), - w() && 1 === a.timers.push(w) && u(e)); - }, - step: function(p) { - var f = +new Date(), - l, - r = this.options, - n = this.elem, - w = r.complete, - u = r.duration, - e = r.curAnim; - n.attr && !n.element - ? (p = !1) - : p || f >= u + this.startTime - ? ((this.now = this.end), - (this.pos = 1), - this.update(), - (l = e[this.prop] = !0), - a.objectEach(e, function(a) { - !0 !== a && (l = !1); - }), - l && w && w.call(n), - (p = !1)) - : ((this.pos = r.easing((f - this.startTime) / u)), - (this.now = this.start + (this.end - this.start) * this.pos), - this.update(), - (p = !0)); - return p; - }, - initPath: function(p, f, l) { - function r(a) { - var b, c; - for (k = a.length; k--; ) - (b = 'M' === a[k] || 'L' === a[k]), - (c = /[a-zA-Z]/.test(a[k + 3])), - b && - c && - a.splice(k + 1, 0, a[k + 1], a[k + 2], a[k + 1], a[k + 2]); - } - function n(a, b) { - for (; a.length < c; ) { - a[0] = b[c - a.length]; - var e = a.slice(0, d); - [].splice.apply(a, [0, 0].concat(e)); - z && - ((e = a.slice(a.length - d)), - [].splice.apply(a, [a.length, 0].concat(e)), - k--); - } - a[0] = 'M'; - } - function w(a, k) { - for (var e = (c - a.length) / d; 0 < e && e--; ) - (b = a.slice().splice(a.length / B - d, d * B)), - (b[0] = k[c - d - e * d]), - m && ((b[d - 6] = b[d - 2]), (b[d - 5] = b[d - 1])), - [].splice.apply(a, [a.length / B, 0].concat(b)), - z && e--; - } - f = f || ''; - var u, - e = p.startX, - h = p.endX, - m = -1 < f.indexOf('C'), - d = m ? 7 : 3, - c, - b, - k; - f = f.split(' '); - l = l.slice(); - var z = p.isArea, - B = z ? 2 : 1, - I; - m && (r(f), r(l)); - if (e && h) { - for (k = 0; k < e.length; k++) - if (e[k] === h[0]) { - u = k; - break; - } else if (e[0] === h[h.length - e.length + k]) { - u = k; - I = !0; - break; - } - void 0 === u && (f = []); - } - f.length && - a.isNumber(u) && - ((c = l.length + u * B * d), - I ? (n(f, l), w(l, f)) : (n(l, f), w(f, l))); - return [f, l]; - }, - }; - a.Fx.prototype.fillSetter = a.Fx.prototype.strokeSetter = function() { - this.elem.attr( - this.prop, - a.color(this.start).tweenTo(a.color(this.end), this.pos), - null, - !0, - ); - }; - a.extend = function(a, f) { - var l; - a || (a = {}); - for (l in f) a[l] = f[l]; - return a; - }; - a.merge = function() { - var p, - f = arguments, - l, - r = {}, - n = function(l, p) { - 'object' !== typeof l && (l = {}); - a.objectEach(p, function(e, h) { - !a.isObject(e, !0) || a.isClass(e) || a.isDOMElement(e) - ? (l[h] = p[h]) - : (l[h] = n(l[h] || {}, e)); - }); - return l; - }; - !0 === f[0] && ((r = f[1]), (f = Array.prototype.slice.call(f, 2))); - l = f.length; - for (p = 0; p < l; p++) r = n(r, f[p]); - return r; - }; - a.pInt = function(a, f) { - return parseInt(a, f || 10); - }; - a.isString = function(a) { - return 'string' === typeof a; - }; - a.isArray = function(a) { - a = Object.prototype.toString.call(a); - return '[object Array]' === a || '[object Array Iterator]' === a; - }; - a.isObject = function(p, f) { - return !!p && 'object' === typeof p && (!f || !a.isArray(p)); - }; - a.isDOMElement = function(p) { - return a.isObject(p) && 'number' === typeof p.nodeType; - }; - a.isClass = function(p) { - var f = p && p.constructor; - return !( - !a.isObject(p, !0) || - a.isDOMElement(p) || - !f || - !f.name || - 'Object' === f.name - ); - }; - a.isNumber = function(a) { - return ( - 'number' === typeof a && !isNaN(a) && Infinity > a && -Infinity < a - ); - }; - a.erase = function(a, f) { - for (var l = a.length; l--; ) - if (a[l] === f) { - a.splice(l, 1); - break; - } - }; - a.defined = function(a) { - return void 0 !== a && null !== a; - }; - a.attr = function(p, f, l) { - var r; - a.isString(f) - ? a.defined(l) - ? p.setAttribute(f, l) - : p && p.getAttribute && (r = p.getAttribute(f)) - : a.defined(f) && - a.isObject(f) && - a.objectEach(f, function(a, l) { - p.setAttribute(l, a); - }); - return r; - }; - a.splat = function(p) { - return a.isArray(p) ? p : [p]; - }; - a.syncTimeout = function(a, f, l) { - if (f) return setTimeout(a, f, l); - a.call(0, l); - }; - a.pick = function() { - var a = arguments, - f, - l, - r = a.length; - for (f = 0; f < r; f++) - if (((l = a[f]), void 0 !== l && null !== l)) return l; - }; - a.css = function(p, f) { - a.isMS && - !a.svg && - f && - void 0 !== f.opacity && - (f.filter = 'alpha(opacity\x3d' + 100 * f.opacity + ')'); - a.extend(p.style, f); - }; - a.createElement = function(p, f, l, r, n) { - p = D.createElement(p); - var w = a.css; - f && a.extend(p, f); - n && w(p, { padding: 0, border: 'none', margin: 0 }); - l && w(p, l); - r && r.appendChild(p); - return p; - }; - a.extendClass = function(p, f) { - var l = function() {}; - l.prototype = new p(); - a.extend(l.prototype, f); - return l; - }; - a.pad = function(a, f, l) { - return Array((f || 2) + 1 - String(a).length).join(l || 0) + a; - }; - a.relativeLength = function(a, f, l) { - return /%$/.test(a) - ? (f * parseFloat(a)) / 100 + (l || 0) - : parseFloat(a); - }; - a.wrap = function(a, f, l) { - var p = a[f]; - a[f] = function() { - var a = Array.prototype.slice.call(arguments), - f = arguments, - u = this; - u.proceed = function() { - p.apply(u, arguments.length ? arguments : f); - }; - a.unshift(p); - a = l.apply(this, a); - u.proceed = null; - return a; - }; - }; - a.getTZOffset = function(p) { - var f = a.Date; - return ( - 6e4 * - ((f.hcGetTimezoneOffset && f.hcGetTimezoneOffset(p)) || - f.hcTimezoneOffset || - 0) - ); - }; - a.dateFormat = function(p, f, l) { - if (!a.defined(f) || isNaN(f)) - return a.defaultOptions.lang.invalidDate || ''; - p = a.pick(p, '%Y-%m-%d %H:%M:%S'); - var r = a.Date, - n = new r(f - a.getTZOffset(f)), - w = n[r.hcGetHours](), - u = n[r.hcGetDay](), - e = n[r.hcGetDate](), - h = n[r.hcGetMonth](), - m = n[r.hcGetFullYear](), - d = a.defaultOptions.lang, - c = d.weekdays, - b = d.shortWeekdays, - k = a.pad, - r = a.extend( - { - a: b ? b[u] : c[u].substr(0, 3), - A: c[u], - d: k(e), - e: k(e, 2, ' '), - w: u, - b: d.shortMonths[h], - B: d.months[h], - m: k(h + 1), - y: m.toString().substr(2, 2), - Y: m, - H: k(w), - k: w, - I: k(w % 12 || 12), - l: w % 12 || 12, - M: k(n[r.hcGetMinutes]()), - p: 12 > w ? 'AM' : 'PM', - P: 12 > w ? 'am' : 'pm', - S: k(n.getSeconds()), - L: k(Math.round(f % 1e3), 3), - }, - a.dateFormats, - ); - a.objectEach(r, function(a, b) { - for (; -1 !== p.indexOf('%' + b); ) - p = p.replace('%' + b, 'function' === typeof a ? a(f) : a); - }); - return l ? p.substr(0, 1).toUpperCase() + p.substr(1) : p; - }; - a.formatSingle = function(p, f) { - var l = /\.([0-9])/, - r = a.defaultOptions.lang; - /f$/.test(p) - ? ((l = (l = p.match(l)) ? l[1] : -1), - null !== f && - (f = a.numberFormat( - f, - l, - r.decimalPoint, - -1 < p.indexOf(',') ? r.thousandsSep : '', - ))) - : (f = a.dateFormat(p, f)); - return f; - }; - a.format = function(p, f) { - for (var l = '{', r = !1, n, w, u, e, h = [], m; p; ) { - l = p.indexOf(l); - if (-1 === l) break; - n = p.slice(0, l); - if (r) { - n = n.split(':'); - w = n.shift().split('.'); - e = w.length; - m = f; - for (u = 0; u < e; u++) m && (m = m[w[u]]); - n.length && (m = a.formatSingle(n.join(':'), m)); - h.push(m); - } else h.push(n); - p = p.slice(l + 1); - l = (r = !r) ? '}' : '{'; - } - h.push(p); - return h.join(''); - }; - a.getMagnitude = function(a) { - return Math.pow(10, Math.floor(Math.log(a) / Math.LN10)); - }; - a.normalizeTickInterval = function(p, f, l, r, n) { - var w, - u = p; - l = a.pick(l, 1); - w = p / l; - f || - ((f = n - ? [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] - : [1, 2, 2.5, 5, 10]), - !1 === r && - (1 === l - ? (f = a.grep(f, function(a) { - return 0 === a % 1; - })) - : 0.1 >= l && (f = [1 / l]))); - for ( - r = 0; - r < f.length && - !((u = f[r]), - (n && u * l >= p) || (!n && w <= (f[r] + (f[r + 1] || f[r])) / 2)); - r++ - ); - return (u = a.correctFloat( - u * l, - -Math.round(Math.log(0.001) / Math.LN10), - )); - }; - a.stableSort = function(a, f) { - var l = a.length, - p, - n; - for (n = 0; n < l; n++) a[n].safeI = n; - a.sort(function(a, n) { - p = f(a, n); - return 0 === p ? a.safeI - n.safeI : p; - }); - for (n = 0; n < l; n++) delete a[n].safeI; - }; - a.arrayMin = function(a) { - for (var f = a.length, l = a[0]; f--; ) a[f] < l && (l = a[f]); - return l; - }; - a.arrayMax = function(a) { - for (var f = a.length, l = a[0]; f--; ) a[f] > l && (l = a[f]); - return l; - }; - a.destroyObjectProperties = function(p, f) { - a.objectEach(p, function(a, r) { - a && a !== f && a.destroy && a.destroy(); - delete p[r]; - }); - }; - a.discardElement = function(p) { - var f = a.garbageBin; - f || (f = a.createElement('div')); - p && f.appendChild(p); - f.innerHTML = ''; - }; - a.correctFloat = function(a, f) { - return parseFloat(a.toPrecision(f || 14)); - }; - a.setAnimation = function(p, f) { - f.renderer.globalAnimation = a.pick(p, f.options.chart.animation, !0); - }; - a.animObject = function(p) { - return a.isObject(p) ? a.merge(p) : { duration: p ? 500 : 0 }; - }; - a.timeUnits = { - millisecond: 1, - second: 1e3, - minute: 6e4, - hour: 36e5, - day: 864e5, - week: 6048e5, - month: 24192e5, - year: 314496e5, - }; - a.numberFormat = function(p, f, l, r) { - p = +p || 0; - f = +f; - var n = a.defaultOptions.lang, - w = (p.toString().split('.')[1] || '').split('e')[0].length, - u, - e, - h = p.toString().split('e'); - -1 === f - ? (f = Math.min(w, 20)) - : a.isNumber(f) - ? f && - h[1] && - 0 > h[1] && - ((u = f + +h[1]), - 0 <= u - ? ((h[0] = (+h[0]).toExponential(u).split('e')[0]), (f = u)) - : ((h[0] = h[0].split('.')[0] || 0), - (p = 20 > f ? (h[0] * Math.pow(10, h[1])).toFixed(f) : 0), - (h[1] = 0))) - : (f = 2); - e = ( - Math.abs(h[1] ? h[0] : p) + Math.pow(10, -Math.max(f, w) - 1) - ).toFixed(f); - w = String(a.pInt(e)); - u = 3 < w.length ? w.length % 3 : 0; - l = a.pick(l, n.decimalPoint); - r = a.pick(r, n.thousandsSep); - p = (0 > p ? '-' : '') + (u ? w.substr(0, u) + r : ''); - p += w.substr(u).replace(/(\d{3})(?=\d)/g, '$1' + r); - f && (p += l + e.slice(-f)); - h[1] && 0 !== +p && (p += 'e' + h[1]); - return p; - }; - Math.easeInOutSine = function(a) { - return -0.5 * (Math.cos(Math.PI * a) - 1); - }; - a.getStyle = function(p, f, l) { - if ('width' === f) - return ( - Math.min(p.offsetWidth, p.scrollWidth) - - a.getStyle(p, 'padding-left') - - a.getStyle(p, 'padding-right') - ); - if ('height' === f) - return ( - Math.min(p.offsetHeight, p.scrollHeight) - - a.getStyle(p, 'padding-top') - - a.getStyle(p, 'padding-bottom') - ); - H.getComputedStyle || a.error(27, !0); - if ((p = H.getComputedStyle(p, void 0))) - (p = p.getPropertyValue(f)), - a.pick(l, 'opacity' !== f) && (p = a.pInt(p)); - return p; - }; - a.inArray = function(p, f) { - return (a.indexOfPolyfill || Array.prototype.indexOf).call(f, p); - }; - a.grep = function(p, f) { - return (a.filterPolyfill || Array.prototype.filter).call(p, f); - }; - a.find = Array.prototype.find - ? function(a, f) { - return a.find(f); - } - : function(a, f) { - var l, - r = a.length; - for (l = 0; l < r; l++) if (f(a[l], l)) return a[l]; - }; - a.map = function(a, f) { - for (var l = [], r = 0, n = a.length; r < n; r++) - l[r] = f.call(a[r], a[r], r, a); - return l; - }; - a.keys = function(p) { - return (a.keysPolyfill || Object.keys).call(void 0, p); - }; - a.reduce = function(p, f, l) { - return (a.reducePolyfill || Array.prototype.reduce).call(p, f, l); - }; - a.offset = function(a) { - var f = D.documentElement; - a = a.parentElement ? a.getBoundingClientRect() : { top: 0, left: 0 }; - return { - top: a.top + (H.pageYOffset || f.scrollTop) - (f.clientTop || 0), - left: a.left + (H.pageXOffset || f.scrollLeft) - (f.clientLeft || 0), - }; - }; - a.stop = function(p, f) { - for (var l = a.timers.length; l--; ) - a.timers[l].elem !== p || - (f && f !== a.timers[l].prop) || - (a.timers[l].stopped = !0); - }; - a.each = function(p, f, l) { - return (a.forEachPolyfill || Array.prototype.forEach).call(p, f, l); - }; - a.objectEach = function(a, f, l) { - for (var r in a) a.hasOwnProperty(r) && f.call(l, a[r], r, a); - }; - a.addEvent = function(p, f, l) { - var r, - n, - w = p.addEventListener || a.addEventListenerPolyfill; - p.hcEvents && - !Object.prototype.hasOwnProperty.call(p, 'hcEvents') && - ((n = {}), - a.objectEach(p.hcEvents, function(a, e) { - n[e] = a.slice(0); - }), - (p.hcEvents = n)); - r = p.hcEvents = p.hcEvents || {}; - w && w.call(p, f, l, !1); - r[f] || (r[f] = []); - r[f].push(l); - return function() { - a.removeEvent(p, f, l); - }; - }; - a.removeEvent = function(p, f, l) { - function r(e, m) { - var d = p.removeEventListener || a.removeEventListenerPolyfill; - d && d.call(p, e, m, !1); - } - function n() { - var e, m; - p.nodeName && - (f ? ((e = {}), (e[f] = !0)) : (e = u), - a.objectEach(e, function(a, c) { - if (u[c]) for (m = u[c].length; m--; ) r(c, u[c][m]); - })); - } - var w, - u = p.hcEvents, - e; - u && - (f - ? ((w = u[f] || []), - l - ? ((e = a.inArray(l, w)), - -1 < e && (w.splice(e, 1), (u[f] = w)), - r(f, l)) - : (n(), (u[f] = []))) - : (n(), (p.hcEvents = {}))); - }; - a.fireEvent = function(p, f, l, r) { - var n; - n = p.hcEvents; - var w, u; - l = l || {}; - if (D.createEvent && (p.dispatchEvent || p.fireEvent)) - (n = D.createEvent('Events')), - n.initEvent(f, !0, !0), - a.extend(n, l), - p.dispatchEvent ? p.dispatchEvent(n) : p.fireEvent(f, n); - else if (n) - for ( - n = n[f] || [], - w = n.length, - l.target || - a.extend(l, { - preventDefault: function() { - l.defaultPrevented = !0; - }, - target: p, - type: f, - }), - f = 0; - f < w; - f++ - ) - (u = n[f]) && !1 === u.call(p, l) && l.preventDefault(); - r && !l.defaultPrevented && r(l); - }; - a.animate = function(p, f, l) { - var r, - n = '', - w, - u, - e; - a.isObject(l) || - ((e = arguments), - (l = { duration: e[2], easing: e[3], complete: e[4] })); - a.isNumber(l.duration) || (l.duration = 400); - l.easing = - 'function' === typeof l.easing - ? l.easing - : Math[l.easing] || Math.easeInOutSine; - l.curAnim = a.merge(f); - a.objectEach(f, function(e, m) { - a.stop(p, m); - u = new a.Fx(p, l, m); - w = null; - 'd' === m - ? ((u.paths = u.initPath(p, p.d, f.d)), - (u.toD = f.d), - (r = 0), - (w = 1)) - : p.attr - ? (r = p.attr(m)) - : ((r = parseFloat(a.getStyle(p, m)) || 0), - 'opacity' !== m && (n = 'px')); - w || (w = e); - w && w.match && w.match('px') && (w = w.replace(/px/g, '')); - u.run(r, w, n); - }); - }; - a.seriesType = function(p, f, l, r, n) { - var w = a.getOptions(), - u = a.seriesTypes; - w.plotOptions[p] = a.merge(w.plotOptions[f], l); - u[p] = a.extendClass(u[f] || function() {}, r); - u[p].prototype.type = p; - n && (u[p].prototype.pointClass = a.extendClass(a.Point, n)); - return u[p]; - }; - a.uniqueKey = (function() { - var a = Math.random() - .toString(36) - .substring(2, 9), - f = 0; - return function() { - return 'highcharts-' + a + '-' + f++; - }; - })(); - H.jQuery && - (H.jQuery.fn.highcharts = function() { - var p = [].slice.call(arguments); - if (this[0]) - return p[0] - ? (new a[a.isString(p[0]) ? p.shift() : 'Chart']( - this[0], - p[0], - p[1], - ), - this) - : E[a.attr(this[0], 'data-highcharts-chart')]; - }); - })(M); - (function(a) { - var E = a.each, - D = a.isNumber, - H = a.map, - p = a.merge, - f = a.pInt; - a.Color = function(l) { - if (!(this instanceof a.Color)) return new a.Color(l); - this.init(l); - }; - a.Color.prototype = { - parsers: [ - { - regex: /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/, - parse: function(a) { - return [f(a[1]), f(a[2]), f(a[3]), parseFloat(a[4], 10)]; - }, - }, - { - regex: /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/, - parse: function(a) { - return [f(a[1]), f(a[2]), f(a[3]), 1]; - }, - }, - ], - names: { - none: 'rgba(255,255,255,0)', - white: '#ffffff', - black: '#000000', - }, - init: function(l) { - var f, n, w, u; - if ( - (this.input = l = - this.names[l && l.toLowerCase ? l.toLowerCase() : ''] || l) && - l.stops - ) - this.stops = H(l.stops, function(e) { - return new a.Color(e[1]); - }); - else if ( - (l && - l.charAt && - '#' === l.charAt() && - ((f = l.length), - (l = parseInt(l.substr(1), 16)), - 7 === f - ? (n = [(l & 16711680) >> 16, (l & 65280) >> 8, l & 255, 1]) - : 4 === f && - (n = [ - ((l & 3840) >> 4) | ((l & 3840) >> 8), - ((l & 240) >> 4) | (l & 240), - ((l & 15) << 4) | (l & 15), - 1, - ])), - !n) - ) - for (w = this.parsers.length; w-- && !n; ) - (u = this.parsers[w]), (f = u.regex.exec(l)) && (n = u.parse(f)); - this.rgba = n || []; - }, - get: function(a) { - var f = this.input, - n = this.rgba, - l; - this.stops - ? ((l = p(f)), - (l.stops = [].concat(l.stops)), - E(this.stops, function(n, e) { - l.stops[e] = [l.stops[e][0], n.get(a)]; - })) - : (l = - n && D(n[0]) - ? 'rgb' === a || (!a && 1 === n[3]) - ? 'rgb(' + n[0] + ',' + n[1] + ',' + n[2] + ')' - : 'a' === a - ? n[3] - : 'rgba(' + n.join(',') + ')' - : f); - return l; - }, - brighten: function(a) { - var l, - n = this.rgba; - if (this.stops) - E(this.stops, function(n) { - n.brighten(a); - }); - else if (D(a) && 0 !== a) - for (l = 0; 3 > l; l++) - (n[l] += f(255 * a)), - 0 > n[l] && (n[l] = 0), - 255 < n[l] && (n[l] = 255); - return this; - }, - setOpacity: function(a) { - this.rgba[3] = a; - return this; - }, - tweenTo: function(a, f) { - var n = this.rgba, - l = a.rgba; - l.length && n && n.length - ? ((a = 1 !== l[3] || 1 !== n[3]), - (f = - (a ? 'rgba(' : 'rgb(') + - Math.round(l[0] + (n[0] - l[0]) * (1 - f)) + - ',' + - Math.round(l[1] + (n[1] - l[1]) * (1 - f)) + - ',' + - Math.round(l[2] + (n[2] - l[2]) * (1 - f)) + - (a ? ',' + (l[3] + (n[3] - l[3]) * (1 - f)) : '') + - ')')) - : (f = a.input || 'none'); - return f; - }, - }; - a.color = function(l) { - return new a.Color(l); - }; - })(M); - (function(a) { - var E, - D, - H = a.addEvent, - p = a.animate, - f = a.attr, - l = a.charts, - r = a.color, - n = a.css, - w = a.createElement, - u = a.defined, - e = a.deg2rad, - h = a.destroyObjectProperties, - m = a.doc, - d = a.each, - c = a.extend, - b = a.erase, - k = a.grep, - z = a.hasTouch, - B = a.inArray, - I = a.isArray, - x = a.isFirefox, - K = a.isMS, - t = a.isObject, - C = a.isString, - N = a.isWebKit, - q = a.merge, - A = a.noop, - F = a.objectEach, - G = a.pick, - g = a.pInt, - v = a.removeEvent, - Q = a.stop, - L = a.svg, - P = a.SVG_NS, - J = a.symbolSizes, - R = a.win; - E = a.SVGElement = function() { - return this; - }; - c(E.prototype, { - opacity: 1, - SVG_NS: P, - textProps: 'direction fontSize fontWeight fontFamily fontStyle color lineHeight width textAlign textDecoration textOverflow textOutline'.split( - ' ', - ), - init: function(a, g) { - this.element = 'span' === g ? w(g) : m.createElementNS(this.SVG_NS, g); - this.renderer = a; - }, - animate: function(y, g, b) { - g = a.animObject(G(g, this.renderer.globalAnimation, !0)); - 0 !== g.duration - ? (b && (g.complete = b), p(this, y, g)) - : (this.attr(y, null, b), g.step && g.step.call(this)); - return this; - }, - colorGradient: function(y, g, b) { - var v = this.renderer, - c, - O, - k, - e, - z, - h, - m, - L, - A, - J, - t = [], - x; - y.radialGradient - ? (O = 'radialGradient') - : y.linearGradient && (O = 'linearGradient'); - O && - ((k = y[O]), - (z = v.gradients), - (m = y.stops), - (J = b.radialReference), - I(k) && - (y[O] = k = { - x1: k[0], - y1: k[1], - x2: k[2], - y2: k[3], - gradientUnits: 'userSpaceOnUse', - }), - 'radialGradient' === O && - J && - !u(k.gradientUnits) && - ((e = k), - (k = q(k, v.getRadialAttr(J, e), { - gradientUnits: 'userSpaceOnUse', - }))), - F(k, function(a, y) { - 'id' !== y && t.push(y, a); - }), - F(m, function(a) { - t.push(a); - }), - (t = t.join(',')), - z[t] - ? (J = z[t].attr('id')) - : ((k.id = J = a.uniqueKey()), - (z[t] = h = v - .createElement(O) - .attr(k) - .add(v.defs)), - (h.radAttr = e), - (h.stops = []), - d(m, function(y) { - 0 === y[1].indexOf('rgba') - ? ((c = a.color(y[1])), (L = c.get('rgb')), (A = c.get('a'))) - : ((L = y[1]), (A = 1)); - y = v - .createElement('stop') - .attr({ offset: y[0], 'stop-color': L, 'stop-opacity': A }) - .add(h); - h.stops.push(y); - })), - (x = 'url(' + v.url + '#' + J + ')'), - b.setAttribute(g, x), - (b.gradient = t), - (y.toString = function() { - return x; - })); - }, - applyTextOutline: function(y) { - var g = this.element, - v, - c, - k, - q, - e; - -1 !== y.indexOf('contrast') && - (y = y.replace(/contrast/g, this.renderer.getContrast(g.style.fill))); - y = y.split(' '); - c = y[y.length - 1]; - if ((k = y[0]) && 'none' !== k && a.svg) { - this.fakeTS = !0; - y = [].slice.call(g.getElementsByTagName('tspan')); - this.ySetter = this.xSetter; - k = k.replace(/(^[\d\.]+)(.*?)$/g, function(a, y, g) { - return 2 * y + g; - }); - for (e = y.length; e--; ) - (v = y[e]), - 'highcharts-text-outline' === v.getAttribute('class') && - b(y, g.removeChild(v)); - q = g.firstChild; - d(y, function(a, y) { - 0 === y && - (a.setAttribute('x', g.getAttribute('x')), - (y = g.getAttribute('y')), - a.setAttribute('y', y || 0), - null === y && g.setAttribute('y', 0)); - a = a.cloneNode(1); - f(a, { - class: 'highcharts-text-outline', - fill: c, - stroke: c, - 'stroke-width': k, - 'stroke-linejoin': 'round', - }); - g.insertBefore(a, q); - }); - } - }, - attr: function(a, g, b, v) { - var y, - c = this.element, - k, - d = this, - O, - q; - 'string' === typeof a && - void 0 !== g && - ((y = a), (a = {}), (a[y] = g)); - 'string' === typeof a - ? (d = (this[a + 'Getter'] || this._defaultGetter).call(this, a, c)) - : (F( - a, - function(y, g) { - O = !1; - v || Q(this, g); - this.symbolName && - /^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)$/.test( - g, - ) && - (k || (this.symbolAttr(a), (k = !0)), (O = !0)); - !this.rotation || - ('x' !== g && 'y' !== g) || - (this.doTransform = !0); - O || - ((q = this[g + 'Setter'] || this._defaultSetter), - q.call(this, y, g, c), - this.shadows && - /^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test( - g, - ) && - this.updateShadows(g, y, q)); - }, - this, - ), - this.afterSetters()); - b && b(); - return d; - }, - afterSetters: function() { - this.doTransform && (this.updateTransform(), (this.doTransform = !1)); - }, - updateShadows: function(a, g, b) { - for (var y = this.shadows, v = y.length; v--; ) - b.call( - y[v], - 'height' === a - ? Math.max(g - (y[v].cutHeight || 0), 0) - : 'd' === a - ? this.d - : g, - a, - y[v], - ); - }, - addClass: function(a, g) { - var y = this.attr('class') || ''; - -1 === y.indexOf(a) && - (g || (a = (y + (y ? ' ' : '') + a).replace(' ', ' ')), - this.attr('class', a)); - return this; - }, - hasClass: function(a) { - return -1 !== B(a, (this.attr('class') || '').split(' ')); - }, - removeClass: function(a) { - return this.attr('class', (this.attr('class') || '').replace(a, '')); - }, - symbolAttr: function(a) { - var y = this; - d( - 'x y r start end width height innerR anchorX anchorY'.split(' '), - function(g) { - y[g] = G(a[g], y[g]); - }, - ); - y.attr({ - d: y.renderer.symbols[y.symbolName](y.x, y.y, y.width, y.height, y), - }); - }, - clip: function(a) { - return this.attr( - 'clip-path', - a ? 'url(' + this.renderer.url + '#' + a.id + ')' : 'none', - ); - }, - crisp: function(a, g) { - var y; - g = g || a.strokeWidth || 0; - y = (Math.round(g) % 2) / 2; - a.x = Math.floor(a.x || this.x || 0) + y; - a.y = Math.floor(a.y || this.y || 0) + y; - a.width = Math.floor((a.width || this.width || 0) - 2 * y); - a.height = Math.floor((a.height || this.height || 0) - 2 * y); - u(a.strokeWidth) && (a.strokeWidth = g); - return a; - }, - css: function(a) { - var y = this.styles, - b = {}, - v = this.element, - k, - d = '', - q, - e = !y, - z = ['textOutline', 'textOverflow', 'width']; - a && a.color && (a.fill = a.color); - y && - F(a, function(a, g) { - a !== y[g] && ((b[g] = a), (e = !0)); - }); - e && - (y && (a = c(y, b)), - (k = this.textWidth = - a && - a.width && - 'auto' !== a.width && - 'text' === v.nodeName.toLowerCase() && - g(a.width)), - (this.styles = a), - k && !L && this.renderer.forExport && delete a.width, - K && !L - ? n(this.element, a) - : ((q = function(a, y) { - return '-' + y.toLowerCase(); - }), - F(a, function(a, y) { - -1 === B(y, z) && - (d += y.replace(/([A-Z])/g, q) + ':' + a + ';'); - }), - d && f(v, 'style', d)), - this.added && - ('text' === this.element.nodeName && this.renderer.buildText(this), - a && a.textOutline && this.applyTextOutline(a.textOutline))); - return this; - }, - strokeWidth: function() { - return this['stroke-width'] || 0; - }, - on: function(a, g) { - var y = this, - b = y.element; - z && 'click' === a - ? ((b.ontouchstart = function(a) { - y.touchEventFired = Date.now(); - a.preventDefault(); - g.call(b, a); - }), - (b.onclick = function(a) { - (-1 === R.navigator.userAgent.indexOf('Android') || - 1100 < Date.now() - (y.touchEventFired || 0)) && - g.call(b, a); - })) - : (b['on' + a] = g); - return this; - }, - setRadialReference: function(a) { - var y = this.renderer.gradients[this.element.gradient]; - this.element.radialReference = a; - y && y.radAttr && y.animate(this.renderer.getRadialAttr(a, y.radAttr)); - return this; - }, - translate: function(a, g) { - return this.attr({ translateX: a, translateY: g }); - }, - invert: function(a) { - this.inverted = a; - this.updateTransform(); - return this; - }, - updateTransform: function() { - var a = this.translateX || 0, - g = this.translateY || 0, - b = this.scaleX, - v = this.scaleY, - c = this.inverted, - k = this.rotation, - d = this.matrix, - q = this.element; - c && ((a += this.width), (g += this.height)); - a = ['translate(' + a + ',' + g + ')']; - u(d) && a.push('matrix(' + d.join(',') + ')'); - c - ? a.push('rotate(90) scale(-1,1)') - : k && - a.push( - 'rotate(' + - k + - ' ' + - G(this.rotationOriginX, q.getAttribute('x'), 0) + - ' ' + - G(this.rotationOriginY, q.getAttribute('y') || 0) + - ')', - ); - (u(b) || u(v)) && a.push('scale(' + G(b, 1) + ' ' + G(v, 1) + ')'); - a.length && q.setAttribute('transform', a.join(' ')); - }, - toFront: function() { - var a = this.element; - a.parentNode.appendChild(a); - return this; - }, - align: function(a, g, v) { - var y, - c, - k, - d, - q = {}; - c = this.renderer; - k = c.alignedObjects; - var e, O; - if (a) { - if ( - ((this.alignOptions = a), (this.alignByTranslate = g), !v || C(v)) - ) - (this.alignTo = y = v || 'renderer'), - b(k, this), - k.push(this), - (v = null); - } else - (a = this.alignOptions), - (g = this.alignByTranslate), - (y = this.alignTo); - v = G(v, c[y], c); - y = a.align; - c = a.verticalAlign; - k = (v.x || 0) + (a.x || 0); - d = (v.y || 0) + (a.y || 0); - 'right' === y ? (e = 1) : 'center' === y && (e = 2); - e && (k += (v.width - (a.width || 0)) / e); - q[g ? 'translateX' : 'x'] = Math.round(k); - 'bottom' === c ? (O = 1) : 'middle' === c && (O = 2); - O && (d += (v.height - (a.height || 0)) / O); - q[g ? 'translateY' : 'y'] = Math.round(d); - this[this.placed ? 'animate' : 'attr'](q); - this.placed = !0; - this.alignAttr = q; - return this; - }, - getBBox: function(a, g) { - var y, - b = this.renderer, - v, - k = this.element, - q = this.styles, - O, - z = this.textStr, - h, - m = b.cache, - L = b.cacheKeys, - A; - g = G(g, this.rotation); - v = g * e; - O = q && q.fontSize; - u(z) && - ((A = z.toString()), - -1 === A.indexOf('\x3c') && (A = A.replace(/[0-9]/g, '0')), - (A += ['', g || 0, O, q && q.width, q && q.textOverflow].join())); - A && !a && (y = m[A]); - if (!y) { - if (k.namespaceURI === this.SVG_NS || b.forExport) { - try { - (h = - this.fakeTS && - function(a) { - d(k.querySelectorAll('.highcharts-text-outline'), function( - y, - ) { - y.style.display = a; - }); - }) && h('none'), - (y = k.getBBox - ? c({}, k.getBBox()) - : { width: k.offsetWidth, height: k.offsetHeight }), - h && h(''); - } catch (W) {} - if (!y || 0 > y.width) y = { width: 0, height: 0 }; - } else y = this.htmlGetBBox(); - b.isSVG && - ((a = y.width), - (b = y.height), - q && - '11px' === q.fontSize && - 17 === Math.round(b) && - (y.height = b = 14), - g && - ((y.width = - Math.abs(b * Math.sin(v)) + Math.abs(a * Math.cos(v))), - (y.height = - Math.abs(b * Math.cos(v)) + Math.abs(a * Math.sin(v))))); - if (A && 0 < y.height) { - for (; 250 < L.length; ) delete m[L.shift()]; - m[A] || L.push(A); - m[A] = y; - } - } - return y; - }, - show: function(a) { - return this.attr({ visibility: a ? 'inherit' : 'visible' }); - }, - hide: function() { - return this.attr({ visibility: 'hidden' }); - }, - fadeOut: function(a) { - var y = this; - y.animate( - { opacity: 0 }, - { - duration: a || 150, - complete: function() { - y.attr({ y: -9999 }); - }, - }, - ); - }, - add: function(a) { - var y = this.renderer, - g = this.element, - b; - a && (this.parentGroup = a); - this.parentInverted = a && a.inverted; - void 0 !== this.textStr && y.buildText(this); - this.added = !0; - if (!a || a.handleZ || this.zIndex) b = this.zIndexSetter(); - b || (a ? a.element : y.box).appendChild(g); - if (this.onAdd) this.onAdd(); - return this; - }, - safeRemoveChild: function(a) { - var y = a.parentNode; - y && y.removeChild(a); - }, - destroy: function() { - var a = this, - g = a.element || {}, - v = a.renderer.isSVG && 'SPAN' === g.nodeName && a.parentGroup, - c = g.ownerSVGElement; - g.onclick = g.onmouseout = g.onmouseover = g.onmousemove = g.point = null; - Q(a); - a.clipPath && - c && - (d(c.querySelectorAll('[clip-path],[CLIP-PATH]'), function(g) { - g - .getAttribute('clip-path') - .match(RegExp('[("]#' + a.clipPath.element.id + '[)"]')) && - g.removeAttribute('clip-path'); - }), - (a.clipPath = a.clipPath.destroy())); - if (a.stops) { - for (c = 0; c < a.stops.length; c++) - a.stops[c] = a.stops[c].destroy(); - a.stops = null; - } - a.safeRemoveChild(g); - for (a.destroyShadows(); v && v.div && 0 === v.div.childNodes.length; ) - (g = v.parentGroup), a.safeRemoveChild(v.div), delete v.div, (v = g); - a.alignTo && b(a.renderer.alignedObjects, a); - F(a, function(g, y) { - delete a[y]; - }); - return null; - }, - shadow: function(a, g, b) { - var y = [], - v, - c, - k = this.element, - d, - q, - e, - z; - if (!a) this.destroyShadows(); - else if (!this.shadows) { - q = G(a.width, 3); - e = (a.opacity || 0.15) / q; - z = this.parentInverted - ? '(-1,-1)' - : '(' + G(a.offsetX, 1) + ', ' + G(a.offsetY, 1) + ')'; - for (v = 1; v <= q; v++) - (c = k.cloneNode(0)), - (d = 2 * q + 1 - 2 * v), - f(c, { - isShadow: 'true', - stroke: a.color || '#000000', - 'stroke-opacity': e * v, - 'stroke-width': d, - transform: 'translate' + z, - fill: 'none', - }), - b && - (f(c, 'height', Math.max(f(c, 'height') - d, 0)), - (c.cutHeight = d)), - g - ? g.element.appendChild(c) - : k.parentNode && k.parentNode.insertBefore(c, k), - y.push(c); - this.shadows = y; - } - return this; - }, - destroyShadows: function() { - d( - this.shadows || [], - function(a) { - this.safeRemoveChild(a); - }, - this, - ); - this.shadows = void 0; - }, - xGetter: function(a) { - 'circle' === this.element.nodeName && - ('x' === a ? (a = 'cx') : 'y' === a && (a = 'cy')); - return this._defaultGetter(a); - }, - _defaultGetter: function(a) { - a = G( - this[a + 'Value'], - this[a], - this.element ? this.element.getAttribute(a) : null, - 0, - ); - /^[\-0-9\.]+$/.test(a) && (a = parseFloat(a)); - return a; - }, - dSetter: function(a, g, b) { - a && a.join && (a = a.join(' ')); - /(NaN| {2}|^$)/.test(a) && (a = 'M 0 0'); - this[g] !== a && (b.setAttribute(g, a), (this[g] = a)); - }, - dashstyleSetter: function(a) { - var b, - v = this['stroke-width']; - 'inherit' === v && (v = 1); - if ((a = a && a.toLowerCase())) { - a = a - .replace('shortdashdotdot', '3,1,1,1,1,1,') - .replace('shortdashdot', '3,1,1,1') - .replace('shortdot', '1,1,') - .replace('shortdash', '3,1,') - .replace('longdash', '8,3,') - .replace(/dot/g, '1,3,') - .replace('dash', '4,3,') - .replace(/,$/, '') - .split(','); - for (b = a.length; b--; ) a[b] = g(a[b]) * v; - a = a.join(',').replace(/NaN/g, 'none'); - this.element.setAttribute('stroke-dasharray', a); - } - }, - alignSetter: function(a) { - this.alignValue = a; - this.element.setAttribute( - 'text-anchor', - { left: 'start', center: 'middle', right: 'end' }[a], - ); - }, - opacitySetter: function(a, g, b) { - this[g] = a; - b.setAttribute(g, a); - }, - titleSetter: function(a) { - var g = this.element.getElementsByTagName('title')[0]; - g || - ((g = m.createElementNS(this.SVG_NS, 'title')), - this.element.appendChild(g)); - g.firstChild && g.removeChild(g.firstChild); - g.appendChild( - m.createTextNode(String(G(a), '').replace(/<[^>]*>/g, '')), - ); - }, - textSetter: function(a) { - a !== this.textStr && - (delete this.bBox, - (this.textStr = a), - this.added && this.renderer.buildText(this)); - }, - fillSetter: function(a, g, b) { - 'string' === typeof a - ? b.setAttribute(g, a) - : a && this.colorGradient(a, g, b); - }, - visibilitySetter: function(a, g, b) { - 'inherit' === a - ? b.removeAttribute(g) - : this[g] !== a && b.setAttribute(g, a); - this[g] = a; - }, - zIndexSetter: function(a, b) { - var v = this.renderer, - y = this.parentGroup, - c = (y || v).element || v.box, - k, - d = this.element, - q, - e, - v = c === v.box; - k = this.added; - var z; - u(a) && - ((d.zIndex = a), (a = +a), this[b] === a && (k = !1), (this[b] = a)); - if (k) { - (a = this.zIndex) && y && (y.handleZ = !0); - b = c.childNodes; - for (z = b.length - 1; 0 <= z && !q; z--) - if (((y = b[z]), (k = y.zIndex), (e = !u(k)), y !== d)) - if (0 > a && e && !v && !z) c.insertBefore(d, b[z]), (q = !0); - else if (g(k) <= a || (e && (!u(a) || 0 <= a))) - c.insertBefore(d, b[z + 1] || null), (q = !0); - q || (c.insertBefore(d, b[v ? 3 : 0] || null), (q = !0)); - } - return q; - }, - _defaultSetter: function(a, g, b) { - b.setAttribute(g, a); - }, - }); - E.prototype.yGetter = E.prototype.xGetter; - E.prototype.translateXSetter = E.prototype.translateYSetter = E.prototype.rotationSetter = E.prototype.verticalAlignSetter = E.prototype.rotationOriginXSetter = E.prototype.rotationOriginYSetter = E.prototype.scaleXSetter = E.prototype.scaleYSetter = E.prototype.matrixSetter = function( - a, - g, - ) { - this[g] = a; - this.doTransform = !0; - }; - E.prototype['stroke-widthSetter'] = E.prototype.strokeSetter = function( - a, - g, - b, - ) { - this[g] = a; - this.stroke && this['stroke-width'] - ? (E.prototype.fillSetter.call(this, this.stroke, 'stroke', b), - b.setAttribute('stroke-width', this['stroke-width']), - (this.hasStroke = !0)) - : 'stroke-width' === g && - 0 === a && - this.hasStroke && - (b.removeAttribute('stroke'), (this.hasStroke = !1)); - }; - D = a.SVGRenderer = function() { - this.init.apply(this, arguments); - }; - c(D.prototype, { - Element: E, - SVG_NS: P, - init: function(a, g, b, v, c, k) { - var y; - v = this.createElement('svg') - .attr({ version: '1.1', class: 'highcharts-root' }) - .css(this.getStyle(v)); - y = v.element; - a.appendChild(y); - f(a, 'dir', 'ltr'); - -1 === a.innerHTML.indexOf('xmlns') && f(y, 'xmlns', this.SVG_NS); - this.isSVG = !0; - this.box = y; - this.boxWrapper = v; - this.alignedObjects = []; - this.url = - (x || N) && m.getElementsByTagName('base').length - ? R.location.href - .replace(/#.*?$/, '') - .replace(/<[^>]*>/g, '') - .replace(/([\('\)])/g, '\\$1') - .replace(/ /g, '%20') - : ''; - this.createElement('desc') - .add() - .element.appendChild( - m.createTextNode('Created with Highcharts 6.0.4'), - ); - this.defs = this.createElement('defs').add(); - this.allowHTML = k; - this.forExport = c; - this.gradients = {}; - this.cache = {}; - this.cacheKeys = []; - this.imgCount = 0; - this.setSize(g, b, !1); - var d; - x && - a.getBoundingClientRect && - ((g = function() { - n(a, { left: 0, top: 0 }); - d = a.getBoundingClientRect(); - n(a, { - left: Math.ceil(d.left) - d.left + 'px', - top: Math.ceil(d.top) - d.top + 'px', - }); - }), - g(), - (this.unSubPixelFix = H(R, 'resize', g))); - }, - getStyle: function(a) { - return (this.style = c( - { - fontFamily: - '"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif', - fontSize: '12px', - }, - a, - )); - }, - setStyle: function(a) { - this.boxWrapper.css(this.getStyle(a)); - }, - isHidden: function() { - return !this.boxWrapper.getBBox().width; - }, - destroy: function() { - var a = this.defs; - this.box = null; - this.boxWrapper = this.boxWrapper.destroy(); - h(this.gradients || {}); - this.gradients = null; - a && (this.defs = a.destroy()); - this.unSubPixelFix && this.unSubPixelFix(); - return (this.alignedObjects = null); - }, - createElement: function(a) { - var g = new this.Element(); - g.init(this, a); - return g; - }, - draw: A, - getRadialAttr: function(a, g) { - return { - cx: a[0] - a[2] / 2 + g.cx * a[2], - cy: a[1] - a[2] / 2 + g.cy * a[2], - r: g.r * a[2], - }; - }, - getSpanWidth: function(a, g) { - var b = a.getBBox(!0).width; - !L && - this.forExport && - (b = this.measureSpanWidth(g.firstChild.data, a.styles)); - return b; - }, - applyEllipsis: function(a, g, b, v) { - var c = a.rotation, - y = b, - k, - d = 0, - q = b.length, - e = function(a) { - g.removeChild(g.firstChild); - a && g.appendChild(m.createTextNode(a)); - }, - z; - a.rotation = 0; - y = this.getSpanWidth(a, g); - if ((z = y > v)) { - for (; d <= q; ) - (k = Math.ceil((d + q) / 2)), - (y = b.substring(0, k) + '\u2026'), - e(y), - (y = this.getSpanWidth(a, g)), - d === q ? (d = q + 1) : y > v ? (q = k - 1) : (d = k); - 0 === q && e(''); - } - a.rotation = c; - return z; - }, - escapes: { - '\x26': '\x26amp;', - '\x3c': '\x26lt;', - '\x3e': '\x26gt;', - "'": '\x26#39;', - '"': '\x26quot;', - }, - buildText: function(a) { - var b = a.element, - v = this, - c = v.forExport, - y = G(a.textStr, '').toString(), - q = -1 !== y.indexOf('\x3c'), - e = b.childNodes, - z, - h, - A, - J, - t = f(b, 'x'), - x = a.styles, - B = a.textWidth, - l = x && x.lineHeight, - C = x && x.textOutline, - u = x && 'ellipsis' === x.textOverflow, - Q = x && 'nowrap' === x.whiteSpace, - w = x && x.fontSize, - R, - I, - r = e.length, - x = B && !a.added && this.box, - p = function(a) { - var c; - c = /(px|em)$/.test(a && a.style.fontSize) - ? a.style.fontSize - : w || v.style.fontSize || 12; - return l - ? g(l) - : v.fontMetrics(c, a.getAttribute('style') ? a : b).h; - }, - K = function(a) { - F(v.escapes, function(g, b) { - a = a.replace(new RegExp(g, 'g'), b); - }); - return a; - }; - R = [y, u, Q, l, C, w, B].join(); - if (R !== a.textCache) { - for (a.textCache = R; r--; ) b.removeChild(e[r]); - q || C || u || B || -1 !== y.indexOf(' ') - ? ((z = /<.*class="([^"]+)".*>/), - (h = /<.*style="([^"]+)".*>/), - (A = /<.*href="([^"]+)".*>/), - x && x.appendChild(b), - (y = q - ? y - .replace( - /<(b|strong)>/g, - '\x3cspan style\x3d"font-weight:bold"\x3e', - ) - .replace( - /<(i|em)>/g, - '\x3cspan style\x3d"font-style:italic"\x3e', - ) - .replace(//g, '\x3c/span\x3e') - .split(//g) - : [y]), - (y = k(y, function(a) { - return '' !== a; - })), - d(y, function(g, y) { - var k, - q = 0; - g = g - .replace(/^\s+|\s+$/g, '') - .replace(//g, '\x3c/span\x3e|||'); - k = g.split('|||'); - d(k, function(g) { - if ('' !== g || 1 === k.length) { - var d = {}, - e = m.createElementNS(v.SVG_NS, 'tspan'), - x, - F; - z.test(g) && ((x = g.match(z)[1]), f(e, 'class', x)); - h.test(g) && - ((F = g - .match(h)[1] - .replace(/(;| |^)color([ :])/, '$1fill$2')), - f(e, 'style', F)); - A.test(g) && - !c && - (f( - e, - 'onclick', - 'location.href\x3d"' + g.match(A)[1] + '"', - ), - f(e, 'class', 'highcharts-anchor'), - n(e, { cursor: 'pointer' })); - g = K(g.replace(/<[a-zA-Z\/](.|\n)*?>/g, '') || ' '); - if (' ' !== g) { - e.appendChild(m.createTextNode(g)); - q ? (d.dx = 0) : y && null !== t && (d.x = t); - f(e, d); - b.appendChild(e); - !q && - I && - (!L && c && n(e, { display: 'block' }), - f(e, 'dy', p(e))); - if (B) { - d = g.replace(/([^\^])-/g, '$1- ').split(' '); - x = 1 < k.length || y || (1 < d.length && !Q); - var O = [], - l, - C = p(e), - G = a.rotation; - for ( - u && (J = v.applyEllipsis(a, e, g, B)); - !u && x && (d.length || O.length); - - ) - (a.rotation = 0), - (l = v.getSpanWidth(a, e)), - (g = l > B), - void 0 === J && (J = g), - g && 1 !== d.length - ? (e.removeChild(e.firstChild), - O.unshift(d.pop())) - : ((d = O), - (O = []), - d.length && - !Q && - ((e = m.createElementNS(P, 'tspan')), - f(e, { dy: C, x: t }), - F && f(e, 'style', F), - b.appendChild(e)), - l > B && (B = l)), - d.length && - e.appendChild( - m.createTextNode( - d.join(' ').replace(/- /g, '-'), - ), - ); - a.rotation = G; - } - q++; - } - } - }); - I = I || b.childNodes.length; - }), - J && a.attr('title', a.textStr), - x && x.removeChild(b), - C && a.applyTextOutline && a.applyTextOutline(C)) - : b.appendChild(m.createTextNode(K(y))); - } - }, - getContrast: function(a) { - a = r(a).rgba; - return 510 < a[0] + a[1] + a[2] ? '#000000' : '#FFFFFF'; - }, - button: function(a, g, b, v, d, k, e, z, h) { - var y = this.label(a, g, b, h, null, null, null, null, 'button'), - m = 0; - y.attr(q({ padding: 8, r: 2 }, d)); - var A, L, J, t; - d = q( - { - fill: '#f7f7f7', - stroke: '#cccccc', - 'stroke-width': 1, - style: { - color: '#333333', - cursor: 'pointer', - fontWeight: 'normal', - }, - }, - d, - ); - A = d.style; - delete d.style; - k = q(d, { fill: '#e6e6e6' }, k); - L = k.style; - delete k.style; - e = q( - d, - { fill: '#e6ebf5', style: { color: '#000000', fontWeight: 'bold' } }, - e, - ); - J = e.style; - delete e.style; - z = q(d, { style: { color: '#cccccc' } }, z); - t = z.style; - delete z.style; - H(y.element, K ? 'mouseover' : 'mouseenter', function() { - 3 !== m && y.setState(1); - }); - H(y.element, K ? 'mouseout' : 'mouseleave', function() { - 3 !== m && y.setState(m); - }); - y.setState = function(a) { - 1 !== a && (y.state = m = a); - y.removeClass( - /highcharts-button-(normal|hover|pressed|disabled)/, - ).addClass( - 'highcharts-button-' + - ['normal', 'hover', 'pressed', 'disabled'][a || 0], - ); - y.attr([d, k, e, z][a || 0]).css([A, L, J, t][a || 0]); - }; - y.attr(d).css(c({ cursor: 'default' }, A)); - return y.on('click', function(a) { - 3 !== m && v.call(y, a); - }); - }, - crispLine: function(a, g) { - a[1] === a[4] && (a[1] = a[4] = Math.round(a[1]) - (g % 2) / 2); - a[2] === a[5] && (a[2] = a[5] = Math.round(a[2]) + (g % 2) / 2); - return a; - }, - path: function(a) { - var g = { fill: 'none' }; - I(a) ? (g.d = a) : t(a) && c(g, a); - return this.createElement('path').attr(g); - }, - circle: function(a, g, b) { - a = t(a) ? a : { x: a, y: g, r: b }; - g = this.createElement('circle'); - g.xSetter = g.ySetter = function(a, g, b) { - b.setAttribute('c' + g, a); - }; - return g.attr(a); - }, - arc: function(a, g, b, v, c, d) { - t(a) - ? ((v = a), (g = v.y), (b = v.r), (a = v.x)) - : (v = { innerR: v, start: c, end: d }); - a = this.symbol('arc', a, g, b, b, v); - a.r = b; - return a; - }, - rect: function(a, g, b, v, c, d) { - c = t(a) ? a.r : c; - var k = this.createElement('rect'); - a = t(a) - ? a - : void 0 === a - ? {} - : { x: a, y: g, width: Math.max(b, 0), height: Math.max(v, 0) }; - void 0 !== d && ((a.strokeWidth = d), (a = k.crisp(a))); - a.fill = 'none'; - c && (a.r = c); - k.rSetter = function(a, g, b) { - f(b, { rx: a, ry: a }); - }; - return k.attr(a); - }, - setSize: function(a, g, b) { - var v = this.alignedObjects, - c = v.length; - this.width = a; - this.height = g; - for ( - this.boxWrapper.animate( - { width: a, height: g }, - { - step: function() { - this.attr({ - viewBox: - '0 0 ' + this.attr('width') + ' ' + this.attr('height'), - }); - }, - duration: G(b, !0) ? void 0 : 0, - }, - ); - c--; - - ) - v[c].align(); - }, - g: function(a) { - var g = this.createElement('g'); - return a ? g.attr({ class: 'highcharts-' + a }) : g; - }, - image: function(a, g, b, v, d) { - var k = { preserveAspectRatio: 'none' }; - 1 < arguments.length && c(k, { x: g, y: b, width: v, height: d }); - k = this.createElement('image').attr(k); - k.element.setAttributeNS - ? k.element.setAttributeNS('http://www.w3.org/1999/xlink', 'href', a) - : k.element.setAttribute('hc-svg-href', a); - return k; - }, - symbol: function(a, g, b, v, k, q) { - var e = this, - y, - z = /^url\((.*?)\)$/, - h = z.test(a), - A = !h && (this.symbols[a] ? a : 'circle'), - L = A && this.symbols[A], - t = - u(g) && - L && - L.call(this.symbols, Math.round(g), Math.round(b), v, k, q), - x, - F; - L - ? ((y = this.path(t)), - y.attr('fill', 'none'), - c(y, { symbolName: A, x: g, y: b, width: v, height: k }), - q && c(y, q)) - : h && - ((x = a.match(z)[1]), - (y = this.image(x)), - (y.imgwidth = G(J[x] && J[x].width, q && q.width)), - (y.imgheight = G(J[x] && J[x].height, q && q.height)), - (F = function() { - y.attr({ width: y.width, height: y.height }); - }), - d(['width', 'height'], function(a) { - y[a + 'Setter'] = function(a, g) { - var b = {}, - v = this['img' + g], - c = 'width' === g ? 'translateX' : 'translateY'; - this[g] = a; - u(v) && - (this.element && this.element.setAttribute(g, v), - this.alignByTranslate || - ((b[c] = ((this[g] || 0) - v) / 2), this.attr(b))); - }; - }), - u(g) && y.attr({ x: g, y: b }), - (y.isImg = !0), - u(y.imgwidth) && u(y.imgheight) - ? F() - : (y.attr({ width: 0, height: 0 }), - w('img', { - onload: function() { - var a = l[e.chartIndex]; - 0 === this.width && - (n(this, { position: 'absolute', top: '-999em' }), - m.body.appendChild(this)); - J[x] = { width: this.width, height: this.height }; - y.imgwidth = this.width; - y.imgheight = this.height; - y.element && F(); - this.parentNode && this.parentNode.removeChild(this); - e.imgCount--; - if (!e.imgCount && a && a.onload) a.onload(); - }, - src: x, - }), - this.imgCount++)); - return y; - }, - symbols: { - circle: function(a, g, b, v) { - return this.arc(a + b / 2, g + v / 2, b / 2, v / 2, { - start: 0, - end: 2 * Math.PI, - open: !1, - }); - }, - square: function(a, g, b, v) { - return ['M', a, g, 'L', a + b, g, a + b, g + v, a, g + v, 'Z']; - }, - triangle: function(a, g, b, v) { - return ['M', a + b / 2, g, 'L', a + b, g + v, a, g + v, 'Z']; - }, - 'triangle-down': function(a, g, b, v) { - return ['M', a, g, 'L', a + b, g, a + b / 2, g + v, 'Z']; - }, - diamond: function(a, g, b, v) { - return [ - 'M', - a + b / 2, - g, - 'L', - a + b, - g + v / 2, - a + b / 2, - g + v, - a, - g + v / 2, - 'Z', - ]; - }, - arc: function(a, g, b, v, c) { - var k = c.start, - d = c.r || b, - q = c.r || v || b, - e = c.end - 0.001; - b = c.innerR; - v = G(c.open, 0.001 > Math.abs(c.end - c.start - 2 * Math.PI)); - var y = Math.cos(k), - z = Math.sin(k), - h = Math.cos(e), - e = Math.sin(e); - c = 0.001 > c.end - k - Math.PI ? 0 : 1; - d = [ - 'M', - a + d * y, - g + q * z, - 'A', - d, - q, - 0, - c, - 1, - a + d * h, - g + q * e, - ]; - u(b) && - d.push( - v ? 'M' : 'L', - a + b * h, - g + b * e, - 'A', - b, - b, - 0, - c, - 0, - a + b * y, - g + b * z, - ); - d.push(v ? '' : 'Z'); - return d; - }, - callout: function(a, g, b, v, c) { - var d = Math.min((c && c.r) || 0, b, v), - k = d + 6, - q = c && c.anchorX; - c = c && c.anchorY; - var e; - e = [ - 'M', - a + d, - g, - 'L', - a + b - d, - g, - 'C', - a + b, - g, - a + b, - g, - a + b, - g + d, - 'L', - a + b, - g + v - d, - 'C', - a + b, - g + v, - a + b, - g + v, - a + b - d, - g + v, - 'L', - a + d, - g + v, - 'C', - a, - g + v, - a, - g + v, - a, - g + v - d, - 'L', - a, - g + d, - 'C', - a, - g, - a, - g, - a + d, - g, - ]; - q && q > b - ? c > g + k && c < g + v - k - ? e.splice( - 13, - 3, - 'L', - a + b, - c - 6, - a + b + 6, - c, - a + b, - c + 6, - a + b, - g + v - d, - ) - : e.splice( - 13, - 3, - 'L', - a + b, - v / 2, - q, - c, - a + b, - v / 2, - a + b, - g + v - d, - ) - : q && 0 > q - ? c > g + k && c < g + v - k - ? e.splice(33, 3, 'L', a, c + 6, a - 6, c, a, c - 6, a, g + d) - : e.splice(33, 3, 'L', a, v / 2, q, c, a, v / 2, a, g + d) - : c && c > v && q > a + k && q < a + b - k - ? e.splice( - 23, - 3, - 'L', - q + 6, - g + v, - q, - g + v + 6, - q - 6, - g + v, - a + d, - g + v, - ) - : c && - 0 > c && - q > a + k && - q < a + b - k && - e.splice(3, 3, 'L', q - 6, g, q, g - 6, q + 6, g, b - d, g); - return e; - }, - }, - clipRect: function(g, b, v, c) { - var d = a.uniqueKey(), - k = this.createElement('clipPath') - .attr({ id: d }) - .add(this.defs); - g = this.rect(g, b, v, c, 0).add(k); - g.id = d; - g.clipPath = k; - g.count = 0; - return g; - }, - text: function(a, g, b, v) { - var c = {}; - if (v && (this.allowHTML || !this.forExport)) return this.html(a, g, b); - c.x = Math.round(g || 0); - b && (c.y = Math.round(b)); - if (a || 0 === a) c.text = a; - a = this.createElement('text').attr(c); - v || - (a.xSetter = function(a, g, b) { - var v = b.getElementsByTagName('tspan'), - c, - d = b.getAttribute(g), - k; - for (k = 0; k < v.length; k++) - (c = v[k]), c.getAttribute(g) === d && c.setAttribute(g, a); - b.setAttribute(g, a); - }); - return a; - }, - fontMetrics: function(a, b) { - a = - a || - (b && b.style && b.style.fontSize) || - (this.style && this.style.fontSize); - a = /px/.test(a) - ? g(a) - : /em/.test(a) - ? parseFloat(a) * (b ? this.fontMetrics(null, b.parentNode).f : 16) - : 12; - b = 24 > a ? a + 3 : Math.round(1.2 * a); - return { h: b, b: Math.round(0.8 * b), f: a }; - }, - rotCorr: function(a, g, b) { - var v = a; - g && b && (v = Math.max(v * Math.cos(g * e), 4)); - return { x: (-a / 3) * Math.sin(g * e), y: v }; - }, - label: function(g, b, k, e, z, h, m, A, L) { - var y = this, - J = y.g('button' !== L && 'label'), - t = (J.text = y.text('', 0, 0, m).attr({ zIndex: 1 })), - x, - F, - n = 0, - B = 3, - l = 0, - C, - f, - Q, - G, - w, - R = {}, - I, - P, - r = /^url\((.*?)\)$/.test(e), - p = r, - K, - O, - N, - T; - L && J.addClass('highcharts-' + L); - p = r; - K = function() { - return ((I || 0) % 2) / 2; - }; - O = function() { - var a = t.element.style, - g = {}; - F = - (void 0 === C || void 0 === f || w) && u(t.textStr) && t.getBBox(); - J.width = (C || F.width || 0) + 2 * B + l; - J.height = (f || F.height || 0) + 2 * B; - P = B + y.fontMetrics(a && a.fontSize, t).b; - p && - (x || - ((J.box = x = y.symbols[e] || r ? y.symbol(e) : y.rect()), - x.addClass( - ('button' === L ? '' : 'highcharts-label-box') + - (L ? ' highcharts-' + L + '-box' : ''), - ), - x.add(J), - (a = K()), - (g.x = a), - (g.y = (A ? -P : 0) + a)), - (g.width = Math.round(J.width)), - (g.height = Math.round(J.height)), - x.attr(c(g, R)), - (R = {})); - }; - N = function() { - var a = l + B, - g; - g = A ? 0 : P; - u(C) && - F && - ('center' === w || 'right' === w) && - (a += { center: 0.5, right: 1 }[w] * (C - F.width)); - if (a !== t.x || g !== t.y) - t.attr('x', a), void 0 !== g && t.attr('y', g); - t.x = a; - t.y = g; - }; - T = function(a, g) { - x ? x.attr(a, g) : (R[a] = g); - }; - J.onAdd = function() { - t.add(J); - J.attr({ text: g || 0 === g ? g : '', x: b, y: k }); - x && u(z) && J.attr({ anchorX: z, anchorY: h }); - }; - J.widthSetter = function(g) { - C = a.isNumber(g) ? g : null; - }; - J.heightSetter = function(a) { - f = a; - }; - J['text-alignSetter'] = function(a) { - w = a; - }; - J.paddingSetter = function(a) { - u(a) && a !== B && ((B = J.padding = a), N()); - }; - J.paddingLeftSetter = function(a) { - u(a) && a !== l && ((l = a), N()); - }; - J.alignSetter = function(a) { - a = { left: 0, center: 0.5, right: 1 }[a]; - a !== n && ((n = a), F && J.attr({ x: Q })); - }; - J.textSetter = function(a) { - void 0 !== a && t.textSetter(a); - O(); - N(); - }; - J['stroke-widthSetter'] = function(a, g) { - a && (p = !0); - I = this['stroke-width'] = a; - T(g, a); - }; - J.strokeSetter = J.fillSetter = J.rSetter = function(a, g) { - 'r' !== g && ('fill' === g && a && (p = !0), (J[g] = a)); - T(g, a); - }; - J.anchorXSetter = function(a, g) { - z = J.anchorX = a; - T(g, Math.round(a) - K() - Q); - }; - J.anchorYSetter = function(a, g) { - h = J.anchorY = a; - T(g, a - G); - }; - J.xSetter = function(a) { - J.x = a; - n && (a -= n * ((C || F.width) + 2 * B)); - Q = Math.round(a); - J.attr('translateX', Q); - }; - J.ySetter = function(a) { - G = J.y = Math.round(a); - J.attr('translateY', G); - }; - var U = J.css; - return c(J, { - css: function(a) { - if (a) { - var g = {}; - a = q(a); - d(J.textProps, function(b) { - void 0 !== a[b] && ((g[b] = a[b]), delete a[b]); - }); - t.css(g); - } - return U.call(J, a); - }, - getBBox: function() { - return { - width: F.width + 2 * B, - height: F.height + 2 * B, - x: F.x - B, - y: F.y - B, - }; - }, - shadow: function(a) { - a && (O(), x && x.shadow(a)); - return J; - }, - destroy: function() { - v(J.element, 'mouseenter'); - v(J.element, 'mouseleave'); - t && (t = t.destroy()); - x && (x = x.destroy()); - E.prototype.destroy.call(J); - J = y = O = N = T = null; - }, - }); - }, - }); - a.Renderer = D; - })(M); - (function(a) { - var E = a.attr, - D = a.createElement, - H = a.css, - p = a.defined, - f = a.each, - l = a.extend, - r = a.isFirefox, - n = a.isMS, - w = a.isWebKit, - u = a.pick, - e = a.pInt, - h = a.SVGRenderer, - m = a.win, - d = a.wrap; - l(a.SVGElement.prototype, { - htmlCss: function(a) { - var b = this.element; - if ((b = a && 'SPAN' === b.tagName && a.width)) - delete a.width, (this.textWidth = b), this.updateTransform(); - a && - 'ellipsis' === a.textOverflow && - ((a.whiteSpace = 'nowrap'), (a.overflow = 'hidden')); - this.styles = l(this.styles, a); - H(this.element, a); - return this; - }, - htmlGetBBox: function() { - var a = this.element; - return { - x: a.offsetLeft, - y: a.offsetTop, - width: a.offsetWidth, - height: a.offsetHeight, - }; - }, - htmlUpdateTransform: function() { - if (this.added) { - var a = this.renderer, - b = this.element, - d = this.translateX || 0, - z = this.translateY || 0, - h = this.x || 0, - m = this.y || 0, - x = this.textAlign || 'left', - n = { left: 0, center: 0.5, right: 1 }[x], - t = this.styles; - H(b, { marginLeft: d, marginTop: z }); - this.shadows && - f(this.shadows, function(a) { - H(a, { marginLeft: d + 1, marginTop: z + 1 }); - }); - this.inverted && - f(b.childNodes, function(c) { - a.invertChild(c, b); - }); - if ('SPAN' === b.tagName) { - var l = this.rotation, - u = e(this.textWidth), - q = t && t.whiteSpace, - A = [l, x, b.innerHTML, this.textWidth, this.textAlign].join(); - A !== this.cTT && - ((t = a.fontMetrics(b.style.fontSize).b), - p(l) && this.setSpanRotation(l, n, t), - H(b, { width: '', whiteSpace: q || 'nowrap' }), - b.offsetWidth > u && - /[ \-]/.test(b.textContent || b.innerText) && - H(b, { - width: u + 'px', - display: 'block', - whiteSpace: q || 'normal', - }), - this.getSpanCorrection(b.offsetWidth, t, n, l, x)); - H(b, { - left: h + (this.xCorr || 0) + 'px', - top: m + (this.yCorr || 0) + 'px', - }); - w && (t = b.offsetHeight); - this.cTT = A; - } - } else this.alignOnAdd = !0; - }, - setSpanRotation: function(a, b, d) { - var c = {}, - k = this.renderer.getTransformKey(); - c[k] = c.transform = 'rotate(' + a + 'deg)'; - c[k + (r ? 'Origin' : '-origin')] = c.transformOrigin = - 100 * b + '% ' + d + 'px'; - H(this.element, c); - }, - getSpanCorrection: function(a, b, d) { - this.xCorr = -a * d; - this.yCorr = -b; - }, - }); - l(h.prototype, { - getTransformKey: function() { - return n && !/Edge/.test(m.navigator.userAgent) - ? '-ms-transform' - : w - ? '-webkit-transform' - : r - ? 'MozTransform' - : m.opera - ? '-o-transform' - : ''; - }, - html: function(a, b, k) { - var c = this.createElement('span'), - e = c.element, - h = c.renderer, - m = h.isSVG, - w = function(a, b) { - f(['opacity', 'visibility'], function(c) { - d(a, c + 'Setter', function(a, c, d, k) { - a.call(this, c, d, k); - b[d] = c; - }); - }); - }; - c.textSetter = function(a) { - a !== e.innerHTML && delete this.bBox; - this.textStr = a; - e.innerHTML = u(a, ''); - c.htmlUpdateTransform(); - }; - m && w(c, c.element.style); - c.xSetter = c.ySetter = c.alignSetter = c.rotationSetter = function( - a, - b, - ) { - 'align' === b && (b = 'textAlign'); - c[b] = a; - c.htmlUpdateTransform(); - }; - c.attr({ text: a, x: Math.round(b), y: Math.round(k) }).css({ - fontFamily: this.style.fontFamily, - fontSize: this.style.fontSize, - position: 'absolute', - }); - e.style.whiteSpace = 'nowrap'; - c.css = c.htmlCss; - m && - (c.add = function(a) { - var b, - d = h.box.parentNode, - k = []; - if ((this.parentGroup = a)) { - if (((b = a.div), !b)) { - for (; a; ) k.push(a), (a = a.parentGroup); - f(k.reverse(), function(a) { - function e(g, b) { - a[b] = g; - n - ? (q[h.getTransformKey()] = - 'translate(' + - (a.x || a.translateX) + - 'px,' + - (a.y || a.translateY) + - 'px)') - : 'translateX' === b - ? (q.left = g + 'px') - : (q.top = g + 'px'); - a.doTransform = !0; - } - var q, - g = E(a.element, 'class'); - g && (g = { className: g }); - b = a.div = - a.div || - D( - 'div', - g, - { - position: 'absolute', - left: (a.translateX || 0) + 'px', - top: (a.translateY || 0) + 'px', - display: a.display, - opacity: a.opacity, - pointerEvents: a.styles && a.styles.pointerEvents, - }, - b || d, - ); - q = b.style; - l(a, { - classSetter: (function(a) { - return function(g) { - this.element.setAttribute('class', g); - a.className = g; - }; - })(b), - on: function() { - k[0].div && c.on.apply({ element: k[0].div }, arguments); - return a; - }, - translateXSetter: e, - translateYSetter: e, - }); - w(a, q); - }); - } - } else b = d; - b.appendChild(e); - c.added = !0; - c.alignOnAdd && c.htmlUpdateTransform(); - return c; - }); - return c; - }, - }); - })(M); - (function(a) { - function E() { - var n = a.defaultOptions.global, - l = r.moment; - if (n.timezone) { - if (l) - return function(a) { - return -l.tz(a, n.timezone).utcOffset(); - }; - a.error(25); - } - return n.useUTC && n.getTimezoneOffset; - } - function D() { - var n = a.defaultOptions.global, - f, - u = n.useUTC, - e = u ? 'getUTC' : 'get', - h = u ? 'setUTC' : 'set', - m = 'Minutes Hours Day Date Month FullYear'.split(' '), - d = m.concat(['Milliseconds', 'Seconds']); - a.Date = f = n.Date || r.Date; - f.hcTimezoneOffset = u && n.timezoneOffset; - f.hcGetTimezoneOffset = E(); - f.hcHasTimeZone = !(!f.hcTimezoneOffset && !f.hcGetTimezoneOffset); - f.hcMakeTime = function(a, b, d, e, h, m) { - var c; - u - ? ((c = f.UTC.apply(0, arguments)), (c += p(c))) - : (c = new f(a, b, l(d, 1), l(e, 0), l(h, 0), l(m, 0)).getTime()); - return c; - }; - for (n = 0; n < m.length; n++) f['hcGet' + m[n]] = e + m[n]; - for (n = 0; n < d.length; n++) f['hcSet' + d[n]] = h + d[n]; - } - var H = a.color, - p = a.getTZOffset, - f = a.merge, - l = a.pick, - r = a.win; - a.defaultOptions = { - colors: '#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1'.split( - ' ', - ), - symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'], - lang: { - loading: 'Loading...', - months: 'January February March April May June July August September October November December'.split( - ' ', - ), - shortMonths: 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split( - ' ', - ), - weekdays: 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split( - ' ', - ), - decimalPoint: '.', - numericSymbols: 'kMGTPE'.split(''), - resetZoom: 'Reset zoom', - resetZoomTitle: 'Reset zoom level 1:1', - thousandsSep: ' ', - }, - global: { useUTC: !0 }, - chart: { - borderRadius: 0, - defaultSeriesType: 'line', - ignoreHiddenSeries: !0, - spacing: [10, 10, 15, 10], - resetZoomButton: { - theme: { zIndex: 6 }, - position: { align: 'right', x: -10, y: 10 }, - }, - width: null, - height: null, - borderColor: '#335cad', - backgroundColor: '#ffffff', - plotBorderColor: '#cccccc', - }, - title: { - text: 'Chart title', - align: 'center', - margin: 15, - widthAdjust: -44, - }, - subtitle: { text: '', align: 'center', widthAdjust: -44 }, - plotOptions: {}, - labels: { style: { position: 'absolute', color: '#333333' } }, - legend: { - enabled: !0, - align: 'center', - layout: 'horizontal', - labelFormatter: function() { - return this.name; - }, - borderColor: '#999999', - borderRadius: 0, - navigation: { activeColor: '#003399', inactiveColor: '#cccccc' }, - itemStyle: { - color: '#333333', - fontSize: '12px', - fontWeight: 'bold', - textOverflow: 'ellipsis', - }, - itemHoverStyle: { color: '#000000' }, - itemHiddenStyle: { color: '#cccccc' }, - shadow: !1, - itemCheckboxStyle: { - position: 'absolute', - width: '13px', - height: '13px', - }, - squareSymbol: !0, - symbolPadding: 5, - verticalAlign: 'bottom', - x: 0, - y: 0, - title: { style: { fontWeight: 'bold' } }, - }, - loading: { - labelStyle: { fontWeight: 'bold', position: 'relative', top: '45%' }, - style: { - position: 'absolute', - backgroundColor: '#ffffff', - opacity: 0.5, - textAlign: 'center', - }, - }, - tooltip: { - enabled: !0, - animation: a.svg, - borderRadius: 3, - dateTimeLabelFormats: { - millisecond: '%A, %b %e, %H:%M:%S.%L', - second: '%A, %b %e, %H:%M:%S', - minute: '%A, %b %e, %H:%M', - hour: '%A, %b %e, %H:%M', - day: '%A, %b %e, %Y', - week: 'Week from %A, %b %e, %Y', - month: '%B %Y', - year: '%Y', - }, - footerFormat: '', - padding: 8, - snap: a.isTouchDevice ? 25 : 10, - backgroundColor: H('#f7f7f7') - .setOpacity(0.85) - .get(), - borderWidth: 1, - headerFormat: - '\x3cspan style\x3d"font-size: 10px"\x3e{point.key}\x3c/span\x3e\x3cbr/\x3e', - pointFormat: - '\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e {series.name}: \x3cb\x3e{point.y}\x3c/b\x3e\x3cbr/\x3e', - shadow: !0, - style: { - color: '#333333', - cursor: 'default', - fontSize: '12px', - pointerEvents: 'none', - whiteSpace: 'nowrap', - }, - }, - credits: { - enabled: !0, - href: 'http://www.highcharts.com', - position: { align: 'right', x: -10, verticalAlign: 'bottom', y: -5 }, - style: { cursor: 'pointer', color: '#999999', fontSize: '9px' }, - text: 'Highcharts.com', - }, - }; - a.setOptions = function(n) { - a.defaultOptions = f(!0, a.defaultOptions, n); - D(); - return a.defaultOptions; - }; - a.getOptions = function() { - return a.defaultOptions; - }; - a.defaultPlotOptions = a.defaultOptions.plotOptions; - D(); - })(M); - (function(a) { - var E = a.correctFloat, - D = a.defined, - H = a.destroyObjectProperties, - p = a.isNumber, - f = a.merge, - l = a.pick, - r = a.deg2rad; - a.Tick = function(a, l, f, e) { - this.axis = a; - this.pos = l; - this.type = f || ''; - this.isNewLabel = this.isNew = !0; - f || e || this.addLabel(); - }; - a.Tick.prototype = { - addLabel: function() { - var a = this.axis, - w = a.options, - u = a.chart, - e = a.categories, - h = a.names, - m = this.pos, - d = w.labels, - c = a.tickPositions, - b = m === c[0], - k = m === c[c.length - 1], - h = e ? l(e[m], h[m], m) : m, - e = this.label, - c = c.info, - z; - a.isDatetimeAxis && - c && - (z = w.dateTimeLabelFormats[c.higherRanks[m] || c.unitName]); - this.isFirst = b; - this.isLast = k; - w = a.labelFormatter.call({ - axis: a, - chart: u, - isFirst: b, - isLast: k, - dateTimeLabelFormat: z, - value: a.isLog ? E(a.lin2log(h)) : h, - pos: m, - }); - D(e) - ? e && e.attr({ text: w }) - : ((this.labelLength = - (this.label = e = - D(w) && d.enabled - ? u.renderer - .text(w, 0, 0, d.useHTML) - .css(f(d.style)) - .add(a.labelGroup) - : null) && e.getBBox().width), - (this.rotation = 0)); - }, - getLabelSize: function() { - return this.label - ? this.label.getBBox()[this.axis.horiz ? 'height' : 'width'] - : 0; - }, - handleOverflow: function(a) { - var f = this.axis, - n = f.options.labels, - e = a.x, - h = f.chart.chartWidth, - m = f.chart.spacing, - d = l(f.labelLeft, Math.min(f.pos, m[3])), - m = l( - f.labelRight, - Math.max(f.isRadial ? 0 : f.pos + f.len, h - m[1]), - ), - c = this.label, - b = this.rotation, - k = { left: 0, center: 0.5, right: 1 }[ - f.labelAlign || c.attr('align') - ], - z = c.getBBox().width, - B = f.getSlotWidth(), - I = B, - x = 1, - p, - t = {}; - if (b || !1 === n.overflow) - 0 > b && e - k * z < d - ? (p = Math.round(e / Math.cos(b * r) - d)) - : 0 < b && - e + k * z > m && - (p = Math.round((h - e) / Math.cos(b * r))); - else if ( - ((h = e + (1 - k) * z), - e - k * z < d - ? (I = a.x + I * (1 - k) - d) - : h > m && ((I = m - a.x + I * k), (x = -1)), - (I = Math.min(B, I)), - I < B && - 'center' === f.labelAlign && - (a.x += x * (B - I - k * (B - Math.min(z, I)))), - z > I || (f.autoRotation && (c.styles || {}).width)) - ) - p = I; - p && - ((t.width = p), - (n.style || {}).textOverflow || (t.textOverflow = 'ellipsis'), - c.css(t)); - }, - getPosition: function(a, f, l, e) { - var h = this.axis, - m = h.chart, - d = (e && m.oldChartHeight) || m.chartHeight; - return { - x: a - ? h.translate(f + l, null, null, e) + h.transB - : h.left + - h.offset + - (h.opposite - ? ((e && m.oldChartWidth) || m.chartWidth) - h.right - h.left - : 0), - y: a - ? d - h.bottom + h.offset - (h.opposite ? h.height : 0) - : d - h.translate(f + l, null, null, e) - h.transB, - }; - }, - getLabelPosition: function(a, f, l, e, h, m, d, c) { - var b = this.axis, - k = b.transA, - z = b.reversed, - B = b.staggerLines, - n = b.tickRotCorr || { x: 0, y: 0 }, - x = h.y, - u = - e || b.reserveSpaceDefault - ? 0 - : -b.labelOffset * ('center' === b.labelAlign ? 0.5 : 1); - D(x) || - (x = - 0 === b.side - ? l.rotation - ? -8 - : -l.getBBox().height - : 2 === b.side - ? n.y + 8 - : Math.cos(l.rotation * r) * (n.y - l.getBBox(!1, 0).height / 2)); - a = a + h.x + u + n.x - (m && e ? m * k * (z ? -1 : 1) : 0); - f = f + x - (m && !e ? m * k * (z ? 1 : -1) : 0); - B && - ((l = (d / (c || 1)) % B), - b.opposite && (l = B - l - 1), - (f += (b.labelOffset / B) * l)); - return { x: a, y: Math.round(f) }; - }, - getMarkPath: function(a, f, l, e, h, m) { - return m.crispLine( - ['M', a, f, 'L', a + (h ? 0 : -l), f + (h ? l : 0)], - e, - ); - }, - renderGridLine: function(a, f, l) { - var e = this.axis, - h = e.options, - m = this.gridLine, - d = {}, - c = this.pos, - b = this.type, - k = e.tickmarkOffset, - z = e.chart.renderer, - B = b ? b + 'Grid' : 'grid', - n = h[B + 'LineWidth'], - x = h[B + 'LineColor'], - h = h[B + 'LineDashStyle']; - m || - ((d.stroke = x), - (d['stroke-width'] = n), - h && (d.dashstyle = h), - b || (d.zIndex = 1), - a && (d.opacity = 0), - (this.gridLine = m = z - .path() - .attr(d) - .addClass('highcharts-' + (b ? b + '-' : '') + 'grid-line') - .add(e.gridGroup))); - if ( - !a && - m && - (a = e.getPlotLinePath(c + k, m.strokeWidth() * l, a, !0)) - ) - m[this.isNew ? 'attr' : 'animate']({ d: a, opacity: f }); - }, - renderMark: function(a, f, u) { - var e = this.axis, - h = e.options, - m = e.chart.renderer, - d = this.type, - c = d ? d + 'Tick' : 'tick', - b = e.tickSize(c), - k = this.mark, - z = !k, - B = a.x; - a = a.y; - var n = l(h[c + 'Width'], !d && e.isXAxis ? 1 : 0), - h = h[c + 'Color']; - b && - (e.opposite && (b[0] = -b[0]), - z && - ((this.mark = k = m - .path() - .addClass('highcharts-' + (d ? d + '-' : '') + 'tick') - .add(e.axisGroup)), - k.attr({ stroke: h, 'stroke-width': n })), - k[z ? 'attr' : 'animate']({ - d: this.getMarkPath(B, a, b[0], k.strokeWidth() * u, e.horiz, m), - opacity: f, - })); - }, - renderLabel: function(a, f, u, e) { - var h = this.axis, - m = h.horiz, - d = h.options, - c = this.label, - b = d.labels, - k = b.step, - h = h.tickmarkOffset, - z = !0, - B = a.x; - a = a.y; - c && - p(B) && - ((c.xy = a = this.getLabelPosition(B, a, c, m, b, h, e, k)), - (this.isFirst && !this.isLast && !l(d.showFirstLabel, 1)) || - (this.isLast && !this.isFirst && !l(d.showLastLabel, 1)) - ? (z = !1) - : !m || - b.step || - b.rotation || - f || - 0 === u || - this.handleOverflow(a), - k && e % k && (z = !1), - z && p(a.y) - ? ((a.opacity = u), - c[this.isNewLabel ? 'attr' : 'animate'](a), - (this.isNewLabel = !1)) - : (c.attr('y', -9999), (this.isNewLabel = !0))); - }, - render: function(a, f, u) { - var e = this.axis, - h = e.horiz, - m = this.getPosition(h, this.pos, e.tickmarkOffset, f), - d = m.x, - c = m.y, - e = (h && d === e.pos + e.len) || (!h && c === e.pos) ? -1 : 1; - u = l(u, 1); - this.isActive = !0; - this.renderGridLine(f, u, e); - this.renderMark(m, u, e); - this.renderLabel(m, f, u, a); - this.isNew = !1; - }, - destroy: function() { - H(this, this.axis); - }, - }; - })(M); - var V = (function(a) { - var E = a.addEvent, - D = a.animObject, - H = a.arrayMax, - p = a.arrayMin, - f = a.color, - l = a.correctFloat, - r = a.defaultOptions, - n = a.defined, - w = a.deg2rad, - u = a.destroyObjectProperties, - e = a.each, - h = a.extend, - m = a.fireEvent, - d = a.format, - c = a.getMagnitude, - b = a.grep, - k = a.inArray, - z = a.isArray, - B = a.isNumber, - I = a.isString, - x = a.merge, - K = a.normalizeTickInterval, - t = a.objectEach, - C = a.pick, - N = a.removeEvent, - q = a.splat, - A = a.syncTimeout, - F = a.Tick, - G = function() { - this.init.apply(this, arguments); - }; - a.extend(G.prototype, { - defaultOptions: { - dateTimeLabelFormats: { - millisecond: '%H:%M:%S.%L', - second: '%H:%M:%S', - minute: '%H:%M', - hour: '%H:%M', - day: '%e. %b', - week: '%e. %b', - month: "%b '%y", - year: '%Y', - }, - endOnTick: !1, - labels: { - enabled: !0, - style: { color: '#666666', cursor: 'default', fontSize: '11px' }, - x: 0, - }, - maxPadding: 0.01, - minorTickLength: 2, - minorTickPosition: 'outside', - minPadding: 0.01, - startOfWeek: 1, - startOnTick: !1, - tickLength: 10, - tickmarkPlacement: 'between', - tickPixelInterval: 100, - tickPosition: 'outside', - title: { align: 'middle', style: { color: '#666666' } }, - type: 'linear', - minorGridLineColor: '#f2f2f2', - minorGridLineWidth: 1, - minorTickColor: '#999999', - lineColor: '#ccd6eb', - lineWidth: 1, - gridLineColor: '#e6e6e6', - tickColor: '#ccd6eb', - }, - defaultYAxisOptions: { - endOnTick: !0, - tickPixelInterval: 72, - showLastLabel: !0, - labels: { x: -8 }, - maxPadding: 0.05, - minPadding: 0.05, - startOnTick: !0, - title: { rotation: 270, text: 'Values' }, - stackLabels: { - allowOverlap: !1, - enabled: !1, - formatter: function() { - return a.numberFormat(this.total, -1); - }, - style: { - fontSize: '11px', - fontWeight: 'bold', - color: '#000000', - textOutline: '1px contrast', - }, - }, - gridLineWidth: 1, - lineWidth: 0, - }, - defaultLeftAxisOptions: { labels: { x: -15 }, title: { rotation: 270 } }, - defaultRightAxisOptions: { labels: { x: 15 }, title: { rotation: 90 } }, - defaultBottomAxisOptions: { - labels: { autoRotation: [-45], x: 0 }, - title: { rotation: 0 }, - }, - defaultTopAxisOptions: { - labels: { autoRotation: [-45], x: 0 }, - title: { rotation: 0 }, - }, - init: function(a, b) { - var g = b.isX, - v = this; - v.chart = a; - v.horiz = a.inverted && !v.isZAxis ? !g : g; - v.isXAxis = g; - v.coll = v.coll || (g ? 'xAxis' : 'yAxis'); - v.opposite = b.opposite; - v.side = - b.side || (v.horiz ? (v.opposite ? 0 : 2) : v.opposite ? 1 : 3); - v.setOptions(b); - var c = this.options, - d = c.type; - v.labelFormatter = c.labels.formatter || v.defaultLabelFormatter; - v.userOptions = b; - v.minPixelPadding = 0; - v.reversed = c.reversed; - v.visible = !1 !== c.visible; - v.zoomEnabled = !1 !== c.zoomEnabled; - v.hasNames = 'category' === d || !0 === c.categories; - v.categories = c.categories || v.hasNames; - v.names = v.names || []; - v.plotLinesAndBandsGroups = {}; - v.isLog = 'logarithmic' === d; - v.isDatetimeAxis = 'datetime' === d; - v.positiveValuesOnly = v.isLog && !v.allowNegativeLog; - v.isLinked = n(c.linkedTo); - v.ticks = {}; - v.labelEdge = []; - v.minorTicks = {}; - v.plotLinesAndBands = []; - v.alternateBands = {}; - v.len = 0; - v.minRange = v.userMinRange = c.minRange || c.maxZoom; - v.range = c.range; - v.offset = c.offset || 0; - v.stacks = {}; - v.oldStacks = {}; - v.stacksTouched = 0; - v.max = null; - v.min = null; - v.crosshair = C( - c.crosshair, - q(a.options.tooltip.crosshairs)[g ? 0 : 1], - !1, - ); - b = v.options.events; - -1 === k(v, a.axes) && - (g ? a.axes.splice(a.xAxis.length, 0, v) : a.axes.push(v), - a[v.coll].push(v)); - v.series = v.series || []; - a.inverted && - !v.isZAxis && - g && - void 0 === v.reversed && - (v.reversed = !0); - t(b, function(a, g) { - E(v, g, a); - }); - v.lin2log = c.linearToLogConverter || v.lin2log; - v.isLog && ((v.val2lin = v.log2lin), (v.lin2val = v.lin2log)); - }, - setOptions: function(a) { - this.options = x( - this.defaultOptions, - 'yAxis' === this.coll && this.defaultYAxisOptions, - [ - this.defaultTopAxisOptions, - this.defaultRightAxisOptions, - this.defaultBottomAxisOptions, - this.defaultLeftAxisOptions, - ][this.side], - x(r[this.coll], a), - ); - }, - defaultLabelFormatter: function() { - var g = this.axis, - b = this.value, - c = g.categories, - k = this.dateTimeLabelFormat, - e = r.lang, - q = e.numericSymbols, - e = e.numericSymbolMagnitude || 1e3, - h = q && q.length, - m, - z = g.options.labels.format, - g = g.isLog ? Math.abs(b) : g.tickInterval; - if (z) m = d(z, this); - else if (c) m = b; - else if (k) m = a.dateFormat(k, b); - else if (h && 1e3 <= g) - for (; h-- && void 0 === m; ) - (c = Math.pow(e, h + 1)), - g >= c && - 0 === (10 * b) % c && - null !== q[h] && - 0 !== b && - (m = a.numberFormat(b / c, -1) + q[h]); - void 0 === m && - (m = - 1e4 <= Math.abs(b) - ? a.numberFormat(b, -1) - : a.numberFormat(b, -1, void 0, '')); - return m; - }, - getSeriesExtremes: function() { - var a = this, - v = a.chart; - a.hasVisibleSeries = !1; - a.dataMin = a.dataMax = a.threshold = null; - a.softThreshold = !a.isXAxis; - a.buildStacks && a.buildStacks(); - e(a.series, function(g) { - if (g.visible || !v.options.chart.ignoreHiddenSeries) { - var c = g.options, - d = c.threshold, - k; - a.hasVisibleSeries = !0; - a.positiveValuesOnly && 0 >= d && (d = null); - if (a.isXAxis) - (c = g.xData), - c.length && - ((g = p(c)), - (k = H(c)), - B(g) || g instanceof Date || ((c = b(c, B)), (g = p(c))), - (a.dataMin = Math.min(C(a.dataMin, c[0], g), g)), - (a.dataMax = Math.max(C(a.dataMax, c[0], k), k))); - else if ( - (g.getExtremes(), - (k = g.dataMax), - (g = g.dataMin), - n(g) && - n(k) && - ((a.dataMin = Math.min(C(a.dataMin, g), g)), - (a.dataMax = Math.max(C(a.dataMax, k), k))), - n(d) && (a.threshold = d), - !c.softThreshold || a.positiveValuesOnly) - ) - a.softThreshold = !1; - } - }); - }, - translate: function(a, b, c, d, k, e) { - var g = this.linkedParent || this, - v = 1, - q = 0, - h = d ? g.oldTransA : g.transA; - d = d ? g.oldMin : g.min; - var m = g.minPixelPadding; - k = (g.isOrdinal || g.isBroken || (g.isLog && k)) && g.lin2val; - h || (h = g.transA); - c && ((v *= -1), (q = g.len)); - g.reversed && ((v *= -1), (q -= v * (g.sector || g.len))); - b - ? ((a = (a * v + q - m) / h + d), k && (a = g.lin2val(a))) - : (k && (a = g.val2lin(a)), - (a = B(d) - ? v * (a - d) * h + q + v * m + (B(e) ? h * e : 0) - : void 0)); - return a; - }, - toPixels: function(a, b) { - return ( - this.translate(a, !1, !this.horiz, null, !0) + (b ? 0 : this.pos) - ); - }, - toValue: function(a, b) { - return this.translate( - a - (b ? 0 : this.pos), - !0, - !this.horiz, - null, - !0, - ); - }, - getPlotLinePath: function(a, b, c, d, k) { - var g = this.chart, - v = this.left, - q = this.top, - e, - h, - m = (c && g.oldChartHeight) || g.chartHeight, - z = (c && g.oldChartWidth) || g.chartWidth, - A; - e = this.transB; - var t = function(a, g, b) { - if (a < g || a > b) d ? (a = Math.min(Math.max(g, a), b)) : (A = !0); - return a; - }; - k = C(k, this.translate(a, null, null, c)); - a = c = Math.round(k + e); - e = h = Math.round(m - k - e); - B(k) - ? this.horiz - ? ((e = q), - (h = m - this.bottom), - (a = c = t(a, v, v + this.width))) - : ((a = v), - (c = z - this.right), - (e = h = t(e, q, q + this.height))) - : ((A = !0), (d = !1)); - return A && !d - ? null - : g.renderer.crispLine(['M', a, e, 'L', c, h], b || 1); - }, - getLinearTickPositions: function(a, b, c) { - var g, - v = l(Math.floor(b / a) * a); - c = l(Math.ceil(c / a) * a); - var d = [], - k; - l(v + a) === v && (k = 20); - if (this.single) return [b]; - for (b = v; b <= c; ) { - d.push(b); - b = l(b + a, k); - if (b === g) break; - g = b; - } - return d; - }, - getMinorTickInterval: function() { - var a = this.options; - return !0 === a.minorTicks - ? C(a.minorTickInterval, 'auto') - : !1 === a.minorTicks - ? null - : a.minorTickInterval; - }, - getMinorTickPositions: function() { - var a = this, - b = a.options, - c = a.tickPositions, - d = a.minorTickInterval, - k = [], - q = a.pointRangePadding || 0, - h = a.min - q, - q = a.max + q, - m = q - h; - if (m && m / d < a.len / 3) - if (a.isLog) - e(this.paddedTicks, function(g, b, v) { - b && - k.push.apply(k, a.getLogTickPositions(d, v[b - 1], v[b], !0)); - }); - else if (a.isDatetimeAxis && 'auto' === this.getMinorTickInterval()) - k = k.concat( - a.getTimeTicks( - a.normalizeTimeTickInterval(d), - h, - q, - b.startOfWeek, - ), - ); - else - for (b = h + ((c[0] - h) % d); b <= q && b !== k[0]; b += d) - k.push(b); - 0 !== k.length && a.trimTicks(k); - return k; - }, - adjustForMinRange: function() { - var a = this.options, - b = this.min, - c = this.max, - d, - k, - q, - h, - m, - z, - A, - t; - this.isXAxis && - void 0 === this.minRange && - !this.isLog && - (n(a.min) || n(a.max) - ? (this.minRange = null) - : (e(this.series, function(a) { - z = a.xData; - for (h = A = a.xIncrement ? 1 : z.length - 1; 0 < h; h--) - if (((m = z[h] - z[h - 1]), void 0 === q || m < q)) q = m; - }), - (this.minRange = Math.min(5 * q, this.dataMax - this.dataMin)))); - c - b < this.minRange && - ((k = this.dataMax - this.dataMin >= this.minRange), - (t = this.minRange), - (d = (t - c + b) / 2), - (d = [b - d, C(a.min, b - d)]), - k && (d[2] = this.isLog ? this.log2lin(this.dataMin) : this.dataMin), - (b = H(d)), - (c = [b + t, C(a.max, b + t)]), - k && (c[2] = this.isLog ? this.log2lin(this.dataMax) : this.dataMax), - (c = p(c)), - c - b < t && ((d[0] = c - t), (d[1] = C(a.min, c - t)), (b = H(d)))); - this.min = b; - this.max = c; - }, - getClosest: function() { - var a; - this.categories - ? (a = 1) - : e(this.series, function(g) { - var b = g.closestPointRange, - v = g.visible || !g.chart.options.chart.ignoreHiddenSeries; - !g.noSharedTooltip && - n(b) && - v && - (a = n(a) ? Math.min(a, b) : b); - }); - return a; - }, - nameToX: function(a) { - var g = z(this.categories), - b = g ? this.categories : this.names, - c = a.options.x, - d; - a.series.requireSorting = !1; - n(c) || - (c = - !1 === this.options.uniqueNames - ? a.series.autoIncrement() - : k(a.name, b)); - -1 === c ? g || (d = b.length) : (d = c); - void 0 !== d && (this.names[d] = a.name); - return d; - }, - updateNames: function() { - var a = this; - 0 < this.names.length && - ((this.names.length = 0), - (this.minRange = this.userMinRange), - e(this.series || [], function(g) { - g.xIncrement = null; - if (!g.points || g.isDirtyData) g.processData(), g.generatePoints(); - e(g.points, function(b, v) { - var c; - b.options && - ((c = a.nameToX(b)), - void 0 !== c && c !== b.x && ((b.x = c), (g.xData[v] = c))); - }); - })); - }, - setAxisTranslation: function(a) { - var g = this, - b = g.max - g.min, - c = g.axisPointRange || 0, - d, - k = 0, - q = 0, - h = g.linkedParent, - m = !!g.categories, - z = g.transA, - A = g.isXAxis; - if (A || m || c) - (d = g.getClosest()), - h - ? ((k = h.minPointOffset), (q = h.pointRangePadding)) - : e(g.series, function(a) { - var b = m - ? 1 - : A - ? C(a.options.pointRange, d, 0) - : g.axisPointRange || 0; - a = a.options.pointPlacement; - c = Math.max(c, b); - g.single || - ((k = Math.max(k, I(a) ? 0 : b / 2)), - (q = Math.max(q, 'on' === a ? 0 : b))); - }), - (h = g.ordinalSlope && d ? g.ordinalSlope / d : 1), - (g.minPointOffset = k *= h), - (g.pointRangePadding = q *= h), - (g.pointRange = Math.min(c, b)), - A && (g.closestPointRange = d); - a && (g.oldTransA = z); - g.translationSlope = g.transA = z = - g.options.staticScale || g.len / (b + q || 1); - g.transB = g.horiz ? g.left : g.bottom; - g.minPixelPadding = z * k; - }, - minFromRange: function() { - return this.max - this.range; - }, - setTickInterval: function(g) { - var b = this, - d = b.chart, - k = b.options, - q = b.isLog, - h = b.log2lin, - z = b.isDatetimeAxis, - A = b.isXAxis, - t = b.isLinked, - x = k.maxPadding, - f = k.minPadding, - F = k.tickInterval, - u = k.tickPixelInterval, - G = b.categories, - p = b.threshold, - I = b.softThreshold, - r, - w, - N, - D; - z || G || t || this.getTickAmount(); - N = C(b.userMin, k.min); - D = C(b.userMax, k.max); - t - ? ((b.linkedParent = d[b.coll][k.linkedTo]), - (d = b.linkedParent.getExtremes()), - (b.min = C(d.min, d.dataMin)), - (b.max = C(d.max, d.dataMax)), - k.type !== b.linkedParent.options.type && a.error(11, 1)) - : (!I && - n(p) && - (b.dataMin >= p - ? ((r = p), (f = 0)) - : b.dataMax <= p && ((w = p), (x = 0))), - (b.min = C(N, r, b.dataMin)), - (b.max = C(D, w, b.dataMax))); - q && - (b.positiveValuesOnly && - !g && - 0 >= Math.min(b.min, C(b.dataMin, b.min)) && - a.error(10, 1), - (b.min = l(h(b.min), 15)), - (b.max = l(h(b.max), 15))); - b.range && - n(b.max) && - ((b.userMin = b.min = N = Math.max(b.dataMin, b.minFromRange())), - (b.userMax = D = b.max), - (b.range = null)); - m(b, 'foundExtremes'); - b.beforePadding && b.beforePadding(); - b.adjustForMinRange(); - !(G || b.axisPointRange || b.usePercentage || t) && - n(b.min) && - n(b.max) && - (h = b.max - b.min) && - (!n(N) && f && (b.min -= h * f), !n(D) && x && (b.max += h * x)); - B(k.softMin) && !B(b.userMin) && (b.min = Math.min(b.min, k.softMin)); - B(k.softMax) && !B(b.userMax) && (b.max = Math.max(b.max, k.softMax)); - B(k.floor) && (b.min = Math.max(b.min, k.floor)); - B(k.ceiling) && (b.max = Math.min(b.max, k.ceiling)); - I && - n(b.dataMin) && - ((p = p || 0), - !n(N) && b.min < p && b.dataMin >= p - ? (b.min = p) - : !n(D) && b.max > p && b.dataMax <= p && (b.max = p)); - b.tickInterval = - b.min === b.max || void 0 === b.min || void 0 === b.max - ? 1 - : t && !F && u === b.linkedParent.options.tickPixelInterval - ? (F = b.linkedParent.tickInterval) - : C( - F, - this.tickAmount - ? (b.max - b.min) / Math.max(this.tickAmount - 1, 1) - : void 0, - G ? 1 : ((b.max - b.min) * u) / Math.max(b.len, u), - ); - A && - !g && - e(b.series, function(a) { - a.processData(b.min !== b.oldMin || b.max !== b.oldMax); - }); - b.setAxisTranslation(!0); - b.beforeSetTickPositions && b.beforeSetTickPositions(); - b.postProcessTickInterval && - (b.tickInterval = b.postProcessTickInterval(b.tickInterval)); - b.pointRange && - !F && - (b.tickInterval = Math.max(b.pointRange, b.tickInterval)); - g = C(k.minTickInterval, b.isDatetimeAxis && b.closestPointRange); - !F && b.tickInterval < g && (b.tickInterval = g); - z || - q || - F || - (b.tickInterval = K( - b.tickInterval, - null, - c(b.tickInterval), - C( - k.allowDecimals, - !( - 0.5 < b.tickInterval && - 5 > b.tickInterval && - 1e3 < b.max && - 9999 > b.max - ), - ), - !!this.tickAmount, - )); - this.tickAmount || (b.tickInterval = b.unsquish()); - this.setTickPositions(); - }, - setTickPositions: function() { - var a = this.options, - b, - c = a.tickPositions; - b = this.getMinorTickInterval(); - var d = a.tickPositioner, - k = a.startOnTick, - q = a.endOnTick; - this.tickmarkOffset = - this.categories && - 'between' === a.tickmarkPlacement && - 1 === this.tickInterval - ? 0.5 - : 0; - this.minorTickInterval = - 'auto' === b && this.tickInterval ? this.tickInterval / 5 : b; - this.single = - this.min === this.max && - n(this.min) && - !this.tickAmount && - (parseInt(this.min, 10) === this.min || !1 !== a.allowDecimals); - this.tickPositions = b = c && c.slice(); - !b && - ((b = this.isDatetimeAxis - ? this.getTimeTicks( - this.normalizeTimeTickInterval(this.tickInterval, a.units), - this.min, - this.max, - a.startOfWeek, - this.ordinalPositions, - this.closestPointRange, - !0, - ) - : this.isLog - ? this.getLogTickPositions(this.tickInterval, this.min, this.max) - : this.getLinearTickPositions( - this.tickInterval, - this.min, - this.max, - )), - b.length > this.len && - ((b = [b[0], b.pop()]), b[0] === b[1] && (b.length = 1)), - (this.tickPositions = b), - d && (d = d.apply(this, [this.min, this.max]))) && - (this.tickPositions = b = d); - this.paddedTicks = b.slice(0); - this.trimTicks(b, k, q); - this.isLinked || - (this.single && - 2 > b.length && - ((this.min -= 0.5), (this.max += 0.5)), - c || d || this.adjustTickAmount()); - }, - trimTicks: function(a, b, c) { - var g = a[0], - d = a[a.length - 1], - k = this.minPointOffset || 0; - if (!this.isLinked) { - if (b && -Infinity !== g) this.min = g; - else for (; this.min - k > a[0]; ) a.shift(); - if (c) this.max = d; - else for (; this.max + k < a[a.length - 1]; ) a.pop(); - 0 === a.length && - n(g) && - !this.options.tickPositions && - a.push((d + g) / 2); - } - }, - alignToOthers: function() { - var a = {}, - b, - c = this.options; - !1 === this.chart.options.chart.alignTicks || - !1 === c.alignTicks || - this.isLog || - e(this.chart[this.coll], function(g) { - var c = g.options, - c = [g.horiz ? c.left : c.top, c.width, c.height, c.pane].join(); - g.series.length && (a[c] ? (b = !0) : (a[c] = 1)); - }); - return b; - }, - getTickAmount: function() { - var a = this.options, - b = a.tickAmount, - c = a.tickPixelInterval; - !n(a.tickInterval) && - this.len < c && - !this.isRadial && - !this.isLog && - a.startOnTick && - a.endOnTick && - (b = 2); - !b && this.alignToOthers() && (b = Math.ceil(this.len / c) + 1); - 4 > b && ((this.finalTickAmt = b), (b = 5)); - this.tickAmount = b; - }, - adjustTickAmount: function() { - var a = this.tickInterval, - b = this.tickPositions, - c = this.tickAmount, - d = this.finalTickAmt, - k = b && b.length, - q = C(this.threshold, this.softThreshold ? 0 : null); - if (this.hasData()) { - if (k < c) { - for (; b.length < c; ) - b.length % 2 || this.min === q - ? b.push(l(b[b.length - 1] + a)) - : b.unshift(l(b[0] - a)); - this.transA *= (k - 1) / (c - 1); - this.min = b[0]; - this.max = b[b.length - 1]; - } else k > c && ((this.tickInterval *= 2), this.setTickPositions()); - if (n(d)) { - for (a = c = b.length; a--; ) - ((3 === d && 1 === a % 2) || (2 >= d && 0 < a && a < c - 1)) && - b.splice(a, 1); - this.finalTickAmt = void 0; - } - } - }, - setScale: function() { - var a, b; - this.oldMin = this.min; - this.oldMax = this.max; - this.oldAxisLength = this.len; - this.setAxisSize(); - b = this.len !== this.oldAxisLength; - e(this.series, function(b) { - if (b.isDirtyData || b.isDirty || b.xAxis.isDirty) a = !0; - }); - b || - a || - this.isLinked || - this.forceRedraw || - this.userMin !== this.oldUserMin || - this.userMax !== this.oldUserMax || - this.alignToOthers() - ? (this.resetStacks && this.resetStacks(), - (this.forceRedraw = !1), - this.getSeriesExtremes(), - this.setTickInterval(), - (this.oldUserMin = this.userMin), - (this.oldUserMax = this.userMax), - this.isDirty || - (this.isDirty = - b || this.min !== this.oldMin || this.max !== this.oldMax)) - : this.cleanStacks && this.cleanStacks(); - }, - setExtremes: function(a, b, c, d, k) { - var g = this, - q = g.chart; - c = C(c, !0); - e(g.series, function(a) { - delete a.kdTree; - }); - k = h(k, { min: a, max: b }); - m(g, 'setExtremes', k, function() { - g.userMin = a; - g.userMax = b; - g.eventArgs = k; - c && q.redraw(d); - }); - }, - zoom: function(a, b) { - var g = this.dataMin, - c = this.dataMax, - d = this.options, - k = Math.min(g, C(d.min, g)), - d = Math.max(c, C(d.max, c)); - if (a !== this.min || b !== this.max) - this.allowZoomOutside || - (n(g) && (a < k && (a = k), a > d && (a = d)), - n(c) && (b < k && (b = k), b > d && (b = d))), - (this.displayBtn = void 0 !== a || void 0 !== b), - this.setExtremes(a, b, !1, void 0, { trigger: 'zoom' }); - return !0; - }, - setAxisSize: function() { - var b = this.chart, - c = this.options, - d = c.offsets || [0, 0, 0, 0], - k = this.horiz, - q = (this.width = Math.round( - a.relativeLength( - C(c.width, b.plotWidth - d[3] + d[1]), - b.plotWidth, - ), - )), - e = (this.height = Math.round( - a.relativeLength( - C(c.height, b.plotHeight - d[0] + d[2]), - b.plotHeight, - ), - )), - h = (this.top = Math.round( - a.relativeLength( - C(c.top, b.plotTop + d[0]), - b.plotHeight, - b.plotTop, - ), - )), - c = (this.left = Math.round( - a.relativeLength( - C(c.left, b.plotLeft + d[3]), - b.plotWidth, - b.plotLeft, - ), - )); - this.bottom = b.chartHeight - e - h; - this.right = b.chartWidth - q - c; - this.len = Math.max(k ? q : e, 0); - this.pos = k ? c : h; - }, - getExtremes: function() { - var a = this.isLog, - b = this.lin2log; - return { - min: a ? l(b(this.min)) : this.min, - max: a ? l(b(this.max)) : this.max, - dataMin: this.dataMin, - dataMax: this.dataMax, - userMin: this.userMin, - userMax: this.userMax, - }; - }, - getThreshold: function(a) { - var b = this.isLog, - g = this.lin2log, - c = b ? g(this.min) : this.min, - b = b ? g(this.max) : this.max; - null === a ? (a = c) : c > a ? (a = c) : b < a && (a = b); - return this.translate(a, 0, 1, 0, 1); - }, - autoLabelAlign: function(a) { - a = (C(a, 0) - 90 * this.side + 720) % 360; - return 15 < a && 165 > a - ? 'right' - : 195 < a && 345 > a - ? 'left' - : 'center'; - }, - tickSize: function(a) { - var b = this.options, - g = b[a + 'Length'], - c = C(b[a + 'Width'], 'tick' === a && this.isXAxis ? 1 : 0); - if (c && g) return 'inside' === b[a + 'Position'] && (g = -g), [g, c]; - }, - labelMetrics: function() { - var a = (this.tickPositions && this.tickPositions[0]) || 0; - return this.chart.renderer.fontMetrics( - this.options.labels.style && this.options.labels.style.fontSize, - this.ticks[a] && this.ticks[a].label, - ); - }, - unsquish: function() { - var a = this.options.labels, - b = this.horiz, - c = this.tickInterval, - d = c, - k = - this.len / (((this.categories ? 1 : 0) + this.max - this.min) / c), - q, - h = a.rotation, - m = this.labelMetrics(), - z, - A = Number.MAX_VALUE, - t, - x = function(a) { - a /= k || 1; - a = 1 < a ? Math.ceil(a) : 1; - return a * c; - }; - b - ? (t = - !a.staggerLines && - !a.step && - (n(h) - ? [h] - : k < C(a.autoRotationLimit, 80) && a.autoRotation)) && - e(t, function(a) { - var b; - if (a === h || (a && -90 <= a && 90 >= a)) - (z = x(Math.abs(m.h / Math.sin(w * a)))), - (b = z + Math.abs(a / 360)), - b < A && ((A = b), (q = a), (d = z)); - }) - : a.step || (d = x(m.h)); - this.autoRotation = t; - this.labelRotation = C(q, h); - return d; - }, - getSlotWidth: function() { - var a = this.chart, - b = this.horiz, - c = this.options.labels, - d = Math.max( - this.tickPositions.length - (this.categories ? 0 : 1), - 1, - ), - k = a.margin[3]; - return ( - (b && - 2 > (c.step || 0) && - !c.rotation && - ((this.staggerLines || 1) * this.len) / d) || - (!b && - ((c.style && parseInt(c.style.width, 10)) || - (k && k - a.spacing[3]) || - 0.33 * a.chartWidth)) - ); - }, - renderUnsquish: function() { - var a = this.chart, - b = a.renderer, - c = this.tickPositions, - d = this.ticks, - k = this.options.labels, - q = this.horiz, - h = this.getSlotWidth(), - m = Math.max(1, Math.round(h - 2 * (k.padding || 5))), - z = {}, - A = this.labelMetrics(), - t = k.style && k.style.textOverflow, - f, - F = 0, - l, - B; - I(k.rotation) || (z.rotation = k.rotation || 0); - e(c, function(a) { - (a = d[a]) && a.labelLength > F && (F = a.labelLength); - }); - this.maxLabelLength = F; - if (this.autoRotation) - F > m && F > A.h - ? (z.rotation = this.labelRotation) - : (this.labelRotation = 0); - else if (h && ((f = { width: m + 'px' }), !t)) - for (f.textOverflow = 'clip', l = c.length; !q && l--; ) - if (((B = c[l]), (m = d[B].label))) - m.styles && 'ellipsis' === m.styles.textOverflow - ? m.css({ textOverflow: 'clip' }) - : d[B].labelLength > h && m.css({ width: h + 'px' }), - m.getBBox().height > this.len / c.length - (A.h - A.f) && - (m.specCss = { textOverflow: 'ellipsis' }); - z.rotation && - ((f = { - width: - (F > 0.5 * a.chartHeight ? 0.33 * a.chartHeight : a.chartHeight) + - 'px', - }), - t || (f.textOverflow = 'ellipsis')); - if ( - (this.labelAlign = k.align || this.autoLabelAlign(this.labelRotation)) - ) - z.align = this.labelAlign; - e(c, function(a) { - var b = (a = d[a]) && a.label; - b && - (b.attr(z), - f && b.css(x(f, b.specCss)), - delete b.specCss, - (a.rotation = z.rotation)); - }); - this.tickRotCorr = b.rotCorr( - A.b, - this.labelRotation || 0, - 0 !== this.side, - ); - }, - hasData: function() { - return ( - this.hasVisibleSeries || - (n(this.min) && - n(this.max) && - this.tickPositions && - 0 < this.tickPositions.length) - ); - }, - addTitle: function(a) { - var b = this.chart.renderer, - g = this.horiz, - c = this.opposite, - d = this.options.title, - k; - this.axisTitle || - ((k = d.textAlign) || - (k = (g - ? { low: 'left', middle: 'center', high: 'right' } - : { - low: c ? 'right' : 'left', - middle: 'center', - high: c ? 'left' : 'right', - })[d.align]), - (this.axisTitle = b - .text(d.text, 0, 0, d.useHTML) - .attr({ zIndex: 7, rotation: d.rotation || 0, align: k }) - .addClass('highcharts-axis-title') - .css(d.style) - .add(this.axisGroup)), - (this.axisTitle.isNew = !0)); - d.style.width || - this.isRadial || - this.axisTitle.css({ width: this.len }); - this.axisTitle[a ? 'show' : 'hide'](!0); - }, - generateTick: function(a) { - var b = this.ticks; - b[a] ? b[a].addLabel() : (b[a] = new F(this, a)); - }, - getOffset: function() { - var a = this, - b = a.chart, - c = b.renderer, - d = a.options, - k = a.tickPositions, - q = a.ticks, - h = a.horiz, - m = a.side, - z = b.inverted && !a.isZAxis ? [1, 0, 3, 2][m] : m, - A, - x, - f = 0, - F, - l = 0, - B = d.title, - u = d.labels, - G = 0, - p = b.axisOffset, - b = b.clipOffset, - I = [-1, 1, 1, -1][m], - r = d.className, - w = a.axisParent, - K = this.tickSize('tick'); - A = a.hasData(); - a.showAxis = x = A || C(d.showEmpty, !0); - a.staggerLines = a.horiz && u.staggerLines; - a.axisGroup || - ((a.gridGroup = c - .g('grid') - .attr({ zIndex: d.gridZIndex || 1 }) - .addClass( - 'highcharts-' + this.coll.toLowerCase() + '-grid ' + (r || ''), - ) - .add(w)), - (a.axisGroup = c - .g('axis') - .attr({ zIndex: d.zIndex || 2 }) - .addClass('highcharts-' + this.coll.toLowerCase() + ' ' + (r || '')) - .add(w)), - (a.labelGroup = c - .g('axis-labels') - .attr({ zIndex: u.zIndex || 7 }) - .addClass( - 'highcharts-' + a.coll.toLowerCase() + '-labels ' + (r || ''), - ) - .add(w))); - A || a.isLinked - ? (e(k, function(b, c) { - a.generateTick(b, c); - }), - a.renderUnsquish(), - (a.reserveSpaceDefault = - 0 === m || - 2 === m || - { 1: 'left', 3: 'right' }[m] === a.labelAlign), - C( - u.reserveSpace, - 'center' === a.labelAlign ? !0 : null, - a.reserveSpaceDefault, - ) && - e(k, function(a) { - G = Math.max(q[a].getLabelSize(), G); - }), - a.staggerLines && (G *= a.staggerLines), - (a.labelOffset = G * (a.opposite ? -1 : 1))) - : t(q, function(a, b) { - a.destroy(); - delete q[b]; - }); - B && - B.text && - !1 !== B.enabled && - (a.addTitle(x), - x && - !1 !== B.reserveSpace && - ((a.titleOffset = f = a.axisTitle.getBBox()[ - h ? 'height' : 'width' - ]), - (F = B.offset), - (l = n(F) ? 0 : C(B.margin, h ? 5 : 10)))); - a.renderLine(); - a.offset = I * C(d.offset, p[m]); - a.tickRotCorr = a.tickRotCorr || { x: 0, y: 0 }; - c = 0 === m ? -a.labelMetrics().h : 2 === m ? a.tickRotCorr.y : 0; - l = Math.abs(G) + l; - G && (l = l - c + I * (h ? C(u.y, a.tickRotCorr.y + 8 * I) : u.x)); - a.axisTitleMargin = C(F, l); - p[m] = Math.max( - p[m], - a.axisTitleMargin + f + I * a.offset, - l, - A && k.length && K ? K[0] + I * a.offset : 0, - ); - d = d.offset ? 0 : 2 * Math.floor(a.axisLine.strokeWidth() / 2); - b[z] = Math.max(b[z], d); - }, - getLinePath: function(a) { - var b = this.chart, - c = this.opposite, - g = this.offset, - d = this.horiz, - k = this.left + (c ? this.width : 0) + g, - g = b.chartHeight - this.bottom - (c ? this.height : 0) + g; - c && (a *= -1); - return b.renderer.crispLine( - [ - 'M', - d ? this.left : k, - d ? g : this.top, - 'L', - d ? b.chartWidth - this.right : k, - d ? g : b.chartHeight - this.bottom, - ], - a, - ); - }, - renderLine: function() { - this.axisLine || - ((this.axisLine = this.chart.renderer - .path() - .addClass('highcharts-axis-line') - .add(this.axisGroup)), - this.axisLine.attr({ - stroke: this.options.lineColor, - 'stroke-width': this.options.lineWidth, - zIndex: 7, - })); - }, - getTitlePosition: function() { - var a = this.horiz, - b = this.left, - c = this.top, - d = this.len, - k = this.options.title, - q = a ? b : c, - e = this.opposite, - h = this.offset, - m = k.x || 0, - z = k.y || 0, - A = this.axisTitle, - t = this.chart.renderer.fontMetrics(k.style && k.style.fontSize, A), - A = Math.max(A.getBBox(null, 0).height - t.h - 1, 0), - d = { - low: q + (a ? 0 : d), - middle: q + d / 2, - high: q + (a ? d : 0), - }[k.align], - b = - (a ? c + this.height : b) + - (a ? 1 : -1) * (e ? -1 : 1) * this.axisTitleMargin + - [-A, A, t.f, -A][this.side]; - return { - x: a ? d + m : b + (e ? this.width : 0) + h + m, - y: a ? b + z - (e ? this.height : 0) + h : d + z, - }; - }, - renderMinorTick: function(a) { - var b = this.chart.hasRendered && B(this.oldMin), - c = this.minorTicks; - c[a] || (c[a] = new F(this, a, 'minor')); - b && c[a].isNew && c[a].render(null, !0); - c[a].render(null, !1, 1); - }, - renderTick: function(a, b) { - var c = this.isLinked, - g = this.ticks, - d = this.chart.hasRendered && B(this.oldMin); - if (!c || (a >= this.min && a <= this.max)) - g[a] || (g[a] = new F(this, a)), - d && g[a].isNew && g[a].render(b, !0, 0.1), - g[a].render(b); - }, - render: function() { - var b = this, - c = b.chart, - d = b.options, - k = b.isLog, - q = b.lin2log, - h = b.isLinked, - m = b.tickPositions, - z = b.axisTitle, - x = b.ticks, - f = b.minorTicks, - l = b.alternateBands, - C = d.stackLabels, - n = d.alternateGridColor, - u = b.tickmarkOffset, - G = b.axisLine, - p = b.showAxis, - I = D(c.renderer.globalAnimation), - r, - w; - b.labelEdge.length = 0; - b.overlap = !1; - e([x, f, l], function(a) { - t(a, function(a) { - a.isActive = !1; - }); - }); - if (b.hasData() || h) - b.minorTickInterval && - !b.categories && - e(b.getMinorTickPositions(), function(a) { - b.renderMinorTick(a); - }), - m.length && - (e(m, function(a, c) { - b.renderTick(a, c); - }), - u && - (0 === b.min || b.single) && - (x[-1] || (x[-1] = new F(b, -1, null, !0)), x[-1].render(-1))), - n && - e(m, function(d, g) { - w = void 0 !== m[g + 1] ? m[g + 1] + u : b.max - u; - 0 === g % 2 && - d < b.max && - w <= b.max + (c.polar ? -u : u) && - (l[d] || (l[d] = new a.PlotLineOrBand(b)), - (r = d + u), - (l[d].options = { - from: k ? q(r) : r, - to: k ? q(w) : w, - color: n, - }), - l[d].render(), - (l[d].isActive = !0)); - }), - b._addedPlotLB || - (e((d.plotLines || []).concat(d.plotBands || []), function(a) { - b.addPlotBandOrLine(a); - }), - (b._addedPlotLB = !0)); - e([x, f, l], function(a) { - var b, - d = [], - g = I.duration; - t(a, function(a, b) { - a.isActive || (a.render(b, !1, 0), (a.isActive = !1), d.push(b)); - }); - A( - function() { - for (b = d.length; b--; ) - a[d[b]] && - !a[d[b]].isActive && - (a[d[b]].destroy(), delete a[d[b]]); - }, - a !== l && c.hasRendered && g ? g : 0, - ); - }); - G && - (G[G.isPlaced ? 'animate' : 'attr']({ - d: this.getLinePath(G.strokeWidth()), - }), - (G.isPlaced = !0), - G[p ? 'show' : 'hide'](!0)); - z && - p && - ((d = b.getTitlePosition()), - B(d.y) - ? (z[z.isNew ? 'attr' : 'animate'](d), (z.isNew = !1)) - : (z.attr('y', -9999), (z.isNew = !0))); - C && C.enabled && b.renderStackTotals(); - b.isDirty = !1; - }, - redraw: function() { - this.visible && - (this.render(), - e(this.plotLinesAndBands, function(a) { - a.render(); - })); - e(this.series, function(a) { - a.isDirty = !0; - }); - }, - keepProps: 'extKey hcEvents names series userMax userMin'.split(' '), - destroy: function(a) { - var b = this, - c = b.stacks, - d = b.plotLinesAndBands, - g; - a || N(b); - t(c, function(a, b) { - u(a); - c[b] = null; - }); - e([b.ticks, b.minorTicks, b.alternateBands], function(a) { - u(a); - }); - if (d) for (a = d.length; a--; ) d[a].destroy(); - e( - 'stackTotalGroup axisLine axisTitle axisGroup gridGroup labelGroup cross'.split( - ' ', - ), - function(a) { - b[a] && (b[a] = b[a].destroy()); - }, - ); - for (g in b.plotLinesAndBandsGroups) - b.plotLinesAndBandsGroups[g] = b.plotLinesAndBandsGroups[g].destroy(); - t(b, function(a, c) { - -1 === k(c, b.keepProps) && delete b[c]; - }); - }, - drawCrosshair: function(a, b) { - var c, - d = this.crosshair, - g = C(d.snap, !0), - k, - q = this.cross; - a || (a = this.cross && this.cross.e); - this.crosshair && !1 !== (n(b) || !g) - ? (g - ? n(b) && (k = this.isXAxis ? b.plotX : this.len - b.plotY) - : (k = - a && - (this.horiz - ? a.chartX - this.pos - : this.len - a.chartY + this.pos)), - n(k) && - (c = - this.getPlotLinePath( - b && (this.isXAxis ? b.x : C(b.stackY, b.y)), - null, - null, - null, - k, - ) || null), - n(c) - ? ((b = this.categories && !this.isRadial), - q || - ((this.cross = q = this.chart.renderer - .path() - .addClass( - 'highcharts-crosshair highcharts-crosshair-' + - (b ? 'category ' : 'thin ') + - d.className, - ) - .attr({ zIndex: C(d.zIndex, 2) }) - .add()), - q - .attr({ - stroke: - d.color || - (b - ? f('#ccd6eb') - .setOpacity(0.25) - .get() - : '#cccccc'), - 'stroke-width': C(d.width, 1), - }) - .css({ 'pointer-events': 'none' }), - d.dashStyle && q.attr({ dashstyle: d.dashStyle })), - q.show().attr({ d: c }), - b && !d.width && q.attr({ 'stroke-width': this.transA }), - (this.cross.e = a)) - : this.hideCrosshair()) - : this.hideCrosshair(); - }, - hideCrosshair: function() { - this.cross && this.cross.hide(); - }, - }); - return (a.Axis = G); - })(M); - (function(a) { - var E = a.Axis, - D = a.Date, - H = a.dateFormat, - p = a.defaultOptions, - f = a.defined, - l = a.each, - r = a.extend, - n = a.getMagnitude, - w = a.getTZOffset, - u = a.normalizeTickInterval, - e = a.pick, - h = a.timeUnits; - E.prototype.getTimeTicks = function(a, d, c, b) { - var k = [], - m = {}, - B = p.global.useUTC, - n, - x = new D(d - Math.max(w(d), w(c))), - u = D.hcMakeTime, - t = a.unitRange, - C = a.count, - N, - q; - if (f(d)) { - x[D.hcSetMilliseconds]( - t >= h.second ? 0 : C * Math.floor(x.getMilliseconds() / C), - ); - if (t >= h.second) - x[D.hcSetSeconds]( - t >= h.minute ? 0 : C * Math.floor(x.getSeconds() / C), - ); - if (t >= h.minute) - x[D.hcSetMinutes]( - t >= h.hour ? 0 : C * Math.floor(x[D.hcGetMinutes]() / C), - ); - if (t >= h.hour) - x[D.hcSetHours]( - t >= h.day ? 0 : C * Math.floor(x[D.hcGetHours]() / C), - ); - if (t >= h.day) - x[D.hcSetDate]( - t >= h.month ? 1 : C * Math.floor(x[D.hcGetDate]() / C), - ); - t >= h.month && - (x[D.hcSetMonth]( - t >= h.year ? 0 : C * Math.floor(x[D.hcGetMonth]() / C), - ), - (n = x[D.hcGetFullYear]())); - if (t >= h.year) x[D.hcSetFullYear](n - (n % C)); - if (t === h.week) - x[D.hcSetDate](x[D.hcGetDate]() - x[D.hcGetDay]() + e(b, 1)); - n = x[D.hcGetFullYear](); - b = x[D.hcGetMonth](); - var A = x[D.hcGetDate](), - F = x[D.hcGetHours](); - d = x.getTime(); - D.hcHasTimeZone && - ((q = - (!B || !!D.hcGetTimezoneOffset) && - (c - d > 4 * h.month || w(d) !== w(c))), - (N = w(x)), - (x = new D(d + N))); - B = x.getTime(); - for (d = 1; B < c; ) - k.push(B), - (B = - t === h.year - ? u(n + d * C, 0) - : t === h.month - ? u(n, b + d * C) - : !q || (t !== h.day && t !== h.week) - ? q && t === h.hour - ? u(n, b, A, F + d * C, 0, 0, N) - N - : B + t * C - : u(n, b, A + d * C * (t === h.day ? 1 : 7))), - d++; - k.push(B); - t <= h.hour && - 1e4 > k.length && - l(k, function(a) { - 0 === a % 18e5 && - '000000000' === H('%H%M%S%L', a) && - (m[a] = 'day'); - }); - } - k.info = r(a, { higherRanks: m, totalRange: t * C }); - return k; - }; - E.prototype.normalizeTimeTickInterval = function(a, d) { - var c = d || [ - ['millisecond', [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]], - ['second', [1, 2, 5, 10, 15, 30]], - ['minute', [1, 2, 5, 10, 15, 30]], - ['hour', [1, 2, 3, 4, 6, 8, 12]], - ['day', [1, 2]], - ['week', [1, 2]], - ['month', [1, 2, 3, 4, 6]], - ['year', null], - ]; - d = c[c.length - 1]; - var b = h[d[0]], - k = d[1], - e; - for ( - e = 0; - e < c.length && - !((d = c[e]), - (b = h[d[0]]), - (k = d[1]), - c[e + 1] && a <= (b * k[k.length - 1] + h[c[e + 1][0]]) / 2); - e++ - ); - b === h.year && a < 5 * b && (k = [1, 2, 5]); - a = u(a / b, k, 'year' === d[0] ? Math.max(n(a / b), 1) : 1); - return { unitRange: b, count: a, unitName: d[0] }; - }; - })(M); - (function(a) { - var E = a.Axis, - D = a.getMagnitude, - H = a.map, - p = a.normalizeTickInterval, - f = a.pick; - E.prototype.getLogTickPositions = function(a, r, n, w) { - var l = this.options, - e = this.len, - h = this.lin2log, - m = this.log2lin, - d = []; - w || (this._minorAutoInterval = null); - if (0.5 <= a) - (a = Math.round(a)), (d = this.getLinearTickPositions(a, r, n)); - else if (0.08 <= a) - for ( - var e = Math.floor(r), - c, - b, - k, - z, - B, - l = - 0.3 < a - ? [1, 2, 4] - : 0.15 < a - ? [1, 2, 4, 6, 8] - : [1, 2, 3, 4, 5, 6, 7, 8, 9]; - e < n + 1 && !B; - e++ - ) - for (b = l.length, c = 0; c < b && !B; c++) - (k = m(h(e) * l[c])), - k > r && (!w || z <= n) && void 0 !== z && d.push(z), - z > n && (B = !0), - (z = k); - else - (r = h(r)), - (n = h(n)), - (a = w ? this.getMinorTickInterval() : l.tickInterval), - (a = f( - 'auto' === a ? null : a, - this._minorAutoInterval, - ((l.tickPixelInterval / (w ? 5 : 1)) * (n - r)) / - ((w ? e / this.tickPositions.length : e) || 1), - )), - (a = p(a, null, D(a))), - (d = H(this.getLinearTickPositions(a, r, n), m)), - w || (this._minorAutoInterval = a / 5); - w || (this.tickInterval = a); - return d; - }; - E.prototype.log2lin = function(a) { - return Math.log(a) / Math.LN10; - }; - E.prototype.lin2log = function(a) { - return Math.pow(10, a); - }; - })(M); - (function(a, E) { - var D = a.arrayMax, - H = a.arrayMin, - p = a.defined, - f = a.destroyObjectProperties, - l = a.each, - r = a.erase, - n = a.merge, - w = a.pick; - a.PlotLineOrBand = function(a, e) { - this.axis = a; - e && ((this.options = e), (this.id = e.id)); - }; - a.PlotLineOrBand.prototype = { - render: function() { - var f = this, - e = f.axis, - h = e.horiz, - m = f.options, - d = m.label, - c = f.label, - b = m.to, - k = m.from, - z = m.value, - l = p(k) && p(b), - r = p(z), - x = f.svgElem, - K = !x, - t = [], - C = m.color, - N = w(m.zIndex, 0), - q = m.events, - t = { - class: - 'highcharts-plot-' + - (l ? 'band ' : 'line ') + - (m.className || ''), - }, - A = {}, - F = e.chart.renderer, - G = l ? 'bands' : 'lines', - g = e.log2lin; - e.isLog && ((k = g(k)), (b = g(b)), (z = g(z))); - r - ? ((t = { stroke: C, 'stroke-width': m.width }), - m.dashStyle && (t.dashstyle = m.dashStyle)) - : l && - (C && (t.fill = C), - m.borderWidth && - ((t.stroke = m.borderColor), - (t['stroke-width'] = m.borderWidth))); - A.zIndex = N; - G += '-' + N; - (C = e.plotLinesAndBandsGroups[G]) || - (e.plotLinesAndBandsGroups[G] = C = F.g('plot-' + G) - .attr(A) - .add()); - K && - (f.svgElem = x = F.path() - .attr(t) - .add(C)); - if (r) t = e.getPlotLinePath(z, x.strokeWidth()); - else if (l) t = e.getPlotBandPath(k, b, m); - else return; - K && t && t.length - ? (x.attr({ d: t }), - q && - a.objectEach(q, function(a, b) { - x.on(b, function(a) { - q[b].apply(f, [a]); - }); - })) - : x && - (t - ? (x.show(), x.animate({ d: t })) - : (x.hide(), c && (f.label = c = c.destroy()))); - d && - p(d.text) && - t && - t.length && - 0 < e.width && - 0 < e.height && - !t.flat - ? ((d = n( - { - align: h && l && 'center', - x: h ? !l && 4 : 10, - verticalAlign: !h && l && 'middle', - y: h ? (l ? 16 : 10) : l ? 6 : -4, - rotation: h && !l && 90, - }, - d, - )), - this.renderLabel(d, t, l, N)) - : c && c.hide(); - return f; - }, - renderLabel: function(a, e, h, m) { - var d = this.label, - c = this.axis.chart.renderer; - d || - ((d = { - align: a.textAlign || a.align, - rotation: a.rotation, - class: - 'highcharts-plot-' + - (h ? 'band' : 'line') + - '-label ' + - (a.className || ''), - }), - (d.zIndex = m), - (this.label = d = c - .text(a.text, 0, 0, a.useHTML) - .attr(d) - .add()), - d.css(a.style)); - m = e.xBounds || [e[1], e[4], h ? e[6] : e[1]]; - e = e.yBounds || [e[2], e[5], h ? e[7] : e[2]]; - h = H(m); - c = H(e); - d.align(a, !1, { x: h, y: c, width: D(m) - h, height: D(e) - c }); - d.show(); - }, - destroy: function() { - r(this.axis.plotLinesAndBands, this); - delete this.axis; - f(this); - }, - }; - a.extend(E.prototype, { - getPlotBandPath: function(a, e) { - var h = this.getPlotLinePath(e, null, null, !0), - m = this.getPlotLinePath(a, null, null, !0), - d = [], - c = this.horiz, - b = 1, - k; - a = (a < this.min && e < this.min) || (a > this.max && e > this.max); - if (m && h) - for ( - a && ((k = m.toString() === h.toString()), (b = 0)), a = 0; - a < m.length; - a += 6 - ) - c && h[a + 1] === m[a + 1] - ? ((h[a + 1] += b), (h[a + 4] += b)) - : c || - h[a + 2] !== m[a + 2] || - ((h[a + 2] += b), (h[a + 5] += b)), - d.push( - 'M', - m[a + 1], - m[a + 2], - 'L', - m[a + 4], - m[a + 5], - h[a + 4], - h[a + 5], - h[a + 1], - h[a + 2], - 'z', - ), - (d.flat = k); - return d; - }, - addPlotBand: function(a) { - return this.addPlotBandOrLine(a, 'plotBands'); - }, - addPlotLine: function(a) { - return this.addPlotBandOrLine(a, 'plotLines'); - }, - addPlotBandOrLine: function(f, e) { - var h = new a.PlotLineOrBand(this, f).render(), - m = this.userOptions; - h && - (e && ((m[e] = m[e] || []), m[e].push(f)), - this.plotLinesAndBands.push(h)); - return h; - }, - removePlotBandOrLine: function(a) { - for ( - var e = this.plotLinesAndBands, - h = this.options, - m = this.userOptions, - d = e.length; - d--; - - ) - e[d].id === a && e[d].destroy(); - l( - [ - h.plotLines || [], - m.plotLines || [], - h.plotBands || [], - m.plotBands || [], - ], - function(c) { - for (d = c.length; d--; ) c[d].id === a && r(c, c[d]); - }, - ); - }, - removePlotBand: function(a) { - this.removePlotBandOrLine(a); - }, - removePlotLine: function(a) { - this.removePlotBandOrLine(a); - }, - }); - })(M, V); - (function(a) { - var E = a.dateFormat, - D = a.each, - H = a.extend, - p = a.format, - f = a.isNumber, - l = a.map, - r = a.merge, - n = a.pick, - w = a.splat, - u = a.syncTimeout, - e = a.timeUnits; - a.Tooltip = function() { - this.init.apply(this, arguments); - }; - a.Tooltip.prototype = { - init: function(a, e) { - this.chart = a; - this.options = e; - this.crosshairs = []; - this.now = { x: 0, y: 0 }; - this.isHidden = !0; - this.split = e.split && !a.inverted; - this.shared = e.shared || this.split; - }, - cleanSplit: function(a) { - D(this.chart.series, function(e) { - var d = e && e.tt; - d && (!d.isActive || a ? (e.tt = d.destroy()) : (d.isActive = !1)); - }); - }, - getLabel: function() { - var a = this.chart.renderer, - e = this.options; - this.label || - (this.split - ? (this.label = a.g('tooltip')) - : ((this.label = a - .label( - '', - 0, - 0, - e.shape || 'callout', - null, - null, - e.useHTML, - null, - 'tooltip', - ) - .attr({ padding: e.padding, r: e.borderRadius })), - this.label - .attr({ - fill: e.backgroundColor, - 'stroke-width': e.borderWidth, - }) - .css(e.style) - .shadow(e.shadow)), - this.label.attr({ zIndex: 8 }).add()); - return this.label; - }, - update: function(a) { - this.destroy(); - r(!0, this.chart.options.tooltip.userOptions, a); - this.init(this.chart, r(!0, this.options, a)); - }, - destroy: function() { - this.label && (this.label = this.label.destroy()); - this.split && - this.tt && - (this.cleanSplit(this.chart, !0), (this.tt = this.tt.destroy())); - clearTimeout(this.hideTimer); - clearTimeout(this.tooltipTimeout); - }, - move: function(a, e, d, c) { - var b = this, - k = b.now, - h = - !1 !== b.options.animation && - !b.isHidden && - (1 < Math.abs(a - k.x) || 1 < Math.abs(e - k.y)), - m = b.followPointer || 1 < b.len; - H(k, { - x: h ? (2 * k.x + a) / 3 : a, - y: h ? (k.y + e) / 2 : e, - anchorX: m ? void 0 : h ? (2 * k.anchorX + d) / 3 : d, - anchorY: m ? void 0 : h ? (k.anchorY + c) / 2 : c, - }); - b.getLabel().attr(k); - h && - (clearTimeout(this.tooltipTimeout), - (this.tooltipTimeout = setTimeout(function() { - b && b.move(a, e, d, c); - }, 32))); - }, - hide: function(a) { - var e = this; - clearTimeout(this.hideTimer); - a = n(a, this.options.hideDelay, 500); - this.isHidden || - (this.hideTimer = u(function() { - e.getLabel()[a ? 'fadeOut' : 'hide'](); - e.isHidden = !0; - }, a)); - }, - getAnchor: function(a, e) { - var d, - c = this.chart, - b = c.inverted, - k = c.plotTop, - h = c.plotLeft, - m = 0, - f = 0, - x, - n; - a = w(a); - d = a[0].tooltipPos; - this.followPointer && - e && - (void 0 === e.chartX && (e = c.pointer.normalize(e)), - (d = [e.chartX - c.plotLeft, e.chartY - k])); - d || - (D(a, function(a) { - x = a.series.yAxis; - n = a.series.xAxis; - m += a.plotX + (!b && n ? n.left - h : 0); - f += - (a.plotLow ? (a.plotLow + a.plotHigh) / 2 : a.plotY) + - (!b && x ? x.top - k : 0); - }), - (m /= a.length), - (f /= a.length), - (d = [ - b ? c.plotWidth - f : m, - this.shared && !b && 1 < a.length && e - ? e.chartY - k - : b - ? c.plotHeight - m - : f, - ])); - return l(d, Math.round); - }, - getPosition: function(a, e, d) { - var c = this.chart, - b = this.distance, - k = {}, - h = (c.inverted && d.h) || 0, - m, - f = [ - 'y', - c.chartHeight, - e, - d.plotY + c.plotTop, - c.plotTop, - c.plotTop + c.plotHeight, - ], - x = [ - 'x', - c.chartWidth, - a, - d.plotX + c.plotLeft, - c.plotLeft, - c.plotLeft + c.plotWidth, - ], - l = !this.followPointer && n(d.ttBelow, !c.inverted === !!d.negative), - t = function(a, c, d, g, e, q) { - var m = d < g - b, - z = g + b + d < c, - A = g - b - d; - g += b; - if (l && z) k[a] = g; - else if (!l && m) k[a] = A; - else if (m) k[a] = Math.min(q - d, 0 > A - h ? A : A - h); - else if (z) k[a] = Math.max(e, g + h + d > c ? g : g + h); - else return !1; - }, - C = function(a, c, d, g) { - var e; - g < b || g > c - b - ? (e = !1) - : (k[a] = g < d / 2 ? 1 : g > c - d / 2 ? c - d - 2 : g - d / 2); - return e; - }, - p = function(a) { - var b = f; - f = x; - x = b; - m = a; - }, - q = function() { - !1 !== t.apply(0, f) - ? !1 !== C.apply(0, x) || m || (p(!0), q()) - : m - ? (k.x = k.y = 0) - : (p(!0), q()); - }; - (c.inverted || 1 < this.len) && p(); - q(); - return k; - }, - defaultFormatter: function(a) { - var e = this.points || w(this), - d; - d = [a.tooltipFooterHeaderFormatter(e[0])]; - d = d.concat(a.bodyFormatter(e)); - d.push(a.tooltipFooterHeaderFormatter(e[0], !0)); - return d; - }, - refresh: function(a, e) { - var d, - c = this.options, - b, - k = a, - h, - m = {}, - f = []; - d = c.formatter || this.defaultFormatter; - var m = this.shared, - x; - c.enabled && - (clearTimeout(this.hideTimer), - (this.followPointer = w(k)[0].series.tooltipOptions.followPointer), - (h = this.getAnchor(k, e)), - (e = h[0]), - (b = h[1]), - !m || (k.series && k.series.noSharedTooltip) - ? (m = k.getLabelConfig()) - : (D(k, function(a) { - a.setState('hover'); - f.push(a.getLabelConfig()); - }), - (m = { x: k[0].category, y: k[0].y }), - (m.points = f), - (k = k[0])), - (this.len = f.length), - (m = d.call(m, this)), - (x = k.series), - (this.distance = n(x.tooltipOptions.distance, 16)), - !1 === m - ? this.hide() - : ((d = this.getLabel()), - this.isHidden && d.attr({ opacity: 1 }).show(), - this.split - ? this.renderSplit(m, w(a)) - : (c.style.width || - d.css({ width: this.chart.spacingBox.width }), - d.attr({ text: m && m.join ? m.join('') : m }), - d - .removeClass(/highcharts-color-[\d]+/g) - .addClass( - 'highcharts-color-' + n(k.colorIndex, x.colorIndex), - ), - d.attr({ - stroke: c.borderColor || k.color || x.color || '#666666', - }), - this.updatePosition({ - plotX: e, - plotY: b, - negative: k.negative, - ttBelow: k.ttBelow, - h: h[2] || 0, - })), - (this.isHidden = !1))); - }, - renderSplit: function(e, m) { - var d = this, - c = [], - b = this.chart, - k = b.renderer, - h = !0, - f = this.options, - l = 0, - x = this.getLabel(); - a.isString(e) && (e = [!1, e]); - D(e.slice(0, m.length + 1), function(a, e) { - if (!1 !== a) { - e = m[e - 1] || { isHeader: !0, plotX: m[0].plotX }; - var z = e.series || d, - t = z.tt, - q = e.series || {}, - A = 'highcharts-color-' + n(e.colorIndex, q.colorIndex, 'none'); - t || - (z.tt = t = k - .label(null, null, null, 'callout', null, null, f.useHTML) - .addClass('highcharts-tooltip-box ' + A) - .attr({ - padding: f.padding, - r: f.borderRadius, - fill: f.backgroundColor, - stroke: f.borderColor || e.color || q.color || '#333333', - 'stroke-width': f.borderWidth, - }) - .add(x)); - t.isActive = !0; - t.attr({ text: a }); - t.css(f.style).shadow(f.shadow); - a = t.getBBox(); - q = a.width + t.strokeWidth(); - e.isHeader - ? ((l = a.height), - (q = Math.max( - 0, - Math.min(e.plotX + b.plotLeft - q / 2, b.chartWidth - q), - ))) - : (q = e.plotX + b.plotLeft - n(f.distance, 16) - q); - 0 > q && (h = !1); - a = - (e.series && e.series.yAxis && e.series.yAxis.pos) + - (e.plotY || 0); - a -= b.plotTop; - c.push({ - target: e.isHeader ? b.plotHeight + l : a, - rank: e.isHeader ? 1 : 0, - size: z.tt.getBBox().height + 1, - point: e, - x: q, - tt: t, - }); - } - }); - this.cleanSplit(); - a.distribute(c, b.plotHeight + l); - D(c, function(a) { - var c = a.point, - d = c.series; - a.tt.attr({ - visibility: void 0 === a.pos ? 'hidden' : 'inherit', - x: h || c.isHeader ? a.x : c.plotX + b.plotLeft + n(f.distance, 16), - y: a.pos + b.plotTop, - anchorX: c.isHeader ? c.plotX + b.plotLeft : c.plotX + d.xAxis.pos, - anchorY: c.isHeader - ? a.pos + b.plotTop - 15 - : c.plotY + d.yAxis.pos, - }); - }); - }, - updatePosition: function(a) { - var e = this.chart, - d = this.getLabel(), - d = (this.options.positioner || this.getPosition).call( - this, - d.width, - d.height, - a, - ); - this.move( - Math.round(d.x), - Math.round(d.y || 0), - a.plotX + e.plotLeft, - a.plotY + e.plotTop, - ); - }, - getDateFormat: function(a, m, d, c) { - var b = E('%m-%d %H:%M:%S.%L', m), - k, - h, - f = { millisecond: 15, second: 12, minute: 9, hour: 6, day: 3 }, - l = 'millisecond'; - for (h in e) { - if ( - a === e.week && - +E('%w', m) === d && - '00:00:00.000' === b.substr(6) - ) { - h = 'week'; - break; - } - if (e[h] > a) { - h = l; - break; - } - if (f[h] && b.substr(f[h]) !== '01-01 00:00:00.000'.substr(f[h])) - break; - 'week' !== h && (l = h); - } - h && (k = c[h]); - return k; - }, - getXDateFormat: function(a, e, d) { - e = e.dateTimeLabelFormats; - var c = d && d.closestPointRange; - return ( - (c ? this.getDateFormat(c, a.x, d.options.startOfWeek, e) : e.day) || - e.year - ); - }, - tooltipFooterHeaderFormatter: function(a, e) { - e = e ? 'footer' : 'header'; - var d = a.series, - c = d.tooltipOptions, - b = c.xDateFormat, - k = d.xAxis, - h = k && 'datetime' === k.options.type && f(a.key), - m = c[e + 'Format']; - h && !b && (b = this.getXDateFormat(a, c, k)); - h && - b && - D((a.point && a.point.tooltipDateKeys) || ['key'], function(a) { - m = m.replace('{point.' + a + '}', '{point.' + a + ':' + b + '}'); - }); - return p(m, { point: a, series: d }); - }, - bodyFormatter: function(a) { - return l(a, function(a) { - var d = a.series.tooltipOptions; - return ( - d[(a.point.formatPrefix || 'point') + 'Formatter'] || - a.point.tooltipFormatter - ).call(a.point, d[(a.point.formatPrefix || 'point') + 'Format']); - }); - }, - }; - })(M); - (function(a) { - var E = a.addEvent, - D = a.attr, - H = a.charts, - p = a.color, - f = a.css, - l = a.defined, - r = a.each, - n = a.extend, - w = a.find, - u = a.fireEvent, - e = a.isObject, - h = a.offset, - m = a.pick, - d = a.splat, - c = a.Tooltip; - a.Pointer = function(a, c) { - this.init(a, c); - }; - a.Pointer.prototype = { - init: function(a, d) { - this.options = d; - this.chart = a; - this.runChartClick = d.chart.events && !!d.chart.events.click; - this.pinchDown = []; - this.lastValidTouch = {}; - c && - ((a.tooltip = new c(a, d.tooltip)), - (this.followTouchMove = m(d.tooltip.followTouchMove, !0))); - this.setDOMEvents(); - }, - zoomOption: function(a) { - var b = this.chart, - c = b.options.chart, - d = c.zoomType || '', - b = b.inverted; - /touch/.test(a.type) && (d = m(c.pinchType, d)); - this.zoomX = a = /x/.test(d); - this.zoomY = d = /y/.test(d); - this.zoomHor = (a && !b) || (d && b); - this.zoomVert = (d && !b) || (a && b); - this.hasZoom = a || d; - }, - normalize: function(a, c) { - var b; - b = a.touches - ? a.touches.length - ? a.touches.item(0) - : a.changedTouches[0] - : a; - c || (this.chartPosition = c = h(this.chart.container)); - return n(a, { - chartX: Math.round(b.pageX - c.left), - chartY: Math.round(b.pageY - c.top), - }); - }, - getCoordinates: function(a) { - var b = { xAxis: [], yAxis: [] }; - r(this.chart.axes, function(c) { - b[c.isXAxis ? 'xAxis' : 'yAxis'].push({ - axis: c, - value: c.toValue(a[c.horiz ? 'chartX' : 'chartY']), - }); - }); - return b; - }, - findNearestKDPoint: function(a, c, d) { - var b; - r(a, function(a) { - var k = - !(a.noSharedTooltip && c) && - 0 > a.options.findNearestPointBy.indexOf('y'); - a = a.searchPoint(d, k); - if ((k = e(a, !0)) && !(k = !e(b, !0))) - var k = b.distX - a.distX, - h = b.dist - a.dist, - m = - (a.series.group && a.series.group.zIndex) - - (b.series.group && b.series.group.zIndex), - k = - 0 < - (0 !== k && c - ? k - : 0 !== h - ? h - : 0 !== m - ? m - : b.series.index > a.series.index - ? -1 - : 1); - k && (b = a); - }); - return b; - }, - getPointFromEvent: function(a) { - a = a.target; - for (var b; a && !b; ) (b = a.point), (a = a.parentNode); - return b; - }, - getChartCoordinatesFromPoint: function(a, c) { - var b = a.series, - d = b.xAxis, - b = b.yAxis, - k = m(a.clientX, a.plotX); - if (d && b) - return c - ? { chartX: d.len + d.pos - k, chartY: b.len + b.pos - a.plotY } - : { chartX: k + d.pos, chartY: a.plotY + b.pos }; - }, - getHoverData: function(b, c, d, h, f, l, n) { - var k, - z = [], - x = n && n.isBoosting; - h = !(!h || !b); - n = - c && !c.stickyTracking - ? [c] - : a.grep(d, function(a) { - return ( - a.visible && - !(!f && a.directTouch) && - m(a.options.enableMouseTracking, !0) && - a.stickyTracking - ); - }); - c = (k = h ? b : this.findNearestKDPoint(n, f, l)) && k.series; - k && - (f && !c.noSharedTooltip - ? ((n = a.grep(d, function(a) { - return ( - a.visible && - !(!f && a.directTouch) && - m(a.options.enableMouseTracking, !0) && - !a.noSharedTooltip - ); - })), - r(n, function(a) { - var b = w(a.points, function(a) { - return a.x === k.x && !a.isNull; - }); - e(b) && (x && (b = a.getPoint(b)), z.push(b)); - })) - : z.push(k)); - return { hoverPoint: k, hoverSeries: c, hoverPoints: z }; - }, - runPointActions: function(b, c) { - var d = this.chart, - k = d.tooltip && d.tooltip.options.enabled ? d.tooltip : void 0, - e = k ? k.shared : !1, - h = c || d.hoverPoint, - f = (h && h.series) || d.hoverSeries, - f = this.getHoverData( - h, - f, - d.series, - !!c || (f && f.directTouch && this.isDirectTouch), - e, - b, - { isBoosting: d.isBoosting }, - ), - l, - h = f.hoverPoint; - l = f.hoverPoints; - c = (f = f.hoverSeries) && f.tooltipOptions.followPointer; - e = e && f && !f.noSharedTooltip; - if (h && (h !== d.hoverPoint || (k && k.isHidden))) { - r(d.hoverPoints || [], function(b) { - -1 === a.inArray(b, l) && b.setState(); - }); - r(l || [], function(a) { - a.setState('hover'); - }); - if (d.hoverSeries !== f) f.onMouseOver(); - d.hoverPoint && d.hoverPoint.firePointEvent('mouseOut'); - if (!h.series) return; - h.firePointEvent('mouseOver'); - d.hoverPoints = l; - d.hoverPoint = h; - k && k.refresh(e ? l : h, b); - } else - c && - k && - !k.isHidden && - ((h = k.getAnchor([{}], b)), - k.updatePosition({ plotX: h[0], plotY: h[1] })); - this.unDocMouseMove || - (this.unDocMouseMove = E( - d.container.ownerDocument, - 'mousemove', - function(b) { - var c = H[a.hoverChartIndex]; - if (c) c.pointer.onDocumentMouseMove(b); - }, - )); - r(d.axes, function(c) { - var d = m(c.crosshair.snap, !0), - k = d - ? a.find(l, function(a) { - return a.series[c.coll] === c; - }) - : void 0; - k || !d ? c.drawCrosshair(b, k) : c.hideCrosshair(); - }); - }, - reset: function(a, c) { - var b = this.chart, - k = b.hoverSeries, - e = b.hoverPoint, - h = b.hoverPoints, - m = b.tooltip, - f = m && m.shared ? h : e; - a && - f && - r(d(f), function(b) { - b.series.isCartesian && void 0 === b.plotX && (a = !1); - }); - if (a) - m && - f && - (m.refresh(f), - e && - (e.setState(e.state, !0), - r(b.axes, function(a) { - a.crosshair && a.drawCrosshair(null, e); - }))); - else { - if (e) e.onMouseOut(); - h && - r(h, function(a) { - a.setState(); - }); - if (k) k.onMouseOut(); - m && m.hide(c); - this.unDocMouseMove && (this.unDocMouseMove = this.unDocMouseMove()); - r(b.axes, function(a) { - a.hideCrosshair(); - }); - this.hoverX = b.hoverPoints = b.hoverPoint = null; - } - }, - scaleGroups: function(a, c) { - var b = this.chart, - d; - r(b.series, function(k) { - d = a || k.getPlotBox(); - k.xAxis && - k.xAxis.zoomEnabled && - k.group && - (k.group.attr(d), - k.markerGroup && - (k.markerGroup.attr(d), - k.markerGroup.clip(c ? b.clipRect : null)), - k.dataLabelsGroup && k.dataLabelsGroup.attr(d)); - }); - b.clipRect.attr(c || b.clipBox); - }, - dragStart: function(a) { - var b = this.chart; - b.mouseIsDown = a.type; - b.cancelClick = !1; - b.mouseDownX = this.mouseDownX = a.chartX; - b.mouseDownY = this.mouseDownY = a.chartY; - }, - drag: function(a) { - var b = this.chart, - c = b.options.chart, - d = a.chartX, - e = a.chartY, - h = this.zoomHor, - m = this.zoomVert, - f = b.plotLeft, - l = b.plotTop, - n = b.plotWidth, - q = b.plotHeight, - A, - F = this.selectionMarker, - G = this.mouseDownX, - g = this.mouseDownY, - v = c.panKey && a[c.panKey + 'Key']; - (F && F.touch) || - (d < f ? (d = f) : d > f + n && (d = f + n), - e < l ? (e = l) : e > l + q && (e = l + q), - (this.hasDragged = Math.sqrt( - Math.pow(G - d, 2) + Math.pow(g - e, 2), - )), - 10 < this.hasDragged && - ((A = b.isInsidePlot(G - f, g - l)), - b.hasCartesianSeries && - (this.zoomX || this.zoomY) && - A && - !v && - !F && - (this.selectionMarker = F = b.renderer - .rect(f, l, h ? 1 : n, m ? 1 : q, 0) - .attr({ - fill: - c.selectionMarkerFill || - p('#335cad') - .setOpacity(0.25) - .get(), - class: 'highcharts-selection-marker', - zIndex: 7, - }) - .add()), - F && - h && - ((d -= G), - F.attr({ width: Math.abs(d), x: (0 < d ? 0 : d) + G })), - F && - m && - ((d = e - g), - F.attr({ height: Math.abs(d), y: (0 < d ? 0 : d) + g })), - A && !F && c.panning && b.pan(a, c.panning))); - }, - drop: function(a) { - var b = this, - c = this.chart, - d = this.hasPinched; - if (this.selectionMarker) { - var e = { originalEvent: a, xAxis: [], yAxis: [] }, - h = this.selectionMarker, - m = h.attr ? h.attr('x') : h.x, - t = h.attr ? h.attr('y') : h.y, - p = h.attr ? h.attr('width') : h.width, - w = h.attr ? h.attr('height') : h.height, - q; - if (this.hasDragged || d) - r(c.axes, function(c) { - if ( - c.zoomEnabled && - l(c.min) && - (d || b[{ xAxis: 'zoomX', yAxis: 'zoomY' }[c.coll]]) - ) { - var k = c.horiz, - h = 'touchend' === a.type ? c.minPixelPadding : 0, - g = c.toValue((k ? m : t) + h), - k = c.toValue((k ? m + p : t + w) - h); - e[c.coll].push({ - axis: c, - min: Math.min(g, k), - max: Math.max(g, k), - }); - q = !0; - } - }), - q && - u(c, 'selection', e, function(a) { - c.zoom(n(a, d ? { animation: !1 } : null)); - }); - this.selectionMarker = this.selectionMarker.destroy(); - d && this.scaleGroups(); - } - c && - (f(c.container, { cursor: c._cursor }), - (c.cancelClick = 10 < this.hasDragged), - (c.mouseIsDown = this.hasDragged = this.hasPinched = !1), - (this.pinchDown = [])); - }, - onContainerMouseDown: function(a) { - 2 !== a.button && - ((a = this.normalize(a)), - this.zoomOption(a), - a.preventDefault && a.preventDefault(), - this.dragStart(a)); - }, - onDocumentMouseUp: function(b) { - H[a.hoverChartIndex] && H[a.hoverChartIndex].pointer.drop(b); - }, - onDocumentMouseMove: function(a) { - var b = this.chart, - c = this.chartPosition; - a = this.normalize(a, c); - !c || - this.inClass(a.target, 'highcharts-tracker') || - b.isInsidePlot(a.chartX - b.plotLeft, a.chartY - b.plotTop) || - this.reset(); - }, - onContainerMouseLeave: function(b) { - var c = H[a.hoverChartIndex]; - c && - (b.relatedTarget || b.toElement) && - (c.pointer.reset(), (c.pointer.chartPosition = null)); - }, - onContainerMouseMove: function(b) { - var c = this.chart; - (l(a.hoverChartIndex) && - H[a.hoverChartIndex] && - H[a.hoverChartIndex].mouseIsDown) || - (a.hoverChartIndex = c.index); - b = this.normalize(b); - b.returnValue = !1; - 'mousedown' === c.mouseIsDown && this.drag(b); - (!this.inClass(b.target, 'highcharts-tracker') && - !c.isInsidePlot(b.chartX - c.plotLeft, b.chartY - c.plotTop)) || - c.openMenu || - this.runPointActions(b); - }, - inClass: function(a, c) { - for (var b; a; ) { - if ((b = D(a, 'class'))) { - if (-1 !== b.indexOf(c)) return !0; - if (-1 !== b.indexOf('highcharts-container')) return !1; - } - a = a.parentNode; - } - }, - onTrackerMouseOut: function(a) { - var b = this.chart.hoverSeries; - a = a.relatedTarget || a.toElement; - this.isDirectTouch = !1; - if ( - !( - !b || - !a || - b.stickyTracking || - this.inClass(a, 'highcharts-tooltip') || - (this.inClass(a, 'highcharts-series-' + b.index) && - this.inClass(a, 'highcharts-tracker')) - ) - ) - b.onMouseOut(); - }, - onContainerClick: function(a) { - var b = this.chart, - c = b.hoverPoint, - d = b.plotLeft, - e = b.plotTop; - a = this.normalize(a); - b.cancelClick || - (c && this.inClass(a.target, 'highcharts-tracker') - ? (u(c.series, 'click', n(a, { point: c })), - b.hoverPoint && c.firePointEvent('click', a)) - : (n(a, this.getCoordinates(a)), - b.isInsidePlot(a.chartX - d, a.chartY - e) && u(b, 'click', a))); - }, - setDOMEvents: function() { - var b = this, - c = b.chart.container, - d = c.ownerDocument; - c.onmousedown = function(a) { - b.onContainerMouseDown(a); - }; - c.onmousemove = function(a) { - b.onContainerMouseMove(a); - }; - c.onclick = function(a) { - b.onContainerClick(a); - }; - this.unbindContainerMouseLeave = E( - c, - 'mouseleave', - b.onContainerMouseLeave, - ); - a.unbindDocumentMouseUp || - (a.unbindDocumentMouseUp = E(d, 'mouseup', b.onDocumentMouseUp)); - a.hasTouch && - ((c.ontouchstart = function(a) { - b.onContainerTouchStart(a); - }), - (c.ontouchmove = function(a) { - b.onContainerTouchMove(a); - }), - a.unbindDocumentTouchEnd || - (a.unbindDocumentTouchEnd = E( - d, - 'touchend', - b.onDocumentTouchEnd, - ))); - }, - destroy: function() { - var b = this; - b.unDocMouseMove && b.unDocMouseMove(); - this.unbindContainerMouseLeave(); - a.chartCount || - (a.unbindDocumentMouseUp && - (a.unbindDocumentMouseUp = a.unbindDocumentMouseUp()), - a.unbindDocumentTouchEnd && - (a.unbindDocumentTouchEnd = a.unbindDocumentTouchEnd())); - clearInterval(b.tooltipTimeout); - a.objectEach(b, function(a, c) { - b[c] = null; - }); - }, - }; - })(M); - (function(a) { - var E = a.charts, - D = a.each, - H = a.extend, - p = a.map, - f = a.noop, - l = a.pick; - H(a.Pointer.prototype, { - pinchTranslate: function(a, f, l, p, e, h) { - this.zoomHor && this.pinchTranslateDirection(!0, a, f, l, p, e, h); - this.zoomVert && this.pinchTranslateDirection(!1, a, f, l, p, e, h); - }, - pinchTranslateDirection: function(a, f, l, p, e, h, m, d) { - var c = this.chart, - b = a ? 'x' : 'y', - k = a ? 'X' : 'Y', - z = 'chart' + k, - n = a ? 'width' : 'height', - r = c['plot' + (a ? 'Left' : 'Top')], - x, - w, - t = d || 1, - C = c.inverted, - u = c.bounds[a ? 'h' : 'v'], - q = 1 === f.length, - A = f[0][z], - F = l[0][z], - G = !q && f[1][z], - g = !q && l[1][z], - v; - l = function() { - !q && - 20 < Math.abs(A - G) && - (t = d || Math.abs(F - g) / Math.abs(A - G)); - w = (r - F) / t + A; - x = c['plot' + (a ? 'Width' : 'Height')] / t; - }; - l(); - f = w; - f < u.min - ? ((f = u.min), (v = !0)) - : f + x > u.max && ((f = u.max - x), (v = !0)); - v - ? ((F -= 0.8 * (F - m[b][0])), q || (g -= 0.8 * (g - m[b][1])), l()) - : (m[b] = [F, g]); - C || ((h[b] = w - r), (h[n] = x)); - h = C ? 1 / t : t; - e[n] = x; - e[b] = f; - p[C ? (a ? 'scaleY' : 'scaleX') : 'scale' + k] = t; - p['translate' + k] = h * r + (F - h * A); - }, - pinch: function(a) { - var n = this, - r = n.chart, - u = n.pinchDown, - e = a.touches, - h = e.length, - m = n.lastValidTouch, - d = n.hasZoom, - c = n.selectionMarker, - b = {}, - k = - 1 === h && - ((n.inClass(a.target, 'highcharts-tracker') && r.runTrackerClick) || - n.runChartClick), - z = {}; - 1 < h && (n.initiated = !0); - d && n.initiated && !k && a.preventDefault(); - p(e, function(a) { - return n.normalize(a); - }); - 'touchstart' === a.type - ? (D(e, function(a, b) { - u[b] = { chartX: a.chartX, chartY: a.chartY }; - }), - (m.x = [u[0].chartX, u[1] && u[1].chartX]), - (m.y = [u[0].chartY, u[1] && u[1].chartY]), - D(r.axes, function(a) { - if (a.zoomEnabled) { - var b = r.bounds[a.horiz ? 'h' : 'v'], - c = a.minPixelPadding, - d = a.toPixels(l(a.options.min, a.dataMin)), - e = a.toPixels(l(a.options.max, a.dataMax)), - k = Math.max(d, e); - b.min = Math.min(a.pos, Math.min(d, e) - c); - b.max = Math.max(a.pos + a.len, k + c); - } - }), - (n.res = !0)) - : n.followTouchMove && 1 === h - ? this.runPointActions(n.normalize(a)) - : u.length && - (c || - (n.selectionMarker = c = H({ destroy: f, touch: !0 }, r.plotBox)), - n.pinchTranslate(u, e, b, c, z, m), - (n.hasPinched = d), - n.scaleGroups(b, z), - n.res && ((n.res = !1), this.reset(!1, 0))); - }, - touch: function(f, n) { - var p = this.chart, - r, - e; - if (p.index !== a.hoverChartIndex) - this.onContainerMouseLeave({ relatedTarget: !0 }); - a.hoverChartIndex = p.index; - 1 === f.touches.length - ? ((f = this.normalize(f)), - (e = p.isInsidePlot(f.chartX - p.plotLeft, f.chartY - p.plotTop)) && - !p.openMenu - ? (n && this.runPointActions(f), - 'touchmove' === f.type && - ((n = this.pinchDown), - (r = n[0] - ? 4 <= - Math.sqrt( - Math.pow(n[0].chartX - f.chartX, 2) + - Math.pow(n[0].chartY - f.chartY, 2), - ) - : !1)), - l(r, !0) && this.pinch(f)) - : n && this.reset()) - : 2 === f.touches.length && this.pinch(f); - }, - onContainerTouchStart: function(a) { - this.zoomOption(a); - this.touch(a, !0); - }, - onContainerTouchMove: function(a) { - this.touch(a); - }, - onDocumentTouchEnd: function(f) { - E[a.hoverChartIndex] && E[a.hoverChartIndex].pointer.drop(f); - }, - }); - })(M); - (function(a) { - var E = a.addEvent, - D = a.charts, - H = a.css, - p = a.doc, - f = a.extend, - l = a.noop, - r = a.Pointer, - n = a.removeEvent, - w = a.win, - u = a.wrap; - if (!a.hasTouch && (w.PointerEvent || w.MSPointerEvent)) { - var e = {}, - h = !!w.PointerEvent, - m = function() { - var c = []; - c.item = function(a) { - return this[a]; - }; - a.objectEach(e, function(a) { - c.push({ pageX: a.pageX, pageY: a.pageY, target: a.target }); - }); - return c; - }, - d = function(c, b, d, e) { - ('touch' !== c.pointerType && - c.pointerType !== c.MSPOINTER_TYPE_TOUCH) || - !D[a.hoverChartIndex] || - (e(c), - (e = D[a.hoverChartIndex].pointer), - e[b]({ - type: d, - target: c.currentTarget, - preventDefault: l, - touches: m(), - })); - }; - f(r.prototype, { - onContainerPointerDown: function(a) { - d(a, 'onContainerTouchStart', 'touchstart', function(a) { - e[a.pointerId] = { - pageX: a.pageX, - pageY: a.pageY, - target: a.currentTarget, - }; - }); - }, - onContainerPointerMove: function(a) { - d(a, 'onContainerTouchMove', 'touchmove', function(a) { - e[a.pointerId] = { pageX: a.pageX, pageY: a.pageY }; - e[a.pointerId].target || (e[a.pointerId].target = a.currentTarget); - }); - }, - onDocumentPointerUp: function(a) { - d(a, 'onDocumentTouchEnd', 'touchend', function(a) { - delete e[a.pointerId]; - }); - }, - batchMSEvents: function(a) { - a( - this.chart.container, - h ? 'pointerdown' : 'MSPointerDown', - this.onContainerPointerDown, - ); - a( - this.chart.container, - h ? 'pointermove' : 'MSPointerMove', - this.onContainerPointerMove, - ); - a(p, h ? 'pointerup' : 'MSPointerUp', this.onDocumentPointerUp); - }, - }); - u(r.prototype, 'init', function(a, b, d) { - a.call(this, b, d); - this.hasZoom && - H(b.container, { - '-ms-touch-action': 'none', - 'touch-action': 'none', - }); - }); - u(r.prototype, 'setDOMEvents', function(a) { - a.apply(this); - (this.hasZoom || this.followTouchMove) && this.batchMSEvents(E); - }); - u(r.prototype, 'destroy', function(a) { - this.batchMSEvents(n); - a.call(this); - }); - } - })(M); - (function(a) { - var E = a.addEvent, - D = a.css, - H = a.discardElement, - p = a.defined, - f = a.each, - l = a.isFirefox, - r = a.marginNames, - n = a.merge, - w = a.pick, - u = a.setAnimation, - e = a.stableSort, - h = a.win, - m = a.wrap; - a.Legend = function(a, c) { - this.init(a, c); - }; - a.Legend.prototype = { - init: function(a, c) { - this.chart = a; - this.setOptions(c); - c.enabled && - (this.render(), - E(this.chart, 'endResize', function() { - this.legend.positionCheckboxes(); - })); - }, - setOptions: function(a) { - var c = w(a.padding, 8); - this.options = a; - this.itemStyle = a.itemStyle; - this.itemHiddenStyle = n(this.itemStyle, a.itemHiddenStyle); - this.itemMarginTop = a.itemMarginTop || 0; - this.padding = c; - this.initialItemY = c - 5; - this.itemHeight = this.maxItemWidth = 0; - this.symbolWidth = w(a.symbolWidth, 16); - this.pages = []; - }, - update: function(a, c) { - var b = this.chart; - this.setOptions(n(!0, this.options, a)); - this.destroy(); - b.isDirtyLegend = b.isDirtyBox = !0; - w(c, !0) && b.redraw(); - }, - colorizeItem: function(a, c) { - a.legendGroup[c ? 'removeClass' : 'addClass']( - 'highcharts-legend-item-hidden', - ); - var b = this.options, - d = a.legendItem, - e = a.legendLine, - h = a.legendSymbol, - f = this.itemHiddenStyle.color, - b = c ? b.itemStyle.color : f, - m = c ? a.color || f : f, - l = a.options && a.options.marker, - t = { fill: m }; - d && d.css({ fill: b, color: b }); - e && e.attr({ stroke: m }); - h && - (l && - h.isMarker && - ((t = a.pointAttribs()), c || (t.stroke = t.fill = f)), - h.attr(t)); - }, - positionItem: function(a) { - var c = this.options, - b = c.symbolPadding, - c = !c.rtl, - d = a._legendItemPos, - e = d[0], - d = d[1], - h = a.checkbox; - (a = a.legendGroup) && - a.element && - a.translate(c ? e : this.legendWidth - e - 2 * b - 4, d); - h && ((h.x = e), (h.y = d)); - }, - destroyItem: function(a) { - var c = a.checkbox; - f(['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'], function( - b, - ) { - a[b] && (a[b] = a[b].destroy()); - }); - c && H(a.checkbox); - }, - destroy: function() { - function a(a) { - this[a] && (this[a] = this[a].destroy()); - } - f(this.getAllItems(), function(c) { - f(['legendItem', 'legendGroup'], a, c); - }); - f('clipRect up down pager nav box title group'.split(' '), a, this); - this.display = null; - }, - positionCheckboxes: function() { - var a = this.group && this.group.alignAttr, - c, - b = this.clipHeight || this.legendHeight, - e = this.titleHeight; - a && - ((c = a.translateY), - f( - this.allItems, - function(d) { - var k = d.checkbox, - h; - k && - ((h = c + e + k.y + (this.scrollOffset || 0) + 3), - D(k, { - left: a.translateX + d.checkboxOffset + k.x - 20 + 'px', - top: h + 'px', - display: h > c - 6 && h < c + b - 6 ? '' : 'none', - })); - }, - this, - )); - }, - renderTitle: function() { - var a = this.options, - c = this.padding, - b = a.title, - e = 0; - b.text && - (this.title || - (this.title = this.chart.renderer - .label( - b.text, - c - 3, - c - 4, - null, - null, - null, - a.useHTML, - null, - 'legend-title', - ) - .attr({ zIndex: 1 }) - .css(b.style) - .add(this.group)), - (a = this.title.getBBox()), - (e = a.height), - (this.offsetWidth = a.width), - this.contentGroup.attr({ translateY: e })); - this.titleHeight = e; - }, - setText: function(d) { - var c = this.options; - d.legendItem.attr({ - text: c.labelFormat - ? a.format(c.labelFormat, d) - : c.labelFormatter.call(d), - }); - }, - renderItem: function(a) { - var c = this.chart, - b = c.renderer, - d = this.options, - e = 'horizontal' === d.layout, - h = this.symbolWidth, - f = d.symbolPadding, - m = this.itemStyle, - l = this.itemHiddenStyle, - t = this.padding, - p = e ? w(d.itemDistance, 20) : 0, - r = !d.rtl, - q = d.width, - A = d.itemMarginBottom || 0, - F = this.itemMarginTop, - G = a.legendItem, - g = !a.series, - v = !g && a.series.drawLegendSymbol ? a.series : a, - u = v.options, - L = this.createCheckboxForItem && u && u.showCheckbox, - u = h + f + p + (L ? 20 : 0), - P = d.useHTML, - J = a.options.className; - G || - ((a.legendGroup = b - .g('legend-item') - .addClass( - 'highcharts-' + - v.type + - '-series highcharts-color-' + - a.colorIndex + - (J ? ' ' + J : '') + - (g ? ' highcharts-series-' + a.index : ''), - ) - .attr({ zIndex: 1 }) - .add(this.scrollGroup)), - (a.legendItem = G = b - .text('', r ? h + f : -f, this.baseline || 0, P) - .css(n(a.visible ? m : l)) - .attr({ align: r ? 'left' : 'right', zIndex: 2 }) - .add(a.legendGroup)), - this.baseline || - ((h = m.fontSize), - (this.fontMetrics = b.fontMetrics(h, G)), - (this.baseline = this.fontMetrics.f + 3 + F), - G.attr('y', this.baseline)), - (this.symbolHeight = d.symbolHeight || this.fontMetrics.f), - v.drawLegendSymbol(this, a), - this.setItemEvents && this.setItemEvents(a, G, P), - L && this.createCheckboxForItem(a)); - this.colorizeItem(a, a.visible); - m.width || - G.css({ width: (d.itemWidth || d.width || c.spacingBox.width) - u }); - this.setText(a); - b = G.getBBox(); - m = a.checkboxOffset = d.itemWidth || a.legendItemWidth || b.width + u; - this.itemHeight = b = Math.round( - a.legendItemHeight || b.height || this.symbolHeight, - ); - e && - this.itemX - t + m > (q || c.spacingBox.width - 2 * t - d.x) && - ((this.itemX = t), - (this.itemY += F + this.lastLineHeight + A), - (this.lastLineHeight = 0)); - this.maxItemWidth = Math.max(this.maxItemWidth, m); - this.lastItemY = F + this.itemY + A; - this.lastLineHeight = Math.max(b, this.lastLineHeight); - a._legendItemPos = [this.itemX, this.itemY]; - e - ? (this.itemX += m) - : ((this.itemY += F + b + A), (this.lastLineHeight = b)); - this.offsetWidth = - q || - Math.max( - (e ? this.itemX - t - (a.checkbox ? 0 : p) : m) + t, - this.offsetWidth, - ); - }, - getAllItems: function() { - var a = []; - f(this.chart.series, function(c) { - var b = c && c.options; - c && - w(b.showInLegend, p(b.linkedTo) ? !1 : void 0, !0) && - (a = a.concat( - c.legendItems || ('point' === b.legendType ? c.data : c), - )); - }); - return a; - }, - getAlignment: function() { - var a = this.options; - return a.floating - ? '' - : a.align.charAt(0) + a.verticalAlign.charAt(0) + a.layout.charAt(0); - }, - adjustMargins: function(a, c) { - var b = this.chart, - d = this.options, - e = this.getAlignment(); - e && - f( - [/(lth|ct|rth)/, /(rtv|rm|rbv)/, /(rbh|cb|lbh)/, /(lbv|lm|ltv)/], - function(k, h) { - k.test(e) && - !p(a[h]) && - (b[r[h]] = Math.max( - b[r[h]], - b.legend[(h + 1) % 2 ? 'legendHeight' : 'legendWidth'] + - [1, -1, -1, 1][h] * d[h % 2 ? 'x' : 'y'] + - w(d.margin, 12) + - c[h] + - (0 === h ? b.titleOffset + b.options.title.margin : 0), - )); - }, - ); - }, - render: function() { - var a = this, - c = a.chart, - b = c.renderer, - k = a.group, - h, - m, - l, - x, - p = a.box, - t = a.options, - C = a.padding; - a.itemX = C; - a.itemY = a.initialItemY; - a.offsetWidth = 0; - a.lastItemY = 0; - k || - ((a.group = k = b - .g('legend') - .attr({ zIndex: 7 }) - .add()), - (a.contentGroup = b - .g() - .attr({ zIndex: 1 }) - .add(k)), - (a.scrollGroup = b.g().add(a.contentGroup))); - a.renderTitle(); - h = a.getAllItems(); - e(h, function(a, b) { - return ( - ((a.options && a.options.legendIndex) || 0) - - ((b.options && b.options.legendIndex) || 0) - ); - }); - t.reversed && h.reverse(); - a.allItems = h; - a.display = m = !!h.length; - a.lastLineHeight = 0; - f(h, function(b) { - a.renderItem(b); - }); - l = (t.width || a.offsetWidth) + C; - x = a.lastItemY + a.lastLineHeight + a.titleHeight; - x = a.handleOverflow(x); - x += C; - p || - ((a.box = p = b - .rect() - .addClass('highcharts-legend-box') - .attr({ r: t.borderRadius }) - .add(k)), - (p.isNew = !0)); - p.attr({ - stroke: t.borderColor, - 'stroke-width': t.borderWidth || 0, - fill: t.backgroundColor || 'none', - }).shadow(t.shadow); - 0 < l && - 0 < x && - (p[p.isNew ? 'attr' : 'animate']( - p.crisp.call( - {}, - { x: 0, y: 0, width: l, height: x }, - p.strokeWidth(), - ), - ), - (p.isNew = !1)); - p[m ? 'show' : 'hide'](); - a.legendWidth = l; - a.legendHeight = x; - f(h, function(b) { - a.positionItem(b); - }); - m && - ((b = c.spacingBox), - /(lth|ct|rth)/.test(a.getAlignment()) && - (b = n(b, { y: b.y + c.titleOffset + c.options.title.margin })), - k.align(n(t, { width: l, height: x }), !0, b)); - c.isResizing || this.positionCheckboxes(); - }, - handleOverflow: function(a) { - var c = this, - b = this.chart, - d = b.renderer, - e = this.options, - h = e.y, - m = this.padding, - b = b.spacingBox.height + ('top' === e.verticalAlign ? -h : h) - m, - h = e.maxHeight, - l, - n = this.clipRect, - t = e.navigation, - p = w(t.animation, !0), - r = t.arrowSize || 12, - q = this.nav, - A = this.pages, - F, - G = this.allItems, - g = function(a) { - 'number' === typeof a - ? n.attr({ height: a }) - : n && ((c.clipRect = n.destroy()), c.contentGroup.clip()); - c.contentGroup.div && - (c.contentGroup.div.style.clip = a - ? 'rect(' + m + 'px,9999px,' + (m + a) + 'px,0)' - : 'auto'); - }; - 'horizontal' !== e.layout || - 'middle' === e.verticalAlign || - e.floating || - (b /= 2); - h && (b = Math.min(b, h)); - A.length = 0; - a > b && !1 !== t.enabled - ? ((this.clipHeight = l = Math.max(b - 20 - this.titleHeight - m, 0)), - (this.currentPage = w(this.currentPage, 1)), - (this.fullHeight = a), - f(G, function(a, b) { - var c = a._legendItemPos[1], - d = Math.round(a.legendItem.getBBox().height), - g = A.length; - if (!g || (c - A[g - 1] > l && (F || c) !== A[g - 1])) - A.push(F || c), g++; - a.pageIx = g - 1; - F && (G[b - 1].pageIx = g - 1); - b === G.length - 1 && - c + d - A[g - 1] > l && - (A.push(c), (a.pageIx = g)); - c !== F && (F = c); - }), - n || - ((n = c.clipRect = d.clipRect(0, m, 9999, 0)), - c.contentGroup.clip(n)), - g(l), - q || - ((this.nav = q = d - .g() - .attr({ zIndex: 1 }) - .add(this.group)), - (this.up = d - .symbol('triangle', 0, 0, r, r) - .on('click', function() { - c.scroll(-1, p); - }) - .add(q)), - (this.pager = d - .text('', 15, 10) - .addClass('highcharts-legend-navigation') - .css(t.style) - .add(q)), - (this.down = d - .symbol('triangle-down', 0, 0, r, r) - .on('click', function() { - c.scroll(1, p); - }) - .add(q))), - c.scroll(0), - (a = b)) - : q && - (g(), - (this.nav = q.destroy()), - this.scrollGroup.attr({ translateY: 1 }), - (this.clipHeight = 0)); - return a; - }, - scroll: function(a, c) { - var b = this.pages, - d = b.length; - a = this.currentPage + a; - var e = this.clipHeight, - h = this.options.navigation, - f = this.pager, - m = this.padding; - a > d && (a = d); - 0 < a && - (void 0 !== c && u(c, this.chart), - this.nav.attr({ - translateX: m, - translateY: e + this.padding + 7 + this.titleHeight, - visibility: 'visible', - }), - this.up.attr({ - class: - 1 === a - ? 'highcharts-legend-nav-inactive' - : 'highcharts-legend-nav-active', - }), - f.attr({ text: a + '/' + d }), - this.down.attr({ - x: 18 + this.pager.getBBox().width, - class: - a === d - ? 'highcharts-legend-nav-inactive' - : 'highcharts-legend-nav-active', - }), - this.up - .attr({ fill: 1 === a ? h.inactiveColor : h.activeColor }) - .css({ cursor: 1 === a ? 'default' : 'pointer' }), - this.down - .attr({ fill: a === d ? h.inactiveColor : h.activeColor }) - .css({ cursor: a === d ? 'default' : 'pointer' }), - (this.scrollOffset = -b[a - 1] + this.initialItemY), - this.scrollGroup.animate({ translateY: this.scrollOffset }), - (this.currentPage = a), - this.positionCheckboxes()); - }, - }; - a.LegendSymbolMixin = { - drawRectangle: function(a, c) { - var b = a.symbolHeight, - d = a.options.squareSymbol; - c.legendSymbol = this.chart.renderer - .rect( - d ? (a.symbolWidth - b) / 2 : 0, - a.baseline - b + 1, - d ? b : a.symbolWidth, - b, - w(a.options.symbolRadius, b / 2), - ) - .addClass('highcharts-point') - .attr({ zIndex: 3 }) - .add(c.legendGroup); - }, - drawLineMarker: function(a) { - var c = this.options, - b = c.marker, - d = a.symbolWidth, - e = a.symbolHeight, - h = e / 2, - f = this.chart.renderer, - m = this.legendGroup; - a = a.baseline - Math.round(0.3 * a.fontMetrics.b); - var l; - l = { 'stroke-width': c.lineWidth || 0 }; - c.dashStyle && (l.dashstyle = c.dashStyle); - this.legendLine = f - .path(['M', 0, a, 'L', d, a]) - .addClass('highcharts-graph') - .attr(l) - .add(m); - b && - !1 !== b.enabled && - ((c = Math.min(w(b.radius, h), h)), - 0 === this.symbol.indexOf('url') && - ((b = n(b, { width: e, height: e })), (c = 0)), - (this.legendSymbol = b = f - .symbol(this.symbol, d / 2 - c, a - c, 2 * c, 2 * c, b) - .addClass('highcharts-point') - .add(m)), - (b.isMarker = !0)); - }, - }; - (/Trident\/7\.0/.test(h.navigator.userAgent) || l) && - m(a.Legend.prototype, 'positionItem', function(a, c) { - var b = this, - d = function() { - c._legendItemPos && a.call(b, c); - }; - d(); - setTimeout(d); - }); - })(M); - (function(a) { - var E = a.addEvent, - D = a.animate, - H = a.animObject, - p = a.attr, - f = a.doc, - l = a.Axis, - r = a.createElement, - n = a.defaultOptions, - w = a.discardElement, - u = a.charts, - e = a.css, - h = a.defined, - m = a.each, - d = a.extend, - c = a.find, - b = a.fireEvent, - k = a.grep, - z = a.isNumber, - B = a.isObject, - I = a.isString, - x = a.Legend, - K = a.marginNames, - t = a.merge, - C = a.objectEach, - N = a.Pointer, - q = a.pick, - A = a.pInt, - F = a.removeEvent, - G = a.seriesTypes, - g = a.splat, - v = a.svg, - Q = a.syncTimeout, - L = a.win, - P = (a.Chart = function() { - this.getArgs.apply(this, arguments); - }); - a.chart = function(a, b, c) { - return new P(a, b, c); - }; - d(P.prototype, { - callbacks: [], - getArgs: function() { - var a = [].slice.call(arguments); - if (I(a[0]) || a[0].nodeName) this.renderTo = a.shift(); - this.init(a[0], a[1]); - }, - init: function(b, c) { - var d, - g, - e = b.series, - k = b.plotOptions || {}; - b.series = null; - d = t(n, b); - for (g in d.plotOptions) - d.plotOptions[g].tooltip = (k[g] && t(k[g].tooltip)) || void 0; - d.tooltip.userOptions = - (b.chart && b.chart.forExport && b.tooltip.userOptions) || b.tooltip; - d.series = b.series = e; - this.userOptions = b; - b = d.chart; - g = b.events; - this.margin = []; - this.spacing = []; - this.bounds = { h: {}, v: {} }; - this.labelCollectors = []; - this.callback = c; - this.isResizing = 0; - this.options = d; - this.axes = []; - this.series = []; - this.hasCartesianSeries = b.showAxes; - var q = this; - q.index = u.length; - u.push(q); - a.chartCount++; - g && - C(g, function(a, b) { - E(q, b, a); - }); - q.xAxis = []; - q.yAxis = []; - q.pointCount = q.colorCounter = q.symbolCounter = 0; - q.firstRender(); - }, - initSeries: function(b) { - var c = this.options.chart; - (c = G[b.type || c.type || c.defaultSeriesType]) || a.error(17, !0); - c = new c(); - c.init(this, b); - return c; - }, - orderSeries: function(a) { - var b = this.series; - for (a = a || 0; a < b.length; a++) - b[a] && - ((b[a].index = a), - (b[a].name = b[a].name || 'Series ' + (b[a].index + 1))); - }, - isInsidePlot: function(a, b, c) { - var d = c ? b : a; - a = c ? a : b; - return 0 <= d && d <= this.plotWidth && 0 <= a && a <= this.plotHeight; - }, - redraw: function(c) { - var g = this.axes, - e = this.series, - k = this.pointer, - q = this.legend, - h = this.isDirtyLegend, - f, - l, - v = this.hasCartesianSeries, - A = this.isDirtyBox, - F, - t = this.renderer, - x = t.isHidden(), - n = []; - this.setResponsive && this.setResponsive(!1); - a.setAnimation(c, this); - x && this.temporaryDisplay(); - this.layOutTitles(); - for (c = e.length; c--; ) - if (((F = e[c]), F.options.stacking && ((f = !0), F.isDirty))) { - l = !0; - break; - } - if (l) - for (c = e.length; c--; ) - (F = e[c]), F.options.stacking && (F.isDirty = !0); - m(e, function(a) { - a.isDirty && - 'point' === a.options.legendType && - (a.updateTotals && a.updateTotals(), (h = !0)); - a.isDirtyData && b(a, 'updatedData'); - }); - h && q.options.enabled && (q.render(), (this.isDirtyLegend = !1)); - f && this.getStacks(); - v && - m(g, function(a) { - a.updateNames(); - a.setScale(); - }); - this.getMargins(); - v && - (m(g, function(a) { - a.isDirty && (A = !0); - }), - m(g, function(a) { - var c = a.min + ',' + a.max; - a.extKey !== c && - ((a.extKey = c), - n.push(function() { - b(a, 'afterSetExtremes', d(a.eventArgs, a.getExtremes())); - delete a.eventArgs; - })); - (A || f) && a.redraw(); - })); - A && this.drawChartBox(); - b(this, 'predraw'); - m(e, function(a) { - (A || a.isDirty) && a.visible && a.redraw(); - a.isDirtyData = !1; - }); - k && k.reset(!0); - t.draw(); - b(this, 'redraw'); - b(this, 'render'); - x && this.temporaryDisplay(!0); - m(n, function(a) { - a.call(); - }); - }, - get: function(a) { - function b(b) { - return b.id === a || (b.options && b.options.id === a); - } - var d, - g = this.series, - e; - d = c(this.axes, b) || c(this.series, b); - for (e = 0; !d && e < g.length; e++) d = c(g[e].points || [], b); - return d; - }, - getAxes: function() { - var a = this, - b = this.options, - c = (b.xAxis = g(b.xAxis || {})), - b = (b.yAxis = g(b.yAxis || {})); - m(c, function(a, b) { - a.index = b; - a.isX = !0; - }); - m(b, function(a, b) { - a.index = b; - }); - c = c.concat(b); - m(c, function(b) { - new l(a, b); - }); - }, - getSelectedPoints: function() { - var a = []; - m(this.series, function(b) { - a = a.concat( - k(b.data || [], function(a) { - return a.selected; - }), - ); - }); - return a; - }, - getSelectedSeries: function() { - return k(this.series, function(a) { - return a.selected; - }); - }, - setTitle: function(a, b, c) { - var d = this, - g = d.options, - e; - e = g.title = t( - { - style: { color: '#333333', fontSize: g.isStock ? '16px' : '18px' }, - }, - g.title, - a, - ); - g = g.subtitle = t({ style: { color: '#666666' } }, g.subtitle, b); - m([['title', a, e], ['subtitle', b, g]], function(a, b) { - var c = a[0], - g = d[c], - e = a[1]; - a = a[2]; - g && e && (d[c] = g = g.destroy()); - a && - !g && - ((d[c] = d.renderer - .text(a.text, 0, 0, a.useHTML) - .attr({ - align: a.align, - class: 'highcharts-' + c, - zIndex: a.zIndex || 4, - }) - .add()), - (d[c].update = function(a) { - d.setTitle(!b && a, b && a); - }), - d[c].css(a.style)); - }); - d.layOutTitles(c); - }, - layOutTitles: function(a) { - var b = 0, - c, - g = this.renderer, - e = this.spacingBox; - m( - ['title', 'subtitle'], - function(a) { - var c = this[a], - k = this.options[a]; - a = 'title' === a ? -3 : k.verticalAlign ? 0 : b + 2; - var q; - c && - ((q = k.style.fontSize), - (q = g.fontMetrics(q, c).b), - c - .css({ width: (k.width || e.width + k.widthAdjust) + 'px' }) - .align(d({ y: a + q }, k), !1, 'spacingBox'), - k.floating || - k.verticalAlign || - (b = Math.ceil(b + c.getBBox(k.useHTML).height))); - }, - this, - ); - c = this.titleOffset !== b; - this.titleOffset = b; - !this.isDirtyBox && - c && - ((this.isDirtyBox = c), - this.hasRendered && q(a, !0) && this.isDirtyBox && this.redraw()); - }, - getChartSize: function() { - var b = this.options.chart, - c = b.width, - b = b.height, - d = this.renderTo; - h(c) || (this.containerWidth = a.getStyle(d, 'width')); - h(b) || (this.containerHeight = a.getStyle(d, 'height')); - this.chartWidth = Math.max(0, c || this.containerWidth || 600); - this.chartHeight = Math.max( - 0, - a.relativeLength(b, this.chartWidth) || - (1 < this.containerHeight ? this.containerHeight : 400), - ); - }, - temporaryDisplay: function(b) { - var c = this.renderTo; - if (b) - for (; c && c.style; ) - c.hcOrigStyle && (a.css(c, c.hcOrigStyle), delete c.hcOrigStyle), - c.hcOrigDetached && - (f.body.removeChild(c), (c.hcOrigDetached = !1)), - (c = c.parentNode); - else - for (; c && c.style; ) { - f.body.contains(c) || - c.parentNode || - ((c.hcOrigDetached = !0), f.body.appendChild(c)); - if ('none' === a.getStyle(c, 'display', !1) || c.hcOricDetached) - (c.hcOrigStyle = { - display: c.style.display, - height: c.style.height, - overflow: c.style.overflow, - }), - (b = { display: 'block', overflow: 'hidden' }), - c !== this.renderTo && (b.height = 0), - a.css(c, b), - c.offsetWidth || - c.style.setProperty('display', 'block', 'important'); - c = c.parentNode; - if (c === f.body) break; - } - }, - setClassName: function(a) { - this.container.className = 'highcharts-container ' + (a || ''); - }, - getContainer: function() { - var b, - c = this.options, - g = c.chart, - e, - k; - b = this.renderTo; - var q = a.uniqueKey(), - h; - b || (this.renderTo = b = g.renderTo); - I(b) && (this.renderTo = b = f.getElementById(b)); - b || a.error(13, !0); - e = A(p(b, 'data-highcharts-chart')); - z(e) && u[e] && u[e].hasRendered && u[e].destroy(); - p(b, 'data-highcharts-chart', this.index); - b.innerHTML = ''; - g.skipClone || b.offsetWidth || this.temporaryDisplay(); - this.getChartSize(); - e = this.chartWidth; - k = this.chartHeight; - h = d( - { - position: 'relative', - overflow: 'hidden', - width: e + 'px', - height: k + 'px', - textAlign: 'left', - lineHeight: 'normal', - zIndex: 0, - '-webkit-tap-highlight-color': 'rgba(0,0,0,0)', - }, - g.style, - ); - this.container = b = r('div', { id: q }, h, b); - this._cursor = b.style.cursor; - this.renderer = new (a[g.renderer] || a.Renderer)( - b, - e, - k, - null, - g.forExport, - c.exporting && c.exporting.allowHTML, - ); - this.setClassName(g.className); - this.renderer.setStyle(g.style); - this.renderer.chartIndex = this.index; - }, - getMargins: function(a) { - var b = this.spacing, - c = this.margin, - d = this.titleOffset; - this.resetMargins(); - d && - !h(c[0]) && - (this.plotTop = Math.max( - this.plotTop, - d + this.options.title.margin + b[0], - )); - this.legend && this.legend.display && this.legend.adjustMargins(c, b); - this.extraMargin && - (this[this.extraMargin.type] = - (this[this.extraMargin.type] || 0) + this.extraMargin.value); - this.adjustPlotArea && this.adjustPlotArea(); - a || this.getAxisMargins(); - }, - getAxisMargins: function() { - var a = this, - b = (a.axisOffset = [0, 0, 0, 0]), - c = a.margin; - a.hasCartesianSeries && - m(a.axes, function(a) { - a.visible && a.getOffset(); - }); - m(K, function(d, g) { - h(c[g]) || (a[d] += b[g]); - }); - a.setChartSize(); - }, - reflow: function(b) { - var c = this, - d = c.options.chart, - g = c.renderTo, - e = h(d.width) && h(d.height), - k = d.width || a.getStyle(g, 'width'), - d = d.height || a.getStyle(g, 'height'), - g = b ? b.target : L; - if (!e && !c.isPrinting && k && d && (g === L || g === f)) { - if (k !== c.containerWidth || d !== c.containerHeight) - clearTimeout(c.reflowTimeout), - (c.reflowTimeout = Q( - function() { - c.container && c.setSize(void 0, void 0, !1); - }, - b ? 100 : 0, - )); - c.containerWidth = k; - c.containerHeight = d; - } - }, - initReflow: function() { - var a = this, - b; - b = E(L, 'resize', function(b) { - a.reflow(b); - }); - E(a, 'destroy', b); - }, - setSize: function(c, d, g) { - var k = this, - q = k.renderer; - k.isResizing += 1; - a.setAnimation(g, k); - k.oldChartHeight = k.chartHeight; - k.oldChartWidth = k.chartWidth; - void 0 !== c && (k.options.chart.width = c); - void 0 !== d && (k.options.chart.height = d); - k.getChartSize(); - c = q.globalAnimation; - (c ? D : e)( - k.container, - { width: k.chartWidth + 'px', height: k.chartHeight + 'px' }, - c, - ); - k.setChartSize(!0); - q.setSize(k.chartWidth, k.chartHeight, g); - m(k.axes, function(a) { - a.isDirty = !0; - a.setScale(); - }); - k.isDirtyLegend = !0; - k.isDirtyBox = !0; - k.layOutTitles(); - k.getMargins(); - k.redraw(g); - k.oldChartHeight = null; - b(k, 'resize'); - Q(function() { - k && - b(k, 'endResize', null, function() { - --k.isResizing; - }); - }, H(c).duration); - }, - setChartSize: function(a) { - var b = this.inverted, - c = this.renderer, - d = this.chartWidth, - g = this.chartHeight, - e = this.options.chart, - k = this.spacing, - q = this.clipOffset, - h, - f, - l, - v; - this.plotLeft = h = Math.round(this.plotLeft); - this.plotTop = f = Math.round(this.plotTop); - this.plotWidth = l = Math.max(0, Math.round(d - h - this.marginRight)); - this.plotHeight = v = Math.max( - 0, - Math.round(g - f - this.marginBottom), - ); - this.plotSizeX = b ? v : l; - this.plotSizeY = b ? l : v; - this.plotBorderWidth = e.plotBorderWidth || 0; - this.spacingBox = c.spacingBox = { - x: k[3], - y: k[0], - width: d - k[3] - k[1], - height: g - k[0] - k[2], - }; - this.plotBox = c.plotBox = { x: h, y: f, width: l, height: v }; - d = 2 * Math.floor(this.plotBorderWidth / 2); - b = Math.ceil(Math.max(d, q[3]) / 2); - c = Math.ceil(Math.max(d, q[0]) / 2); - this.clipBox = { - x: b, - y: c, - width: Math.floor(this.plotSizeX - Math.max(d, q[1]) / 2 - b), - height: Math.max( - 0, - Math.floor(this.plotSizeY - Math.max(d, q[2]) / 2 - c), - ), - }; - a || - m(this.axes, function(a) { - a.setAxisSize(); - a.setAxisTranslation(); - }); - }, - resetMargins: function() { - var a = this, - b = a.options.chart; - m(['margin', 'spacing'], function(c) { - var d = b[c], - g = B(d) ? d : [d, d, d, d]; - m(['Top', 'Right', 'Bottom', 'Left'], function(d, e) { - a[c][e] = q(b[c + d], g[e]); - }); - }); - m(K, function(b, c) { - a[b] = q(a.margin[c], a.spacing[c]); - }); - a.axisOffset = [0, 0, 0, 0]; - a.clipOffset = [0, 0, 0, 0]; - }, - drawChartBox: function() { - var a = this.options.chart, - b = this.renderer, - c = this.chartWidth, - d = this.chartHeight, - g = this.chartBackground, - e = this.plotBackground, - k = this.plotBorder, - q, - h = this.plotBGImage, - f = a.backgroundColor, - m = a.plotBackgroundColor, - l = a.plotBackgroundImage, - v, - A = this.plotLeft, - F = this.plotTop, - t = this.plotWidth, - x = this.plotHeight, - n = this.plotBox, - p = this.clipRect, - z = this.clipBox, - G = 'animate'; - g || - ((this.chartBackground = g = b - .rect() - .addClass('highcharts-background') - .add()), - (G = 'attr')); - q = a.borderWidth || 0; - v = q + (a.shadow ? 8 : 0); - f = { fill: f || 'none' }; - if (q || g['stroke-width']) - (f.stroke = a.borderColor), (f['stroke-width'] = q); - g.attr(f).shadow(a.shadow); - g[G]({ - x: v / 2, - y: v / 2, - width: c - v - (q % 2), - height: d - v - (q % 2), - r: a.borderRadius, - }); - G = 'animate'; - e || - ((G = 'attr'), - (this.plotBackground = e = b - .rect() - .addClass('highcharts-plot-background') - .add())); - e[G](n); - e.attr({ fill: m || 'none' }).shadow(a.plotShadow); - l && - (h - ? h.animate(n) - : (this.plotBGImage = b.image(l, A, F, t, x).add())); - p - ? p.animate({ width: z.width, height: z.height }) - : (this.clipRect = b.clipRect(z)); - G = 'animate'; - k || - ((G = 'attr'), - (this.plotBorder = k = b - .rect() - .addClass('highcharts-plot-border') - .attr({ zIndex: 1 }) - .add())); - k.attr({ - stroke: a.plotBorderColor, - 'stroke-width': a.plotBorderWidth || 0, - fill: 'none', - }); - k[G](k.crisp({ x: A, y: F, width: t, height: x }, -k.strokeWidth())); - this.isDirtyBox = !1; - }, - propFromSeries: function() { - var a = this, - b = a.options.chart, - c, - d = a.options.series, - g, - e; - m(['inverted', 'angular', 'polar'], function(k) { - c = G[b.type || b.defaultSeriesType]; - e = b[k] || (c && c.prototype[k]); - for (g = d && d.length; !e && g--; ) - (c = G[d[g].type]) && c.prototype[k] && (e = !0); - a[k] = e; - }); - }, - linkSeries: function() { - var a = this, - b = a.series; - m(b, function(a) { - a.linkedSeries.length = 0; - }); - m(b, function(b) { - var c = b.options.linkedTo; - I(c) && - (c = ':previous' === c ? a.series[b.index - 1] : a.get(c)) && - c.linkedParent !== b && - (c.linkedSeries.push(b), - (b.linkedParent = c), - (b.visible = q(b.options.visible, c.options.visible, b.visible))); - }); - }, - renderSeries: function() { - m(this.series, function(a) { - a.translate(); - a.render(); - }); - }, - renderLabels: function() { - var a = this, - b = a.options.labels; - b.items && - m(b.items, function(c) { - var g = d(b.style, c.style), - e = A(g.left) + a.plotLeft, - k = A(g.top) + a.plotTop + 12; - delete g.left; - delete g.top; - a.renderer - .text(c.html, e, k) - .attr({ zIndex: 2 }) - .css(g) - .add(); - }); - }, - render: function() { - var a = this.axes, - b = this.renderer, - c = this.options, - d, - g, - e; - this.setTitle(); - this.legend = new x(this, c.legend); - this.getStacks && this.getStacks(); - this.getMargins(!0); - this.setChartSize(); - c = this.plotWidth; - d = this.plotHeight = Math.max(this.plotHeight - 21, 0); - m(a, function(a) { - a.setScale(); - }); - this.getAxisMargins(); - g = 1.1 < c / this.plotWidth; - e = 1.05 < d / this.plotHeight; - if (g || e) - m(a, function(a) { - ((a.horiz && g) || (!a.horiz && e)) && a.setTickInterval(!0); - }), - this.getMargins(); - this.drawChartBox(); - this.hasCartesianSeries && - m(a, function(a) { - a.visible && a.render(); - }); - this.seriesGroup || - (this.seriesGroup = b - .g('series-group') - .attr({ zIndex: 3 }) - .add()); - this.renderSeries(); - this.renderLabels(); - this.addCredits(); - this.setResponsive && this.setResponsive(); - this.hasRendered = !0; - }, - addCredits: function(a) { - var b = this; - a = t(!0, this.options.credits, a); - a.enabled && - !this.credits && - ((this.credits = this.renderer - .text(a.text + (this.mapCredits || ''), 0, 0) - .addClass('highcharts-credits') - .on('click', function() { - a.href && (L.location.href = a.href); - }) - .attr({ align: a.position.align, zIndex: 8 }) - .css(a.style) - .add() - .align(a.position)), - (this.credits.update = function(a) { - b.credits = b.credits.destroy(); - b.addCredits(a); - })); - }, - destroy: function() { - var c = this, - d = c.axes, - g = c.series, - e = c.container, - k, - q = e && e.parentNode; - b(c, 'destroy'); - c.renderer.forExport ? a.erase(u, c) : (u[c.index] = void 0); - a.chartCount--; - c.renderTo.removeAttribute('data-highcharts-chart'); - F(c); - for (k = d.length; k--; ) d[k] = d[k].destroy(); - this.scroller && this.scroller.destroy && this.scroller.destroy(); - for (k = g.length; k--; ) g[k] = g[k].destroy(); - m( - 'title subtitle chartBackground plotBackground plotBGImage plotBorder seriesGroup clipRect credits pointer rangeSelector legend resetZoomButton tooltip renderer'.split( - ' ', - ), - function(a) { - var b = c[a]; - b && b.destroy && (c[a] = b.destroy()); - }, - ); - e && ((e.innerHTML = ''), F(e), q && w(e)); - C(c, function(a, b) { - delete c[b]; - }); - }, - isReadyToRender: function() { - var a = this; - return v || L != L.top || 'complete' === f.readyState - ? !0 - : (f.attachEvent('onreadystatechange', function() { - f.detachEvent('onreadystatechange', a.firstRender); - 'complete' === f.readyState && a.firstRender(); - }), - !1); - }, - firstRender: function() { - var a = this, - c = a.options; - if (a.isReadyToRender()) { - a.getContainer(); - b(a, 'init'); - a.resetMargins(); - a.setChartSize(); - a.propFromSeries(); - a.getAxes(); - m(c.series || [], function(b) { - a.initSeries(b); - }); - a.linkSeries(); - b(a, 'beforeRender'); - N && (a.pointer = new N(a, c)); - a.render(); - if (!a.renderer.imgCount && a.onload) a.onload(); - a.temporaryDisplay(!0); - } - }, - onload: function() { - m( - [this.callback].concat(this.callbacks), - function(a) { - a && void 0 !== this.index && a.apply(this, [this]); - }, - this, - ); - b(this, 'load'); - b(this, 'render'); - h(this.index) && !1 !== this.options.chart.reflow && this.initReflow(); - this.onload = null; - }, - }); - })(M); - (function(a) { - var E, - D = a.each, - H = a.extend, - p = a.erase, - f = a.fireEvent, - l = a.format, - r = a.isArray, - n = a.isNumber, - w = a.pick, - u = a.removeEvent; - a.Point = E = function() {}; - a.Point.prototype = { - init: function(a, h, f) { - this.series = a; - this.color = a.color; - this.applyOptions(h, f); - a.options.colorByPoint - ? ((h = a.options.colors || a.chart.options.colors), - (this.color = this.color || h[a.colorCounter]), - (h = h.length), - (f = a.colorCounter), - a.colorCounter++, - a.colorCounter === h && (a.colorCounter = 0)) - : (f = a.colorIndex); - this.colorIndex = w(this.colorIndex, f); - a.chart.pointCount++; - return this; - }, - applyOptions: function(a, h) { - var e = this.series, - d = e.options.pointValKey || e.pointValKey; - a = E.prototype.optionsToObject.call(this, a); - H(this, a); - this.options = this.options ? H(this.options, a) : a; - a.group && delete this.group; - d && (this.y = this[d]); - this.isNull = w( - this.isValid && !this.isValid(), - null === this.x || !n(this.y, !0), - ); - this.selected && (this.state = 'select'); - 'name' in this && - void 0 === h && - e.xAxis && - e.xAxis.hasNames && - (this.x = e.xAxis.nameToX(this)); - void 0 === this.x && - e && - (this.x = void 0 === h ? e.autoIncrement(this) : h); - return this; - }, - optionsToObject: function(a) { - var e = {}, - f = this.series, - d = f.options.keys, - c = d || f.pointArrayMap || ['y'], - b = c.length, - k = 0, - l = 0; - if (n(a) || null === a) e[c[0]] = a; - else if (r(a)) - for ( - !d && - a.length > b && - ((f = typeof a[0]), - 'string' === f ? (e.name = a[0]) : 'number' === f && (e.x = a[0]), - k++); - l < b; - - ) - (d && void 0 === a[k]) || (e[c[l]] = a[k]), k++, l++; - else - 'object' === typeof a && - ((e = a), - a.dataLabels && (f._hasPointLabels = !0), - a.marker && (f._hasPointMarkers = !0)); - return e; - }, - getClassName: function() { - return ( - 'highcharts-point' + - (this.selected ? ' highcharts-point-select' : '') + - (this.negative ? ' highcharts-negative' : '') + - (this.isNull ? ' highcharts-null-point' : '') + - (void 0 !== this.colorIndex - ? ' highcharts-color-' + this.colorIndex - : '') + - (this.options.className ? ' ' + this.options.className : '') + - (this.zone && this.zone.className - ? ' ' + this.zone.className.replace('highcharts-negative', '') - : '') - ); - }, - getZone: function() { - var a = this.series, - h = a.zones, - a = a.zoneAxis || 'y', - f = 0, - d; - for (d = h[f]; this[a] >= d.value; ) d = h[++f]; - d && d.color && !this.options.color && (this.color = d.color); - return d; - }, - destroy: function() { - var a = this.series.chart, - h = a.hoverPoints, - f; - a.pointCount--; - h && (this.setState(), p(h, this), h.length || (a.hoverPoints = null)); - if (this === a.hoverPoint) this.onMouseOut(); - if (this.graphic || this.dataLabel) u(this), this.destroyElements(); - this.legendItem && a.legend.destroyItem(this); - for (f in this) this[f] = null; - }, - destroyElements: function() { - for ( - var a = [ - 'graphic', - 'dataLabel', - 'dataLabelUpper', - 'connector', - 'shadowGroup', - ], - h, - f = 6; - f--; - - ) - (h = a[f]), this[h] && (this[h] = this[h].destroy()); - }, - getLabelConfig: function() { - return { - x: this.category, - y: this.y, - color: this.color, - colorIndex: this.colorIndex, - key: this.name || this.category, - series: this.series, - point: this, - percentage: this.percentage, - total: this.total || this.stackTotal, - }; - }, - tooltipFormatter: function(a) { - var e = this.series, - f = e.tooltipOptions, - d = w(f.valueDecimals, ''), - c = f.valuePrefix || '', - b = f.valueSuffix || ''; - D(e.pointArrayMap || ['y'], function(e) { - e = '{point.' + e; - if (c || b) a = a.replace(e + '}', c + e + '}' + b); - a = a.replace(e + '}', e + ':,.' + d + 'f}'); - }); - return l(a, { point: this, series: this.series }); - }, - firePointEvent: function(a, h, m) { - var d = this, - c = this.series.options; - (c.point.events[a] || - (d.options && d.options.events && d.options.events[a])) && - this.importEvents(); - 'click' === a && - c.allowPointSelect && - (m = function(a) { - d.select && d.select(null, a.ctrlKey || a.metaKey || a.shiftKey); - }); - f(this, a, h, m); - }, - visible: !0, - }; - })(M); - (function(a) { - var E = a.addEvent, - D = a.animObject, - H = a.arrayMax, - p = a.arrayMin, - f = a.correctFloat, - l = a.Date, - r = a.defaultOptions, - n = a.defaultPlotOptions, - w = a.defined, - u = a.each, - e = a.erase, - h = a.extend, - m = a.fireEvent, - d = a.grep, - c = a.isArray, - b = a.isNumber, - k = a.isString, - z = a.merge, - B = a.objectEach, - I = a.pick, - x = a.removeEvent, - K = a.splat, - t = a.SVGElement, - C = a.syncTimeout, - N = a.win; - a.Series = a.seriesType( - 'line', - null, - { - lineWidth: 2, - allowPointSelect: !1, - showCheckbox: !1, - animation: { duration: 1e3 }, - events: {}, - marker: { - lineWidth: 0, - lineColor: '#ffffff', - radius: 4, - states: { - hover: { - animation: { duration: 50 }, - enabled: !0, - radiusPlus: 2, - lineWidthPlus: 1, - }, - select: { - fillColor: '#cccccc', - lineColor: '#000000', - lineWidth: 2, - }, - }, - }, - point: { events: {} }, - dataLabels: { - align: 'center', - formatter: function() { - return null === this.y ? '' : a.numberFormat(this.y, -1); - }, - style: { - fontSize: '11px', - fontWeight: 'bold', - color: 'contrast', - textOutline: '1px contrast', - }, - verticalAlign: 'bottom', - x: 0, - y: 0, - padding: 5, - }, - cropThreshold: 300, - pointRange: 0, - softThreshold: !0, - states: { - hover: { - animation: { duration: 50 }, - lineWidthPlus: 1, - marker: {}, - halo: { size: 10, opacity: 0.25 }, - }, - select: { marker: {} }, - }, - stickyTracking: !0, - turboThreshold: 1e3, - findNearestPointBy: 'x', - }, - { - isCartesian: !0, - pointClass: a.Point, - sorted: !0, - requireSorting: !0, - directTouch: !1, - axisTypes: ['xAxis', 'yAxis'], - colorCounter: 0, - parallelArrays: ['x', 'y'], - coll: 'series', - init: function(a, b) { - var c = this, - d, - g = a.series, - e; - c.chart = a; - c.options = b = c.setOptions(b); - c.linkedSeries = []; - c.bindAxes(); - h(c, { - name: b.name, - state: '', - visible: !1 !== b.visible, - selected: !0 === b.selected, - }); - d = b.events; - B(d, function(a, b) { - E(c, b, a); - }); - if ( - (d && d.click) || - (b.point && b.point.events && b.point.events.click) || - b.allowPointSelect - ) - a.runTrackerClick = !0; - c.getColor(); - c.getSymbol(); - u(c.parallelArrays, function(a) { - c[a + 'Data'] = []; - }); - c.setData(b.data, !1); - c.isCartesian && (a.hasCartesianSeries = !0); - g.length && (e = g[g.length - 1]); - c._i = I(e && e._i, -1) + 1; - a.orderSeries(this.insert(g)); - }, - insert: function(a) { - var c = this.options.index, - d; - if (b(c)) { - for (d = a.length; d--; ) - if (c >= I(a[d].options.index, a[d]._i)) { - a.splice(d + 1, 0, this); - break; - } - -1 === d && a.unshift(this); - d += 1; - } else a.push(this); - return I(d, a.length - 1); - }, - bindAxes: function() { - var b = this, - c = b.options, - d = b.chart, - e; - u(b.axisTypes || [], function(g) { - u(d[g], function(a) { - e = a.options; - if ( - c[g] === e.index || - (void 0 !== c[g] && c[g] === e.id) || - (void 0 === c[g] && 0 === e.index) - ) - b.insert(a.series), (b[g] = a), (a.isDirty = !0); - }); - b[g] || b.optionalAxis === g || a.error(18, !0); - }); - }, - updateParallelArrays: function(a, c) { - var d = a.series, - e = arguments, - g = b(c) - ? function(b) { - var g = 'y' === b && d.toYData ? d.toYData(a) : a[b]; - d[b + 'Data'][c] = g; - } - : function(a) { - Array.prototype[c].apply( - d[a + 'Data'], - Array.prototype.slice.call(e, 2), - ); - }; - u(d.parallelArrays, g); - }, - autoIncrement: function() { - var b = this.options, - c = this.xIncrement, - d, - e = b.pointIntervalUnit, - g = 0, - c = I(c, b.pointStart, 0); - this.pointInterval = d = I(this.pointInterval, b.pointInterval, 1); - e && - ((b = new l(c)), - 'day' === e - ? (b = +b[l.hcSetDate](b[l.hcGetDate]() + d)) - : 'month' === e - ? (b = +b[l.hcSetMonth](b[l.hcGetMonth]() + d)) - : 'year' === e && - (b = +b[l.hcSetFullYear](b[l.hcGetFullYear]() + d)), - l.hcHasTimeZone && (g = a.getTZOffset(b) - a.getTZOffset(c)), - (d = b - c + g)); - this.xIncrement = c + d; - return c; - }, - setOptions: function(a) { - var b = this.chart, - c = b.options, - d = c.plotOptions, - g = (b.userOptions || {}).plotOptions || {}, - e = d[this.type]; - this.userOptions = a; - b = z(e, d.series, a); - this.tooltipOptions = z( - r.tooltip, - r.plotOptions.series && r.plotOptions.series.tooltip, - r.plotOptions[this.type].tooltip, - c.tooltip.userOptions, - d.series && d.series.tooltip, - d[this.type].tooltip, - a.tooltip, - ); - this.stickyTracking = I( - a.stickyTracking, - g[this.type] && g[this.type].stickyTracking, - g.series && g.series.stickyTracking, - this.tooltipOptions.shared && !this.noSharedTooltip - ? !0 - : b.stickyTracking, - ); - null === e.marker && delete b.marker; - this.zoneAxis = b.zoneAxis; - a = this.zones = (b.zones || []).slice(); - (!b.negativeColor && !b.negativeFillColor) || - b.zones || - a.push({ - value: b[this.zoneAxis + 'Threshold'] || b.threshold || 0, - className: 'highcharts-negative', - color: b.negativeColor, - fillColor: b.negativeFillColor, - }); - a.length && - w(a[a.length - 1].value) && - a.push({ color: this.color, fillColor: this.fillColor }); - return b; - }, - getCyclic: function(a, b, c) { - var d, - g = this.chart, - e = this.userOptions, - k = a + 'Index', - h = a + 'Counter', - q = c ? c.length : I(g.options.chart[a + 'Count'], g[a + 'Count']); - b || - ((d = I(e[k], e['_' + k])), - w(d) || - (g.series.length || (g[h] = 0), - (e['_' + k] = d = g[h] % q), - (g[h] += 1)), - c && (b = c[d])); - void 0 !== d && (this[k] = d); - this[a] = b; - }, - getColor: function() { - this.options.colorByPoint - ? (this.options.color = null) - : this.getCyclic( - 'color', - this.options.color || n[this.type].color, - this.chart.options.colors, - ); - }, - getSymbol: function() { - this.getCyclic( - 'symbol', - this.options.marker.symbol, - this.chart.options.symbols, - ); - }, - drawLegendSymbol: a.LegendSymbolMixin.drawLineMarker, - setData: function(d, e, h, f) { - var g = this, - q = g.points, - m = (q && q.length) || 0, - l, - A = g.options, - t = g.chart, - x = null, - n = g.xAxis, - p = A.turboThreshold, - z = this.xData, - F = this.yData, - C = (l = g.pointArrayMap) && l.length; - d = d || []; - l = d.length; - e = I(e, !0); - if ( - !1 !== f && - l && - m === l && - !g.cropped && - !g.hasGroupedData && - g.visible - ) - u(d, function(a, b) { - q[b].update && a !== A.data[b] && q[b].update(a, !1, null, !1); - }); - else { - g.xIncrement = null; - g.colorCounter = 0; - u(this.parallelArrays, function(a) { - g[a + 'Data'].length = 0; - }); - if (p && l > p) { - for (h = 0; null === x && h < l; ) (x = d[h]), h++; - if (b(x)) - for (h = 0; h < l; h++) - (z[h] = this.autoIncrement()), (F[h] = d[h]); - else if (c(x)) - if (C) - for (h = 0; h < l; h++) - (x = d[h]), (z[h] = x[0]), (F[h] = x.slice(1, C + 1)); - else - for (h = 0; h < l; h++) - (x = d[h]), (z[h] = x[0]), (F[h] = x[1]); - else a.error(12); - } else - for (h = 0; h < l; h++) - void 0 !== d[h] && - ((x = { series: g }), - g.pointClass.prototype.applyOptions.apply(x, [d[h]]), - g.updateParallelArrays(x, h)); - F && k(F[0]) && a.error(14, !0); - g.data = []; - g.options.data = g.userOptions.data = d; - for (h = m; h--; ) q[h] && q[h].destroy && q[h].destroy(); - n && (n.minRange = n.userMinRange); - g.isDirty = t.isDirtyBox = !0; - g.isDirtyData = !!q; - h = !1; - } - 'point' === A.legendType && - (this.processData(), this.generatePoints()); - e && t.redraw(h); - }, - processData: function(b) { - var c = this.xData, - d = this.yData, - e = c.length, - g; - g = 0; - var k, - h, - q = this.xAxis, - f, - m = this.options; - f = m.cropThreshold; - var l = this.getExtremesFromAll || m.getExtremesFromAll, - t = this.isCartesian, - m = q && q.val2lin, - x = q && q.isLog, - n = this.requireSorting, - p, - z; - if (t && !this.isDirty && !q.isDirty && !this.yAxis.isDirty && !b) - return !1; - q && ((b = q.getExtremes()), (p = b.min), (z = b.max)); - if (t && this.sorted && !l && (!f || e > f || this.forceCrop)) - if (c[e - 1] < p || c[0] > z) (c = []), (d = []); - else if (c[0] < p || c[e - 1] > z) - (g = this.cropData(this.xData, this.yData, p, z)), - (c = g.xData), - (d = g.yData), - (g = g.start), - (k = !0); - for (f = c.length || 1; --f; ) - (e = x ? m(c[f]) - m(c[f - 1]) : c[f] - c[f - 1]), - 0 < e && (void 0 === h || e < h) - ? (h = e) - : 0 > e && n && (a.error(15), (n = !1)); - this.cropped = k; - this.cropStart = g; - this.processedXData = c; - this.processedYData = d; - this.closestPointRange = h; - }, - cropData: function(a, b, c, d) { - var g = a.length, - e = 0, - k = g, - h = I(this.cropShoulder, 1), - f; - for (f = 0; f < g; f++) - if (a[f] >= c) { - e = Math.max(0, f - h); - break; - } - for (c = f; c < g; c++) - if (a[c] > d) { - k = c + h; - break; - } - return { - xData: a.slice(e, k), - yData: b.slice(e, k), - start: e, - end: k, - }; - }, - generatePoints: function() { - var a = this.options, - b = a.data, - c = this.data, - d, - g = this.processedXData, - e = this.processedYData, - k = this.pointClass, - h = g.length, - f = this.cropStart || 0, - m, - l = this.hasGroupedData, - a = a.keys, - t, - x = [], - n; - c || l || ((c = []), (c.length = b.length), (c = this.data = c)); - a && l && (this.options.keys = !1); - for (n = 0; n < h; n++) - (m = f + n), - l - ? ((t = new k().init(this, [g[n]].concat(K(e[n])))), - (t.dataGroup = this.groupMap[n])) - : (t = c[m]) || - void 0 === b[m] || - (c[m] = t = new k().init(this, b[m], g[n])), - t && ((t.index = m), (x[n] = t)); - this.options.keys = a; - if (c && (h !== (d = c.length) || l)) - for (n = 0; n < d; n++) - n !== f || l || (n += h), - c[n] && (c[n].destroyElements(), (c[n].plotX = void 0)); - this.data = c; - this.points = x; - }, - getExtremes: function(a) { - var d = this.yAxis, - e = this.processedXData, - k, - g = [], - h = 0; - k = this.xAxis.getExtremes(); - var f = k.min, - q = k.max, - m, - l, - t, - n; - a = a || this.stackedYData || this.processedYData || []; - k = a.length; - for (n = 0; n < k; n++) - if ( - ((l = e[n]), - (t = a[n]), - (m = - (b(t, !0) || c(t)) && - (!d.positiveValuesOnly || t.length || 0 < t)), - (l = - this.getExtremesFromAll || - this.options.getExtremesFromAll || - this.cropped || - ((e[n + 1] || l) >= f && (e[n - 1] || l) <= q)), - m && l) - ) - if ((m = t.length)) - for (; m--; ) 'number' === typeof t[m] && (g[h++] = t[m]); - else g[h++] = t; - this.dataMin = p(g); - this.dataMax = H(g); - }, - translate: function() { - this.processedXData || this.processData(); - this.generatePoints(); - var a = this.options, - c = a.stacking, - d = this.xAxis, - e = d.categories, - g = this.yAxis, - k = this.points, - h = k.length, - m = !!this.modifyValue, - l = a.pointPlacement, - t = 'between' === l || b(l), - n = a.threshold, - x = a.startFromThreshold ? n : 0, - p, - z, - C, - r, - u = Number.MAX_VALUE; - 'between' === l && (l = 0.5); - b(l) && (l *= I(a.pointRange || d.pointRange)); - for (a = 0; a < h; a++) { - var B = k[a], - N = B.x, - K = B.y; - z = B.low; - var D = - c && - g.stacks[ - (this.negStacks && K < (x ? 0 : n) ? '-' : '') + this.stackKey - ], - E; - g.positiveValuesOnly && null !== K && 0 >= K && (B.isNull = !0); - B.plotX = p = f( - Math.min( - Math.max( - -1e5, - d.translate(N, 0, 0, 0, 1, l, 'flags' === this.type), - ), - 1e5, - ), - ); - c && - this.visible && - !B.isNull && - D && - D[N] && - ((r = this.getStackIndicator(r, N, this.index)), - (E = D[N]), - (K = E.points[r.key]), - (z = K[0]), - (K = K[1]), - z === x && r.key === D[N].base && (z = I(n, g.min)), - g.positiveValuesOnly && 0 >= z && (z = null), - (B.total = B.stackTotal = E.total), - (B.percentage = E.total && (B.y / E.total) * 100), - (B.stackY = K), - E.setOffset(this.pointXOffset || 0, this.barW || 0)); - B.yBottom = w(z) ? g.translate(z, 0, 1, 0, 1) : null; - m && (K = this.modifyValue(K, B)); - B.plotY = z = - 'number' === typeof K && Infinity !== K - ? Math.min(Math.max(-1e5, g.translate(K, 0, 1, 0, 1)), 1e5) - : void 0; - B.isInside = - void 0 !== z && 0 <= z && z <= g.len && 0 <= p && p <= d.len; - B.clientX = t ? f(d.translate(N, 0, 0, 0, 1, l)) : p; - B.negative = B.y < (n || 0); - B.category = e && void 0 !== e[B.x] ? e[B.x] : B.x; - B.isNull || - (void 0 !== C && (u = Math.min(u, Math.abs(p - C))), (C = p)); - B.zone = this.zones.length && B.getZone(); - } - this.closestPointRangePx = u; - }, - getValidPoints: function(a, b) { - var c = this.chart; - return d(a || this.points || [], function(a) { - return b && !c.isInsidePlot(a.plotX, a.plotY, c.inverted) - ? !1 - : !a.isNull; - }); - }, - setClip: function(a) { - var b = this.chart, - c = this.options, - d = b.renderer, - g = b.inverted, - e = this.clipBox, - k = e || b.clipBox, - h = - this.sharedClipKey || - [ - '_sharedClip', - a && a.duration, - a && a.easing, - k.height, - c.xAxis, - c.yAxis, - ].join(), - f = b[h], - q = b[h + 'm']; - f || - (a && - ((k.width = 0), - g && (k.x = b.plotSizeX), - (b[h + 'm'] = q = d.clipRect( - g ? b.plotSizeX + 99 : -99, - g ? -b.plotLeft : -b.plotTop, - 99, - g ? b.chartWidth : b.chartHeight, - ))), - (b[h] = f = d.clipRect(k)), - (f.count = { length: 0 })); - a && - !f.count[this.index] && - ((f.count[this.index] = !0), (f.count.length += 1)); - !1 !== c.clip && - (this.group.clip(a || e ? f : b.clipRect), - this.markerGroup.clip(q), - (this.sharedClipKey = h)); - a || - (f.count[this.index] && - (delete f.count[this.index], --f.count.length), - 0 === f.count.length && - h && - b[h] && - (e || (b[h] = b[h].destroy()), - b[h + 'm'] && (b[h + 'm'] = b[h + 'm'].destroy()))); - }, - animate: function(a) { - var b = this.chart, - c = D(this.options.animation), - d; - a - ? this.setClip(c) - : ((d = this.sharedClipKey), - (a = b[d]) && a.animate({ width: b.plotSizeX, x: 0 }, c), - b[d + 'm'] && - b[d + 'm'].animate({ width: b.plotSizeX + 99, x: 0 }, c), - (this.animate = null)); - }, - afterAnimate: function() { - this.setClip(); - m(this, 'afterAnimate'); - this.finishedAnimating = !0; - }, - drawPoints: function() { - var a = this.points, - b = this.chart, - c, - d, - g, - e, - k = this.options.marker, - h, - f, - l, - m = this[this.specialGroup] || this.markerGroup, - t, - n = I( - k.enabled, - this.xAxis.isRadial ? !0 : null, - this.closestPointRangePx >= 2 * k.radius, - ); - if (!1 !== k.enabled || this._hasPointMarkers) - for (c = 0; c < a.length; c++) - (d = a[c]), - (e = d.graphic), - (h = d.marker || {}), - (f = !!d.marker), - (g = (n && void 0 === h.enabled) || h.enabled), - (l = d.isInside), - g && !d.isNull - ? ((g = I(h.symbol, this.symbol)), - (d.hasImage = 0 === g.indexOf('url')), - (t = this.markerAttribs(d, d.selected && 'select')), - e - ? e[l ? 'show' : 'hide'](!0).animate(t) - : l && - (0 < t.width || d.hasImage) && - (d.graphic = e = b.renderer - .symbol(g, t.x, t.y, t.width, t.height, f ? h : k) - .add(m)), - e && e.attr(this.pointAttribs(d, d.selected && 'select')), - e && e.addClass(d.getClassName(), !0)) - : e && (d.graphic = e.destroy()); - }, - markerAttribs: function(a, b) { - var c = this.options.marker, - d = a.marker || {}, - g = I(d.radius, c.radius); - b && - ((c = c.states[b]), - (b = d.states && d.states[b]), - (g = I( - b && b.radius, - c && c.radius, - g + ((c && c.radiusPlus) || 0), - ))); - a.hasImage && (g = 0); - a = { x: Math.floor(a.plotX) - g, y: a.plotY - g }; - g && (a.width = a.height = 2 * g); - return a; - }, - pointAttribs: function(a, b) { - var c = this.options.marker, - d = a && a.options, - g = (d && d.marker) || {}, - e = this.color, - k = d && d.color, - h = a && a.color, - d = I(g.lineWidth, c.lineWidth); - a = a && a.zone && a.zone.color; - e = k || a || h || e; - a = g.fillColor || c.fillColor || e; - e = g.lineColor || c.lineColor || e; - b && - ((c = c.states[b]), - (b = (g.states && g.states[b]) || {}), - (d = I( - b.lineWidth, - c.lineWidth, - d + I(b.lineWidthPlus, c.lineWidthPlus, 0), - )), - (a = b.fillColor || c.fillColor || a), - (e = b.lineColor || c.lineColor || e)); - return { stroke: e, 'stroke-width': d, fill: a }; - }, - destroy: function() { - var a = this, - b = a.chart, - c = /AppleWebKit\/533/.test(N.navigator.userAgent), - d, - g, - k = a.data || [], - h, - f; - m(a, 'destroy'); - x(a); - u(a.axisTypes || [], function(b) { - (f = a[b]) && - f.series && - (e(f.series, a), (f.isDirty = f.forceRedraw = !0)); - }); - a.legendItem && a.chart.legend.destroyItem(a); - for (g = k.length; g--; ) (h = k[g]) && h.destroy && h.destroy(); - a.points = null; - clearTimeout(a.animationTimeout); - B(a, function(a, b) { - a instanceof t && - !a.survive && - ((d = c && 'group' === b ? 'hide' : 'destroy'), a[d]()); - }); - b.hoverSeries === a && (b.hoverSeries = null); - e(b.series, a); - b.orderSeries(); - B(a, function(b, c) { - delete a[c]; - }); - }, - getGraphPath: function(a, b, c) { - var d = this, - g = d.options, - e = g.step, - k, - h = [], - f = [], - l; - a = a || d.points; - (k = a.reversed) && a.reverse(); - (e = { right: 1, center: 2 }[e] || (e && 3)) && k && (e = 4 - e); - !g.connectNulls || b || c || (a = this.getValidPoints(a)); - u(a, function(k, m) { - var q = k.plotX, - t = k.plotY, - n = a[m - 1]; - (k.leftCliff || (n && n.rightCliff)) && !c && (l = !0); - k.isNull && !w(b) && 0 < m - ? (l = !g.connectNulls) - : k.isNull && !b - ? (l = !0) - : (0 === m || l - ? (m = ['M', k.plotX, k.plotY]) - : d.getPointSpline - ? (m = d.getPointSpline(a, k, m)) - : e - ? ((m = - 1 === e - ? ['L', n.plotX, t] - : 2 === e - ? [ - 'L', - (n.plotX + q) / 2, - n.plotY, - 'L', - (n.plotX + q) / 2, - t, - ] - : ['L', q, n.plotY]), - m.push('L', q, t)) - : (m = ['L', q, t]), - f.push(k.x), - e && f.push(k.x), - h.push.apply(h, m), - (l = !1)); - }); - h.xMap = f; - return (d.graphPath = h); - }, - drawGraph: function() { - var a = this, - b = this.options, - c = (this.gappedPath || this.getGraphPath).call(this), - d = [ - [ - 'graph', - 'highcharts-graph', - b.lineColor || this.color, - b.dashStyle, - ], - ]; - u(this.zones, function(c, e) { - d.push([ - 'zone-graph-' + e, - 'highcharts-graph highcharts-zone-graph-' + - e + - ' ' + - (c.className || ''), - c.color || a.color, - c.dashStyle || b.dashStyle, - ]); - }); - u(d, function(d, e) { - var g = d[0], - k = a[g]; - k - ? ((k.endX = a.preventGraphAnimation ? null : c.xMap), - k.animate({ d: c })) - : c.length && - ((a[g] = a.chart.renderer - .path(c) - .addClass(d[1]) - .attr({ zIndex: 1 }) - .add(a.group)), - (k = { - stroke: d[2], - 'stroke-width': b.lineWidth, - fill: (a.fillGraph && a.color) || 'none', - }), - d[3] - ? (k.dashstyle = d[3]) - : 'square' !== b.linecap && - (k['stroke-linecap'] = k['stroke-linejoin'] = 'round'), - (k = a[g].attr(k).shadow(2 > e && b.shadow))); - k && ((k.startX = c.xMap), (k.isArea = c.isArea)); - }); - }, - applyZones: function() { - var a = this, - b = this.chart, - c = b.renderer, - d = this.zones, - e, - k, - h = this.clips || [], - f, - m = this.graph, - l = this.area, - t = Math.max(b.chartWidth, b.chartHeight), - n = this[(this.zoneAxis || 'y') + 'Axis'], - x, - p, - z = b.inverted, - C, - r, - w, - B, - K = !1; - d.length && - (m || l) && - n && - void 0 !== n.min && - ((p = n.reversed), - (C = n.horiz), - m && m.hide(), - l && l.hide(), - (x = n.getExtremes()), - u(d, function(d, g) { - e = p ? (C ? b.plotWidth : 0) : C ? 0 : n.toPixels(x.min); - e = Math.min(Math.max(I(k, e), 0), t); - k = Math.min( - Math.max(Math.round(n.toPixels(I(d.value, x.max), !0)), 0), - t, - ); - K && (e = k = n.toPixels(x.max)); - r = Math.abs(e - k); - w = Math.min(e, k); - B = Math.max(e, k); - n.isXAxis - ? ((f = { x: z ? B : w, y: 0, width: r, height: t }), - C || (f.x = b.plotHeight - f.x)) - : ((f = { x: 0, y: z ? B : w, width: t, height: r }), - C && (f.y = b.plotWidth - f.y)); - z && - c.isVML && - (f = n.isXAxis - ? { x: 0, y: p ? w : B, height: f.width, width: b.chartWidth } - : { - x: f.y - b.plotLeft - b.spacingBox.x, - y: 0, - width: f.height, - height: b.chartHeight, - }); - h[g] - ? h[g].animate(f) - : ((h[g] = c.clipRect(f)), - m && a['zone-graph-' + g].clip(h[g]), - l && a['zone-area-' + g].clip(h[g])); - K = d.value > x.max; - }), - (this.clips = h)); - }, - invertGroups: function(a) { - function b() { - u(['group', 'markerGroup'], function(b) { - c[b] && - (d.renderer.isVML && - c[b].attr({ width: c.yAxis.len, height: c.xAxis.len }), - (c[b].width = c.yAxis.len), - (c[b].height = c.xAxis.len), - c[b].invert(a)); - }); - } - var c = this, - d = c.chart, - e; - c.xAxis && - ((e = E(d, 'resize', b)), - E(c, 'destroy', e), - b(a), - (c.invertGroups = b)); - }, - plotGroup: function(a, b, c, d, e) { - var g = this[a], - k = !g; - k && - (this[a] = g = this.chart.renderer - .g() - .attr({ zIndex: d || 0.1 }) - .add(e)); - g.addClass( - 'highcharts-' + - b + - ' highcharts-series-' + - this.index + - ' highcharts-' + - this.type + - '-series ' + - (w(this.colorIndex) - ? 'highcharts-color-' + this.colorIndex + ' ' - : '') + - (this.options.className || '') + - (g.hasClass('highcharts-tracker') ? ' highcharts-tracker' : ''), - !0, - ); - g.attr({ visibility: c })[k ? 'attr' : 'animate'](this.getPlotBox()); - return g; - }, - getPlotBox: function() { - var a = this.chart, - b = this.xAxis, - c = this.yAxis; - a.inverted && ((b = c), (c = this.xAxis)); - return { - translateX: b ? b.left : a.plotLeft, - translateY: c ? c.top : a.plotTop, - scaleX: 1, - scaleY: 1, - }; - }, - render: function() { - var a = this, - b = a.chart, - c, - d = a.options, - e = !!a.animate && b.renderer.isSVG && D(d.animation).duration, - k = a.visible ? 'inherit' : 'hidden', - h = d.zIndex, - f = a.hasRendered, - m = b.seriesGroup, - l = b.inverted; - c = a.plotGroup('group', 'series', k, h, m); - a.markerGroup = a.plotGroup('markerGroup', 'markers', k, h, m); - e && a.animate(!0); - c.inverted = a.isCartesian ? l : !1; - a.drawGraph && (a.drawGraph(), a.applyZones()); - a.drawDataLabels && a.drawDataLabels(); - a.visible && a.drawPoints(); - a.drawTracker && - !1 !== a.options.enableMouseTracking && - a.drawTracker(); - a.invertGroups(l); - !1 === d.clip || a.sharedClipKey || f || c.clip(b.clipRect); - e && a.animate(); - f || - (a.animationTimeout = C(function() { - a.afterAnimate(); - }, e)); - a.isDirty = !1; - a.hasRendered = !0; - }, - redraw: function() { - var a = this.chart, - b = this.isDirty || this.isDirtyData, - c = this.group, - d = this.xAxis, - e = this.yAxis; - c && - (a.inverted && c.attr({ width: a.plotWidth, height: a.plotHeight }), - c.animate({ - translateX: I(d && d.left, a.plotLeft), - translateY: I(e && e.top, a.plotTop), - })); - this.translate(); - this.render(); - b && delete this.kdTree; - }, - kdAxisArray: ['clientX', 'plotY'], - searchPoint: function(a, b) { - var c = this.xAxis, - d = this.yAxis, - e = this.chart.inverted; - return this.searchKDTree( - { - clientX: e ? c.len - a.chartY + c.pos : a.chartX - c.pos, - plotY: e ? d.len - a.chartX + d.pos : a.chartY - d.pos, - }, - b, - ); - }, - buildKDTree: function() { - function a(c, d, e) { - var g, k; - if ((k = c && c.length)) - return ( - (g = b.kdAxisArray[d % e]), - c.sort(function(a, b) { - return a[g] - b[g]; - }), - (k = Math.floor(k / 2)), - { - point: c[k], - left: a(c.slice(0, k), d + 1, e), - right: a(c.slice(k + 1), d + 1, e), - } - ); - } - this.buildingKdTree = !0; - var b = this, - c = -1 < b.options.findNearestPointBy.indexOf('y') ? 2 : 1; - delete b.kdTree; - C( - function() { - b.kdTree = a(b.getValidPoints(null, !b.directTouch), c, c); - b.buildingKdTree = !1; - }, - b.options.kdNow ? 0 : 1, - ); - }, - searchKDTree: function(a, b) { - function c(a, b, g, f) { - var m = b.point, - l = d.kdAxisArray[g % f], - q, - t, - n = m; - t = w(a[e]) && w(m[e]) ? Math.pow(a[e] - m[e], 2) : null; - q = w(a[k]) && w(m[k]) ? Math.pow(a[k] - m[k], 2) : null; - q = (t || 0) + (q || 0); - m.dist = w(q) ? Math.sqrt(q) : Number.MAX_VALUE; - m.distX = w(t) ? Math.sqrt(t) : Number.MAX_VALUE; - l = a[l] - m[l]; - q = 0 > l ? 'left' : 'right'; - t = 0 > l ? 'right' : 'left'; - b[q] && ((q = c(a, b[q], g + 1, f)), (n = q[h] < n[h] ? q : m)); - b[t] && - Math.sqrt(l * l) < n[h] && - ((a = c(a, b[t], g + 1, f)), (n = a[h] < n[h] ? a : n)); - return n; - } - var d = this, - e = this.kdAxisArray[0], - k = this.kdAxisArray[1], - h = b ? 'distX' : 'dist'; - b = -1 < d.options.findNearestPointBy.indexOf('y') ? 2 : 1; - this.kdTree || this.buildingKdTree || this.buildKDTree(); - if (this.kdTree) return c(a, this.kdTree, b, b); - }, - }, - ); - })(M); - (function(a) { - var E = a.Axis, - D = a.Chart, - H = a.correctFloat, - p = a.defined, - f = a.destroyObjectProperties, - l = a.each, - r = a.format, - n = a.objectEach, - w = a.pick, - u = a.Series; - a.StackItem = function(a, h, f, d, c) { - var b = a.chart.inverted; - this.axis = a; - this.isNegative = f; - this.options = h; - this.x = d; - this.total = null; - this.points = {}; - this.stack = c; - this.rightCliff = this.leftCliff = 0; - this.alignOptions = { - align: h.align || (b ? (f ? 'left' : 'right') : 'center'), - verticalAlign: h.verticalAlign || (b ? 'middle' : f ? 'bottom' : 'top'), - y: w(h.y, b ? 4 : f ? 14 : -6), - x: w(h.x, b ? (f ? -6 : 6) : 0), - }; - this.textAlign = h.textAlign || (b ? (f ? 'right' : 'left') : 'center'); - }; - a.StackItem.prototype = { - destroy: function() { - f(this, this.axis); - }, - render: function(a) { - var e = this.options, - f = e.format, - f = f ? r(f, this) : e.formatter.call(this); - this.label - ? this.label.attr({ text: f, visibility: 'hidden' }) - : (this.label = this.axis.chart.renderer - .text(f, null, null, e.useHTML) - .css(e.style) - .attr({ - align: this.textAlign, - rotation: e.rotation, - visibility: 'hidden', - }) - .add(a)); - }, - setOffset: function(a, h) { - var e = this.axis, - d = e.chart, - c = e.translate(e.usePercentage ? 100 : this.total, 0, 0, 0, 1), - e = e.translate(0), - e = Math.abs(c - e); - a = d.xAxis[0].translate(this.x) + a; - c = this.getStackBox(d, this, a, c, h, e); - if ((h = this.label)) - h.align(this.alignOptions, null, c), - (c = h.alignAttr), - h[ - !1 === this.options.crop || d.isInsidePlot(c.x, c.y) - ? 'show' - : 'hide' - ](!0); - }, - getStackBox: function(a, h, f, d, c, b) { - var e = h.axis.reversed, - l = a.inverted; - a = a.plotHeight; - h = (h.isNegative && !e) || (!h.isNegative && e); - return { - x: l ? (h ? d : d - b) : f, - y: l ? a - f - c : h ? a - d - b : a - d, - width: l ? b : c, - height: l ? c : b, - }; - }, - }; - D.prototype.getStacks = function() { - var a = this; - l(a.yAxis, function(a) { - a.stacks && a.hasVisibleSeries && (a.oldStacks = a.stacks); - }); - l(a.series, function(e) { - !e.options.stacking || - (!0 !== e.visible && !1 !== a.options.chart.ignoreHiddenSeries) || - (e.stackKey = e.type + w(e.options.stack, '')); - }); - }; - E.prototype.buildStacks = function() { - var a = this.series, - h = w(this.options.reversedStacks, !0), - f = a.length, - d; - if (!this.isXAxis) { - this.usePercentage = !1; - for (d = f; d--; ) a[h ? d : f - d - 1].setStackedPoints(); - for (d = 0; d < f; d++) a[d].modifyStacks(); - } - }; - E.prototype.renderStackTotals = function() { - var a = this.chart, - h = a.renderer, - f = this.stacks, - d = this.stackTotalGroup; - d || - (this.stackTotalGroup = d = h - .g('stack-labels') - .attr({ visibility: 'visible', zIndex: 6 }) - .add()); - d.translate(a.plotLeft, a.plotTop); - n(f, function(a) { - n(a, function(a) { - a.render(d); - }); - }); - }; - E.prototype.resetStacks = function() { - var a = this, - h = a.stacks; - a.isXAxis || - n(h, function(e) { - n(e, function(d, c) { - d.touched < a.stacksTouched - ? (d.destroy(), delete e[c]) - : ((d.total = null), (d.cumulative = null)); - }); - }); - }; - E.prototype.cleanStacks = function() { - var a; - this.isXAxis || - (this.oldStacks && (a = this.stacks = this.oldStacks), - n(a, function(a) { - n(a, function(a) { - a.cumulative = a.total; - }); - })); - }; - u.prototype.setStackedPoints = function() { - if ( - this.options.stacking && - (!0 === this.visible || - !1 === this.chart.options.chart.ignoreHiddenSeries) - ) { - var e = this.processedXData, - h = this.processedYData, - f = [], - d = h.length, - c = this.options, - b = c.threshold, - k = w(c.startFromThreshold && b, 0), - l = c.stack, - c = c.stacking, - n = this.stackKey, - r = '-' + n, - x = this.negStacks, - u = this.yAxis, - t = u.stacks, - C = u.oldStacks, - N, - q, - A, - F, - G, - g, - v; - u.stacksTouched += 1; - for (G = 0; G < d; G++) - (g = e[G]), - (v = h[G]), - (N = this.getStackIndicator(N, g, this.index)), - (F = N.key), - (A = (q = x && v < (k ? 0 : b)) ? r : n), - t[A] || (t[A] = {}), - t[A][g] || - (C[A] && C[A][g] - ? ((t[A][g] = C[A][g]), (t[A][g].total = null)) - : (t[A][g] = new a.StackItem( - u, - u.options.stackLabels, - q, - g, - l, - ))), - (A = t[A][g]), - null !== v - ? ((A.points[F] = A.points[this.index] = [w(A.cumulative, k)]), - p(A.cumulative) || (A.base = F), - (A.touched = u.stacksTouched), - 0 < N.index && - !1 === this.singleStacks && - (A.points[F][0] = A.points[this.index + ',' + g + ',0'][0])) - : (A.points[F] = A.points[this.index] = null), - 'percent' === c - ? ((q = q ? n : r), - x && t[q] && t[q][g] - ? ((q = t[q][g]), - (A.total = q.total = - Math.max(q.total, A.total) + Math.abs(v) || 0)) - : (A.total = H(A.total + (Math.abs(v) || 0)))) - : (A.total = H(A.total + (v || 0))), - (A.cumulative = w(A.cumulative, k) + (v || 0)), - null !== v && - (A.points[F].push(A.cumulative), (f[G] = A.cumulative)); - 'percent' === c && (u.usePercentage = !0); - this.stackedYData = f; - u.oldStacks = {}; - } - }; - u.prototype.modifyStacks = function() { - var a = this, - h = a.stackKey, - f = a.yAxis.stacks, - d = a.processedXData, - c, - b = a.options.stacking; - a[b + 'Stacker'] && - l([h, '-' + h], function(e) { - for (var k = d.length, h, l; k--; ) - if ( - ((h = d[k]), - (c = a.getStackIndicator(c, h, a.index, e)), - (l = (h = f[e] && f[e][h]) && h.points[c.key])) - ) - a[b + 'Stacker'](l, h, k); - }); - }; - u.prototype.percentStacker = function(a, h, f) { - h = h.total ? 100 / h.total : 0; - a[0] = H(a[0] * h); - a[1] = H(a[1] * h); - this.stackedYData[f] = a[1]; - }; - u.prototype.getStackIndicator = function(a, h, f, d) { - !p(a) || a.x !== h || (d && a.key !== d) - ? (a = { x: h, index: 0, key: d }) - : a.index++; - a.key = [f, h, a.index].join(); - return a; - }; - })(M); - (function(a) { - var E = a.addEvent, - D = a.animate, - H = a.Axis, - p = a.createElement, - f = a.css, - l = a.defined, - r = a.each, - n = a.erase, - w = a.extend, - u = a.fireEvent, - e = a.inArray, - h = a.isNumber, - m = a.isObject, - d = a.isArray, - c = a.merge, - b = a.objectEach, - k = a.pick, - z = a.Point, - B = a.Series, - I = a.seriesTypes, - x = a.setAnimation, - K = a.splat; - w(a.Chart.prototype, { - addSeries: function(a, b, c) { - var d, - e = this; - a && - ((b = k(b, !0)), - u(e, 'addSeries', { options: a }, function() { - d = e.initSeries(a); - e.isDirtyLegend = !0; - e.linkSeries(); - b && e.redraw(c); - })); - return d; - }, - addAxis: function(a, b, d, e) { - var h = b ? 'xAxis' : 'yAxis', - f = this.options; - a = c(a, { index: this[h].length, isX: b }); - b = new H(this, a); - f[h] = K(f[h] || {}); - f[h].push(a); - k(d, !0) && this.redraw(e); - return b; - }, - showLoading: function(a) { - var b = this, - c = b.options, - d = b.loadingDiv, - e = c.loading, - k = function() { - d && - f(d, { - left: b.plotLeft + 'px', - top: b.plotTop + 'px', - width: b.plotWidth + 'px', - height: b.plotHeight + 'px', - }); - }; - d || - ((b.loadingDiv = d = p( - 'div', - { className: 'highcharts-loading highcharts-loading-hidden' }, - null, - b.container, - )), - (b.loadingSpan = p( - 'span', - { className: 'highcharts-loading-inner' }, - null, - d, - )), - E(b, 'redraw', k)); - d.className = 'highcharts-loading'; - b.loadingSpan.innerHTML = a || c.lang.loading; - f(d, w(e.style, { zIndex: 10 })); - f(b.loadingSpan, e.labelStyle); - b.loadingShown || - (f(d, { opacity: 0, display: '' }), - D( - d, - { opacity: e.style.opacity || 0.5 }, - { duration: e.showDuration || 0 }, - )); - b.loadingShown = !0; - k(); - }, - hideLoading: function() { - var a = this.options, - b = this.loadingDiv; - b && - ((b.className = 'highcharts-loading highcharts-loading-hidden'), - D( - b, - { opacity: 0 }, - { - duration: a.loading.hideDuration || 100, - complete: function() { - f(b, { display: 'none' }); - }, - }, - )); - this.loadingShown = !1; - }, - propsRequireDirtyBox: 'backgroundColor borderColor borderWidth margin marginTop marginRight marginBottom marginLeft spacing spacingTop spacingRight spacingBottom spacingLeft borderRadius plotBackgroundColor plotBackgroundImage plotBorderColor plotBorderWidth plotShadow shadow'.split( - ' ', - ), - propsRequireUpdateSeries: 'chart.inverted chart.polar chart.ignoreHiddenSeries chart.type colors plotOptions tooltip'.split( - ' ', - ), - update: function(a, d, f) { - var m = this, - n = { - credits: 'addCredits', - title: 'setTitle', - subtitle: 'setSubtitle', - }, - t = a.chart, - x, - g, - p = []; - if (t) { - c(!0, m.options.chart, t); - 'className' in t && m.setClassName(t.className); - if ('inverted' in t || 'polar' in t) m.propFromSeries(), (x = !0); - 'alignTicks' in t && (x = !0); - b(t, function(a, b) { - -1 !== e('chart.' + b, m.propsRequireUpdateSeries) && (g = !0); - -1 !== e(b, m.propsRequireDirtyBox) && (m.isDirtyBox = !0); - }); - 'style' in t && m.renderer.setStyle(t.style); - } - a.colors && (this.options.colors = a.colors); - a.plotOptions && c(!0, this.options.plotOptions, a.plotOptions); - b(a, function(a, b) { - if (m[b] && 'function' === typeof m[b].update) m[b].update(a, !1); - else if ('function' === typeof m[n[b]]) m[n[b]](a); - 'chart' !== b && -1 !== e(b, m.propsRequireUpdateSeries) && (g = !0); - }); - r('xAxis yAxis zAxis series colorAxis pane'.split(' '), function(b) { - a[b] && - (r(K(a[b]), function(a, c) { - (c = (l(a.id) && m.get(a.id)) || m[b][c]) && - c.coll === b && - (c.update(a, !1), f && (c.touched = !0)); - if (!c && f) - if ('series' === b) m.addSeries(a, !1).touched = !0; - else if ('xAxis' === b || 'yAxis' === b) - m.addAxis(a, 'xAxis' === b, !1).touched = !0; - }), - f && - r(m[b], function(a) { - a.touched ? delete a.touched : p.push(a); - })); - }); - r(p, function(a) { - a.remove(!1); - }); - x && - r(m.axes, function(a) { - a.update({}, !1); - }); - g && - r(m.series, function(a) { - a.update({}, !1); - }); - a.loading && c(!0, m.options.loading, a.loading); - x = t && t.width; - t = t && t.height; - (h(x) && x !== m.chartWidth) || (h(t) && t !== m.chartHeight) - ? m.setSize(x, t) - : k(d, !0) && m.redraw(); - }, - setSubtitle: function(a) { - this.setTitle(void 0, a); - }, - }); - w(z.prototype, { - update: function(a, b, c, d) { - function e() { - h.applyOptions(a); - null === h.y && g && (h.graphic = g.destroy()); - m(a, !0) && - (g && - g.element && - a && - a.marker && - void 0 !== a.marker.symbol && - (h.graphic = g.destroy()), - a && - a.dataLabels && - h.dataLabel && - (h.dataLabel = h.dataLabel.destroy()), - h.connector && (h.connector = h.connector.destroy())); - l = h.index; - f.updateParallelArrays(h, l); - t.data[l] = m(t.data[l], !0) || m(a, !0) ? h.options : a; - f.isDirty = f.isDirtyData = !0; - !f.fixedBox && f.hasCartesianSeries && (n.isDirtyBox = !0); - 'point' === t.legendType && (n.isDirtyLegend = !0); - b && n.redraw(c); - } - var h = this, - f = h.series, - g = h.graphic, - l, - n = f.chart, - t = f.options; - b = k(b, !0); - !1 === d ? e() : h.firePointEvent('update', { options: a }, e); - }, - remove: function(a, b) { - this.series.removePoint(e(this, this.series.data), a, b); - }, - }); - w(B.prototype, { - addPoint: function(a, b, c, d) { - var e = this.options, - h = this.data, - f = this.chart, - g = this.xAxis, - g = g && g.hasNames && g.names, - l = e.data, - m, - n, - t = this.xData, - q, - x; - b = k(b, !0); - m = { series: this }; - this.pointClass.prototype.applyOptions.apply(m, [a]); - x = m.x; - q = t.length; - if (this.requireSorting && x < t[q - 1]) - for (n = !0; q && t[q - 1] > x; ) q--; - this.updateParallelArrays(m, 'splice', q, 0, 0); - this.updateParallelArrays(m, q); - g && m.name && (g[x] = m.name); - l.splice(q, 0, a); - n && (this.data.splice(q, 0, null), this.processData()); - 'point' === e.legendType && this.generatePoints(); - c && - (h[0] && h[0].remove - ? h[0].remove(!1) - : (h.shift(), this.updateParallelArrays(m, 'shift'), l.shift())); - this.isDirtyData = this.isDirty = !0; - b && f.redraw(d); - }, - removePoint: function(a, b, c) { - var d = this, - e = d.data, - h = e[a], - f = d.points, - g = d.chart, - l = function() { - f && f.length === e.length && f.splice(a, 1); - e.splice(a, 1); - d.options.data.splice(a, 1); - d.updateParallelArrays(h || { series: d }, 'splice', a, 1); - h && h.destroy(); - d.isDirty = !0; - d.isDirtyData = !0; - b && g.redraw(); - }; - x(c, g); - b = k(b, !0); - h ? h.firePointEvent('remove', null, l) : l(); - }, - remove: function(a, b, c) { - function d() { - e.destroy(); - h.isDirtyLegend = h.isDirtyBox = !0; - h.linkSeries(); - k(a, !0) && h.redraw(b); - } - var e = this, - h = e.chart; - !1 !== c ? u(e, 'remove', null, d) : d(); - }, - update: function(a, b) { - var d = this, - e = d.chart, - h = d.userOptions, - f = d.oldType || d.type, - l = a.type || h.type || e.options.chart.type, - g = I[f].prototype, - m, - n = ['group', 'markerGroup', 'dataLabelsGroup'], - t = ['navigatorSeries', 'baseSeries'], - x = d.finishedAnimating && { animation: !1 }; - if (Object.keys && 'data' === Object.keys(a).toString()) - return this.setData(a.data, b); - t = n.concat(t); - r(t, function(a) { - t[a] = d[a]; - delete d[a]; - }); - a = c( - h, - x, - { index: d.index, pointStart: d.xData[0] }, - { data: d.options.data }, - a, - ); - d.remove(!1, null, !1); - for (m in g) d[m] = void 0; - w(d, I[l || f].prototype); - r(t, function(a) { - d[a] = t[a]; - }); - d.init(e, a); - a.zIndex !== h.zIndex && - r(n, function(b) { - d[b] && d[b].attr({ zIndex: a.zIndex }); - }); - d.oldType = f; - e.linkSeries(); - k(b, !0) && e.redraw(!1); - }, - }); - w(H.prototype, { - update: function(a, b) { - var d = this.chart; - a = d.options[this.coll][this.options.index] = c(this.userOptions, a); - this.destroy(!0); - this.init(d, w(a, { events: void 0 })); - d.isDirtyBox = !0; - k(b, !0) && d.redraw(); - }, - remove: function(a) { - for ( - var b = this.chart, c = this.coll, e = this.series, h = e.length; - h--; - - ) - e[h] && e[h].remove(!1); - n(b.axes, this); - n(b[c], this); - d(b.options[c]) - ? b.options[c].splice(this.options.index, 1) - : delete b.options[c]; - r(b[c], function(a, b) { - a.options.index = b; - }); - this.destroy(); - b.isDirtyBox = !0; - k(a, !0) && b.redraw(); - }, - setTitle: function(a, b) { - this.update({ title: a }, b); - }, - setCategories: function(a, b) { - this.update({ categories: a }, b); - }, - }); - })(M); - (function(a) { - var E = a.color, - D = a.each, - H = a.map, - p = a.pick, - f = a.Series, - l = a.seriesType; - l( - 'area', - 'line', - { softThreshold: !1, threshold: 0 }, - { - singleStacks: !1, - getStackPoints: function(f) { - var l = [], - r = [], - u = this.xAxis, - e = this.yAxis, - h = e.stacks[this.stackKey], - m = {}, - d = this.index, - c = e.series, - b = c.length, - k, - z = p(e.options.reversedStacks, !0) ? 1 : -1, - B; - f = f || this.points; - if (this.options.stacking) { - for (B = 0; B < f.length; B++) - (f[B].leftNull = f[B].rightNull = null), (m[f[B].x] = f[B]); - a.objectEach(h, function(a, b) { - null !== a.total && r.push(b); - }); - r.sort(function(a, b) { - return a - b; - }); - k = H(c, function() { - return this.visible; - }); - D(r, function(a, c) { - var f = 0, - n, - x; - if (m[a] && !m[a].isNull) - l.push(m[a]), - D([-1, 1], function(e) { - var f = 1 === e ? 'rightNull' : 'leftNull', - l = 0, - t = h[r[c + e]]; - if (t) - for (B = d; 0 <= B && B < b; ) - (n = t.points[B]), - n || - (B === d - ? (m[a][f] = !0) - : k[B] && - (x = h[a].points[B]) && - (l -= x[1] - x[0])), - (B += z); - m[a][1 === e ? 'rightCliff' : 'leftCliff'] = l; - }); - else { - for (B = d; 0 <= B && B < b; ) { - if ((n = h[a].points[B])) { - f = n[1]; - break; - } - B += z; - } - f = e.translate(f, 0, 1, 0, 1); - l.push({ - isNull: !0, - plotX: u.translate(a, 0, 0, 0, 1), - x: a, - plotY: f, - yBottom: f, - }); - } - }); - } - return l; - }, - getGraphPath: function(a) { - var l = f.prototype.getGraphPath, - r = this.options, - u = r.stacking, - e = this.yAxis, - h, - m, - d = [], - c = [], - b = this.index, - k, - z = e.stacks[this.stackKey], - B = r.threshold, - I = e.getThreshold(r.threshold), - x, - r = r.connectNulls || 'percent' === u, - K = function(h, f, l) { - var m = a[h]; - h = u && z[m.x].points[b]; - var n = m[l + 'Null'] || 0; - l = m[l + 'Cliff'] || 0; - var x, - t, - m = !0; - l || n - ? ((x = (n ? h[0] : h[1]) + l), (t = h[0] + l), (m = !!n)) - : !u && a[f] && a[f].isNull && (x = t = B); - void 0 !== x && - (c.push({ - plotX: k, - plotY: null === x ? I : e.getThreshold(x), - isNull: m, - isCliff: !0, - }), - d.push({ - plotX: k, - plotY: null === t ? I : e.getThreshold(t), - doCurve: !1, - })); - }; - a = a || this.points; - u && (a = this.getStackPoints(a)); - for (h = 0; h < a.length; h++) - if ( - ((m = a[h].isNull), - (k = p(a[h].rectPlotX, a[h].plotX)), - (x = p(a[h].yBottom, I)), - !m || r) - ) - r || K(h, h - 1, 'left'), - (m && !u && r) || - (c.push(a[h]), d.push({ x: h, plotX: k, plotY: x })), - r || K(h, h + 1, 'right'); - h = l.call(this, c, !0, !0); - d.reversed = !0; - m = l.call(this, d, !0, !0); - m.length && (m[0] = 'L'); - m = h.concat(m); - l = l.call(this, c, !1, r); - m.xMap = h.xMap; - this.areaPath = m; - return l; - }, - drawGraph: function() { - this.areaPath = []; - f.prototype.drawGraph.apply(this); - var a = this, - l = this.areaPath, - w = this.options, - u = [['area', 'highcharts-area', this.color, w.fillColor]]; - D(this.zones, function(e, h) { - u.push([ - 'zone-area-' + h, - 'highcharts-area highcharts-zone-area-' + h + ' ' + e.className, - e.color || a.color, - e.fillColor || w.fillColor, - ]); - }); - D(u, function(e) { - var h = e[0], - f = a[h]; - f - ? ((f.endX = a.preventGraphAnimation ? null : l.xMap), - f.animate({ d: l })) - : ((f = a[h] = a.chart.renderer - .path(l) - .addClass(e[1]) - .attr({ - fill: p( - e[3], - E(e[2]) - .setOpacity(p(w.fillOpacity, 0.75)) - .get(), - ), - zIndex: 0, - }) - .add(a.group)), - (f.isArea = !0)); - f.startX = l.xMap; - f.shiftUnit = w.step ? 2 : 1; - }); - }, - drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, - }, - ); - })(M); - (function(a) { - var E = a.pick; - a = a.seriesType; - a( - 'spline', - 'line', - {}, - { - getPointSpline: function(a, H, p) { - var f = H.plotX, - l = H.plotY, - r = a[p - 1]; - p = a[p + 1]; - var n, w, u, e; - if ( - r && - !r.isNull && - !1 !== r.doCurve && - !H.isCliff && - p && - !p.isNull && - !1 !== p.doCurve && - !H.isCliff - ) { - a = r.plotY; - u = p.plotX; - p = p.plotY; - var h = 0; - n = (1.5 * f + r.plotX) / 2.5; - w = (1.5 * l + a) / 2.5; - u = (1.5 * f + u) / 2.5; - e = (1.5 * l + p) / 2.5; - u !== n && (h = ((e - w) * (u - f)) / (u - n) + l - e); - w += h; - e += h; - w > a && w > l - ? ((w = Math.max(a, l)), (e = 2 * l - w)) - : w < a && w < l && ((w = Math.min(a, l)), (e = 2 * l - w)); - e > p && e > l - ? ((e = Math.max(p, l)), (w = 2 * l - e)) - : e < p && e < l && ((e = Math.min(p, l)), (w = 2 * l - e)); - H.rightContX = u; - H.rightContY = e; - } - H = [ - 'C', - E(r.rightContX, r.plotX), - E(r.rightContY, r.plotY), - E(n, f), - E(w, l), - f, - l, - ]; - r.rightContX = r.rightContY = null; - return H; - }, - }, - ); - })(M); - (function(a) { - var E = a.seriesTypes.area.prototype, - D = a.seriesType; - D('areaspline', 'spline', a.defaultPlotOptions.area, { - getStackPoints: E.getStackPoints, - getGraphPath: E.getGraphPath, - drawGraph: E.drawGraph, - drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, - }); - })(M); - (function(a) { - var E = a.animObject, - D = a.color, - H = a.each, - p = a.extend, - f = a.isNumber, - l = a.merge, - r = a.pick, - n = a.Series, - w = a.seriesType, - u = a.svg; - w( - 'column', - 'line', - { - borderRadius: 0, - crisp: !0, - groupPadding: 0.2, - marker: null, - pointPadding: 0.1, - minPointLength: 0, - cropThreshold: 50, - pointRange: null, - states: { - hover: { halo: !1, brightness: 0.1 }, - select: { color: '#cccccc', borderColor: '#000000' }, - }, - dataLabels: { align: null, verticalAlign: null, y: null }, - softThreshold: !1, - startFromThreshold: !0, - stickyTracking: !1, - tooltip: { distance: 6 }, - threshold: 0, - borderColor: '#ffffff', - }, - { - cropShoulder: 0, - directTouch: !0, - trackerGroups: ['group', 'dataLabelsGroup'], - negStacks: !0, - init: function() { - n.prototype.init.apply(this, arguments); - var a = this, - h = a.chart; - h.hasRendered && - H(h.series, function(e) { - e.type === a.type && (e.isDirty = !0); - }); - }, - getColumnMetrics: function() { - var a = this, - h = a.options, - f = a.xAxis, - d = a.yAxis, - c = f.reversed, - b, - k = {}, - l = 0; - !1 === h.grouping - ? (l = 1) - : H(a.chart.series, function(c) { - var e = c.options, - h = c.yAxis, - f; - c.type !== a.type || - (!c.visible && a.chart.options.chart.ignoreHiddenSeries) || - d.len !== h.len || - d.pos !== h.pos || - (e.stacking - ? ((b = c.stackKey), - void 0 === k[b] && (k[b] = l++), - (f = k[b])) - : !1 !== e.grouping && (f = l++), - (c.columnIndex = f)); - }); - var n = Math.min( - Math.abs(f.transA) * - (f.ordinalSlope || - h.pointRange || - f.closestPointRange || - f.tickInterval || - 1), - f.len, - ), - p = n * h.groupPadding, - x = (n - 2 * p) / (l || 1), - h = Math.min( - h.maxPointWidth || f.len, - r(h.pointWidth, x * (1 - 2 * h.pointPadding)), - ); - a.columnMetrics = { - width: h, - offset: - (x - h) / 2 + - (p + ((a.columnIndex || 0) + (c ? 1 : 0)) * x - n / 2) * - (c ? -1 : 1), - }; - return a.columnMetrics; - }, - crispCol: function(a, h, f, d) { - var c = this.chart, - b = this.borderWidth, - e = -(b % 2 ? 0.5 : 0), - b = b % 2 ? 0.5 : 1; - c.inverted && c.renderer.isVML && (b += 1); - this.options.crisp && - ((f = Math.round(a + f) + e), (a = Math.round(a) + e), (f -= a)); - d = Math.round(h + d) + b; - e = 0.5 >= Math.abs(h) && 0.5 < d; - h = Math.round(h) + b; - d -= h; - e && d && (--h, (d += 1)); - return { x: a, y: h, width: f, height: d }; - }, - translate: function() { - var a = this, - h = a.chart, - f = a.options, - d = (a.dense = 2 > a.closestPointRange * a.xAxis.transA), - d = (a.borderWidth = r(f.borderWidth, d ? 0 : 1)), - c = a.yAxis, - b = f.threshold, - k = (a.translatedThreshold = c.getThreshold(b)), - l = r(f.minPointLength, 5), - p = a.getColumnMetrics(), - u = p.width, - x = (a.barW = Math.max(u, 1 + 2 * d)), - w = (a.pointXOffset = p.offset); - h.inverted && (k -= 0.5); - f.pointPadding && (x = Math.ceil(x)); - n.prototype.translate.apply(a); - H(a.points, function(d) { - var e = r(d.yBottom, k), - f = 999 + Math.abs(e), - f = Math.min(Math.max(-f, d.plotY), c.len + f), - m = d.plotX + w, - n = x, - t = Math.min(f, e), - p, - g = Math.max(f, e) - t; - l && - Math.abs(g) < l && - ((g = l), - (p = (!c.reversed && !d.negative) || (c.reversed && d.negative)), - d.y === b && a.dataMax <= b && c.min < b && (p = !p), - (t = Math.abs(t - k) > l ? e - l : k - (p ? l : 0))); - d.barX = m; - d.pointWidth = u; - d.tooltipPos = h.inverted - ? [c.len + c.pos - h.plotLeft - f, a.xAxis.len - m - n / 2, g] - : [m + n / 2, f + c.pos - h.plotTop, g]; - d.shapeType = 'rect'; - d.shapeArgs = a.crispCol.apply( - a, - d.isNull ? [m, k, n, 0] : [m, t, n, g], - ); - }); - }, - getSymbol: a.noop, - drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, - drawGraph: function() { - this.group[this.dense ? 'addClass' : 'removeClass']( - 'highcharts-dense-data', - ); - }, - pointAttribs: function(a, f) { - var e = this.options, - d, - c = this.pointAttrToOptions || {}; - d = c.stroke || 'borderColor'; - var b = c['stroke-width'] || 'borderWidth', - k = (a && a.color) || this.color, - h = (a && a[d]) || e[d] || this.color || k, - n = (a && a[b]) || e[b] || this[b] || 0, - c = e.dashStyle; - a && - this.zones.length && - ((k = a.getZone()), - (k = a.options.color || (k && k.color) || this.color)); - f && - ((a = l( - e.states[f], - (a.options.states && a.options.states[f]) || {}, - )), - (f = a.brightness), - (k = - a.color || - (void 0 !== f && - D(k) - .brighten(a.brightness) - .get()) || - k), - (h = a[d] || h), - (n = a[b] || n), - (c = a.dashStyle || c)); - d = { fill: k, stroke: h, 'stroke-width': n }; - c && (d.dashstyle = c); - return d; - }, - drawPoints: function() { - var a = this, - h = this.chart, - m = a.options, - d = h.renderer, - c = m.animationLimit || 250, - b; - H(a.points, function(e) { - var k = e.graphic; - if (f(e.plotY) && null !== e.y) { - b = e.shapeArgs; - if (k) k[h.pointCount < c ? 'animate' : 'attr'](l(b)); - else e.graphic = k = d[e.shapeType](b).add(e.group || a.group); - m.borderRadius && k.attr({ r: m.borderRadius }); - k.attr(a.pointAttribs(e, e.selected && 'select')).shadow( - m.shadow, - null, - m.stacking && !m.borderRadius, - ); - k.addClass(e.getClassName(), !0); - } else k && (e.graphic = k.destroy()); - }); - }, - animate: function(a) { - var e = this, - f = this.yAxis, - d = e.options, - c = this.chart.inverted, - b = {}, - k = c ? 'translateX' : 'translateY', - l; - u && - (a - ? ((b.scaleY = 0.001), - (a = Math.min( - f.pos + f.len, - Math.max(f.pos, f.toPixels(d.threshold)), - )), - c ? (b.translateX = a - f.len) : (b.translateY = a), - e.group.attr(b)) - : ((l = e.group.attr(k)), - e.group.animate( - { scaleY: 1 }, - p(E(e.options.animation), { - step: function(a, c) { - b[k] = l + c.pos * (f.pos - l); - e.group.attr(b); - }, - }), - ), - (e.animate = null))); - }, - remove: function() { - var a = this, - f = a.chart; - f.hasRendered && - H(f.series, function(e) { - e.type === a.type && (e.isDirty = !0); - }); - n.prototype.remove.apply(a, arguments); - }, - }, - ); - })(M); - (function(a) { - a = a.seriesType; - a('bar', 'column', null, { inverted: !0 }); - })(M); - (function(a) { - var E = a.Series; - a = a.seriesType; - a( - 'scatter', - 'line', - { - lineWidth: 0, - findNearestPointBy: 'xy', - marker: { enabled: !0 }, - tooltip: { - headerFormat: - '\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e \x3cspan style\x3d"font-size: 0.85em"\x3e {series.name}\x3c/span\x3e\x3cbr/\x3e', - pointFormat: - 'x: \x3cb\x3e{point.x}\x3c/b\x3e\x3cbr/\x3ey: \x3cb\x3e{point.y}\x3c/b\x3e\x3cbr/\x3e', - }, - }, - { - sorted: !1, - requireSorting: !1, - noSharedTooltip: !0, - trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], - takeOrdinalPosition: !1, - drawGraph: function() { - this.options.lineWidth && E.prototype.drawGraph.call(this); - }, - }, - ); - })(M); - (function(a) { - var E = a.deg2rad, - D = a.isNumber, - H = a.pick, - p = a.relativeLength; - a.CenteredSeriesMixin = { - getCenter: function() { - var a = this.options, - l = this.chart, - r = 2 * (a.slicedOffset || 0), - n = l.plotWidth - 2 * r, - l = l.plotHeight - 2 * r, - w = a.center, - w = [ - H(w[0], '50%'), - H(w[1], '50%'), - a.size || '100%', - a.innerSize || 0, - ], - u = Math.min(n, l), - e, - h; - for (e = 0; 4 > e; ++e) - (h = w[e]), - (a = 2 > e || (2 === e && /%$/.test(h))), - (w[e] = p(h, [n, l, u, w[2]][e]) + (a ? r : 0)); - w[3] > w[2] && (w[3] = w[2]); - return w; - }, - getStartAndEndRadians: function(a, l) { - a = D(a) ? a : 0; - l = D(l) && l > a && 360 > l - a ? l : a + 360; - return { start: E * (a + -90), end: E * (l + -90) }; - }, - }; - })(M); - (function(a) { - var E = a.addEvent, - D = a.CenteredSeriesMixin, - H = a.defined, - p = a.each, - f = a.extend, - l = D.getStartAndEndRadians, - r = a.inArray, - n = a.noop, - w = a.pick, - u = a.Point, - e = a.Series, - h = a.seriesType, - m = a.setAnimation; - h( - 'pie', - 'line', - { - center: [null, null], - clip: !1, - colorByPoint: !0, - dataLabels: { - distance: 30, - enabled: !0, - formatter: function() { - return this.point.isNull ? void 0 : this.point.name; - }, - x: 0, - }, - ignoreHiddenPoint: !0, - legendType: 'point', - marker: null, - size: null, - showInLegend: !1, - slicedOffset: 10, - stickyTracking: !1, - tooltip: { followPointer: !0 }, - borderColor: '#ffffff', - borderWidth: 1, - states: { hover: { brightness: 0.1, shadow: !1 } }, - }, - { - isCartesian: !1, - requireSorting: !1, - directTouch: !0, - noSharedTooltip: !0, - trackerGroups: ['group', 'dataLabelsGroup'], - axisTypes: [], - pointAttribs: a.seriesTypes.column.prototype.pointAttribs, - animate: function(a) { - var c = this, - b = c.points, - d = c.startAngleRad; - a || - (p(b, function(a) { - var b = a.graphic, - e = a.shapeArgs; - b && - (b.attr({ r: a.startR || c.center[3] / 2, start: d, end: d }), - b.animate( - { r: e.r, start: e.start, end: e.end }, - c.options.animation, - )); - }), - (c.animate = null)); - }, - updateTotals: function() { - var a, - c = 0, - b = this.points, - e = b.length, - f, - h = this.options.ignoreHiddenPoint; - for (a = 0; a < e; a++) - (f = b[a]), (c += h && !f.visible ? 0 : f.isNull ? 0 : f.y); - this.total = c; - for (a = 0; a < e; a++) - (f = b[a]), - (f.percentage = 0 < c && (f.visible || !h) ? (f.y / c) * 100 : 0), - (f.total = c); - }, - generatePoints: function() { - e.prototype.generatePoints.call(this); - this.updateTotals(); - }, - translate: function(a) { - this.generatePoints(); - var c = 0, - b = this.options, - d = b.slicedOffset, - e = d + (b.borderWidth || 0), - f, - h, - m, - n = l(b.startAngle, b.endAngle), - t = (this.startAngleRad = n.start), - n = (this.endAngleRad = n.end) - t, - p = this.points, - u, - q = b.dataLabels.distance, - b = b.ignoreHiddenPoint, - r, - F = p.length, - G; - a || (this.center = a = this.getCenter()); - this.getX = function(b, c, d) { - m = Math.asin( - Math.min((b - a[1]) / (a[2] / 2 + d.labelDistance), 1), - ); - return ( - a[0] + (c ? -1 : 1) * Math.cos(m) * (a[2] / 2 + d.labelDistance) - ); - }; - for (r = 0; r < F; r++) { - G = p[r]; - G.labelDistance = w( - G.options.dataLabels && G.options.dataLabels.distance, - q, - ); - this.maxLabelDistance = Math.max( - this.maxLabelDistance || 0, - G.labelDistance, - ); - f = t + c * n; - if (!b || G.visible) c += G.percentage / 100; - h = t + c * n; - G.shapeType = 'arc'; - G.shapeArgs = { - x: a[0], - y: a[1], - r: a[2] / 2, - innerR: a[3] / 2, - start: Math.round(1e3 * f) / 1e3, - end: Math.round(1e3 * h) / 1e3, - }; - m = (h + f) / 2; - m > 1.5 * Math.PI - ? (m -= 2 * Math.PI) - : m < -Math.PI / 2 && (m += 2 * Math.PI); - G.slicedTranslation = { - translateX: Math.round(Math.cos(m) * d), - translateY: Math.round(Math.sin(m) * d), - }; - h = (Math.cos(m) * a[2]) / 2; - u = (Math.sin(m) * a[2]) / 2; - G.tooltipPos = [a[0] + 0.7 * h, a[1] + 0.7 * u]; - G.half = m < -Math.PI / 2 || m > Math.PI / 2 ? 1 : 0; - G.angle = m; - f = Math.min(e, G.labelDistance / 5); - G.labelPos = [ - a[0] + h + Math.cos(m) * G.labelDistance, - a[1] + u + Math.sin(m) * G.labelDistance, - a[0] + h + Math.cos(m) * f, - a[1] + u + Math.sin(m) * f, - a[0] + h, - a[1] + u, - 0 > G.labelDistance ? 'center' : G.half ? 'right' : 'left', - m, - ]; - } - }, - drawGraph: null, - drawPoints: function() { - var a = this, - c = a.chart.renderer, - b, - e, - h, - l, - m = a.options.shadow; - m && !a.shadowGroup && (a.shadowGroup = c.g('shadow').add(a.group)); - p(a.points, function(d) { - e = d.graphic; - if (d.isNull) e && (d.graphic = e.destroy()); - else { - l = d.shapeArgs; - b = d.getTranslate(); - var k = d.shadowGroup; - m && !k && (k = d.shadowGroup = c.g('shadow').add(a.shadowGroup)); - k && k.attr(b); - h = a.pointAttribs(d, d.selected && 'select'); - e - ? e - .setRadialReference(a.center) - .attr(h) - .animate(f(l, b)) - : ((d.graphic = e = c[d.shapeType](l) - .setRadialReference(a.center) - .attr(b) - .add(a.group)), - d.visible || e.attr({ visibility: 'hidden' }), - e - .attr(h) - .attr({ 'stroke-linejoin': 'round' }) - .shadow(m, k)); - e.addClass(d.getClassName()); - } - }); - }, - searchPoint: n, - sortByAngle: function(a, c) { - a.sort(function(a, d) { - return void 0 !== a.angle && (d.angle - a.angle) * c; - }); - }, - drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, - getCenter: D.getCenter, - getSymbol: n, - }, - { - init: function() { - u.prototype.init.apply(this, arguments); - var a = this, - c; - a.name = w(a.name, 'Slice'); - c = function(b) { - a.slice('select' === b.type); - }; - E(a, 'select', c); - E(a, 'unselect', c); - return a; - }, - isValid: function() { - return a.isNumber(this.y, !0) && 0 <= this.y; - }, - setVisible: function(a, c) { - var b = this, - d = b.series, - e = d.chart, - f = d.options.ignoreHiddenPoint; - c = w(c, f); - a !== b.visible && - ((b.visible = b.options.visible = a = - void 0 === a ? !b.visible : a), - (d.options.data[r(b, d.data)] = b.options), - p(['graphic', 'dataLabel', 'connector', 'shadowGroup'], function( - c, - ) { - if (b[c]) b[c][a ? 'show' : 'hide'](!0); - }), - b.legendItem && e.legend.colorizeItem(b, a), - a || 'hover' !== b.state || b.setState(''), - f && (d.isDirty = !0), - c && e.redraw()); - }, - slice: function(a, c, b) { - var d = this.series; - m(b, d.chart); - w(c, !0); - this.sliced = this.options.sliced = H(a) ? a : !this.sliced; - d.options.data[r(this, d.data)] = this.options; - this.graphic.animate(this.getTranslate()); - this.shadowGroup && this.shadowGroup.animate(this.getTranslate()); - }, - getTranslate: function() { - return this.sliced - ? this.slicedTranslation - : { translateX: 0, translateY: 0 }; - }, - haloPath: function(a) { - var c = this.shapeArgs; - return this.sliced || !this.visible - ? [] - : this.series.chart.renderer.symbols.arc( - c.x, - c.y, - c.r + a, - c.r + a, - { innerR: this.shapeArgs.r - 1, start: c.start, end: c.end }, - ); - }, - }, - ); - })(M); - (function(a) { - var E = a.addEvent, - D = a.arrayMax, - H = a.defined, - p = a.each, - f = a.extend, - l = a.format, - r = a.map, - n = a.merge, - w = a.noop, - u = a.pick, - e = a.relativeLength, - h = a.Series, - m = a.seriesTypes, - d = a.stableSort; - a.distribute = function(a, b) { - function c(a, b) { - return a.target - b.target; - } - var e, - f = !0, - h = a, - l = [], - m; - m = 0; - for (e = a.length; e--; ) m += a[e].size; - if (m > b) { - d(a, function(a, b) { - return (b.rank || 0) - (a.rank || 0); - }); - for (m = e = 0; m <= b; ) (m += a[e].size), e++; - l = a.splice(e - 1, a.length); - } - d(a, c); - for ( - a = r(a, function(a) { - return { size: a.size, targets: [a.target], align: u(a.align, 0.5) }; - }); - f; - - ) { - for (e = a.length; e--; ) - (f = a[e]), - (m = - (Math.min.apply(0, f.targets) + Math.max.apply(0, f.targets)) / - 2), - (f.pos = Math.min(Math.max(0, m - f.size * f.align), b - f.size)); - e = a.length; - for (f = !1; e--; ) - 0 < e && - a[e - 1].pos + a[e - 1].size > a[e].pos && - ((a[e - 1].size += a[e].size), - (a[e - 1].targets = a[e - 1].targets.concat(a[e].targets)), - (a[e - 1].align = 0.5), - a[e - 1].pos + a[e - 1].size > b && - (a[e - 1].pos = b - a[e - 1].size), - a.splice(e, 1), - (f = !0)); - } - e = 0; - p(a, function(a) { - var b = 0; - p(a.targets, function() { - h[e].pos = a.pos + b; - b += h[e].size; - e++; - }); - }); - h.push.apply(h, l); - d(h, c); - }; - h.prototype.drawDataLabels = function() { - function c(a, b) { - var c = b.filter; - return c - ? ((b = c.operator), - (a = a[c.property]), - (c = c.value), - ('\x3e' === b && a > c) || - ('\x3c' === b && a < c) || - ('\x3e\x3d' === b && a >= c) || - ('\x3c\x3d' === b && a <= c) || - ('\x3d\x3d' === b && a == c) || - ('\x3d\x3d\x3d' === b && a === c) - ? !0 - : !1) - : !0; - } - var b = this, - d = b.options, - e = d.dataLabels, - f = b.points, - h, - m, - r = b.hasRendered || 0, - t, - w, - D = u(e.defer, !!d.animation), - q = b.chart.renderer; - if (e.enabled || b._hasPointLabels) - b.dlProcessOptions && b.dlProcessOptions(e), - (w = b.plotGroup( - 'dataLabelsGroup', - 'data-labels', - D && !r ? 'hidden' : 'visible', - e.zIndex || 6, - )), - D && - (w.attr({ opacity: +r }), - r || - E(b, 'afterAnimate', function() { - b.visible && w.show(!0); - w[d.animation ? 'animate' : 'attr']( - { opacity: 1 }, - { duration: 200 }, - ); - })), - (m = e), - p(f, function(f) { - var k, - p = f.dataLabel, - g, - x, - r = f.connector, - z = !p, - C; - h = f.dlOptions || (f.options && f.options.dataLabels); - (k = u(h && h.enabled, m.enabled) && !f.isNull) && - (k = !0 === c(f, h || e)); - k && - ((e = n(m, h)), - (g = f.getLabelConfig()), - (C = e[f.formatPrefix + 'Format'] || e.format), - (t = H(C) - ? l(C, g) - : (e[f.formatPrefix + 'Formatter'] || e.formatter).call(g, e)), - (C = e.style), - (g = e.rotation), - (C.color = u(e.color, C.color, b.color, '#000000')), - 'contrast' === C.color && - ((f.contrastColor = q.getContrast(f.color || b.color)), - (C.color = - e.inside || 0 > u(f.labelDistance, e.distance) || d.stacking - ? f.contrastColor - : '#000000')), - d.cursor && (C.cursor = d.cursor), - (x = { - fill: e.backgroundColor, - stroke: e.borderColor, - 'stroke-width': e.borderWidth, - r: e.borderRadius || 0, - rotation: g, - padding: e.padding, - zIndex: 1, - }), - a.objectEach(x, function(a, b) { - void 0 === a && delete x[b]; - })); - !p || (k && H(t)) - ? k && - H(t) && - (p - ? (x.text = t) - : ((p = f.dataLabel = g - ? q.text(t, 0, -9999).addClass('highcharts-data-label') - : q.label( - t, - 0, - -9999, - e.shape, - null, - null, - e.useHTML, - null, - 'data-label', - )), - p.addClass( - ' highcharts-data-label-color-' + - f.colorIndex + - ' ' + - (e.className || '') + - (e.useHTML ? 'highcharts-tracker' : ''), - )), - p.attr(x), - p.css(C).shadow(e.shadow), - p.added || p.add(w), - b.alignDataLabel(f, p, e, null, z)) - : ((f.dataLabel = p = p.destroy()), - r && (f.connector = r.destroy())); - }); - }; - h.prototype.alignDataLabel = function(a, b, d, e, h) { - var c = this.chart, - k = c.inverted, - l = u(a.dlBox && a.dlBox.centerX, a.plotX, -9999), - m = u(a.plotY, -9999), - n = b.getBBox(), - p, - q = d.rotation, - r = d.align, - w = - this.visible && - (a.series.forceDL || - c.isInsidePlot(l, Math.round(m), k) || - (e && c.isInsidePlot(l, k ? e.x + 1 : e.y + e.height - 1, k))), - z = 'justify' === u(d.overflow, 'justify'); - if ( - w && - ((p = d.style.fontSize), - (p = c.renderer.fontMetrics(p, b).b), - (e = f( - { - x: k ? this.yAxis.len - m : l, - y: Math.round(k ? this.xAxis.len - l : m), - width: 0, - height: 0, - }, - e, - )), - f(d, { width: n.width, height: n.height }), - q - ? ((z = !1), - (l = c.renderer.rotCorr(p, q)), - (l = { - x: e.x + d.x + e.width / 2 + l.x, - y: - e.y + - d.y + - { top: 0, middle: 0.5, bottom: 1 }[d.verticalAlign] * e.height, - }), - b[h ? 'attr' : 'animate'](l).attr({ align: r }), - (m = (q + 720) % 360), - (m = 180 < m && 360 > m), - 'left' === r - ? (l.y -= m ? n.height : 0) - : 'center' === r - ? ((l.x -= n.width / 2), (l.y -= n.height / 2)) - : 'right' === r && ((l.x -= n.width), (l.y -= m ? 0 : n.height))) - : (b.align(d, null, e), (l = b.alignAttr)), - z - ? (a.isLabelJustified = this.justifyDataLabel(b, d, l, n, e, h)) - : u(d.crop, !0) && - (w = - c.isInsidePlot(l.x, l.y) && - c.isInsidePlot(l.x + n.width, l.y + n.height)), - d.shape && !q) - ) - b[h ? 'attr' : 'animate']({ - anchorX: k ? c.plotWidth - a.plotY : a.plotX, - anchorY: k ? c.plotHeight - a.plotX : a.plotY, - }); - w || (b.attr({ y: -9999 }), (b.placed = !1)); - }; - h.prototype.justifyDataLabel = function(a, b, d, e, f, h) { - var c = this.chart, - k = b.align, - l = b.verticalAlign, - m, - n, - p = a.box ? 0 : a.padding || 0; - m = d.x + p; - 0 > m && ('right' === k ? (b.align = 'left') : (b.x = -m), (n = !0)); - m = d.x + e.width - p; - m > c.plotWidth && - ('left' === k ? (b.align = 'right') : (b.x = c.plotWidth - m), - (n = !0)); - m = d.y + p; - 0 > m && - ('bottom' === l ? (b.verticalAlign = 'top') : (b.y = -m), (n = !0)); - m = d.y + e.height - p; - m > c.plotHeight && - ('top' === l ? (b.verticalAlign = 'bottom') : (b.y = c.plotHeight - m), - (n = !0)); - n && ((a.placed = !h), a.align(b, null, f)); - return n; - }; - m.pie && - ((m.pie.prototype.drawDataLabels = function() { - var c = this, - b = c.data, - d, - e = c.chart, - f = c.options.dataLabels, - l = u(f.connectorPadding, 10), - m = u(f.connectorWidth, 1), - n = e.plotWidth, - t = e.plotHeight, - r, - w = c.center, - q = w[2] / 2, - A = w[1], - F, - G, - g, - v, - E = [[], []], - L, - P, - J, - M, - y = [0, 0, 0, 0]; - c.visible && - (f.enabled || c._hasPointLabels) && - (p(b, function(a) { - a.dataLabel && - a.visible && - a.dataLabel.shortened && - (a.dataLabel - .attr({ width: 'auto' }) - .css({ width: 'auto', textOverflow: 'clip' }), - (a.dataLabel.shortened = !1)); - }), - h.prototype.drawDataLabels.apply(c), - p(b, function(a) { - a.dataLabel && - a.visible && - (E[a.half].push(a), (a.dataLabel._pos = null)); - }), - p(E, function(b, h) { - var k, - m, - x = b.length, - r = [], - z; - if (x) - for ( - c.sortByAngle(b, h - 0.5), - 0 < c.maxLabelDistance && - ((k = Math.max(0, A - q - c.maxLabelDistance)), - (m = Math.min(A + q + c.maxLabelDistance, e.plotHeight)), - p(b, function(a) { - 0 < a.labelDistance && - a.dataLabel && - ((a.top = Math.max(0, A - q - a.labelDistance)), - (a.bottom = Math.min( - A + q + a.labelDistance, - e.plotHeight, - )), - (z = a.dataLabel.getBBox().height || 21), - (a.positionsIndex = - r.push({ - target: a.labelPos[1] - a.top + z / 2, - size: z, - rank: a.y, - }) - 1)); - }), - a.distribute(r, m + z - k)), - M = 0; - M < x; - M++ - ) - (d = b[M]), - (m = d.positionsIndex), - (g = d.labelPos), - (F = d.dataLabel), - (J = !1 === d.visible ? 'hidden' : 'inherit'), - (P = k = g[1]), - r && - H(r[m]) && - (void 0 === r[m].pos - ? (J = 'hidden') - : ((v = r[m].size), (P = d.top + r[m].pos))), - delete d.positionIndex, - (L = f.justify - ? w[0] + (h ? -1 : 1) * (q + d.labelDistance) - : c.getX(P < d.top + 2 || P > d.bottom - 2 ? k : P, h, d)), - (F._attr = { visibility: J, align: g[6] }), - (F._pos = { - x: L + f.x + ({ left: l, right: -l }[g[6]] || 0), - y: P + f.y - 10, - }), - (g.x = L), - (g.y = P), - u(f.crop, !0) && - ((G = F.getBBox().width), - (k = null), - L - G < l - ? ((k = Math.round(G - L + l)), - (y[3] = Math.max(k, y[3]))) - : L + G > n - l && - ((k = Math.round(L + G - n + l)), - (y[1] = Math.max(k, y[1]))), - 0 > P - v / 2 - ? (y[0] = Math.max(Math.round(-P + v / 2), y[0])) - : P + v / 2 > t && - (y[2] = Math.max(Math.round(P + v / 2 - t), y[2])), - (F.sideOverflow = k)); - }), - 0 === D(y) || this.verifyDataLabelOverflow(y)) && - (this.placeDataLabels(), - m && - p(this.points, function(a) { - var b; - r = a.connector; - if ( - (F = a.dataLabel) && - F._pos && - a.visible && - 0 < a.labelDistance - ) { - J = F._attr.visibility; - if ((b = !r)) - (a.connector = r = e.renderer - .path() - .addClass( - 'highcharts-data-label-connector highcharts-color-' + - a.colorIndex, - ) - .add(c.dataLabelsGroup)), - r.attr({ - 'stroke-width': m, - stroke: f.connectorColor || a.color || '#666666', - }); - r[b ? 'attr' : 'animate']({ d: c.connectorPath(a.labelPos) }); - r.attr('visibility', J); - } else r && (a.connector = r.destroy()); - })); - }), - (m.pie.prototype.connectorPath = function(a) { - var b = a.x, - c = a.y; - return u(this.options.dataLabels.softConnector, !0) - ? [ - 'M', - b + ('left' === a[6] ? 5 : -5), - c, - 'C', - b, - c, - 2 * a[2] - a[4], - 2 * a[3] - a[5], - a[2], - a[3], - 'L', - a[4], - a[5], - ] - : [ - 'M', - b + ('left' === a[6] ? 5 : -5), - c, - 'L', - a[2], - a[3], - 'L', - a[4], - a[5], - ]; - }), - (m.pie.prototype.placeDataLabels = function() { - p( - this.points, - function(a) { - var b = a.dataLabel; - b && - a.visible && - ((a = b._pos) - ? (b.sideOverflow && - ((b._attr.width = b.getBBox().width - b.sideOverflow), - b.css({ - width: b._attr.width + 'px', - textOverflow: 'ellipsis', - }), - (b.shortened = !0)), - b.attr(b._attr), - b[b.moved ? 'animate' : 'attr'](a), - (b.moved = !0)) - : b && b.attr({ y: -9999 })); - }, - this, - ); - }), - (m.pie.prototype.alignDataLabel = w), - (m.pie.prototype.verifyDataLabelOverflow = function(a) { - var b = this.center, - c = this.options, - d = c.center, - f = c.minSize || 80, - h, - l = null !== c.size; - l || - (null !== d[0] - ? (h = Math.max(b[2] - Math.max(a[1], a[3]), f)) - : ((h = Math.max(b[2] - a[1] - a[3], f)), - (b[0] += (a[3] - a[1]) / 2)), - null !== d[1] - ? (h = Math.max(Math.min(h, b[2] - Math.max(a[0], a[2])), f)) - : ((h = Math.max(Math.min(h, b[2] - a[0] - a[2]), f)), - (b[1] += (a[0] - a[2]) / 2)), - h < b[2] - ? ((b[2] = h), - (b[3] = Math.min(e(c.innerSize || 0, h), h)), - this.translate(b), - this.drawDataLabels && this.drawDataLabels()) - : (l = !0)); - return l; - })); - m.column && - (m.column.prototype.alignDataLabel = function(a, b, d, e, f) { - var c = this.chart.inverted, - k = a.series, - l = a.dlBox || a.shapeArgs, - m = u(a.below, a.plotY > u(this.translatedThreshold, k.yAxis.len)), - p = u(d.inside, !!this.options.stacking); - l && - ((e = n(l)), - 0 > e.y && ((e.height += e.y), (e.y = 0)), - (l = e.y + e.height - k.yAxis.len), - 0 < l && (e.height -= l), - c && - (e = { - x: k.yAxis.len - e.y - e.height, - y: k.xAxis.len - e.x - e.width, - width: e.height, - height: e.width, - }), - p || - (c - ? ((e.x += m ? 0 : e.width), (e.width = 0)) - : ((e.y += m ? e.height : 0), (e.height = 0)))); - d.align = u(d.align, !c || p ? 'center' : m ? 'right' : 'left'); - d.verticalAlign = u( - d.verticalAlign, - c || p ? 'middle' : m ? 'top' : 'bottom', - ); - h.prototype.alignDataLabel.call(this, a, b, d, e, f); - a.isLabelJustified && - a.contrastColor && - a.dataLabel.css({ color: a.contrastColor }); - }); - })(M); - (function(a) { - var E = a.Chart, - D = a.each, - H = a.objectEach, - p = a.pick; - a = a.addEvent; - a(E.prototype, 'render', function() { - var a = []; - D(this.labelCollectors || [], function(f) { - a = a.concat(f()); - }); - D(this.yAxis || [], function(f) { - f.options.stackLabels && - !f.options.stackLabels.allowOverlap && - H(f.stacks, function(f) { - H(f, function(f) { - a.push(f.label); - }); - }); - }); - D(this.series || [], function(f) { - var l = f.options.dataLabels, - n = f.dataLabelCollections || ['dataLabel']; - (l.enabled || f._hasPointLabels) && - !l.allowOverlap && - f.visible && - D(n, function(l) { - D(f.points, function(f) { - f[l] && - ((f[l].labelrank = p( - f.labelrank, - f.shapeArgs && f.shapeArgs.height, - )), - a.push(f[l])); - }); - }); - }); - this.hideOverlappingLabels(a); - }); - E.prototype.hideOverlappingLabels = function(a) { - var f = a.length, - p, - n, - w, - u, - e, - h, - m, - d, - c, - b = function(a, b, c, d, e, f, h, l) { - return !(e > a + c || e + h < a || f > b + d || f + l < b); - }; - for (n = 0; n < f; n++) - if ((p = a[n])) - (p.oldOpacity = p.opacity), - (p.newOpacity = 1), - p.width || - ((w = p.getBBox()), (p.width = w.width), (p.height = w.height)); - a.sort(function(a, b) { - return (b.labelrank || 0) - (a.labelrank || 0); - }); - for (n = 0; n < f; n++) - for (w = a[n], p = n + 1; p < f; ++p) - if ( - ((u = a[p]), - w && - u && - w !== u && - w.placed && - u.placed && - 0 !== w.newOpacity && - 0 !== u.newOpacity && - ((e = w.alignAttr), - (h = u.alignAttr), - (m = w.parentGroup), - (d = u.parentGroup), - (c = 2 * (w.box ? 0 : w.padding || 0)), - (e = b( - e.x + m.translateX, - e.y + m.translateY, - w.width - c, - w.height - c, - h.x + d.translateX, - h.y + d.translateY, - u.width - c, - u.height - c, - )))) - ) - (w.labelrank < u.labelrank ? w : u).newOpacity = 0; - D(a, function(a) { - var b, c; - a && - ((c = a.newOpacity), - a.oldOpacity !== c && - a.placed && - (c - ? a.show(!0) - : (b = function() { - a.hide(); - }), - (a.alignAttr.opacity = c), - a[a.isOld ? 'animate' : 'attr'](a.alignAttr, null, b)), - (a.isOld = !0)); - }); - }; - })(M); - (function(a) { - var E = a.addEvent, - D = a.Chart, - H = a.createElement, - p = a.css, - f = a.defaultOptions, - l = a.defaultPlotOptions, - r = a.each, - n = a.extend, - w = a.fireEvent, - u = a.hasTouch, - e = a.inArray, - h = a.isObject, - m = a.Legend, - d = a.merge, - c = a.pick, - b = a.Point, - k = a.Series, - z = a.seriesTypes, - B = a.svg, - I; - I = a.TrackerMixin = { - drawTrackerPoint: function() { - var a = this, - b = a.chart.pointer, - c = function(a) { - var c = b.getPointFromEvent(a); - void 0 !== c && ((b.isDirectTouch = !0), c.onMouseOver(a)); - }; - r(a.points, function(a) { - a.graphic && (a.graphic.element.point = a); - a.dataLabel && - (a.dataLabel.div - ? (a.dataLabel.div.point = a) - : (a.dataLabel.element.point = a)); - }); - a._hasTracking || - (r(a.trackerGroups, function(d) { - if (a[d]) { - a[d] - .addClass('highcharts-tracker') - .on('mouseover', c) - .on('mouseout', function(a) { - b.onTrackerMouseOut(a); - }); - if (u) a[d].on('touchstart', c); - a.options.cursor && a[d].css(p).css({ cursor: a.options.cursor }); - } - }), - (a._hasTracking = !0)); - }, - drawTrackerGraph: function() { - var a = this, - b = a.options, - c = b.trackByArea, - d = [].concat(c ? a.areaPath : a.graphPath), - e = d.length, - f = a.chart, - h = f.pointer, - k = f.renderer, - l = f.options.tooltip.snap, - g = a.tracker, - m, - n = function() { - if (f.hoverSeries !== a) a.onMouseOver(); - }, - p = 'rgba(192,192,192,' + (B ? 0.0001 : 0.002) + ')'; - if (e && !c) - for (m = e + 1; m--; ) - 'M' === d[m] && d.splice(m + 1, 0, d[m + 1] - l, d[m + 2], 'L'), - ((m && 'M' === d[m]) || m === e) && - d.splice(m, 0, 'L', d[m - 2] + l, d[m - 1]); - g - ? g.attr({ d: d }) - : a.graph && - ((a.tracker = k - .path(d) - .attr({ - 'stroke-linejoin': 'round', - visibility: a.visible ? 'visible' : 'hidden', - stroke: p, - fill: c ? p : 'none', - 'stroke-width': a.graph.strokeWidth() + (c ? 0 : 2 * l), - zIndex: 2, - }) - .add(a.group)), - r([a.tracker, a.markerGroup], function(a) { - a.addClass('highcharts-tracker') - .on('mouseover', n) - .on('mouseout', function(a) { - h.onTrackerMouseOut(a); - }); - b.cursor && a.css({ cursor: b.cursor }); - if (u) a.on('touchstart', n); - })); - }, - }; - z.column && (z.column.prototype.drawTracker = I.drawTrackerPoint); - z.pie && (z.pie.prototype.drawTracker = I.drawTrackerPoint); - z.scatter && (z.scatter.prototype.drawTracker = I.drawTrackerPoint); - n(m.prototype, { - setItemEvents: function(a, c, e) { - var f = this, - h = f.chart.renderer.boxWrapper, - k = - 'highcharts-legend-' + - (a instanceof b ? 'point' : 'series') + - '-active'; - (e ? c : a.legendGroup) - .on('mouseover', function() { - a.setState('hover'); - h.addClass(k); - c.css(f.options.itemHoverStyle); - }) - .on('mouseout', function() { - c.css(d(a.visible ? f.itemStyle : f.itemHiddenStyle)); - h.removeClass(k); - a.setState(); - }) - .on('click', function(b) { - var c = function() { - a.setVisible && a.setVisible(); - }; - h.removeClass(k); - b = { browserEvent: b }; - a.firePointEvent - ? a.firePointEvent('legendItemClick', b, c) - : w(a, 'legendItemClick', b, c); - }); - }, - createCheckboxForItem: function(a) { - a.checkbox = H( - 'input', - { type: 'checkbox', checked: a.selected, defaultChecked: a.selected }, - this.options.itemCheckboxStyle, - this.chart.container, - ); - E(a.checkbox, 'click', function(b) { - w( - a.series || a, - 'checkboxClick', - { checked: b.target.checked, item: a }, - function() { - a.select(); - }, - ); - }); - }, - }); - f.legend.itemStyle.cursor = 'pointer'; - n(D.prototype, { - showResetZoom: function() { - var a = this, - b = f.lang, - c = a.options.chart.resetZoomButton, - d = c.theme, - e = d.states, - h = 'chart' === c.relativeTo ? null : 'plotBox'; - this.resetZoomButton = a.renderer - .button( - b.resetZoom, - null, - null, - function() { - a.zoomOut(); - }, - d, - e && e.hover, - ) - .attr({ align: c.position.align, title: b.resetZoomTitle }) - .addClass('highcharts-reset-zoom') - .add() - .align(c.position, !1, h); - }, - zoomOut: function() { - var a = this; - w(a, 'selection', { resetSelection: !0 }, function() { - a.zoom(); - }); - }, - zoom: function(a) { - var b, - d = this.pointer, - e = !1, - f; - !a || a.resetSelection - ? (r(this.axes, function(a) { - b = a.zoom(); - }), - (d.initiated = !1)) - : r(a.xAxis.concat(a.yAxis), function(a) { - var c = a.axis; - d[c.isXAxis ? 'zoomX' : 'zoomY'] && - ((b = c.zoom(a.min, a.max)), c.displayBtn && (e = !0)); - }); - f = this.resetZoomButton; - e && !f - ? this.showResetZoom() - : !e && h(f) && (this.resetZoomButton = f.destroy()); - b && - this.redraw( - c( - this.options.chart.animation, - a && a.animation, - 100 > this.pointCount, - ), - ); - }, - pan: function(a, b) { - var c = this, - d = c.hoverPoints, - e; - d && - r(d, function(a) { - a.setState(); - }); - r('xy' === b ? [1, 0] : [1], function(b) { - b = c[b ? 'xAxis' : 'yAxis'][0]; - var d = b.horiz, - f = a[d ? 'chartX' : 'chartY'], - d = d ? 'mouseDownX' : 'mouseDownY', - h = c[d], - g = (b.pointRange || 0) / 2, - k = b.getExtremes(), - l = b.toValue(h - f, !0) + g, - m = b.toValue(h + b.len - f, !0) - g, - n = m < l, - h = n ? m : l, - l = n ? l : m, - m = Math.min( - k.dataMin, - g ? k.min : b.toValue(b.toPixels(k.min) - b.minPixelPadding), - ), - g = Math.max( - k.dataMax, - g ? k.max : b.toValue(b.toPixels(k.max) + b.minPixelPadding), - ), - n = m - h; - 0 < n && ((l += n), (h = m)); - n = l - g; - 0 < n && ((l = g), (h -= n)); - b.series.length && - h !== k.min && - l !== k.max && - (b.setExtremes(h, l, !1, !1, { trigger: 'pan' }), (e = !0)); - c[d] = f; - }); - e && c.redraw(!1); - p(c.container, { cursor: 'move' }); - }, - }); - n(b.prototype, { - select: function(a, b) { - var d = this, - f = d.series, - h = f.chart; - a = c(a, !d.selected); - d.firePointEvent( - a ? 'select' : 'unselect', - { accumulate: b }, - function() { - d.selected = d.options.selected = a; - f.options.data[e(d, f.data)] = d.options; - d.setState(a && 'select'); - b || - r(h.getSelectedPoints(), function(a) { - a.selected && - a !== d && - ((a.selected = a.options.selected = !1), - (f.options.data[e(a, f.data)] = a.options), - a.setState(''), - a.firePointEvent('unselect')); - }); - }, - ); - }, - onMouseOver: function(a) { - var b = this.series.chart, - c = b.pointer; - a = a - ? c.normalize(a) - : c.getChartCoordinatesFromPoint(this, b.inverted); - c.runPointActions(a, this); - }, - onMouseOut: function() { - var a = this.series.chart; - this.firePointEvent('mouseOut'); - r(a.hoverPoints || [], function(a) { - a.setState(); - }); - a.hoverPoints = a.hoverPoint = null; - }, - importEvents: function() { - if (!this.hasImportedEvents) { - var b = this, - c = d(b.series.options.point, b.options).events; - b.events = c; - a.objectEach(c, function(a, c) { - E(b, c, a); - }); - this.hasImportedEvents = !0; - } - }, - setState: function(a, b) { - var d = Math.floor(this.plotX), - e = this.plotY, - f = this.series, - h = f.options.states[a] || {}, - k = l[f.type].marker && f.options.marker, - m = k && !1 === k.enabled, - p = (k && k.states && k.states[a]) || {}, - g = !1 === p.enabled, - r = f.stateMarkerGraphic, - u = this.marker || {}, - w = f.chart, - x = f.halo, - z, - B = k && f.markerAttribs; - a = a || ''; - if ( - !( - (a === this.state && !b) || - (this.selected && 'select' !== a) || - !1 === h.enabled || - (a && (g || (m && !1 === p.enabled))) || - (a && u.states && u.states[a] && !1 === u.states[a].enabled) - ) - ) { - B && (z = f.markerAttribs(this, a)); - if (this.graphic) - this.state && - this.graphic.removeClass('highcharts-point-' + this.state), - a && this.graphic.addClass('highcharts-point-' + a), - this.graphic.animate( - f.pointAttribs(this, a), - c(w.options.chart.animation, h.animation), - ), - z && - this.graphic.animate( - z, - c(w.options.chart.animation, p.animation, k.animation), - ), - r && r.hide(); - else { - if (a && p) { - k = u.symbol || f.symbol; - r && r.currentSymbol !== k && (r = r.destroy()); - if (r) r[b ? 'animate' : 'attr']({ x: z.x, y: z.y }); - else - k && - ((f.stateMarkerGraphic = r = w.renderer - .symbol(k, z.x, z.y, z.width, z.height) - .add(f.markerGroup)), - (r.currentSymbol = k)); - r && r.attr(f.pointAttribs(this, a)); - } - r && - (r[a && w.isInsidePlot(d, e, w.inverted) ? 'show' : 'hide'](), - (r.element.point = this)); - } - (d = h.halo) && d.size - ? (x || - (f.halo = x = w.renderer - .path() - .add((this.graphic || r).parentGroup)), - x[b ? 'animate' : 'attr']({ d: this.haloPath(d.size) }), - x.attr({ - class: - 'highcharts-halo highcharts-color-' + - c(this.colorIndex, f.colorIndex), - }), - (x.point = this), - x.attr( - n( - { - fill: this.color || f.color, - 'fill-opacity': d.opacity, - zIndex: -1, - }, - d.attributes, - ), - )) - : x && - x.point && - x.point.haloPath && - x.animate({ d: x.point.haloPath(0) }); - this.state = a; - } - }, - haloPath: function(a) { - return this.series.chart.renderer.symbols.circle( - Math.floor(this.plotX) - a, - this.plotY - a, - 2 * a, - 2 * a, - ); - }, - }); - n(k.prototype, { - onMouseOver: function() { - var a = this.chart, - b = a.hoverSeries; - if (b && b !== this) b.onMouseOut(); - this.options.events.mouseOver && w(this, 'mouseOver'); - this.setState('hover'); - a.hoverSeries = this; - }, - onMouseOut: function() { - var a = this.options, - b = this.chart, - c = b.tooltip, - d = b.hoverPoint; - b.hoverSeries = null; - if (d) d.onMouseOut(); - this && a.events.mouseOut && w(this, 'mouseOut'); - !c || - this.stickyTracking || - (c.shared && !this.noSharedTooltip) || - c.hide(); - this.setState(); - }, - setState: function(a) { - var b = this, - d = b.options, - e = b.graph, - f = d.states, - h = d.lineWidth, - d = 0; - a = a || ''; - if ( - b.state !== a && - (r([b.group, b.markerGroup, b.dataLabelsGroup], function(c) { - c && - (b.state && c.removeClass('highcharts-series-' + b.state), - a && c.addClass('highcharts-series-' + a)); - }), - (b.state = a), - !f[a] || !1 !== f[a].enabled) && - (a && (h = f[a].lineWidth || h + (f[a].lineWidthPlus || 0)), - e && !e.dashstyle) - ) - for ( - h = { 'stroke-width': h }, - e.animate( - h, - c(b.chart.options.chart.animation, f[a] && f[a].animation), - ); - b['zone-graph-' + d]; - - ) - b['zone-graph-' + d].attr(h), (d += 1); - }, - setVisible: function(a, b) { - var c = this, - d = c.chart, - e = c.legendItem, - f, - h = d.options.chart.ignoreHiddenSeries, - k = c.visible; - f = (c.visible = a = c.options.visible = c.userOptions.visible = - void 0 === a ? !k : a) - ? 'show' - : 'hide'; - r( - ['group', 'dataLabelsGroup', 'markerGroup', 'tracker', 'tt'], - function(a) { - if (c[a]) c[a][f](); - }, - ); - if (d.hoverSeries === c || (d.hoverPoint && d.hoverPoint.series) === c) - c.onMouseOut(); - e && d.legend.colorizeItem(c, a); - c.isDirty = !0; - c.options.stacking && - r(d.series, function(a) { - a.options.stacking && a.visible && (a.isDirty = !0); - }); - r(c.linkedSeries, function(b) { - b.setVisible(a, !1); - }); - h && (d.isDirtyBox = !0); - !1 !== b && d.redraw(); - w(c, f); - }, - show: function() { - this.setVisible(!0); - }, - hide: function() { - this.setVisible(!1); - }, - select: function(a) { - this.selected = a = void 0 === a ? !this.selected : a; - this.checkbox && (this.checkbox.checked = a); - w(this, a ? 'select' : 'unselect'); - }, - drawTracker: I.drawTrackerGraph, - }); - })(M); - (function(a) { - var E = a.Chart, - D = a.each, - H = a.inArray, - p = a.isArray, - f = a.isObject, - l = a.pick, - r = a.splat; - E.prototype.setResponsive = function(f) { - var l = this.options.responsive, - n = [], - e = this.currentResponsive; - l && - l.rules && - D( - l.rules, - function(e) { - void 0 === e._id && (e._id = a.uniqueKey()); - this.matchResponsiveRule(e, n, f); - }, - this, - ); - var h = a.merge.apply( - 0, - a.map(n, function(e) { - return a.find(l.rules, function(a) { - return a._id === e; - }).chartOptions; - }), - ), - n = n.toString() || void 0; - n !== (e && e.ruleIds) && - (e && this.update(e.undoOptions, f), - n - ? ((this.currentResponsive = { - ruleIds: n, - mergedOptions: h, - undoOptions: this.currentOptions(h), - }), - this.update(h, f)) - : (this.currentResponsive = void 0)); - }; - E.prototype.matchResponsiveRule = function(a, f) { - var n = a.condition; - ( - n.callback || - function() { - return ( - this.chartWidth <= l(n.maxWidth, Number.MAX_VALUE) && - this.chartHeight <= l(n.maxHeight, Number.MAX_VALUE) && - this.chartWidth >= l(n.minWidth, 0) && - this.chartHeight >= l(n.minHeight, 0) - ); - } - ).call(this) && f.push(a._id); - }; - E.prototype.currentOptions = function(l) { - function n(e, h, l, d) { - var c; - a.objectEach(e, function(a, e) { - if (!d && -1 < H(e, ['series', 'xAxis', 'yAxis'])) - for (a = r(a), l[e] = [], c = 0; c < a.length; c++) - h[e][c] && ((l[e][c] = {}), n(a[c], h[e][c], l[e][c], d + 1)); - else - f(a) - ? ((l[e] = p(a) ? [] : {}), n(a, h[e] || {}, l[e], d + 1)) - : (l[e] = h[e] || null); - }); - } - var u = {}; - n(l, this.options, u, 0); - return u; - }; - })(M); - return M; -}); +(function(S,M){"object"===typeof module&&module.exports?module.exports=S.document?M(S):M:S.Highcharts=M(S)})("undefined"!==typeof window?window:this,function(S){var M=function(){var a="undefined"===typeof S?window:S,E=a.document,D=a.navigator&&a.navigator.userAgent||"",H=E&&E.createElementNS&&!!E.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,p=/(edge|msie|trident)/i.test(D)&&!a.opera,f=/Firefox/.test(D),l=f&&4>parseInt(D.split("Firefox/")[1],10);return a.Highcharts?a.Highcharts.error(16, +!0):{product:"Highcharts",version:"6.0.4",deg2rad:2*Math.PI/360,doc:E,hasBidiBug:l,hasTouch:E&&void 0!==E.documentElement.ontouchstart,isMS:p,isWebKit:/AppleWebKit/.test(D),isFirefox:f,isTouchDevice:/(Mobile|Android|Windows Phone)/.test(D),SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:H,win:a,marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){},charts:[]}}();(function(a){a.timers=[];var E=a.charts,D=a.doc,H=a.win;a.error=function(p, +f){p=a.isNumber(p)?"Highcharts error #"+p+": www.highcharts.com/errors/"+p:p;if(f)throw Error(p);H.console&&console.log(p)};a.Fx=function(a,f,l){this.options=f;this.elem=a;this.prop=l};a.Fx.prototype={dSetter:function(){var a=this.paths[0],f=this.paths[1],l=[],r=this.now,n=a.length,w;if(1===r)l=this.toD;else if(n===f.length&&1>r)for(;n--;)w=parseFloat(a[n]),l[n]=isNaN(w)?f[n]:r*parseFloat(f[n]-w)+w;else l=f;this.elem.attr("d",l,null,!0)},update:function(){var a=this.elem,f=this.prop,l=this.now,r= +this.options.step;if(this[f+"Setter"])this[f+"Setter"]();else a.attr?a.element&&a.attr(f,l,null,!0):a.style[f]=l+this.unit;r&&r.call(a,l,this)},run:function(p,f,l){var r=this,n=r.options,w=function(a){return w.stopped?!1:r.step(a)},u=H.requestAnimationFrame||function(a){setTimeout(a,13)},e=function(){for(var h=0;h=u+this.startTime?(this.now=this.end,this.pos=1,this.update(),l=e[this.prop]=!0,a.objectEach(e,function(a){!0!==a&&(l=!1)}),l&&w&&w.call(n),p=!1):(this.pos=r.easing((f-this.startTime)/u),this.now=this.start+(this.end- +this.start)*this.pos,this.update(),p=!0);return p},initPath:function(p,f,l){function r(a){var b,c;for(k=a.length;k--;)b="M"===a[k]||"L"===a[k],c=/[a-zA-Z]/.test(a[k+3]),b&&c&&a.splice(k+1,0,a[k+1],a[k+2],a[k+1],a[k+2])}function n(a,b){for(;a.lengtha&&-Infinityw?"AM":"PM",P:12>w?"am":"pm",S:k(n.getSeconds()),L:k(Math.round(f%1E3),3)},a.dateFormats);a.objectEach(r,function(a,b){for(;-1!==p.indexOf("%"+b);)p=p.replace("%"+b,"function"===typeof a?a(f):a)});return l?p.substr(0,1).toUpperCase()+p.substr(1):p};a.formatSingle=function(p,f){var l=/\.([0-9])/,r=a.defaultOptions.lang;/f$/.test(p)?(l=(l=p.match(l))?l[1]:-1,null!==f&&(f=a.numberFormat(f,l,r.decimalPoint,-1=l&&(f=[1/l])));for(r=0;r=p||!n&&w<=(f[r]+(f[r+1]||f[r]))/2);r++);return u=a.correctFloat(u*l,-Math.round(Math.log(.001)/Math.LN10))};a.stableSort=function(a,f){var l=a.length,p,n;for(n=0;nl&&(l=a[f]);return l};a.destroyObjectProperties=function(p,f){a.objectEach(p,function(a,r){a&&a!==f&&a.destroy&&a.destroy();delete p[r]})};a.discardElement=function(p){var f=a.garbageBin;f||(f=a.createElement("div"));p&&f.appendChild(p);f.innerHTML=""};a.correctFloat=function(a,f){return parseFloat(a.toPrecision(f||14))};a.setAnimation=function(p,f){f.renderer.globalAnimation=a.pick(p,f.options.chart.animation, +!0)};a.animObject=function(p){return a.isObject(p)?a.merge(p):{duration:p?500:0}};a.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5,month:24192E5,year:314496E5};a.numberFormat=function(p,f,l,r){p=+p||0;f=+f;var n=a.defaultOptions.lang,w=(p.toString().split(".")[1]||"").split("e")[0].length,u,e,h=p.toString().split("e");-1===f?f=Math.min(w,20):a.isNumber(f)?f&&h[1]&&0>h[1]&&(u=f+ +h[1],0<=u?(h[0]=(+h[0]).toExponential(u).split("e")[0],f=u):(h[0]=h[0].split(".")[0]||0, +p=20>f?(h[0]*Math.pow(10,h[1])).toFixed(f):0,h[1]=0)):f=2;e=(Math.abs(h[1]?h[0]:p)+Math.pow(10,-Math.max(f,w)-1)).toFixed(f);w=String(a.pInt(e));u=3p?"-":"")+(u?w.substr(0,u)+r:"");p+=w.substr(u).replace(/(\d{3})(?=\d)/g,"$1"+r);f&&(p+=l+e.slice(-f));h[1]&&0!==+p&&(p+="e"+h[1]);return p};Math.easeInOutSine=function(a){return-.5*(Math.cos(Math.PI*a)-1)};a.getStyle=function(p,f,l){if("width"===f)return Math.min(p.offsetWidth, +p.scrollWidth)-a.getStyle(p,"padding-left")-a.getStyle(p,"padding-right");if("height"===f)return Math.min(p.offsetHeight,p.scrollHeight)-a.getStyle(p,"padding-top")-a.getStyle(p,"padding-bottom");H.getComputedStyle||a.error(27,!0);if(p=H.getComputedStyle(p,void 0))p=p.getPropertyValue(f),a.pick(l,"opacity"!==f)&&(p=a.pInt(p));return p};a.inArray=function(p,f){return(a.indexOfPolyfill||Array.prototype.indexOf).call(f,p)};a.grep=function(p,f){return(a.filterPolyfill||Array.prototype.filter).call(p, +f)};a.find=Array.prototype.find?function(a,f){return a.find(f)}:function(a,f){var l,r=a.length;for(l=0;l>16,(l&65280)>> +8,l&255,1]:4===f&&(n=[(l&3840)>>4|(l&3840)>>8,(l&240)>>4|l&240,(l&15)<<4|l&15,1])),!n)for(w=this.parsers.length;w--&&!n;)u=this.parsers[w],(f=u.regex.exec(l))&&(n=u.parse(f));this.rgba=n||[]},get:function(a){var f=this.input,n=this.rgba,l;this.stops?(l=p(f),l.stops=[].concat(l.stops),E(this.stops,function(n,e){l.stops[e]=[l.stops[e][0],n.get(a)]})):l=n&&D(n[0])?"rgb"===a||!a&&1===n[3]?"rgb("+n[0]+","+n[1]+","+n[2]+")":"a"===a?n[3]:"rgba("+n.join(",")+")":f;return l},brighten:function(a){var l,n=this.rgba; +if(this.stops)E(this.stops,function(n){n.brighten(a)});else if(D(a)&&0!==a)for(l=0;3>l;l++)n[l]+=f(255*a),0>n[l]&&(n[l]=0),255y.width)y={width:0,height:0}}else y=this.htmlGetBBox();b.isSVG&& +(a=y.width,b=y.height,q&&"11px"===q.fontSize&&17===Math.round(b)&&(y.height=b=14),g&&(y.width=Math.abs(b*Math.sin(v))+Math.abs(a*Math.cos(v)),y.height=Math.abs(b*Math.cos(v))+Math.abs(a*Math.sin(v))));if(A&&0]*>/g,"")))},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,g,b){"string"===typeof a?b.setAttribute(g,a):a&&this.colorGradient(a,g,b)},visibilitySetter:function(a,g,b){"inherit"===a?b.removeAttribute(g):this[g]!==a&&b.setAttribute(g,a);this[g]=a},zIndexSetter:function(a,b){var v=this.renderer,y=this.parentGroup,c=(y||v).element||v.box,k,d=this.element,q,e,v=c===v.box;k=this.added;var z;u(a)&& +(d.zIndex=a,a=+a,this[b]===a&&(k=!1),this[b]=a);if(k){(a=this.zIndex)&&y&&(y.handleZ=!0);b=c.childNodes;for(z=b.length-1;0<=z&&!q;z--)if(y=b[z],k=y.zIndex,e=!u(k),y!==d)if(0>a&&e&&!v&&!z)c.insertBefore(d,b[z]),q=!0;else if(g(k)<=a||e&&(!u(a)||0<=a))c.insertBefore(d,b[z+1]||null),q=!0;q||(c.insertBefore(d,b[v?3:0]||null),q=!0)}return q},_defaultSetter:function(a,g,b){b.setAttribute(g,a)}});E.prototype.yGetter=E.prototype.xGetter;E.prototype.translateXSetter=E.prototype.translateYSetter=E.prototype.rotationSetter= +E.prototype.verticalAlignSetter=E.prototype.rotationOriginXSetter=E.prototype.rotationOriginYSetter=E.prototype.scaleXSetter=E.prototype.scaleYSetter=E.prototype.matrixSetter=function(a,g){this[g]=a;this.doTransform=!0};E.prototype["stroke-widthSetter"]=E.prototype.strokeSetter=function(a,g,b){this[g]=a;this.stroke&&this["stroke-width"]?(E.prototype.fillSetter.call(this,this.stroke,"stroke",b),b.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0):"stroke-width"===g&&0===a&&this.hasStroke&& +(b.removeAttribute("stroke"),this.hasStroke=!1)};D=a.SVGRenderer=function(){this.init.apply(this,arguments)};c(D.prototype,{Element:E,SVG_NS:P,init:function(a,g,b,v,c,k){var y;v=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"}).css(this.getStyle(v));y=v.element;a.appendChild(y);f(a,"dir","ltr");-1===a.innerHTML.indexOf("xmlns")&&f(y,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=y;this.boxWrapper=v;this.alignedObjects=[];this.url=(x||N)&&m.getElementsByTagName("base").length? +R.location.href.replace(/#.*?$/,"").replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(m.createTextNode("Created with Highcharts 6.0.4"));this.defs=this.createElement("defs").add();this.allowHTML=k;this.forExport=c;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(g,b,!1);var d;x&&a.getBoundingClientRect&&(g=function(){n(a,{left:0,top:0});d=a.getBoundingClientRect();n(a,{left:Math.ceil(d.left)- +d.left+"px",top:Math.ceil(d.top)-d.top+"px"})},g(),this.unSubPixelFix=H(R,"resize",g))},getStyle:function(a){return this.style=c({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},setStyle:function(a){this.boxWrapper.css(this.getStyle(a))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();h(this.gradients||{});this.gradients=null;a&&(this.defs=a.destroy()); +this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(a){var g=new this.Element;g.init(this,a);return g},draw:A,getRadialAttr:function(a,g){return{cx:a[0]-a[2]/2+g.cx*a[2],cy:a[1]-a[2]/2+g.cy*a[2],r:g.r*a[2]}},getSpanWidth:function(a,g){var b=a.getBBox(!0).width;!L&&this.forExport&&(b=this.measureSpanWidth(g.firstChild.data,a.styles));return b},applyEllipsis:function(a,g,b,v){var c=a.rotation,y=b,k,d=0,q=b.length,e=function(a){g.removeChild(g.firstChild); +a&&g.appendChild(m.createTextNode(a))},z;a.rotation=0;y=this.getSpanWidth(a,g);if(z=y>v){for(;d<=q;)k=Math.ceil((d+q)/2),y=b.substring(0,k)+"\u2026",e(y),y=this.getSpanWidth(a,g),d===q?d=q+1:y>v?q=k-1:d=k;0===q&&e("")}a.rotation=c;return z},escapes:{"\x26":"\x26amp;","\x3c":"\x26lt;","\x3e":"\x26gt;","'":"\x26#39;",'"':"\x26quot;"},buildText:function(a){var b=a.element,v=this,c=v.forExport,y=G(a.textStr,"").toString(),q=-1!==y.indexOf("\x3c"),e=b.childNodes,z,h,A,J,t=f(b,"x"),x=a.styles,B=a.textWidth, +l=x&&x.lineHeight,C=x&&x.textOutline,u=x&&"ellipsis"===x.textOverflow,Q=x&&"nowrap"===x.whiteSpace,w=x&&x.fontSize,R,I,r=e.length,x=B&&!a.added&&this.box,p=function(a){var c;c=/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:w||v.style.fontSize||12;return l?g(l):v.fontMetrics(c,a.getAttribute("style")?a:b).h},K=function(a){F(v.escapes,function(g,b){a=a.replace(new RegExp(g,"g"),b)});return a};R=[y,u,Q,l,C,w,B].join();if(R!==a.textCache){for(a.textCache=R;r--;)b.removeChild(e[r]);q||C||u||B|| +-1!==y.indexOf(" ")?(z=/<.*class="([^"]+)".*>/,h=/<.*style="([^"]+)".*>/,A=/<.*href="([^"]+)".*>/,x&&x.appendChild(b),y=q?y.replace(/<(b|strong)>/g,'\x3cspan style\x3d"font-weight:bold"\x3e').replace(/<(i|em)>/g,'\x3cspan style\x3d"font-style:italic"\x3e').replace(//g,"\x3c/span\x3e").split(//g):[y],y=k(y,function(a){return""!==a}),d(y,function(g,y){var k,q=0;g=g.replace(/^\s+|\s+$/g,"").replace(//g,"\x3c/span\x3e|||"); +k=g.split("|||");d(k,function(g){if(""!==g||1===k.length){var d={},e=m.createElementNS(v.SVG_NS,"tspan"),x,F;z.test(g)&&(x=g.match(z)[1],f(e,"class",x));h.test(g)&&(F=g.match(h)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),f(e,"style",F));A.test(g)&&!c&&(f(e,"onclick",'location.href\x3d"'+g.match(A)[1]+'"'),f(e,"class","highcharts-anchor"),n(e,{cursor:"pointer"}));g=K(g.replace(/<[a-zA-Z\/](.|\n)*?>/g,"")||" ");if(" "!==g){e.appendChild(m.createTextNode(g));q?d.dx=0:y&&null!==t&&(d.x=t);f(e,d);b.appendChild(e); +!q&&I&&(!L&&c&&n(e,{display:"block"}),f(e,"dy",p(e)));if(B){d=g.replace(/([^\^])-/g,"$1- ").split(" ");x=1B,void 0===J&&(J=g),g&&1!==d.length?(e.removeChild(e.firstChild),O.unshift(d.pop())):(d=O,O=[],d.length&&!Q&&(e=m.createElementNS(P,"tspan"),f(e,{dy:C,x:t}),F&&f(e,"style",F),b.appendChild(e)),l>B&&(B=l)),d.length&&e.appendChild(m.createTextNode(d.join(" ").replace(/- /g, +"-")));a.rotation=G}q++}}});I=I||b.childNodes.length}),J&&a.attr("title",a.textStr),x&&x.removeChild(b),C&&a.applyTextOutline&&a.applyTextOutline(C)):b.appendChild(m.createTextNode(K(y)))}},getContrast:function(a){a=r(a).rgba;return 510Math.abs(c.end-c.start-2*Math.PI));var y=Math.cos(k),z=Math.sin(k),h=Math.cos(e),e=Math.sin(e);c=.001>c.end-k-Math.PI?0:1;d=["M",a+d*y,g+q*z,"A",d,q,0,c,1,a+d*h,g+q*e];u(b)&&d.push(v?"M":"L",a+b* +h,g+b*e,"A",b,b,0,c,0,a+b*y,g+b*z);d.push(v?"":"Z");return d},callout:function(a,g,b,v,c){var d=Math.min(c&&c.r||0,b,v),k=d+6,q=c&&c.anchorX;c=c&&c.anchorY;var e;e=["M",a+d,g,"L",a+b-d,g,"C",a+b,g,a+b,g,a+b,g+d,"L",a+b,g+v-d,"C",a+b,g+v,a+b,g+v,a+b-d,g+v,"L",a+d,g+v,"C",a,g+v,a,g+v,a,g+v-d,"L",a,g+d,"C",a,g,a,g,a+d,g];q&&q>b?c>g+k&&cq?c>g+k&&cv&&q>a+k&&qc&&q>a+k&&qa?a+3:Math.round(1.2*a);return{h:b,b:Math.round(.8* +b),f:a}},rotCorr:function(a,g,b){var v=a;g&&b&&(v=Math.max(v*Math.cos(g*e),4));return{x:-a/3*Math.sin(g*e),y:v}},label:function(g,b,k,e,z,h,m,A,L){var y=this,J=y.g("button"!==L&&"label"),t=J.text=y.text("",0,0,m).attr({zIndex:1}),x,F,n=0,B=3,l=0,C,f,Q,G,w,R={},I,P,r=/^url\((.*?)\)$/.test(e),p=r,K,O,N,T;L&&J.addClass("highcharts-"+L);p=r;K=function(){return(I||0)%2/2};O=function(){var a=t.element.style,g={};F=(void 0===C||void 0===f||w)&&u(t.textStr)&&t.getBBox();J.width=(C||F.width||0)+2*B+l;J.height= +(f||F.height||0)+2*B;P=B+y.fontMetrics(a&&a.fontSize,t).b;p&&(x||(J.box=x=y.symbols[e]||r?y.symbol(e):y.rect(),x.addClass(("button"===L?"":"highcharts-label-box")+(L?" highcharts-"+L+"-box":"")),x.add(J),a=K(),g.x=a,g.y=(A?-P:0)+a),g.width=Math.round(J.width),g.height=Math.round(J.height),x.attr(c(g,R)),R={})};N=function(){var a=l+B,g;g=A?0:P;u(C)&&F&&("center"===w||"right"===w)&&(a+={center:.5,right:1}[w]*(C-F.width));if(a!==t.x||g!==t.y)t.attr("x",a),void 0!==g&&t.attr("y",g);t.x=a;t.y=g};T=function(a, +g){x?x.attr(a,g):R[a]=g};J.onAdd=function(){t.add(J);J.attr({text:g||0===g?g:"",x:b,y:k});x&&u(z)&&J.attr({anchorX:z,anchorY:h})};J.widthSetter=function(g){C=a.isNumber(g)?g:null};J.heightSetter=function(a){f=a};J["text-alignSetter"]=function(a){w=a};J.paddingSetter=function(a){u(a)&&a!==B&&(B=J.padding=a,N())};J.paddingLeftSetter=function(a){u(a)&&a!==l&&(l=a,N())};J.alignSetter=function(a){a={left:0,center:.5,right:1}[a];a!==n&&(n=a,F&&J.attr({x:Q}))};J.textSetter=function(a){void 0!==a&&t.textSetter(a); +O();N()};J["stroke-widthSetter"]=function(a,g){a&&(p=!0);I=this["stroke-width"]=a;T(g,a)};J.strokeSetter=J.fillSetter=J.rSetter=function(a,g){"r"!==g&&("fill"===g&&a&&(p=!0),J[g]=a);T(g,a)};J.anchorXSetter=function(a,g){z=J.anchorX=a;T(g,Math.round(a)-K()-Q)};J.anchorYSetter=function(a,g){h=J.anchorY=a;T(g,a-G)};J.xSetter=function(a){J.x=a;n&&(a-=n*((C||F.width)+2*B));Q=Math.round(a);J.attr("translateX",Q)};J.ySetter=function(a){G=J.y=Math.round(a);J.attr("translateY",G)};var U=J.css;return c(J,{css:function(a){if(a){var g= +{};a=q(a);d(J.textProps,function(b){void 0!==a[b]&&(g[b]=a[b],delete a[b])});t.css(g)}return U.call(J,a)},getBBox:function(){return{width:F.width+2*B,height:F.height+2*B,x:F.x-B,y:F.y-B}},shadow:function(a){a&&(O(),x&&x.shadow(a));return J},destroy:function(){v(J.element,"mouseenter");v(J.element,"mouseleave");t&&(t=t.destroy());x&&(x=x.destroy());E.prototype.destroy.call(J);J=y=O=N=T=null}})}});a.Renderer=D})(M);(function(a){var E=a.attr,D=a.createElement,H=a.css,p=a.defined,f=a.each,l=a.extend, +r=a.isFirefox,n=a.isMS,w=a.isWebKit,u=a.pick,e=a.pInt,h=a.SVGRenderer,m=a.win,d=a.wrap;l(a.SVGElement.prototype,{htmlCss:function(a){var b=this.element;if(b=a&&"SPAN"===b.tagName&&a.width)delete a.width,this.textWidth=b,this.updateTransform();a&&"ellipsis"===a.textOverflow&&(a.whiteSpace="nowrap",a.overflow="hidden");this.styles=l(this.styles,a);H(this.element,a);return this},htmlGetBBox:function(){var a=this.element;return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}, +htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,d=this.translateX||0,z=this.translateY||0,h=this.x||0,m=this.y||0,x=this.textAlign||"left",n={left:0,center:.5,right:1}[x],t=this.styles;H(b,{marginLeft:d,marginTop:z});this.shadows&&f(this.shadows,function(a){H(a,{marginLeft:d+1,marginTop:z+1})});this.inverted&&f(b.childNodes,function(c){a.invertChild(c,b)});if("SPAN"===b.tagName){var l=this.rotation,u=e(this.textWidth),q=t&&t.whiteSpace,A=[l,x,b.innerHTML,this.textWidth, +this.textAlign].join();A!==this.cTT&&(t=a.fontMetrics(b.style.fontSize).b,p(l)&&this.setSpanRotation(l,n,t),H(b,{width:"",whiteSpace:q||"nowrap"}),b.offsetWidth>u&&/[ \-]/.test(b.textContent||b.innerText)&&H(b,{width:u+"px",display:"block",whiteSpace:q||"normal"}),this.getSpanCorrection(b.offsetWidth,t,n,l,x));H(b,{left:h+(this.xCorr||0)+"px",top:m+(this.yCorr||0)+"px"});w&&(t=b.offsetHeight);this.cTT=A}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,d){var c={},k=this.renderer.getTransformKey(); +c[k]=c.transform="rotate("+a+"deg)";c[k+(r?"Origin":"-origin")]=c.transformOrigin=100*b+"% "+d+"px";H(this.element,c)},getSpanCorrection:function(a,b,d){this.xCorr=-a*d;this.yCorr=-b}});l(h.prototype,{getTransformKey:function(){return n&&!/Edge/.test(m.navigator.userAgent)?"-ms-transform":w?"-webkit-transform":r?"MozTransform":m.opera?"-o-transform":""},html:function(a,b,k){var c=this.createElement("span"),e=c.element,h=c.renderer,m=h.isSVG,w=function(a,b){f(["opacity","visibility"],function(c){d(a, +c+"Setter",function(a,c,d,k){a.call(this,c,d,k);b[d]=c})})};c.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;this.textStr=a;e.innerHTML=u(a,"");c.htmlUpdateTransform()};m&&w(c,c.element.style);c.xSetter=c.ySetter=c.alignSetter=c.rotationSetter=function(a,b){"align"===b&&(b="textAlign");c[b]=a;c.htmlUpdateTransform()};c.attr({text:a,x:Math.round(b),y:Math.round(k)}).css({fontFamily:this.style.fontFamily,fontSize:this.style.fontSize,position:"absolute"});e.style.whiteSpace="nowrap";c.css= +c.htmlCss;m&&(c.add=function(a){var b,d=h.box.parentNode,k=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)k.push(a),a=a.parentGroup;f(k.reverse(),function(a){function e(g,b){a[b]=g;n?q[h.getTransformKey()]="translate("+(a.x||a.translateX)+"px,"+(a.y||a.translateY)+"px)":"translateX"===b?q.left=g+"px":q.top=g+"px";a.doTransform=!0}var q,g=E(a.element,"class");g&&(g={className:g});b=a.div=a.div||D("div",g,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px",display:a.display, +opacity:a.opacity,pointerEvents:a.styles&&a.styles.pointerEvents},b||d);q=b.style;l(a,{classSetter:function(a){return function(g){this.element.setAttribute("class",g);a.className=g}}(b),on:function(){k[0].div&&c.on.apply({element:k[0].div},arguments);return a},translateXSetter:e,translateYSetter:e});w(a,q)})}}else b=d;b.appendChild(e);c.added=!0;c.alignOnAdd&&c.htmlUpdateTransform();return c});return c}})})(M);(function(a){function E(){var n=a.defaultOptions.global,l=r.moment;if(n.timezone){if(l)return function(a){return-l.tz(a, +n.timezone).utcOffset()};a.error(25)}return n.useUTC&&n.getTimezoneOffset}function D(){var n=a.defaultOptions.global,f,u=n.useUTC,e=u?"getUTC":"get",h=u?"setUTC":"set",m="Minutes Hours Day Date Month FullYear".split(" "),d=m.concat(["Milliseconds","Seconds"]);a.Date=f=n.Date||r.Date;f.hcTimezoneOffset=u&&n.timezoneOffset;f.hcGetTimezoneOffset=E();f.hcHasTimeZone=!(!f.hcTimezoneOffset&&!f.hcGetTimezoneOffset);f.hcMakeTime=function(a,b,d,e,h,m){var c;u?(c=f.UTC.apply(0,arguments),c+=p(c)):c=(new f(a, +b,l(d,1),l(e,0),l(h,0),l(m,0))).getTime();return c};for(n=0;nb&&e-k*zm&&(p=Math.round((h-e)/Math.cos(b*r)));else if(h=e+(1-k)*z,e-k*zm&&(I=m-a.x+I*k,x=-1),I=Math.min(B,I),II||f.autoRotation&&(c.styles||{}).width)p=I;p&&(t.width=p,(n.style||{}).textOverflow||(t.textOverflow="ellipsis"),c.css(t))},getPosition:function(a,f,l,e){var h=this.axis,m=h.chart,d=e&&m.oldChartHeight||m.chartHeight;return{x:a?h.translate(f+l,null,null,e)+h.transB:h.left+h.offset+(h.opposite?(e&&m.oldChartWidth||m.chartWidth)-h.right-h.left:0),y:a?d-h.bottom+h.offset-(h.opposite?h.height:0):d-h.translate(f+l,null,null,e)-h.transB}},getLabelPosition:function(a, +f,l,e,h,m,d,c){var b=this.axis,k=b.transA,z=b.reversed,B=b.staggerLines,n=b.tickRotCorr||{x:0,y:0},x=h.y,u=e||b.reserveSpaceDefault?0:-b.labelOffset*("center"===b.labelAlign?.5:1);D(x)||(x=0===b.side?l.rotation?-8:-l.getBBox().height:2===b.side?n.y+8:Math.cos(l.rotation*r)*(n.y-l.getBBox(!1,0).height/2));a=a+h.x+u+n.x-(m&&e?m*k*(z?-1:1):0);f=f+x-(m&&!e?m*k*(z?1:-1):0);B&&(l=d/(c||1)%B,b.opposite&&(l=B-l-1),f+=b.labelOffset/B*l);return{x:a,y:Math.round(f)}},getMarkPath:function(a,f,l,e,h,m){return m.crispLine(["M", +a,f,"L",a+(h?0:-l),f+(h?l:0)],e)},renderGridLine:function(a,f,l){var e=this.axis,h=e.options,m=this.gridLine,d={},c=this.pos,b=this.type,k=e.tickmarkOffset,z=e.chart.renderer,B=b?b+"Grid":"grid",n=h[B+"LineWidth"],x=h[B+"LineColor"],h=h[B+"LineDashStyle"];m||(d.stroke=x,d["stroke-width"]=n,h&&(d.dashstyle=h),b||(d.zIndex=1),a&&(d.opacity=0),this.gridLine=m=z.path().attr(d).addClass("highcharts-"+(b?b+"-":"")+"grid-line").add(e.gridGroup));if(!a&&m&&(a=e.getPlotLinePath(c+k,m.strokeWidth()*l,a,!0)))m[this.isNew? +"attr":"animate"]({d:a,opacity:f})},renderMark:function(a,f,u){var e=this.axis,h=e.options,m=e.chart.renderer,d=this.type,c=d?d+"Tick":"tick",b=e.tickSize(c),k=this.mark,z=!k,B=a.x;a=a.y;var n=l(h[c+"Width"],!d&&e.isXAxis?1:0),h=h[c+"Color"];b&&(e.opposite&&(b[0]=-b[0]),z&&(this.mark=k=m.path().addClass("highcharts-"+(d?d+"-":"")+"tick").add(e.axisGroup),k.attr({stroke:h,"stroke-width":n})),k[z?"attr":"animate"]({d:this.getMarkPath(B,a,b[0],k.strokeWidth()*u,e.horiz,m),opacity:f}))},renderLabel:function(a, +f,u,e){var h=this.axis,m=h.horiz,d=h.options,c=this.label,b=d.labels,k=b.step,h=h.tickmarkOffset,z=!0,B=a.x;a=a.y;c&&p(B)&&(c.xy=a=this.getLabelPosition(B,a,c,m,b,h,e,k),this.isFirst&&!this.isLast&&!l(d.showFirstLabel,1)||this.isLast&&!this.isFirst&&!l(d.showLastLabel,1)?z=!1:!m||b.step||b.rotation||f||0===u||this.handleOverflow(a),k&&e%k&&(z=!1),z&&p(a.y)?(a.opacity=u,c[this.isNewLabel?"attr":"animate"](a),this.isNewLabel=!1):(c.attr("y",-9999),this.isNewLabel=!0))},render:function(a,f,u){var e= +this.axis,h=e.horiz,m=this.getPosition(h,this.pos,e.tickmarkOffset,f),d=m.x,c=m.y,e=h&&d===e.pos+e.len||!h&&c===e.pos?-1:1;u=l(u,1);this.isActive=!0;this.renderGridLine(f,u,e);this.renderMark(m,u,e);this.renderLabel(m,f,u,a);this.isNew=!1},destroy:function(){H(this,this.axis)}}})(M);var V=function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.color,l=a.correctFloat,r=a.defaultOptions,n=a.defined,w=a.deg2rad,u=a.destroyObjectProperties,e=a.each,h=a.extend,m=a.fireEvent,d=a.format, +c=a.getMagnitude,b=a.grep,k=a.inArray,z=a.isArray,B=a.isNumber,I=a.isString,x=a.merge,K=a.normalizeTickInterval,t=a.objectEach,C=a.pick,N=a.removeEvent,q=a.splat,A=a.syncTimeout,F=a.Tick,G=function(){this.init.apply(this,arguments)};a.extend(G.prototype,{defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,labels:{enabled:!0,style:{color:"#666666",cursor:"default",fontSize:"11px"}, +x:0},maxPadding:.01,minorTickLength:2,minorTickPosition:"outside",minPadding:.01,startOfWeek:1,startOnTick:!1,tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",title:{align:"middle",style:{color:"#666666"}},type:"linear",minorGridLineColor:"#f2f2f2",minorGridLineWidth:1,minorTickColor:"#999999",lineColor:"#ccd6eb",lineWidth:1,gridLineColor:"#e6e6e6",tickColor:"#ccd6eb"},defaultYAxisOptions:{endOnTick:!0,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8},maxPadding:.05, +minPadding:.05,startOnTick:!0,title:{rotation:270,text:"Values"},stackLabels:{allowOverlap:!1,enabled:!1,formatter:function(){return a.numberFormat(this.total,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"#000000",textOutline:"1px contrast"}},gridLineWidth:1,lineWidth:0},defaultLeftAxisOptions:{labels:{x:-15},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45], +x:0},title:{rotation:0}},init:function(a,b){var g=b.isX,v=this;v.chart=a;v.horiz=a.inverted&&!v.isZAxis?!g:g;v.isXAxis=g;v.coll=v.coll||(g?"xAxis":"yAxis");v.opposite=b.opposite;v.side=b.side||(v.horiz?v.opposite?0:2:v.opposite?1:3);v.setOptions(b);var c=this.options,d=c.type;v.labelFormatter=c.labels.formatter||v.defaultLabelFormatter;v.userOptions=b;v.minPixelPadding=0;v.reversed=c.reversed;v.visible=!1!==c.visible;v.zoomEnabled=!1!==c.zoomEnabled;v.hasNames="category"===d||!0===c.categories;v.categories= +c.categories||v.hasNames;v.names=v.names||[];v.plotLinesAndBandsGroups={};v.isLog="logarithmic"===d;v.isDatetimeAxis="datetime"===d;v.positiveValuesOnly=v.isLog&&!v.allowNegativeLog;v.isLinked=n(c.linkedTo);v.ticks={};v.labelEdge=[];v.minorTicks={};v.plotLinesAndBands=[];v.alternateBands={};v.len=0;v.minRange=v.userMinRange=c.minRange||c.maxZoom;v.range=c.range;v.offset=c.offset||0;v.stacks={};v.oldStacks={};v.stacksTouched=0;v.max=null;v.min=null;v.crosshair=C(c.crosshair,q(a.options.tooltip.crosshairs)[g? +0:1],!1);b=v.options.events;-1===k(v,a.axes)&&(g?a.axes.splice(a.xAxis.length,0,v):a.axes.push(v),a[v.coll].push(v));v.series=v.series||[];a.inverted&&!v.isZAxis&&g&&void 0===v.reversed&&(v.reversed=!0);t(b,function(a,g){E(v,g,a)});v.lin2log=c.linearToLogConverter||v.lin2log;v.isLog&&(v.val2lin=v.log2lin,v.lin2val=v.lin2log)},setOptions:function(a){this.options=x(this.defaultOptions,"yAxis"===this.coll&&this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions, +this.defaultLeftAxisOptions][this.side],x(r[this.coll],a))},defaultLabelFormatter:function(){var g=this.axis,b=this.value,c=g.categories,k=this.dateTimeLabelFormat,e=r.lang,q=e.numericSymbols,e=e.numericSymbolMagnitude||1E3,h=q&&q.length,m,z=g.options.labels.format,g=g.isLog?Math.abs(b):g.tickInterval;if(z)m=d(z,this);else if(c)m=b;else if(k)m=a.dateFormat(k,b);else if(h&&1E3<=g)for(;h--&&void 0===m;)c=Math.pow(e,h+1),g>=c&&0===10*b%c&&null!==q[h]&&0!==b&&(m=a.numberFormat(b/c,-1)+q[h]);void 0=== +m&&(m=1E4<=Math.abs(b)?a.numberFormat(b,-1):a.numberFormat(b,-1,void 0,""));return m},getSeriesExtremes:function(){var a=this,v=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.threshold=null;a.softThreshold=!a.isXAxis;a.buildStacks&&a.buildStacks();e(a.series,function(g){if(g.visible||!v.options.chart.ignoreHiddenSeries){var c=g.options,d=c.threshold,k;a.hasVisibleSeries=!0;a.positiveValuesOnly&&0>=d&&(d=null);if(a.isXAxis)c=g.xData,c.length&&(g=p(c),k=H(c),B(g)||g instanceof Date||(c=b(c,B), +g=p(c)),a.dataMin=Math.min(C(a.dataMin,c[0],g),g),a.dataMax=Math.max(C(a.dataMax,c[0],k),k));else if(g.getExtremes(),k=g.dataMax,g=g.dataMin,n(g)&&n(k)&&(a.dataMin=Math.min(C(a.dataMin,g),g),a.dataMax=Math.max(C(a.dataMax,k),k)),n(d)&&(a.threshold=d),!c.softThreshold||a.positiveValuesOnly)a.softThreshold=!1}})},translate:function(a,b,c,d,k,e){var g=this.linkedParent||this,v=1,q=0,h=d?g.oldTransA:g.transA;d=d?g.oldMin:g.min;var m=g.minPixelPadding;k=(g.isOrdinal||g.isBroken||g.isLog&&k)&&g.lin2val; +h||(h=g.transA);c&&(v*=-1,q=g.len);g.reversed&&(v*=-1,q-=v*(g.sector||g.len));b?(a=(a*v+q-m)/h+d,k&&(a=g.lin2val(a))):(k&&(a=g.val2lin(a)),a=B(d)?v*(a-d)*h+q+v*m+(B(e)?h*e:0):void 0);return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d,k){var g=this.chart,v=this.left,q=this.top,e,h,m=c&&g.oldChartHeight||g.chartHeight,z=c&&g.oldChartWidth|| +g.chartWidth,A;e=this.transB;var t=function(a,g,b){if(ab)d?a=Math.min(Math.max(g,a),b):A=!0;return a};k=C(k,this.translate(a,null,null,c));a=c=Math.round(k+e);e=h=Math.round(m-k-e);B(k)?this.horiz?(e=q,h=m-this.bottom,a=c=t(a,v,v+this.width)):(a=v,c=z-this.right,e=h=t(e,q,q+this.height)):(A=!0,d=!1);return A&&!d?null:g.renderer.crispLine(["M",a,e,"L",c,h],b||1)},getLinearTickPositions:function(a,b,c){var g,v=l(Math.floor(b/a)*a);c=l(Math.ceil(c/a)*a);var d=[],k;l(v+a)===v&&(k=20);if(this.single)return[b]; +for(b=v;b<=c;){d.push(b);b=l(b+a,k);if(b===g)break;g=b}return d},getMinorTickInterval:function(){var a=this.options;return!0===a.minorTicks?C(a.minorTickInterval,"auto"):!1===a.minorTicks?null:a.minorTickInterval},getMinorTickPositions:function(){var a=this,b=a.options,c=a.tickPositions,d=a.minorTickInterval,k=[],q=a.pointRangePadding||0,h=a.min-q,q=a.max+q,m=q-h;if(m&&m/d=this.minRange,t=this.minRange,d=(t-c+b)/2,d=[b-d,C(a.min,b-d)],k&&(d[2]=this.isLog?this.log2lin(this.dataMin):this.dataMin),b=H(d),c=[b+t,C(a.max,b+t)],k&&(c[2]=this.isLog?this.log2lin(this.dataMax):this.dataMax),c=p(c),c-b=p?(r=p,f=0):b.dataMax<=p&&(w=p,x=0)),b.min= +C(N,r,b.dataMin),b.max=C(D,w,b.dataMax));q&&(b.positiveValuesOnly&&!g&&0>=Math.min(b.min,C(b.dataMin,b.min))&&a.error(10,1),b.min=l(h(b.min),15),b.max=l(h(b.max),15));b.range&&n(b.max)&&(b.userMin=b.min=N=Math.max(b.dataMin,b.minFromRange()),b.userMax=D=b.max,b.range=null);m(b,"foundExtremes");b.beforePadding&&b.beforePadding();b.adjustForMinRange();!(G||b.axisPointRange||b.usePercentage||t)&&n(b.min)&&n(b.max)&&(h=b.max-b.min)&&(!n(N)&&f&&(b.min-=h*f),!n(D)&&x&&(b.max+=h*x));B(k.softMin)&&!B(b.userMin)&& +(b.min=Math.min(b.min,k.softMin));B(k.softMax)&&!B(b.userMax)&&(b.max=Math.max(b.max,k.softMax));B(k.floor)&&(b.min=Math.max(b.min,k.floor));B(k.ceiling)&&(b.max=Math.min(b.max,k.ceiling));I&&n(b.dataMin)&&(p=p||0,!n(N)&&b.min=p?b.min=p:!n(D)&&b.max>p&&b.dataMax<=p&&(b.max=p));b.tickInterval=b.min===b.max||void 0===b.min||void 0===b.max?1:t&&!F&&u===b.linkedParent.options.tickPixelInterval?F=b.linkedParent.tickInterval:C(F,this.tickAmount?(b.max-b.min)/Math.max(this.tickAmount-1,1): +void 0,G?1:(b.max-b.min)*u/Math.max(b.len,u));A&&!g&&e(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();b.postProcessTickInterval&&(b.tickInterval=b.postProcessTickInterval(b.tickInterval));b.pointRange&&!F&&(b.tickInterval=Math.max(b.pointRange,b.tickInterval));g=C(k.minTickInterval,b.isDatetimeAxis&&b.closestPointRange);!F&&b.tickIntervalb.tickInterval&&1E3b.max)),!!this.tickAmount));this.tickAmount||(b.tickInterval=b.unsquish());this.setTickPositions()},setTickPositions:function(){var a=this.options,b,c=a.tickPositions;b=this.getMinorTickInterval();var d=a.tickPositioner,k=a.startOnTick,q=a.endOnTick;this.tickmarkOffset=this.categories&&"between"===a.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===b&&this.tickInterval?this.tickInterval/ +5:b;this.single=this.min===this.max&&n(this.min)&&!this.tickAmount&&(parseInt(this.min,10)===this.min||!1!==a.allowDecimals);this.tickPositions=b=c&&c.slice();!b&&(b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),b.length>this.len&&(b= +[b[0],b.pop()],b[0]===b[1]&&(b.length=1)),this.tickPositions=b,d&&(d=d.apply(this,[this.min,this.max])))&&(this.tickPositions=b=d);this.paddedTicks=b.slice(0);this.trimTicks(b,k,q);this.isLinked||(this.single&&2>b.length&&(this.min-=.5,this.max+=.5),c||d||this.adjustTickAmount())},trimTicks:function(a,b,c){var g=a[0],d=a[a.length-1],k=this.minPointOffset||0;if(!this.isLinked){if(b&&-Infinity!==g)this.min=g;else for(;this.min-k>a[0];)a.shift();if(c)this.max=d;else for(;this.max+kb&&(this.finalTickAmt=b,b=5);this.tickAmount=b},adjustTickAmount:function(){var a=this.tickInterval,b=this.tickPositions,c=this.tickAmount,d=this.finalTickAmt,k=b&&b.length,q=C(this.threshold,this.softThreshold?0:null);if(this.hasData()){if(kc&&(this.tickInterval*= +2,this.setTickPositions());if(n(d)){for(a=c=b.length;a--;)(3===d&&1===a%2||2>=d&&0d&&(a=d)),n(c)&&(bd&&(b=d))),this.displayBtn=void 0!==a||void 0!==b,this.setExtremes(a,b,!1,void 0,{trigger:"zoom"});return!0},setAxisSize:function(){var b=this.chart,c=this.options,d=c.offsets||[0,0,0,0],k=this.horiz,q=this.width=Math.round(a.relativeLength(C(c.width,b.plotWidth-d[3]+d[1]),b.plotWidth)),e=this.height=Math.round(a.relativeLength(C(c.height, +b.plotHeight-d[0]+d[2]),b.plotHeight)),h=this.top=Math.round(a.relativeLength(C(c.top,b.plotTop+d[0]),b.plotHeight,b.plotTop)),c=this.left=Math.round(a.relativeLength(C(c.left,b.plotLeft+d[3]),b.plotWidth,b.plotLeft));this.bottom=b.chartHeight-e-h;this.right=b.chartWidth-q-c;this.len=Math.max(k?q:e,0);this.pos=k?c:h},getExtremes:function(){var a=this.isLog,b=this.lin2log;return{min:a?l(b(this.min)):this.min,max:a?l(b(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin, +userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,g=this.lin2log,c=b?g(this.min):this.min,b=b?g(this.max):this.max;null===a?a=c:c>a?a=c:ba?"right":195a?"left":"center"},tickSize:function(a){var b=this.options,g=b[a+"Length"],c=C(b[a+"Width"],"tick"===a&&this.isXAxis?1:0);if(c&&g)return"inside"===b[a+"Position"]&&(g=-g),[g,c]},labelMetrics:function(){var a= +this.tickPositions&&this.tickPositions[0]||0;return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize,this.ticks[a]&&this.ticks[a].label)},unsquish:function(){var a=this.options.labels,b=this.horiz,c=this.tickInterval,d=c,k=this.len/(((this.categories?1:0)+this.max-this.min)/c),q,h=a.rotation,m=this.labelMetrics(),z,A=Number.MAX_VALUE,t,x=function(a){a/=k||1;a=1=a)z=x(Math.abs(m.h/Math.sin(w*a))),b=z+Math.abs(a/360),b(c.step||0)&&!c.rotation&&(this.staggerLines||1)*this.len/d||!b&&(c.style&&parseInt(c.style.width,10)||k&&k-a.spacing[3]|| +.33*a.chartWidth)},renderUnsquish:function(){var a=this.chart,b=a.renderer,c=this.tickPositions,d=this.ticks,k=this.options.labels,q=this.horiz,h=this.getSlotWidth(),m=Math.max(1,Math.round(h-2*(k.padding||5))),z={},A=this.labelMetrics(),t=k.style&&k.style.textOverflow,f,F=0,l,B;I(k.rotation)||(z.rotation=k.rotation||0);e(c,function(a){(a=d[a])&&a.labelLength>F&&(F=a.labelLength)});this.maxLabelLength=F;if(this.autoRotation)F>m&&F>A.h?z.rotation=this.labelRotation:this.labelRotation=0;else if(h&& +(f={width:m+"px"},!t))for(f.textOverflow="clip",l=c.length;!q&&l--;)if(B=c[l],m=d[B].label)m.styles&&"ellipsis"===m.styles.textOverflow?m.css({textOverflow:"clip"}):d[B].labelLength>h&&m.css({width:h+"px"}),m.getBBox().height>this.len/c.length-(A.h-A.f)&&(m.specCss={textOverflow:"ellipsis"});z.rotation&&(f={width:(F>.5*a.chartHeight?.33*a.chartHeight:a.chartHeight)+"px"},t||(f.textOverflow="ellipsis"));if(this.labelAlign=k.align||this.autoLabelAlign(this.labelRotation))z.align=this.labelAlign;e(c, +function(a){var b=(a=d[a])&&a.label;b&&(b.attr(z),f&&b.css(x(f,b.specCss)),delete b.specCss,a.rotation=z.rotation)});this.tickRotCorr=b.rotCorr(A.b,this.labelRotation||0,0!==this.side)},hasData:function(){return this.hasVisibleSeries||n(this.min)&&n(this.max)&&this.tickPositions&&0=this.min&&a<=this.max)g[a]||(g[a]=new F(this,a)),d&&g[a].isNew&&g[a].render(b,!0,.1),g[a].render(b)},render:function(){var b= +this,c=b.chart,d=b.options,k=b.isLog,q=b.lin2log,h=b.isLinked,m=b.tickPositions,z=b.axisTitle,x=b.ticks,f=b.minorTicks,l=b.alternateBands,C=d.stackLabels,n=d.alternateGridColor,u=b.tickmarkOffset,G=b.axisLine,p=b.showAxis,I=D(c.renderer.globalAnimation),r,w;b.labelEdge.length=0;b.overlap=!1;e([x,f,l],function(a){t(a,function(a){a.isActive=!1})});if(b.hasData()||h)b.minorTickInterval&&!b.categories&&e(b.getMinorTickPositions(),function(a){b.renderMinorTick(a)}),m.length&&(e(m,function(a,c){b.renderTick(a, +c)}),u&&(0===b.min||b.single)&&(x[-1]||(x[-1]=new F(b,-1,null,!0)),x[-1].render(-1))),n&&e(m,function(d,g){w=void 0!==m[g+1]?m[g+1]+u:b.max-u;0===g%2&&d=h.second?0:C*Math.floor(x.getMilliseconds()/C));if(t>=h.second)x[D.hcSetSeconds](t>=h.minute? +0:C*Math.floor(x.getSeconds()/C));if(t>=h.minute)x[D.hcSetMinutes](t>=h.hour?0:C*Math.floor(x[D.hcGetMinutes]()/C));if(t>=h.hour)x[D.hcSetHours](t>=h.day?0:C*Math.floor(x[D.hcGetHours]()/C));if(t>=h.day)x[D.hcSetDate](t>=h.month?1:C*Math.floor(x[D.hcGetDate]()/C));t>=h.month&&(x[D.hcSetMonth](t>=h.year?0:C*Math.floor(x[D.hcGetMonth]()/C)),n=x[D.hcGetFullYear]());if(t>=h.year)x[D.hcSetFullYear](n-n%C);if(t===h.week)x[D.hcSetDate](x[D.hcGetDate]()-x[D.hcGetDay]()+e(b,1));n=x[D.hcGetFullYear]();b=x[D.hcGetMonth](); +var A=x[D.hcGetDate](),F=x[D.hcGetHours]();d=x.getTime();D.hcHasTimeZone&&(q=(!B||!!D.hcGetTimezoneOffset)&&(c-d>4*h.month||w(d)!==w(c)),N=w(x),x=new D(d+N));B=x.getTime();for(d=1;Bk.length&&l(k,function(a){0===a%18E5&&"000000000"===H("%H%M%S%L",a)&&(m[a]="day")})}k.info=r(a,{higherRanks:m,totalRange:t*C});return k}; +E.prototype.normalizeTimeTickInterval=function(a,d){var c=d||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2,3,4,6]],["year",null]];d=c[c.length-1];var b=h[d[0]],k=d[1],e;for(e=0;er&&(!w||z<=n)&&void 0!==z&&d.push(z),z>n&& +(B=!0),z=k;else r=h(r),n=h(n),a=w?this.getMinorTickInterval():l.tickInterval,a=f("auto"===a?null:a,this._minorAutoInterval,l.tickPixelInterval/(w?5:1)*(n-r)/((w?e/this.tickPositions.length:e)||1)),a=p(a,null,D(a)),d=H(this.getLinearTickPositions(a,r,n),m),w||(this._minorAutoInterval=a/5);w||(this.tickInterval=a);return d};E.prototype.log2lin=function(a){return Math.log(a)/Math.LN10};E.prototype.lin2log=function(a){return Math.pow(10,a)}})(M);(function(a,E){var D=a.arrayMax,H=a.arrayMin,p=a.defined, +f=a.destroyObjectProperties,l=a.each,r=a.erase,n=a.merge,w=a.pick;a.PlotLineOrBand=function(a,e){this.axis=a;e&&(this.options=e,this.id=e.id)};a.PlotLineOrBand.prototype={render:function(){var f=this,e=f.axis,h=e.horiz,m=f.options,d=m.label,c=f.label,b=m.to,k=m.from,z=m.value,l=p(k)&&p(b),r=p(z),x=f.svgElem,K=!x,t=[],C=m.color,N=w(m.zIndex,0),q=m.events,t={"class":"highcharts-plot-"+(l?"band ":"line ")+(m.className||"")},A={},F=e.chart.renderer,G=l?"bands":"lines",g=e.log2lin;e.isLog&&(k=g(k),b=g(b), +z=g(z));r?(t={stroke:C,"stroke-width":m.width},m.dashStyle&&(t.dashstyle=m.dashStyle)):l&&(C&&(t.fill=C),m.borderWidth&&(t.stroke=m.borderColor,t["stroke-width"]=m.borderWidth));A.zIndex=N;G+="-"+N;(C=e.plotLinesAndBandsGroups[G])||(e.plotLinesAndBandsGroups[G]=C=F.g("plot-"+G).attr(A).add());K&&(f.svgElem=x=F.path().attr(t).add(C));if(r)t=e.getPlotLinePath(z,x.strokeWidth());else if(l)t=e.getPlotBandPath(k,b,m);else return;K&&t&&t.length?(x.attr({d:t}),q&&a.objectEach(q,function(a,b){x.on(b,function(a){q[b].apply(f, +[a])})})):x&&(t?(x.show(),x.animate({d:t})):(x.hide(),c&&(f.label=c=c.destroy())));d&&p(d.text)&&t&&t.length&&0this.max&& +e>this.max;if(m&&h)for(a&&(k=m.toString()===h.toString(),b=0),a=0;aA-h?A:A-h);else if(z)k[a]=Math.max(e,g+h+d>c?g:g+h);else return!1},C=function(a,c,d,g){var e;gc-b?e=!1:k[a]=gc-d/2?c-d-2:g-d/2;return e},p=function(a){var b=f;f=x;x=b;m=a},q=function(){!1!==t.apply(0,f)?!1!==C.apply(0,x)||m||(p(!0),q()):m?k.x=k.y=0:(p(!0),q())};(c.inverted||1q&&(h=!1);a=(e.series&& +e.series.yAxis&&e.series.yAxis.pos)+(e.plotY||0);a-=b.plotTop;c.push({target:e.isHeader?b.plotHeight+l:a,rank:e.isHeader?1:0,size:z.tt.getBBox().height+1,point:e,x:q,tt:t})}});this.cleanSplit();a.distribute(c,b.plotHeight+l);D(c,function(a){var c=a.point,d=c.series;a.tt.attr({visibility:void 0===a.pos?"hidden":"inherit",x:h||c.isHeader?a.x:c.plotX+b.plotLeft+n(f.distance,16),y:a.pos+b.plotTop,anchorX:c.isHeader?c.plotX+b.plotLeft:c.plotX+d.xAxis.pos,anchorY:c.isHeader?a.pos+b.plotTop-15:c.plotY+d.yAxis.pos})})}, +updatePosition:function(a){var e=this.chart,d=this.getLabel(),d=(this.options.positioner||this.getPosition).call(this,d.width,d.height,a);this.move(Math.round(d.x),Math.round(d.y||0),a.plotX+e.plotLeft,a.plotY+e.plotTop)},getDateFormat:function(a,m,d,c){var b=E("%m-%d %H:%M:%S.%L",m),k,h,f={millisecond:15,second:12,minute:9,hour:6,day:3},l="millisecond";for(h in e){if(a===e.week&&+E("%w",m)===d&&"00:00:00.000"===b.substr(6)){h="week";break}if(e[h]>a){h=l;break}if(f[h]&&b.substr(f[h])!=="01-01 00:00:00.000".substr(f[h]))break; +"week"!==h&&(l=h)}h&&(k=c[h]);return k},getXDateFormat:function(a,e,d){e=e.dateTimeLabelFormats;var c=d&&d.closestPointRange;return(c?this.getDateFormat(c,a.x,d.options.startOfWeek,e):e.day)||e.year},tooltipFooterHeaderFormatter:function(a,e){e=e?"footer":"header";var d=a.series,c=d.tooltipOptions,b=c.xDateFormat,k=d.xAxis,h=k&&"datetime"===k.options.type&&f(a.key),m=c[e+"Format"];h&&!b&&(b=this.getXDateFormat(a,c,k));h&&b&&D(a.point&&a.point.tooltipDateKeys||["key"],function(a){m=m.replace("{point."+ +a+"}","{point."+a+":"+b+"}")});return p(m,{point:a,series:d})},bodyFormatter:function(a){return l(a,function(a){var d=a.series.tooltipOptions;return(d[(a.point.formatPrefix||"point")+"Formatter"]||a.point.tooltipFormatter).call(a.point,d[(a.point.formatPrefix||"point")+"Format"])})}}})(M);(function(a){var E=a.addEvent,D=a.attr,H=a.charts,p=a.color,f=a.css,l=a.defined,r=a.each,n=a.extend,w=a.find,u=a.fireEvent,e=a.isObject,h=a.offset,m=a.pick,d=a.splat,c=a.Tooltip;a.Pointer=function(a,c){this.init(a, +c)};a.Pointer.prototype={init:function(a,d){this.options=d;this.chart=a;this.runChartClick=d.chart.events&&!!d.chart.events.click;this.pinchDown=[];this.lastValidTouch={};c&&(a.tooltip=new c(a,d.tooltip),this.followTouchMove=m(d.tooltip.followTouchMove,!0));this.setDOMEvents()},zoomOption:function(a){var b=this.chart,c=b.options.chart,d=c.zoomType||"",b=b.inverted;/touch/.test(a.type)&&(d=m(c.pinchType,d));this.zoomX=a=/x/.test(d);this.zoomY=d=/y/.test(d);this.zoomHor=a&&!b||d&&b;this.zoomVert=d&& +!b||a&&b;this.hasZoom=a||d},normalize:function(a,c){var b;b=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:a;c||(this.chartPosition=c=h(this.chart.container));return n(a,{chartX:Math.round(b.pageX-c.left),chartY:Math.round(b.pageY-c.top)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};r(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},findNearestKDPoint:function(a,c,d){var b;r(a,function(a){var k= +!(a.noSharedTooltip&&c)&&0>a.options.findNearestPointBy.indexOf("y");a=a.searchPoint(d,k);if((k=e(a,!0))&&!(k=!e(b,!0)))var k=b.distX-a.distX,h=b.dist-a.dist,m=(a.series.group&&a.series.group.zIndex)-(b.series.group&&b.series.group.zIndex),k=0<(0!==k&&c?k:0!==h?h:0!==m?m:b.series.index>a.series.index?-1:1);k&&(b=a)});return b},getPointFromEvent:function(a){a=a.target;for(var b;a&&!b;)b=a.point,a=a.parentNode;return b},getChartCoordinatesFromPoint:function(a,c){var b=a.series,d=b.xAxis,b=b.yAxis,k= +m(a.clientX,a.plotX);if(d&&b)return c?{chartX:d.len+d.pos-k,chartY:b.len+b.pos-a.plotY}:{chartX:k+d.pos,chartY:a.plotY+b.pos}},getHoverData:function(b,c,d,h,f,l,n){var k,z=[],x=n&&n.isBoosting;h=!(!h||!b);n=c&&!c.stickyTracking?[c]:a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking,!0)&&a.stickyTracking});c=(k=h?b:this.findNearestKDPoint(n,f,l))&&k.series;k&&(f&&!c.noSharedTooltip?(n=a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking, +!0)&&!a.noSharedTooltip}),r(n,function(a){var b=w(a.points,function(a){return a.x===k.x&&!a.isNull});e(b)&&(x&&(b=a.getPoint(b)),z.push(b))})):z.push(k));return{hoverPoint:k,hoverSeries:c,hoverPoints:z}},runPointActions:function(b,c){var d=this.chart,k=d.tooltip&&d.tooltip.options.enabled?d.tooltip:void 0,e=k?k.shared:!1,h=c||d.hoverPoint,f=h&&h.series||d.hoverSeries,f=this.getHoverData(h,f,d.series,!!c||f&&f.directTouch&&this.isDirectTouch,e,b,{isBoosting:d.isBoosting}),l,h=f.hoverPoint;l=f.hoverPoints; +c=(f=f.hoverSeries)&&f.tooltipOptions.followPointer;e=e&&f&&!f.noSharedTooltip;if(h&&(h!==d.hoverPoint||k&&k.isHidden)){r(d.hoverPoints||[],function(b){-1===a.inArray(b,l)&&b.setState()});r(l||[],function(a){a.setState("hover")});if(d.hoverSeries!==f)f.onMouseOver();d.hoverPoint&&d.hoverPoint.firePointEvent("mouseOut");if(!h.series)return;h.firePointEvent("mouseOver");d.hoverPoints=l;d.hoverPoint=h;k&&k.refresh(e?l:h,b)}else c&&k&&!k.isHidden&&(h=k.getAnchor([{}],b),k.updatePosition({plotX:h[0],plotY:h[1]})); +this.unDocMouseMove||(this.unDocMouseMove=E(d.container.ownerDocument,"mousemove",function(b){var c=H[a.hoverChartIndex];if(c)c.pointer.onDocumentMouseMove(b)}));r(d.axes,function(c){var d=m(c.crosshair.snap,!0),k=d?a.find(l,function(a){return a.series[c.coll]===c}):void 0;k||!d?c.drawCrosshair(b,k):c.hideCrosshair()})},reset:function(a,c){var b=this.chart,k=b.hoverSeries,e=b.hoverPoint,h=b.hoverPoints,m=b.tooltip,f=m&&m.shared?h:e;a&&f&&r(d(f),function(b){b.series.isCartesian&&void 0===b.plotX&& +(a=!1)});if(a)m&&f&&(m.refresh(f),e&&(e.setState(e.state,!0),r(b.axes,function(a){a.crosshair&&a.drawCrosshair(null,e)})));else{if(e)e.onMouseOut();h&&r(h,function(a){a.setState()});if(k)k.onMouseOut();m&&m.hide(c);this.unDocMouseMove&&(this.unDocMouseMove=this.unDocMouseMove());r(b.axes,function(a){a.hideCrosshair()});this.hoverX=b.hoverPoints=b.hoverPoint=null}},scaleGroups:function(a,c){var b=this.chart,d;r(b.series,function(k){d=a||k.getPlotBox();k.xAxis&&k.xAxis.zoomEnabled&&k.group&&(k.group.attr(d), +k.markerGroup&&(k.markerGroup.attr(d),k.markerGroup.clip(c?b.clipRect:null)),k.dataLabelsGroup&&k.dataLabelsGroup.attr(d))});b.clipRect.attr(c||b.clipBox)},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,h=this.zoomHor,m=this.zoomVert,f=b.plotLeft,l=b.plotTop,n=b.plotWidth,q=b.plotHeight,A,F=this.selectionMarker,G=this.mouseDownX, +g=this.mouseDownY,v=c.panKey&&a[c.panKey+"Key"];F&&F.touch||(df+n&&(d=f+n),el+q&&(e=l+q),this.hasDragged=Math.sqrt(Math.pow(G-d,2)+Math.pow(g-e,2)),10u.max&&(f=u.max-x,v=!0);v?(F-=.8*(F-m[b][0]),q||(g-=.8*(g-m[b][1])),l()):m[b]=[F,g];C||(h[b]=w-r,h[n]=x);h=C?1/t:t;e[n]=x;e[b]=f;p[C?a?"scaleY":"scaleX":"scale"+k]=t;p["translate"+k]=h*r+(F-h*A)},pinch:function(a){var n=this,r=n.chart,u=n.pinchDown,e=a.touches,h=e.length,m=n.lastValidTouch, +d=n.hasZoom,c=n.selectionMarker,b={},k=1===h&&(n.inClass(a.target,"highcharts-tracker")&&r.runTrackerClick||n.runChartClick),z={};1c-6&&h(q||c.spacingBox.width-2*t-d.x)&&(this.itemX=t,this.itemY+=F+this.lastLineHeight+A,this.lastLineHeight=0);this.maxItemWidth=Math.max(this.maxItemWidth,m);this.lastItemY=F+this.itemY+A;this.lastLineHeight=Math.max(b,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=m:(this.itemY+=F+b+A,this.lastLineHeight=b);this.offsetWidth=q||Math.max((e?this.itemX-t-(a.checkbox?0:p):m)+t,this.offsetWidth)}, +getAllItems:function(){var a=[];f(this.chart.series,function(c){var b=c&&c.options;c&&w(b.showInLegend,p(b.linkedTo)?!1:void 0,!0)&&(a=a.concat(c.legendItems||("point"===b.legendType?c.data:c)))});return a},getAlignment:function(){var a=this.options;return a.floating?"":a.align.charAt(0)+a.verticalAlign.charAt(0)+a.layout.charAt(0)},adjustMargins:function(a,c){var b=this.chart,d=this.options,e=this.getAlignment();e&&f([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(k,h){k.test(e)&& +!p(a[h])&&(b[r[h]]=Math.max(b[r[h]],b.legend[(h+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][h]*d[h%2?"x":"y"]+w(d.margin,12)+c[h]+(0===h?b.titleOffset+b.options.title.margin:0)))})},render:function(){var a=this,c=a.chart,b=c.renderer,k=a.group,h,m,l,x,p=a.box,t=a.options,C=a.padding;a.itemX=C;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;k||(a.group=k=b.g("legend").attr({zIndex:7}).add(),a.contentGroup=b.g().attr({zIndex:1}).add(k),a.scrollGroup=b.g().add(a.contentGroup));a.renderTitle(); +h=a.getAllItems();e(h,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});t.reversed&&h.reverse();a.allItems=h;a.display=m=!!h.length;a.lastLineHeight=0;f(h,function(b){a.renderItem(b)});l=(t.width||a.offsetWidth)+C;x=a.lastItemY+a.lastLineHeight+a.titleHeight;x=a.handleOverflow(x);x+=C;p||(a.box=p=b.rect().addClass("highcharts-legend-box").attr({r:t.borderRadius}).add(k),p.isNew=!0);p.attr({stroke:t.borderColor,"stroke-width":t.borderWidth||0,fill:t.backgroundColor|| +"none"}).shadow(t.shadow);0b&&!1!==t.enabled?(this.clipHeight=l=Math.max(b-20-this.titleHeight-m,0),this.currentPage=w(this.currentPage,1),this.fullHeight=a,f(G,function(a,b){var c=a._legendItemPos[1],d=Math.round(a.legendItem.getBBox().height),g=A.length;if(!g||c-A[g-1]>l&&(F||c)!==A[g-1])A.push(F||c),g++;a.pageIx=g-1;F&&(G[b-1].pageIx=g-1);b===G.length-1&&c+d-A[g-1]>l&&(A.push(c),a.pageIx=g);c!==F&&(F=c)}),n||(n=c.clipRect=d.clipRect(0,m,9999,0),c.contentGroup.clip(n)),g(l),q||(this.nav=q=d.g().attr({zIndex:1}).add(this.group), +this.up=d.symbol("triangle",0,0,r,r).on("click",function(){c.scroll(-1,p)}).add(q),this.pager=d.text("",15,10).addClass("highcharts-legend-navigation").css(t.style).add(q),this.down=d.symbol("triangle-down",0,0,r,r).on("click",function(){c.scroll(1,p)}).add(q)),c.scroll(0),a=b):q&&(g(),this.nav=q.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return a},scroll:function(a,c){var b=this.pages,d=b.length;a=this.currentPage+a;var e=this.clipHeight,h=this.options.navigation,f=this.pager, +m=this.padding;a>d&&(a=d);0b&&(f=typeof a[0],"string"===f?e.name=a[0]:"number"===f&&(e.x=a[0]),k++);l=d.value;)d=h[++f];d&&d.color&&!this.options.color&&(this.color=d.color);return d},destroy:function(){var a=this.series.chart,h=a.hoverPoints,f;a.pointCount--;h&&(this.setState(),p(h,this),h.length||(a.hoverPoints=null));if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)u(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(f in this)this[f]=null},destroyElements:function(){for(var a=["graphic","dataLabel", +"dataLabelUpper","connector","shadowGroup"],h,f=6;f--;)h=a[f],this[h]&&(this[h]=this[h].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,color:this.color,colorIndex:this.colorIndex,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},tooltipFormatter:function(a){var e=this.series,f=e.tooltipOptions,d=w(f.valueDecimals,""),c=f.valuePrefix||"",b=f.valueSuffix||"";D(e.pointArrayMap||["y"],function(e){e="{point."+ +e;if(c||b)a=a.replace(e+"}",c+e+"}"+b);a=a.replace(e+"}",e+":,."+d+"f}")});return l(a,{point:this,series:this.series})},firePointEvent:function(a,h,m){var d=this,c=this.series.options;(c.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents();"click"===a&&c.allowPointSelect&&(m=function(a){d.select&&d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});f(this,a,h,m)},visible:!0}})(M);(function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.correctFloat, +l=a.Date,r=a.defaultOptions,n=a.defaultPlotOptions,w=a.defined,u=a.each,e=a.erase,h=a.extend,m=a.fireEvent,d=a.grep,c=a.isArray,b=a.isNumber,k=a.isString,z=a.merge,B=a.objectEach,I=a.pick,x=a.removeEvent,K=a.splat,t=a.SVGElement,C=a.syncTimeout,N=a.win;a.Series=a.seriesType("line",null,{lineWidth:2,allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},marker:{lineWidth:0,lineColor:"#ffffff",radius:4,states:{hover:{animation:{duration:50},enabled:!0,radiusPlus:2,lineWidthPlus:1},select:{fillColor:"#cccccc", +lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:{align:"center",formatter:function(){return null===this.y?"":a.numberFormat(this.y,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"contrast",textOutline:"1px contrast"},verticalAlign:"bottom",x:0,y:0,padding:5},cropThreshold:300,pointRange:0,softThreshold:!0,states:{hover:{animation:{duration:50},lineWidthPlus:1,marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1E3,findNearestPointBy:"x"}, +{isCartesian:!0,pointClass:a.Point,sorted:!0,requireSorting:!0,directTouch:!1,axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],coll:"series",init:function(a,b){var c=this,d,g=a.series,e;c.chart=a;c.options=b=c.setOptions(b);c.linkedSeries=[];c.bindAxes();h(c,{name:b.name,state:"",visible:!1!==b.visible,selected:!0===b.selected});d=b.events;B(d,function(a,b){E(c,b,a)});if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;c.getColor(); +c.getSymbol();u(c.parallelArrays,function(a){c[a+"Data"]=[]});c.setData(b.data,!1);c.isCartesian&&(a.hasCartesianSeries=!0);g.length&&(e=g[g.length-1]);c._i=I(e&&e._i,-1)+1;a.orderSeries(this.insert(g))},insert:function(a){var c=this.options.index,d;if(b(c)){for(d=a.length;d--;)if(c>=I(a[d].options.index,a[d]._i)){a.splice(d+1,0,this);break}-1===d&&a.unshift(this);d+=1}else a.push(this);return I(d,a.length-1)},bindAxes:function(){var b=this,c=b.options,d=b.chart,e;u(b.axisTypes||[],function(g){u(d[g], +function(a){e=a.options;if(c[g]===e.index||void 0!==c[g]&&c[g]===e.id||void 0===c[g]&&0===e.index)b.insert(a.series),b[g]=a,a.isDirty=!0});b[g]||b.optionalAxis===g||a.error(18,!0)})},updateParallelArrays:function(a,c){var d=a.series,e=arguments,g=b(c)?function(b){var g="y"===b&&d.toYData?d.toYData(a):a[b];d[b+"Data"][c]=g}:function(a){Array.prototype[c].apply(d[a+"Data"],Array.prototype.slice.call(e,2))};u(d.parallelArrays,g)},autoIncrement:function(){var b=this.options,c=this.xIncrement,d,e=b.pointIntervalUnit, +g=0,c=I(c,b.pointStart,0);this.pointInterval=d=I(this.pointInterval,b.pointInterval,1);e&&(b=new l(c),"day"===e?b=+b[l.hcSetDate](b[l.hcGetDate]()+d):"month"===e?b=+b[l.hcSetMonth](b[l.hcGetMonth]()+d):"year"===e&&(b=+b[l.hcSetFullYear](b[l.hcGetFullYear]()+d)),l.hcHasTimeZone&&(g=a.getTZOffset(b)-a.getTZOffset(c)),d=b-c+g);this.xIncrement=c+d;return c},setOptions:function(a){var b=this.chart,c=b.options,d=c.plotOptions,g=(b.userOptions||{}).plotOptions||{},e=d[this.type];this.userOptions=a;b=z(e, +d.series,a);this.tooltipOptions=z(r.tooltip,r.plotOptions.series&&r.plotOptions.series.tooltip,r.plotOptions[this.type].tooltip,c.tooltip.userOptions,d.series&&d.series.tooltip,d[this.type].tooltip,a.tooltip);this.stickyTracking=I(a.stickyTracking,g[this.type]&&g[this.type].stickyTracking,g.series&&g.series.stickyTracking,this.tooltipOptions.shared&&!this.noSharedTooltip?!0:b.stickyTracking);null===e.marker&&delete b.marker;this.zoneAxis=b.zoneAxis;a=this.zones=(b.zones||[]).slice();!b.negativeColor&& +!b.negativeFillColor||b.zones||a.push({value:b[this.zoneAxis+"Threshold"]||b.threshold||0,className:"highcharts-negative",color:b.negativeColor,fillColor:b.negativeFillColor});a.length&&w(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return b},getCyclic:function(a,b,c){var d,g=this.chart,e=this.userOptions,k=a+"Index",h=a+"Counter",q=c?c.length:I(g.options.chart[a+"Count"],g[a+"Count"]);b||(d=I(e[k],e["_"+k]),w(d)||(g.series.length||(g[h]=0),e["_"+k]=d=g[h]%q,g[h]+=1), +c&&(b=c[d]));void 0!==d&&(this[k]=d);this[a]=b},getColor:function(){this.options.colorByPoint?this.options.color=null:this.getCyclic("color",this.options.color||n[this.type].color,this.chart.options.colors)},getSymbol:function(){this.getCyclic("symbol",this.options.marker.symbol,this.chart.options.symbols)},drawLegendSymbol:a.LegendSymbolMixin.drawLineMarker,setData:function(d,e,h,f){var g=this,q=g.points,m=q&&q.length||0,l,A=g.options,t=g.chart,x=null,n=g.xAxis,p=A.turboThreshold,z=this.xData,F= +this.yData,C=(l=g.pointArrayMap)&&l.length;d=d||[];l=d.length;e=I(e,!0);if(!1!==f&&l&&m===l&&!g.cropped&&!g.hasGroupedData&&g.visible)u(d,function(a,b){q[b].update&&a!==A.data[b]&&q[b].update(a,!1,null,!1)});else{g.xIncrement=null;g.colorCounter=0;u(this.parallelArrays,function(a){g[a+"Data"].length=0});if(p&&l>p){for(h=0;null===x&&hf||this.forceCrop))if(c[e-1]z)c=[],d=[];else if(c[0]z)g=this.cropData(this.xData,this.yData,p,z),c=g.xData,d=g.yData,g=g.start,k=!0;for(f=c.length|| +1;--f;)e=x?m(c[f])-m(c[f-1]):c[f]-c[f-1],0e&&n&&(a.error(15),n=!1);this.cropped=k;this.cropStart=g;this.processedXData=c;this.processedYData=d;this.closestPointRange=h},cropData:function(a,b,c,d){var g=a.length,e=0,k=g,h=I(this.cropShoulder,1),f;for(f=0;f=c){e=Math.max(0,f-h);break}for(c=f;cd){k=c+h;break}return{xData:a.slice(e,k),yData:b.slice(e,k),start:e,end:k}},generatePoints:function(){var a=this.options,b=a.data,c=this.data,d,g=this.processedXData, +e=this.processedYData,k=this.pointClass,h=g.length,f=this.cropStart||0,m,l=this.hasGroupedData,a=a.keys,t,x=[],n;c||l||(c=[],c.length=b.length,c=this.data=c);a&&l&&(this.options.keys=!1);for(n=0;n=f&&(e[n-1]||l)<=q,m&&l)if(m=t.length)for(;m--;)"number"===typeof t[m]&&(g[h++]=t[m]);else g[h++]=t;this.dataMin= +p(g);this.dataMax=H(g)},translate:function(){this.processedXData||this.processData();this.generatePoints();var a=this.options,c=a.stacking,d=this.xAxis,e=d.categories,g=this.yAxis,k=this.points,h=k.length,m=!!this.modifyValue,l=a.pointPlacement,t="between"===l||b(l),n=a.threshold,x=a.startFromThreshold?n:0,p,z,C,r,u=Number.MAX_VALUE;"between"===l&&(l=.5);b(l)&&(l*=I(a.pointRange||d.pointRange));for(a=0;a=K&&(B.isNull=!0);B.plotX=p=f(Math.min(Math.max(-1E5,d.translate(N,0,0,0,1,l,"flags"===this.type)),1E5));c&&this.visible&&!B.isNull&&D&&D[N]&&(r=this.getStackIndicator(r,N,this.index),E=D[N],K=E.points[r.key],z=K[0],K=K[1],z===x&&r.key===D[N].base&&(z=I(n,g.min)),g.positiveValuesOnly&&0>=z&&(z=null),B.total=B.stackTotal=E.total,B.percentage=E.total&&B.y/E.total*100,B.stackY=K,E.setOffset(this.pointXOffset||0,this.barW||0));B.yBottom=w(z)?g.translate(z,0,1,0,1): +null;m&&(K=this.modifyValue(K,B));B.plotY=z="number"===typeof K&&Infinity!==K?Math.min(Math.max(-1E5,g.translate(K,0,1,0,1)),1E5):void 0;B.isInside=void 0!==z&&0<=z&&z<=g.len&&0<=p&&p<=d.len;B.clientX=t?f(d.translate(N,0,0,0,1,l)):p;B.negative=B.y<(n||0);B.category=e&&void 0!==e[B.x]?e[B.x]:B.x;B.isNull||(void 0!==C&&(u=Math.min(u,Math.abs(p-C))),C=p);B.zone=this.zones.length&&B.getZone()}this.closestPointRangePx=u},getValidPoints:function(a,b){var c=this.chart;return d(a||this.points||[],function(a){return b&& +!c.isInsidePlot(a.plotX,a.plotY,c.inverted)?!1:!a.isNull})},setClip:function(a){var b=this.chart,c=this.options,d=b.renderer,g=b.inverted,e=this.clipBox,k=e||b.clipBox,h=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,k.height,c.xAxis,c.yAxis].join(),f=b[h],q=b[h+"m"];f||(a&&(k.width=0,g&&(k.x=b.plotSizeX),b[h+"m"]=q=d.clipRect(g?b.plotSizeX+99:-99,g?-b.plotLeft:-b.plotTop,99,g?b.chartWidth:b.chartHeight)),b[h]=f=d.clipRect(k),f.count={length:0});a&&!f.count[this.index]&&(f.count[this.index]= +!0,f.count.length+=1);!1!==c.clip&&(this.group.clip(a||e?f:b.clipRect),this.markerGroup.clip(q),this.sharedClipKey=h);a||(f.count[this.index]&&(delete f.count[this.index],--f.count.length),0===f.count.length&&h&&b[h]&&(e||(b[h]=b[h].destroy()),b[h+"m"]&&(b[h+"m"]=b[h+"m"].destroy())))},animate:function(a){var b=this.chart,c=D(this.options.animation),d;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX,x:0},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99,x:0},c),this.animate= +null)},afterAnimate:function(){this.setClip();m(this,"afterAnimate");this.finishedAnimating=!0},drawPoints:function(){var a=this.points,b=this.chart,c,d,g,e,k=this.options.marker,h,f,l,m=this[this.specialGroup]||this.markerGroup,t,n=I(k.enabled,this.xAxis.isRadial?!0:null,this.closestPointRangePx>=2*k.radius);if(!1!==k.enabled||this._hasPointMarkers)for(c=0;ce&&b.shadow));k&&(k.startX=c.xMap,k.isArea=c.isArea)})}, +applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,e,k,h=this.clips||[],f,m=this.graph,l=this.area,t=Math.max(b.chartWidth,b.chartHeight),n=this[(this.zoneAxis||"y")+"Axis"],x,p,z=b.inverted,C,r,w,B,K=!1;d.length&&(m||l)&&n&&void 0!==n.min&&(p=n.reversed,C=n.horiz,m&&m.hide(),l&&l.hide(),x=n.getExtremes(),u(d,function(d,g){e=p?C?b.plotWidth:0:C?0:n.toPixels(x.min);e=Math.min(Math.max(I(k,e),0),t);k=Math.min(Math.max(Math.round(n.toPixels(I(d.value,x.max),!0)),0),t);K&&(e=k=n.toPixels(x.max)); +r=Math.abs(e-k);w=Math.min(e,k);B=Math.max(e,k);n.isXAxis?(f={x:z?B:w,y:0,width:r,height:t},C||(f.x=b.plotHeight-f.x)):(f={x:0,y:z?B:w,width:t,height:r},C&&(f.y=b.plotWidth-f.y));z&&c.isVML&&(f=n.isXAxis?{x:0,y:p?w:B,height:f.width,width:b.chartWidth}:{x:f.y-b.plotLeft-b.spacingBox.x,y:0,width:f.height,height:b.chartHeight});h[g]?h[g].animate(f):(h[g]=c.clipRect(f),m&&a["zone-graph-"+g].clip(h[g]),l&&a["zone-area-"+g].clip(h[g]));K=d.value>x.max}),this.clips=h)},invertGroups:function(a){function b(){u(["group", +"markerGroup"],function(b){c[b]&&(d.renderer.isVML&&c[b].attr({width:c.yAxis.len,height:c.xAxis.len}),c[b].width=c.yAxis.len,c[b].height=c.xAxis.len,c[b].invert(a))})}var c=this,d=c.chart,e;c.xAxis&&(e=E(d,"resize",b),E(c,"destroy",e),b(a),c.invertGroups=b)},plotGroup:function(a,b,c,d,e){var g=this[a],k=!g;k&&(this[a]=g=this.chart.renderer.g().attr({zIndex:d||.1}).add(e));g.addClass("highcharts-"+b+" highcharts-series-"+this.index+" highcharts-"+this.type+"-series "+(w(this.colorIndex)?"highcharts-color-"+ +this.colorIndex+" ":"")+(this.options.className||"")+(g.hasClass("highcharts-tracker")?" highcharts-tracker":""),!0);g.attr({visibility:c})[k?"attr":"animate"](this.getPlotBox());return g},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;a.inverted&&(b=c,c=this.xAxis);return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this,b=a.chart,c,d=a.options,e=!!a.animate&&b.renderer.isSVG&&D(d.animation).duration,k=a.visible?"inherit": +"hidden",h=d.zIndex,f=a.hasRendered,m=b.seriesGroup,l=b.inverted;c=a.plotGroup("group","series",k,h,m);a.markerGroup=a.plotGroup("markerGroup","markers",k,h,m);e&&a.animate(!0);c.inverted=a.isCartesian?l:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(l);!1===d.clip||a.sharedClipKey||f||c.clip(b.clipRect);e&&a.animate();f||(a.animationTimeout=C(function(){a.afterAnimate()}, +e));a.isDirty=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirty||this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:I(d&&d.left,a.plotLeft),translateY:I(e&&e.top,a.plotTop)}));this.translate();this.render();b&&delete this.kdTree},kdAxisArray:["clientX","plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,e=this.chart.inverted;return this.searchKDTree({clientX:e?c.len-a.chartY+ +c.pos:a.chartX-c.pos,plotY:e?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(c,d,e){var g,k;if(k=c&&c.length)return g=b.kdAxisArray[d%e],c.sort(function(a,b){return a[g]-b[g]}),k=Math.floor(k/2),{point:c[k],left:a(c.slice(0,k),d+1,e),right:a(c.slice(k+1),d+1,e)}}this.buildingKdTree=!0;var b=this,c=-1l?"left":"right";t=0>l?"right":"left";b[q]&&(q=c(a,b[q],g+1,f),n=q[h]x;)q--;this.updateParallelArrays(m,"splice",q,0,0);this.updateParallelArrays(m,q);g&&m.name&&(g[x]=m.name);l.splice(q,0,a);n&&(this.data.splice(q,0,null),this.processData());"point"===e.legendType&&this.generatePoints();c&&(h[0]&&h[0].remove?h[0].remove(!1):(h.shift(),this.updateParallelArrays(m,"shift"),l.shift()));this.isDirtyData=this.isDirty=!0;b&&f.redraw(d)},removePoint:function(a,b,c){var d=this,e=d.data,h=e[a],f=d.points,g=d.chart,l=function(){f&&f.length===e.length&& +f.splice(a,1);e.splice(a,1);d.options.data.splice(a,1);d.updateParallelArrays(h||{series:d},"splice",a,1);h&&h.destroy();d.isDirty=!0;d.isDirtyData=!0;b&&g.redraw()};x(c,g);b=k(b,!0);h?h.firePointEvent("remove",null,l):l()},remove:function(a,b,c){function d(){e.destroy();h.isDirtyLegend=h.isDirtyBox=!0;h.linkSeries();k(a,!0)&&h.redraw(b)}var e=this,h=e.chart;!1!==c?u(e,"remove",null,d):d()},update:function(a,b){var d=this,e=d.chart,h=d.userOptions,f=d.oldType||d.type,l=a.type||h.type||e.options.chart.type, +g=I[f].prototype,m,n=["group","markerGroup","dataLabelsGroup"],t=["navigatorSeries","baseSeries"],x=d.finishedAnimating&&{animation:!1};if(Object.keys&&"data"===Object.keys(a).toString())return this.setData(a.data,b);t=n.concat(t);r(t,function(a){t[a]=d[a];delete d[a]});a=c(h,x,{index:d.index,pointStart:d.xData[0]},{data:d.options.data},a);d.remove(!1,null,!1);for(m in g)d[m]=void 0;w(d,I[l||f].prototype);r(t,function(a){d[a]=t[a]});d.init(e,a);a.zIndex!==h.zIndex&&r(n,function(b){d[b]&&d[b].attr({zIndex:a.zIndex})}); +d.oldType=f;e.linkSeries();k(b,!0)&&e.redraw(!1)}});w(H.prototype,{update:function(a,b){var d=this.chart;a=d.options[this.coll][this.options.index]=c(this.userOptions,a);this.destroy(!0);this.init(d,w(a,{events:void 0}));d.isDirtyBox=!0;k(b,!0)&&d.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,e=this.series,h=e.length;h--;)e[h]&&e[h].remove(!1);n(b.axes,this);n(b[c],this);d(b.options[c])?b.options[c].splice(this.options.index,1):delete b.options[c];r(b[c],function(a,b){a.options.index= +b});this.destroy();b.isDirtyBox=!0;k(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}})})(M);(function(a){var E=a.color,D=a.each,H=a.map,p=a.pick,f=a.Series,l=a.seriesType;l("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(f){var l=[],r=[],u=this.xAxis,e=this.yAxis,h=e.stacks[this.stackKey],m={},d=this.index,c=e.series,b=c.length,k,z=p(e.options.reversedStacks,!0)?1:-1,B;f=f||this.points; +if(this.options.stacking){for(B=0;Ba&&w>l?(w=Math.max(a,l),e=2*l-w):wp&&e>l?(e=Math.max(p,l),w=2*l-e):e=Math.abs(h)&&.5a.closestPointRange*a.xAxis.transA,d=a.borderWidth=r(f.borderWidth,d?0:1),c=a.yAxis,b=f.threshold,k=a.translatedThreshold=c.getThreshold(b),l=r(f.minPointLength,5),p=a.getColumnMetrics(),u=p.width,x=a.barW=Math.max(u,1+2*d),w=a.pointXOffset=p.offset;h.inverted&&(k-=.5);f.pointPadding&&(x=Math.ceil(x));n.prototype.translate.apply(a);H(a.points,function(d){var e=r(d.yBottom,k),f=999+Math.abs(e),f=Math.min(Math.max(-f,d.plotY),c.len+f),m=d.plotX+w,n=x,t=Math.min(f,e),p,g=Math.max(f,e)-t;l&& +Math.abs(g)l?e-l:k-(p?l:0));d.barX=m;d.pointWidth=u;d.tooltipPos=h.inverted?[c.len+c.pos-h.plotLeft-f,a.xAxis.len-m-n/2,g]:[m+n/2,f+c.pos-h.plotTop,g];d.shapeType="rect";d.shapeArgs=a.crispCol.apply(a,d.isNull?[m,k,n,0]:[m,t,n,g])})},getSymbol:a.noop,drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")}, +pointAttribs:function(a,f){var e=this.options,d,c=this.pointAttrToOptions||{};d=c.stroke||"borderColor";var b=c["stroke-width"]||"borderWidth",k=a&&a.color||this.color,h=a&&a[d]||e[d]||this.color||k,n=a&&a[b]||e[b]||this[b]||0,c=e.dashStyle;a&&this.zones.length&&(k=a.getZone(),k=a.options.color||k&&k.color||this.color);f&&(a=l(e.states[f],a.options.states&&a.options.states[f]||{}),f=a.brightness,k=a.color||void 0!==f&&D(k).brighten(a.brightness).get()||k,h=a[d]||h,n=a[b]||n,c=a.dashStyle||c);d={fill:k, +stroke:h,"stroke-width":n};c&&(d.dashstyle=c);return d},drawPoints:function(){var a=this,h=this.chart,m=a.options,d=h.renderer,c=m.animationLimit||250,b;H(a.points,function(e){var k=e.graphic;if(f(e.plotY)&&null!==e.y){b=e.shapeArgs;if(k)k[h.pointCounte;++e)h=w[e],a=2>e||2===e&&/%$/.test(h),w[e]=p(h,[n,l,u,w[2]][e])+(a?r:0);w[3]>w[2]&&(w[3]=w[2]);return w},getStartAndEndRadians:function(a,l){a=D(a)?a:0;l=D(l)&&l>a&&360>l-a?l:a+360;return{start:E*(a+-90),end:E*(l+-90)}}}})(M);(function(a){var E=a.addEvent,D=a.CenteredSeriesMixin,H=a.defined,p=a.each,f=a.extend,l=D.getStartAndEndRadians,r=a.inArray,n=a.noop,w=a.pick,u=a.Point,e=a.Series,h=a.seriesType,m=a.setAnimation;h("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30, +enabled:!0,formatter:function(){return this.point.isNull?void 0:this.point.name},x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff",borderWidth:1,states:{hover:{brightness:.1,shadow:!1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:a.seriesTypes.column.prototype.pointAttribs,animate:function(a){var c= +this,b=c.points,d=c.startAngleRad;a||(p(b,function(a){var b=a.graphic,e=a.shapeArgs;b&&(b.attr({r:a.startR||c.center[3]/2,start:d,end:d}),b.animate({r:e.r,start:e.start,end:e.end},c.options.animation))}),c.animate=null)},updateTotals:function(){var a,c=0,b=this.points,e=b.length,f,h=this.options.ignoreHiddenPoint;for(a=0;a1.5*Math.PI?m-=2*Math.PI:m<-Math.PI/2&&(m+=2*Math.PI);G.slicedTranslation={translateX:Math.round(Math.cos(m)*d),translateY:Math.round(Math.sin(m)*d)};h=Math.cos(m)*a[2]/ +2;u=Math.sin(m)*a[2]/2;G.tooltipPos=[a[0]+.7*h,a[1]+.7*u];G.half=m<-Math.PI/2||m>Math.PI/2?1:0;G.angle=m;f=Math.min(e,G.labelDistance/5);G.labelPos=[a[0]+h+Math.cos(m)*G.labelDistance,a[1]+u+Math.sin(m)*G.labelDistance,a[0]+h+Math.cos(m)*f,a[1]+u+Math.sin(m)*f,a[0]+h,a[1]+u,0>G.labelDistance?"center":G.half?"right":"left",m]}},drawGraph:null,drawPoints:function(){var a=this,c=a.chart.renderer,b,e,h,l,m=a.options.shadow;m&&!a.shadowGroup&&(a.shadowGroup=c.g("shadow").add(a.group));p(a.points,function(d){e= +d.graphic;if(d.isNull)e&&(d.graphic=e.destroy());else{l=d.shapeArgs;b=d.getTranslate();var k=d.shadowGroup;m&&!k&&(k=d.shadowGroup=c.g("shadow").add(a.shadowGroup));k&&k.attr(b);h=a.pointAttribs(d,d.selected&&"select");e?e.setRadialReference(a.center).attr(h).animate(f(l,b)):(d.graphic=e=c[d.shapeType](l).setRadialReference(a.center).attr(b).add(a.group),d.visible||e.attr({visibility:"hidden"}),e.attr(h).attr({"stroke-linejoin":"round"}).shadow(m,k));e.addClass(d.getClassName())}})},searchPoint:n, +sortByAngle:function(a,c){a.sort(function(a,d){return void 0!==a.angle&&(d.angle-a.angle)*c})},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,getCenter:D.getCenter,getSymbol:n},{init:function(){u.prototype.init.apply(this,arguments);var a=this,c;a.name=w(a.name,"Slice");c=function(b){a.slice("select"===b.type)};E(a,"select",c);E(a,"unselect",c);return a},isValid:function(){return a.isNumber(this.y,!0)&&0<=this.y},setVisible:function(a,c){var b=this,d=b.series,e=d.chart,f=d.options.ignoreHiddenPoint; +c=w(c,f);a!==b.visible&&(b.visible=b.options.visible=a=void 0===a?!b.visible:a,d.options.data[r(b,d.data)]=b.options,p(["graphic","dataLabel","connector","shadowGroup"],function(c){if(b[c])b[c][a?"show":"hide"](!0)}),b.legendItem&&e.legend.colorizeItem(b,a),a||"hover"!==b.state||b.setState(""),f&&(d.isDirty=!0),c&&e.redraw())},slice:function(a,c,b){var d=this.series;m(b,d.chart);w(c,!0);this.sliced=this.options.sliced=H(a)?a:!this.sliced;d.options.data[r(this,d.data)]=this.options;this.graphic.animate(this.getTranslate()); +this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())},getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(a){var c=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.x,c.y,c.r+a,c.r+a,{innerR:this.shapeArgs.r-1,start:c.start,end:c.end})}})})(M);(function(a){var E=a.addEvent,D=a.arrayMax,H=a.defined,p=a.each,f=a.extend,l=a.format,r=a.map,n=a.merge,w=a.noop,u=a.pick,e=a.relativeLength,h= +a.Series,m=a.seriesTypes,d=a.stableSort;a.distribute=function(a,b){function c(a,b){return a.target-b.target}var e,f=!0,h=a,l=[],m;m=0;for(e=a.length;e--;)m+=a[e].size;if(m>b){d(a,function(a,b){return(b.rank||0)-(a.rank||0)});for(m=e=0;m<=b;)m+=a[e].size,e++;l=a.splice(e-1,a.length)}d(a,c);for(a=r(a,function(a){return{size:a.size,targets:[a.target],align:u(a.align,.5)}});f;){for(e=a.length;e--;)f=a[e],m=(Math.min.apply(0,f.targets)+Math.max.apply(0,f.targets))/2,f.pos=Math.min(Math.max(0,m-f.size* +f.align),b-f.size);e=a.length;for(f=!1;e--;)0a[e].pos&&(a[e-1].size+=a[e].size,a[e-1].targets=a[e-1].targets.concat(a[e].targets),a[e-1].align=.5,a[e-1].pos+a[e-1].size>b&&(a[e-1].pos=b-a[e-1].size),a.splice(e,1),f=!0)}e=0;p(a,function(a){var b=0;p(a.targets,function(){h[e].pos=a.pos+b;b+=h[e].size;e++})});h.push.apply(h,l);d(h,c)};h.prototype.drawDataLabels=function(){function c(a,b){var c=b.filter;return c?(b=c.operator,a=a[c.property],c=c.value,"\x3e"===b&&a>c||"\x3c"=== +b&&a=c||"\x3c\x3d"===b&&a<=c||"\x3d\x3d"===b&&a==c||"\x3d\x3d\x3d"===b&&a===c?!0:!1):!0}var b=this,d=b.options,e=d.dataLabels,f=b.points,h,m,r=b.hasRendered||0,t,w,D=u(e.defer,!!d.animation),q=b.chart.renderer;if(e.enabled||b._hasPointLabels)b.dlProcessOptions&&b.dlProcessOptions(e),w=b.plotGroup("dataLabelsGroup","data-labels",D&&!r?"hidden":"visible",e.zIndex||6),D&&(w.attr({opacity:+r}),r||E(b,"afterAnimate",function(){b.visible&&w.show(!0);w[d.animation?"animate":"attr"]({opacity:1}, +{duration:200})})),m=e,p(f,function(f){var k,p=f.dataLabel,g,x,r=f.connector,z=!p,C;h=f.dlOptions||f.options&&f.options.dataLabels;(k=u(h&&h.enabled,m.enabled)&&!f.isNull)&&(k=!0===c(f,h||e));k&&(e=n(m,h),g=f.getLabelConfig(),C=e[f.formatPrefix+"Format"]||e.format,t=H(C)?l(C,g):(e[f.formatPrefix+"Formatter"]||e.formatter).call(g,e),C=e.style,g=e.rotation,C.color=u(e.color,C.color,b.color,"#000000"),"contrast"===C.color&&(f.contrastColor=q.getContrast(f.color||b.color),C.color=e.inside||0>u(f.labelDistance, +e.distance)||d.stacking?f.contrastColor:"#000000"),d.cursor&&(C.cursor=d.cursor),x={fill:e.backgroundColor,stroke:e.borderColor,"stroke-width":e.borderWidth,r:e.borderRadius||0,rotation:g,padding:e.padding,zIndex:1},a.objectEach(x,function(a,b){void 0===a&&delete x[b]}));!p||k&&H(t)?k&&H(t)&&(p?x.text=t:(p=f.dataLabel=g?q.text(t,0,-9999).addClass("highcharts-data-label"):q.label(t,0,-9999,e.shape,null,null,e.useHTML,null,"data-label"),p.addClass(" highcharts-data-label-color-"+f.colorIndex+" "+(e.className|| +"")+(e.useHTML?"highcharts-tracker":""))),p.attr(x),p.css(C).shadow(e.shadow),p.added||p.add(w),b.alignDataLabel(f,p,e,null,z)):(f.dataLabel=p=p.destroy(),r&&(f.connector=r.destroy()))})};h.prototype.alignDataLabel=function(a,b,d,e,h){var c=this.chart,k=c.inverted,l=u(a.dlBox&&a.dlBox.centerX,a.plotX,-9999),m=u(a.plotY,-9999),n=b.getBBox(),p,q=d.rotation,r=d.align,w=this.visible&&(a.series.forceDL||c.isInsidePlot(l,Math.round(m),k)||e&&c.isInsidePlot(l,k?e.x+1:e.y+e.height-1,k)),z="justify"===u(d.overflow, +"justify");if(w&&(p=d.style.fontSize,p=c.renderer.fontMetrics(p,b).b,e=f({x:k?this.yAxis.len-m:l,y:Math.round(k?this.xAxis.len-l:m),width:0,height:0},e),f(d,{width:n.width,height:n.height}),q?(z=!1,l=c.renderer.rotCorr(p,q),l={x:e.x+d.x+e.width/2+l.x,y:e.y+d.y+{top:0,middle:.5,bottom:1}[d.verticalAlign]*e.height},b[h?"attr":"animate"](l).attr({align:r}),m=(q+720)%360,m=180m,"left"===r?l.y-=m?n.height:0:"center"===r?(l.x-=n.width/2,l.y-=n.height/2):"right"===r&&(l.x-=n.width,l.y-=m?0:n.height)): +(b.align(d,null,e),l=b.alignAttr),z?a.isLabelJustified=this.justifyDataLabel(b,d,l,n,e,h):u(d.crop,!0)&&(w=c.isInsidePlot(l.x,l.y)&&c.isInsidePlot(l.x+n.width,l.y+n.height)),d.shape&&!q))b[h?"attr":"animate"]({anchorX:k?c.plotWidth-a.plotY:a.plotX,anchorY:k?c.plotHeight-a.plotX:a.plotY});w||(b.attr({y:-9999}),b.placed=!1)};h.prototype.justifyDataLabel=function(a,b,d,e,f,h){var c=this.chart,k=b.align,l=b.verticalAlign,m,n,p=a.box?0:a.padding||0;m=d.x+p;0>m&&("right"===k?b.align="left":b.x=-m,n=!0); +m=d.x+e.width-p;m>c.plotWidth&&("left"===k?b.align="right":b.x=c.plotWidth-m,n=!0);m=d.y+p;0>m&&("bottom"===l?b.verticalAlign="top":b.y=-m,n=!0);m=d.y+e.height-p;m>c.plotHeight&&("top"===l?b.verticalAlign="bottom":b.y=c.plotHeight-m,n=!0);n&&(a.placed=!h,a.align(b,null,f));return n};m.pie&&(m.pie.prototype.drawDataLabels=function(){var c=this,b=c.data,d,e=c.chart,f=c.options.dataLabels,l=u(f.connectorPadding,10),m=u(f.connectorWidth,1),n=e.plotWidth,t=e.plotHeight,r,w=c.center,q=w[2]/2,A=w[1],F,G, +g,v,E=[[],[]],L,P,J,M,y=[0,0,0,0];c.visible&&(f.enabled||c._hasPointLabels)&&(p(b,function(a){a.dataLabel&&a.visible&&a.dataLabel.shortened&&(a.dataLabel.attr({width:"auto"}).css({width:"auto",textOverflow:"clip"}),a.dataLabel.shortened=!1)}),h.prototype.drawDataLabels.apply(c),p(b,function(a){a.dataLabel&&a.visible&&(E[a.half].push(a),a.dataLabel._pos=null)}),p(E,function(b,h){var k,m,x=b.length,r=[],z;if(x)for(c.sortByAngle(b,h-.5),0d.bottom-2?k:P,h,d),F._attr={visibility:J,align:g[6]},F._pos={x:L+f.x+({left:l,right:-l}[g[6]]||0),y:P+f.y-10},g.x=L,g.y=P,u(f.crop,!0)&&(G=F.getBBox().width,k=null,L-Gn-l&&(k=Math.round(L+G-n+l),y[1]=Math.max(k,y[1])),0>P-v/2?y[0]=Math.max(Math.round(-P+v/2),y[0]):P+v/2>t&&(y[2]=Math.max(Math.round(P+v/2-t),y[2])),F.sideOverflow=k)}),0===D(y)||this.verifyDataLabelOverflow(y))&&(this.placeDataLabels(), +m&&p(this.points,function(a){var b;r=a.connector;if((F=a.dataLabel)&&F._pos&&a.visible&&0u(this.translatedThreshold,k.yAxis.len)),p=u(d.inside,!!this.options.stacking);l&&(e=n(l),0>e.y&&(e.height+=e.y,e.y=0),l=e.y+e.height-k.yAxis.len,0a+c||e+hb+d||f+lthis.pointCount))},pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&r(d,function(a){a.setState()});r("xy"===b?[1,0]:[1],function(b){b= +c[b?"xAxis":"yAxis"][0];var d=b.horiz,f=a[d?"chartX":"chartY"],d=d?"mouseDownX":"mouseDownY",h=c[d],g=(b.pointRange||0)/2,k=b.getExtremes(),l=b.toValue(h-f,!0)+g,m=b.toValue(h+b.len-f,!0)-g,n=m=l(n.minWidth,0)&&this.chartHeight>=l(n.minHeight,0)}).call(this)&&f.push(a._id)};E.prototype.currentOptions=function(l){function n(e,h,l,d){var c;a.objectEach(e,function(a,e){if(!d&&-1 Date: Fri, 4 Jan 2019 05:15:13 +0000 Subject: [PATCH 258/267] Auto corrected by following Format Javascript Code --- app/assets/javascripts/highcharts.js | 11651 ++++++++++++++++++++++++- 1 file changed, 11269 insertions(+), 382 deletions(-) diff --git a/app/assets/javascripts/highcharts.js b/app/assets/javascripts/highcharts.js index 9554ef58b..c7136bafe 100644 --- a/app/assets/javascripts/highcharts.js +++ b/app/assets/javascripts/highcharts.js @@ -5,385 +5,11272 @@ License: www.highcharts.com/license */ -(function(S,M){"object"===typeof module&&module.exports?module.exports=S.document?M(S):M:S.Highcharts=M(S)})("undefined"!==typeof window?window:this,function(S){var M=function(){var a="undefined"===typeof S?window:S,E=a.document,D=a.navigator&&a.navigator.userAgent||"",H=E&&E.createElementNS&&!!E.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,p=/(edge|msie|trident)/i.test(D)&&!a.opera,f=/Firefox/.test(D),l=f&&4>parseInt(D.split("Firefox/")[1],10);return a.Highcharts?a.Highcharts.error(16, -!0):{product:"Highcharts",version:"6.0.4",deg2rad:2*Math.PI/360,doc:E,hasBidiBug:l,hasTouch:E&&void 0!==E.documentElement.ontouchstart,isMS:p,isWebKit:/AppleWebKit/.test(D),isFirefox:f,isTouchDevice:/(Mobile|Android|Windows Phone)/.test(D),SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:H,win:a,marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){},charts:[]}}();(function(a){a.timers=[];var E=a.charts,D=a.doc,H=a.win;a.error=function(p, -f){p=a.isNumber(p)?"Highcharts error #"+p+": www.highcharts.com/errors/"+p:p;if(f)throw Error(p);H.console&&console.log(p)};a.Fx=function(a,f,l){this.options=f;this.elem=a;this.prop=l};a.Fx.prototype={dSetter:function(){var a=this.paths[0],f=this.paths[1],l=[],r=this.now,n=a.length,w;if(1===r)l=this.toD;else if(n===f.length&&1>r)for(;n--;)w=parseFloat(a[n]),l[n]=isNaN(w)?f[n]:r*parseFloat(f[n]-w)+w;else l=f;this.elem.attr("d",l,null,!0)},update:function(){var a=this.elem,f=this.prop,l=this.now,r= -this.options.step;if(this[f+"Setter"])this[f+"Setter"]();else a.attr?a.element&&a.attr(f,l,null,!0):a.style[f]=l+this.unit;r&&r.call(a,l,this)},run:function(p,f,l){var r=this,n=r.options,w=function(a){return w.stopped?!1:r.step(a)},u=H.requestAnimationFrame||function(a){setTimeout(a,13)},e=function(){for(var h=0;h=u+this.startTime?(this.now=this.end,this.pos=1,this.update(),l=e[this.prop]=!0,a.objectEach(e,function(a){!0!==a&&(l=!1)}),l&&w&&w.call(n),p=!1):(this.pos=r.easing((f-this.startTime)/u),this.now=this.start+(this.end- -this.start)*this.pos,this.update(),p=!0);return p},initPath:function(p,f,l){function r(a){var b,c;for(k=a.length;k--;)b="M"===a[k]||"L"===a[k],c=/[a-zA-Z]/.test(a[k+3]),b&&c&&a.splice(k+1,0,a[k+1],a[k+2],a[k+1],a[k+2])}function n(a,b){for(;a.lengtha&&-Infinityw?"AM":"PM",P:12>w?"am":"pm",S:k(n.getSeconds()),L:k(Math.round(f%1E3),3)},a.dateFormats);a.objectEach(r,function(a,b){for(;-1!==p.indexOf("%"+b);)p=p.replace("%"+b,"function"===typeof a?a(f):a)});return l?p.substr(0,1).toUpperCase()+p.substr(1):p};a.formatSingle=function(p,f){var l=/\.([0-9])/,r=a.defaultOptions.lang;/f$/.test(p)?(l=(l=p.match(l))?l[1]:-1,null!==f&&(f=a.numberFormat(f,l,r.decimalPoint,-1=l&&(f=[1/l])));for(r=0;r=p||!n&&w<=(f[r]+(f[r+1]||f[r]))/2);r++);return u=a.correctFloat(u*l,-Math.round(Math.log(.001)/Math.LN10))};a.stableSort=function(a,f){var l=a.length,p,n;for(n=0;nl&&(l=a[f]);return l};a.destroyObjectProperties=function(p,f){a.objectEach(p,function(a,r){a&&a!==f&&a.destroy&&a.destroy();delete p[r]})};a.discardElement=function(p){var f=a.garbageBin;f||(f=a.createElement("div"));p&&f.appendChild(p);f.innerHTML=""};a.correctFloat=function(a,f){return parseFloat(a.toPrecision(f||14))};a.setAnimation=function(p,f){f.renderer.globalAnimation=a.pick(p,f.options.chart.animation, -!0)};a.animObject=function(p){return a.isObject(p)?a.merge(p):{duration:p?500:0}};a.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5,month:24192E5,year:314496E5};a.numberFormat=function(p,f,l,r){p=+p||0;f=+f;var n=a.defaultOptions.lang,w=(p.toString().split(".")[1]||"").split("e")[0].length,u,e,h=p.toString().split("e");-1===f?f=Math.min(w,20):a.isNumber(f)?f&&h[1]&&0>h[1]&&(u=f+ +h[1],0<=u?(h[0]=(+h[0]).toExponential(u).split("e")[0],f=u):(h[0]=h[0].split(".")[0]||0, -p=20>f?(h[0]*Math.pow(10,h[1])).toFixed(f):0,h[1]=0)):f=2;e=(Math.abs(h[1]?h[0]:p)+Math.pow(10,-Math.max(f,w)-1)).toFixed(f);w=String(a.pInt(e));u=3p?"-":"")+(u?w.substr(0,u)+r:"");p+=w.substr(u).replace(/(\d{3})(?=\d)/g,"$1"+r);f&&(p+=l+e.slice(-f));h[1]&&0!==+p&&(p+="e"+h[1]);return p};Math.easeInOutSine=function(a){return-.5*(Math.cos(Math.PI*a)-1)};a.getStyle=function(p,f,l){if("width"===f)return Math.min(p.offsetWidth, -p.scrollWidth)-a.getStyle(p,"padding-left")-a.getStyle(p,"padding-right");if("height"===f)return Math.min(p.offsetHeight,p.scrollHeight)-a.getStyle(p,"padding-top")-a.getStyle(p,"padding-bottom");H.getComputedStyle||a.error(27,!0);if(p=H.getComputedStyle(p,void 0))p=p.getPropertyValue(f),a.pick(l,"opacity"!==f)&&(p=a.pInt(p));return p};a.inArray=function(p,f){return(a.indexOfPolyfill||Array.prototype.indexOf).call(f,p)};a.grep=function(p,f){return(a.filterPolyfill||Array.prototype.filter).call(p, -f)};a.find=Array.prototype.find?function(a,f){return a.find(f)}:function(a,f){var l,r=a.length;for(l=0;l>16,(l&65280)>> -8,l&255,1]:4===f&&(n=[(l&3840)>>4|(l&3840)>>8,(l&240)>>4|l&240,(l&15)<<4|l&15,1])),!n)for(w=this.parsers.length;w--&&!n;)u=this.parsers[w],(f=u.regex.exec(l))&&(n=u.parse(f));this.rgba=n||[]},get:function(a){var f=this.input,n=this.rgba,l;this.stops?(l=p(f),l.stops=[].concat(l.stops),E(this.stops,function(n,e){l.stops[e]=[l.stops[e][0],n.get(a)]})):l=n&&D(n[0])?"rgb"===a||!a&&1===n[3]?"rgb("+n[0]+","+n[1]+","+n[2]+")":"a"===a?n[3]:"rgba("+n.join(",")+")":f;return l},brighten:function(a){var l,n=this.rgba; -if(this.stops)E(this.stops,function(n){n.brighten(a)});else if(D(a)&&0!==a)for(l=0;3>l;l++)n[l]+=f(255*a),0>n[l]&&(n[l]=0),255y.width)y={width:0,height:0}}else y=this.htmlGetBBox();b.isSVG&& -(a=y.width,b=y.height,q&&"11px"===q.fontSize&&17===Math.round(b)&&(y.height=b=14),g&&(y.width=Math.abs(b*Math.sin(v))+Math.abs(a*Math.cos(v)),y.height=Math.abs(b*Math.cos(v))+Math.abs(a*Math.sin(v))));if(A&&0]*>/g,"")))},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,g,b){"string"===typeof a?b.setAttribute(g,a):a&&this.colorGradient(a,g,b)},visibilitySetter:function(a,g,b){"inherit"===a?b.removeAttribute(g):this[g]!==a&&b.setAttribute(g,a);this[g]=a},zIndexSetter:function(a,b){var v=this.renderer,y=this.parentGroup,c=(y||v).element||v.box,k,d=this.element,q,e,v=c===v.box;k=this.added;var z;u(a)&& -(d.zIndex=a,a=+a,this[b]===a&&(k=!1),this[b]=a);if(k){(a=this.zIndex)&&y&&(y.handleZ=!0);b=c.childNodes;for(z=b.length-1;0<=z&&!q;z--)if(y=b[z],k=y.zIndex,e=!u(k),y!==d)if(0>a&&e&&!v&&!z)c.insertBefore(d,b[z]),q=!0;else if(g(k)<=a||e&&(!u(a)||0<=a))c.insertBefore(d,b[z+1]||null),q=!0;q||(c.insertBefore(d,b[v?3:0]||null),q=!0)}return q},_defaultSetter:function(a,g,b){b.setAttribute(g,a)}});E.prototype.yGetter=E.prototype.xGetter;E.prototype.translateXSetter=E.prototype.translateYSetter=E.prototype.rotationSetter= -E.prototype.verticalAlignSetter=E.prototype.rotationOriginXSetter=E.prototype.rotationOriginYSetter=E.prototype.scaleXSetter=E.prototype.scaleYSetter=E.prototype.matrixSetter=function(a,g){this[g]=a;this.doTransform=!0};E.prototype["stroke-widthSetter"]=E.prototype.strokeSetter=function(a,g,b){this[g]=a;this.stroke&&this["stroke-width"]?(E.prototype.fillSetter.call(this,this.stroke,"stroke",b),b.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0):"stroke-width"===g&&0===a&&this.hasStroke&& -(b.removeAttribute("stroke"),this.hasStroke=!1)};D=a.SVGRenderer=function(){this.init.apply(this,arguments)};c(D.prototype,{Element:E,SVG_NS:P,init:function(a,g,b,v,c,k){var y;v=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"}).css(this.getStyle(v));y=v.element;a.appendChild(y);f(a,"dir","ltr");-1===a.innerHTML.indexOf("xmlns")&&f(y,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=y;this.boxWrapper=v;this.alignedObjects=[];this.url=(x||N)&&m.getElementsByTagName("base").length? -R.location.href.replace(/#.*?$/,"").replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(m.createTextNode("Created with Highcharts 6.0.4"));this.defs=this.createElement("defs").add();this.allowHTML=k;this.forExport=c;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(g,b,!1);var d;x&&a.getBoundingClientRect&&(g=function(){n(a,{left:0,top:0});d=a.getBoundingClientRect();n(a,{left:Math.ceil(d.left)- -d.left+"px",top:Math.ceil(d.top)-d.top+"px"})},g(),this.unSubPixelFix=H(R,"resize",g))},getStyle:function(a){return this.style=c({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},setStyle:function(a){this.boxWrapper.css(this.getStyle(a))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();h(this.gradients||{});this.gradients=null;a&&(this.defs=a.destroy()); -this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(a){var g=new this.Element;g.init(this,a);return g},draw:A,getRadialAttr:function(a,g){return{cx:a[0]-a[2]/2+g.cx*a[2],cy:a[1]-a[2]/2+g.cy*a[2],r:g.r*a[2]}},getSpanWidth:function(a,g){var b=a.getBBox(!0).width;!L&&this.forExport&&(b=this.measureSpanWidth(g.firstChild.data,a.styles));return b},applyEllipsis:function(a,g,b,v){var c=a.rotation,y=b,k,d=0,q=b.length,e=function(a){g.removeChild(g.firstChild); -a&&g.appendChild(m.createTextNode(a))},z;a.rotation=0;y=this.getSpanWidth(a,g);if(z=y>v){for(;d<=q;)k=Math.ceil((d+q)/2),y=b.substring(0,k)+"\u2026",e(y),y=this.getSpanWidth(a,g),d===q?d=q+1:y>v?q=k-1:d=k;0===q&&e("")}a.rotation=c;return z},escapes:{"\x26":"\x26amp;","\x3c":"\x26lt;","\x3e":"\x26gt;","'":"\x26#39;",'"':"\x26quot;"},buildText:function(a){var b=a.element,v=this,c=v.forExport,y=G(a.textStr,"").toString(),q=-1!==y.indexOf("\x3c"),e=b.childNodes,z,h,A,J,t=f(b,"x"),x=a.styles,B=a.textWidth, -l=x&&x.lineHeight,C=x&&x.textOutline,u=x&&"ellipsis"===x.textOverflow,Q=x&&"nowrap"===x.whiteSpace,w=x&&x.fontSize,R,I,r=e.length,x=B&&!a.added&&this.box,p=function(a){var c;c=/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:w||v.style.fontSize||12;return l?g(l):v.fontMetrics(c,a.getAttribute("style")?a:b).h},K=function(a){F(v.escapes,function(g,b){a=a.replace(new RegExp(g,"g"),b)});return a};R=[y,u,Q,l,C,w,B].join();if(R!==a.textCache){for(a.textCache=R;r--;)b.removeChild(e[r]);q||C||u||B|| --1!==y.indexOf(" ")?(z=/<.*class="([^"]+)".*>/,h=/<.*style="([^"]+)".*>/,A=/<.*href="([^"]+)".*>/,x&&x.appendChild(b),y=q?y.replace(/<(b|strong)>/g,'\x3cspan style\x3d"font-weight:bold"\x3e').replace(/<(i|em)>/g,'\x3cspan style\x3d"font-style:italic"\x3e').replace(//g,"\x3c/span\x3e").split(//g):[y],y=k(y,function(a){return""!==a}),d(y,function(g,y){var k,q=0;g=g.replace(/^\s+|\s+$/g,"").replace(//g,"\x3c/span\x3e|||"); -k=g.split("|||");d(k,function(g){if(""!==g||1===k.length){var d={},e=m.createElementNS(v.SVG_NS,"tspan"),x,F;z.test(g)&&(x=g.match(z)[1],f(e,"class",x));h.test(g)&&(F=g.match(h)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),f(e,"style",F));A.test(g)&&!c&&(f(e,"onclick",'location.href\x3d"'+g.match(A)[1]+'"'),f(e,"class","highcharts-anchor"),n(e,{cursor:"pointer"}));g=K(g.replace(/<[a-zA-Z\/](.|\n)*?>/g,"")||" ");if(" "!==g){e.appendChild(m.createTextNode(g));q?d.dx=0:y&&null!==t&&(d.x=t);f(e,d);b.appendChild(e); -!q&&I&&(!L&&c&&n(e,{display:"block"}),f(e,"dy",p(e)));if(B){d=g.replace(/([^\^])-/g,"$1- ").split(" ");x=1B,void 0===J&&(J=g),g&&1!==d.length?(e.removeChild(e.firstChild),O.unshift(d.pop())):(d=O,O=[],d.length&&!Q&&(e=m.createElementNS(P,"tspan"),f(e,{dy:C,x:t}),F&&f(e,"style",F),b.appendChild(e)),l>B&&(B=l)),d.length&&e.appendChild(m.createTextNode(d.join(" ").replace(/- /g, -"-")));a.rotation=G}q++}}});I=I||b.childNodes.length}),J&&a.attr("title",a.textStr),x&&x.removeChild(b),C&&a.applyTextOutline&&a.applyTextOutline(C)):b.appendChild(m.createTextNode(K(y)))}},getContrast:function(a){a=r(a).rgba;return 510Math.abs(c.end-c.start-2*Math.PI));var y=Math.cos(k),z=Math.sin(k),h=Math.cos(e),e=Math.sin(e);c=.001>c.end-k-Math.PI?0:1;d=["M",a+d*y,g+q*z,"A",d,q,0,c,1,a+d*h,g+q*e];u(b)&&d.push(v?"M":"L",a+b* -h,g+b*e,"A",b,b,0,c,0,a+b*y,g+b*z);d.push(v?"":"Z");return d},callout:function(a,g,b,v,c){var d=Math.min(c&&c.r||0,b,v),k=d+6,q=c&&c.anchorX;c=c&&c.anchorY;var e;e=["M",a+d,g,"L",a+b-d,g,"C",a+b,g,a+b,g,a+b,g+d,"L",a+b,g+v-d,"C",a+b,g+v,a+b,g+v,a+b-d,g+v,"L",a+d,g+v,"C",a,g+v,a,g+v,a,g+v-d,"L",a,g+d,"C",a,g,a,g,a+d,g];q&&q>b?c>g+k&&cq?c>g+k&&cv&&q>a+k&&qc&&q>a+k&&qa?a+3:Math.round(1.2*a);return{h:b,b:Math.round(.8* -b),f:a}},rotCorr:function(a,g,b){var v=a;g&&b&&(v=Math.max(v*Math.cos(g*e),4));return{x:-a/3*Math.sin(g*e),y:v}},label:function(g,b,k,e,z,h,m,A,L){var y=this,J=y.g("button"!==L&&"label"),t=J.text=y.text("",0,0,m).attr({zIndex:1}),x,F,n=0,B=3,l=0,C,f,Q,G,w,R={},I,P,r=/^url\((.*?)\)$/.test(e),p=r,K,O,N,T;L&&J.addClass("highcharts-"+L);p=r;K=function(){return(I||0)%2/2};O=function(){var a=t.element.style,g={};F=(void 0===C||void 0===f||w)&&u(t.textStr)&&t.getBBox();J.width=(C||F.width||0)+2*B+l;J.height= -(f||F.height||0)+2*B;P=B+y.fontMetrics(a&&a.fontSize,t).b;p&&(x||(J.box=x=y.symbols[e]||r?y.symbol(e):y.rect(),x.addClass(("button"===L?"":"highcharts-label-box")+(L?" highcharts-"+L+"-box":"")),x.add(J),a=K(),g.x=a,g.y=(A?-P:0)+a),g.width=Math.round(J.width),g.height=Math.round(J.height),x.attr(c(g,R)),R={})};N=function(){var a=l+B,g;g=A?0:P;u(C)&&F&&("center"===w||"right"===w)&&(a+={center:.5,right:1}[w]*(C-F.width));if(a!==t.x||g!==t.y)t.attr("x",a),void 0!==g&&t.attr("y",g);t.x=a;t.y=g};T=function(a, -g){x?x.attr(a,g):R[a]=g};J.onAdd=function(){t.add(J);J.attr({text:g||0===g?g:"",x:b,y:k});x&&u(z)&&J.attr({anchorX:z,anchorY:h})};J.widthSetter=function(g){C=a.isNumber(g)?g:null};J.heightSetter=function(a){f=a};J["text-alignSetter"]=function(a){w=a};J.paddingSetter=function(a){u(a)&&a!==B&&(B=J.padding=a,N())};J.paddingLeftSetter=function(a){u(a)&&a!==l&&(l=a,N())};J.alignSetter=function(a){a={left:0,center:.5,right:1}[a];a!==n&&(n=a,F&&J.attr({x:Q}))};J.textSetter=function(a){void 0!==a&&t.textSetter(a); -O();N()};J["stroke-widthSetter"]=function(a,g){a&&(p=!0);I=this["stroke-width"]=a;T(g,a)};J.strokeSetter=J.fillSetter=J.rSetter=function(a,g){"r"!==g&&("fill"===g&&a&&(p=!0),J[g]=a);T(g,a)};J.anchorXSetter=function(a,g){z=J.anchorX=a;T(g,Math.round(a)-K()-Q)};J.anchorYSetter=function(a,g){h=J.anchorY=a;T(g,a-G)};J.xSetter=function(a){J.x=a;n&&(a-=n*((C||F.width)+2*B));Q=Math.round(a);J.attr("translateX",Q)};J.ySetter=function(a){G=J.y=Math.round(a);J.attr("translateY",G)};var U=J.css;return c(J,{css:function(a){if(a){var g= -{};a=q(a);d(J.textProps,function(b){void 0!==a[b]&&(g[b]=a[b],delete a[b])});t.css(g)}return U.call(J,a)},getBBox:function(){return{width:F.width+2*B,height:F.height+2*B,x:F.x-B,y:F.y-B}},shadow:function(a){a&&(O(),x&&x.shadow(a));return J},destroy:function(){v(J.element,"mouseenter");v(J.element,"mouseleave");t&&(t=t.destroy());x&&(x=x.destroy());E.prototype.destroy.call(J);J=y=O=N=T=null}})}});a.Renderer=D})(M);(function(a){var E=a.attr,D=a.createElement,H=a.css,p=a.defined,f=a.each,l=a.extend, -r=a.isFirefox,n=a.isMS,w=a.isWebKit,u=a.pick,e=a.pInt,h=a.SVGRenderer,m=a.win,d=a.wrap;l(a.SVGElement.prototype,{htmlCss:function(a){var b=this.element;if(b=a&&"SPAN"===b.tagName&&a.width)delete a.width,this.textWidth=b,this.updateTransform();a&&"ellipsis"===a.textOverflow&&(a.whiteSpace="nowrap",a.overflow="hidden");this.styles=l(this.styles,a);H(this.element,a);return this},htmlGetBBox:function(){var a=this.element;return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}, -htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,d=this.translateX||0,z=this.translateY||0,h=this.x||0,m=this.y||0,x=this.textAlign||"left",n={left:0,center:.5,right:1}[x],t=this.styles;H(b,{marginLeft:d,marginTop:z});this.shadows&&f(this.shadows,function(a){H(a,{marginLeft:d+1,marginTop:z+1})});this.inverted&&f(b.childNodes,function(c){a.invertChild(c,b)});if("SPAN"===b.tagName){var l=this.rotation,u=e(this.textWidth),q=t&&t.whiteSpace,A=[l,x,b.innerHTML,this.textWidth, -this.textAlign].join();A!==this.cTT&&(t=a.fontMetrics(b.style.fontSize).b,p(l)&&this.setSpanRotation(l,n,t),H(b,{width:"",whiteSpace:q||"nowrap"}),b.offsetWidth>u&&/[ \-]/.test(b.textContent||b.innerText)&&H(b,{width:u+"px",display:"block",whiteSpace:q||"normal"}),this.getSpanCorrection(b.offsetWidth,t,n,l,x));H(b,{left:h+(this.xCorr||0)+"px",top:m+(this.yCorr||0)+"px"});w&&(t=b.offsetHeight);this.cTT=A}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,d){var c={},k=this.renderer.getTransformKey(); -c[k]=c.transform="rotate("+a+"deg)";c[k+(r?"Origin":"-origin")]=c.transformOrigin=100*b+"% "+d+"px";H(this.element,c)},getSpanCorrection:function(a,b,d){this.xCorr=-a*d;this.yCorr=-b}});l(h.prototype,{getTransformKey:function(){return n&&!/Edge/.test(m.navigator.userAgent)?"-ms-transform":w?"-webkit-transform":r?"MozTransform":m.opera?"-o-transform":""},html:function(a,b,k){var c=this.createElement("span"),e=c.element,h=c.renderer,m=h.isSVG,w=function(a,b){f(["opacity","visibility"],function(c){d(a, -c+"Setter",function(a,c,d,k){a.call(this,c,d,k);b[d]=c})})};c.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;this.textStr=a;e.innerHTML=u(a,"");c.htmlUpdateTransform()};m&&w(c,c.element.style);c.xSetter=c.ySetter=c.alignSetter=c.rotationSetter=function(a,b){"align"===b&&(b="textAlign");c[b]=a;c.htmlUpdateTransform()};c.attr({text:a,x:Math.round(b),y:Math.round(k)}).css({fontFamily:this.style.fontFamily,fontSize:this.style.fontSize,position:"absolute"});e.style.whiteSpace="nowrap";c.css= -c.htmlCss;m&&(c.add=function(a){var b,d=h.box.parentNode,k=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)k.push(a),a=a.parentGroup;f(k.reverse(),function(a){function e(g,b){a[b]=g;n?q[h.getTransformKey()]="translate("+(a.x||a.translateX)+"px,"+(a.y||a.translateY)+"px)":"translateX"===b?q.left=g+"px":q.top=g+"px";a.doTransform=!0}var q,g=E(a.element,"class");g&&(g={className:g});b=a.div=a.div||D("div",g,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px",display:a.display, -opacity:a.opacity,pointerEvents:a.styles&&a.styles.pointerEvents},b||d);q=b.style;l(a,{classSetter:function(a){return function(g){this.element.setAttribute("class",g);a.className=g}}(b),on:function(){k[0].div&&c.on.apply({element:k[0].div},arguments);return a},translateXSetter:e,translateYSetter:e});w(a,q)})}}else b=d;b.appendChild(e);c.added=!0;c.alignOnAdd&&c.htmlUpdateTransform();return c});return c}})})(M);(function(a){function E(){var n=a.defaultOptions.global,l=r.moment;if(n.timezone){if(l)return function(a){return-l.tz(a, -n.timezone).utcOffset()};a.error(25)}return n.useUTC&&n.getTimezoneOffset}function D(){var n=a.defaultOptions.global,f,u=n.useUTC,e=u?"getUTC":"get",h=u?"setUTC":"set",m="Minutes Hours Day Date Month FullYear".split(" "),d=m.concat(["Milliseconds","Seconds"]);a.Date=f=n.Date||r.Date;f.hcTimezoneOffset=u&&n.timezoneOffset;f.hcGetTimezoneOffset=E();f.hcHasTimeZone=!(!f.hcTimezoneOffset&&!f.hcGetTimezoneOffset);f.hcMakeTime=function(a,b,d,e,h,m){var c;u?(c=f.UTC.apply(0,arguments),c+=p(c)):c=(new f(a, -b,l(d,1),l(e,0),l(h,0),l(m,0))).getTime();return c};for(n=0;nb&&e-k*zm&&(p=Math.round((h-e)/Math.cos(b*r)));else if(h=e+(1-k)*z,e-k*zm&&(I=m-a.x+I*k,x=-1),I=Math.min(B,I),II||f.autoRotation&&(c.styles||{}).width)p=I;p&&(t.width=p,(n.style||{}).textOverflow||(t.textOverflow="ellipsis"),c.css(t))},getPosition:function(a,f,l,e){var h=this.axis,m=h.chart,d=e&&m.oldChartHeight||m.chartHeight;return{x:a?h.translate(f+l,null,null,e)+h.transB:h.left+h.offset+(h.opposite?(e&&m.oldChartWidth||m.chartWidth)-h.right-h.left:0),y:a?d-h.bottom+h.offset-(h.opposite?h.height:0):d-h.translate(f+l,null,null,e)-h.transB}},getLabelPosition:function(a, -f,l,e,h,m,d,c){var b=this.axis,k=b.transA,z=b.reversed,B=b.staggerLines,n=b.tickRotCorr||{x:0,y:0},x=h.y,u=e||b.reserveSpaceDefault?0:-b.labelOffset*("center"===b.labelAlign?.5:1);D(x)||(x=0===b.side?l.rotation?-8:-l.getBBox().height:2===b.side?n.y+8:Math.cos(l.rotation*r)*(n.y-l.getBBox(!1,0).height/2));a=a+h.x+u+n.x-(m&&e?m*k*(z?-1:1):0);f=f+x-(m&&!e?m*k*(z?1:-1):0);B&&(l=d/(c||1)%B,b.opposite&&(l=B-l-1),f+=b.labelOffset/B*l);return{x:a,y:Math.round(f)}},getMarkPath:function(a,f,l,e,h,m){return m.crispLine(["M", -a,f,"L",a+(h?0:-l),f+(h?l:0)],e)},renderGridLine:function(a,f,l){var e=this.axis,h=e.options,m=this.gridLine,d={},c=this.pos,b=this.type,k=e.tickmarkOffset,z=e.chart.renderer,B=b?b+"Grid":"grid",n=h[B+"LineWidth"],x=h[B+"LineColor"],h=h[B+"LineDashStyle"];m||(d.stroke=x,d["stroke-width"]=n,h&&(d.dashstyle=h),b||(d.zIndex=1),a&&(d.opacity=0),this.gridLine=m=z.path().attr(d).addClass("highcharts-"+(b?b+"-":"")+"grid-line").add(e.gridGroup));if(!a&&m&&(a=e.getPlotLinePath(c+k,m.strokeWidth()*l,a,!0)))m[this.isNew? -"attr":"animate"]({d:a,opacity:f})},renderMark:function(a,f,u){var e=this.axis,h=e.options,m=e.chart.renderer,d=this.type,c=d?d+"Tick":"tick",b=e.tickSize(c),k=this.mark,z=!k,B=a.x;a=a.y;var n=l(h[c+"Width"],!d&&e.isXAxis?1:0),h=h[c+"Color"];b&&(e.opposite&&(b[0]=-b[0]),z&&(this.mark=k=m.path().addClass("highcharts-"+(d?d+"-":"")+"tick").add(e.axisGroup),k.attr({stroke:h,"stroke-width":n})),k[z?"attr":"animate"]({d:this.getMarkPath(B,a,b[0],k.strokeWidth()*u,e.horiz,m),opacity:f}))},renderLabel:function(a, -f,u,e){var h=this.axis,m=h.horiz,d=h.options,c=this.label,b=d.labels,k=b.step,h=h.tickmarkOffset,z=!0,B=a.x;a=a.y;c&&p(B)&&(c.xy=a=this.getLabelPosition(B,a,c,m,b,h,e,k),this.isFirst&&!this.isLast&&!l(d.showFirstLabel,1)||this.isLast&&!this.isFirst&&!l(d.showLastLabel,1)?z=!1:!m||b.step||b.rotation||f||0===u||this.handleOverflow(a),k&&e%k&&(z=!1),z&&p(a.y)?(a.opacity=u,c[this.isNewLabel?"attr":"animate"](a),this.isNewLabel=!1):(c.attr("y",-9999),this.isNewLabel=!0))},render:function(a,f,u){var e= -this.axis,h=e.horiz,m=this.getPosition(h,this.pos,e.tickmarkOffset,f),d=m.x,c=m.y,e=h&&d===e.pos+e.len||!h&&c===e.pos?-1:1;u=l(u,1);this.isActive=!0;this.renderGridLine(f,u,e);this.renderMark(m,u,e);this.renderLabel(m,f,u,a);this.isNew=!1},destroy:function(){H(this,this.axis)}}})(M);var V=function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.color,l=a.correctFloat,r=a.defaultOptions,n=a.defined,w=a.deg2rad,u=a.destroyObjectProperties,e=a.each,h=a.extend,m=a.fireEvent,d=a.format, -c=a.getMagnitude,b=a.grep,k=a.inArray,z=a.isArray,B=a.isNumber,I=a.isString,x=a.merge,K=a.normalizeTickInterval,t=a.objectEach,C=a.pick,N=a.removeEvent,q=a.splat,A=a.syncTimeout,F=a.Tick,G=function(){this.init.apply(this,arguments)};a.extend(G.prototype,{defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,labels:{enabled:!0,style:{color:"#666666",cursor:"default",fontSize:"11px"}, -x:0},maxPadding:.01,minorTickLength:2,minorTickPosition:"outside",minPadding:.01,startOfWeek:1,startOnTick:!1,tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",title:{align:"middle",style:{color:"#666666"}},type:"linear",minorGridLineColor:"#f2f2f2",minorGridLineWidth:1,minorTickColor:"#999999",lineColor:"#ccd6eb",lineWidth:1,gridLineColor:"#e6e6e6",tickColor:"#ccd6eb"},defaultYAxisOptions:{endOnTick:!0,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8},maxPadding:.05, -minPadding:.05,startOnTick:!0,title:{rotation:270,text:"Values"},stackLabels:{allowOverlap:!1,enabled:!1,formatter:function(){return a.numberFormat(this.total,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"#000000",textOutline:"1px contrast"}},gridLineWidth:1,lineWidth:0},defaultLeftAxisOptions:{labels:{x:-15},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45], -x:0},title:{rotation:0}},init:function(a,b){var g=b.isX,v=this;v.chart=a;v.horiz=a.inverted&&!v.isZAxis?!g:g;v.isXAxis=g;v.coll=v.coll||(g?"xAxis":"yAxis");v.opposite=b.opposite;v.side=b.side||(v.horiz?v.opposite?0:2:v.opposite?1:3);v.setOptions(b);var c=this.options,d=c.type;v.labelFormatter=c.labels.formatter||v.defaultLabelFormatter;v.userOptions=b;v.minPixelPadding=0;v.reversed=c.reversed;v.visible=!1!==c.visible;v.zoomEnabled=!1!==c.zoomEnabled;v.hasNames="category"===d||!0===c.categories;v.categories= -c.categories||v.hasNames;v.names=v.names||[];v.plotLinesAndBandsGroups={};v.isLog="logarithmic"===d;v.isDatetimeAxis="datetime"===d;v.positiveValuesOnly=v.isLog&&!v.allowNegativeLog;v.isLinked=n(c.linkedTo);v.ticks={};v.labelEdge=[];v.minorTicks={};v.plotLinesAndBands=[];v.alternateBands={};v.len=0;v.minRange=v.userMinRange=c.minRange||c.maxZoom;v.range=c.range;v.offset=c.offset||0;v.stacks={};v.oldStacks={};v.stacksTouched=0;v.max=null;v.min=null;v.crosshair=C(c.crosshair,q(a.options.tooltip.crosshairs)[g? -0:1],!1);b=v.options.events;-1===k(v,a.axes)&&(g?a.axes.splice(a.xAxis.length,0,v):a.axes.push(v),a[v.coll].push(v));v.series=v.series||[];a.inverted&&!v.isZAxis&&g&&void 0===v.reversed&&(v.reversed=!0);t(b,function(a,g){E(v,g,a)});v.lin2log=c.linearToLogConverter||v.lin2log;v.isLog&&(v.val2lin=v.log2lin,v.lin2val=v.lin2log)},setOptions:function(a){this.options=x(this.defaultOptions,"yAxis"===this.coll&&this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions, -this.defaultLeftAxisOptions][this.side],x(r[this.coll],a))},defaultLabelFormatter:function(){var g=this.axis,b=this.value,c=g.categories,k=this.dateTimeLabelFormat,e=r.lang,q=e.numericSymbols,e=e.numericSymbolMagnitude||1E3,h=q&&q.length,m,z=g.options.labels.format,g=g.isLog?Math.abs(b):g.tickInterval;if(z)m=d(z,this);else if(c)m=b;else if(k)m=a.dateFormat(k,b);else if(h&&1E3<=g)for(;h--&&void 0===m;)c=Math.pow(e,h+1),g>=c&&0===10*b%c&&null!==q[h]&&0!==b&&(m=a.numberFormat(b/c,-1)+q[h]);void 0=== -m&&(m=1E4<=Math.abs(b)?a.numberFormat(b,-1):a.numberFormat(b,-1,void 0,""));return m},getSeriesExtremes:function(){var a=this,v=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.threshold=null;a.softThreshold=!a.isXAxis;a.buildStacks&&a.buildStacks();e(a.series,function(g){if(g.visible||!v.options.chart.ignoreHiddenSeries){var c=g.options,d=c.threshold,k;a.hasVisibleSeries=!0;a.positiveValuesOnly&&0>=d&&(d=null);if(a.isXAxis)c=g.xData,c.length&&(g=p(c),k=H(c),B(g)||g instanceof Date||(c=b(c,B), -g=p(c)),a.dataMin=Math.min(C(a.dataMin,c[0],g),g),a.dataMax=Math.max(C(a.dataMax,c[0],k),k));else if(g.getExtremes(),k=g.dataMax,g=g.dataMin,n(g)&&n(k)&&(a.dataMin=Math.min(C(a.dataMin,g),g),a.dataMax=Math.max(C(a.dataMax,k),k)),n(d)&&(a.threshold=d),!c.softThreshold||a.positiveValuesOnly)a.softThreshold=!1}})},translate:function(a,b,c,d,k,e){var g=this.linkedParent||this,v=1,q=0,h=d?g.oldTransA:g.transA;d=d?g.oldMin:g.min;var m=g.minPixelPadding;k=(g.isOrdinal||g.isBroken||g.isLog&&k)&&g.lin2val; -h||(h=g.transA);c&&(v*=-1,q=g.len);g.reversed&&(v*=-1,q-=v*(g.sector||g.len));b?(a=(a*v+q-m)/h+d,k&&(a=g.lin2val(a))):(k&&(a=g.val2lin(a)),a=B(d)?v*(a-d)*h+q+v*m+(B(e)?h*e:0):void 0);return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d,k){var g=this.chart,v=this.left,q=this.top,e,h,m=c&&g.oldChartHeight||g.chartHeight,z=c&&g.oldChartWidth|| -g.chartWidth,A;e=this.transB;var t=function(a,g,b){if(ab)d?a=Math.min(Math.max(g,a),b):A=!0;return a};k=C(k,this.translate(a,null,null,c));a=c=Math.round(k+e);e=h=Math.round(m-k-e);B(k)?this.horiz?(e=q,h=m-this.bottom,a=c=t(a,v,v+this.width)):(a=v,c=z-this.right,e=h=t(e,q,q+this.height)):(A=!0,d=!1);return A&&!d?null:g.renderer.crispLine(["M",a,e,"L",c,h],b||1)},getLinearTickPositions:function(a,b,c){var g,v=l(Math.floor(b/a)*a);c=l(Math.ceil(c/a)*a);var d=[],k;l(v+a)===v&&(k=20);if(this.single)return[b]; -for(b=v;b<=c;){d.push(b);b=l(b+a,k);if(b===g)break;g=b}return d},getMinorTickInterval:function(){var a=this.options;return!0===a.minorTicks?C(a.minorTickInterval,"auto"):!1===a.minorTicks?null:a.minorTickInterval},getMinorTickPositions:function(){var a=this,b=a.options,c=a.tickPositions,d=a.minorTickInterval,k=[],q=a.pointRangePadding||0,h=a.min-q,q=a.max+q,m=q-h;if(m&&m/d=this.minRange,t=this.minRange,d=(t-c+b)/2,d=[b-d,C(a.min,b-d)],k&&(d[2]=this.isLog?this.log2lin(this.dataMin):this.dataMin),b=H(d),c=[b+t,C(a.max,b+t)],k&&(c[2]=this.isLog?this.log2lin(this.dataMax):this.dataMax),c=p(c),c-b=p?(r=p,f=0):b.dataMax<=p&&(w=p,x=0)),b.min= -C(N,r,b.dataMin),b.max=C(D,w,b.dataMax));q&&(b.positiveValuesOnly&&!g&&0>=Math.min(b.min,C(b.dataMin,b.min))&&a.error(10,1),b.min=l(h(b.min),15),b.max=l(h(b.max),15));b.range&&n(b.max)&&(b.userMin=b.min=N=Math.max(b.dataMin,b.minFromRange()),b.userMax=D=b.max,b.range=null);m(b,"foundExtremes");b.beforePadding&&b.beforePadding();b.adjustForMinRange();!(G||b.axisPointRange||b.usePercentage||t)&&n(b.min)&&n(b.max)&&(h=b.max-b.min)&&(!n(N)&&f&&(b.min-=h*f),!n(D)&&x&&(b.max+=h*x));B(k.softMin)&&!B(b.userMin)&& -(b.min=Math.min(b.min,k.softMin));B(k.softMax)&&!B(b.userMax)&&(b.max=Math.max(b.max,k.softMax));B(k.floor)&&(b.min=Math.max(b.min,k.floor));B(k.ceiling)&&(b.max=Math.min(b.max,k.ceiling));I&&n(b.dataMin)&&(p=p||0,!n(N)&&b.min=p?b.min=p:!n(D)&&b.max>p&&b.dataMax<=p&&(b.max=p));b.tickInterval=b.min===b.max||void 0===b.min||void 0===b.max?1:t&&!F&&u===b.linkedParent.options.tickPixelInterval?F=b.linkedParent.tickInterval:C(F,this.tickAmount?(b.max-b.min)/Math.max(this.tickAmount-1,1): -void 0,G?1:(b.max-b.min)*u/Math.max(b.len,u));A&&!g&&e(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();b.postProcessTickInterval&&(b.tickInterval=b.postProcessTickInterval(b.tickInterval));b.pointRange&&!F&&(b.tickInterval=Math.max(b.pointRange,b.tickInterval));g=C(k.minTickInterval,b.isDatetimeAxis&&b.closestPointRange);!F&&b.tickIntervalb.tickInterval&&1E3b.max)),!!this.tickAmount));this.tickAmount||(b.tickInterval=b.unsquish());this.setTickPositions()},setTickPositions:function(){var a=this.options,b,c=a.tickPositions;b=this.getMinorTickInterval();var d=a.tickPositioner,k=a.startOnTick,q=a.endOnTick;this.tickmarkOffset=this.categories&&"between"===a.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===b&&this.tickInterval?this.tickInterval/ -5:b;this.single=this.min===this.max&&n(this.min)&&!this.tickAmount&&(parseInt(this.min,10)===this.min||!1!==a.allowDecimals);this.tickPositions=b=c&&c.slice();!b&&(b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),b.length>this.len&&(b= -[b[0],b.pop()],b[0]===b[1]&&(b.length=1)),this.tickPositions=b,d&&(d=d.apply(this,[this.min,this.max])))&&(this.tickPositions=b=d);this.paddedTicks=b.slice(0);this.trimTicks(b,k,q);this.isLinked||(this.single&&2>b.length&&(this.min-=.5,this.max+=.5),c||d||this.adjustTickAmount())},trimTicks:function(a,b,c){var g=a[0],d=a[a.length-1],k=this.minPointOffset||0;if(!this.isLinked){if(b&&-Infinity!==g)this.min=g;else for(;this.min-k>a[0];)a.shift();if(c)this.max=d;else for(;this.max+kb&&(this.finalTickAmt=b,b=5);this.tickAmount=b},adjustTickAmount:function(){var a=this.tickInterval,b=this.tickPositions,c=this.tickAmount,d=this.finalTickAmt,k=b&&b.length,q=C(this.threshold,this.softThreshold?0:null);if(this.hasData()){if(kc&&(this.tickInterval*= -2,this.setTickPositions());if(n(d)){for(a=c=b.length;a--;)(3===d&&1===a%2||2>=d&&0d&&(a=d)),n(c)&&(bd&&(b=d))),this.displayBtn=void 0!==a||void 0!==b,this.setExtremes(a,b,!1,void 0,{trigger:"zoom"});return!0},setAxisSize:function(){var b=this.chart,c=this.options,d=c.offsets||[0,0,0,0],k=this.horiz,q=this.width=Math.round(a.relativeLength(C(c.width,b.plotWidth-d[3]+d[1]),b.plotWidth)),e=this.height=Math.round(a.relativeLength(C(c.height, -b.plotHeight-d[0]+d[2]),b.plotHeight)),h=this.top=Math.round(a.relativeLength(C(c.top,b.plotTop+d[0]),b.plotHeight,b.plotTop)),c=this.left=Math.round(a.relativeLength(C(c.left,b.plotLeft+d[3]),b.plotWidth,b.plotLeft));this.bottom=b.chartHeight-e-h;this.right=b.chartWidth-q-c;this.len=Math.max(k?q:e,0);this.pos=k?c:h},getExtremes:function(){var a=this.isLog,b=this.lin2log;return{min:a?l(b(this.min)):this.min,max:a?l(b(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin, -userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,g=this.lin2log,c=b?g(this.min):this.min,b=b?g(this.max):this.max;null===a?a=c:c>a?a=c:ba?"right":195a?"left":"center"},tickSize:function(a){var b=this.options,g=b[a+"Length"],c=C(b[a+"Width"],"tick"===a&&this.isXAxis?1:0);if(c&&g)return"inside"===b[a+"Position"]&&(g=-g),[g,c]},labelMetrics:function(){var a= -this.tickPositions&&this.tickPositions[0]||0;return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize,this.ticks[a]&&this.ticks[a].label)},unsquish:function(){var a=this.options.labels,b=this.horiz,c=this.tickInterval,d=c,k=this.len/(((this.categories?1:0)+this.max-this.min)/c),q,h=a.rotation,m=this.labelMetrics(),z,A=Number.MAX_VALUE,t,x=function(a){a/=k||1;a=1=a)z=x(Math.abs(m.h/Math.sin(w*a))),b=z+Math.abs(a/360),b(c.step||0)&&!c.rotation&&(this.staggerLines||1)*this.len/d||!b&&(c.style&&parseInt(c.style.width,10)||k&&k-a.spacing[3]|| -.33*a.chartWidth)},renderUnsquish:function(){var a=this.chart,b=a.renderer,c=this.tickPositions,d=this.ticks,k=this.options.labels,q=this.horiz,h=this.getSlotWidth(),m=Math.max(1,Math.round(h-2*(k.padding||5))),z={},A=this.labelMetrics(),t=k.style&&k.style.textOverflow,f,F=0,l,B;I(k.rotation)||(z.rotation=k.rotation||0);e(c,function(a){(a=d[a])&&a.labelLength>F&&(F=a.labelLength)});this.maxLabelLength=F;if(this.autoRotation)F>m&&F>A.h?z.rotation=this.labelRotation:this.labelRotation=0;else if(h&& -(f={width:m+"px"},!t))for(f.textOverflow="clip",l=c.length;!q&&l--;)if(B=c[l],m=d[B].label)m.styles&&"ellipsis"===m.styles.textOverflow?m.css({textOverflow:"clip"}):d[B].labelLength>h&&m.css({width:h+"px"}),m.getBBox().height>this.len/c.length-(A.h-A.f)&&(m.specCss={textOverflow:"ellipsis"});z.rotation&&(f={width:(F>.5*a.chartHeight?.33*a.chartHeight:a.chartHeight)+"px"},t||(f.textOverflow="ellipsis"));if(this.labelAlign=k.align||this.autoLabelAlign(this.labelRotation))z.align=this.labelAlign;e(c, -function(a){var b=(a=d[a])&&a.label;b&&(b.attr(z),f&&b.css(x(f,b.specCss)),delete b.specCss,a.rotation=z.rotation)});this.tickRotCorr=b.rotCorr(A.b,this.labelRotation||0,0!==this.side)},hasData:function(){return this.hasVisibleSeries||n(this.min)&&n(this.max)&&this.tickPositions&&0=this.min&&a<=this.max)g[a]||(g[a]=new F(this,a)),d&&g[a].isNew&&g[a].render(b,!0,.1),g[a].render(b)},render:function(){var b= -this,c=b.chart,d=b.options,k=b.isLog,q=b.lin2log,h=b.isLinked,m=b.tickPositions,z=b.axisTitle,x=b.ticks,f=b.minorTicks,l=b.alternateBands,C=d.stackLabels,n=d.alternateGridColor,u=b.tickmarkOffset,G=b.axisLine,p=b.showAxis,I=D(c.renderer.globalAnimation),r,w;b.labelEdge.length=0;b.overlap=!1;e([x,f,l],function(a){t(a,function(a){a.isActive=!1})});if(b.hasData()||h)b.minorTickInterval&&!b.categories&&e(b.getMinorTickPositions(),function(a){b.renderMinorTick(a)}),m.length&&(e(m,function(a,c){b.renderTick(a, -c)}),u&&(0===b.min||b.single)&&(x[-1]||(x[-1]=new F(b,-1,null,!0)),x[-1].render(-1))),n&&e(m,function(d,g){w=void 0!==m[g+1]?m[g+1]+u:b.max-u;0===g%2&&d=h.second?0:C*Math.floor(x.getMilliseconds()/C));if(t>=h.second)x[D.hcSetSeconds](t>=h.minute? -0:C*Math.floor(x.getSeconds()/C));if(t>=h.minute)x[D.hcSetMinutes](t>=h.hour?0:C*Math.floor(x[D.hcGetMinutes]()/C));if(t>=h.hour)x[D.hcSetHours](t>=h.day?0:C*Math.floor(x[D.hcGetHours]()/C));if(t>=h.day)x[D.hcSetDate](t>=h.month?1:C*Math.floor(x[D.hcGetDate]()/C));t>=h.month&&(x[D.hcSetMonth](t>=h.year?0:C*Math.floor(x[D.hcGetMonth]()/C)),n=x[D.hcGetFullYear]());if(t>=h.year)x[D.hcSetFullYear](n-n%C);if(t===h.week)x[D.hcSetDate](x[D.hcGetDate]()-x[D.hcGetDay]()+e(b,1));n=x[D.hcGetFullYear]();b=x[D.hcGetMonth](); -var A=x[D.hcGetDate](),F=x[D.hcGetHours]();d=x.getTime();D.hcHasTimeZone&&(q=(!B||!!D.hcGetTimezoneOffset)&&(c-d>4*h.month||w(d)!==w(c)),N=w(x),x=new D(d+N));B=x.getTime();for(d=1;Bk.length&&l(k,function(a){0===a%18E5&&"000000000"===H("%H%M%S%L",a)&&(m[a]="day")})}k.info=r(a,{higherRanks:m,totalRange:t*C});return k}; -E.prototype.normalizeTimeTickInterval=function(a,d){var c=d||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2,3,4,6]],["year",null]];d=c[c.length-1];var b=h[d[0]],k=d[1],e;for(e=0;er&&(!w||z<=n)&&void 0!==z&&d.push(z),z>n&& -(B=!0),z=k;else r=h(r),n=h(n),a=w?this.getMinorTickInterval():l.tickInterval,a=f("auto"===a?null:a,this._minorAutoInterval,l.tickPixelInterval/(w?5:1)*(n-r)/((w?e/this.tickPositions.length:e)||1)),a=p(a,null,D(a)),d=H(this.getLinearTickPositions(a,r,n),m),w||(this._minorAutoInterval=a/5);w||(this.tickInterval=a);return d};E.prototype.log2lin=function(a){return Math.log(a)/Math.LN10};E.prototype.lin2log=function(a){return Math.pow(10,a)}})(M);(function(a,E){var D=a.arrayMax,H=a.arrayMin,p=a.defined, -f=a.destroyObjectProperties,l=a.each,r=a.erase,n=a.merge,w=a.pick;a.PlotLineOrBand=function(a,e){this.axis=a;e&&(this.options=e,this.id=e.id)};a.PlotLineOrBand.prototype={render:function(){var f=this,e=f.axis,h=e.horiz,m=f.options,d=m.label,c=f.label,b=m.to,k=m.from,z=m.value,l=p(k)&&p(b),r=p(z),x=f.svgElem,K=!x,t=[],C=m.color,N=w(m.zIndex,0),q=m.events,t={"class":"highcharts-plot-"+(l?"band ":"line ")+(m.className||"")},A={},F=e.chart.renderer,G=l?"bands":"lines",g=e.log2lin;e.isLog&&(k=g(k),b=g(b), -z=g(z));r?(t={stroke:C,"stroke-width":m.width},m.dashStyle&&(t.dashstyle=m.dashStyle)):l&&(C&&(t.fill=C),m.borderWidth&&(t.stroke=m.borderColor,t["stroke-width"]=m.borderWidth));A.zIndex=N;G+="-"+N;(C=e.plotLinesAndBandsGroups[G])||(e.plotLinesAndBandsGroups[G]=C=F.g("plot-"+G).attr(A).add());K&&(f.svgElem=x=F.path().attr(t).add(C));if(r)t=e.getPlotLinePath(z,x.strokeWidth());else if(l)t=e.getPlotBandPath(k,b,m);else return;K&&t&&t.length?(x.attr({d:t}),q&&a.objectEach(q,function(a,b){x.on(b,function(a){q[b].apply(f, -[a])})})):x&&(t?(x.show(),x.animate({d:t})):(x.hide(),c&&(f.label=c=c.destroy())));d&&p(d.text)&&t&&t.length&&0this.max&& -e>this.max;if(m&&h)for(a&&(k=m.toString()===h.toString(),b=0),a=0;aA-h?A:A-h);else if(z)k[a]=Math.max(e,g+h+d>c?g:g+h);else return!1},C=function(a,c,d,g){var e;gc-b?e=!1:k[a]=gc-d/2?c-d-2:g-d/2;return e},p=function(a){var b=f;f=x;x=b;m=a},q=function(){!1!==t.apply(0,f)?!1!==C.apply(0,x)||m||(p(!0),q()):m?k.x=k.y=0:(p(!0),q())};(c.inverted||1q&&(h=!1);a=(e.series&& -e.series.yAxis&&e.series.yAxis.pos)+(e.plotY||0);a-=b.plotTop;c.push({target:e.isHeader?b.plotHeight+l:a,rank:e.isHeader?1:0,size:z.tt.getBBox().height+1,point:e,x:q,tt:t})}});this.cleanSplit();a.distribute(c,b.plotHeight+l);D(c,function(a){var c=a.point,d=c.series;a.tt.attr({visibility:void 0===a.pos?"hidden":"inherit",x:h||c.isHeader?a.x:c.plotX+b.plotLeft+n(f.distance,16),y:a.pos+b.plotTop,anchorX:c.isHeader?c.plotX+b.plotLeft:c.plotX+d.xAxis.pos,anchorY:c.isHeader?a.pos+b.plotTop-15:c.plotY+d.yAxis.pos})})}, -updatePosition:function(a){var e=this.chart,d=this.getLabel(),d=(this.options.positioner||this.getPosition).call(this,d.width,d.height,a);this.move(Math.round(d.x),Math.round(d.y||0),a.plotX+e.plotLeft,a.plotY+e.plotTop)},getDateFormat:function(a,m,d,c){var b=E("%m-%d %H:%M:%S.%L",m),k,h,f={millisecond:15,second:12,minute:9,hour:6,day:3},l="millisecond";for(h in e){if(a===e.week&&+E("%w",m)===d&&"00:00:00.000"===b.substr(6)){h="week";break}if(e[h]>a){h=l;break}if(f[h]&&b.substr(f[h])!=="01-01 00:00:00.000".substr(f[h]))break; -"week"!==h&&(l=h)}h&&(k=c[h]);return k},getXDateFormat:function(a,e,d){e=e.dateTimeLabelFormats;var c=d&&d.closestPointRange;return(c?this.getDateFormat(c,a.x,d.options.startOfWeek,e):e.day)||e.year},tooltipFooterHeaderFormatter:function(a,e){e=e?"footer":"header";var d=a.series,c=d.tooltipOptions,b=c.xDateFormat,k=d.xAxis,h=k&&"datetime"===k.options.type&&f(a.key),m=c[e+"Format"];h&&!b&&(b=this.getXDateFormat(a,c,k));h&&b&&D(a.point&&a.point.tooltipDateKeys||["key"],function(a){m=m.replace("{point."+ -a+"}","{point."+a+":"+b+"}")});return p(m,{point:a,series:d})},bodyFormatter:function(a){return l(a,function(a){var d=a.series.tooltipOptions;return(d[(a.point.formatPrefix||"point")+"Formatter"]||a.point.tooltipFormatter).call(a.point,d[(a.point.formatPrefix||"point")+"Format"])})}}})(M);(function(a){var E=a.addEvent,D=a.attr,H=a.charts,p=a.color,f=a.css,l=a.defined,r=a.each,n=a.extend,w=a.find,u=a.fireEvent,e=a.isObject,h=a.offset,m=a.pick,d=a.splat,c=a.Tooltip;a.Pointer=function(a,c){this.init(a, -c)};a.Pointer.prototype={init:function(a,d){this.options=d;this.chart=a;this.runChartClick=d.chart.events&&!!d.chart.events.click;this.pinchDown=[];this.lastValidTouch={};c&&(a.tooltip=new c(a,d.tooltip),this.followTouchMove=m(d.tooltip.followTouchMove,!0));this.setDOMEvents()},zoomOption:function(a){var b=this.chart,c=b.options.chart,d=c.zoomType||"",b=b.inverted;/touch/.test(a.type)&&(d=m(c.pinchType,d));this.zoomX=a=/x/.test(d);this.zoomY=d=/y/.test(d);this.zoomHor=a&&!b||d&&b;this.zoomVert=d&& -!b||a&&b;this.hasZoom=a||d},normalize:function(a,c){var b;b=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:a;c||(this.chartPosition=c=h(this.chart.container));return n(a,{chartX:Math.round(b.pageX-c.left),chartY:Math.round(b.pageY-c.top)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};r(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},findNearestKDPoint:function(a,c,d){var b;r(a,function(a){var k= -!(a.noSharedTooltip&&c)&&0>a.options.findNearestPointBy.indexOf("y");a=a.searchPoint(d,k);if((k=e(a,!0))&&!(k=!e(b,!0)))var k=b.distX-a.distX,h=b.dist-a.dist,m=(a.series.group&&a.series.group.zIndex)-(b.series.group&&b.series.group.zIndex),k=0<(0!==k&&c?k:0!==h?h:0!==m?m:b.series.index>a.series.index?-1:1);k&&(b=a)});return b},getPointFromEvent:function(a){a=a.target;for(var b;a&&!b;)b=a.point,a=a.parentNode;return b},getChartCoordinatesFromPoint:function(a,c){var b=a.series,d=b.xAxis,b=b.yAxis,k= -m(a.clientX,a.plotX);if(d&&b)return c?{chartX:d.len+d.pos-k,chartY:b.len+b.pos-a.plotY}:{chartX:k+d.pos,chartY:a.plotY+b.pos}},getHoverData:function(b,c,d,h,f,l,n){var k,z=[],x=n&&n.isBoosting;h=!(!h||!b);n=c&&!c.stickyTracking?[c]:a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking,!0)&&a.stickyTracking});c=(k=h?b:this.findNearestKDPoint(n,f,l))&&k.series;k&&(f&&!c.noSharedTooltip?(n=a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking, -!0)&&!a.noSharedTooltip}),r(n,function(a){var b=w(a.points,function(a){return a.x===k.x&&!a.isNull});e(b)&&(x&&(b=a.getPoint(b)),z.push(b))})):z.push(k));return{hoverPoint:k,hoverSeries:c,hoverPoints:z}},runPointActions:function(b,c){var d=this.chart,k=d.tooltip&&d.tooltip.options.enabled?d.tooltip:void 0,e=k?k.shared:!1,h=c||d.hoverPoint,f=h&&h.series||d.hoverSeries,f=this.getHoverData(h,f,d.series,!!c||f&&f.directTouch&&this.isDirectTouch,e,b,{isBoosting:d.isBoosting}),l,h=f.hoverPoint;l=f.hoverPoints; -c=(f=f.hoverSeries)&&f.tooltipOptions.followPointer;e=e&&f&&!f.noSharedTooltip;if(h&&(h!==d.hoverPoint||k&&k.isHidden)){r(d.hoverPoints||[],function(b){-1===a.inArray(b,l)&&b.setState()});r(l||[],function(a){a.setState("hover")});if(d.hoverSeries!==f)f.onMouseOver();d.hoverPoint&&d.hoverPoint.firePointEvent("mouseOut");if(!h.series)return;h.firePointEvent("mouseOver");d.hoverPoints=l;d.hoverPoint=h;k&&k.refresh(e?l:h,b)}else c&&k&&!k.isHidden&&(h=k.getAnchor([{}],b),k.updatePosition({plotX:h[0],plotY:h[1]})); -this.unDocMouseMove||(this.unDocMouseMove=E(d.container.ownerDocument,"mousemove",function(b){var c=H[a.hoverChartIndex];if(c)c.pointer.onDocumentMouseMove(b)}));r(d.axes,function(c){var d=m(c.crosshair.snap,!0),k=d?a.find(l,function(a){return a.series[c.coll]===c}):void 0;k||!d?c.drawCrosshair(b,k):c.hideCrosshair()})},reset:function(a,c){var b=this.chart,k=b.hoverSeries,e=b.hoverPoint,h=b.hoverPoints,m=b.tooltip,f=m&&m.shared?h:e;a&&f&&r(d(f),function(b){b.series.isCartesian&&void 0===b.plotX&& -(a=!1)});if(a)m&&f&&(m.refresh(f),e&&(e.setState(e.state,!0),r(b.axes,function(a){a.crosshair&&a.drawCrosshair(null,e)})));else{if(e)e.onMouseOut();h&&r(h,function(a){a.setState()});if(k)k.onMouseOut();m&&m.hide(c);this.unDocMouseMove&&(this.unDocMouseMove=this.unDocMouseMove());r(b.axes,function(a){a.hideCrosshair()});this.hoverX=b.hoverPoints=b.hoverPoint=null}},scaleGroups:function(a,c){var b=this.chart,d;r(b.series,function(k){d=a||k.getPlotBox();k.xAxis&&k.xAxis.zoomEnabled&&k.group&&(k.group.attr(d), -k.markerGroup&&(k.markerGroup.attr(d),k.markerGroup.clip(c?b.clipRect:null)),k.dataLabelsGroup&&k.dataLabelsGroup.attr(d))});b.clipRect.attr(c||b.clipBox)},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,h=this.zoomHor,m=this.zoomVert,f=b.plotLeft,l=b.plotTop,n=b.plotWidth,q=b.plotHeight,A,F=this.selectionMarker,G=this.mouseDownX, -g=this.mouseDownY,v=c.panKey&&a[c.panKey+"Key"];F&&F.touch||(df+n&&(d=f+n),el+q&&(e=l+q),this.hasDragged=Math.sqrt(Math.pow(G-d,2)+Math.pow(g-e,2)),10u.max&&(f=u.max-x,v=!0);v?(F-=.8*(F-m[b][0]),q||(g-=.8*(g-m[b][1])),l()):m[b]=[F,g];C||(h[b]=w-r,h[n]=x);h=C?1/t:t;e[n]=x;e[b]=f;p[C?a?"scaleY":"scaleX":"scale"+k]=t;p["translate"+k]=h*r+(F-h*A)},pinch:function(a){var n=this,r=n.chart,u=n.pinchDown,e=a.touches,h=e.length,m=n.lastValidTouch, -d=n.hasZoom,c=n.selectionMarker,b={},k=1===h&&(n.inClass(a.target,"highcharts-tracker")&&r.runTrackerClick||n.runChartClick),z={};1c-6&&h(q||c.spacingBox.width-2*t-d.x)&&(this.itemX=t,this.itemY+=F+this.lastLineHeight+A,this.lastLineHeight=0);this.maxItemWidth=Math.max(this.maxItemWidth,m);this.lastItemY=F+this.itemY+A;this.lastLineHeight=Math.max(b,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=m:(this.itemY+=F+b+A,this.lastLineHeight=b);this.offsetWidth=q||Math.max((e?this.itemX-t-(a.checkbox?0:p):m)+t,this.offsetWidth)}, -getAllItems:function(){var a=[];f(this.chart.series,function(c){var b=c&&c.options;c&&w(b.showInLegend,p(b.linkedTo)?!1:void 0,!0)&&(a=a.concat(c.legendItems||("point"===b.legendType?c.data:c)))});return a},getAlignment:function(){var a=this.options;return a.floating?"":a.align.charAt(0)+a.verticalAlign.charAt(0)+a.layout.charAt(0)},adjustMargins:function(a,c){var b=this.chart,d=this.options,e=this.getAlignment();e&&f([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(k,h){k.test(e)&& -!p(a[h])&&(b[r[h]]=Math.max(b[r[h]],b.legend[(h+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][h]*d[h%2?"x":"y"]+w(d.margin,12)+c[h]+(0===h?b.titleOffset+b.options.title.margin:0)))})},render:function(){var a=this,c=a.chart,b=c.renderer,k=a.group,h,m,l,x,p=a.box,t=a.options,C=a.padding;a.itemX=C;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;k||(a.group=k=b.g("legend").attr({zIndex:7}).add(),a.contentGroup=b.g().attr({zIndex:1}).add(k),a.scrollGroup=b.g().add(a.contentGroup));a.renderTitle(); -h=a.getAllItems();e(h,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});t.reversed&&h.reverse();a.allItems=h;a.display=m=!!h.length;a.lastLineHeight=0;f(h,function(b){a.renderItem(b)});l=(t.width||a.offsetWidth)+C;x=a.lastItemY+a.lastLineHeight+a.titleHeight;x=a.handleOverflow(x);x+=C;p||(a.box=p=b.rect().addClass("highcharts-legend-box").attr({r:t.borderRadius}).add(k),p.isNew=!0);p.attr({stroke:t.borderColor,"stroke-width":t.borderWidth||0,fill:t.backgroundColor|| -"none"}).shadow(t.shadow);0b&&!1!==t.enabled?(this.clipHeight=l=Math.max(b-20-this.titleHeight-m,0),this.currentPage=w(this.currentPage,1),this.fullHeight=a,f(G,function(a,b){var c=a._legendItemPos[1],d=Math.round(a.legendItem.getBBox().height),g=A.length;if(!g||c-A[g-1]>l&&(F||c)!==A[g-1])A.push(F||c),g++;a.pageIx=g-1;F&&(G[b-1].pageIx=g-1);b===G.length-1&&c+d-A[g-1]>l&&(A.push(c),a.pageIx=g);c!==F&&(F=c)}),n||(n=c.clipRect=d.clipRect(0,m,9999,0),c.contentGroup.clip(n)),g(l),q||(this.nav=q=d.g().attr({zIndex:1}).add(this.group), -this.up=d.symbol("triangle",0,0,r,r).on("click",function(){c.scroll(-1,p)}).add(q),this.pager=d.text("",15,10).addClass("highcharts-legend-navigation").css(t.style).add(q),this.down=d.symbol("triangle-down",0,0,r,r).on("click",function(){c.scroll(1,p)}).add(q)),c.scroll(0),a=b):q&&(g(),this.nav=q.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return a},scroll:function(a,c){var b=this.pages,d=b.length;a=this.currentPage+a;var e=this.clipHeight,h=this.options.navigation,f=this.pager, -m=this.padding;a>d&&(a=d);0b&&(f=typeof a[0],"string"===f?e.name=a[0]:"number"===f&&(e.x=a[0]),k++);l=d.value;)d=h[++f];d&&d.color&&!this.options.color&&(this.color=d.color);return d},destroy:function(){var a=this.series.chart,h=a.hoverPoints,f;a.pointCount--;h&&(this.setState(),p(h,this),h.length||(a.hoverPoints=null));if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)u(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(f in this)this[f]=null},destroyElements:function(){for(var a=["graphic","dataLabel", -"dataLabelUpper","connector","shadowGroup"],h,f=6;f--;)h=a[f],this[h]&&(this[h]=this[h].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,color:this.color,colorIndex:this.colorIndex,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},tooltipFormatter:function(a){var e=this.series,f=e.tooltipOptions,d=w(f.valueDecimals,""),c=f.valuePrefix||"",b=f.valueSuffix||"";D(e.pointArrayMap||["y"],function(e){e="{point."+ -e;if(c||b)a=a.replace(e+"}",c+e+"}"+b);a=a.replace(e+"}",e+":,."+d+"f}")});return l(a,{point:this,series:this.series})},firePointEvent:function(a,h,m){var d=this,c=this.series.options;(c.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents();"click"===a&&c.allowPointSelect&&(m=function(a){d.select&&d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});f(this,a,h,m)},visible:!0}})(M);(function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.correctFloat, -l=a.Date,r=a.defaultOptions,n=a.defaultPlotOptions,w=a.defined,u=a.each,e=a.erase,h=a.extend,m=a.fireEvent,d=a.grep,c=a.isArray,b=a.isNumber,k=a.isString,z=a.merge,B=a.objectEach,I=a.pick,x=a.removeEvent,K=a.splat,t=a.SVGElement,C=a.syncTimeout,N=a.win;a.Series=a.seriesType("line",null,{lineWidth:2,allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},marker:{lineWidth:0,lineColor:"#ffffff",radius:4,states:{hover:{animation:{duration:50},enabled:!0,radiusPlus:2,lineWidthPlus:1},select:{fillColor:"#cccccc", -lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:{align:"center",formatter:function(){return null===this.y?"":a.numberFormat(this.y,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"contrast",textOutline:"1px contrast"},verticalAlign:"bottom",x:0,y:0,padding:5},cropThreshold:300,pointRange:0,softThreshold:!0,states:{hover:{animation:{duration:50},lineWidthPlus:1,marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1E3,findNearestPointBy:"x"}, -{isCartesian:!0,pointClass:a.Point,sorted:!0,requireSorting:!0,directTouch:!1,axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],coll:"series",init:function(a,b){var c=this,d,g=a.series,e;c.chart=a;c.options=b=c.setOptions(b);c.linkedSeries=[];c.bindAxes();h(c,{name:b.name,state:"",visible:!1!==b.visible,selected:!0===b.selected});d=b.events;B(d,function(a,b){E(c,b,a)});if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;c.getColor(); -c.getSymbol();u(c.parallelArrays,function(a){c[a+"Data"]=[]});c.setData(b.data,!1);c.isCartesian&&(a.hasCartesianSeries=!0);g.length&&(e=g[g.length-1]);c._i=I(e&&e._i,-1)+1;a.orderSeries(this.insert(g))},insert:function(a){var c=this.options.index,d;if(b(c)){for(d=a.length;d--;)if(c>=I(a[d].options.index,a[d]._i)){a.splice(d+1,0,this);break}-1===d&&a.unshift(this);d+=1}else a.push(this);return I(d,a.length-1)},bindAxes:function(){var b=this,c=b.options,d=b.chart,e;u(b.axisTypes||[],function(g){u(d[g], -function(a){e=a.options;if(c[g]===e.index||void 0!==c[g]&&c[g]===e.id||void 0===c[g]&&0===e.index)b.insert(a.series),b[g]=a,a.isDirty=!0});b[g]||b.optionalAxis===g||a.error(18,!0)})},updateParallelArrays:function(a,c){var d=a.series,e=arguments,g=b(c)?function(b){var g="y"===b&&d.toYData?d.toYData(a):a[b];d[b+"Data"][c]=g}:function(a){Array.prototype[c].apply(d[a+"Data"],Array.prototype.slice.call(e,2))};u(d.parallelArrays,g)},autoIncrement:function(){var b=this.options,c=this.xIncrement,d,e=b.pointIntervalUnit, -g=0,c=I(c,b.pointStart,0);this.pointInterval=d=I(this.pointInterval,b.pointInterval,1);e&&(b=new l(c),"day"===e?b=+b[l.hcSetDate](b[l.hcGetDate]()+d):"month"===e?b=+b[l.hcSetMonth](b[l.hcGetMonth]()+d):"year"===e&&(b=+b[l.hcSetFullYear](b[l.hcGetFullYear]()+d)),l.hcHasTimeZone&&(g=a.getTZOffset(b)-a.getTZOffset(c)),d=b-c+g);this.xIncrement=c+d;return c},setOptions:function(a){var b=this.chart,c=b.options,d=c.plotOptions,g=(b.userOptions||{}).plotOptions||{},e=d[this.type];this.userOptions=a;b=z(e, -d.series,a);this.tooltipOptions=z(r.tooltip,r.plotOptions.series&&r.plotOptions.series.tooltip,r.plotOptions[this.type].tooltip,c.tooltip.userOptions,d.series&&d.series.tooltip,d[this.type].tooltip,a.tooltip);this.stickyTracking=I(a.stickyTracking,g[this.type]&&g[this.type].stickyTracking,g.series&&g.series.stickyTracking,this.tooltipOptions.shared&&!this.noSharedTooltip?!0:b.stickyTracking);null===e.marker&&delete b.marker;this.zoneAxis=b.zoneAxis;a=this.zones=(b.zones||[]).slice();!b.negativeColor&& -!b.negativeFillColor||b.zones||a.push({value:b[this.zoneAxis+"Threshold"]||b.threshold||0,className:"highcharts-negative",color:b.negativeColor,fillColor:b.negativeFillColor});a.length&&w(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return b},getCyclic:function(a,b,c){var d,g=this.chart,e=this.userOptions,k=a+"Index",h=a+"Counter",q=c?c.length:I(g.options.chart[a+"Count"],g[a+"Count"]);b||(d=I(e[k],e["_"+k]),w(d)||(g.series.length||(g[h]=0),e["_"+k]=d=g[h]%q,g[h]+=1), -c&&(b=c[d]));void 0!==d&&(this[k]=d);this[a]=b},getColor:function(){this.options.colorByPoint?this.options.color=null:this.getCyclic("color",this.options.color||n[this.type].color,this.chart.options.colors)},getSymbol:function(){this.getCyclic("symbol",this.options.marker.symbol,this.chart.options.symbols)},drawLegendSymbol:a.LegendSymbolMixin.drawLineMarker,setData:function(d,e,h,f){var g=this,q=g.points,m=q&&q.length||0,l,A=g.options,t=g.chart,x=null,n=g.xAxis,p=A.turboThreshold,z=this.xData,F= -this.yData,C=(l=g.pointArrayMap)&&l.length;d=d||[];l=d.length;e=I(e,!0);if(!1!==f&&l&&m===l&&!g.cropped&&!g.hasGroupedData&&g.visible)u(d,function(a,b){q[b].update&&a!==A.data[b]&&q[b].update(a,!1,null,!1)});else{g.xIncrement=null;g.colorCounter=0;u(this.parallelArrays,function(a){g[a+"Data"].length=0});if(p&&l>p){for(h=0;null===x&&hf||this.forceCrop))if(c[e-1]z)c=[],d=[];else if(c[0]z)g=this.cropData(this.xData,this.yData,p,z),c=g.xData,d=g.yData,g=g.start,k=!0;for(f=c.length|| -1;--f;)e=x?m(c[f])-m(c[f-1]):c[f]-c[f-1],0e&&n&&(a.error(15),n=!1);this.cropped=k;this.cropStart=g;this.processedXData=c;this.processedYData=d;this.closestPointRange=h},cropData:function(a,b,c,d){var g=a.length,e=0,k=g,h=I(this.cropShoulder,1),f;for(f=0;f=c){e=Math.max(0,f-h);break}for(c=f;cd){k=c+h;break}return{xData:a.slice(e,k),yData:b.slice(e,k),start:e,end:k}},generatePoints:function(){var a=this.options,b=a.data,c=this.data,d,g=this.processedXData, -e=this.processedYData,k=this.pointClass,h=g.length,f=this.cropStart||0,m,l=this.hasGroupedData,a=a.keys,t,x=[],n;c||l||(c=[],c.length=b.length,c=this.data=c);a&&l&&(this.options.keys=!1);for(n=0;n=f&&(e[n-1]||l)<=q,m&&l)if(m=t.length)for(;m--;)"number"===typeof t[m]&&(g[h++]=t[m]);else g[h++]=t;this.dataMin= -p(g);this.dataMax=H(g)},translate:function(){this.processedXData||this.processData();this.generatePoints();var a=this.options,c=a.stacking,d=this.xAxis,e=d.categories,g=this.yAxis,k=this.points,h=k.length,m=!!this.modifyValue,l=a.pointPlacement,t="between"===l||b(l),n=a.threshold,x=a.startFromThreshold?n:0,p,z,C,r,u=Number.MAX_VALUE;"between"===l&&(l=.5);b(l)&&(l*=I(a.pointRange||d.pointRange));for(a=0;a=K&&(B.isNull=!0);B.plotX=p=f(Math.min(Math.max(-1E5,d.translate(N,0,0,0,1,l,"flags"===this.type)),1E5));c&&this.visible&&!B.isNull&&D&&D[N]&&(r=this.getStackIndicator(r,N,this.index),E=D[N],K=E.points[r.key],z=K[0],K=K[1],z===x&&r.key===D[N].base&&(z=I(n,g.min)),g.positiveValuesOnly&&0>=z&&(z=null),B.total=B.stackTotal=E.total,B.percentage=E.total&&B.y/E.total*100,B.stackY=K,E.setOffset(this.pointXOffset||0,this.barW||0));B.yBottom=w(z)?g.translate(z,0,1,0,1): -null;m&&(K=this.modifyValue(K,B));B.plotY=z="number"===typeof K&&Infinity!==K?Math.min(Math.max(-1E5,g.translate(K,0,1,0,1)),1E5):void 0;B.isInside=void 0!==z&&0<=z&&z<=g.len&&0<=p&&p<=d.len;B.clientX=t?f(d.translate(N,0,0,0,1,l)):p;B.negative=B.y<(n||0);B.category=e&&void 0!==e[B.x]?e[B.x]:B.x;B.isNull||(void 0!==C&&(u=Math.min(u,Math.abs(p-C))),C=p);B.zone=this.zones.length&&B.getZone()}this.closestPointRangePx=u},getValidPoints:function(a,b){var c=this.chart;return d(a||this.points||[],function(a){return b&& -!c.isInsidePlot(a.plotX,a.plotY,c.inverted)?!1:!a.isNull})},setClip:function(a){var b=this.chart,c=this.options,d=b.renderer,g=b.inverted,e=this.clipBox,k=e||b.clipBox,h=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,k.height,c.xAxis,c.yAxis].join(),f=b[h],q=b[h+"m"];f||(a&&(k.width=0,g&&(k.x=b.plotSizeX),b[h+"m"]=q=d.clipRect(g?b.plotSizeX+99:-99,g?-b.plotLeft:-b.plotTop,99,g?b.chartWidth:b.chartHeight)),b[h]=f=d.clipRect(k),f.count={length:0});a&&!f.count[this.index]&&(f.count[this.index]= -!0,f.count.length+=1);!1!==c.clip&&(this.group.clip(a||e?f:b.clipRect),this.markerGroup.clip(q),this.sharedClipKey=h);a||(f.count[this.index]&&(delete f.count[this.index],--f.count.length),0===f.count.length&&h&&b[h]&&(e||(b[h]=b[h].destroy()),b[h+"m"]&&(b[h+"m"]=b[h+"m"].destroy())))},animate:function(a){var b=this.chart,c=D(this.options.animation),d;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX,x:0},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99,x:0},c),this.animate= -null)},afterAnimate:function(){this.setClip();m(this,"afterAnimate");this.finishedAnimating=!0},drawPoints:function(){var a=this.points,b=this.chart,c,d,g,e,k=this.options.marker,h,f,l,m=this[this.specialGroup]||this.markerGroup,t,n=I(k.enabled,this.xAxis.isRadial?!0:null,this.closestPointRangePx>=2*k.radius);if(!1!==k.enabled||this._hasPointMarkers)for(c=0;ce&&b.shadow));k&&(k.startX=c.xMap,k.isArea=c.isArea)})}, -applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,e,k,h=this.clips||[],f,m=this.graph,l=this.area,t=Math.max(b.chartWidth,b.chartHeight),n=this[(this.zoneAxis||"y")+"Axis"],x,p,z=b.inverted,C,r,w,B,K=!1;d.length&&(m||l)&&n&&void 0!==n.min&&(p=n.reversed,C=n.horiz,m&&m.hide(),l&&l.hide(),x=n.getExtremes(),u(d,function(d,g){e=p?C?b.plotWidth:0:C?0:n.toPixels(x.min);e=Math.min(Math.max(I(k,e),0),t);k=Math.min(Math.max(Math.round(n.toPixels(I(d.value,x.max),!0)),0),t);K&&(e=k=n.toPixels(x.max)); -r=Math.abs(e-k);w=Math.min(e,k);B=Math.max(e,k);n.isXAxis?(f={x:z?B:w,y:0,width:r,height:t},C||(f.x=b.plotHeight-f.x)):(f={x:0,y:z?B:w,width:t,height:r},C&&(f.y=b.plotWidth-f.y));z&&c.isVML&&(f=n.isXAxis?{x:0,y:p?w:B,height:f.width,width:b.chartWidth}:{x:f.y-b.plotLeft-b.spacingBox.x,y:0,width:f.height,height:b.chartHeight});h[g]?h[g].animate(f):(h[g]=c.clipRect(f),m&&a["zone-graph-"+g].clip(h[g]),l&&a["zone-area-"+g].clip(h[g]));K=d.value>x.max}),this.clips=h)},invertGroups:function(a){function b(){u(["group", -"markerGroup"],function(b){c[b]&&(d.renderer.isVML&&c[b].attr({width:c.yAxis.len,height:c.xAxis.len}),c[b].width=c.yAxis.len,c[b].height=c.xAxis.len,c[b].invert(a))})}var c=this,d=c.chart,e;c.xAxis&&(e=E(d,"resize",b),E(c,"destroy",e),b(a),c.invertGroups=b)},plotGroup:function(a,b,c,d,e){var g=this[a],k=!g;k&&(this[a]=g=this.chart.renderer.g().attr({zIndex:d||.1}).add(e));g.addClass("highcharts-"+b+" highcharts-series-"+this.index+" highcharts-"+this.type+"-series "+(w(this.colorIndex)?"highcharts-color-"+ -this.colorIndex+" ":"")+(this.options.className||"")+(g.hasClass("highcharts-tracker")?" highcharts-tracker":""),!0);g.attr({visibility:c})[k?"attr":"animate"](this.getPlotBox());return g},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;a.inverted&&(b=c,c=this.xAxis);return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this,b=a.chart,c,d=a.options,e=!!a.animate&&b.renderer.isSVG&&D(d.animation).duration,k=a.visible?"inherit": -"hidden",h=d.zIndex,f=a.hasRendered,m=b.seriesGroup,l=b.inverted;c=a.plotGroup("group","series",k,h,m);a.markerGroup=a.plotGroup("markerGroup","markers",k,h,m);e&&a.animate(!0);c.inverted=a.isCartesian?l:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(l);!1===d.clip||a.sharedClipKey||f||c.clip(b.clipRect);e&&a.animate();f||(a.animationTimeout=C(function(){a.afterAnimate()}, -e));a.isDirty=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirty||this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:I(d&&d.left,a.plotLeft),translateY:I(e&&e.top,a.plotTop)}));this.translate();this.render();b&&delete this.kdTree},kdAxisArray:["clientX","plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,e=this.chart.inverted;return this.searchKDTree({clientX:e?c.len-a.chartY+ -c.pos:a.chartX-c.pos,plotY:e?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(c,d,e){var g,k;if(k=c&&c.length)return g=b.kdAxisArray[d%e],c.sort(function(a,b){return a[g]-b[g]}),k=Math.floor(k/2),{point:c[k],left:a(c.slice(0,k),d+1,e),right:a(c.slice(k+1),d+1,e)}}this.buildingKdTree=!0;var b=this,c=-1l?"left":"right";t=0>l?"right":"left";b[q]&&(q=c(a,b[q],g+1,f),n=q[h]x;)q--;this.updateParallelArrays(m,"splice",q,0,0);this.updateParallelArrays(m,q);g&&m.name&&(g[x]=m.name);l.splice(q,0,a);n&&(this.data.splice(q,0,null),this.processData());"point"===e.legendType&&this.generatePoints();c&&(h[0]&&h[0].remove?h[0].remove(!1):(h.shift(),this.updateParallelArrays(m,"shift"),l.shift()));this.isDirtyData=this.isDirty=!0;b&&f.redraw(d)},removePoint:function(a,b,c){var d=this,e=d.data,h=e[a],f=d.points,g=d.chart,l=function(){f&&f.length===e.length&& -f.splice(a,1);e.splice(a,1);d.options.data.splice(a,1);d.updateParallelArrays(h||{series:d},"splice",a,1);h&&h.destroy();d.isDirty=!0;d.isDirtyData=!0;b&&g.redraw()};x(c,g);b=k(b,!0);h?h.firePointEvent("remove",null,l):l()},remove:function(a,b,c){function d(){e.destroy();h.isDirtyLegend=h.isDirtyBox=!0;h.linkSeries();k(a,!0)&&h.redraw(b)}var e=this,h=e.chart;!1!==c?u(e,"remove",null,d):d()},update:function(a,b){var d=this,e=d.chart,h=d.userOptions,f=d.oldType||d.type,l=a.type||h.type||e.options.chart.type, -g=I[f].prototype,m,n=["group","markerGroup","dataLabelsGroup"],t=["navigatorSeries","baseSeries"],x=d.finishedAnimating&&{animation:!1};if(Object.keys&&"data"===Object.keys(a).toString())return this.setData(a.data,b);t=n.concat(t);r(t,function(a){t[a]=d[a];delete d[a]});a=c(h,x,{index:d.index,pointStart:d.xData[0]},{data:d.options.data},a);d.remove(!1,null,!1);for(m in g)d[m]=void 0;w(d,I[l||f].prototype);r(t,function(a){d[a]=t[a]});d.init(e,a);a.zIndex!==h.zIndex&&r(n,function(b){d[b]&&d[b].attr({zIndex:a.zIndex})}); -d.oldType=f;e.linkSeries();k(b,!0)&&e.redraw(!1)}});w(H.prototype,{update:function(a,b){var d=this.chart;a=d.options[this.coll][this.options.index]=c(this.userOptions,a);this.destroy(!0);this.init(d,w(a,{events:void 0}));d.isDirtyBox=!0;k(b,!0)&&d.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,e=this.series,h=e.length;h--;)e[h]&&e[h].remove(!1);n(b.axes,this);n(b[c],this);d(b.options[c])?b.options[c].splice(this.options.index,1):delete b.options[c];r(b[c],function(a,b){a.options.index= -b});this.destroy();b.isDirtyBox=!0;k(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}})})(M);(function(a){var E=a.color,D=a.each,H=a.map,p=a.pick,f=a.Series,l=a.seriesType;l("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(f){var l=[],r=[],u=this.xAxis,e=this.yAxis,h=e.stacks[this.stackKey],m={},d=this.index,c=e.series,b=c.length,k,z=p(e.options.reversedStacks,!0)?1:-1,B;f=f||this.points; -if(this.options.stacking){for(B=0;Ba&&w>l?(w=Math.max(a,l),e=2*l-w):wp&&e>l?(e=Math.max(p,l),w=2*l-e):e=Math.abs(h)&&.5a.closestPointRange*a.xAxis.transA,d=a.borderWidth=r(f.borderWidth,d?0:1),c=a.yAxis,b=f.threshold,k=a.translatedThreshold=c.getThreshold(b),l=r(f.minPointLength,5),p=a.getColumnMetrics(),u=p.width,x=a.barW=Math.max(u,1+2*d),w=a.pointXOffset=p.offset;h.inverted&&(k-=.5);f.pointPadding&&(x=Math.ceil(x));n.prototype.translate.apply(a);H(a.points,function(d){var e=r(d.yBottom,k),f=999+Math.abs(e),f=Math.min(Math.max(-f,d.plotY),c.len+f),m=d.plotX+w,n=x,t=Math.min(f,e),p,g=Math.max(f,e)-t;l&& -Math.abs(g)l?e-l:k-(p?l:0));d.barX=m;d.pointWidth=u;d.tooltipPos=h.inverted?[c.len+c.pos-h.plotLeft-f,a.xAxis.len-m-n/2,g]:[m+n/2,f+c.pos-h.plotTop,g];d.shapeType="rect";d.shapeArgs=a.crispCol.apply(a,d.isNull?[m,k,n,0]:[m,t,n,g])})},getSymbol:a.noop,drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")}, -pointAttribs:function(a,f){var e=this.options,d,c=this.pointAttrToOptions||{};d=c.stroke||"borderColor";var b=c["stroke-width"]||"borderWidth",k=a&&a.color||this.color,h=a&&a[d]||e[d]||this.color||k,n=a&&a[b]||e[b]||this[b]||0,c=e.dashStyle;a&&this.zones.length&&(k=a.getZone(),k=a.options.color||k&&k.color||this.color);f&&(a=l(e.states[f],a.options.states&&a.options.states[f]||{}),f=a.brightness,k=a.color||void 0!==f&&D(k).brighten(a.brightness).get()||k,h=a[d]||h,n=a[b]||n,c=a.dashStyle||c);d={fill:k, -stroke:h,"stroke-width":n};c&&(d.dashstyle=c);return d},drawPoints:function(){var a=this,h=this.chart,m=a.options,d=h.renderer,c=m.animationLimit||250,b;H(a.points,function(e){var k=e.graphic;if(f(e.plotY)&&null!==e.y){b=e.shapeArgs;if(k)k[h.pointCounte;++e)h=w[e],a=2>e||2===e&&/%$/.test(h),w[e]=p(h,[n,l,u,w[2]][e])+(a?r:0);w[3]>w[2]&&(w[3]=w[2]);return w},getStartAndEndRadians:function(a,l){a=D(a)?a:0;l=D(l)&&l>a&&360>l-a?l:a+360;return{start:E*(a+-90),end:E*(l+-90)}}}})(M);(function(a){var E=a.addEvent,D=a.CenteredSeriesMixin,H=a.defined,p=a.each,f=a.extend,l=D.getStartAndEndRadians,r=a.inArray,n=a.noop,w=a.pick,u=a.Point,e=a.Series,h=a.seriesType,m=a.setAnimation;h("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30, -enabled:!0,formatter:function(){return this.point.isNull?void 0:this.point.name},x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff",borderWidth:1,states:{hover:{brightness:.1,shadow:!1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:a.seriesTypes.column.prototype.pointAttribs,animate:function(a){var c= -this,b=c.points,d=c.startAngleRad;a||(p(b,function(a){var b=a.graphic,e=a.shapeArgs;b&&(b.attr({r:a.startR||c.center[3]/2,start:d,end:d}),b.animate({r:e.r,start:e.start,end:e.end},c.options.animation))}),c.animate=null)},updateTotals:function(){var a,c=0,b=this.points,e=b.length,f,h=this.options.ignoreHiddenPoint;for(a=0;a1.5*Math.PI?m-=2*Math.PI:m<-Math.PI/2&&(m+=2*Math.PI);G.slicedTranslation={translateX:Math.round(Math.cos(m)*d),translateY:Math.round(Math.sin(m)*d)};h=Math.cos(m)*a[2]/ -2;u=Math.sin(m)*a[2]/2;G.tooltipPos=[a[0]+.7*h,a[1]+.7*u];G.half=m<-Math.PI/2||m>Math.PI/2?1:0;G.angle=m;f=Math.min(e,G.labelDistance/5);G.labelPos=[a[0]+h+Math.cos(m)*G.labelDistance,a[1]+u+Math.sin(m)*G.labelDistance,a[0]+h+Math.cos(m)*f,a[1]+u+Math.sin(m)*f,a[0]+h,a[1]+u,0>G.labelDistance?"center":G.half?"right":"left",m]}},drawGraph:null,drawPoints:function(){var a=this,c=a.chart.renderer,b,e,h,l,m=a.options.shadow;m&&!a.shadowGroup&&(a.shadowGroup=c.g("shadow").add(a.group));p(a.points,function(d){e= -d.graphic;if(d.isNull)e&&(d.graphic=e.destroy());else{l=d.shapeArgs;b=d.getTranslate();var k=d.shadowGroup;m&&!k&&(k=d.shadowGroup=c.g("shadow").add(a.shadowGroup));k&&k.attr(b);h=a.pointAttribs(d,d.selected&&"select");e?e.setRadialReference(a.center).attr(h).animate(f(l,b)):(d.graphic=e=c[d.shapeType](l).setRadialReference(a.center).attr(b).add(a.group),d.visible||e.attr({visibility:"hidden"}),e.attr(h).attr({"stroke-linejoin":"round"}).shadow(m,k));e.addClass(d.getClassName())}})},searchPoint:n, -sortByAngle:function(a,c){a.sort(function(a,d){return void 0!==a.angle&&(d.angle-a.angle)*c})},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,getCenter:D.getCenter,getSymbol:n},{init:function(){u.prototype.init.apply(this,arguments);var a=this,c;a.name=w(a.name,"Slice");c=function(b){a.slice("select"===b.type)};E(a,"select",c);E(a,"unselect",c);return a},isValid:function(){return a.isNumber(this.y,!0)&&0<=this.y},setVisible:function(a,c){var b=this,d=b.series,e=d.chart,f=d.options.ignoreHiddenPoint; -c=w(c,f);a!==b.visible&&(b.visible=b.options.visible=a=void 0===a?!b.visible:a,d.options.data[r(b,d.data)]=b.options,p(["graphic","dataLabel","connector","shadowGroup"],function(c){if(b[c])b[c][a?"show":"hide"](!0)}),b.legendItem&&e.legend.colorizeItem(b,a),a||"hover"!==b.state||b.setState(""),f&&(d.isDirty=!0),c&&e.redraw())},slice:function(a,c,b){var d=this.series;m(b,d.chart);w(c,!0);this.sliced=this.options.sliced=H(a)?a:!this.sliced;d.options.data[r(this,d.data)]=this.options;this.graphic.animate(this.getTranslate()); -this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())},getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(a){var c=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.x,c.y,c.r+a,c.r+a,{innerR:this.shapeArgs.r-1,start:c.start,end:c.end})}})})(M);(function(a){var E=a.addEvent,D=a.arrayMax,H=a.defined,p=a.each,f=a.extend,l=a.format,r=a.map,n=a.merge,w=a.noop,u=a.pick,e=a.relativeLength,h= -a.Series,m=a.seriesTypes,d=a.stableSort;a.distribute=function(a,b){function c(a,b){return a.target-b.target}var e,f=!0,h=a,l=[],m;m=0;for(e=a.length;e--;)m+=a[e].size;if(m>b){d(a,function(a,b){return(b.rank||0)-(a.rank||0)});for(m=e=0;m<=b;)m+=a[e].size,e++;l=a.splice(e-1,a.length)}d(a,c);for(a=r(a,function(a){return{size:a.size,targets:[a.target],align:u(a.align,.5)}});f;){for(e=a.length;e--;)f=a[e],m=(Math.min.apply(0,f.targets)+Math.max.apply(0,f.targets))/2,f.pos=Math.min(Math.max(0,m-f.size* -f.align),b-f.size);e=a.length;for(f=!1;e--;)0a[e].pos&&(a[e-1].size+=a[e].size,a[e-1].targets=a[e-1].targets.concat(a[e].targets),a[e-1].align=.5,a[e-1].pos+a[e-1].size>b&&(a[e-1].pos=b-a[e-1].size),a.splice(e,1),f=!0)}e=0;p(a,function(a){var b=0;p(a.targets,function(){h[e].pos=a.pos+b;b+=h[e].size;e++})});h.push.apply(h,l);d(h,c)};h.prototype.drawDataLabels=function(){function c(a,b){var c=b.filter;return c?(b=c.operator,a=a[c.property],c=c.value,"\x3e"===b&&a>c||"\x3c"=== -b&&a=c||"\x3c\x3d"===b&&a<=c||"\x3d\x3d"===b&&a==c||"\x3d\x3d\x3d"===b&&a===c?!0:!1):!0}var b=this,d=b.options,e=d.dataLabels,f=b.points,h,m,r=b.hasRendered||0,t,w,D=u(e.defer,!!d.animation),q=b.chart.renderer;if(e.enabled||b._hasPointLabels)b.dlProcessOptions&&b.dlProcessOptions(e),w=b.plotGroup("dataLabelsGroup","data-labels",D&&!r?"hidden":"visible",e.zIndex||6),D&&(w.attr({opacity:+r}),r||E(b,"afterAnimate",function(){b.visible&&w.show(!0);w[d.animation?"animate":"attr"]({opacity:1}, -{duration:200})})),m=e,p(f,function(f){var k,p=f.dataLabel,g,x,r=f.connector,z=!p,C;h=f.dlOptions||f.options&&f.options.dataLabels;(k=u(h&&h.enabled,m.enabled)&&!f.isNull)&&(k=!0===c(f,h||e));k&&(e=n(m,h),g=f.getLabelConfig(),C=e[f.formatPrefix+"Format"]||e.format,t=H(C)?l(C,g):(e[f.formatPrefix+"Formatter"]||e.formatter).call(g,e),C=e.style,g=e.rotation,C.color=u(e.color,C.color,b.color,"#000000"),"contrast"===C.color&&(f.contrastColor=q.getContrast(f.color||b.color),C.color=e.inside||0>u(f.labelDistance, -e.distance)||d.stacking?f.contrastColor:"#000000"),d.cursor&&(C.cursor=d.cursor),x={fill:e.backgroundColor,stroke:e.borderColor,"stroke-width":e.borderWidth,r:e.borderRadius||0,rotation:g,padding:e.padding,zIndex:1},a.objectEach(x,function(a,b){void 0===a&&delete x[b]}));!p||k&&H(t)?k&&H(t)&&(p?x.text=t:(p=f.dataLabel=g?q.text(t,0,-9999).addClass("highcharts-data-label"):q.label(t,0,-9999,e.shape,null,null,e.useHTML,null,"data-label"),p.addClass(" highcharts-data-label-color-"+f.colorIndex+" "+(e.className|| -"")+(e.useHTML?"highcharts-tracker":""))),p.attr(x),p.css(C).shadow(e.shadow),p.added||p.add(w),b.alignDataLabel(f,p,e,null,z)):(f.dataLabel=p=p.destroy(),r&&(f.connector=r.destroy()))})};h.prototype.alignDataLabel=function(a,b,d,e,h){var c=this.chart,k=c.inverted,l=u(a.dlBox&&a.dlBox.centerX,a.plotX,-9999),m=u(a.plotY,-9999),n=b.getBBox(),p,q=d.rotation,r=d.align,w=this.visible&&(a.series.forceDL||c.isInsidePlot(l,Math.round(m),k)||e&&c.isInsidePlot(l,k?e.x+1:e.y+e.height-1,k)),z="justify"===u(d.overflow, -"justify");if(w&&(p=d.style.fontSize,p=c.renderer.fontMetrics(p,b).b,e=f({x:k?this.yAxis.len-m:l,y:Math.round(k?this.xAxis.len-l:m),width:0,height:0},e),f(d,{width:n.width,height:n.height}),q?(z=!1,l=c.renderer.rotCorr(p,q),l={x:e.x+d.x+e.width/2+l.x,y:e.y+d.y+{top:0,middle:.5,bottom:1}[d.verticalAlign]*e.height},b[h?"attr":"animate"](l).attr({align:r}),m=(q+720)%360,m=180m,"left"===r?l.y-=m?n.height:0:"center"===r?(l.x-=n.width/2,l.y-=n.height/2):"right"===r&&(l.x-=n.width,l.y-=m?0:n.height)): -(b.align(d,null,e),l=b.alignAttr),z?a.isLabelJustified=this.justifyDataLabel(b,d,l,n,e,h):u(d.crop,!0)&&(w=c.isInsidePlot(l.x,l.y)&&c.isInsidePlot(l.x+n.width,l.y+n.height)),d.shape&&!q))b[h?"attr":"animate"]({anchorX:k?c.plotWidth-a.plotY:a.plotX,anchorY:k?c.plotHeight-a.plotX:a.plotY});w||(b.attr({y:-9999}),b.placed=!1)};h.prototype.justifyDataLabel=function(a,b,d,e,f,h){var c=this.chart,k=b.align,l=b.verticalAlign,m,n,p=a.box?0:a.padding||0;m=d.x+p;0>m&&("right"===k?b.align="left":b.x=-m,n=!0); -m=d.x+e.width-p;m>c.plotWidth&&("left"===k?b.align="right":b.x=c.plotWidth-m,n=!0);m=d.y+p;0>m&&("bottom"===l?b.verticalAlign="top":b.y=-m,n=!0);m=d.y+e.height-p;m>c.plotHeight&&("top"===l?b.verticalAlign="bottom":b.y=c.plotHeight-m,n=!0);n&&(a.placed=!h,a.align(b,null,f));return n};m.pie&&(m.pie.prototype.drawDataLabels=function(){var c=this,b=c.data,d,e=c.chart,f=c.options.dataLabels,l=u(f.connectorPadding,10),m=u(f.connectorWidth,1),n=e.plotWidth,t=e.plotHeight,r,w=c.center,q=w[2]/2,A=w[1],F,G, -g,v,E=[[],[]],L,P,J,M,y=[0,0,0,0];c.visible&&(f.enabled||c._hasPointLabels)&&(p(b,function(a){a.dataLabel&&a.visible&&a.dataLabel.shortened&&(a.dataLabel.attr({width:"auto"}).css({width:"auto",textOverflow:"clip"}),a.dataLabel.shortened=!1)}),h.prototype.drawDataLabels.apply(c),p(b,function(a){a.dataLabel&&a.visible&&(E[a.half].push(a),a.dataLabel._pos=null)}),p(E,function(b,h){var k,m,x=b.length,r=[],z;if(x)for(c.sortByAngle(b,h-.5),0d.bottom-2?k:P,h,d),F._attr={visibility:J,align:g[6]},F._pos={x:L+f.x+({left:l,right:-l}[g[6]]||0),y:P+f.y-10},g.x=L,g.y=P,u(f.crop,!0)&&(G=F.getBBox().width,k=null,L-Gn-l&&(k=Math.round(L+G-n+l),y[1]=Math.max(k,y[1])),0>P-v/2?y[0]=Math.max(Math.round(-P+v/2),y[0]):P+v/2>t&&(y[2]=Math.max(Math.round(P+v/2-t),y[2])),F.sideOverflow=k)}),0===D(y)||this.verifyDataLabelOverflow(y))&&(this.placeDataLabels(), -m&&p(this.points,function(a){var b;r=a.connector;if((F=a.dataLabel)&&F._pos&&a.visible&&0u(this.translatedThreshold,k.yAxis.len)),p=u(d.inside,!!this.options.stacking);l&&(e=n(l),0>e.y&&(e.height+=e.y,e.y=0),l=e.y+e.height-k.yAxis.len,0a+c||e+hb+d||f+lthis.pointCount))},pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&r(d,function(a){a.setState()});r("xy"===b?[1,0]:[1],function(b){b= -c[b?"xAxis":"yAxis"][0];var d=b.horiz,f=a[d?"chartX":"chartY"],d=d?"mouseDownX":"mouseDownY",h=c[d],g=(b.pointRange||0)/2,k=b.getExtremes(),l=b.toValue(h-f,!0)+g,m=b.toValue(h+b.len-f,!0)-g,n=m=l(n.minWidth,0)&&this.chartHeight>=l(n.minHeight,0)}).call(this)&&f.push(a._id)};E.prototype.currentOptions=function(l){function n(e,h,l,d){var c;a.objectEach(e,function(a,e){if(!d&&-1 parseInt(D.split('Firefox/')[1], 10); + return a.Highcharts + ? a.Highcharts.error(16, !0) + : { + product: 'Highcharts', + version: '6.0.4', + deg2rad: (2 * Math.PI) / 360, + doc: E, + hasBidiBug: l, + hasTouch: E && void 0 !== E.documentElement.ontouchstart, + isMS: p, + isWebKit: /AppleWebKit/.test(D), + isFirefox: f, + isTouchDevice: /(Mobile|Android|Windows Phone)/.test(D), + SVG_NS: 'http://www.w3.org/2000/svg', + chartCount: 0, + seriesTypes: {}, + symbolSizes: {}, + svg: H, + win: a, + marginNames: ['plotTop', 'marginRight', 'marginBottom', 'plotLeft'], + noop: function() {}, + charts: [], + }; + })(); + (function(a) { + a.timers = []; + var E = a.charts, + D = a.doc, + H = a.win; + a.error = function(p, f) { + p = a.isNumber(p) + ? 'Highcharts error #' + p + ': www.highcharts.com/errors/' + p + : p; + if (f) throw Error(p); + H.console && console.log(p); + }; + a.Fx = function(a, f, l) { + this.options = f; + this.elem = a; + this.prop = l; + }; + a.Fx.prototype = { + dSetter: function() { + var a = this.paths[0], + f = this.paths[1], + l = [], + r = this.now, + n = a.length, + w; + if (1 === r) l = this.toD; + else if (n === f.length && 1 > r) + for (; n--; ) + (w = parseFloat(a[n])), + (l[n] = isNaN(w) ? f[n] : r * parseFloat(f[n] - w) + w); + else l = f; + this.elem.attr('d', l, null, !0); + }, + update: function() { + var a = this.elem, + f = this.prop, + l = this.now, + r = this.options.step; + if (this[f + 'Setter']) this[f + 'Setter'](); + else + a.attr + ? a.element && a.attr(f, l, null, !0) + : (a.style[f] = l + this.unit); + r && r.call(a, l, this); + }, + run: function(p, f, l) { + var r = this, + n = r.options, + w = function(a) { + return w.stopped ? !1 : r.step(a); + }, + u = + H.requestAnimationFrame || + function(a) { + setTimeout(a, 13); + }, + e = function() { + for (var h = 0; h < a.timers.length; h++) + a.timers[h]() || a.timers.splice(h--, 1); + a.timers.length && u(e); + }; + p === f + ? (delete n.curAnim[this.prop], + n.complete && + 0 === a.keys(n.curAnim).length && + n.complete.call(this.elem)) + : ((this.startTime = +new Date()), + (this.start = p), + (this.end = f), + (this.unit = l), + (this.now = this.start), + (this.pos = 0), + (w.elem = this.elem), + (w.prop = this.prop), + w() && 1 === a.timers.push(w) && u(e)); + }, + step: function(p) { + var f = +new Date(), + l, + r = this.options, + n = this.elem, + w = r.complete, + u = r.duration, + e = r.curAnim; + n.attr && !n.element + ? (p = !1) + : p || f >= u + this.startTime + ? ((this.now = this.end), + (this.pos = 1), + this.update(), + (l = e[this.prop] = !0), + a.objectEach(e, function(a) { + !0 !== a && (l = !1); + }), + l && w && w.call(n), + (p = !1)) + : ((this.pos = r.easing((f - this.startTime) / u)), + (this.now = this.start + (this.end - this.start) * this.pos), + this.update(), + (p = !0)); + return p; + }, + initPath: function(p, f, l) { + function r(a) { + var b, c; + for (k = a.length; k--; ) + (b = 'M' === a[k] || 'L' === a[k]), + (c = /[a-zA-Z]/.test(a[k + 3])), + b && + c && + a.splice(k + 1, 0, a[k + 1], a[k + 2], a[k + 1], a[k + 2]); + } + function n(a, b) { + for (; a.length < c; ) { + a[0] = b[c - a.length]; + var e = a.slice(0, d); + [].splice.apply(a, [0, 0].concat(e)); + z && + ((e = a.slice(a.length - d)), + [].splice.apply(a, [a.length, 0].concat(e)), + k--); + } + a[0] = 'M'; + } + function w(a, k) { + for (var e = (c - a.length) / d; 0 < e && e--; ) + (b = a.slice().splice(a.length / B - d, d * B)), + (b[0] = k[c - d - e * d]), + m && ((b[d - 6] = b[d - 2]), (b[d - 5] = b[d - 1])), + [].splice.apply(a, [a.length / B, 0].concat(b)), + z && e--; + } + f = f || ''; + var u, + e = p.startX, + h = p.endX, + m = -1 < f.indexOf('C'), + d = m ? 7 : 3, + c, + b, + k; + f = f.split(' '); + l = l.slice(); + var z = p.isArea, + B = z ? 2 : 1, + I; + m && (r(f), r(l)); + if (e && h) { + for (k = 0; k < e.length; k++) + if (e[k] === h[0]) { + u = k; + break; + } else if (e[0] === h[h.length - e.length + k]) { + u = k; + I = !0; + break; + } + void 0 === u && (f = []); + } + f.length && + a.isNumber(u) && + ((c = l.length + u * B * d), + I ? (n(f, l), w(l, f)) : (n(l, f), w(f, l))); + return [f, l]; + }, + }; + a.Fx.prototype.fillSetter = a.Fx.prototype.strokeSetter = function() { + this.elem.attr( + this.prop, + a.color(this.start).tweenTo(a.color(this.end), this.pos), + null, + !0, + ); + }; + a.extend = function(a, f) { + var l; + a || (a = {}); + for (l in f) a[l] = f[l]; + return a; + }; + a.merge = function() { + var p, + f = arguments, + l, + r = {}, + n = function(l, p) { + 'object' !== typeof l && (l = {}); + a.objectEach(p, function(e, h) { + !a.isObject(e, !0) || a.isClass(e) || a.isDOMElement(e) + ? (l[h] = p[h]) + : (l[h] = n(l[h] || {}, e)); + }); + return l; + }; + !0 === f[0] && ((r = f[1]), (f = Array.prototype.slice.call(f, 2))); + l = f.length; + for (p = 0; p < l; p++) r = n(r, f[p]); + return r; + }; + a.pInt = function(a, f) { + return parseInt(a, f || 10); + }; + a.isString = function(a) { + return 'string' === typeof a; + }; + a.isArray = function(a) { + a = Object.prototype.toString.call(a); + return '[object Array]' === a || '[object Array Iterator]' === a; + }; + a.isObject = function(p, f) { + return !!p && 'object' === typeof p && (!f || !a.isArray(p)); + }; + a.isDOMElement = function(p) { + return a.isObject(p) && 'number' === typeof p.nodeType; + }; + a.isClass = function(p) { + var f = p && p.constructor; + return !( + !a.isObject(p, !0) || + a.isDOMElement(p) || + !f || + !f.name || + 'Object' === f.name + ); + }; + a.isNumber = function(a) { + return ( + 'number' === typeof a && !isNaN(a) && Infinity > a && -Infinity < a + ); + }; + a.erase = function(a, f) { + for (var l = a.length; l--; ) + if (a[l] === f) { + a.splice(l, 1); + break; + } + }; + a.defined = function(a) { + return void 0 !== a && null !== a; + }; + a.attr = function(p, f, l) { + var r; + a.isString(f) + ? a.defined(l) + ? p.setAttribute(f, l) + : p && p.getAttribute && (r = p.getAttribute(f)) + : a.defined(f) && + a.isObject(f) && + a.objectEach(f, function(a, l) { + p.setAttribute(l, a); + }); + return r; + }; + a.splat = function(p) { + return a.isArray(p) ? p : [p]; + }; + a.syncTimeout = function(a, f, l) { + if (f) return setTimeout(a, f, l); + a.call(0, l); + }; + a.pick = function() { + var a = arguments, + f, + l, + r = a.length; + for (f = 0; f < r; f++) + if (((l = a[f]), void 0 !== l && null !== l)) return l; + }; + a.css = function(p, f) { + a.isMS && + !a.svg && + f && + void 0 !== f.opacity && + (f.filter = 'alpha(opacity\x3d' + 100 * f.opacity + ')'); + a.extend(p.style, f); + }; + a.createElement = function(p, f, l, r, n) { + p = D.createElement(p); + var w = a.css; + f && a.extend(p, f); + n && w(p, { padding: 0, border: 'none', margin: 0 }); + l && w(p, l); + r && r.appendChild(p); + return p; + }; + a.extendClass = function(p, f) { + var l = function() {}; + l.prototype = new p(); + a.extend(l.prototype, f); + return l; + }; + a.pad = function(a, f, l) { + return Array((f || 2) + 1 - String(a).length).join(l || 0) + a; + }; + a.relativeLength = function(a, f, l) { + return /%$/.test(a) + ? (f * parseFloat(a)) / 100 + (l || 0) + : parseFloat(a); + }; + a.wrap = function(a, f, l) { + var p = a[f]; + a[f] = function() { + var a = Array.prototype.slice.call(arguments), + f = arguments, + u = this; + u.proceed = function() { + p.apply(u, arguments.length ? arguments : f); + }; + a.unshift(p); + a = l.apply(this, a); + u.proceed = null; + return a; + }; + }; + a.getTZOffset = function(p) { + var f = a.Date; + return ( + 6e4 * + ((f.hcGetTimezoneOffset && f.hcGetTimezoneOffset(p)) || + f.hcTimezoneOffset || + 0) + ); + }; + a.dateFormat = function(p, f, l) { + if (!a.defined(f) || isNaN(f)) + return a.defaultOptions.lang.invalidDate || ''; + p = a.pick(p, '%Y-%m-%d %H:%M:%S'); + var r = a.Date, + n = new r(f - a.getTZOffset(f)), + w = n[r.hcGetHours](), + u = n[r.hcGetDay](), + e = n[r.hcGetDate](), + h = n[r.hcGetMonth](), + m = n[r.hcGetFullYear](), + d = a.defaultOptions.lang, + c = d.weekdays, + b = d.shortWeekdays, + k = a.pad, + r = a.extend( + { + a: b ? b[u] : c[u].substr(0, 3), + A: c[u], + d: k(e), + e: k(e, 2, ' '), + w: u, + b: d.shortMonths[h], + B: d.months[h], + m: k(h + 1), + y: m.toString().substr(2, 2), + Y: m, + H: k(w), + k: w, + I: k(w % 12 || 12), + l: w % 12 || 12, + M: k(n[r.hcGetMinutes]()), + p: 12 > w ? 'AM' : 'PM', + P: 12 > w ? 'am' : 'pm', + S: k(n.getSeconds()), + L: k(Math.round(f % 1e3), 3), + }, + a.dateFormats, + ); + a.objectEach(r, function(a, b) { + for (; -1 !== p.indexOf('%' + b); ) + p = p.replace('%' + b, 'function' === typeof a ? a(f) : a); + }); + return l ? p.substr(0, 1).toUpperCase() + p.substr(1) : p; + }; + a.formatSingle = function(p, f) { + var l = /\.([0-9])/, + r = a.defaultOptions.lang; + /f$/.test(p) + ? ((l = (l = p.match(l)) ? l[1] : -1), + null !== f && + (f = a.numberFormat( + f, + l, + r.decimalPoint, + -1 < p.indexOf(',') ? r.thousandsSep : '', + ))) + : (f = a.dateFormat(p, f)); + return f; + }; + a.format = function(p, f) { + for (var l = '{', r = !1, n, w, u, e, h = [], m; p; ) { + l = p.indexOf(l); + if (-1 === l) break; + n = p.slice(0, l); + if (r) { + n = n.split(':'); + w = n.shift().split('.'); + e = w.length; + m = f; + for (u = 0; u < e; u++) m && (m = m[w[u]]); + n.length && (m = a.formatSingle(n.join(':'), m)); + h.push(m); + } else h.push(n); + p = p.slice(l + 1); + l = (r = !r) ? '}' : '{'; + } + h.push(p); + return h.join(''); + }; + a.getMagnitude = function(a) { + return Math.pow(10, Math.floor(Math.log(a) / Math.LN10)); + }; + a.normalizeTickInterval = function(p, f, l, r, n) { + var w, + u = p; + l = a.pick(l, 1); + w = p / l; + f || + ((f = n + ? [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] + : [1, 2, 2.5, 5, 10]), + !1 === r && + (1 === l + ? (f = a.grep(f, function(a) { + return 0 === a % 1; + })) + : 0.1 >= l && (f = [1 / l]))); + for ( + r = 0; + r < f.length && + !((u = f[r]), + (n && u * l >= p) || (!n && w <= (f[r] + (f[r + 1] || f[r])) / 2)); + r++ + ); + return (u = a.correctFloat( + u * l, + -Math.round(Math.log(0.001) / Math.LN10), + )); + }; + a.stableSort = function(a, f) { + var l = a.length, + p, + n; + for (n = 0; n < l; n++) a[n].safeI = n; + a.sort(function(a, n) { + p = f(a, n); + return 0 === p ? a.safeI - n.safeI : p; + }); + for (n = 0; n < l; n++) delete a[n].safeI; + }; + a.arrayMin = function(a) { + for (var f = a.length, l = a[0]; f--; ) a[f] < l && (l = a[f]); + return l; + }; + a.arrayMax = function(a) { + for (var f = a.length, l = a[0]; f--; ) a[f] > l && (l = a[f]); + return l; + }; + a.destroyObjectProperties = function(p, f) { + a.objectEach(p, function(a, r) { + a && a !== f && a.destroy && a.destroy(); + delete p[r]; + }); + }; + a.discardElement = function(p) { + var f = a.garbageBin; + f || (f = a.createElement('div')); + p && f.appendChild(p); + f.innerHTML = ''; + }; + a.correctFloat = function(a, f) { + return parseFloat(a.toPrecision(f || 14)); + }; + a.setAnimation = function(p, f) { + f.renderer.globalAnimation = a.pick(p, f.options.chart.animation, !0); + }; + a.animObject = function(p) { + return a.isObject(p) ? a.merge(p) : { duration: p ? 500 : 0 }; + }; + a.timeUnits = { + millisecond: 1, + second: 1e3, + minute: 6e4, + hour: 36e5, + day: 864e5, + week: 6048e5, + month: 24192e5, + year: 314496e5, + }; + a.numberFormat = function(p, f, l, r) { + p = +p || 0; + f = +f; + var n = a.defaultOptions.lang, + w = (p.toString().split('.')[1] || '').split('e')[0].length, + u, + e, + h = p.toString().split('e'); + -1 === f + ? (f = Math.min(w, 20)) + : a.isNumber(f) + ? f && + h[1] && + 0 > h[1] && + ((u = f + +h[1]), + 0 <= u + ? ((h[0] = (+h[0]).toExponential(u).split('e')[0]), (f = u)) + : ((h[0] = h[0].split('.')[0] || 0), + (p = 20 > f ? (h[0] * Math.pow(10, h[1])).toFixed(f) : 0), + (h[1] = 0))) + : (f = 2); + e = ( + Math.abs(h[1] ? h[0] : p) + Math.pow(10, -Math.max(f, w) - 1) + ).toFixed(f); + w = String(a.pInt(e)); + u = 3 < w.length ? w.length % 3 : 0; + l = a.pick(l, n.decimalPoint); + r = a.pick(r, n.thousandsSep); + p = (0 > p ? '-' : '') + (u ? w.substr(0, u) + r : ''); + p += w.substr(u).replace(/(\d{3})(?=\d)/g, '$1' + r); + f && (p += l + e.slice(-f)); + h[1] && 0 !== +p && (p += 'e' + h[1]); + return p; + }; + Math.easeInOutSine = function(a) { + return -0.5 * (Math.cos(Math.PI * a) - 1); + }; + a.getStyle = function(p, f, l) { + if ('width' === f) + return ( + Math.min(p.offsetWidth, p.scrollWidth) - + a.getStyle(p, 'padding-left') - + a.getStyle(p, 'padding-right') + ); + if ('height' === f) + return ( + Math.min(p.offsetHeight, p.scrollHeight) - + a.getStyle(p, 'padding-top') - + a.getStyle(p, 'padding-bottom') + ); + H.getComputedStyle || a.error(27, !0); + if ((p = H.getComputedStyle(p, void 0))) + (p = p.getPropertyValue(f)), + a.pick(l, 'opacity' !== f) && (p = a.pInt(p)); + return p; + }; + a.inArray = function(p, f) { + return (a.indexOfPolyfill || Array.prototype.indexOf).call(f, p); + }; + a.grep = function(p, f) { + return (a.filterPolyfill || Array.prototype.filter).call(p, f); + }; + a.find = Array.prototype.find + ? function(a, f) { + return a.find(f); + } + : function(a, f) { + var l, + r = a.length; + for (l = 0; l < r; l++) if (f(a[l], l)) return a[l]; + }; + a.map = function(a, f) { + for (var l = [], r = 0, n = a.length; r < n; r++) + l[r] = f.call(a[r], a[r], r, a); + return l; + }; + a.keys = function(p) { + return (a.keysPolyfill || Object.keys).call(void 0, p); + }; + a.reduce = function(p, f, l) { + return (a.reducePolyfill || Array.prototype.reduce).call(p, f, l); + }; + a.offset = function(a) { + var f = D.documentElement; + a = a.parentElement ? a.getBoundingClientRect() : { top: 0, left: 0 }; + return { + top: a.top + (H.pageYOffset || f.scrollTop) - (f.clientTop || 0), + left: a.left + (H.pageXOffset || f.scrollLeft) - (f.clientLeft || 0), + }; + }; + a.stop = function(p, f) { + for (var l = a.timers.length; l--; ) + a.timers[l].elem !== p || + (f && f !== a.timers[l].prop) || + (a.timers[l].stopped = !0); + }; + a.each = function(p, f, l) { + return (a.forEachPolyfill || Array.prototype.forEach).call(p, f, l); + }; + a.objectEach = function(a, f, l) { + for (var r in a) a.hasOwnProperty(r) && f.call(l, a[r], r, a); + }; + a.addEvent = function(p, f, l) { + var r, + n, + w = p.addEventListener || a.addEventListenerPolyfill; + p.hcEvents && + !Object.prototype.hasOwnProperty.call(p, 'hcEvents') && + ((n = {}), + a.objectEach(p.hcEvents, function(a, e) { + n[e] = a.slice(0); + }), + (p.hcEvents = n)); + r = p.hcEvents = p.hcEvents || {}; + w && w.call(p, f, l, !1); + r[f] || (r[f] = []); + r[f].push(l); + return function() { + a.removeEvent(p, f, l); + }; + }; + a.removeEvent = function(p, f, l) { + function r(e, m) { + var d = p.removeEventListener || a.removeEventListenerPolyfill; + d && d.call(p, e, m, !1); + } + function n() { + var e, m; + p.nodeName && + (f ? ((e = {}), (e[f] = !0)) : (e = u), + a.objectEach(e, function(a, c) { + if (u[c]) for (m = u[c].length; m--; ) r(c, u[c][m]); + })); + } + var w, + u = p.hcEvents, + e; + u && + (f + ? ((w = u[f] || []), + l + ? ((e = a.inArray(l, w)), + -1 < e && (w.splice(e, 1), (u[f] = w)), + r(f, l)) + : (n(), (u[f] = []))) + : (n(), (p.hcEvents = {}))); + }; + a.fireEvent = function(p, f, l, r) { + var n; + n = p.hcEvents; + var w, u; + l = l || {}; + if (D.createEvent && (p.dispatchEvent || p.fireEvent)) + (n = D.createEvent('Events')), + n.initEvent(f, !0, !0), + a.extend(n, l), + p.dispatchEvent ? p.dispatchEvent(n) : p.fireEvent(f, n); + else if (n) + for ( + n = n[f] || [], + w = n.length, + l.target || + a.extend(l, { + preventDefault: function() { + l.defaultPrevented = !0; + }, + target: p, + type: f, + }), + f = 0; + f < w; + f++ + ) + (u = n[f]) && !1 === u.call(p, l) && l.preventDefault(); + r && !l.defaultPrevented && r(l); + }; + a.animate = function(p, f, l) { + var r, + n = '', + w, + u, + e; + a.isObject(l) || + ((e = arguments), + (l = { duration: e[2], easing: e[3], complete: e[4] })); + a.isNumber(l.duration) || (l.duration = 400); + l.easing = + 'function' === typeof l.easing + ? l.easing + : Math[l.easing] || Math.easeInOutSine; + l.curAnim = a.merge(f); + a.objectEach(f, function(e, m) { + a.stop(p, m); + u = new a.Fx(p, l, m); + w = null; + 'd' === m + ? ((u.paths = u.initPath(p, p.d, f.d)), + (u.toD = f.d), + (r = 0), + (w = 1)) + : p.attr + ? (r = p.attr(m)) + : ((r = parseFloat(a.getStyle(p, m)) || 0), + 'opacity' !== m && (n = 'px')); + w || (w = e); + w && w.match && w.match('px') && (w = w.replace(/px/g, '')); + u.run(r, w, n); + }); + }; + a.seriesType = function(p, f, l, r, n) { + var w = a.getOptions(), + u = a.seriesTypes; + w.plotOptions[p] = a.merge(w.plotOptions[f], l); + u[p] = a.extendClass(u[f] || function() {}, r); + u[p].prototype.type = p; + n && (u[p].prototype.pointClass = a.extendClass(a.Point, n)); + return u[p]; + }; + a.uniqueKey = (function() { + var a = Math.random() + .toString(36) + .substring(2, 9), + f = 0; + return function() { + return 'highcharts-' + a + '-' + f++; + }; + })(); + H.jQuery && + (H.jQuery.fn.highcharts = function() { + var p = [].slice.call(arguments); + if (this[0]) + return p[0] + ? (new a[a.isString(p[0]) ? p.shift() : 'Chart']( + this[0], + p[0], + p[1], + ), + this) + : E[a.attr(this[0], 'data-highcharts-chart')]; + }); + })(M); + (function(a) { + var E = a.each, + D = a.isNumber, + H = a.map, + p = a.merge, + f = a.pInt; + a.Color = function(l) { + if (!(this instanceof a.Color)) return new a.Color(l); + this.init(l); + }; + a.Color.prototype = { + parsers: [ + { + regex: /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/, + parse: function(a) { + return [f(a[1]), f(a[2]), f(a[3]), parseFloat(a[4], 10)]; + }, + }, + { + regex: /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/, + parse: function(a) { + return [f(a[1]), f(a[2]), f(a[3]), 1]; + }, + }, + ], + names: { + none: 'rgba(255,255,255,0)', + white: '#ffffff', + black: '#000000', + }, + init: function(l) { + var f, n, w, u; + if ( + (this.input = l = + this.names[l && l.toLowerCase ? l.toLowerCase() : ''] || l) && + l.stops + ) + this.stops = H(l.stops, function(e) { + return new a.Color(e[1]); + }); + else if ( + (l && + l.charAt && + '#' === l.charAt() && + ((f = l.length), + (l = parseInt(l.substr(1), 16)), + 7 === f + ? (n = [(l & 16711680) >> 16, (l & 65280) >> 8, l & 255, 1]) + : 4 === f && + (n = [ + ((l & 3840) >> 4) | ((l & 3840) >> 8), + ((l & 240) >> 4) | (l & 240), + ((l & 15) << 4) | (l & 15), + 1, + ])), + !n) + ) + for (w = this.parsers.length; w-- && !n; ) + (u = this.parsers[w]), (f = u.regex.exec(l)) && (n = u.parse(f)); + this.rgba = n || []; + }, + get: function(a) { + var f = this.input, + n = this.rgba, + l; + this.stops + ? ((l = p(f)), + (l.stops = [].concat(l.stops)), + E(this.stops, function(n, e) { + l.stops[e] = [l.stops[e][0], n.get(a)]; + })) + : (l = + n && D(n[0]) + ? 'rgb' === a || (!a && 1 === n[3]) + ? 'rgb(' + n[0] + ',' + n[1] + ',' + n[2] + ')' + : 'a' === a + ? n[3] + : 'rgba(' + n.join(',') + ')' + : f); + return l; + }, + brighten: function(a) { + var l, + n = this.rgba; + if (this.stops) + E(this.stops, function(n) { + n.brighten(a); + }); + else if (D(a) && 0 !== a) + for (l = 0; 3 > l; l++) + (n[l] += f(255 * a)), + 0 > n[l] && (n[l] = 0), + 255 < n[l] && (n[l] = 255); + return this; + }, + setOpacity: function(a) { + this.rgba[3] = a; + return this; + }, + tweenTo: function(a, f) { + var n = this.rgba, + l = a.rgba; + l.length && n && n.length + ? ((a = 1 !== l[3] || 1 !== n[3]), + (f = + (a ? 'rgba(' : 'rgb(') + + Math.round(l[0] + (n[0] - l[0]) * (1 - f)) + + ',' + + Math.round(l[1] + (n[1] - l[1]) * (1 - f)) + + ',' + + Math.round(l[2] + (n[2] - l[2]) * (1 - f)) + + (a ? ',' + (l[3] + (n[3] - l[3]) * (1 - f)) : '') + + ')')) + : (f = a.input || 'none'); + return f; + }, + }; + a.color = function(l) { + return new a.Color(l); + }; + })(M); + (function(a) { + var E, + D, + H = a.addEvent, + p = a.animate, + f = a.attr, + l = a.charts, + r = a.color, + n = a.css, + w = a.createElement, + u = a.defined, + e = a.deg2rad, + h = a.destroyObjectProperties, + m = a.doc, + d = a.each, + c = a.extend, + b = a.erase, + k = a.grep, + z = a.hasTouch, + B = a.inArray, + I = a.isArray, + x = a.isFirefox, + K = a.isMS, + t = a.isObject, + C = a.isString, + N = a.isWebKit, + q = a.merge, + A = a.noop, + F = a.objectEach, + G = a.pick, + g = a.pInt, + v = a.removeEvent, + Q = a.stop, + L = a.svg, + P = a.SVG_NS, + J = a.symbolSizes, + R = a.win; + E = a.SVGElement = function() { + return this; + }; + c(E.prototype, { + opacity: 1, + SVG_NS: P, + textProps: 'direction fontSize fontWeight fontFamily fontStyle color lineHeight width textAlign textDecoration textOverflow textOutline'.split( + ' ', + ), + init: function(a, g) { + this.element = 'span' === g ? w(g) : m.createElementNS(this.SVG_NS, g); + this.renderer = a; + }, + animate: function(y, g, b) { + g = a.animObject(G(g, this.renderer.globalAnimation, !0)); + 0 !== g.duration + ? (b && (g.complete = b), p(this, y, g)) + : (this.attr(y, null, b), g.step && g.step.call(this)); + return this; + }, + colorGradient: function(y, g, b) { + var v = this.renderer, + c, + O, + k, + e, + z, + h, + m, + L, + A, + J, + t = [], + x; + y.radialGradient + ? (O = 'radialGradient') + : y.linearGradient && (O = 'linearGradient'); + O && + ((k = y[O]), + (z = v.gradients), + (m = y.stops), + (J = b.radialReference), + I(k) && + (y[O] = k = { + x1: k[0], + y1: k[1], + x2: k[2], + y2: k[3], + gradientUnits: 'userSpaceOnUse', + }), + 'radialGradient' === O && + J && + !u(k.gradientUnits) && + ((e = k), + (k = q(k, v.getRadialAttr(J, e), { + gradientUnits: 'userSpaceOnUse', + }))), + F(k, function(a, y) { + 'id' !== y && t.push(y, a); + }), + F(m, function(a) { + t.push(a); + }), + (t = t.join(',')), + z[t] + ? (J = z[t].attr('id')) + : ((k.id = J = a.uniqueKey()), + (z[t] = h = v + .createElement(O) + .attr(k) + .add(v.defs)), + (h.radAttr = e), + (h.stops = []), + d(m, function(y) { + 0 === y[1].indexOf('rgba') + ? ((c = a.color(y[1])), (L = c.get('rgb')), (A = c.get('a'))) + : ((L = y[1]), (A = 1)); + y = v + .createElement('stop') + .attr({ offset: y[0], 'stop-color': L, 'stop-opacity': A }) + .add(h); + h.stops.push(y); + })), + (x = 'url(' + v.url + '#' + J + ')'), + b.setAttribute(g, x), + (b.gradient = t), + (y.toString = function() { + return x; + })); + }, + applyTextOutline: function(y) { + var g = this.element, + v, + c, + k, + q, + e; + -1 !== y.indexOf('contrast') && + (y = y.replace(/contrast/g, this.renderer.getContrast(g.style.fill))); + y = y.split(' '); + c = y[y.length - 1]; + if ((k = y[0]) && 'none' !== k && a.svg) { + this.fakeTS = !0; + y = [].slice.call(g.getElementsByTagName('tspan')); + this.ySetter = this.xSetter; + k = k.replace(/(^[\d\.]+)(.*?)$/g, function(a, y, g) { + return 2 * y + g; + }); + for (e = y.length; e--; ) + (v = y[e]), + 'highcharts-text-outline' === v.getAttribute('class') && + b(y, g.removeChild(v)); + q = g.firstChild; + d(y, function(a, y) { + 0 === y && + (a.setAttribute('x', g.getAttribute('x')), + (y = g.getAttribute('y')), + a.setAttribute('y', y || 0), + null === y && g.setAttribute('y', 0)); + a = a.cloneNode(1); + f(a, { + class: 'highcharts-text-outline', + fill: c, + stroke: c, + 'stroke-width': k, + 'stroke-linejoin': 'round', + }); + g.insertBefore(a, q); + }); + } + }, + attr: function(a, g, b, v) { + var y, + c = this.element, + k, + d = this, + O, + q; + 'string' === typeof a && + void 0 !== g && + ((y = a), (a = {}), (a[y] = g)); + 'string' === typeof a + ? (d = (this[a + 'Getter'] || this._defaultGetter).call(this, a, c)) + : (F( + a, + function(y, g) { + O = !1; + v || Q(this, g); + this.symbolName && + /^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)$/.test( + g, + ) && + (k || (this.symbolAttr(a), (k = !0)), (O = !0)); + !this.rotation || + ('x' !== g && 'y' !== g) || + (this.doTransform = !0); + O || + ((q = this[g + 'Setter'] || this._defaultSetter), + q.call(this, y, g, c), + this.shadows && + /^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test( + g, + ) && + this.updateShadows(g, y, q)); + }, + this, + ), + this.afterSetters()); + b && b(); + return d; + }, + afterSetters: function() { + this.doTransform && (this.updateTransform(), (this.doTransform = !1)); + }, + updateShadows: function(a, g, b) { + for (var y = this.shadows, v = y.length; v--; ) + b.call( + y[v], + 'height' === a + ? Math.max(g - (y[v].cutHeight || 0), 0) + : 'd' === a + ? this.d + : g, + a, + y[v], + ); + }, + addClass: function(a, g) { + var y = this.attr('class') || ''; + -1 === y.indexOf(a) && + (g || (a = (y + (y ? ' ' : '') + a).replace(' ', ' ')), + this.attr('class', a)); + return this; + }, + hasClass: function(a) { + return -1 !== B(a, (this.attr('class') || '').split(' ')); + }, + removeClass: function(a) { + return this.attr('class', (this.attr('class') || '').replace(a, '')); + }, + symbolAttr: function(a) { + var y = this; + d( + 'x y r start end width height innerR anchorX anchorY'.split(' '), + function(g) { + y[g] = G(a[g], y[g]); + }, + ); + y.attr({ + d: y.renderer.symbols[y.symbolName](y.x, y.y, y.width, y.height, y), + }); + }, + clip: function(a) { + return this.attr( + 'clip-path', + a ? 'url(' + this.renderer.url + '#' + a.id + ')' : 'none', + ); + }, + crisp: function(a, g) { + var y; + g = g || a.strokeWidth || 0; + y = (Math.round(g) % 2) / 2; + a.x = Math.floor(a.x || this.x || 0) + y; + a.y = Math.floor(a.y || this.y || 0) + y; + a.width = Math.floor((a.width || this.width || 0) - 2 * y); + a.height = Math.floor((a.height || this.height || 0) - 2 * y); + u(a.strokeWidth) && (a.strokeWidth = g); + return a; + }, + css: function(a) { + var y = this.styles, + b = {}, + v = this.element, + k, + d = '', + q, + e = !y, + z = ['textOutline', 'textOverflow', 'width']; + a && a.color && (a.fill = a.color); + y && + F(a, function(a, g) { + a !== y[g] && ((b[g] = a), (e = !0)); + }); + e && + (y && (a = c(y, b)), + (k = this.textWidth = + a && + a.width && + 'auto' !== a.width && + 'text' === v.nodeName.toLowerCase() && + g(a.width)), + (this.styles = a), + k && !L && this.renderer.forExport && delete a.width, + K && !L + ? n(this.element, a) + : ((q = function(a, y) { + return '-' + y.toLowerCase(); + }), + F(a, function(a, y) { + -1 === B(y, z) && + (d += y.replace(/([A-Z])/g, q) + ':' + a + ';'); + }), + d && f(v, 'style', d)), + this.added && + ('text' === this.element.nodeName && this.renderer.buildText(this), + a && a.textOutline && this.applyTextOutline(a.textOutline))); + return this; + }, + strokeWidth: function() { + return this['stroke-width'] || 0; + }, + on: function(a, g) { + var y = this, + b = y.element; + z && 'click' === a + ? ((b.ontouchstart = function(a) { + y.touchEventFired = Date.now(); + a.preventDefault(); + g.call(b, a); + }), + (b.onclick = function(a) { + (-1 === R.navigator.userAgent.indexOf('Android') || + 1100 < Date.now() - (y.touchEventFired || 0)) && + g.call(b, a); + })) + : (b['on' + a] = g); + return this; + }, + setRadialReference: function(a) { + var y = this.renderer.gradients[this.element.gradient]; + this.element.radialReference = a; + y && y.radAttr && y.animate(this.renderer.getRadialAttr(a, y.radAttr)); + return this; + }, + translate: function(a, g) { + return this.attr({ translateX: a, translateY: g }); + }, + invert: function(a) { + this.inverted = a; + this.updateTransform(); + return this; + }, + updateTransform: function() { + var a = this.translateX || 0, + g = this.translateY || 0, + b = this.scaleX, + v = this.scaleY, + c = this.inverted, + k = this.rotation, + d = this.matrix, + q = this.element; + c && ((a += this.width), (g += this.height)); + a = ['translate(' + a + ',' + g + ')']; + u(d) && a.push('matrix(' + d.join(',') + ')'); + c + ? a.push('rotate(90) scale(-1,1)') + : k && + a.push( + 'rotate(' + + k + + ' ' + + G(this.rotationOriginX, q.getAttribute('x'), 0) + + ' ' + + G(this.rotationOriginY, q.getAttribute('y') || 0) + + ')', + ); + (u(b) || u(v)) && a.push('scale(' + G(b, 1) + ' ' + G(v, 1) + ')'); + a.length && q.setAttribute('transform', a.join(' ')); + }, + toFront: function() { + var a = this.element; + a.parentNode.appendChild(a); + return this; + }, + align: function(a, g, v) { + var y, + c, + k, + d, + q = {}; + c = this.renderer; + k = c.alignedObjects; + var e, O; + if (a) { + if ( + ((this.alignOptions = a), (this.alignByTranslate = g), !v || C(v)) + ) + (this.alignTo = y = v || 'renderer'), + b(k, this), + k.push(this), + (v = null); + } else + (a = this.alignOptions), + (g = this.alignByTranslate), + (y = this.alignTo); + v = G(v, c[y], c); + y = a.align; + c = a.verticalAlign; + k = (v.x || 0) + (a.x || 0); + d = (v.y || 0) + (a.y || 0); + 'right' === y ? (e = 1) : 'center' === y && (e = 2); + e && (k += (v.width - (a.width || 0)) / e); + q[g ? 'translateX' : 'x'] = Math.round(k); + 'bottom' === c ? (O = 1) : 'middle' === c && (O = 2); + O && (d += (v.height - (a.height || 0)) / O); + q[g ? 'translateY' : 'y'] = Math.round(d); + this[this.placed ? 'animate' : 'attr'](q); + this.placed = !0; + this.alignAttr = q; + return this; + }, + getBBox: function(a, g) { + var y, + b = this.renderer, + v, + k = this.element, + q = this.styles, + O, + z = this.textStr, + h, + m = b.cache, + L = b.cacheKeys, + A; + g = G(g, this.rotation); + v = g * e; + O = q && q.fontSize; + u(z) && + ((A = z.toString()), + -1 === A.indexOf('\x3c') && (A = A.replace(/[0-9]/g, '0')), + (A += ['', g || 0, O, q && q.width, q && q.textOverflow].join())); + A && !a && (y = m[A]); + if (!y) { + if (k.namespaceURI === this.SVG_NS || b.forExport) { + try { + (h = + this.fakeTS && + function(a) { + d(k.querySelectorAll('.highcharts-text-outline'), function( + y, + ) { + y.style.display = a; + }); + }) && h('none'), + (y = k.getBBox + ? c({}, k.getBBox()) + : { width: k.offsetWidth, height: k.offsetHeight }), + h && h(''); + } catch (W) {} + if (!y || 0 > y.width) y = { width: 0, height: 0 }; + } else y = this.htmlGetBBox(); + b.isSVG && + ((a = y.width), + (b = y.height), + q && + '11px' === q.fontSize && + 17 === Math.round(b) && + (y.height = b = 14), + g && + ((y.width = + Math.abs(b * Math.sin(v)) + Math.abs(a * Math.cos(v))), + (y.height = + Math.abs(b * Math.cos(v)) + Math.abs(a * Math.sin(v))))); + if (A && 0 < y.height) { + for (; 250 < L.length; ) delete m[L.shift()]; + m[A] || L.push(A); + m[A] = y; + } + } + return y; + }, + show: function(a) { + return this.attr({ visibility: a ? 'inherit' : 'visible' }); + }, + hide: function() { + return this.attr({ visibility: 'hidden' }); + }, + fadeOut: function(a) { + var y = this; + y.animate( + { opacity: 0 }, + { + duration: a || 150, + complete: function() { + y.attr({ y: -9999 }); + }, + }, + ); + }, + add: function(a) { + var y = this.renderer, + g = this.element, + b; + a && (this.parentGroup = a); + this.parentInverted = a && a.inverted; + void 0 !== this.textStr && y.buildText(this); + this.added = !0; + if (!a || a.handleZ || this.zIndex) b = this.zIndexSetter(); + b || (a ? a.element : y.box).appendChild(g); + if (this.onAdd) this.onAdd(); + return this; + }, + safeRemoveChild: function(a) { + var y = a.parentNode; + y && y.removeChild(a); + }, + destroy: function() { + var a = this, + g = a.element || {}, + v = a.renderer.isSVG && 'SPAN' === g.nodeName && a.parentGroup, + c = g.ownerSVGElement; + g.onclick = g.onmouseout = g.onmouseover = g.onmousemove = g.point = null; + Q(a); + a.clipPath && + c && + (d(c.querySelectorAll('[clip-path],[CLIP-PATH]'), function(g) { + g + .getAttribute('clip-path') + .match(RegExp('[("]#' + a.clipPath.element.id + '[)"]')) && + g.removeAttribute('clip-path'); + }), + (a.clipPath = a.clipPath.destroy())); + if (a.stops) { + for (c = 0; c < a.stops.length; c++) + a.stops[c] = a.stops[c].destroy(); + a.stops = null; + } + a.safeRemoveChild(g); + for (a.destroyShadows(); v && v.div && 0 === v.div.childNodes.length; ) + (g = v.parentGroup), a.safeRemoveChild(v.div), delete v.div, (v = g); + a.alignTo && b(a.renderer.alignedObjects, a); + F(a, function(g, y) { + delete a[y]; + }); + return null; + }, + shadow: function(a, g, b) { + var y = [], + v, + c, + k = this.element, + d, + q, + e, + z; + if (!a) this.destroyShadows(); + else if (!this.shadows) { + q = G(a.width, 3); + e = (a.opacity || 0.15) / q; + z = this.parentInverted + ? '(-1,-1)' + : '(' + G(a.offsetX, 1) + ', ' + G(a.offsetY, 1) + ')'; + for (v = 1; v <= q; v++) + (c = k.cloneNode(0)), + (d = 2 * q + 1 - 2 * v), + f(c, { + isShadow: 'true', + stroke: a.color || '#000000', + 'stroke-opacity': e * v, + 'stroke-width': d, + transform: 'translate' + z, + fill: 'none', + }), + b && + (f(c, 'height', Math.max(f(c, 'height') - d, 0)), + (c.cutHeight = d)), + g + ? g.element.appendChild(c) + : k.parentNode && k.parentNode.insertBefore(c, k), + y.push(c); + this.shadows = y; + } + return this; + }, + destroyShadows: function() { + d( + this.shadows || [], + function(a) { + this.safeRemoveChild(a); + }, + this, + ); + this.shadows = void 0; + }, + xGetter: function(a) { + 'circle' === this.element.nodeName && + ('x' === a ? (a = 'cx') : 'y' === a && (a = 'cy')); + return this._defaultGetter(a); + }, + _defaultGetter: function(a) { + a = G( + this[a + 'Value'], + this[a], + this.element ? this.element.getAttribute(a) : null, + 0, + ); + /^[\-0-9\.]+$/.test(a) && (a = parseFloat(a)); + return a; + }, + dSetter: function(a, g, b) { + a && a.join && (a = a.join(' ')); + /(NaN| {2}|^$)/.test(a) && (a = 'M 0 0'); + this[g] !== a && (b.setAttribute(g, a), (this[g] = a)); + }, + dashstyleSetter: function(a) { + var b, + v = this['stroke-width']; + 'inherit' === v && (v = 1); + if ((a = a && a.toLowerCase())) { + a = a + .replace('shortdashdotdot', '3,1,1,1,1,1,') + .replace('shortdashdot', '3,1,1,1') + .replace('shortdot', '1,1,') + .replace('shortdash', '3,1,') + .replace('longdash', '8,3,') + .replace(/dot/g, '1,3,') + .replace('dash', '4,3,') + .replace(/,$/, '') + .split(','); + for (b = a.length; b--; ) a[b] = g(a[b]) * v; + a = a.join(',').replace(/NaN/g, 'none'); + this.element.setAttribute('stroke-dasharray', a); + } + }, + alignSetter: function(a) { + this.alignValue = a; + this.element.setAttribute( + 'text-anchor', + { left: 'start', center: 'middle', right: 'end' }[a], + ); + }, + opacitySetter: function(a, g, b) { + this[g] = a; + b.setAttribute(g, a); + }, + titleSetter: function(a) { + var g = this.element.getElementsByTagName('title')[0]; + g || + ((g = m.createElementNS(this.SVG_NS, 'title')), + this.element.appendChild(g)); + g.firstChild && g.removeChild(g.firstChild); + g.appendChild( + m.createTextNode(String(G(a), '').replace(/<[^>]*>/g, '')), + ); + }, + textSetter: function(a) { + a !== this.textStr && + (delete this.bBox, + (this.textStr = a), + this.added && this.renderer.buildText(this)); + }, + fillSetter: function(a, g, b) { + 'string' === typeof a + ? b.setAttribute(g, a) + : a && this.colorGradient(a, g, b); + }, + visibilitySetter: function(a, g, b) { + 'inherit' === a + ? b.removeAttribute(g) + : this[g] !== a && b.setAttribute(g, a); + this[g] = a; + }, + zIndexSetter: function(a, b) { + var v = this.renderer, + y = this.parentGroup, + c = (y || v).element || v.box, + k, + d = this.element, + q, + e, + v = c === v.box; + k = this.added; + var z; + u(a) && + ((d.zIndex = a), (a = +a), this[b] === a && (k = !1), (this[b] = a)); + if (k) { + (a = this.zIndex) && y && (y.handleZ = !0); + b = c.childNodes; + for (z = b.length - 1; 0 <= z && !q; z--) + if (((y = b[z]), (k = y.zIndex), (e = !u(k)), y !== d)) + if (0 > a && e && !v && !z) c.insertBefore(d, b[z]), (q = !0); + else if (g(k) <= a || (e && (!u(a) || 0 <= a))) + c.insertBefore(d, b[z + 1] || null), (q = !0); + q || (c.insertBefore(d, b[v ? 3 : 0] || null), (q = !0)); + } + return q; + }, + _defaultSetter: function(a, g, b) { + b.setAttribute(g, a); + }, + }); + E.prototype.yGetter = E.prototype.xGetter; + E.prototype.translateXSetter = E.prototype.translateYSetter = E.prototype.rotationSetter = E.prototype.verticalAlignSetter = E.prototype.rotationOriginXSetter = E.prototype.rotationOriginYSetter = E.prototype.scaleXSetter = E.prototype.scaleYSetter = E.prototype.matrixSetter = function( + a, + g, + ) { + this[g] = a; + this.doTransform = !0; + }; + E.prototype['stroke-widthSetter'] = E.prototype.strokeSetter = function( + a, + g, + b, + ) { + this[g] = a; + this.stroke && this['stroke-width'] + ? (E.prototype.fillSetter.call(this, this.stroke, 'stroke', b), + b.setAttribute('stroke-width', this['stroke-width']), + (this.hasStroke = !0)) + : 'stroke-width' === g && + 0 === a && + this.hasStroke && + (b.removeAttribute('stroke'), (this.hasStroke = !1)); + }; + D = a.SVGRenderer = function() { + this.init.apply(this, arguments); + }; + c(D.prototype, { + Element: E, + SVG_NS: P, + init: function(a, g, b, v, c, k) { + var y; + v = this.createElement('svg') + .attr({ version: '1.1', class: 'highcharts-root' }) + .css(this.getStyle(v)); + y = v.element; + a.appendChild(y); + f(a, 'dir', 'ltr'); + -1 === a.innerHTML.indexOf('xmlns') && f(y, 'xmlns', this.SVG_NS); + this.isSVG = !0; + this.box = y; + this.boxWrapper = v; + this.alignedObjects = []; + this.url = + (x || N) && m.getElementsByTagName('base').length + ? R.location.href + .replace(/#.*?$/, '') + .replace(/<[^>]*>/g, '') + .replace(/([\('\)])/g, '\\$1') + .replace(/ /g, '%20') + : ''; + this.createElement('desc') + .add() + .element.appendChild( + m.createTextNode('Created with Highcharts 6.0.4'), + ); + this.defs = this.createElement('defs').add(); + this.allowHTML = k; + this.forExport = c; + this.gradients = {}; + this.cache = {}; + this.cacheKeys = []; + this.imgCount = 0; + this.setSize(g, b, !1); + var d; + x && + a.getBoundingClientRect && + ((g = function() { + n(a, { left: 0, top: 0 }); + d = a.getBoundingClientRect(); + n(a, { + left: Math.ceil(d.left) - d.left + 'px', + top: Math.ceil(d.top) - d.top + 'px', + }); + }), + g(), + (this.unSubPixelFix = H(R, 'resize', g))); + }, + getStyle: function(a) { + return (this.style = c( + { + fontFamily: + '"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif', + fontSize: '12px', + }, + a, + )); + }, + setStyle: function(a) { + this.boxWrapper.css(this.getStyle(a)); + }, + isHidden: function() { + return !this.boxWrapper.getBBox().width; + }, + destroy: function() { + var a = this.defs; + this.box = null; + this.boxWrapper = this.boxWrapper.destroy(); + h(this.gradients || {}); + this.gradients = null; + a && (this.defs = a.destroy()); + this.unSubPixelFix && this.unSubPixelFix(); + return (this.alignedObjects = null); + }, + createElement: function(a) { + var g = new this.Element(); + g.init(this, a); + return g; + }, + draw: A, + getRadialAttr: function(a, g) { + return { + cx: a[0] - a[2] / 2 + g.cx * a[2], + cy: a[1] - a[2] / 2 + g.cy * a[2], + r: g.r * a[2], + }; + }, + getSpanWidth: function(a, g) { + var b = a.getBBox(!0).width; + !L && + this.forExport && + (b = this.measureSpanWidth(g.firstChild.data, a.styles)); + return b; + }, + applyEllipsis: function(a, g, b, v) { + var c = a.rotation, + y = b, + k, + d = 0, + q = b.length, + e = function(a) { + g.removeChild(g.firstChild); + a && g.appendChild(m.createTextNode(a)); + }, + z; + a.rotation = 0; + y = this.getSpanWidth(a, g); + if ((z = y > v)) { + for (; d <= q; ) + (k = Math.ceil((d + q) / 2)), + (y = b.substring(0, k) + '\u2026'), + e(y), + (y = this.getSpanWidth(a, g)), + d === q ? (d = q + 1) : y > v ? (q = k - 1) : (d = k); + 0 === q && e(''); + } + a.rotation = c; + return z; + }, + escapes: { + '\x26': '\x26amp;', + '\x3c': '\x26lt;', + '\x3e': '\x26gt;', + "'": '\x26#39;', + '"': '\x26quot;', + }, + buildText: function(a) { + var b = a.element, + v = this, + c = v.forExport, + y = G(a.textStr, '').toString(), + q = -1 !== y.indexOf('\x3c'), + e = b.childNodes, + z, + h, + A, + J, + t = f(b, 'x'), + x = a.styles, + B = a.textWidth, + l = x && x.lineHeight, + C = x && x.textOutline, + u = x && 'ellipsis' === x.textOverflow, + Q = x && 'nowrap' === x.whiteSpace, + w = x && x.fontSize, + R, + I, + r = e.length, + x = B && !a.added && this.box, + p = function(a) { + var c; + c = /(px|em)$/.test(a && a.style.fontSize) + ? a.style.fontSize + : w || v.style.fontSize || 12; + return l + ? g(l) + : v.fontMetrics(c, a.getAttribute('style') ? a : b).h; + }, + K = function(a) { + F(v.escapes, function(g, b) { + a = a.replace(new RegExp(g, 'g'), b); + }); + return a; + }; + R = [y, u, Q, l, C, w, B].join(); + if (R !== a.textCache) { + for (a.textCache = R; r--; ) b.removeChild(e[r]); + q || C || u || B || -1 !== y.indexOf(' ') + ? ((z = /<.*class="([^"]+)".*>/), + (h = /<.*style="([^"]+)".*>/), + (A = /<.*href="([^"]+)".*>/), + x && x.appendChild(b), + (y = q + ? y + .replace( + /<(b|strong)>/g, + '\x3cspan style\x3d"font-weight:bold"\x3e', + ) + .replace( + /<(i|em)>/g, + '\x3cspan style\x3d"font-style:italic"\x3e', + ) + .replace(//g, '\x3c/span\x3e') + .split(//g) + : [y]), + (y = k(y, function(a) { + return '' !== a; + })), + d(y, function(g, y) { + var k, + q = 0; + g = g + .replace(/^\s+|\s+$/g, '') + .replace(//g, '\x3c/span\x3e|||'); + k = g.split('|||'); + d(k, function(g) { + if ('' !== g || 1 === k.length) { + var d = {}, + e = m.createElementNS(v.SVG_NS, 'tspan'), + x, + F; + z.test(g) && ((x = g.match(z)[1]), f(e, 'class', x)); + h.test(g) && + ((F = g + .match(h)[1] + .replace(/(;| |^)color([ :])/, '$1fill$2')), + f(e, 'style', F)); + A.test(g) && + !c && + (f( + e, + 'onclick', + 'location.href\x3d"' + g.match(A)[1] + '"', + ), + f(e, 'class', 'highcharts-anchor'), + n(e, { cursor: 'pointer' })); + g = K(g.replace(/<[a-zA-Z\/](.|\n)*?>/g, '') || ' '); + if (' ' !== g) { + e.appendChild(m.createTextNode(g)); + q ? (d.dx = 0) : y && null !== t && (d.x = t); + f(e, d); + b.appendChild(e); + !q && + I && + (!L && c && n(e, { display: 'block' }), + f(e, 'dy', p(e))); + if (B) { + d = g.replace(/([^\^])-/g, '$1- ').split(' '); + x = 1 < k.length || y || (1 < d.length && !Q); + var O = [], + l, + C = p(e), + G = a.rotation; + for ( + u && (J = v.applyEllipsis(a, e, g, B)); + !u && x && (d.length || O.length); + + ) + (a.rotation = 0), + (l = v.getSpanWidth(a, e)), + (g = l > B), + void 0 === J && (J = g), + g && 1 !== d.length + ? (e.removeChild(e.firstChild), + O.unshift(d.pop())) + : ((d = O), + (O = []), + d.length && + !Q && + ((e = m.createElementNS(P, 'tspan')), + f(e, { dy: C, x: t }), + F && f(e, 'style', F), + b.appendChild(e)), + l > B && (B = l)), + d.length && + e.appendChild( + m.createTextNode( + d.join(' ').replace(/- /g, '-'), + ), + ); + a.rotation = G; + } + q++; + } + } + }); + I = I || b.childNodes.length; + }), + J && a.attr('title', a.textStr), + x && x.removeChild(b), + C && a.applyTextOutline && a.applyTextOutline(C)) + : b.appendChild(m.createTextNode(K(y))); + } + }, + getContrast: function(a) { + a = r(a).rgba; + return 510 < a[0] + a[1] + a[2] ? '#000000' : '#FFFFFF'; + }, + button: function(a, g, b, v, d, k, e, z, h) { + var y = this.label(a, g, b, h, null, null, null, null, 'button'), + m = 0; + y.attr(q({ padding: 8, r: 2 }, d)); + var A, L, J, t; + d = q( + { + fill: '#f7f7f7', + stroke: '#cccccc', + 'stroke-width': 1, + style: { + color: '#333333', + cursor: 'pointer', + fontWeight: 'normal', + }, + }, + d, + ); + A = d.style; + delete d.style; + k = q(d, { fill: '#e6e6e6' }, k); + L = k.style; + delete k.style; + e = q( + d, + { fill: '#e6ebf5', style: { color: '#000000', fontWeight: 'bold' } }, + e, + ); + J = e.style; + delete e.style; + z = q(d, { style: { color: '#cccccc' } }, z); + t = z.style; + delete z.style; + H(y.element, K ? 'mouseover' : 'mouseenter', function() { + 3 !== m && y.setState(1); + }); + H(y.element, K ? 'mouseout' : 'mouseleave', function() { + 3 !== m && y.setState(m); + }); + y.setState = function(a) { + 1 !== a && (y.state = m = a); + y.removeClass( + /highcharts-button-(normal|hover|pressed|disabled)/, + ).addClass( + 'highcharts-button-' + + ['normal', 'hover', 'pressed', 'disabled'][a || 0], + ); + y.attr([d, k, e, z][a || 0]).css([A, L, J, t][a || 0]); + }; + y.attr(d).css(c({ cursor: 'default' }, A)); + return y.on('click', function(a) { + 3 !== m && v.call(y, a); + }); + }, + crispLine: function(a, g) { + a[1] === a[4] && (a[1] = a[4] = Math.round(a[1]) - (g % 2) / 2); + a[2] === a[5] && (a[2] = a[5] = Math.round(a[2]) + (g % 2) / 2); + return a; + }, + path: function(a) { + var g = { fill: 'none' }; + I(a) ? (g.d = a) : t(a) && c(g, a); + return this.createElement('path').attr(g); + }, + circle: function(a, g, b) { + a = t(a) ? a : { x: a, y: g, r: b }; + g = this.createElement('circle'); + g.xSetter = g.ySetter = function(a, g, b) { + b.setAttribute('c' + g, a); + }; + return g.attr(a); + }, + arc: function(a, g, b, v, c, d) { + t(a) + ? ((v = a), (g = v.y), (b = v.r), (a = v.x)) + : (v = { innerR: v, start: c, end: d }); + a = this.symbol('arc', a, g, b, b, v); + a.r = b; + return a; + }, + rect: function(a, g, b, v, c, d) { + c = t(a) ? a.r : c; + var k = this.createElement('rect'); + a = t(a) + ? a + : void 0 === a + ? {} + : { x: a, y: g, width: Math.max(b, 0), height: Math.max(v, 0) }; + void 0 !== d && ((a.strokeWidth = d), (a = k.crisp(a))); + a.fill = 'none'; + c && (a.r = c); + k.rSetter = function(a, g, b) { + f(b, { rx: a, ry: a }); + }; + return k.attr(a); + }, + setSize: function(a, g, b) { + var v = this.alignedObjects, + c = v.length; + this.width = a; + this.height = g; + for ( + this.boxWrapper.animate( + { width: a, height: g }, + { + step: function() { + this.attr({ + viewBox: + '0 0 ' + this.attr('width') + ' ' + this.attr('height'), + }); + }, + duration: G(b, !0) ? void 0 : 0, + }, + ); + c--; + + ) + v[c].align(); + }, + g: function(a) { + var g = this.createElement('g'); + return a ? g.attr({ class: 'highcharts-' + a }) : g; + }, + image: function(a, g, b, v, d) { + var k = { preserveAspectRatio: 'none' }; + 1 < arguments.length && c(k, { x: g, y: b, width: v, height: d }); + k = this.createElement('image').attr(k); + k.element.setAttributeNS + ? k.element.setAttributeNS('http://www.w3.org/1999/xlink', 'href', a) + : k.element.setAttribute('hc-svg-href', a); + return k; + }, + symbol: function(a, g, b, v, k, q) { + var e = this, + y, + z = /^url\((.*?)\)$/, + h = z.test(a), + A = !h && (this.symbols[a] ? a : 'circle'), + L = A && this.symbols[A], + t = + u(g) && + L && + L.call(this.symbols, Math.round(g), Math.round(b), v, k, q), + x, + F; + L + ? ((y = this.path(t)), + y.attr('fill', 'none'), + c(y, { symbolName: A, x: g, y: b, width: v, height: k }), + q && c(y, q)) + : h && + ((x = a.match(z)[1]), + (y = this.image(x)), + (y.imgwidth = G(J[x] && J[x].width, q && q.width)), + (y.imgheight = G(J[x] && J[x].height, q && q.height)), + (F = function() { + y.attr({ width: y.width, height: y.height }); + }), + d(['width', 'height'], function(a) { + y[a + 'Setter'] = function(a, g) { + var b = {}, + v = this['img' + g], + c = 'width' === g ? 'translateX' : 'translateY'; + this[g] = a; + u(v) && + (this.element && this.element.setAttribute(g, v), + this.alignByTranslate || + ((b[c] = ((this[g] || 0) - v) / 2), this.attr(b))); + }; + }), + u(g) && y.attr({ x: g, y: b }), + (y.isImg = !0), + u(y.imgwidth) && u(y.imgheight) + ? F() + : (y.attr({ width: 0, height: 0 }), + w('img', { + onload: function() { + var a = l[e.chartIndex]; + 0 === this.width && + (n(this, { position: 'absolute', top: '-999em' }), + m.body.appendChild(this)); + J[x] = { width: this.width, height: this.height }; + y.imgwidth = this.width; + y.imgheight = this.height; + y.element && F(); + this.parentNode && this.parentNode.removeChild(this); + e.imgCount--; + if (!e.imgCount && a && a.onload) a.onload(); + }, + src: x, + }), + this.imgCount++)); + return y; + }, + symbols: { + circle: function(a, g, b, v) { + return this.arc(a + b / 2, g + v / 2, b / 2, v / 2, { + start: 0, + end: 2 * Math.PI, + open: !1, + }); + }, + square: function(a, g, b, v) { + return ['M', a, g, 'L', a + b, g, a + b, g + v, a, g + v, 'Z']; + }, + triangle: function(a, g, b, v) { + return ['M', a + b / 2, g, 'L', a + b, g + v, a, g + v, 'Z']; + }, + 'triangle-down': function(a, g, b, v) { + return ['M', a, g, 'L', a + b, g, a + b / 2, g + v, 'Z']; + }, + diamond: function(a, g, b, v) { + return [ + 'M', + a + b / 2, + g, + 'L', + a + b, + g + v / 2, + a + b / 2, + g + v, + a, + g + v / 2, + 'Z', + ]; + }, + arc: function(a, g, b, v, c) { + var k = c.start, + d = c.r || b, + q = c.r || v || b, + e = c.end - 0.001; + b = c.innerR; + v = G(c.open, 0.001 > Math.abs(c.end - c.start - 2 * Math.PI)); + var y = Math.cos(k), + z = Math.sin(k), + h = Math.cos(e), + e = Math.sin(e); + c = 0.001 > c.end - k - Math.PI ? 0 : 1; + d = [ + 'M', + a + d * y, + g + q * z, + 'A', + d, + q, + 0, + c, + 1, + a + d * h, + g + q * e, + ]; + u(b) && + d.push( + v ? 'M' : 'L', + a + b * h, + g + b * e, + 'A', + b, + b, + 0, + c, + 0, + a + b * y, + g + b * z, + ); + d.push(v ? '' : 'Z'); + return d; + }, + callout: function(a, g, b, v, c) { + var d = Math.min((c && c.r) || 0, b, v), + k = d + 6, + q = c && c.anchorX; + c = c && c.anchorY; + var e; + e = [ + 'M', + a + d, + g, + 'L', + a + b - d, + g, + 'C', + a + b, + g, + a + b, + g, + a + b, + g + d, + 'L', + a + b, + g + v - d, + 'C', + a + b, + g + v, + a + b, + g + v, + a + b - d, + g + v, + 'L', + a + d, + g + v, + 'C', + a, + g + v, + a, + g + v, + a, + g + v - d, + 'L', + a, + g + d, + 'C', + a, + g, + a, + g, + a + d, + g, + ]; + q && q > b + ? c > g + k && c < g + v - k + ? e.splice( + 13, + 3, + 'L', + a + b, + c - 6, + a + b + 6, + c, + a + b, + c + 6, + a + b, + g + v - d, + ) + : e.splice( + 13, + 3, + 'L', + a + b, + v / 2, + q, + c, + a + b, + v / 2, + a + b, + g + v - d, + ) + : q && 0 > q + ? c > g + k && c < g + v - k + ? e.splice(33, 3, 'L', a, c + 6, a - 6, c, a, c - 6, a, g + d) + : e.splice(33, 3, 'L', a, v / 2, q, c, a, v / 2, a, g + d) + : c && c > v && q > a + k && q < a + b - k + ? e.splice( + 23, + 3, + 'L', + q + 6, + g + v, + q, + g + v + 6, + q - 6, + g + v, + a + d, + g + v, + ) + : c && + 0 > c && + q > a + k && + q < a + b - k && + e.splice(3, 3, 'L', q - 6, g, q, g - 6, q + 6, g, b - d, g); + return e; + }, + }, + clipRect: function(g, b, v, c) { + var d = a.uniqueKey(), + k = this.createElement('clipPath') + .attr({ id: d }) + .add(this.defs); + g = this.rect(g, b, v, c, 0).add(k); + g.id = d; + g.clipPath = k; + g.count = 0; + return g; + }, + text: function(a, g, b, v) { + var c = {}; + if (v && (this.allowHTML || !this.forExport)) return this.html(a, g, b); + c.x = Math.round(g || 0); + b && (c.y = Math.round(b)); + if (a || 0 === a) c.text = a; + a = this.createElement('text').attr(c); + v || + (a.xSetter = function(a, g, b) { + var v = b.getElementsByTagName('tspan'), + c, + d = b.getAttribute(g), + k; + for (k = 0; k < v.length; k++) + (c = v[k]), c.getAttribute(g) === d && c.setAttribute(g, a); + b.setAttribute(g, a); + }); + return a; + }, + fontMetrics: function(a, b) { + a = + a || + (b && b.style && b.style.fontSize) || + (this.style && this.style.fontSize); + a = /px/.test(a) + ? g(a) + : /em/.test(a) + ? parseFloat(a) * (b ? this.fontMetrics(null, b.parentNode).f : 16) + : 12; + b = 24 > a ? a + 3 : Math.round(1.2 * a); + return { h: b, b: Math.round(0.8 * b), f: a }; + }, + rotCorr: function(a, g, b) { + var v = a; + g && b && (v = Math.max(v * Math.cos(g * e), 4)); + return { x: (-a / 3) * Math.sin(g * e), y: v }; + }, + label: function(g, b, k, e, z, h, m, A, L) { + var y = this, + J = y.g('button' !== L && 'label'), + t = (J.text = y.text('', 0, 0, m).attr({ zIndex: 1 })), + x, + F, + n = 0, + B = 3, + l = 0, + C, + f, + Q, + G, + w, + R = {}, + I, + P, + r = /^url\((.*?)\)$/.test(e), + p = r, + K, + O, + N, + T; + L && J.addClass('highcharts-' + L); + p = r; + K = function() { + return ((I || 0) % 2) / 2; + }; + O = function() { + var a = t.element.style, + g = {}; + F = + (void 0 === C || void 0 === f || w) && u(t.textStr) && t.getBBox(); + J.width = (C || F.width || 0) + 2 * B + l; + J.height = (f || F.height || 0) + 2 * B; + P = B + y.fontMetrics(a && a.fontSize, t).b; + p && + (x || + ((J.box = x = y.symbols[e] || r ? y.symbol(e) : y.rect()), + x.addClass( + ('button' === L ? '' : 'highcharts-label-box') + + (L ? ' highcharts-' + L + '-box' : ''), + ), + x.add(J), + (a = K()), + (g.x = a), + (g.y = (A ? -P : 0) + a)), + (g.width = Math.round(J.width)), + (g.height = Math.round(J.height)), + x.attr(c(g, R)), + (R = {})); + }; + N = function() { + var a = l + B, + g; + g = A ? 0 : P; + u(C) && + F && + ('center' === w || 'right' === w) && + (a += { center: 0.5, right: 1 }[w] * (C - F.width)); + if (a !== t.x || g !== t.y) + t.attr('x', a), void 0 !== g && t.attr('y', g); + t.x = a; + t.y = g; + }; + T = function(a, g) { + x ? x.attr(a, g) : (R[a] = g); + }; + J.onAdd = function() { + t.add(J); + J.attr({ text: g || 0 === g ? g : '', x: b, y: k }); + x && u(z) && J.attr({ anchorX: z, anchorY: h }); + }; + J.widthSetter = function(g) { + C = a.isNumber(g) ? g : null; + }; + J.heightSetter = function(a) { + f = a; + }; + J['text-alignSetter'] = function(a) { + w = a; + }; + J.paddingSetter = function(a) { + u(a) && a !== B && ((B = J.padding = a), N()); + }; + J.paddingLeftSetter = function(a) { + u(a) && a !== l && ((l = a), N()); + }; + J.alignSetter = function(a) { + a = { left: 0, center: 0.5, right: 1 }[a]; + a !== n && ((n = a), F && J.attr({ x: Q })); + }; + J.textSetter = function(a) { + void 0 !== a && t.textSetter(a); + O(); + N(); + }; + J['stroke-widthSetter'] = function(a, g) { + a && (p = !0); + I = this['stroke-width'] = a; + T(g, a); + }; + J.strokeSetter = J.fillSetter = J.rSetter = function(a, g) { + 'r' !== g && ('fill' === g && a && (p = !0), (J[g] = a)); + T(g, a); + }; + J.anchorXSetter = function(a, g) { + z = J.anchorX = a; + T(g, Math.round(a) - K() - Q); + }; + J.anchorYSetter = function(a, g) { + h = J.anchorY = a; + T(g, a - G); + }; + J.xSetter = function(a) { + J.x = a; + n && (a -= n * ((C || F.width) + 2 * B)); + Q = Math.round(a); + J.attr('translateX', Q); + }; + J.ySetter = function(a) { + G = J.y = Math.round(a); + J.attr('translateY', G); + }; + var U = J.css; + return c(J, { + css: function(a) { + if (a) { + var g = {}; + a = q(a); + d(J.textProps, function(b) { + void 0 !== a[b] && ((g[b] = a[b]), delete a[b]); + }); + t.css(g); + } + return U.call(J, a); + }, + getBBox: function() { + return { + width: F.width + 2 * B, + height: F.height + 2 * B, + x: F.x - B, + y: F.y - B, + }; + }, + shadow: function(a) { + a && (O(), x && x.shadow(a)); + return J; + }, + destroy: function() { + v(J.element, 'mouseenter'); + v(J.element, 'mouseleave'); + t && (t = t.destroy()); + x && (x = x.destroy()); + E.prototype.destroy.call(J); + J = y = O = N = T = null; + }, + }); + }, + }); + a.Renderer = D; + })(M); + (function(a) { + var E = a.attr, + D = a.createElement, + H = a.css, + p = a.defined, + f = a.each, + l = a.extend, + r = a.isFirefox, + n = a.isMS, + w = a.isWebKit, + u = a.pick, + e = a.pInt, + h = a.SVGRenderer, + m = a.win, + d = a.wrap; + l(a.SVGElement.prototype, { + htmlCss: function(a) { + var b = this.element; + if ((b = a && 'SPAN' === b.tagName && a.width)) + delete a.width, (this.textWidth = b), this.updateTransform(); + a && + 'ellipsis' === a.textOverflow && + ((a.whiteSpace = 'nowrap'), (a.overflow = 'hidden')); + this.styles = l(this.styles, a); + H(this.element, a); + return this; + }, + htmlGetBBox: function() { + var a = this.element; + return { + x: a.offsetLeft, + y: a.offsetTop, + width: a.offsetWidth, + height: a.offsetHeight, + }; + }, + htmlUpdateTransform: function() { + if (this.added) { + var a = this.renderer, + b = this.element, + d = this.translateX || 0, + z = this.translateY || 0, + h = this.x || 0, + m = this.y || 0, + x = this.textAlign || 'left', + n = { left: 0, center: 0.5, right: 1 }[x], + t = this.styles; + H(b, { marginLeft: d, marginTop: z }); + this.shadows && + f(this.shadows, function(a) { + H(a, { marginLeft: d + 1, marginTop: z + 1 }); + }); + this.inverted && + f(b.childNodes, function(c) { + a.invertChild(c, b); + }); + if ('SPAN' === b.tagName) { + var l = this.rotation, + u = e(this.textWidth), + q = t && t.whiteSpace, + A = [l, x, b.innerHTML, this.textWidth, this.textAlign].join(); + A !== this.cTT && + ((t = a.fontMetrics(b.style.fontSize).b), + p(l) && this.setSpanRotation(l, n, t), + H(b, { width: '', whiteSpace: q || 'nowrap' }), + b.offsetWidth > u && + /[ \-]/.test(b.textContent || b.innerText) && + H(b, { + width: u + 'px', + display: 'block', + whiteSpace: q || 'normal', + }), + this.getSpanCorrection(b.offsetWidth, t, n, l, x)); + H(b, { + left: h + (this.xCorr || 0) + 'px', + top: m + (this.yCorr || 0) + 'px', + }); + w && (t = b.offsetHeight); + this.cTT = A; + } + } else this.alignOnAdd = !0; + }, + setSpanRotation: function(a, b, d) { + var c = {}, + k = this.renderer.getTransformKey(); + c[k] = c.transform = 'rotate(' + a + 'deg)'; + c[k + (r ? 'Origin' : '-origin')] = c.transformOrigin = + 100 * b + '% ' + d + 'px'; + H(this.element, c); + }, + getSpanCorrection: function(a, b, d) { + this.xCorr = -a * d; + this.yCorr = -b; + }, + }); + l(h.prototype, { + getTransformKey: function() { + return n && !/Edge/.test(m.navigator.userAgent) + ? '-ms-transform' + : w + ? '-webkit-transform' + : r + ? 'MozTransform' + : m.opera + ? '-o-transform' + : ''; + }, + html: function(a, b, k) { + var c = this.createElement('span'), + e = c.element, + h = c.renderer, + m = h.isSVG, + w = function(a, b) { + f(['opacity', 'visibility'], function(c) { + d(a, c + 'Setter', function(a, c, d, k) { + a.call(this, c, d, k); + b[d] = c; + }); + }); + }; + c.textSetter = function(a) { + a !== e.innerHTML && delete this.bBox; + this.textStr = a; + e.innerHTML = u(a, ''); + c.htmlUpdateTransform(); + }; + m && w(c, c.element.style); + c.xSetter = c.ySetter = c.alignSetter = c.rotationSetter = function( + a, + b, + ) { + 'align' === b && (b = 'textAlign'); + c[b] = a; + c.htmlUpdateTransform(); + }; + c.attr({ text: a, x: Math.round(b), y: Math.round(k) }).css({ + fontFamily: this.style.fontFamily, + fontSize: this.style.fontSize, + position: 'absolute', + }); + e.style.whiteSpace = 'nowrap'; + c.css = c.htmlCss; + m && + (c.add = function(a) { + var b, + d = h.box.parentNode, + k = []; + if ((this.parentGroup = a)) { + if (((b = a.div), !b)) { + for (; a; ) k.push(a), (a = a.parentGroup); + f(k.reverse(), function(a) { + function e(g, b) { + a[b] = g; + n + ? (q[h.getTransformKey()] = + 'translate(' + + (a.x || a.translateX) + + 'px,' + + (a.y || a.translateY) + + 'px)') + : 'translateX' === b + ? (q.left = g + 'px') + : (q.top = g + 'px'); + a.doTransform = !0; + } + var q, + g = E(a.element, 'class'); + g && (g = { className: g }); + b = a.div = + a.div || + D( + 'div', + g, + { + position: 'absolute', + left: (a.translateX || 0) + 'px', + top: (a.translateY || 0) + 'px', + display: a.display, + opacity: a.opacity, + pointerEvents: a.styles && a.styles.pointerEvents, + }, + b || d, + ); + q = b.style; + l(a, { + classSetter: (function(a) { + return function(g) { + this.element.setAttribute('class', g); + a.className = g; + }; + })(b), + on: function() { + k[0].div && c.on.apply({ element: k[0].div }, arguments); + return a; + }, + translateXSetter: e, + translateYSetter: e, + }); + w(a, q); + }); + } + } else b = d; + b.appendChild(e); + c.added = !0; + c.alignOnAdd && c.htmlUpdateTransform(); + return c; + }); + return c; + }, + }); + })(M); + (function(a) { + function E() { + var n = a.defaultOptions.global, + l = r.moment; + if (n.timezone) { + if (l) + return function(a) { + return -l.tz(a, n.timezone).utcOffset(); + }; + a.error(25); + } + return n.useUTC && n.getTimezoneOffset; + } + function D() { + var n = a.defaultOptions.global, + f, + u = n.useUTC, + e = u ? 'getUTC' : 'get', + h = u ? 'setUTC' : 'set', + m = 'Minutes Hours Day Date Month FullYear'.split(' '), + d = m.concat(['Milliseconds', 'Seconds']); + a.Date = f = n.Date || r.Date; + f.hcTimezoneOffset = u && n.timezoneOffset; + f.hcGetTimezoneOffset = E(); + f.hcHasTimeZone = !(!f.hcTimezoneOffset && !f.hcGetTimezoneOffset); + f.hcMakeTime = function(a, b, d, e, h, m) { + var c; + u + ? ((c = f.UTC.apply(0, arguments)), (c += p(c))) + : (c = new f(a, b, l(d, 1), l(e, 0), l(h, 0), l(m, 0)).getTime()); + return c; + }; + for (n = 0; n < m.length; n++) f['hcGet' + m[n]] = e + m[n]; + for (n = 0; n < d.length; n++) f['hcSet' + d[n]] = h + d[n]; + } + var H = a.color, + p = a.getTZOffset, + f = a.merge, + l = a.pick, + r = a.win; + a.defaultOptions = { + colors: '#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1'.split( + ' ', + ), + symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'], + lang: { + loading: 'Loading...', + months: 'January February March April May June July August September October November December'.split( + ' ', + ), + shortMonths: 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split( + ' ', + ), + weekdays: 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split( + ' ', + ), + decimalPoint: '.', + numericSymbols: 'kMGTPE'.split(''), + resetZoom: 'Reset zoom', + resetZoomTitle: 'Reset zoom level 1:1', + thousandsSep: ' ', + }, + global: { useUTC: !0 }, + chart: { + borderRadius: 0, + defaultSeriesType: 'line', + ignoreHiddenSeries: !0, + spacing: [10, 10, 15, 10], + resetZoomButton: { + theme: { zIndex: 6 }, + position: { align: 'right', x: -10, y: 10 }, + }, + width: null, + height: null, + borderColor: '#335cad', + backgroundColor: '#ffffff', + plotBorderColor: '#cccccc', + }, + title: { + text: 'Chart title', + align: 'center', + margin: 15, + widthAdjust: -44, + }, + subtitle: { text: '', align: 'center', widthAdjust: -44 }, + plotOptions: {}, + labels: { style: { position: 'absolute', color: '#333333' } }, + legend: { + enabled: !0, + align: 'center', + layout: 'horizontal', + labelFormatter: function() { + return this.name; + }, + borderColor: '#999999', + borderRadius: 0, + navigation: { activeColor: '#003399', inactiveColor: '#cccccc' }, + itemStyle: { + color: '#333333', + fontSize: '12px', + fontWeight: 'bold', + textOverflow: 'ellipsis', + }, + itemHoverStyle: { color: '#000000' }, + itemHiddenStyle: { color: '#cccccc' }, + shadow: !1, + itemCheckboxStyle: { + position: 'absolute', + width: '13px', + height: '13px', + }, + squareSymbol: !0, + symbolPadding: 5, + verticalAlign: 'bottom', + x: 0, + y: 0, + title: { style: { fontWeight: 'bold' } }, + }, + loading: { + labelStyle: { fontWeight: 'bold', position: 'relative', top: '45%' }, + style: { + position: 'absolute', + backgroundColor: '#ffffff', + opacity: 0.5, + textAlign: 'center', + }, + }, + tooltip: { + enabled: !0, + animation: a.svg, + borderRadius: 3, + dateTimeLabelFormats: { + millisecond: '%A, %b %e, %H:%M:%S.%L', + second: '%A, %b %e, %H:%M:%S', + minute: '%A, %b %e, %H:%M', + hour: '%A, %b %e, %H:%M', + day: '%A, %b %e, %Y', + week: 'Week from %A, %b %e, %Y', + month: '%B %Y', + year: '%Y', + }, + footerFormat: '', + padding: 8, + snap: a.isTouchDevice ? 25 : 10, + backgroundColor: H('#f7f7f7') + .setOpacity(0.85) + .get(), + borderWidth: 1, + headerFormat: + '\x3cspan style\x3d"font-size: 10px"\x3e{point.key}\x3c/span\x3e\x3cbr/\x3e', + pointFormat: + '\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e {series.name}: \x3cb\x3e{point.y}\x3c/b\x3e\x3cbr/\x3e', + shadow: !0, + style: { + color: '#333333', + cursor: 'default', + fontSize: '12px', + pointerEvents: 'none', + whiteSpace: 'nowrap', + }, + }, + credits: { + enabled: !0, + href: 'http://www.highcharts.com', + position: { align: 'right', x: -10, verticalAlign: 'bottom', y: -5 }, + style: { cursor: 'pointer', color: '#999999', fontSize: '9px' }, + text: 'Highcharts.com', + }, + }; + a.setOptions = function(n) { + a.defaultOptions = f(!0, a.defaultOptions, n); + D(); + return a.defaultOptions; + }; + a.getOptions = function() { + return a.defaultOptions; + }; + a.defaultPlotOptions = a.defaultOptions.plotOptions; + D(); + })(M); + (function(a) { + var E = a.correctFloat, + D = a.defined, + H = a.destroyObjectProperties, + p = a.isNumber, + f = a.merge, + l = a.pick, + r = a.deg2rad; + a.Tick = function(a, l, f, e) { + this.axis = a; + this.pos = l; + this.type = f || ''; + this.isNewLabel = this.isNew = !0; + f || e || this.addLabel(); + }; + a.Tick.prototype = { + addLabel: function() { + var a = this.axis, + w = a.options, + u = a.chart, + e = a.categories, + h = a.names, + m = this.pos, + d = w.labels, + c = a.tickPositions, + b = m === c[0], + k = m === c[c.length - 1], + h = e ? l(e[m], h[m], m) : m, + e = this.label, + c = c.info, + z; + a.isDatetimeAxis && + c && + (z = w.dateTimeLabelFormats[c.higherRanks[m] || c.unitName]); + this.isFirst = b; + this.isLast = k; + w = a.labelFormatter.call({ + axis: a, + chart: u, + isFirst: b, + isLast: k, + dateTimeLabelFormat: z, + value: a.isLog ? E(a.lin2log(h)) : h, + pos: m, + }); + D(e) + ? e && e.attr({ text: w }) + : ((this.labelLength = + (this.label = e = + D(w) && d.enabled + ? u.renderer + .text(w, 0, 0, d.useHTML) + .css(f(d.style)) + .add(a.labelGroup) + : null) && e.getBBox().width), + (this.rotation = 0)); + }, + getLabelSize: function() { + return this.label + ? this.label.getBBox()[this.axis.horiz ? 'height' : 'width'] + : 0; + }, + handleOverflow: function(a) { + var f = this.axis, + n = f.options.labels, + e = a.x, + h = f.chart.chartWidth, + m = f.chart.spacing, + d = l(f.labelLeft, Math.min(f.pos, m[3])), + m = l( + f.labelRight, + Math.max(f.isRadial ? 0 : f.pos + f.len, h - m[1]), + ), + c = this.label, + b = this.rotation, + k = { left: 0, center: 0.5, right: 1 }[ + f.labelAlign || c.attr('align') + ], + z = c.getBBox().width, + B = f.getSlotWidth(), + I = B, + x = 1, + p, + t = {}; + if (b || !1 === n.overflow) + 0 > b && e - k * z < d + ? (p = Math.round(e / Math.cos(b * r) - d)) + : 0 < b && + e + k * z > m && + (p = Math.round((h - e) / Math.cos(b * r))); + else if ( + ((h = e + (1 - k) * z), + e - k * z < d + ? (I = a.x + I * (1 - k) - d) + : h > m && ((I = m - a.x + I * k), (x = -1)), + (I = Math.min(B, I)), + I < B && + 'center' === f.labelAlign && + (a.x += x * (B - I - k * (B - Math.min(z, I)))), + z > I || (f.autoRotation && (c.styles || {}).width)) + ) + p = I; + p && + ((t.width = p), + (n.style || {}).textOverflow || (t.textOverflow = 'ellipsis'), + c.css(t)); + }, + getPosition: function(a, f, l, e) { + var h = this.axis, + m = h.chart, + d = (e && m.oldChartHeight) || m.chartHeight; + return { + x: a + ? h.translate(f + l, null, null, e) + h.transB + : h.left + + h.offset + + (h.opposite + ? ((e && m.oldChartWidth) || m.chartWidth) - h.right - h.left + : 0), + y: a + ? d - h.bottom + h.offset - (h.opposite ? h.height : 0) + : d - h.translate(f + l, null, null, e) - h.transB, + }; + }, + getLabelPosition: function(a, f, l, e, h, m, d, c) { + var b = this.axis, + k = b.transA, + z = b.reversed, + B = b.staggerLines, + n = b.tickRotCorr || { x: 0, y: 0 }, + x = h.y, + u = + e || b.reserveSpaceDefault + ? 0 + : -b.labelOffset * ('center' === b.labelAlign ? 0.5 : 1); + D(x) || + (x = + 0 === b.side + ? l.rotation + ? -8 + : -l.getBBox().height + : 2 === b.side + ? n.y + 8 + : Math.cos(l.rotation * r) * (n.y - l.getBBox(!1, 0).height / 2)); + a = a + h.x + u + n.x - (m && e ? m * k * (z ? -1 : 1) : 0); + f = f + x - (m && !e ? m * k * (z ? 1 : -1) : 0); + B && + ((l = (d / (c || 1)) % B), + b.opposite && (l = B - l - 1), + (f += (b.labelOffset / B) * l)); + return { x: a, y: Math.round(f) }; + }, + getMarkPath: function(a, f, l, e, h, m) { + return m.crispLine( + ['M', a, f, 'L', a + (h ? 0 : -l), f + (h ? l : 0)], + e, + ); + }, + renderGridLine: function(a, f, l) { + var e = this.axis, + h = e.options, + m = this.gridLine, + d = {}, + c = this.pos, + b = this.type, + k = e.tickmarkOffset, + z = e.chart.renderer, + B = b ? b + 'Grid' : 'grid', + n = h[B + 'LineWidth'], + x = h[B + 'LineColor'], + h = h[B + 'LineDashStyle']; + m || + ((d.stroke = x), + (d['stroke-width'] = n), + h && (d.dashstyle = h), + b || (d.zIndex = 1), + a && (d.opacity = 0), + (this.gridLine = m = z + .path() + .attr(d) + .addClass('highcharts-' + (b ? b + '-' : '') + 'grid-line') + .add(e.gridGroup))); + if ( + !a && + m && + (a = e.getPlotLinePath(c + k, m.strokeWidth() * l, a, !0)) + ) + m[this.isNew ? 'attr' : 'animate']({ d: a, opacity: f }); + }, + renderMark: function(a, f, u) { + var e = this.axis, + h = e.options, + m = e.chart.renderer, + d = this.type, + c = d ? d + 'Tick' : 'tick', + b = e.tickSize(c), + k = this.mark, + z = !k, + B = a.x; + a = a.y; + var n = l(h[c + 'Width'], !d && e.isXAxis ? 1 : 0), + h = h[c + 'Color']; + b && + (e.opposite && (b[0] = -b[0]), + z && + ((this.mark = k = m + .path() + .addClass('highcharts-' + (d ? d + '-' : '') + 'tick') + .add(e.axisGroup)), + k.attr({ stroke: h, 'stroke-width': n })), + k[z ? 'attr' : 'animate']({ + d: this.getMarkPath(B, a, b[0], k.strokeWidth() * u, e.horiz, m), + opacity: f, + })); + }, + renderLabel: function(a, f, u, e) { + var h = this.axis, + m = h.horiz, + d = h.options, + c = this.label, + b = d.labels, + k = b.step, + h = h.tickmarkOffset, + z = !0, + B = a.x; + a = a.y; + c && + p(B) && + ((c.xy = a = this.getLabelPosition(B, a, c, m, b, h, e, k)), + (this.isFirst && !this.isLast && !l(d.showFirstLabel, 1)) || + (this.isLast && !this.isFirst && !l(d.showLastLabel, 1)) + ? (z = !1) + : !m || + b.step || + b.rotation || + f || + 0 === u || + this.handleOverflow(a), + k && e % k && (z = !1), + z && p(a.y) + ? ((a.opacity = u), + c[this.isNewLabel ? 'attr' : 'animate'](a), + (this.isNewLabel = !1)) + : (c.attr('y', -9999), (this.isNewLabel = !0))); + }, + render: function(a, f, u) { + var e = this.axis, + h = e.horiz, + m = this.getPosition(h, this.pos, e.tickmarkOffset, f), + d = m.x, + c = m.y, + e = (h && d === e.pos + e.len) || (!h && c === e.pos) ? -1 : 1; + u = l(u, 1); + this.isActive = !0; + this.renderGridLine(f, u, e); + this.renderMark(m, u, e); + this.renderLabel(m, f, u, a); + this.isNew = !1; + }, + destroy: function() { + H(this, this.axis); + }, + }; + })(M); + var V = (function(a) { + var E = a.addEvent, + D = a.animObject, + H = a.arrayMax, + p = a.arrayMin, + f = a.color, + l = a.correctFloat, + r = a.defaultOptions, + n = a.defined, + w = a.deg2rad, + u = a.destroyObjectProperties, + e = a.each, + h = a.extend, + m = a.fireEvent, + d = a.format, + c = a.getMagnitude, + b = a.grep, + k = a.inArray, + z = a.isArray, + B = a.isNumber, + I = a.isString, + x = a.merge, + K = a.normalizeTickInterval, + t = a.objectEach, + C = a.pick, + N = a.removeEvent, + q = a.splat, + A = a.syncTimeout, + F = a.Tick, + G = function() { + this.init.apply(this, arguments); + }; + a.extend(G.prototype, { + defaultOptions: { + dateTimeLabelFormats: { + millisecond: '%H:%M:%S.%L', + second: '%H:%M:%S', + minute: '%H:%M', + hour: '%H:%M', + day: '%e. %b', + week: '%e. %b', + month: "%b '%y", + year: '%Y', + }, + endOnTick: !1, + labels: { + enabled: !0, + style: { color: '#666666', cursor: 'default', fontSize: '11px' }, + x: 0, + }, + maxPadding: 0.01, + minorTickLength: 2, + minorTickPosition: 'outside', + minPadding: 0.01, + startOfWeek: 1, + startOnTick: !1, + tickLength: 10, + tickmarkPlacement: 'between', + tickPixelInterval: 100, + tickPosition: 'outside', + title: { align: 'middle', style: { color: '#666666' } }, + type: 'linear', + minorGridLineColor: '#f2f2f2', + minorGridLineWidth: 1, + minorTickColor: '#999999', + lineColor: '#ccd6eb', + lineWidth: 1, + gridLineColor: '#e6e6e6', + tickColor: '#ccd6eb', + }, + defaultYAxisOptions: { + endOnTick: !0, + tickPixelInterval: 72, + showLastLabel: !0, + labels: { x: -8 }, + maxPadding: 0.05, + minPadding: 0.05, + startOnTick: !0, + title: { rotation: 270, text: 'Values' }, + stackLabels: { + allowOverlap: !1, + enabled: !1, + formatter: function() { + return a.numberFormat(this.total, -1); + }, + style: { + fontSize: '11px', + fontWeight: 'bold', + color: '#000000', + textOutline: '1px contrast', + }, + }, + gridLineWidth: 1, + lineWidth: 0, + }, + defaultLeftAxisOptions: { labels: { x: -15 }, title: { rotation: 270 } }, + defaultRightAxisOptions: { labels: { x: 15 }, title: { rotation: 90 } }, + defaultBottomAxisOptions: { + labels: { autoRotation: [-45], x: 0 }, + title: { rotation: 0 }, + }, + defaultTopAxisOptions: { + labels: { autoRotation: [-45], x: 0 }, + title: { rotation: 0 }, + }, + init: function(a, b) { + var g = b.isX, + v = this; + v.chart = a; + v.horiz = a.inverted && !v.isZAxis ? !g : g; + v.isXAxis = g; + v.coll = v.coll || (g ? 'xAxis' : 'yAxis'); + v.opposite = b.opposite; + v.side = + b.side || (v.horiz ? (v.opposite ? 0 : 2) : v.opposite ? 1 : 3); + v.setOptions(b); + var c = this.options, + d = c.type; + v.labelFormatter = c.labels.formatter || v.defaultLabelFormatter; + v.userOptions = b; + v.minPixelPadding = 0; + v.reversed = c.reversed; + v.visible = !1 !== c.visible; + v.zoomEnabled = !1 !== c.zoomEnabled; + v.hasNames = 'category' === d || !0 === c.categories; + v.categories = c.categories || v.hasNames; + v.names = v.names || []; + v.plotLinesAndBandsGroups = {}; + v.isLog = 'logarithmic' === d; + v.isDatetimeAxis = 'datetime' === d; + v.positiveValuesOnly = v.isLog && !v.allowNegativeLog; + v.isLinked = n(c.linkedTo); + v.ticks = {}; + v.labelEdge = []; + v.minorTicks = {}; + v.plotLinesAndBands = []; + v.alternateBands = {}; + v.len = 0; + v.minRange = v.userMinRange = c.minRange || c.maxZoom; + v.range = c.range; + v.offset = c.offset || 0; + v.stacks = {}; + v.oldStacks = {}; + v.stacksTouched = 0; + v.max = null; + v.min = null; + v.crosshair = C( + c.crosshair, + q(a.options.tooltip.crosshairs)[g ? 0 : 1], + !1, + ); + b = v.options.events; + -1 === k(v, a.axes) && + (g ? a.axes.splice(a.xAxis.length, 0, v) : a.axes.push(v), + a[v.coll].push(v)); + v.series = v.series || []; + a.inverted && + !v.isZAxis && + g && + void 0 === v.reversed && + (v.reversed = !0); + t(b, function(a, g) { + E(v, g, a); + }); + v.lin2log = c.linearToLogConverter || v.lin2log; + v.isLog && ((v.val2lin = v.log2lin), (v.lin2val = v.lin2log)); + }, + setOptions: function(a) { + this.options = x( + this.defaultOptions, + 'yAxis' === this.coll && this.defaultYAxisOptions, + [ + this.defaultTopAxisOptions, + this.defaultRightAxisOptions, + this.defaultBottomAxisOptions, + this.defaultLeftAxisOptions, + ][this.side], + x(r[this.coll], a), + ); + }, + defaultLabelFormatter: function() { + var g = this.axis, + b = this.value, + c = g.categories, + k = this.dateTimeLabelFormat, + e = r.lang, + q = e.numericSymbols, + e = e.numericSymbolMagnitude || 1e3, + h = q && q.length, + m, + z = g.options.labels.format, + g = g.isLog ? Math.abs(b) : g.tickInterval; + if (z) m = d(z, this); + else if (c) m = b; + else if (k) m = a.dateFormat(k, b); + else if (h && 1e3 <= g) + for (; h-- && void 0 === m; ) + (c = Math.pow(e, h + 1)), + g >= c && + 0 === (10 * b) % c && + null !== q[h] && + 0 !== b && + (m = a.numberFormat(b / c, -1) + q[h]); + void 0 === m && + (m = + 1e4 <= Math.abs(b) + ? a.numberFormat(b, -1) + : a.numberFormat(b, -1, void 0, '')); + return m; + }, + getSeriesExtremes: function() { + var a = this, + v = a.chart; + a.hasVisibleSeries = !1; + a.dataMin = a.dataMax = a.threshold = null; + a.softThreshold = !a.isXAxis; + a.buildStacks && a.buildStacks(); + e(a.series, function(g) { + if (g.visible || !v.options.chart.ignoreHiddenSeries) { + var c = g.options, + d = c.threshold, + k; + a.hasVisibleSeries = !0; + a.positiveValuesOnly && 0 >= d && (d = null); + if (a.isXAxis) + (c = g.xData), + c.length && + ((g = p(c)), + (k = H(c)), + B(g) || g instanceof Date || ((c = b(c, B)), (g = p(c))), + (a.dataMin = Math.min(C(a.dataMin, c[0], g), g)), + (a.dataMax = Math.max(C(a.dataMax, c[0], k), k))); + else if ( + (g.getExtremes(), + (k = g.dataMax), + (g = g.dataMin), + n(g) && + n(k) && + ((a.dataMin = Math.min(C(a.dataMin, g), g)), + (a.dataMax = Math.max(C(a.dataMax, k), k))), + n(d) && (a.threshold = d), + !c.softThreshold || a.positiveValuesOnly) + ) + a.softThreshold = !1; + } + }); + }, + translate: function(a, b, c, d, k, e) { + var g = this.linkedParent || this, + v = 1, + q = 0, + h = d ? g.oldTransA : g.transA; + d = d ? g.oldMin : g.min; + var m = g.minPixelPadding; + k = (g.isOrdinal || g.isBroken || (g.isLog && k)) && g.lin2val; + h || (h = g.transA); + c && ((v *= -1), (q = g.len)); + g.reversed && ((v *= -1), (q -= v * (g.sector || g.len))); + b + ? ((a = (a * v + q - m) / h + d), k && (a = g.lin2val(a))) + : (k && (a = g.val2lin(a)), + (a = B(d) + ? v * (a - d) * h + q + v * m + (B(e) ? h * e : 0) + : void 0)); + return a; + }, + toPixels: function(a, b) { + return ( + this.translate(a, !1, !this.horiz, null, !0) + (b ? 0 : this.pos) + ); + }, + toValue: function(a, b) { + return this.translate( + a - (b ? 0 : this.pos), + !0, + !this.horiz, + null, + !0, + ); + }, + getPlotLinePath: function(a, b, c, d, k) { + var g = this.chart, + v = this.left, + q = this.top, + e, + h, + m = (c && g.oldChartHeight) || g.chartHeight, + z = (c && g.oldChartWidth) || g.chartWidth, + A; + e = this.transB; + var t = function(a, g, b) { + if (a < g || a > b) d ? (a = Math.min(Math.max(g, a), b)) : (A = !0); + return a; + }; + k = C(k, this.translate(a, null, null, c)); + a = c = Math.round(k + e); + e = h = Math.round(m - k - e); + B(k) + ? this.horiz + ? ((e = q), + (h = m - this.bottom), + (a = c = t(a, v, v + this.width))) + : ((a = v), + (c = z - this.right), + (e = h = t(e, q, q + this.height))) + : ((A = !0), (d = !1)); + return A && !d + ? null + : g.renderer.crispLine(['M', a, e, 'L', c, h], b || 1); + }, + getLinearTickPositions: function(a, b, c) { + var g, + v = l(Math.floor(b / a) * a); + c = l(Math.ceil(c / a) * a); + var d = [], + k; + l(v + a) === v && (k = 20); + if (this.single) return [b]; + for (b = v; b <= c; ) { + d.push(b); + b = l(b + a, k); + if (b === g) break; + g = b; + } + return d; + }, + getMinorTickInterval: function() { + var a = this.options; + return !0 === a.minorTicks + ? C(a.minorTickInterval, 'auto') + : !1 === a.minorTicks + ? null + : a.minorTickInterval; + }, + getMinorTickPositions: function() { + var a = this, + b = a.options, + c = a.tickPositions, + d = a.minorTickInterval, + k = [], + q = a.pointRangePadding || 0, + h = a.min - q, + q = a.max + q, + m = q - h; + if (m && m / d < a.len / 3) + if (a.isLog) + e(this.paddedTicks, function(g, b, v) { + b && + k.push.apply(k, a.getLogTickPositions(d, v[b - 1], v[b], !0)); + }); + else if (a.isDatetimeAxis && 'auto' === this.getMinorTickInterval()) + k = k.concat( + a.getTimeTicks( + a.normalizeTimeTickInterval(d), + h, + q, + b.startOfWeek, + ), + ); + else + for (b = h + ((c[0] - h) % d); b <= q && b !== k[0]; b += d) + k.push(b); + 0 !== k.length && a.trimTicks(k); + return k; + }, + adjustForMinRange: function() { + var a = this.options, + b = this.min, + c = this.max, + d, + k, + q, + h, + m, + z, + A, + t; + this.isXAxis && + void 0 === this.minRange && + !this.isLog && + (n(a.min) || n(a.max) + ? (this.minRange = null) + : (e(this.series, function(a) { + z = a.xData; + for (h = A = a.xIncrement ? 1 : z.length - 1; 0 < h; h--) + if (((m = z[h] - z[h - 1]), void 0 === q || m < q)) q = m; + }), + (this.minRange = Math.min(5 * q, this.dataMax - this.dataMin)))); + c - b < this.minRange && + ((k = this.dataMax - this.dataMin >= this.minRange), + (t = this.minRange), + (d = (t - c + b) / 2), + (d = [b - d, C(a.min, b - d)]), + k && (d[2] = this.isLog ? this.log2lin(this.dataMin) : this.dataMin), + (b = H(d)), + (c = [b + t, C(a.max, b + t)]), + k && (c[2] = this.isLog ? this.log2lin(this.dataMax) : this.dataMax), + (c = p(c)), + c - b < t && ((d[0] = c - t), (d[1] = C(a.min, c - t)), (b = H(d)))); + this.min = b; + this.max = c; + }, + getClosest: function() { + var a; + this.categories + ? (a = 1) + : e(this.series, function(g) { + var b = g.closestPointRange, + v = g.visible || !g.chart.options.chart.ignoreHiddenSeries; + !g.noSharedTooltip && + n(b) && + v && + (a = n(a) ? Math.min(a, b) : b); + }); + return a; + }, + nameToX: function(a) { + var g = z(this.categories), + b = g ? this.categories : this.names, + c = a.options.x, + d; + a.series.requireSorting = !1; + n(c) || + (c = + !1 === this.options.uniqueNames + ? a.series.autoIncrement() + : k(a.name, b)); + -1 === c ? g || (d = b.length) : (d = c); + void 0 !== d && (this.names[d] = a.name); + return d; + }, + updateNames: function() { + var a = this; + 0 < this.names.length && + ((this.names.length = 0), + (this.minRange = this.userMinRange), + e(this.series || [], function(g) { + g.xIncrement = null; + if (!g.points || g.isDirtyData) g.processData(), g.generatePoints(); + e(g.points, function(b, v) { + var c; + b.options && + ((c = a.nameToX(b)), + void 0 !== c && c !== b.x && ((b.x = c), (g.xData[v] = c))); + }); + })); + }, + setAxisTranslation: function(a) { + var g = this, + b = g.max - g.min, + c = g.axisPointRange || 0, + d, + k = 0, + q = 0, + h = g.linkedParent, + m = !!g.categories, + z = g.transA, + A = g.isXAxis; + if (A || m || c) + (d = g.getClosest()), + h + ? ((k = h.minPointOffset), (q = h.pointRangePadding)) + : e(g.series, function(a) { + var b = m + ? 1 + : A + ? C(a.options.pointRange, d, 0) + : g.axisPointRange || 0; + a = a.options.pointPlacement; + c = Math.max(c, b); + g.single || + ((k = Math.max(k, I(a) ? 0 : b / 2)), + (q = Math.max(q, 'on' === a ? 0 : b))); + }), + (h = g.ordinalSlope && d ? g.ordinalSlope / d : 1), + (g.minPointOffset = k *= h), + (g.pointRangePadding = q *= h), + (g.pointRange = Math.min(c, b)), + A && (g.closestPointRange = d); + a && (g.oldTransA = z); + g.translationSlope = g.transA = z = + g.options.staticScale || g.len / (b + q || 1); + g.transB = g.horiz ? g.left : g.bottom; + g.minPixelPadding = z * k; + }, + minFromRange: function() { + return this.max - this.range; + }, + setTickInterval: function(g) { + var b = this, + d = b.chart, + k = b.options, + q = b.isLog, + h = b.log2lin, + z = b.isDatetimeAxis, + A = b.isXAxis, + t = b.isLinked, + x = k.maxPadding, + f = k.minPadding, + F = k.tickInterval, + u = k.tickPixelInterval, + G = b.categories, + p = b.threshold, + I = b.softThreshold, + r, + w, + N, + D; + z || G || t || this.getTickAmount(); + N = C(b.userMin, k.min); + D = C(b.userMax, k.max); + t + ? ((b.linkedParent = d[b.coll][k.linkedTo]), + (d = b.linkedParent.getExtremes()), + (b.min = C(d.min, d.dataMin)), + (b.max = C(d.max, d.dataMax)), + k.type !== b.linkedParent.options.type && a.error(11, 1)) + : (!I && + n(p) && + (b.dataMin >= p + ? ((r = p), (f = 0)) + : b.dataMax <= p && ((w = p), (x = 0))), + (b.min = C(N, r, b.dataMin)), + (b.max = C(D, w, b.dataMax))); + q && + (b.positiveValuesOnly && + !g && + 0 >= Math.min(b.min, C(b.dataMin, b.min)) && + a.error(10, 1), + (b.min = l(h(b.min), 15)), + (b.max = l(h(b.max), 15))); + b.range && + n(b.max) && + ((b.userMin = b.min = N = Math.max(b.dataMin, b.minFromRange())), + (b.userMax = D = b.max), + (b.range = null)); + m(b, 'foundExtremes'); + b.beforePadding && b.beforePadding(); + b.adjustForMinRange(); + !(G || b.axisPointRange || b.usePercentage || t) && + n(b.min) && + n(b.max) && + (h = b.max - b.min) && + (!n(N) && f && (b.min -= h * f), !n(D) && x && (b.max += h * x)); + B(k.softMin) && !B(b.userMin) && (b.min = Math.min(b.min, k.softMin)); + B(k.softMax) && !B(b.userMax) && (b.max = Math.max(b.max, k.softMax)); + B(k.floor) && (b.min = Math.max(b.min, k.floor)); + B(k.ceiling) && (b.max = Math.min(b.max, k.ceiling)); + I && + n(b.dataMin) && + ((p = p || 0), + !n(N) && b.min < p && b.dataMin >= p + ? (b.min = p) + : !n(D) && b.max > p && b.dataMax <= p && (b.max = p)); + b.tickInterval = + b.min === b.max || void 0 === b.min || void 0 === b.max + ? 1 + : t && !F && u === b.linkedParent.options.tickPixelInterval + ? (F = b.linkedParent.tickInterval) + : C( + F, + this.tickAmount + ? (b.max - b.min) / Math.max(this.tickAmount - 1, 1) + : void 0, + G ? 1 : ((b.max - b.min) * u) / Math.max(b.len, u), + ); + A && + !g && + e(b.series, function(a) { + a.processData(b.min !== b.oldMin || b.max !== b.oldMax); + }); + b.setAxisTranslation(!0); + b.beforeSetTickPositions && b.beforeSetTickPositions(); + b.postProcessTickInterval && + (b.tickInterval = b.postProcessTickInterval(b.tickInterval)); + b.pointRange && + !F && + (b.tickInterval = Math.max(b.pointRange, b.tickInterval)); + g = C(k.minTickInterval, b.isDatetimeAxis && b.closestPointRange); + !F && b.tickInterval < g && (b.tickInterval = g); + z || + q || + F || + (b.tickInterval = K( + b.tickInterval, + null, + c(b.tickInterval), + C( + k.allowDecimals, + !( + 0.5 < b.tickInterval && + 5 > b.tickInterval && + 1e3 < b.max && + 9999 > b.max + ), + ), + !!this.tickAmount, + )); + this.tickAmount || (b.tickInterval = b.unsquish()); + this.setTickPositions(); + }, + setTickPositions: function() { + var a = this.options, + b, + c = a.tickPositions; + b = this.getMinorTickInterval(); + var d = a.tickPositioner, + k = a.startOnTick, + q = a.endOnTick; + this.tickmarkOffset = + this.categories && + 'between' === a.tickmarkPlacement && + 1 === this.tickInterval + ? 0.5 + : 0; + this.minorTickInterval = + 'auto' === b && this.tickInterval ? this.tickInterval / 5 : b; + this.single = + this.min === this.max && + n(this.min) && + !this.tickAmount && + (parseInt(this.min, 10) === this.min || !1 !== a.allowDecimals); + this.tickPositions = b = c && c.slice(); + !b && + ((b = this.isDatetimeAxis + ? this.getTimeTicks( + this.normalizeTimeTickInterval(this.tickInterval, a.units), + this.min, + this.max, + a.startOfWeek, + this.ordinalPositions, + this.closestPointRange, + !0, + ) + : this.isLog + ? this.getLogTickPositions(this.tickInterval, this.min, this.max) + : this.getLinearTickPositions( + this.tickInterval, + this.min, + this.max, + )), + b.length > this.len && + ((b = [b[0], b.pop()]), b[0] === b[1] && (b.length = 1)), + (this.tickPositions = b), + d && (d = d.apply(this, [this.min, this.max]))) && + (this.tickPositions = b = d); + this.paddedTicks = b.slice(0); + this.trimTicks(b, k, q); + this.isLinked || + (this.single && + 2 > b.length && + ((this.min -= 0.5), (this.max += 0.5)), + c || d || this.adjustTickAmount()); + }, + trimTicks: function(a, b, c) { + var g = a[0], + d = a[a.length - 1], + k = this.minPointOffset || 0; + if (!this.isLinked) { + if (b && -Infinity !== g) this.min = g; + else for (; this.min - k > a[0]; ) a.shift(); + if (c) this.max = d; + else for (; this.max + k < a[a.length - 1]; ) a.pop(); + 0 === a.length && + n(g) && + !this.options.tickPositions && + a.push((d + g) / 2); + } + }, + alignToOthers: function() { + var a = {}, + b, + c = this.options; + !1 === this.chart.options.chart.alignTicks || + !1 === c.alignTicks || + this.isLog || + e(this.chart[this.coll], function(g) { + var c = g.options, + c = [g.horiz ? c.left : c.top, c.width, c.height, c.pane].join(); + g.series.length && (a[c] ? (b = !0) : (a[c] = 1)); + }); + return b; + }, + getTickAmount: function() { + var a = this.options, + b = a.tickAmount, + c = a.tickPixelInterval; + !n(a.tickInterval) && + this.len < c && + !this.isRadial && + !this.isLog && + a.startOnTick && + a.endOnTick && + (b = 2); + !b && this.alignToOthers() && (b = Math.ceil(this.len / c) + 1); + 4 > b && ((this.finalTickAmt = b), (b = 5)); + this.tickAmount = b; + }, + adjustTickAmount: function() { + var a = this.tickInterval, + b = this.tickPositions, + c = this.tickAmount, + d = this.finalTickAmt, + k = b && b.length, + q = C(this.threshold, this.softThreshold ? 0 : null); + if (this.hasData()) { + if (k < c) { + for (; b.length < c; ) + b.length % 2 || this.min === q + ? b.push(l(b[b.length - 1] + a)) + : b.unshift(l(b[0] - a)); + this.transA *= (k - 1) / (c - 1); + this.min = b[0]; + this.max = b[b.length - 1]; + } else k > c && ((this.tickInterval *= 2), this.setTickPositions()); + if (n(d)) { + for (a = c = b.length; a--; ) + ((3 === d && 1 === a % 2) || (2 >= d && 0 < a && a < c - 1)) && + b.splice(a, 1); + this.finalTickAmt = void 0; + } + } + }, + setScale: function() { + var a, b; + this.oldMin = this.min; + this.oldMax = this.max; + this.oldAxisLength = this.len; + this.setAxisSize(); + b = this.len !== this.oldAxisLength; + e(this.series, function(b) { + if (b.isDirtyData || b.isDirty || b.xAxis.isDirty) a = !0; + }); + b || + a || + this.isLinked || + this.forceRedraw || + this.userMin !== this.oldUserMin || + this.userMax !== this.oldUserMax || + this.alignToOthers() + ? (this.resetStacks && this.resetStacks(), + (this.forceRedraw = !1), + this.getSeriesExtremes(), + this.setTickInterval(), + (this.oldUserMin = this.userMin), + (this.oldUserMax = this.userMax), + this.isDirty || + (this.isDirty = + b || this.min !== this.oldMin || this.max !== this.oldMax)) + : this.cleanStacks && this.cleanStacks(); + }, + setExtremes: function(a, b, c, d, k) { + var g = this, + q = g.chart; + c = C(c, !0); + e(g.series, function(a) { + delete a.kdTree; + }); + k = h(k, { min: a, max: b }); + m(g, 'setExtremes', k, function() { + g.userMin = a; + g.userMax = b; + g.eventArgs = k; + c && q.redraw(d); + }); + }, + zoom: function(a, b) { + var g = this.dataMin, + c = this.dataMax, + d = this.options, + k = Math.min(g, C(d.min, g)), + d = Math.max(c, C(d.max, c)); + if (a !== this.min || b !== this.max) + this.allowZoomOutside || + (n(g) && (a < k && (a = k), a > d && (a = d)), + n(c) && (b < k && (b = k), b > d && (b = d))), + (this.displayBtn = void 0 !== a || void 0 !== b), + this.setExtremes(a, b, !1, void 0, { trigger: 'zoom' }); + return !0; + }, + setAxisSize: function() { + var b = this.chart, + c = this.options, + d = c.offsets || [0, 0, 0, 0], + k = this.horiz, + q = (this.width = Math.round( + a.relativeLength( + C(c.width, b.plotWidth - d[3] + d[1]), + b.plotWidth, + ), + )), + e = (this.height = Math.round( + a.relativeLength( + C(c.height, b.plotHeight - d[0] + d[2]), + b.plotHeight, + ), + )), + h = (this.top = Math.round( + a.relativeLength( + C(c.top, b.plotTop + d[0]), + b.plotHeight, + b.plotTop, + ), + )), + c = (this.left = Math.round( + a.relativeLength( + C(c.left, b.plotLeft + d[3]), + b.plotWidth, + b.plotLeft, + ), + )); + this.bottom = b.chartHeight - e - h; + this.right = b.chartWidth - q - c; + this.len = Math.max(k ? q : e, 0); + this.pos = k ? c : h; + }, + getExtremes: function() { + var a = this.isLog, + b = this.lin2log; + return { + min: a ? l(b(this.min)) : this.min, + max: a ? l(b(this.max)) : this.max, + dataMin: this.dataMin, + dataMax: this.dataMax, + userMin: this.userMin, + userMax: this.userMax, + }; + }, + getThreshold: function(a) { + var b = this.isLog, + g = this.lin2log, + c = b ? g(this.min) : this.min, + b = b ? g(this.max) : this.max; + null === a ? (a = c) : c > a ? (a = c) : b < a && (a = b); + return this.translate(a, 0, 1, 0, 1); + }, + autoLabelAlign: function(a) { + a = (C(a, 0) - 90 * this.side + 720) % 360; + return 15 < a && 165 > a + ? 'right' + : 195 < a && 345 > a + ? 'left' + : 'center'; + }, + tickSize: function(a) { + var b = this.options, + g = b[a + 'Length'], + c = C(b[a + 'Width'], 'tick' === a && this.isXAxis ? 1 : 0); + if (c && g) return 'inside' === b[a + 'Position'] && (g = -g), [g, c]; + }, + labelMetrics: function() { + var a = (this.tickPositions && this.tickPositions[0]) || 0; + return this.chart.renderer.fontMetrics( + this.options.labels.style && this.options.labels.style.fontSize, + this.ticks[a] && this.ticks[a].label, + ); + }, + unsquish: function() { + var a = this.options.labels, + b = this.horiz, + c = this.tickInterval, + d = c, + k = + this.len / (((this.categories ? 1 : 0) + this.max - this.min) / c), + q, + h = a.rotation, + m = this.labelMetrics(), + z, + A = Number.MAX_VALUE, + t, + x = function(a) { + a /= k || 1; + a = 1 < a ? Math.ceil(a) : 1; + return a * c; + }; + b + ? (t = + !a.staggerLines && + !a.step && + (n(h) + ? [h] + : k < C(a.autoRotationLimit, 80) && a.autoRotation)) && + e(t, function(a) { + var b; + if (a === h || (a && -90 <= a && 90 >= a)) + (z = x(Math.abs(m.h / Math.sin(w * a)))), + (b = z + Math.abs(a / 360)), + b < A && ((A = b), (q = a), (d = z)); + }) + : a.step || (d = x(m.h)); + this.autoRotation = t; + this.labelRotation = C(q, h); + return d; + }, + getSlotWidth: function() { + var a = this.chart, + b = this.horiz, + c = this.options.labels, + d = Math.max( + this.tickPositions.length - (this.categories ? 0 : 1), + 1, + ), + k = a.margin[3]; + return ( + (b && + 2 > (c.step || 0) && + !c.rotation && + ((this.staggerLines || 1) * this.len) / d) || + (!b && + ((c.style && parseInt(c.style.width, 10)) || + (k && k - a.spacing[3]) || + 0.33 * a.chartWidth)) + ); + }, + renderUnsquish: function() { + var a = this.chart, + b = a.renderer, + c = this.tickPositions, + d = this.ticks, + k = this.options.labels, + q = this.horiz, + h = this.getSlotWidth(), + m = Math.max(1, Math.round(h - 2 * (k.padding || 5))), + z = {}, + A = this.labelMetrics(), + t = k.style && k.style.textOverflow, + f, + F = 0, + l, + B; + I(k.rotation) || (z.rotation = k.rotation || 0); + e(c, function(a) { + (a = d[a]) && a.labelLength > F && (F = a.labelLength); + }); + this.maxLabelLength = F; + if (this.autoRotation) + F > m && F > A.h + ? (z.rotation = this.labelRotation) + : (this.labelRotation = 0); + else if (h && ((f = { width: m + 'px' }), !t)) + for (f.textOverflow = 'clip', l = c.length; !q && l--; ) + if (((B = c[l]), (m = d[B].label))) + m.styles && 'ellipsis' === m.styles.textOverflow + ? m.css({ textOverflow: 'clip' }) + : d[B].labelLength > h && m.css({ width: h + 'px' }), + m.getBBox().height > this.len / c.length - (A.h - A.f) && + (m.specCss = { textOverflow: 'ellipsis' }); + z.rotation && + ((f = { + width: + (F > 0.5 * a.chartHeight ? 0.33 * a.chartHeight : a.chartHeight) + + 'px', + }), + t || (f.textOverflow = 'ellipsis')); + if ( + (this.labelAlign = k.align || this.autoLabelAlign(this.labelRotation)) + ) + z.align = this.labelAlign; + e(c, function(a) { + var b = (a = d[a]) && a.label; + b && + (b.attr(z), + f && b.css(x(f, b.specCss)), + delete b.specCss, + (a.rotation = z.rotation)); + }); + this.tickRotCorr = b.rotCorr( + A.b, + this.labelRotation || 0, + 0 !== this.side, + ); + }, + hasData: function() { + return ( + this.hasVisibleSeries || + (n(this.min) && + n(this.max) && + this.tickPositions && + 0 < this.tickPositions.length) + ); + }, + addTitle: function(a) { + var b = this.chart.renderer, + g = this.horiz, + c = this.opposite, + d = this.options.title, + k; + this.axisTitle || + ((k = d.textAlign) || + (k = (g + ? { low: 'left', middle: 'center', high: 'right' } + : { + low: c ? 'right' : 'left', + middle: 'center', + high: c ? 'left' : 'right', + })[d.align]), + (this.axisTitle = b + .text(d.text, 0, 0, d.useHTML) + .attr({ zIndex: 7, rotation: d.rotation || 0, align: k }) + .addClass('highcharts-axis-title') + .css(d.style) + .add(this.axisGroup)), + (this.axisTitle.isNew = !0)); + d.style.width || + this.isRadial || + this.axisTitle.css({ width: this.len }); + this.axisTitle[a ? 'show' : 'hide'](!0); + }, + generateTick: function(a) { + var b = this.ticks; + b[a] ? b[a].addLabel() : (b[a] = new F(this, a)); + }, + getOffset: function() { + var a = this, + b = a.chart, + c = b.renderer, + d = a.options, + k = a.tickPositions, + q = a.ticks, + h = a.horiz, + m = a.side, + z = b.inverted && !a.isZAxis ? [1, 0, 3, 2][m] : m, + A, + x, + f = 0, + F, + l = 0, + B = d.title, + u = d.labels, + G = 0, + p = b.axisOffset, + b = b.clipOffset, + I = [-1, 1, 1, -1][m], + r = d.className, + w = a.axisParent, + K = this.tickSize('tick'); + A = a.hasData(); + a.showAxis = x = A || C(d.showEmpty, !0); + a.staggerLines = a.horiz && u.staggerLines; + a.axisGroup || + ((a.gridGroup = c + .g('grid') + .attr({ zIndex: d.gridZIndex || 1 }) + .addClass( + 'highcharts-' + this.coll.toLowerCase() + '-grid ' + (r || ''), + ) + .add(w)), + (a.axisGroup = c + .g('axis') + .attr({ zIndex: d.zIndex || 2 }) + .addClass('highcharts-' + this.coll.toLowerCase() + ' ' + (r || '')) + .add(w)), + (a.labelGroup = c + .g('axis-labels') + .attr({ zIndex: u.zIndex || 7 }) + .addClass( + 'highcharts-' + a.coll.toLowerCase() + '-labels ' + (r || ''), + ) + .add(w))); + A || a.isLinked + ? (e(k, function(b, c) { + a.generateTick(b, c); + }), + a.renderUnsquish(), + (a.reserveSpaceDefault = + 0 === m || + 2 === m || + { 1: 'left', 3: 'right' }[m] === a.labelAlign), + C( + u.reserveSpace, + 'center' === a.labelAlign ? !0 : null, + a.reserveSpaceDefault, + ) && + e(k, function(a) { + G = Math.max(q[a].getLabelSize(), G); + }), + a.staggerLines && (G *= a.staggerLines), + (a.labelOffset = G * (a.opposite ? -1 : 1))) + : t(q, function(a, b) { + a.destroy(); + delete q[b]; + }); + B && + B.text && + !1 !== B.enabled && + (a.addTitle(x), + x && + !1 !== B.reserveSpace && + ((a.titleOffset = f = a.axisTitle.getBBox()[ + h ? 'height' : 'width' + ]), + (F = B.offset), + (l = n(F) ? 0 : C(B.margin, h ? 5 : 10)))); + a.renderLine(); + a.offset = I * C(d.offset, p[m]); + a.tickRotCorr = a.tickRotCorr || { x: 0, y: 0 }; + c = 0 === m ? -a.labelMetrics().h : 2 === m ? a.tickRotCorr.y : 0; + l = Math.abs(G) + l; + G && (l = l - c + I * (h ? C(u.y, a.tickRotCorr.y + 8 * I) : u.x)); + a.axisTitleMargin = C(F, l); + p[m] = Math.max( + p[m], + a.axisTitleMargin + f + I * a.offset, + l, + A && k.length && K ? K[0] + I * a.offset : 0, + ); + d = d.offset ? 0 : 2 * Math.floor(a.axisLine.strokeWidth() / 2); + b[z] = Math.max(b[z], d); + }, + getLinePath: function(a) { + var b = this.chart, + c = this.opposite, + g = this.offset, + d = this.horiz, + k = this.left + (c ? this.width : 0) + g, + g = b.chartHeight - this.bottom - (c ? this.height : 0) + g; + c && (a *= -1); + return b.renderer.crispLine( + [ + 'M', + d ? this.left : k, + d ? g : this.top, + 'L', + d ? b.chartWidth - this.right : k, + d ? g : b.chartHeight - this.bottom, + ], + a, + ); + }, + renderLine: function() { + this.axisLine || + ((this.axisLine = this.chart.renderer + .path() + .addClass('highcharts-axis-line') + .add(this.axisGroup)), + this.axisLine.attr({ + stroke: this.options.lineColor, + 'stroke-width': this.options.lineWidth, + zIndex: 7, + })); + }, + getTitlePosition: function() { + var a = this.horiz, + b = this.left, + c = this.top, + d = this.len, + k = this.options.title, + q = a ? b : c, + e = this.opposite, + h = this.offset, + m = k.x || 0, + z = k.y || 0, + A = this.axisTitle, + t = this.chart.renderer.fontMetrics(k.style && k.style.fontSize, A), + A = Math.max(A.getBBox(null, 0).height - t.h - 1, 0), + d = { + low: q + (a ? 0 : d), + middle: q + d / 2, + high: q + (a ? d : 0), + }[k.align], + b = + (a ? c + this.height : b) + + (a ? 1 : -1) * (e ? -1 : 1) * this.axisTitleMargin + + [-A, A, t.f, -A][this.side]; + return { + x: a ? d + m : b + (e ? this.width : 0) + h + m, + y: a ? b + z - (e ? this.height : 0) + h : d + z, + }; + }, + renderMinorTick: function(a) { + var b = this.chart.hasRendered && B(this.oldMin), + c = this.minorTicks; + c[a] || (c[a] = new F(this, a, 'minor')); + b && c[a].isNew && c[a].render(null, !0); + c[a].render(null, !1, 1); + }, + renderTick: function(a, b) { + var c = this.isLinked, + g = this.ticks, + d = this.chart.hasRendered && B(this.oldMin); + if (!c || (a >= this.min && a <= this.max)) + g[a] || (g[a] = new F(this, a)), + d && g[a].isNew && g[a].render(b, !0, 0.1), + g[a].render(b); + }, + render: function() { + var b = this, + c = b.chart, + d = b.options, + k = b.isLog, + q = b.lin2log, + h = b.isLinked, + m = b.tickPositions, + z = b.axisTitle, + x = b.ticks, + f = b.minorTicks, + l = b.alternateBands, + C = d.stackLabels, + n = d.alternateGridColor, + u = b.tickmarkOffset, + G = b.axisLine, + p = b.showAxis, + I = D(c.renderer.globalAnimation), + r, + w; + b.labelEdge.length = 0; + b.overlap = !1; + e([x, f, l], function(a) { + t(a, function(a) { + a.isActive = !1; + }); + }); + if (b.hasData() || h) + b.minorTickInterval && + !b.categories && + e(b.getMinorTickPositions(), function(a) { + b.renderMinorTick(a); + }), + m.length && + (e(m, function(a, c) { + b.renderTick(a, c); + }), + u && + (0 === b.min || b.single) && + (x[-1] || (x[-1] = new F(b, -1, null, !0)), x[-1].render(-1))), + n && + e(m, function(d, g) { + w = void 0 !== m[g + 1] ? m[g + 1] + u : b.max - u; + 0 === g % 2 && + d < b.max && + w <= b.max + (c.polar ? -u : u) && + (l[d] || (l[d] = new a.PlotLineOrBand(b)), + (r = d + u), + (l[d].options = { + from: k ? q(r) : r, + to: k ? q(w) : w, + color: n, + }), + l[d].render(), + (l[d].isActive = !0)); + }), + b._addedPlotLB || + (e((d.plotLines || []).concat(d.plotBands || []), function(a) { + b.addPlotBandOrLine(a); + }), + (b._addedPlotLB = !0)); + e([x, f, l], function(a) { + var b, + d = [], + g = I.duration; + t(a, function(a, b) { + a.isActive || (a.render(b, !1, 0), (a.isActive = !1), d.push(b)); + }); + A( + function() { + for (b = d.length; b--; ) + a[d[b]] && + !a[d[b]].isActive && + (a[d[b]].destroy(), delete a[d[b]]); + }, + a !== l && c.hasRendered && g ? g : 0, + ); + }); + G && + (G[G.isPlaced ? 'animate' : 'attr']({ + d: this.getLinePath(G.strokeWidth()), + }), + (G.isPlaced = !0), + G[p ? 'show' : 'hide'](!0)); + z && + p && + ((d = b.getTitlePosition()), + B(d.y) + ? (z[z.isNew ? 'attr' : 'animate'](d), (z.isNew = !1)) + : (z.attr('y', -9999), (z.isNew = !0))); + C && C.enabled && b.renderStackTotals(); + b.isDirty = !1; + }, + redraw: function() { + this.visible && + (this.render(), + e(this.plotLinesAndBands, function(a) { + a.render(); + })); + e(this.series, function(a) { + a.isDirty = !0; + }); + }, + keepProps: 'extKey hcEvents names series userMax userMin'.split(' '), + destroy: function(a) { + var b = this, + c = b.stacks, + d = b.plotLinesAndBands, + g; + a || N(b); + t(c, function(a, b) { + u(a); + c[b] = null; + }); + e([b.ticks, b.minorTicks, b.alternateBands], function(a) { + u(a); + }); + if (d) for (a = d.length; a--; ) d[a].destroy(); + e( + 'stackTotalGroup axisLine axisTitle axisGroup gridGroup labelGroup cross'.split( + ' ', + ), + function(a) { + b[a] && (b[a] = b[a].destroy()); + }, + ); + for (g in b.plotLinesAndBandsGroups) + b.plotLinesAndBandsGroups[g] = b.plotLinesAndBandsGroups[g].destroy(); + t(b, function(a, c) { + -1 === k(c, b.keepProps) && delete b[c]; + }); + }, + drawCrosshair: function(a, b) { + var c, + d = this.crosshair, + g = C(d.snap, !0), + k, + q = this.cross; + a || (a = this.cross && this.cross.e); + this.crosshair && !1 !== (n(b) || !g) + ? (g + ? n(b) && (k = this.isXAxis ? b.plotX : this.len - b.plotY) + : (k = + a && + (this.horiz + ? a.chartX - this.pos + : this.len - a.chartY + this.pos)), + n(k) && + (c = + this.getPlotLinePath( + b && (this.isXAxis ? b.x : C(b.stackY, b.y)), + null, + null, + null, + k, + ) || null), + n(c) + ? ((b = this.categories && !this.isRadial), + q || + ((this.cross = q = this.chart.renderer + .path() + .addClass( + 'highcharts-crosshair highcharts-crosshair-' + + (b ? 'category ' : 'thin ') + + d.className, + ) + .attr({ zIndex: C(d.zIndex, 2) }) + .add()), + q + .attr({ + stroke: + d.color || + (b + ? f('#ccd6eb') + .setOpacity(0.25) + .get() + : '#cccccc'), + 'stroke-width': C(d.width, 1), + }) + .css({ 'pointer-events': 'none' }), + d.dashStyle && q.attr({ dashstyle: d.dashStyle })), + q.show().attr({ d: c }), + b && !d.width && q.attr({ 'stroke-width': this.transA }), + (this.cross.e = a)) + : this.hideCrosshair()) + : this.hideCrosshair(); + }, + hideCrosshair: function() { + this.cross && this.cross.hide(); + }, + }); + return (a.Axis = G); + })(M); + (function(a) { + var E = a.Axis, + D = a.Date, + H = a.dateFormat, + p = a.defaultOptions, + f = a.defined, + l = a.each, + r = a.extend, + n = a.getMagnitude, + w = a.getTZOffset, + u = a.normalizeTickInterval, + e = a.pick, + h = a.timeUnits; + E.prototype.getTimeTicks = function(a, d, c, b) { + var k = [], + m = {}, + B = p.global.useUTC, + n, + x = new D(d - Math.max(w(d), w(c))), + u = D.hcMakeTime, + t = a.unitRange, + C = a.count, + N, + q; + if (f(d)) { + x[D.hcSetMilliseconds]( + t >= h.second ? 0 : C * Math.floor(x.getMilliseconds() / C), + ); + if (t >= h.second) + x[D.hcSetSeconds]( + t >= h.minute ? 0 : C * Math.floor(x.getSeconds() / C), + ); + if (t >= h.minute) + x[D.hcSetMinutes]( + t >= h.hour ? 0 : C * Math.floor(x[D.hcGetMinutes]() / C), + ); + if (t >= h.hour) + x[D.hcSetHours]( + t >= h.day ? 0 : C * Math.floor(x[D.hcGetHours]() / C), + ); + if (t >= h.day) + x[D.hcSetDate]( + t >= h.month ? 1 : C * Math.floor(x[D.hcGetDate]() / C), + ); + t >= h.month && + (x[D.hcSetMonth]( + t >= h.year ? 0 : C * Math.floor(x[D.hcGetMonth]() / C), + ), + (n = x[D.hcGetFullYear]())); + if (t >= h.year) x[D.hcSetFullYear](n - (n % C)); + if (t === h.week) + x[D.hcSetDate](x[D.hcGetDate]() - x[D.hcGetDay]() + e(b, 1)); + n = x[D.hcGetFullYear](); + b = x[D.hcGetMonth](); + var A = x[D.hcGetDate](), + F = x[D.hcGetHours](); + d = x.getTime(); + D.hcHasTimeZone && + ((q = + (!B || !!D.hcGetTimezoneOffset) && + (c - d > 4 * h.month || w(d) !== w(c))), + (N = w(x)), + (x = new D(d + N))); + B = x.getTime(); + for (d = 1; B < c; ) + k.push(B), + (B = + t === h.year + ? u(n + d * C, 0) + : t === h.month + ? u(n, b + d * C) + : !q || (t !== h.day && t !== h.week) + ? q && t === h.hour + ? u(n, b, A, F + d * C, 0, 0, N) - N + : B + t * C + : u(n, b, A + d * C * (t === h.day ? 1 : 7))), + d++; + k.push(B); + t <= h.hour && + 1e4 > k.length && + l(k, function(a) { + 0 === a % 18e5 && + '000000000' === H('%H%M%S%L', a) && + (m[a] = 'day'); + }); + } + k.info = r(a, { higherRanks: m, totalRange: t * C }); + return k; + }; + E.prototype.normalizeTimeTickInterval = function(a, d) { + var c = d || [ + ['millisecond', [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]], + ['second', [1, 2, 5, 10, 15, 30]], + ['minute', [1, 2, 5, 10, 15, 30]], + ['hour', [1, 2, 3, 4, 6, 8, 12]], + ['day', [1, 2]], + ['week', [1, 2]], + ['month', [1, 2, 3, 4, 6]], + ['year', null], + ]; + d = c[c.length - 1]; + var b = h[d[0]], + k = d[1], + e; + for ( + e = 0; + e < c.length && + !((d = c[e]), + (b = h[d[0]]), + (k = d[1]), + c[e + 1] && a <= (b * k[k.length - 1] + h[c[e + 1][0]]) / 2); + e++ + ); + b === h.year && a < 5 * b && (k = [1, 2, 5]); + a = u(a / b, k, 'year' === d[0] ? Math.max(n(a / b), 1) : 1); + return { unitRange: b, count: a, unitName: d[0] }; + }; + })(M); + (function(a) { + var E = a.Axis, + D = a.getMagnitude, + H = a.map, + p = a.normalizeTickInterval, + f = a.pick; + E.prototype.getLogTickPositions = function(a, r, n, w) { + var l = this.options, + e = this.len, + h = this.lin2log, + m = this.log2lin, + d = []; + w || (this._minorAutoInterval = null); + if (0.5 <= a) + (a = Math.round(a)), (d = this.getLinearTickPositions(a, r, n)); + else if (0.08 <= a) + for ( + var e = Math.floor(r), + c, + b, + k, + z, + B, + l = + 0.3 < a + ? [1, 2, 4] + : 0.15 < a + ? [1, 2, 4, 6, 8] + : [1, 2, 3, 4, 5, 6, 7, 8, 9]; + e < n + 1 && !B; + e++ + ) + for (b = l.length, c = 0; c < b && !B; c++) + (k = m(h(e) * l[c])), + k > r && (!w || z <= n) && void 0 !== z && d.push(z), + z > n && (B = !0), + (z = k); + else + (r = h(r)), + (n = h(n)), + (a = w ? this.getMinorTickInterval() : l.tickInterval), + (a = f( + 'auto' === a ? null : a, + this._minorAutoInterval, + ((l.tickPixelInterval / (w ? 5 : 1)) * (n - r)) / + ((w ? e / this.tickPositions.length : e) || 1), + )), + (a = p(a, null, D(a))), + (d = H(this.getLinearTickPositions(a, r, n), m)), + w || (this._minorAutoInterval = a / 5); + w || (this.tickInterval = a); + return d; + }; + E.prototype.log2lin = function(a) { + return Math.log(a) / Math.LN10; + }; + E.prototype.lin2log = function(a) { + return Math.pow(10, a); + }; + })(M); + (function(a, E) { + var D = a.arrayMax, + H = a.arrayMin, + p = a.defined, + f = a.destroyObjectProperties, + l = a.each, + r = a.erase, + n = a.merge, + w = a.pick; + a.PlotLineOrBand = function(a, e) { + this.axis = a; + e && ((this.options = e), (this.id = e.id)); + }; + a.PlotLineOrBand.prototype = { + render: function() { + var f = this, + e = f.axis, + h = e.horiz, + m = f.options, + d = m.label, + c = f.label, + b = m.to, + k = m.from, + z = m.value, + l = p(k) && p(b), + r = p(z), + x = f.svgElem, + K = !x, + t = [], + C = m.color, + N = w(m.zIndex, 0), + q = m.events, + t = { + class: + 'highcharts-plot-' + + (l ? 'band ' : 'line ') + + (m.className || ''), + }, + A = {}, + F = e.chart.renderer, + G = l ? 'bands' : 'lines', + g = e.log2lin; + e.isLog && ((k = g(k)), (b = g(b)), (z = g(z))); + r + ? ((t = { stroke: C, 'stroke-width': m.width }), + m.dashStyle && (t.dashstyle = m.dashStyle)) + : l && + (C && (t.fill = C), + m.borderWidth && + ((t.stroke = m.borderColor), + (t['stroke-width'] = m.borderWidth))); + A.zIndex = N; + G += '-' + N; + (C = e.plotLinesAndBandsGroups[G]) || + (e.plotLinesAndBandsGroups[G] = C = F.g('plot-' + G) + .attr(A) + .add()); + K && + (f.svgElem = x = F.path() + .attr(t) + .add(C)); + if (r) t = e.getPlotLinePath(z, x.strokeWidth()); + else if (l) t = e.getPlotBandPath(k, b, m); + else return; + K && t && t.length + ? (x.attr({ d: t }), + q && + a.objectEach(q, function(a, b) { + x.on(b, function(a) { + q[b].apply(f, [a]); + }); + })) + : x && + (t + ? (x.show(), x.animate({ d: t })) + : (x.hide(), c && (f.label = c = c.destroy()))); + d && + p(d.text) && + t && + t.length && + 0 < e.width && + 0 < e.height && + !t.flat + ? ((d = n( + { + align: h && l && 'center', + x: h ? !l && 4 : 10, + verticalAlign: !h && l && 'middle', + y: h ? (l ? 16 : 10) : l ? 6 : -4, + rotation: h && !l && 90, + }, + d, + )), + this.renderLabel(d, t, l, N)) + : c && c.hide(); + return f; + }, + renderLabel: function(a, e, h, m) { + var d = this.label, + c = this.axis.chart.renderer; + d || + ((d = { + align: a.textAlign || a.align, + rotation: a.rotation, + class: + 'highcharts-plot-' + + (h ? 'band' : 'line') + + '-label ' + + (a.className || ''), + }), + (d.zIndex = m), + (this.label = d = c + .text(a.text, 0, 0, a.useHTML) + .attr(d) + .add()), + d.css(a.style)); + m = e.xBounds || [e[1], e[4], h ? e[6] : e[1]]; + e = e.yBounds || [e[2], e[5], h ? e[7] : e[2]]; + h = H(m); + c = H(e); + d.align(a, !1, { x: h, y: c, width: D(m) - h, height: D(e) - c }); + d.show(); + }, + destroy: function() { + r(this.axis.plotLinesAndBands, this); + delete this.axis; + f(this); + }, + }; + a.extend(E.prototype, { + getPlotBandPath: function(a, e) { + var h = this.getPlotLinePath(e, null, null, !0), + m = this.getPlotLinePath(a, null, null, !0), + d = [], + c = this.horiz, + b = 1, + k; + a = (a < this.min && e < this.min) || (a > this.max && e > this.max); + if (m && h) + for ( + a && ((k = m.toString() === h.toString()), (b = 0)), a = 0; + a < m.length; + a += 6 + ) + c && h[a + 1] === m[a + 1] + ? ((h[a + 1] += b), (h[a + 4] += b)) + : c || + h[a + 2] !== m[a + 2] || + ((h[a + 2] += b), (h[a + 5] += b)), + d.push( + 'M', + m[a + 1], + m[a + 2], + 'L', + m[a + 4], + m[a + 5], + h[a + 4], + h[a + 5], + h[a + 1], + h[a + 2], + 'z', + ), + (d.flat = k); + return d; + }, + addPlotBand: function(a) { + return this.addPlotBandOrLine(a, 'plotBands'); + }, + addPlotLine: function(a) { + return this.addPlotBandOrLine(a, 'plotLines'); + }, + addPlotBandOrLine: function(f, e) { + var h = new a.PlotLineOrBand(this, f).render(), + m = this.userOptions; + h && + (e && ((m[e] = m[e] || []), m[e].push(f)), + this.plotLinesAndBands.push(h)); + return h; + }, + removePlotBandOrLine: function(a) { + for ( + var e = this.plotLinesAndBands, + h = this.options, + m = this.userOptions, + d = e.length; + d--; + + ) + e[d].id === a && e[d].destroy(); + l( + [ + h.plotLines || [], + m.plotLines || [], + h.plotBands || [], + m.plotBands || [], + ], + function(c) { + for (d = c.length; d--; ) c[d].id === a && r(c, c[d]); + }, + ); + }, + removePlotBand: function(a) { + this.removePlotBandOrLine(a); + }, + removePlotLine: function(a) { + this.removePlotBandOrLine(a); + }, + }); + })(M, V); + (function(a) { + var E = a.dateFormat, + D = a.each, + H = a.extend, + p = a.format, + f = a.isNumber, + l = a.map, + r = a.merge, + n = a.pick, + w = a.splat, + u = a.syncTimeout, + e = a.timeUnits; + a.Tooltip = function() { + this.init.apply(this, arguments); + }; + a.Tooltip.prototype = { + init: function(a, e) { + this.chart = a; + this.options = e; + this.crosshairs = []; + this.now = { x: 0, y: 0 }; + this.isHidden = !0; + this.split = e.split && !a.inverted; + this.shared = e.shared || this.split; + }, + cleanSplit: function(a) { + D(this.chart.series, function(e) { + var d = e && e.tt; + d && (!d.isActive || a ? (e.tt = d.destroy()) : (d.isActive = !1)); + }); + }, + getLabel: function() { + var a = this.chart.renderer, + e = this.options; + this.label || + (this.split + ? (this.label = a.g('tooltip')) + : ((this.label = a + .label( + '', + 0, + 0, + e.shape || 'callout', + null, + null, + e.useHTML, + null, + 'tooltip', + ) + .attr({ padding: e.padding, r: e.borderRadius })), + this.label + .attr({ + fill: e.backgroundColor, + 'stroke-width': e.borderWidth, + }) + .css(e.style) + .shadow(e.shadow)), + this.label.attr({ zIndex: 8 }).add()); + return this.label; + }, + update: function(a) { + this.destroy(); + r(!0, this.chart.options.tooltip.userOptions, a); + this.init(this.chart, r(!0, this.options, a)); + }, + destroy: function() { + this.label && (this.label = this.label.destroy()); + this.split && + this.tt && + (this.cleanSplit(this.chart, !0), (this.tt = this.tt.destroy())); + clearTimeout(this.hideTimer); + clearTimeout(this.tooltipTimeout); + }, + move: function(a, e, d, c) { + var b = this, + k = b.now, + h = + !1 !== b.options.animation && + !b.isHidden && + (1 < Math.abs(a - k.x) || 1 < Math.abs(e - k.y)), + m = b.followPointer || 1 < b.len; + H(k, { + x: h ? (2 * k.x + a) / 3 : a, + y: h ? (k.y + e) / 2 : e, + anchorX: m ? void 0 : h ? (2 * k.anchorX + d) / 3 : d, + anchorY: m ? void 0 : h ? (k.anchorY + c) / 2 : c, + }); + b.getLabel().attr(k); + h && + (clearTimeout(this.tooltipTimeout), + (this.tooltipTimeout = setTimeout(function() { + b && b.move(a, e, d, c); + }, 32))); + }, + hide: function(a) { + var e = this; + clearTimeout(this.hideTimer); + a = n(a, this.options.hideDelay, 500); + this.isHidden || + (this.hideTimer = u(function() { + e.getLabel()[a ? 'fadeOut' : 'hide'](); + e.isHidden = !0; + }, a)); + }, + getAnchor: function(a, e) { + var d, + c = this.chart, + b = c.inverted, + k = c.plotTop, + h = c.plotLeft, + m = 0, + f = 0, + x, + n; + a = w(a); + d = a[0].tooltipPos; + this.followPointer && + e && + (void 0 === e.chartX && (e = c.pointer.normalize(e)), + (d = [e.chartX - c.plotLeft, e.chartY - k])); + d || + (D(a, function(a) { + x = a.series.yAxis; + n = a.series.xAxis; + m += a.plotX + (!b && n ? n.left - h : 0); + f += + (a.plotLow ? (a.plotLow + a.plotHigh) / 2 : a.plotY) + + (!b && x ? x.top - k : 0); + }), + (m /= a.length), + (f /= a.length), + (d = [ + b ? c.plotWidth - f : m, + this.shared && !b && 1 < a.length && e + ? e.chartY - k + : b + ? c.plotHeight - m + : f, + ])); + return l(d, Math.round); + }, + getPosition: function(a, e, d) { + var c = this.chart, + b = this.distance, + k = {}, + h = (c.inverted && d.h) || 0, + m, + f = [ + 'y', + c.chartHeight, + e, + d.plotY + c.plotTop, + c.plotTop, + c.plotTop + c.plotHeight, + ], + x = [ + 'x', + c.chartWidth, + a, + d.plotX + c.plotLeft, + c.plotLeft, + c.plotLeft + c.plotWidth, + ], + l = !this.followPointer && n(d.ttBelow, !c.inverted === !!d.negative), + t = function(a, c, d, g, e, q) { + var m = d < g - b, + z = g + b + d < c, + A = g - b - d; + g += b; + if (l && z) k[a] = g; + else if (!l && m) k[a] = A; + else if (m) k[a] = Math.min(q - d, 0 > A - h ? A : A - h); + else if (z) k[a] = Math.max(e, g + h + d > c ? g : g + h); + else return !1; + }, + C = function(a, c, d, g) { + var e; + g < b || g > c - b + ? (e = !1) + : (k[a] = g < d / 2 ? 1 : g > c - d / 2 ? c - d - 2 : g - d / 2); + return e; + }, + p = function(a) { + var b = f; + f = x; + x = b; + m = a; + }, + q = function() { + !1 !== t.apply(0, f) + ? !1 !== C.apply(0, x) || m || (p(!0), q()) + : m + ? (k.x = k.y = 0) + : (p(!0), q()); + }; + (c.inverted || 1 < this.len) && p(); + q(); + return k; + }, + defaultFormatter: function(a) { + var e = this.points || w(this), + d; + d = [a.tooltipFooterHeaderFormatter(e[0])]; + d = d.concat(a.bodyFormatter(e)); + d.push(a.tooltipFooterHeaderFormatter(e[0], !0)); + return d; + }, + refresh: function(a, e) { + var d, + c = this.options, + b, + k = a, + h, + m = {}, + f = []; + d = c.formatter || this.defaultFormatter; + var m = this.shared, + x; + c.enabled && + (clearTimeout(this.hideTimer), + (this.followPointer = w(k)[0].series.tooltipOptions.followPointer), + (h = this.getAnchor(k, e)), + (e = h[0]), + (b = h[1]), + !m || (k.series && k.series.noSharedTooltip) + ? (m = k.getLabelConfig()) + : (D(k, function(a) { + a.setState('hover'); + f.push(a.getLabelConfig()); + }), + (m = { x: k[0].category, y: k[0].y }), + (m.points = f), + (k = k[0])), + (this.len = f.length), + (m = d.call(m, this)), + (x = k.series), + (this.distance = n(x.tooltipOptions.distance, 16)), + !1 === m + ? this.hide() + : ((d = this.getLabel()), + this.isHidden && d.attr({ opacity: 1 }).show(), + this.split + ? this.renderSplit(m, w(a)) + : (c.style.width || + d.css({ width: this.chart.spacingBox.width }), + d.attr({ text: m && m.join ? m.join('') : m }), + d + .removeClass(/highcharts-color-[\d]+/g) + .addClass( + 'highcharts-color-' + n(k.colorIndex, x.colorIndex), + ), + d.attr({ + stroke: c.borderColor || k.color || x.color || '#666666', + }), + this.updatePosition({ + plotX: e, + plotY: b, + negative: k.negative, + ttBelow: k.ttBelow, + h: h[2] || 0, + })), + (this.isHidden = !1))); + }, + renderSplit: function(e, m) { + var d = this, + c = [], + b = this.chart, + k = b.renderer, + h = !0, + f = this.options, + l = 0, + x = this.getLabel(); + a.isString(e) && (e = [!1, e]); + D(e.slice(0, m.length + 1), function(a, e) { + if (!1 !== a) { + e = m[e - 1] || { isHeader: !0, plotX: m[0].plotX }; + var z = e.series || d, + t = z.tt, + q = e.series || {}, + A = 'highcharts-color-' + n(e.colorIndex, q.colorIndex, 'none'); + t || + (z.tt = t = k + .label(null, null, null, 'callout', null, null, f.useHTML) + .addClass('highcharts-tooltip-box ' + A) + .attr({ + padding: f.padding, + r: f.borderRadius, + fill: f.backgroundColor, + stroke: f.borderColor || e.color || q.color || '#333333', + 'stroke-width': f.borderWidth, + }) + .add(x)); + t.isActive = !0; + t.attr({ text: a }); + t.css(f.style).shadow(f.shadow); + a = t.getBBox(); + q = a.width + t.strokeWidth(); + e.isHeader + ? ((l = a.height), + (q = Math.max( + 0, + Math.min(e.plotX + b.plotLeft - q / 2, b.chartWidth - q), + ))) + : (q = e.plotX + b.plotLeft - n(f.distance, 16) - q); + 0 > q && (h = !1); + a = + (e.series && e.series.yAxis && e.series.yAxis.pos) + + (e.plotY || 0); + a -= b.plotTop; + c.push({ + target: e.isHeader ? b.plotHeight + l : a, + rank: e.isHeader ? 1 : 0, + size: z.tt.getBBox().height + 1, + point: e, + x: q, + tt: t, + }); + } + }); + this.cleanSplit(); + a.distribute(c, b.plotHeight + l); + D(c, function(a) { + var c = a.point, + d = c.series; + a.tt.attr({ + visibility: void 0 === a.pos ? 'hidden' : 'inherit', + x: h || c.isHeader ? a.x : c.plotX + b.plotLeft + n(f.distance, 16), + y: a.pos + b.plotTop, + anchorX: c.isHeader ? c.plotX + b.plotLeft : c.plotX + d.xAxis.pos, + anchorY: c.isHeader + ? a.pos + b.plotTop - 15 + : c.plotY + d.yAxis.pos, + }); + }); + }, + updatePosition: function(a) { + var e = this.chart, + d = this.getLabel(), + d = (this.options.positioner || this.getPosition).call( + this, + d.width, + d.height, + a, + ); + this.move( + Math.round(d.x), + Math.round(d.y || 0), + a.plotX + e.plotLeft, + a.plotY + e.plotTop, + ); + }, + getDateFormat: function(a, m, d, c) { + var b = E('%m-%d %H:%M:%S.%L', m), + k, + h, + f = { millisecond: 15, second: 12, minute: 9, hour: 6, day: 3 }, + l = 'millisecond'; + for (h in e) { + if ( + a === e.week && + +E('%w', m) === d && + '00:00:00.000' === b.substr(6) + ) { + h = 'week'; + break; + } + if (e[h] > a) { + h = l; + break; + } + if (f[h] && b.substr(f[h]) !== '01-01 00:00:00.000'.substr(f[h])) + break; + 'week' !== h && (l = h); + } + h && (k = c[h]); + return k; + }, + getXDateFormat: function(a, e, d) { + e = e.dateTimeLabelFormats; + var c = d && d.closestPointRange; + return ( + (c ? this.getDateFormat(c, a.x, d.options.startOfWeek, e) : e.day) || + e.year + ); + }, + tooltipFooterHeaderFormatter: function(a, e) { + e = e ? 'footer' : 'header'; + var d = a.series, + c = d.tooltipOptions, + b = c.xDateFormat, + k = d.xAxis, + h = k && 'datetime' === k.options.type && f(a.key), + m = c[e + 'Format']; + h && !b && (b = this.getXDateFormat(a, c, k)); + h && + b && + D((a.point && a.point.tooltipDateKeys) || ['key'], function(a) { + m = m.replace('{point.' + a + '}', '{point.' + a + ':' + b + '}'); + }); + return p(m, { point: a, series: d }); + }, + bodyFormatter: function(a) { + return l(a, function(a) { + var d = a.series.tooltipOptions; + return ( + d[(a.point.formatPrefix || 'point') + 'Formatter'] || + a.point.tooltipFormatter + ).call(a.point, d[(a.point.formatPrefix || 'point') + 'Format']); + }); + }, + }; + })(M); + (function(a) { + var E = a.addEvent, + D = a.attr, + H = a.charts, + p = a.color, + f = a.css, + l = a.defined, + r = a.each, + n = a.extend, + w = a.find, + u = a.fireEvent, + e = a.isObject, + h = a.offset, + m = a.pick, + d = a.splat, + c = a.Tooltip; + a.Pointer = function(a, c) { + this.init(a, c); + }; + a.Pointer.prototype = { + init: function(a, d) { + this.options = d; + this.chart = a; + this.runChartClick = d.chart.events && !!d.chart.events.click; + this.pinchDown = []; + this.lastValidTouch = {}; + c && + ((a.tooltip = new c(a, d.tooltip)), + (this.followTouchMove = m(d.tooltip.followTouchMove, !0))); + this.setDOMEvents(); + }, + zoomOption: function(a) { + var b = this.chart, + c = b.options.chart, + d = c.zoomType || '', + b = b.inverted; + /touch/.test(a.type) && (d = m(c.pinchType, d)); + this.zoomX = a = /x/.test(d); + this.zoomY = d = /y/.test(d); + this.zoomHor = (a && !b) || (d && b); + this.zoomVert = (d && !b) || (a && b); + this.hasZoom = a || d; + }, + normalize: function(a, c) { + var b; + b = a.touches + ? a.touches.length + ? a.touches.item(0) + : a.changedTouches[0] + : a; + c || (this.chartPosition = c = h(this.chart.container)); + return n(a, { + chartX: Math.round(b.pageX - c.left), + chartY: Math.round(b.pageY - c.top), + }); + }, + getCoordinates: function(a) { + var b = { xAxis: [], yAxis: [] }; + r(this.chart.axes, function(c) { + b[c.isXAxis ? 'xAxis' : 'yAxis'].push({ + axis: c, + value: c.toValue(a[c.horiz ? 'chartX' : 'chartY']), + }); + }); + return b; + }, + findNearestKDPoint: function(a, c, d) { + var b; + r(a, function(a) { + var k = + !(a.noSharedTooltip && c) && + 0 > a.options.findNearestPointBy.indexOf('y'); + a = a.searchPoint(d, k); + if ((k = e(a, !0)) && !(k = !e(b, !0))) + var k = b.distX - a.distX, + h = b.dist - a.dist, + m = + (a.series.group && a.series.group.zIndex) - + (b.series.group && b.series.group.zIndex), + k = + 0 < + (0 !== k && c + ? k + : 0 !== h + ? h + : 0 !== m + ? m + : b.series.index > a.series.index + ? -1 + : 1); + k && (b = a); + }); + return b; + }, + getPointFromEvent: function(a) { + a = a.target; + for (var b; a && !b; ) (b = a.point), (a = a.parentNode); + return b; + }, + getChartCoordinatesFromPoint: function(a, c) { + var b = a.series, + d = b.xAxis, + b = b.yAxis, + k = m(a.clientX, a.plotX); + if (d && b) + return c + ? { chartX: d.len + d.pos - k, chartY: b.len + b.pos - a.plotY } + : { chartX: k + d.pos, chartY: a.plotY + b.pos }; + }, + getHoverData: function(b, c, d, h, f, l, n) { + var k, + z = [], + x = n && n.isBoosting; + h = !(!h || !b); + n = + c && !c.stickyTracking + ? [c] + : a.grep(d, function(a) { + return ( + a.visible && + !(!f && a.directTouch) && + m(a.options.enableMouseTracking, !0) && + a.stickyTracking + ); + }); + c = (k = h ? b : this.findNearestKDPoint(n, f, l)) && k.series; + k && + (f && !c.noSharedTooltip + ? ((n = a.grep(d, function(a) { + return ( + a.visible && + !(!f && a.directTouch) && + m(a.options.enableMouseTracking, !0) && + !a.noSharedTooltip + ); + })), + r(n, function(a) { + var b = w(a.points, function(a) { + return a.x === k.x && !a.isNull; + }); + e(b) && (x && (b = a.getPoint(b)), z.push(b)); + })) + : z.push(k)); + return { hoverPoint: k, hoverSeries: c, hoverPoints: z }; + }, + runPointActions: function(b, c) { + var d = this.chart, + k = d.tooltip && d.tooltip.options.enabled ? d.tooltip : void 0, + e = k ? k.shared : !1, + h = c || d.hoverPoint, + f = (h && h.series) || d.hoverSeries, + f = this.getHoverData( + h, + f, + d.series, + !!c || (f && f.directTouch && this.isDirectTouch), + e, + b, + { isBoosting: d.isBoosting }, + ), + l, + h = f.hoverPoint; + l = f.hoverPoints; + c = (f = f.hoverSeries) && f.tooltipOptions.followPointer; + e = e && f && !f.noSharedTooltip; + if (h && (h !== d.hoverPoint || (k && k.isHidden))) { + r(d.hoverPoints || [], function(b) { + -1 === a.inArray(b, l) && b.setState(); + }); + r(l || [], function(a) { + a.setState('hover'); + }); + if (d.hoverSeries !== f) f.onMouseOver(); + d.hoverPoint && d.hoverPoint.firePointEvent('mouseOut'); + if (!h.series) return; + h.firePointEvent('mouseOver'); + d.hoverPoints = l; + d.hoverPoint = h; + k && k.refresh(e ? l : h, b); + } else + c && + k && + !k.isHidden && + ((h = k.getAnchor([{}], b)), + k.updatePosition({ plotX: h[0], plotY: h[1] })); + this.unDocMouseMove || + (this.unDocMouseMove = E( + d.container.ownerDocument, + 'mousemove', + function(b) { + var c = H[a.hoverChartIndex]; + if (c) c.pointer.onDocumentMouseMove(b); + }, + )); + r(d.axes, function(c) { + var d = m(c.crosshair.snap, !0), + k = d + ? a.find(l, function(a) { + return a.series[c.coll] === c; + }) + : void 0; + k || !d ? c.drawCrosshair(b, k) : c.hideCrosshair(); + }); + }, + reset: function(a, c) { + var b = this.chart, + k = b.hoverSeries, + e = b.hoverPoint, + h = b.hoverPoints, + m = b.tooltip, + f = m && m.shared ? h : e; + a && + f && + r(d(f), function(b) { + b.series.isCartesian && void 0 === b.plotX && (a = !1); + }); + if (a) + m && + f && + (m.refresh(f), + e && + (e.setState(e.state, !0), + r(b.axes, function(a) { + a.crosshair && a.drawCrosshair(null, e); + }))); + else { + if (e) e.onMouseOut(); + h && + r(h, function(a) { + a.setState(); + }); + if (k) k.onMouseOut(); + m && m.hide(c); + this.unDocMouseMove && (this.unDocMouseMove = this.unDocMouseMove()); + r(b.axes, function(a) { + a.hideCrosshair(); + }); + this.hoverX = b.hoverPoints = b.hoverPoint = null; + } + }, + scaleGroups: function(a, c) { + var b = this.chart, + d; + r(b.series, function(k) { + d = a || k.getPlotBox(); + k.xAxis && + k.xAxis.zoomEnabled && + k.group && + (k.group.attr(d), + k.markerGroup && + (k.markerGroup.attr(d), + k.markerGroup.clip(c ? b.clipRect : null)), + k.dataLabelsGroup && k.dataLabelsGroup.attr(d)); + }); + b.clipRect.attr(c || b.clipBox); + }, + dragStart: function(a) { + var b = this.chart; + b.mouseIsDown = a.type; + b.cancelClick = !1; + b.mouseDownX = this.mouseDownX = a.chartX; + b.mouseDownY = this.mouseDownY = a.chartY; + }, + drag: function(a) { + var b = this.chart, + c = b.options.chart, + d = a.chartX, + e = a.chartY, + h = this.zoomHor, + m = this.zoomVert, + f = b.plotLeft, + l = b.plotTop, + n = b.plotWidth, + q = b.plotHeight, + A, + F = this.selectionMarker, + G = this.mouseDownX, + g = this.mouseDownY, + v = c.panKey && a[c.panKey + 'Key']; + (F && F.touch) || + (d < f ? (d = f) : d > f + n && (d = f + n), + e < l ? (e = l) : e > l + q && (e = l + q), + (this.hasDragged = Math.sqrt( + Math.pow(G - d, 2) + Math.pow(g - e, 2), + )), + 10 < this.hasDragged && + ((A = b.isInsidePlot(G - f, g - l)), + b.hasCartesianSeries && + (this.zoomX || this.zoomY) && + A && + !v && + !F && + (this.selectionMarker = F = b.renderer + .rect(f, l, h ? 1 : n, m ? 1 : q, 0) + .attr({ + fill: + c.selectionMarkerFill || + p('#335cad') + .setOpacity(0.25) + .get(), + class: 'highcharts-selection-marker', + zIndex: 7, + }) + .add()), + F && + h && + ((d -= G), + F.attr({ width: Math.abs(d), x: (0 < d ? 0 : d) + G })), + F && + m && + ((d = e - g), + F.attr({ height: Math.abs(d), y: (0 < d ? 0 : d) + g })), + A && !F && c.panning && b.pan(a, c.panning))); + }, + drop: function(a) { + var b = this, + c = this.chart, + d = this.hasPinched; + if (this.selectionMarker) { + var e = { originalEvent: a, xAxis: [], yAxis: [] }, + h = this.selectionMarker, + m = h.attr ? h.attr('x') : h.x, + t = h.attr ? h.attr('y') : h.y, + p = h.attr ? h.attr('width') : h.width, + w = h.attr ? h.attr('height') : h.height, + q; + if (this.hasDragged || d) + r(c.axes, function(c) { + if ( + c.zoomEnabled && + l(c.min) && + (d || b[{ xAxis: 'zoomX', yAxis: 'zoomY' }[c.coll]]) + ) { + var k = c.horiz, + h = 'touchend' === a.type ? c.minPixelPadding : 0, + g = c.toValue((k ? m : t) + h), + k = c.toValue((k ? m + p : t + w) - h); + e[c.coll].push({ + axis: c, + min: Math.min(g, k), + max: Math.max(g, k), + }); + q = !0; + } + }), + q && + u(c, 'selection', e, function(a) { + c.zoom(n(a, d ? { animation: !1 } : null)); + }); + this.selectionMarker = this.selectionMarker.destroy(); + d && this.scaleGroups(); + } + c && + (f(c.container, { cursor: c._cursor }), + (c.cancelClick = 10 < this.hasDragged), + (c.mouseIsDown = this.hasDragged = this.hasPinched = !1), + (this.pinchDown = [])); + }, + onContainerMouseDown: function(a) { + 2 !== a.button && + ((a = this.normalize(a)), + this.zoomOption(a), + a.preventDefault && a.preventDefault(), + this.dragStart(a)); + }, + onDocumentMouseUp: function(b) { + H[a.hoverChartIndex] && H[a.hoverChartIndex].pointer.drop(b); + }, + onDocumentMouseMove: function(a) { + var b = this.chart, + c = this.chartPosition; + a = this.normalize(a, c); + !c || + this.inClass(a.target, 'highcharts-tracker') || + b.isInsidePlot(a.chartX - b.plotLeft, a.chartY - b.plotTop) || + this.reset(); + }, + onContainerMouseLeave: function(b) { + var c = H[a.hoverChartIndex]; + c && + (b.relatedTarget || b.toElement) && + (c.pointer.reset(), (c.pointer.chartPosition = null)); + }, + onContainerMouseMove: function(b) { + var c = this.chart; + (l(a.hoverChartIndex) && + H[a.hoverChartIndex] && + H[a.hoverChartIndex].mouseIsDown) || + (a.hoverChartIndex = c.index); + b = this.normalize(b); + b.returnValue = !1; + 'mousedown' === c.mouseIsDown && this.drag(b); + (!this.inClass(b.target, 'highcharts-tracker') && + !c.isInsidePlot(b.chartX - c.plotLeft, b.chartY - c.plotTop)) || + c.openMenu || + this.runPointActions(b); + }, + inClass: function(a, c) { + for (var b; a; ) { + if ((b = D(a, 'class'))) { + if (-1 !== b.indexOf(c)) return !0; + if (-1 !== b.indexOf('highcharts-container')) return !1; + } + a = a.parentNode; + } + }, + onTrackerMouseOut: function(a) { + var b = this.chart.hoverSeries; + a = a.relatedTarget || a.toElement; + this.isDirectTouch = !1; + if ( + !( + !b || + !a || + b.stickyTracking || + this.inClass(a, 'highcharts-tooltip') || + (this.inClass(a, 'highcharts-series-' + b.index) && + this.inClass(a, 'highcharts-tracker')) + ) + ) + b.onMouseOut(); + }, + onContainerClick: function(a) { + var b = this.chart, + c = b.hoverPoint, + d = b.plotLeft, + e = b.plotTop; + a = this.normalize(a); + b.cancelClick || + (c && this.inClass(a.target, 'highcharts-tracker') + ? (u(c.series, 'click', n(a, { point: c })), + b.hoverPoint && c.firePointEvent('click', a)) + : (n(a, this.getCoordinates(a)), + b.isInsidePlot(a.chartX - d, a.chartY - e) && u(b, 'click', a))); + }, + setDOMEvents: function() { + var b = this, + c = b.chart.container, + d = c.ownerDocument; + c.onmousedown = function(a) { + b.onContainerMouseDown(a); + }; + c.onmousemove = function(a) { + b.onContainerMouseMove(a); + }; + c.onclick = function(a) { + b.onContainerClick(a); + }; + this.unbindContainerMouseLeave = E( + c, + 'mouseleave', + b.onContainerMouseLeave, + ); + a.unbindDocumentMouseUp || + (a.unbindDocumentMouseUp = E(d, 'mouseup', b.onDocumentMouseUp)); + a.hasTouch && + ((c.ontouchstart = function(a) { + b.onContainerTouchStart(a); + }), + (c.ontouchmove = function(a) { + b.onContainerTouchMove(a); + }), + a.unbindDocumentTouchEnd || + (a.unbindDocumentTouchEnd = E( + d, + 'touchend', + b.onDocumentTouchEnd, + ))); + }, + destroy: function() { + var b = this; + b.unDocMouseMove && b.unDocMouseMove(); + this.unbindContainerMouseLeave(); + a.chartCount || + (a.unbindDocumentMouseUp && + (a.unbindDocumentMouseUp = a.unbindDocumentMouseUp()), + a.unbindDocumentTouchEnd && + (a.unbindDocumentTouchEnd = a.unbindDocumentTouchEnd())); + clearInterval(b.tooltipTimeout); + a.objectEach(b, function(a, c) { + b[c] = null; + }); + }, + }; + })(M); + (function(a) { + var E = a.charts, + D = a.each, + H = a.extend, + p = a.map, + f = a.noop, + l = a.pick; + H(a.Pointer.prototype, { + pinchTranslate: function(a, f, l, p, e, h) { + this.zoomHor && this.pinchTranslateDirection(!0, a, f, l, p, e, h); + this.zoomVert && this.pinchTranslateDirection(!1, a, f, l, p, e, h); + }, + pinchTranslateDirection: function(a, f, l, p, e, h, m, d) { + var c = this.chart, + b = a ? 'x' : 'y', + k = a ? 'X' : 'Y', + z = 'chart' + k, + n = a ? 'width' : 'height', + r = c['plot' + (a ? 'Left' : 'Top')], + x, + w, + t = d || 1, + C = c.inverted, + u = c.bounds[a ? 'h' : 'v'], + q = 1 === f.length, + A = f[0][z], + F = l[0][z], + G = !q && f[1][z], + g = !q && l[1][z], + v; + l = function() { + !q && + 20 < Math.abs(A - G) && + (t = d || Math.abs(F - g) / Math.abs(A - G)); + w = (r - F) / t + A; + x = c['plot' + (a ? 'Width' : 'Height')] / t; + }; + l(); + f = w; + f < u.min + ? ((f = u.min), (v = !0)) + : f + x > u.max && ((f = u.max - x), (v = !0)); + v + ? ((F -= 0.8 * (F - m[b][0])), q || (g -= 0.8 * (g - m[b][1])), l()) + : (m[b] = [F, g]); + C || ((h[b] = w - r), (h[n] = x)); + h = C ? 1 / t : t; + e[n] = x; + e[b] = f; + p[C ? (a ? 'scaleY' : 'scaleX') : 'scale' + k] = t; + p['translate' + k] = h * r + (F - h * A); + }, + pinch: function(a) { + var n = this, + r = n.chart, + u = n.pinchDown, + e = a.touches, + h = e.length, + m = n.lastValidTouch, + d = n.hasZoom, + c = n.selectionMarker, + b = {}, + k = + 1 === h && + ((n.inClass(a.target, 'highcharts-tracker') && r.runTrackerClick) || + n.runChartClick), + z = {}; + 1 < h && (n.initiated = !0); + d && n.initiated && !k && a.preventDefault(); + p(e, function(a) { + return n.normalize(a); + }); + 'touchstart' === a.type + ? (D(e, function(a, b) { + u[b] = { chartX: a.chartX, chartY: a.chartY }; + }), + (m.x = [u[0].chartX, u[1] && u[1].chartX]), + (m.y = [u[0].chartY, u[1] && u[1].chartY]), + D(r.axes, function(a) { + if (a.zoomEnabled) { + var b = r.bounds[a.horiz ? 'h' : 'v'], + c = a.minPixelPadding, + d = a.toPixels(l(a.options.min, a.dataMin)), + e = a.toPixels(l(a.options.max, a.dataMax)), + k = Math.max(d, e); + b.min = Math.min(a.pos, Math.min(d, e) - c); + b.max = Math.max(a.pos + a.len, k + c); + } + }), + (n.res = !0)) + : n.followTouchMove && 1 === h + ? this.runPointActions(n.normalize(a)) + : u.length && + (c || + (n.selectionMarker = c = H({ destroy: f, touch: !0 }, r.plotBox)), + n.pinchTranslate(u, e, b, c, z, m), + (n.hasPinched = d), + n.scaleGroups(b, z), + n.res && ((n.res = !1), this.reset(!1, 0))); + }, + touch: function(f, n) { + var p = this.chart, + r, + e; + if (p.index !== a.hoverChartIndex) + this.onContainerMouseLeave({ relatedTarget: !0 }); + a.hoverChartIndex = p.index; + 1 === f.touches.length + ? ((f = this.normalize(f)), + (e = p.isInsidePlot(f.chartX - p.plotLeft, f.chartY - p.plotTop)) && + !p.openMenu + ? (n && this.runPointActions(f), + 'touchmove' === f.type && + ((n = this.pinchDown), + (r = n[0] + ? 4 <= + Math.sqrt( + Math.pow(n[0].chartX - f.chartX, 2) + + Math.pow(n[0].chartY - f.chartY, 2), + ) + : !1)), + l(r, !0) && this.pinch(f)) + : n && this.reset()) + : 2 === f.touches.length && this.pinch(f); + }, + onContainerTouchStart: function(a) { + this.zoomOption(a); + this.touch(a, !0); + }, + onContainerTouchMove: function(a) { + this.touch(a); + }, + onDocumentTouchEnd: function(f) { + E[a.hoverChartIndex] && E[a.hoverChartIndex].pointer.drop(f); + }, + }); + })(M); + (function(a) { + var E = a.addEvent, + D = a.charts, + H = a.css, + p = a.doc, + f = a.extend, + l = a.noop, + r = a.Pointer, + n = a.removeEvent, + w = a.win, + u = a.wrap; + if (!a.hasTouch && (w.PointerEvent || w.MSPointerEvent)) { + var e = {}, + h = !!w.PointerEvent, + m = function() { + var c = []; + c.item = function(a) { + return this[a]; + }; + a.objectEach(e, function(a) { + c.push({ pageX: a.pageX, pageY: a.pageY, target: a.target }); + }); + return c; + }, + d = function(c, b, d, e) { + ('touch' !== c.pointerType && + c.pointerType !== c.MSPOINTER_TYPE_TOUCH) || + !D[a.hoverChartIndex] || + (e(c), + (e = D[a.hoverChartIndex].pointer), + e[b]({ + type: d, + target: c.currentTarget, + preventDefault: l, + touches: m(), + })); + }; + f(r.prototype, { + onContainerPointerDown: function(a) { + d(a, 'onContainerTouchStart', 'touchstart', function(a) { + e[a.pointerId] = { + pageX: a.pageX, + pageY: a.pageY, + target: a.currentTarget, + }; + }); + }, + onContainerPointerMove: function(a) { + d(a, 'onContainerTouchMove', 'touchmove', function(a) { + e[a.pointerId] = { pageX: a.pageX, pageY: a.pageY }; + e[a.pointerId].target || (e[a.pointerId].target = a.currentTarget); + }); + }, + onDocumentPointerUp: function(a) { + d(a, 'onDocumentTouchEnd', 'touchend', function(a) { + delete e[a.pointerId]; + }); + }, + batchMSEvents: function(a) { + a( + this.chart.container, + h ? 'pointerdown' : 'MSPointerDown', + this.onContainerPointerDown, + ); + a( + this.chart.container, + h ? 'pointermove' : 'MSPointerMove', + this.onContainerPointerMove, + ); + a(p, h ? 'pointerup' : 'MSPointerUp', this.onDocumentPointerUp); + }, + }); + u(r.prototype, 'init', function(a, b, d) { + a.call(this, b, d); + this.hasZoom && + H(b.container, { + '-ms-touch-action': 'none', + 'touch-action': 'none', + }); + }); + u(r.prototype, 'setDOMEvents', function(a) { + a.apply(this); + (this.hasZoom || this.followTouchMove) && this.batchMSEvents(E); + }); + u(r.prototype, 'destroy', function(a) { + this.batchMSEvents(n); + a.call(this); + }); + } + })(M); + (function(a) { + var E = a.addEvent, + D = a.css, + H = a.discardElement, + p = a.defined, + f = a.each, + l = a.isFirefox, + r = a.marginNames, + n = a.merge, + w = a.pick, + u = a.setAnimation, + e = a.stableSort, + h = a.win, + m = a.wrap; + a.Legend = function(a, c) { + this.init(a, c); + }; + a.Legend.prototype = { + init: function(a, c) { + this.chart = a; + this.setOptions(c); + c.enabled && + (this.render(), + E(this.chart, 'endResize', function() { + this.legend.positionCheckboxes(); + })); + }, + setOptions: function(a) { + var c = w(a.padding, 8); + this.options = a; + this.itemStyle = a.itemStyle; + this.itemHiddenStyle = n(this.itemStyle, a.itemHiddenStyle); + this.itemMarginTop = a.itemMarginTop || 0; + this.padding = c; + this.initialItemY = c - 5; + this.itemHeight = this.maxItemWidth = 0; + this.symbolWidth = w(a.symbolWidth, 16); + this.pages = []; + }, + update: function(a, c) { + var b = this.chart; + this.setOptions(n(!0, this.options, a)); + this.destroy(); + b.isDirtyLegend = b.isDirtyBox = !0; + w(c, !0) && b.redraw(); + }, + colorizeItem: function(a, c) { + a.legendGroup[c ? 'removeClass' : 'addClass']( + 'highcharts-legend-item-hidden', + ); + var b = this.options, + d = a.legendItem, + e = a.legendLine, + h = a.legendSymbol, + f = this.itemHiddenStyle.color, + b = c ? b.itemStyle.color : f, + m = c ? a.color || f : f, + l = a.options && a.options.marker, + t = { fill: m }; + d && d.css({ fill: b, color: b }); + e && e.attr({ stroke: m }); + h && + (l && + h.isMarker && + ((t = a.pointAttribs()), c || (t.stroke = t.fill = f)), + h.attr(t)); + }, + positionItem: function(a) { + var c = this.options, + b = c.symbolPadding, + c = !c.rtl, + d = a._legendItemPos, + e = d[0], + d = d[1], + h = a.checkbox; + (a = a.legendGroup) && + a.element && + a.translate(c ? e : this.legendWidth - e - 2 * b - 4, d); + h && ((h.x = e), (h.y = d)); + }, + destroyItem: function(a) { + var c = a.checkbox; + f(['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'], function( + b, + ) { + a[b] && (a[b] = a[b].destroy()); + }); + c && H(a.checkbox); + }, + destroy: function() { + function a(a) { + this[a] && (this[a] = this[a].destroy()); + } + f(this.getAllItems(), function(c) { + f(['legendItem', 'legendGroup'], a, c); + }); + f('clipRect up down pager nav box title group'.split(' '), a, this); + this.display = null; + }, + positionCheckboxes: function() { + var a = this.group && this.group.alignAttr, + c, + b = this.clipHeight || this.legendHeight, + e = this.titleHeight; + a && + ((c = a.translateY), + f( + this.allItems, + function(d) { + var k = d.checkbox, + h; + k && + ((h = c + e + k.y + (this.scrollOffset || 0) + 3), + D(k, { + left: a.translateX + d.checkboxOffset + k.x - 20 + 'px', + top: h + 'px', + display: h > c - 6 && h < c + b - 6 ? '' : 'none', + })); + }, + this, + )); + }, + renderTitle: function() { + var a = this.options, + c = this.padding, + b = a.title, + e = 0; + b.text && + (this.title || + (this.title = this.chart.renderer + .label( + b.text, + c - 3, + c - 4, + null, + null, + null, + a.useHTML, + null, + 'legend-title', + ) + .attr({ zIndex: 1 }) + .css(b.style) + .add(this.group)), + (a = this.title.getBBox()), + (e = a.height), + (this.offsetWidth = a.width), + this.contentGroup.attr({ translateY: e })); + this.titleHeight = e; + }, + setText: function(d) { + var c = this.options; + d.legendItem.attr({ + text: c.labelFormat + ? a.format(c.labelFormat, d) + : c.labelFormatter.call(d), + }); + }, + renderItem: function(a) { + var c = this.chart, + b = c.renderer, + d = this.options, + e = 'horizontal' === d.layout, + h = this.symbolWidth, + f = d.symbolPadding, + m = this.itemStyle, + l = this.itemHiddenStyle, + t = this.padding, + p = e ? w(d.itemDistance, 20) : 0, + r = !d.rtl, + q = d.width, + A = d.itemMarginBottom || 0, + F = this.itemMarginTop, + G = a.legendItem, + g = !a.series, + v = !g && a.series.drawLegendSymbol ? a.series : a, + u = v.options, + L = this.createCheckboxForItem && u && u.showCheckbox, + u = h + f + p + (L ? 20 : 0), + P = d.useHTML, + J = a.options.className; + G || + ((a.legendGroup = b + .g('legend-item') + .addClass( + 'highcharts-' + + v.type + + '-series highcharts-color-' + + a.colorIndex + + (J ? ' ' + J : '') + + (g ? ' highcharts-series-' + a.index : ''), + ) + .attr({ zIndex: 1 }) + .add(this.scrollGroup)), + (a.legendItem = G = b + .text('', r ? h + f : -f, this.baseline || 0, P) + .css(n(a.visible ? m : l)) + .attr({ align: r ? 'left' : 'right', zIndex: 2 }) + .add(a.legendGroup)), + this.baseline || + ((h = m.fontSize), + (this.fontMetrics = b.fontMetrics(h, G)), + (this.baseline = this.fontMetrics.f + 3 + F), + G.attr('y', this.baseline)), + (this.symbolHeight = d.symbolHeight || this.fontMetrics.f), + v.drawLegendSymbol(this, a), + this.setItemEvents && this.setItemEvents(a, G, P), + L && this.createCheckboxForItem(a)); + this.colorizeItem(a, a.visible); + m.width || + G.css({ width: (d.itemWidth || d.width || c.spacingBox.width) - u }); + this.setText(a); + b = G.getBBox(); + m = a.checkboxOffset = d.itemWidth || a.legendItemWidth || b.width + u; + this.itemHeight = b = Math.round( + a.legendItemHeight || b.height || this.symbolHeight, + ); + e && + this.itemX - t + m > (q || c.spacingBox.width - 2 * t - d.x) && + ((this.itemX = t), + (this.itemY += F + this.lastLineHeight + A), + (this.lastLineHeight = 0)); + this.maxItemWidth = Math.max(this.maxItemWidth, m); + this.lastItemY = F + this.itemY + A; + this.lastLineHeight = Math.max(b, this.lastLineHeight); + a._legendItemPos = [this.itemX, this.itemY]; + e + ? (this.itemX += m) + : ((this.itemY += F + b + A), (this.lastLineHeight = b)); + this.offsetWidth = + q || + Math.max( + (e ? this.itemX - t - (a.checkbox ? 0 : p) : m) + t, + this.offsetWidth, + ); + }, + getAllItems: function() { + var a = []; + f(this.chart.series, function(c) { + var b = c && c.options; + c && + w(b.showInLegend, p(b.linkedTo) ? !1 : void 0, !0) && + (a = a.concat( + c.legendItems || ('point' === b.legendType ? c.data : c), + )); + }); + return a; + }, + getAlignment: function() { + var a = this.options; + return a.floating + ? '' + : a.align.charAt(0) + a.verticalAlign.charAt(0) + a.layout.charAt(0); + }, + adjustMargins: function(a, c) { + var b = this.chart, + d = this.options, + e = this.getAlignment(); + e && + f( + [/(lth|ct|rth)/, /(rtv|rm|rbv)/, /(rbh|cb|lbh)/, /(lbv|lm|ltv)/], + function(k, h) { + k.test(e) && + !p(a[h]) && + (b[r[h]] = Math.max( + b[r[h]], + b.legend[(h + 1) % 2 ? 'legendHeight' : 'legendWidth'] + + [1, -1, -1, 1][h] * d[h % 2 ? 'x' : 'y'] + + w(d.margin, 12) + + c[h] + + (0 === h ? b.titleOffset + b.options.title.margin : 0), + )); + }, + ); + }, + render: function() { + var a = this, + c = a.chart, + b = c.renderer, + k = a.group, + h, + m, + l, + x, + p = a.box, + t = a.options, + C = a.padding; + a.itemX = C; + a.itemY = a.initialItemY; + a.offsetWidth = 0; + a.lastItemY = 0; + k || + ((a.group = k = b + .g('legend') + .attr({ zIndex: 7 }) + .add()), + (a.contentGroup = b + .g() + .attr({ zIndex: 1 }) + .add(k)), + (a.scrollGroup = b.g().add(a.contentGroup))); + a.renderTitle(); + h = a.getAllItems(); + e(h, function(a, b) { + return ( + ((a.options && a.options.legendIndex) || 0) - + ((b.options && b.options.legendIndex) || 0) + ); + }); + t.reversed && h.reverse(); + a.allItems = h; + a.display = m = !!h.length; + a.lastLineHeight = 0; + f(h, function(b) { + a.renderItem(b); + }); + l = (t.width || a.offsetWidth) + C; + x = a.lastItemY + a.lastLineHeight + a.titleHeight; + x = a.handleOverflow(x); + x += C; + p || + ((a.box = p = b + .rect() + .addClass('highcharts-legend-box') + .attr({ r: t.borderRadius }) + .add(k)), + (p.isNew = !0)); + p.attr({ + stroke: t.borderColor, + 'stroke-width': t.borderWidth || 0, + fill: t.backgroundColor || 'none', + }).shadow(t.shadow); + 0 < l && + 0 < x && + (p[p.isNew ? 'attr' : 'animate']( + p.crisp.call( + {}, + { x: 0, y: 0, width: l, height: x }, + p.strokeWidth(), + ), + ), + (p.isNew = !1)); + p[m ? 'show' : 'hide'](); + a.legendWidth = l; + a.legendHeight = x; + f(h, function(b) { + a.positionItem(b); + }); + m && + ((b = c.spacingBox), + /(lth|ct|rth)/.test(a.getAlignment()) && + (b = n(b, { y: b.y + c.titleOffset + c.options.title.margin })), + k.align(n(t, { width: l, height: x }), !0, b)); + c.isResizing || this.positionCheckboxes(); + }, + handleOverflow: function(a) { + var c = this, + b = this.chart, + d = b.renderer, + e = this.options, + h = e.y, + m = this.padding, + b = b.spacingBox.height + ('top' === e.verticalAlign ? -h : h) - m, + h = e.maxHeight, + l, + n = this.clipRect, + t = e.navigation, + p = w(t.animation, !0), + r = t.arrowSize || 12, + q = this.nav, + A = this.pages, + F, + G = this.allItems, + g = function(a) { + 'number' === typeof a + ? n.attr({ height: a }) + : n && ((c.clipRect = n.destroy()), c.contentGroup.clip()); + c.contentGroup.div && + (c.contentGroup.div.style.clip = a + ? 'rect(' + m + 'px,9999px,' + (m + a) + 'px,0)' + : 'auto'); + }; + 'horizontal' !== e.layout || + 'middle' === e.verticalAlign || + e.floating || + (b /= 2); + h && (b = Math.min(b, h)); + A.length = 0; + a > b && !1 !== t.enabled + ? ((this.clipHeight = l = Math.max(b - 20 - this.titleHeight - m, 0)), + (this.currentPage = w(this.currentPage, 1)), + (this.fullHeight = a), + f(G, function(a, b) { + var c = a._legendItemPos[1], + d = Math.round(a.legendItem.getBBox().height), + g = A.length; + if (!g || (c - A[g - 1] > l && (F || c) !== A[g - 1])) + A.push(F || c), g++; + a.pageIx = g - 1; + F && (G[b - 1].pageIx = g - 1); + b === G.length - 1 && + c + d - A[g - 1] > l && + (A.push(c), (a.pageIx = g)); + c !== F && (F = c); + }), + n || + ((n = c.clipRect = d.clipRect(0, m, 9999, 0)), + c.contentGroup.clip(n)), + g(l), + q || + ((this.nav = q = d + .g() + .attr({ zIndex: 1 }) + .add(this.group)), + (this.up = d + .symbol('triangle', 0, 0, r, r) + .on('click', function() { + c.scroll(-1, p); + }) + .add(q)), + (this.pager = d + .text('', 15, 10) + .addClass('highcharts-legend-navigation') + .css(t.style) + .add(q)), + (this.down = d + .symbol('triangle-down', 0, 0, r, r) + .on('click', function() { + c.scroll(1, p); + }) + .add(q))), + c.scroll(0), + (a = b)) + : q && + (g(), + (this.nav = q.destroy()), + this.scrollGroup.attr({ translateY: 1 }), + (this.clipHeight = 0)); + return a; + }, + scroll: function(a, c) { + var b = this.pages, + d = b.length; + a = this.currentPage + a; + var e = this.clipHeight, + h = this.options.navigation, + f = this.pager, + m = this.padding; + a > d && (a = d); + 0 < a && + (void 0 !== c && u(c, this.chart), + this.nav.attr({ + translateX: m, + translateY: e + this.padding + 7 + this.titleHeight, + visibility: 'visible', + }), + this.up.attr({ + class: + 1 === a + ? 'highcharts-legend-nav-inactive' + : 'highcharts-legend-nav-active', + }), + f.attr({ text: a + '/' + d }), + this.down.attr({ + x: 18 + this.pager.getBBox().width, + class: + a === d + ? 'highcharts-legend-nav-inactive' + : 'highcharts-legend-nav-active', + }), + this.up + .attr({ fill: 1 === a ? h.inactiveColor : h.activeColor }) + .css({ cursor: 1 === a ? 'default' : 'pointer' }), + this.down + .attr({ fill: a === d ? h.inactiveColor : h.activeColor }) + .css({ cursor: a === d ? 'default' : 'pointer' }), + (this.scrollOffset = -b[a - 1] + this.initialItemY), + this.scrollGroup.animate({ translateY: this.scrollOffset }), + (this.currentPage = a), + this.positionCheckboxes()); + }, + }; + a.LegendSymbolMixin = { + drawRectangle: function(a, c) { + var b = a.symbolHeight, + d = a.options.squareSymbol; + c.legendSymbol = this.chart.renderer + .rect( + d ? (a.symbolWidth - b) / 2 : 0, + a.baseline - b + 1, + d ? b : a.symbolWidth, + b, + w(a.options.symbolRadius, b / 2), + ) + .addClass('highcharts-point') + .attr({ zIndex: 3 }) + .add(c.legendGroup); + }, + drawLineMarker: function(a) { + var c = this.options, + b = c.marker, + d = a.symbolWidth, + e = a.symbolHeight, + h = e / 2, + f = this.chart.renderer, + m = this.legendGroup; + a = a.baseline - Math.round(0.3 * a.fontMetrics.b); + var l; + l = { 'stroke-width': c.lineWidth || 0 }; + c.dashStyle && (l.dashstyle = c.dashStyle); + this.legendLine = f + .path(['M', 0, a, 'L', d, a]) + .addClass('highcharts-graph') + .attr(l) + .add(m); + b && + !1 !== b.enabled && + ((c = Math.min(w(b.radius, h), h)), + 0 === this.symbol.indexOf('url') && + ((b = n(b, { width: e, height: e })), (c = 0)), + (this.legendSymbol = b = f + .symbol(this.symbol, d / 2 - c, a - c, 2 * c, 2 * c, b) + .addClass('highcharts-point') + .add(m)), + (b.isMarker = !0)); + }, + }; + (/Trident\/7\.0/.test(h.navigator.userAgent) || l) && + m(a.Legend.prototype, 'positionItem', function(a, c) { + var b = this, + d = function() { + c._legendItemPos && a.call(b, c); + }; + d(); + setTimeout(d); + }); + })(M); + (function(a) { + var E = a.addEvent, + D = a.animate, + H = a.animObject, + p = a.attr, + f = a.doc, + l = a.Axis, + r = a.createElement, + n = a.defaultOptions, + w = a.discardElement, + u = a.charts, + e = a.css, + h = a.defined, + m = a.each, + d = a.extend, + c = a.find, + b = a.fireEvent, + k = a.grep, + z = a.isNumber, + B = a.isObject, + I = a.isString, + x = a.Legend, + K = a.marginNames, + t = a.merge, + C = a.objectEach, + N = a.Pointer, + q = a.pick, + A = a.pInt, + F = a.removeEvent, + G = a.seriesTypes, + g = a.splat, + v = a.svg, + Q = a.syncTimeout, + L = a.win, + P = (a.Chart = function() { + this.getArgs.apply(this, arguments); + }); + a.chart = function(a, b, c) { + return new P(a, b, c); + }; + d(P.prototype, { + callbacks: [], + getArgs: function() { + var a = [].slice.call(arguments); + if (I(a[0]) || a[0].nodeName) this.renderTo = a.shift(); + this.init(a[0], a[1]); + }, + init: function(b, c) { + var d, + g, + e = b.series, + k = b.plotOptions || {}; + b.series = null; + d = t(n, b); + for (g in d.plotOptions) + d.plotOptions[g].tooltip = (k[g] && t(k[g].tooltip)) || void 0; + d.tooltip.userOptions = + (b.chart && b.chart.forExport && b.tooltip.userOptions) || b.tooltip; + d.series = b.series = e; + this.userOptions = b; + b = d.chart; + g = b.events; + this.margin = []; + this.spacing = []; + this.bounds = { h: {}, v: {} }; + this.labelCollectors = []; + this.callback = c; + this.isResizing = 0; + this.options = d; + this.axes = []; + this.series = []; + this.hasCartesianSeries = b.showAxes; + var q = this; + q.index = u.length; + u.push(q); + a.chartCount++; + g && + C(g, function(a, b) { + E(q, b, a); + }); + q.xAxis = []; + q.yAxis = []; + q.pointCount = q.colorCounter = q.symbolCounter = 0; + q.firstRender(); + }, + initSeries: function(b) { + var c = this.options.chart; + (c = G[b.type || c.type || c.defaultSeriesType]) || a.error(17, !0); + c = new c(); + c.init(this, b); + return c; + }, + orderSeries: function(a) { + var b = this.series; + for (a = a || 0; a < b.length; a++) + b[a] && + ((b[a].index = a), + (b[a].name = b[a].name || 'Series ' + (b[a].index + 1))); + }, + isInsidePlot: function(a, b, c) { + var d = c ? b : a; + a = c ? a : b; + return 0 <= d && d <= this.plotWidth && 0 <= a && a <= this.plotHeight; + }, + redraw: function(c) { + var g = this.axes, + e = this.series, + k = this.pointer, + q = this.legend, + h = this.isDirtyLegend, + f, + l, + v = this.hasCartesianSeries, + A = this.isDirtyBox, + F, + t = this.renderer, + x = t.isHidden(), + n = []; + this.setResponsive && this.setResponsive(!1); + a.setAnimation(c, this); + x && this.temporaryDisplay(); + this.layOutTitles(); + for (c = e.length; c--; ) + if (((F = e[c]), F.options.stacking && ((f = !0), F.isDirty))) { + l = !0; + break; + } + if (l) + for (c = e.length; c--; ) + (F = e[c]), F.options.stacking && (F.isDirty = !0); + m(e, function(a) { + a.isDirty && + 'point' === a.options.legendType && + (a.updateTotals && a.updateTotals(), (h = !0)); + a.isDirtyData && b(a, 'updatedData'); + }); + h && q.options.enabled && (q.render(), (this.isDirtyLegend = !1)); + f && this.getStacks(); + v && + m(g, function(a) { + a.updateNames(); + a.setScale(); + }); + this.getMargins(); + v && + (m(g, function(a) { + a.isDirty && (A = !0); + }), + m(g, function(a) { + var c = a.min + ',' + a.max; + a.extKey !== c && + ((a.extKey = c), + n.push(function() { + b(a, 'afterSetExtremes', d(a.eventArgs, a.getExtremes())); + delete a.eventArgs; + })); + (A || f) && a.redraw(); + })); + A && this.drawChartBox(); + b(this, 'predraw'); + m(e, function(a) { + (A || a.isDirty) && a.visible && a.redraw(); + a.isDirtyData = !1; + }); + k && k.reset(!0); + t.draw(); + b(this, 'redraw'); + b(this, 'render'); + x && this.temporaryDisplay(!0); + m(n, function(a) { + a.call(); + }); + }, + get: function(a) { + function b(b) { + return b.id === a || (b.options && b.options.id === a); + } + var d, + g = this.series, + e; + d = c(this.axes, b) || c(this.series, b); + for (e = 0; !d && e < g.length; e++) d = c(g[e].points || [], b); + return d; + }, + getAxes: function() { + var a = this, + b = this.options, + c = (b.xAxis = g(b.xAxis || {})), + b = (b.yAxis = g(b.yAxis || {})); + m(c, function(a, b) { + a.index = b; + a.isX = !0; + }); + m(b, function(a, b) { + a.index = b; + }); + c = c.concat(b); + m(c, function(b) { + new l(a, b); + }); + }, + getSelectedPoints: function() { + var a = []; + m(this.series, function(b) { + a = a.concat( + k(b.data || [], function(a) { + return a.selected; + }), + ); + }); + return a; + }, + getSelectedSeries: function() { + return k(this.series, function(a) { + return a.selected; + }); + }, + setTitle: function(a, b, c) { + var d = this, + g = d.options, + e; + e = g.title = t( + { + style: { color: '#333333', fontSize: g.isStock ? '16px' : '18px' }, + }, + g.title, + a, + ); + g = g.subtitle = t({ style: { color: '#666666' } }, g.subtitle, b); + m([['title', a, e], ['subtitle', b, g]], function(a, b) { + var c = a[0], + g = d[c], + e = a[1]; + a = a[2]; + g && e && (d[c] = g = g.destroy()); + a && + !g && + ((d[c] = d.renderer + .text(a.text, 0, 0, a.useHTML) + .attr({ + align: a.align, + class: 'highcharts-' + c, + zIndex: a.zIndex || 4, + }) + .add()), + (d[c].update = function(a) { + d.setTitle(!b && a, b && a); + }), + d[c].css(a.style)); + }); + d.layOutTitles(c); + }, + layOutTitles: function(a) { + var b = 0, + c, + g = this.renderer, + e = this.spacingBox; + m( + ['title', 'subtitle'], + function(a) { + var c = this[a], + k = this.options[a]; + a = 'title' === a ? -3 : k.verticalAlign ? 0 : b + 2; + var q; + c && + ((q = k.style.fontSize), + (q = g.fontMetrics(q, c).b), + c + .css({ width: (k.width || e.width + k.widthAdjust) + 'px' }) + .align(d({ y: a + q }, k), !1, 'spacingBox'), + k.floating || + k.verticalAlign || + (b = Math.ceil(b + c.getBBox(k.useHTML).height))); + }, + this, + ); + c = this.titleOffset !== b; + this.titleOffset = b; + !this.isDirtyBox && + c && + ((this.isDirtyBox = c), + this.hasRendered && q(a, !0) && this.isDirtyBox && this.redraw()); + }, + getChartSize: function() { + var b = this.options.chart, + c = b.width, + b = b.height, + d = this.renderTo; + h(c) || (this.containerWidth = a.getStyle(d, 'width')); + h(b) || (this.containerHeight = a.getStyle(d, 'height')); + this.chartWidth = Math.max(0, c || this.containerWidth || 600); + this.chartHeight = Math.max( + 0, + a.relativeLength(b, this.chartWidth) || + (1 < this.containerHeight ? this.containerHeight : 400), + ); + }, + temporaryDisplay: function(b) { + var c = this.renderTo; + if (b) + for (; c && c.style; ) + c.hcOrigStyle && (a.css(c, c.hcOrigStyle), delete c.hcOrigStyle), + c.hcOrigDetached && + (f.body.removeChild(c), (c.hcOrigDetached = !1)), + (c = c.parentNode); + else + for (; c && c.style; ) { + f.body.contains(c) || + c.parentNode || + ((c.hcOrigDetached = !0), f.body.appendChild(c)); + if ('none' === a.getStyle(c, 'display', !1) || c.hcOricDetached) + (c.hcOrigStyle = { + display: c.style.display, + height: c.style.height, + overflow: c.style.overflow, + }), + (b = { display: 'block', overflow: 'hidden' }), + c !== this.renderTo && (b.height = 0), + a.css(c, b), + c.offsetWidth || + c.style.setProperty('display', 'block', 'important'); + c = c.parentNode; + if (c === f.body) break; + } + }, + setClassName: function(a) { + this.container.className = 'highcharts-container ' + (a || ''); + }, + getContainer: function() { + var b, + c = this.options, + g = c.chart, + e, + k; + b = this.renderTo; + var q = a.uniqueKey(), + h; + b || (this.renderTo = b = g.renderTo); + I(b) && (this.renderTo = b = f.getElementById(b)); + b || a.error(13, !0); + e = A(p(b, 'data-highcharts-chart')); + z(e) && u[e] && u[e].hasRendered && u[e].destroy(); + p(b, 'data-highcharts-chart', this.index); + b.innerHTML = ''; + g.skipClone || b.offsetWidth || this.temporaryDisplay(); + this.getChartSize(); + e = this.chartWidth; + k = this.chartHeight; + h = d( + { + position: 'relative', + overflow: 'hidden', + width: e + 'px', + height: k + 'px', + textAlign: 'left', + lineHeight: 'normal', + zIndex: 0, + '-webkit-tap-highlight-color': 'rgba(0,0,0,0)', + }, + g.style, + ); + this.container = b = r('div', { id: q }, h, b); + this._cursor = b.style.cursor; + this.renderer = new (a[g.renderer] || a.Renderer)( + b, + e, + k, + null, + g.forExport, + c.exporting && c.exporting.allowHTML, + ); + this.setClassName(g.className); + this.renderer.setStyle(g.style); + this.renderer.chartIndex = this.index; + }, + getMargins: function(a) { + var b = this.spacing, + c = this.margin, + d = this.titleOffset; + this.resetMargins(); + d && + !h(c[0]) && + (this.plotTop = Math.max( + this.plotTop, + d + this.options.title.margin + b[0], + )); + this.legend && this.legend.display && this.legend.adjustMargins(c, b); + this.extraMargin && + (this[this.extraMargin.type] = + (this[this.extraMargin.type] || 0) + this.extraMargin.value); + this.adjustPlotArea && this.adjustPlotArea(); + a || this.getAxisMargins(); + }, + getAxisMargins: function() { + var a = this, + b = (a.axisOffset = [0, 0, 0, 0]), + c = a.margin; + a.hasCartesianSeries && + m(a.axes, function(a) { + a.visible && a.getOffset(); + }); + m(K, function(d, g) { + h(c[g]) || (a[d] += b[g]); + }); + a.setChartSize(); + }, + reflow: function(b) { + var c = this, + d = c.options.chart, + g = c.renderTo, + e = h(d.width) && h(d.height), + k = d.width || a.getStyle(g, 'width'), + d = d.height || a.getStyle(g, 'height'), + g = b ? b.target : L; + if (!e && !c.isPrinting && k && d && (g === L || g === f)) { + if (k !== c.containerWidth || d !== c.containerHeight) + clearTimeout(c.reflowTimeout), + (c.reflowTimeout = Q( + function() { + c.container && c.setSize(void 0, void 0, !1); + }, + b ? 100 : 0, + )); + c.containerWidth = k; + c.containerHeight = d; + } + }, + initReflow: function() { + var a = this, + b; + b = E(L, 'resize', function(b) { + a.reflow(b); + }); + E(a, 'destroy', b); + }, + setSize: function(c, d, g) { + var k = this, + q = k.renderer; + k.isResizing += 1; + a.setAnimation(g, k); + k.oldChartHeight = k.chartHeight; + k.oldChartWidth = k.chartWidth; + void 0 !== c && (k.options.chart.width = c); + void 0 !== d && (k.options.chart.height = d); + k.getChartSize(); + c = q.globalAnimation; + (c ? D : e)( + k.container, + { width: k.chartWidth + 'px', height: k.chartHeight + 'px' }, + c, + ); + k.setChartSize(!0); + q.setSize(k.chartWidth, k.chartHeight, g); + m(k.axes, function(a) { + a.isDirty = !0; + a.setScale(); + }); + k.isDirtyLegend = !0; + k.isDirtyBox = !0; + k.layOutTitles(); + k.getMargins(); + k.redraw(g); + k.oldChartHeight = null; + b(k, 'resize'); + Q(function() { + k && + b(k, 'endResize', null, function() { + --k.isResizing; + }); + }, H(c).duration); + }, + setChartSize: function(a) { + var b = this.inverted, + c = this.renderer, + d = this.chartWidth, + g = this.chartHeight, + e = this.options.chart, + k = this.spacing, + q = this.clipOffset, + h, + f, + l, + v; + this.plotLeft = h = Math.round(this.plotLeft); + this.plotTop = f = Math.round(this.plotTop); + this.plotWidth = l = Math.max(0, Math.round(d - h - this.marginRight)); + this.plotHeight = v = Math.max( + 0, + Math.round(g - f - this.marginBottom), + ); + this.plotSizeX = b ? v : l; + this.plotSizeY = b ? l : v; + this.plotBorderWidth = e.plotBorderWidth || 0; + this.spacingBox = c.spacingBox = { + x: k[3], + y: k[0], + width: d - k[3] - k[1], + height: g - k[0] - k[2], + }; + this.plotBox = c.plotBox = { x: h, y: f, width: l, height: v }; + d = 2 * Math.floor(this.plotBorderWidth / 2); + b = Math.ceil(Math.max(d, q[3]) / 2); + c = Math.ceil(Math.max(d, q[0]) / 2); + this.clipBox = { + x: b, + y: c, + width: Math.floor(this.plotSizeX - Math.max(d, q[1]) / 2 - b), + height: Math.max( + 0, + Math.floor(this.plotSizeY - Math.max(d, q[2]) / 2 - c), + ), + }; + a || + m(this.axes, function(a) { + a.setAxisSize(); + a.setAxisTranslation(); + }); + }, + resetMargins: function() { + var a = this, + b = a.options.chart; + m(['margin', 'spacing'], function(c) { + var d = b[c], + g = B(d) ? d : [d, d, d, d]; + m(['Top', 'Right', 'Bottom', 'Left'], function(d, e) { + a[c][e] = q(b[c + d], g[e]); + }); + }); + m(K, function(b, c) { + a[b] = q(a.margin[c], a.spacing[c]); + }); + a.axisOffset = [0, 0, 0, 0]; + a.clipOffset = [0, 0, 0, 0]; + }, + drawChartBox: function() { + var a = this.options.chart, + b = this.renderer, + c = this.chartWidth, + d = this.chartHeight, + g = this.chartBackground, + e = this.plotBackground, + k = this.plotBorder, + q, + h = this.plotBGImage, + f = a.backgroundColor, + m = a.plotBackgroundColor, + l = a.plotBackgroundImage, + v, + A = this.plotLeft, + F = this.plotTop, + t = this.plotWidth, + x = this.plotHeight, + n = this.plotBox, + p = this.clipRect, + z = this.clipBox, + G = 'animate'; + g || + ((this.chartBackground = g = b + .rect() + .addClass('highcharts-background') + .add()), + (G = 'attr')); + q = a.borderWidth || 0; + v = q + (a.shadow ? 8 : 0); + f = { fill: f || 'none' }; + if (q || g['stroke-width']) + (f.stroke = a.borderColor), (f['stroke-width'] = q); + g.attr(f).shadow(a.shadow); + g[G]({ + x: v / 2, + y: v / 2, + width: c - v - (q % 2), + height: d - v - (q % 2), + r: a.borderRadius, + }); + G = 'animate'; + e || + ((G = 'attr'), + (this.plotBackground = e = b + .rect() + .addClass('highcharts-plot-background') + .add())); + e[G](n); + e.attr({ fill: m || 'none' }).shadow(a.plotShadow); + l && + (h + ? h.animate(n) + : (this.plotBGImage = b.image(l, A, F, t, x).add())); + p + ? p.animate({ width: z.width, height: z.height }) + : (this.clipRect = b.clipRect(z)); + G = 'animate'; + k || + ((G = 'attr'), + (this.plotBorder = k = b + .rect() + .addClass('highcharts-plot-border') + .attr({ zIndex: 1 }) + .add())); + k.attr({ + stroke: a.plotBorderColor, + 'stroke-width': a.plotBorderWidth || 0, + fill: 'none', + }); + k[G](k.crisp({ x: A, y: F, width: t, height: x }, -k.strokeWidth())); + this.isDirtyBox = !1; + }, + propFromSeries: function() { + var a = this, + b = a.options.chart, + c, + d = a.options.series, + g, + e; + m(['inverted', 'angular', 'polar'], function(k) { + c = G[b.type || b.defaultSeriesType]; + e = b[k] || (c && c.prototype[k]); + for (g = d && d.length; !e && g--; ) + (c = G[d[g].type]) && c.prototype[k] && (e = !0); + a[k] = e; + }); + }, + linkSeries: function() { + var a = this, + b = a.series; + m(b, function(a) { + a.linkedSeries.length = 0; + }); + m(b, function(b) { + var c = b.options.linkedTo; + I(c) && + (c = ':previous' === c ? a.series[b.index - 1] : a.get(c)) && + c.linkedParent !== b && + (c.linkedSeries.push(b), + (b.linkedParent = c), + (b.visible = q(b.options.visible, c.options.visible, b.visible))); + }); + }, + renderSeries: function() { + m(this.series, function(a) { + a.translate(); + a.render(); + }); + }, + renderLabels: function() { + var a = this, + b = a.options.labels; + b.items && + m(b.items, function(c) { + var g = d(b.style, c.style), + e = A(g.left) + a.plotLeft, + k = A(g.top) + a.plotTop + 12; + delete g.left; + delete g.top; + a.renderer + .text(c.html, e, k) + .attr({ zIndex: 2 }) + .css(g) + .add(); + }); + }, + render: function() { + var a = this.axes, + b = this.renderer, + c = this.options, + d, + g, + e; + this.setTitle(); + this.legend = new x(this, c.legend); + this.getStacks && this.getStacks(); + this.getMargins(!0); + this.setChartSize(); + c = this.plotWidth; + d = this.plotHeight = Math.max(this.plotHeight - 21, 0); + m(a, function(a) { + a.setScale(); + }); + this.getAxisMargins(); + g = 1.1 < c / this.plotWidth; + e = 1.05 < d / this.plotHeight; + if (g || e) + m(a, function(a) { + ((a.horiz && g) || (!a.horiz && e)) && a.setTickInterval(!0); + }), + this.getMargins(); + this.drawChartBox(); + this.hasCartesianSeries && + m(a, function(a) { + a.visible && a.render(); + }); + this.seriesGroup || + (this.seriesGroup = b + .g('series-group') + .attr({ zIndex: 3 }) + .add()); + this.renderSeries(); + this.renderLabels(); + this.addCredits(); + this.setResponsive && this.setResponsive(); + this.hasRendered = !0; + }, + addCredits: function(a) { + var b = this; + a = t(!0, this.options.credits, a); + a.enabled && + !this.credits && + ((this.credits = this.renderer + .text(a.text + (this.mapCredits || ''), 0, 0) + .addClass('highcharts-credits') + .on('click', function() { + a.href && (L.location.href = a.href); + }) + .attr({ align: a.position.align, zIndex: 8 }) + .css(a.style) + .add() + .align(a.position)), + (this.credits.update = function(a) { + b.credits = b.credits.destroy(); + b.addCredits(a); + })); + }, + destroy: function() { + var c = this, + d = c.axes, + g = c.series, + e = c.container, + k, + q = e && e.parentNode; + b(c, 'destroy'); + c.renderer.forExport ? a.erase(u, c) : (u[c.index] = void 0); + a.chartCount--; + c.renderTo.removeAttribute('data-highcharts-chart'); + F(c); + for (k = d.length; k--; ) d[k] = d[k].destroy(); + this.scroller && this.scroller.destroy && this.scroller.destroy(); + for (k = g.length; k--; ) g[k] = g[k].destroy(); + m( + 'title subtitle chartBackground plotBackground plotBGImage plotBorder seriesGroup clipRect credits pointer rangeSelector legend resetZoomButton tooltip renderer'.split( + ' ', + ), + function(a) { + var b = c[a]; + b && b.destroy && (c[a] = b.destroy()); + }, + ); + e && ((e.innerHTML = ''), F(e), q && w(e)); + C(c, function(a, b) { + delete c[b]; + }); + }, + isReadyToRender: function() { + var a = this; + return v || L != L.top || 'complete' === f.readyState + ? !0 + : (f.attachEvent('onreadystatechange', function() { + f.detachEvent('onreadystatechange', a.firstRender); + 'complete' === f.readyState && a.firstRender(); + }), + !1); + }, + firstRender: function() { + var a = this, + c = a.options; + if (a.isReadyToRender()) { + a.getContainer(); + b(a, 'init'); + a.resetMargins(); + a.setChartSize(); + a.propFromSeries(); + a.getAxes(); + m(c.series || [], function(b) { + a.initSeries(b); + }); + a.linkSeries(); + b(a, 'beforeRender'); + N && (a.pointer = new N(a, c)); + a.render(); + if (!a.renderer.imgCount && a.onload) a.onload(); + a.temporaryDisplay(!0); + } + }, + onload: function() { + m( + [this.callback].concat(this.callbacks), + function(a) { + a && void 0 !== this.index && a.apply(this, [this]); + }, + this, + ); + b(this, 'load'); + b(this, 'render'); + h(this.index) && !1 !== this.options.chart.reflow && this.initReflow(); + this.onload = null; + }, + }); + })(M); + (function(a) { + var E, + D = a.each, + H = a.extend, + p = a.erase, + f = a.fireEvent, + l = a.format, + r = a.isArray, + n = a.isNumber, + w = a.pick, + u = a.removeEvent; + a.Point = E = function() {}; + a.Point.prototype = { + init: function(a, h, f) { + this.series = a; + this.color = a.color; + this.applyOptions(h, f); + a.options.colorByPoint + ? ((h = a.options.colors || a.chart.options.colors), + (this.color = this.color || h[a.colorCounter]), + (h = h.length), + (f = a.colorCounter), + a.colorCounter++, + a.colorCounter === h && (a.colorCounter = 0)) + : (f = a.colorIndex); + this.colorIndex = w(this.colorIndex, f); + a.chart.pointCount++; + return this; + }, + applyOptions: function(a, h) { + var e = this.series, + d = e.options.pointValKey || e.pointValKey; + a = E.prototype.optionsToObject.call(this, a); + H(this, a); + this.options = this.options ? H(this.options, a) : a; + a.group && delete this.group; + d && (this.y = this[d]); + this.isNull = w( + this.isValid && !this.isValid(), + null === this.x || !n(this.y, !0), + ); + this.selected && (this.state = 'select'); + 'name' in this && + void 0 === h && + e.xAxis && + e.xAxis.hasNames && + (this.x = e.xAxis.nameToX(this)); + void 0 === this.x && + e && + (this.x = void 0 === h ? e.autoIncrement(this) : h); + return this; + }, + optionsToObject: function(a) { + var e = {}, + f = this.series, + d = f.options.keys, + c = d || f.pointArrayMap || ['y'], + b = c.length, + k = 0, + l = 0; + if (n(a) || null === a) e[c[0]] = a; + else if (r(a)) + for ( + !d && + a.length > b && + ((f = typeof a[0]), + 'string' === f ? (e.name = a[0]) : 'number' === f && (e.x = a[0]), + k++); + l < b; + + ) + (d && void 0 === a[k]) || (e[c[l]] = a[k]), k++, l++; + else + 'object' === typeof a && + ((e = a), + a.dataLabels && (f._hasPointLabels = !0), + a.marker && (f._hasPointMarkers = !0)); + return e; + }, + getClassName: function() { + return ( + 'highcharts-point' + + (this.selected ? ' highcharts-point-select' : '') + + (this.negative ? ' highcharts-negative' : '') + + (this.isNull ? ' highcharts-null-point' : '') + + (void 0 !== this.colorIndex + ? ' highcharts-color-' + this.colorIndex + : '') + + (this.options.className ? ' ' + this.options.className : '') + + (this.zone && this.zone.className + ? ' ' + this.zone.className.replace('highcharts-negative', '') + : '') + ); + }, + getZone: function() { + var a = this.series, + h = a.zones, + a = a.zoneAxis || 'y', + f = 0, + d; + for (d = h[f]; this[a] >= d.value; ) d = h[++f]; + d && d.color && !this.options.color && (this.color = d.color); + return d; + }, + destroy: function() { + var a = this.series.chart, + h = a.hoverPoints, + f; + a.pointCount--; + h && (this.setState(), p(h, this), h.length || (a.hoverPoints = null)); + if (this === a.hoverPoint) this.onMouseOut(); + if (this.graphic || this.dataLabel) u(this), this.destroyElements(); + this.legendItem && a.legend.destroyItem(this); + for (f in this) this[f] = null; + }, + destroyElements: function() { + for ( + var a = [ + 'graphic', + 'dataLabel', + 'dataLabelUpper', + 'connector', + 'shadowGroup', + ], + h, + f = 6; + f--; + + ) + (h = a[f]), this[h] && (this[h] = this[h].destroy()); + }, + getLabelConfig: function() { + return { + x: this.category, + y: this.y, + color: this.color, + colorIndex: this.colorIndex, + key: this.name || this.category, + series: this.series, + point: this, + percentage: this.percentage, + total: this.total || this.stackTotal, + }; + }, + tooltipFormatter: function(a) { + var e = this.series, + f = e.tooltipOptions, + d = w(f.valueDecimals, ''), + c = f.valuePrefix || '', + b = f.valueSuffix || ''; + D(e.pointArrayMap || ['y'], function(e) { + e = '{point.' + e; + if (c || b) a = a.replace(e + '}', c + e + '}' + b); + a = a.replace(e + '}', e + ':,.' + d + 'f}'); + }); + return l(a, { point: this, series: this.series }); + }, + firePointEvent: function(a, h, m) { + var d = this, + c = this.series.options; + (c.point.events[a] || + (d.options && d.options.events && d.options.events[a])) && + this.importEvents(); + 'click' === a && + c.allowPointSelect && + (m = function(a) { + d.select && d.select(null, a.ctrlKey || a.metaKey || a.shiftKey); + }); + f(this, a, h, m); + }, + visible: !0, + }; + })(M); + (function(a) { + var E = a.addEvent, + D = a.animObject, + H = a.arrayMax, + p = a.arrayMin, + f = a.correctFloat, + l = a.Date, + r = a.defaultOptions, + n = a.defaultPlotOptions, + w = a.defined, + u = a.each, + e = a.erase, + h = a.extend, + m = a.fireEvent, + d = a.grep, + c = a.isArray, + b = a.isNumber, + k = a.isString, + z = a.merge, + B = a.objectEach, + I = a.pick, + x = a.removeEvent, + K = a.splat, + t = a.SVGElement, + C = a.syncTimeout, + N = a.win; + a.Series = a.seriesType( + 'line', + null, + { + lineWidth: 2, + allowPointSelect: !1, + showCheckbox: !1, + animation: { duration: 1e3 }, + events: {}, + marker: { + lineWidth: 0, + lineColor: '#ffffff', + radius: 4, + states: { + hover: { + animation: { duration: 50 }, + enabled: !0, + radiusPlus: 2, + lineWidthPlus: 1, + }, + select: { + fillColor: '#cccccc', + lineColor: '#000000', + lineWidth: 2, + }, + }, + }, + point: { events: {} }, + dataLabels: { + align: 'center', + formatter: function() { + return null === this.y ? '' : a.numberFormat(this.y, -1); + }, + style: { + fontSize: '11px', + fontWeight: 'bold', + color: 'contrast', + textOutline: '1px contrast', + }, + verticalAlign: 'bottom', + x: 0, + y: 0, + padding: 5, + }, + cropThreshold: 300, + pointRange: 0, + softThreshold: !0, + states: { + hover: { + animation: { duration: 50 }, + lineWidthPlus: 1, + marker: {}, + halo: { size: 10, opacity: 0.25 }, + }, + select: { marker: {} }, + }, + stickyTracking: !0, + turboThreshold: 1e3, + findNearestPointBy: 'x', + }, + { + isCartesian: !0, + pointClass: a.Point, + sorted: !0, + requireSorting: !0, + directTouch: !1, + axisTypes: ['xAxis', 'yAxis'], + colorCounter: 0, + parallelArrays: ['x', 'y'], + coll: 'series', + init: function(a, b) { + var c = this, + d, + g = a.series, + e; + c.chart = a; + c.options = b = c.setOptions(b); + c.linkedSeries = []; + c.bindAxes(); + h(c, { + name: b.name, + state: '', + visible: !1 !== b.visible, + selected: !0 === b.selected, + }); + d = b.events; + B(d, function(a, b) { + E(c, b, a); + }); + if ( + (d && d.click) || + (b.point && b.point.events && b.point.events.click) || + b.allowPointSelect + ) + a.runTrackerClick = !0; + c.getColor(); + c.getSymbol(); + u(c.parallelArrays, function(a) { + c[a + 'Data'] = []; + }); + c.setData(b.data, !1); + c.isCartesian && (a.hasCartesianSeries = !0); + g.length && (e = g[g.length - 1]); + c._i = I(e && e._i, -1) + 1; + a.orderSeries(this.insert(g)); + }, + insert: function(a) { + var c = this.options.index, + d; + if (b(c)) { + for (d = a.length; d--; ) + if (c >= I(a[d].options.index, a[d]._i)) { + a.splice(d + 1, 0, this); + break; + } + -1 === d && a.unshift(this); + d += 1; + } else a.push(this); + return I(d, a.length - 1); + }, + bindAxes: function() { + var b = this, + c = b.options, + d = b.chart, + e; + u(b.axisTypes || [], function(g) { + u(d[g], function(a) { + e = a.options; + if ( + c[g] === e.index || + (void 0 !== c[g] && c[g] === e.id) || + (void 0 === c[g] && 0 === e.index) + ) + b.insert(a.series), (b[g] = a), (a.isDirty = !0); + }); + b[g] || b.optionalAxis === g || a.error(18, !0); + }); + }, + updateParallelArrays: function(a, c) { + var d = a.series, + e = arguments, + g = b(c) + ? function(b) { + var g = 'y' === b && d.toYData ? d.toYData(a) : a[b]; + d[b + 'Data'][c] = g; + } + : function(a) { + Array.prototype[c].apply( + d[a + 'Data'], + Array.prototype.slice.call(e, 2), + ); + }; + u(d.parallelArrays, g); + }, + autoIncrement: function() { + var b = this.options, + c = this.xIncrement, + d, + e = b.pointIntervalUnit, + g = 0, + c = I(c, b.pointStart, 0); + this.pointInterval = d = I(this.pointInterval, b.pointInterval, 1); + e && + ((b = new l(c)), + 'day' === e + ? (b = +b[l.hcSetDate](b[l.hcGetDate]() + d)) + : 'month' === e + ? (b = +b[l.hcSetMonth](b[l.hcGetMonth]() + d)) + : 'year' === e && + (b = +b[l.hcSetFullYear](b[l.hcGetFullYear]() + d)), + l.hcHasTimeZone && (g = a.getTZOffset(b) - a.getTZOffset(c)), + (d = b - c + g)); + this.xIncrement = c + d; + return c; + }, + setOptions: function(a) { + var b = this.chart, + c = b.options, + d = c.plotOptions, + g = (b.userOptions || {}).plotOptions || {}, + e = d[this.type]; + this.userOptions = a; + b = z(e, d.series, a); + this.tooltipOptions = z( + r.tooltip, + r.plotOptions.series && r.plotOptions.series.tooltip, + r.plotOptions[this.type].tooltip, + c.tooltip.userOptions, + d.series && d.series.tooltip, + d[this.type].tooltip, + a.tooltip, + ); + this.stickyTracking = I( + a.stickyTracking, + g[this.type] && g[this.type].stickyTracking, + g.series && g.series.stickyTracking, + this.tooltipOptions.shared && !this.noSharedTooltip + ? !0 + : b.stickyTracking, + ); + null === e.marker && delete b.marker; + this.zoneAxis = b.zoneAxis; + a = this.zones = (b.zones || []).slice(); + (!b.negativeColor && !b.negativeFillColor) || + b.zones || + a.push({ + value: b[this.zoneAxis + 'Threshold'] || b.threshold || 0, + className: 'highcharts-negative', + color: b.negativeColor, + fillColor: b.negativeFillColor, + }); + a.length && + w(a[a.length - 1].value) && + a.push({ color: this.color, fillColor: this.fillColor }); + return b; + }, + getCyclic: function(a, b, c) { + var d, + g = this.chart, + e = this.userOptions, + k = a + 'Index', + h = a + 'Counter', + q = c ? c.length : I(g.options.chart[a + 'Count'], g[a + 'Count']); + b || + ((d = I(e[k], e['_' + k])), + w(d) || + (g.series.length || (g[h] = 0), + (e['_' + k] = d = g[h] % q), + (g[h] += 1)), + c && (b = c[d])); + void 0 !== d && (this[k] = d); + this[a] = b; + }, + getColor: function() { + this.options.colorByPoint + ? (this.options.color = null) + : this.getCyclic( + 'color', + this.options.color || n[this.type].color, + this.chart.options.colors, + ); + }, + getSymbol: function() { + this.getCyclic( + 'symbol', + this.options.marker.symbol, + this.chart.options.symbols, + ); + }, + drawLegendSymbol: a.LegendSymbolMixin.drawLineMarker, + setData: function(d, e, h, f) { + var g = this, + q = g.points, + m = (q && q.length) || 0, + l, + A = g.options, + t = g.chart, + x = null, + n = g.xAxis, + p = A.turboThreshold, + z = this.xData, + F = this.yData, + C = (l = g.pointArrayMap) && l.length; + d = d || []; + l = d.length; + e = I(e, !0); + if ( + !1 !== f && + l && + m === l && + !g.cropped && + !g.hasGroupedData && + g.visible + ) + u(d, function(a, b) { + q[b].update && a !== A.data[b] && q[b].update(a, !1, null, !1); + }); + else { + g.xIncrement = null; + g.colorCounter = 0; + u(this.parallelArrays, function(a) { + g[a + 'Data'].length = 0; + }); + if (p && l > p) { + for (h = 0; null === x && h < l; ) (x = d[h]), h++; + if (b(x)) + for (h = 0; h < l; h++) + (z[h] = this.autoIncrement()), (F[h] = d[h]); + else if (c(x)) + if (C) + for (h = 0; h < l; h++) + (x = d[h]), (z[h] = x[0]), (F[h] = x.slice(1, C + 1)); + else + for (h = 0; h < l; h++) + (x = d[h]), (z[h] = x[0]), (F[h] = x[1]); + else a.error(12); + } else + for (h = 0; h < l; h++) + void 0 !== d[h] && + ((x = { series: g }), + g.pointClass.prototype.applyOptions.apply(x, [d[h]]), + g.updateParallelArrays(x, h)); + F && k(F[0]) && a.error(14, !0); + g.data = []; + g.options.data = g.userOptions.data = d; + for (h = m; h--; ) q[h] && q[h].destroy && q[h].destroy(); + n && (n.minRange = n.userMinRange); + g.isDirty = t.isDirtyBox = !0; + g.isDirtyData = !!q; + h = !1; + } + 'point' === A.legendType && + (this.processData(), this.generatePoints()); + e && t.redraw(h); + }, + processData: function(b) { + var c = this.xData, + d = this.yData, + e = c.length, + g; + g = 0; + var k, + h, + q = this.xAxis, + f, + m = this.options; + f = m.cropThreshold; + var l = this.getExtremesFromAll || m.getExtremesFromAll, + t = this.isCartesian, + m = q && q.val2lin, + x = q && q.isLog, + n = this.requireSorting, + p, + z; + if (t && !this.isDirty && !q.isDirty && !this.yAxis.isDirty && !b) + return !1; + q && ((b = q.getExtremes()), (p = b.min), (z = b.max)); + if (t && this.sorted && !l && (!f || e > f || this.forceCrop)) + if (c[e - 1] < p || c[0] > z) (c = []), (d = []); + else if (c[0] < p || c[e - 1] > z) + (g = this.cropData(this.xData, this.yData, p, z)), + (c = g.xData), + (d = g.yData), + (g = g.start), + (k = !0); + for (f = c.length || 1; --f; ) + (e = x ? m(c[f]) - m(c[f - 1]) : c[f] - c[f - 1]), + 0 < e && (void 0 === h || e < h) + ? (h = e) + : 0 > e && n && (a.error(15), (n = !1)); + this.cropped = k; + this.cropStart = g; + this.processedXData = c; + this.processedYData = d; + this.closestPointRange = h; + }, + cropData: function(a, b, c, d) { + var g = a.length, + e = 0, + k = g, + h = I(this.cropShoulder, 1), + f; + for (f = 0; f < g; f++) + if (a[f] >= c) { + e = Math.max(0, f - h); + break; + } + for (c = f; c < g; c++) + if (a[c] > d) { + k = c + h; + break; + } + return { + xData: a.slice(e, k), + yData: b.slice(e, k), + start: e, + end: k, + }; + }, + generatePoints: function() { + var a = this.options, + b = a.data, + c = this.data, + d, + g = this.processedXData, + e = this.processedYData, + k = this.pointClass, + h = g.length, + f = this.cropStart || 0, + m, + l = this.hasGroupedData, + a = a.keys, + t, + x = [], + n; + c || l || ((c = []), (c.length = b.length), (c = this.data = c)); + a && l && (this.options.keys = !1); + for (n = 0; n < h; n++) + (m = f + n), + l + ? ((t = new k().init(this, [g[n]].concat(K(e[n])))), + (t.dataGroup = this.groupMap[n])) + : (t = c[m]) || + void 0 === b[m] || + (c[m] = t = new k().init(this, b[m], g[n])), + t && ((t.index = m), (x[n] = t)); + this.options.keys = a; + if (c && (h !== (d = c.length) || l)) + for (n = 0; n < d; n++) + n !== f || l || (n += h), + c[n] && (c[n].destroyElements(), (c[n].plotX = void 0)); + this.data = c; + this.points = x; + }, + getExtremes: function(a) { + var d = this.yAxis, + e = this.processedXData, + k, + g = [], + h = 0; + k = this.xAxis.getExtremes(); + var f = k.min, + q = k.max, + m, + l, + t, + n; + a = a || this.stackedYData || this.processedYData || []; + k = a.length; + for (n = 0; n < k; n++) + if ( + ((l = e[n]), + (t = a[n]), + (m = + (b(t, !0) || c(t)) && + (!d.positiveValuesOnly || t.length || 0 < t)), + (l = + this.getExtremesFromAll || + this.options.getExtremesFromAll || + this.cropped || + ((e[n + 1] || l) >= f && (e[n - 1] || l) <= q)), + m && l) + ) + if ((m = t.length)) + for (; m--; ) 'number' === typeof t[m] && (g[h++] = t[m]); + else g[h++] = t; + this.dataMin = p(g); + this.dataMax = H(g); + }, + translate: function() { + this.processedXData || this.processData(); + this.generatePoints(); + var a = this.options, + c = a.stacking, + d = this.xAxis, + e = d.categories, + g = this.yAxis, + k = this.points, + h = k.length, + m = !!this.modifyValue, + l = a.pointPlacement, + t = 'between' === l || b(l), + n = a.threshold, + x = a.startFromThreshold ? n : 0, + p, + z, + C, + r, + u = Number.MAX_VALUE; + 'between' === l && (l = 0.5); + b(l) && (l *= I(a.pointRange || d.pointRange)); + for (a = 0; a < h; a++) { + var B = k[a], + N = B.x, + K = B.y; + z = B.low; + var D = + c && + g.stacks[ + (this.negStacks && K < (x ? 0 : n) ? '-' : '') + this.stackKey + ], + E; + g.positiveValuesOnly && null !== K && 0 >= K && (B.isNull = !0); + B.plotX = p = f( + Math.min( + Math.max( + -1e5, + d.translate(N, 0, 0, 0, 1, l, 'flags' === this.type), + ), + 1e5, + ), + ); + c && + this.visible && + !B.isNull && + D && + D[N] && + ((r = this.getStackIndicator(r, N, this.index)), + (E = D[N]), + (K = E.points[r.key]), + (z = K[0]), + (K = K[1]), + z === x && r.key === D[N].base && (z = I(n, g.min)), + g.positiveValuesOnly && 0 >= z && (z = null), + (B.total = B.stackTotal = E.total), + (B.percentage = E.total && (B.y / E.total) * 100), + (B.stackY = K), + E.setOffset(this.pointXOffset || 0, this.barW || 0)); + B.yBottom = w(z) ? g.translate(z, 0, 1, 0, 1) : null; + m && (K = this.modifyValue(K, B)); + B.plotY = z = + 'number' === typeof K && Infinity !== K + ? Math.min(Math.max(-1e5, g.translate(K, 0, 1, 0, 1)), 1e5) + : void 0; + B.isInside = + void 0 !== z && 0 <= z && z <= g.len && 0 <= p && p <= d.len; + B.clientX = t ? f(d.translate(N, 0, 0, 0, 1, l)) : p; + B.negative = B.y < (n || 0); + B.category = e && void 0 !== e[B.x] ? e[B.x] : B.x; + B.isNull || + (void 0 !== C && (u = Math.min(u, Math.abs(p - C))), (C = p)); + B.zone = this.zones.length && B.getZone(); + } + this.closestPointRangePx = u; + }, + getValidPoints: function(a, b) { + var c = this.chart; + return d(a || this.points || [], function(a) { + return b && !c.isInsidePlot(a.plotX, a.plotY, c.inverted) + ? !1 + : !a.isNull; + }); + }, + setClip: function(a) { + var b = this.chart, + c = this.options, + d = b.renderer, + g = b.inverted, + e = this.clipBox, + k = e || b.clipBox, + h = + this.sharedClipKey || + [ + '_sharedClip', + a && a.duration, + a && a.easing, + k.height, + c.xAxis, + c.yAxis, + ].join(), + f = b[h], + q = b[h + 'm']; + f || + (a && + ((k.width = 0), + g && (k.x = b.plotSizeX), + (b[h + 'm'] = q = d.clipRect( + g ? b.plotSizeX + 99 : -99, + g ? -b.plotLeft : -b.plotTop, + 99, + g ? b.chartWidth : b.chartHeight, + ))), + (b[h] = f = d.clipRect(k)), + (f.count = { length: 0 })); + a && + !f.count[this.index] && + ((f.count[this.index] = !0), (f.count.length += 1)); + !1 !== c.clip && + (this.group.clip(a || e ? f : b.clipRect), + this.markerGroup.clip(q), + (this.sharedClipKey = h)); + a || + (f.count[this.index] && + (delete f.count[this.index], --f.count.length), + 0 === f.count.length && + h && + b[h] && + (e || (b[h] = b[h].destroy()), + b[h + 'm'] && (b[h + 'm'] = b[h + 'm'].destroy()))); + }, + animate: function(a) { + var b = this.chart, + c = D(this.options.animation), + d; + a + ? this.setClip(c) + : ((d = this.sharedClipKey), + (a = b[d]) && a.animate({ width: b.plotSizeX, x: 0 }, c), + b[d + 'm'] && + b[d + 'm'].animate({ width: b.plotSizeX + 99, x: 0 }, c), + (this.animate = null)); + }, + afterAnimate: function() { + this.setClip(); + m(this, 'afterAnimate'); + this.finishedAnimating = !0; + }, + drawPoints: function() { + var a = this.points, + b = this.chart, + c, + d, + g, + e, + k = this.options.marker, + h, + f, + l, + m = this[this.specialGroup] || this.markerGroup, + t, + n = I( + k.enabled, + this.xAxis.isRadial ? !0 : null, + this.closestPointRangePx >= 2 * k.radius, + ); + if (!1 !== k.enabled || this._hasPointMarkers) + for (c = 0; c < a.length; c++) + (d = a[c]), + (e = d.graphic), + (h = d.marker || {}), + (f = !!d.marker), + (g = (n && void 0 === h.enabled) || h.enabled), + (l = d.isInside), + g && !d.isNull + ? ((g = I(h.symbol, this.symbol)), + (d.hasImage = 0 === g.indexOf('url')), + (t = this.markerAttribs(d, d.selected && 'select')), + e + ? e[l ? 'show' : 'hide'](!0).animate(t) + : l && + (0 < t.width || d.hasImage) && + (d.graphic = e = b.renderer + .symbol(g, t.x, t.y, t.width, t.height, f ? h : k) + .add(m)), + e && e.attr(this.pointAttribs(d, d.selected && 'select')), + e && e.addClass(d.getClassName(), !0)) + : e && (d.graphic = e.destroy()); + }, + markerAttribs: function(a, b) { + var c = this.options.marker, + d = a.marker || {}, + g = I(d.radius, c.radius); + b && + ((c = c.states[b]), + (b = d.states && d.states[b]), + (g = I( + b && b.radius, + c && c.radius, + g + ((c && c.radiusPlus) || 0), + ))); + a.hasImage && (g = 0); + a = { x: Math.floor(a.plotX) - g, y: a.plotY - g }; + g && (a.width = a.height = 2 * g); + return a; + }, + pointAttribs: function(a, b) { + var c = this.options.marker, + d = a && a.options, + g = (d && d.marker) || {}, + e = this.color, + k = d && d.color, + h = a && a.color, + d = I(g.lineWidth, c.lineWidth); + a = a && a.zone && a.zone.color; + e = k || a || h || e; + a = g.fillColor || c.fillColor || e; + e = g.lineColor || c.lineColor || e; + b && + ((c = c.states[b]), + (b = (g.states && g.states[b]) || {}), + (d = I( + b.lineWidth, + c.lineWidth, + d + I(b.lineWidthPlus, c.lineWidthPlus, 0), + )), + (a = b.fillColor || c.fillColor || a), + (e = b.lineColor || c.lineColor || e)); + return { stroke: e, 'stroke-width': d, fill: a }; + }, + destroy: function() { + var a = this, + b = a.chart, + c = /AppleWebKit\/533/.test(N.navigator.userAgent), + d, + g, + k = a.data || [], + h, + f; + m(a, 'destroy'); + x(a); + u(a.axisTypes || [], function(b) { + (f = a[b]) && + f.series && + (e(f.series, a), (f.isDirty = f.forceRedraw = !0)); + }); + a.legendItem && a.chart.legend.destroyItem(a); + for (g = k.length; g--; ) (h = k[g]) && h.destroy && h.destroy(); + a.points = null; + clearTimeout(a.animationTimeout); + B(a, function(a, b) { + a instanceof t && + !a.survive && + ((d = c && 'group' === b ? 'hide' : 'destroy'), a[d]()); + }); + b.hoverSeries === a && (b.hoverSeries = null); + e(b.series, a); + b.orderSeries(); + B(a, function(b, c) { + delete a[c]; + }); + }, + getGraphPath: function(a, b, c) { + var d = this, + g = d.options, + e = g.step, + k, + h = [], + f = [], + l; + a = a || d.points; + (k = a.reversed) && a.reverse(); + (e = { right: 1, center: 2 }[e] || (e && 3)) && k && (e = 4 - e); + !g.connectNulls || b || c || (a = this.getValidPoints(a)); + u(a, function(k, m) { + var q = k.plotX, + t = k.plotY, + n = a[m - 1]; + (k.leftCliff || (n && n.rightCliff)) && !c && (l = !0); + k.isNull && !w(b) && 0 < m + ? (l = !g.connectNulls) + : k.isNull && !b + ? (l = !0) + : (0 === m || l + ? (m = ['M', k.plotX, k.plotY]) + : d.getPointSpline + ? (m = d.getPointSpline(a, k, m)) + : e + ? ((m = + 1 === e + ? ['L', n.plotX, t] + : 2 === e + ? [ + 'L', + (n.plotX + q) / 2, + n.plotY, + 'L', + (n.plotX + q) / 2, + t, + ] + : ['L', q, n.plotY]), + m.push('L', q, t)) + : (m = ['L', q, t]), + f.push(k.x), + e && f.push(k.x), + h.push.apply(h, m), + (l = !1)); + }); + h.xMap = f; + return (d.graphPath = h); + }, + drawGraph: function() { + var a = this, + b = this.options, + c = (this.gappedPath || this.getGraphPath).call(this), + d = [ + [ + 'graph', + 'highcharts-graph', + b.lineColor || this.color, + b.dashStyle, + ], + ]; + u(this.zones, function(c, e) { + d.push([ + 'zone-graph-' + e, + 'highcharts-graph highcharts-zone-graph-' + + e + + ' ' + + (c.className || ''), + c.color || a.color, + c.dashStyle || b.dashStyle, + ]); + }); + u(d, function(d, e) { + var g = d[0], + k = a[g]; + k + ? ((k.endX = a.preventGraphAnimation ? null : c.xMap), + k.animate({ d: c })) + : c.length && + ((a[g] = a.chart.renderer + .path(c) + .addClass(d[1]) + .attr({ zIndex: 1 }) + .add(a.group)), + (k = { + stroke: d[2], + 'stroke-width': b.lineWidth, + fill: (a.fillGraph && a.color) || 'none', + }), + d[3] + ? (k.dashstyle = d[3]) + : 'square' !== b.linecap && + (k['stroke-linecap'] = k['stroke-linejoin'] = 'round'), + (k = a[g].attr(k).shadow(2 > e && b.shadow))); + k && ((k.startX = c.xMap), (k.isArea = c.isArea)); + }); + }, + applyZones: function() { + var a = this, + b = this.chart, + c = b.renderer, + d = this.zones, + e, + k, + h = this.clips || [], + f, + m = this.graph, + l = this.area, + t = Math.max(b.chartWidth, b.chartHeight), + n = this[(this.zoneAxis || 'y') + 'Axis'], + x, + p, + z = b.inverted, + C, + r, + w, + B, + K = !1; + d.length && + (m || l) && + n && + void 0 !== n.min && + ((p = n.reversed), + (C = n.horiz), + m && m.hide(), + l && l.hide(), + (x = n.getExtremes()), + u(d, function(d, g) { + e = p ? (C ? b.plotWidth : 0) : C ? 0 : n.toPixels(x.min); + e = Math.min(Math.max(I(k, e), 0), t); + k = Math.min( + Math.max(Math.round(n.toPixels(I(d.value, x.max), !0)), 0), + t, + ); + K && (e = k = n.toPixels(x.max)); + r = Math.abs(e - k); + w = Math.min(e, k); + B = Math.max(e, k); + n.isXAxis + ? ((f = { x: z ? B : w, y: 0, width: r, height: t }), + C || (f.x = b.plotHeight - f.x)) + : ((f = { x: 0, y: z ? B : w, width: t, height: r }), + C && (f.y = b.plotWidth - f.y)); + z && + c.isVML && + (f = n.isXAxis + ? { x: 0, y: p ? w : B, height: f.width, width: b.chartWidth } + : { + x: f.y - b.plotLeft - b.spacingBox.x, + y: 0, + width: f.height, + height: b.chartHeight, + }); + h[g] + ? h[g].animate(f) + : ((h[g] = c.clipRect(f)), + m && a['zone-graph-' + g].clip(h[g]), + l && a['zone-area-' + g].clip(h[g])); + K = d.value > x.max; + }), + (this.clips = h)); + }, + invertGroups: function(a) { + function b() { + u(['group', 'markerGroup'], function(b) { + c[b] && + (d.renderer.isVML && + c[b].attr({ width: c.yAxis.len, height: c.xAxis.len }), + (c[b].width = c.yAxis.len), + (c[b].height = c.xAxis.len), + c[b].invert(a)); + }); + } + var c = this, + d = c.chart, + e; + c.xAxis && + ((e = E(d, 'resize', b)), + E(c, 'destroy', e), + b(a), + (c.invertGroups = b)); + }, + plotGroup: function(a, b, c, d, e) { + var g = this[a], + k = !g; + k && + (this[a] = g = this.chart.renderer + .g() + .attr({ zIndex: d || 0.1 }) + .add(e)); + g.addClass( + 'highcharts-' + + b + + ' highcharts-series-' + + this.index + + ' highcharts-' + + this.type + + '-series ' + + (w(this.colorIndex) + ? 'highcharts-color-' + this.colorIndex + ' ' + : '') + + (this.options.className || '') + + (g.hasClass('highcharts-tracker') ? ' highcharts-tracker' : ''), + !0, + ); + g.attr({ visibility: c })[k ? 'attr' : 'animate'](this.getPlotBox()); + return g; + }, + getPlotBox: function() { + var a = this.chart, + b = this.xAxis, + c = this.yAxis; + a.inverted && ((b = c), (c = this.xAxis)); + return { + translateX: b ? b.left : a.plotLeft, + translateY: c ? c.top : a.plotTop, + scaleX: 1, + scaleY: 1, + }; + }, + render: function() { + var a = this, + b = a.chart, + c, + d = a.options, + e = !!a.animate && b.renderer.isSVG && D(d.animation).duration, + k = a.visible ? 'inherit' : 'hidden', + h = d.zIndex, + f = a.hasRendered, + m = b.seriesGroup, + l = b.inverted; + c = a.plotGroup('group', 'series', k, h, m); + a.markerGroup = a.plotGroup('markerGroup', 'markers', k, h, m); + e && a.animate(!0); + c.inverted = a.isCartesian ? l : !1; + a.drawGraph && (a.drawGraph(), a.applyZones()); + a.drawDataLabels && a.drawDataLabels(); + a.visible && a.drawPoints(); + a.drawTracker && + !1 !== a.options.enableMouseTracking && + a.drawTracker(); + a.invertGroups(l); + !1 === d.clip || a.sharedClipKey || f || c.clip(b.clipRect); + e && a.animate(); + f || + (a.animationTimeout = C(function() { + a.afterAnimate(); + }, e)); + a.isDirty = !1; + a.hasRendered = !0; + }, + redraw: function() { + var a = this.chart, + b = this.isDirty || this.isDirtyData, + c = this.group, + d = this.xAxis, + e = this.yAxis; + c && + (a.inverted && c.attr({ width: a.plotWidth, height: a.plotHeight }), + c.animate({ + translateX: I(d && d.left, a.plotLeft), + translateY: I(e && e.top, a.plotTop), + })); + this.translate(); + this.render(); + b && delete this.kdTree; + }, + kdAxisArray: ['clientX', 'plotY'], + searchPoint: function(a, b) { + var c = this.xAxis, + d = this.yAxis, + e = this.chart.inverted; + return this.searchKDTree( + { + clientX: e ? c.len - a.chartY + c.pos : a.chartX - c.pos, + plotY: e ? d.len - a.chartX + d.pos : a.chartY - d.pos, + }, + b, + ); + }, + buildKDTree: function() { + function a(c, d, e) { + var g, k; + if ((k = c && c.length)) + return ( + (g = b.kdAxisArray[d % e]), + c.sort(function(a, b) { + return a[g] - b[g]; + }), + (k = Math.floor(k / 2)), + { + point: c[k], + left: a(c.slice(0, k), d + 1, e), + right: a(c.slice(k + 1), d + 1, e), + } + ); + } + this.buildingKdTree = !0; + var b = this, + c = -1 < b.options.findNearestPointBy.indexOf('y') ? 2 : 1; + delete b.kdTree; + C( + function() { + b.kdTree = a(b.getValidPoints(null, !b.directTouch), c, c); + b.buildingKdTree = !1; + }, + b.options.kdNow ? 0 : 1, + ); + }, + searchKDTree: function(a, b) { + function c(a, b, g, f) { + var m = b.point, + l = d.kdAxisArray[g % f], + q, + t, + n = m; + t = w(a[e]) && w(m[e]) ? Math.pow(a[e] - m[e], 2) : null; + q = w(a[k]) && w(m[k]) ? Math.pow(a[k] - m[k], 2) : null; + q = (t || 0) + (q || 0); + m.dist = w(q) ? Math.sqrt(q) : Number.MAX_VALUE; + m.distX = w(t) ? Math.sqrt(t) : Number.MAX_VALUE; + l = a[l] - m[l]; + q = 0 > l ? 'left' : 'right'; + t = 0 > l ? 'right' : 'left'; + b[q] && ((q = c(a, b[q], g + 1, f)), (n = q[h] < n[h] ? q : m)); + b[t] && + Math.sqrt(l * l) < n[h] && + ((a = c(a, b[t], g + 1, f)), (n = a[h] < n[h] ? a : n)); + return n; + } + var d = this, + e = this.kdAxisArray[0], + k = this.kdAxisArray[1], + h = b ? 'distX' : 'dist'; + b = -1 < d.options.findNearestPointBy.indexOf('y') ? 2 : 1; + this.kdTree || this.buildingKdTree || this.buildKDTree(); + if (this.kdTree) return c(a, this.kdTree, b, b); + }, + }, + ); + })(M); + (function(a) { + var E = a.Axis, + D = a.Chart, + H = a.correctFloat, + p = a.defined, + f = a.destroyObjectProperties, + l = a.each, + r = a.format, + n = a.objectEach, + w = a.pick, + u = a.Series; + a.StackItem = function(a, h, f, d, c) { + var b = a.chart.inverted; + this.axis = a; + this.isNegative = f; + this.options = h; + this.x = d; + this.total = null; + this.points = {}; + this.stack = c; + this.rightCliff = this.leftCliff = 0; + this.alignOptions = { + align: h.align || (b ? (f ? 'left' : 'right') : 'center'), + verticalAlign: h.verticalAlign || (b ? 'middle' : f ? 'bottom' : 'top'), + y: w(h.y, b ? 4 : f ? 14 : -6), + x: w(h.x, b ? (f ? -6 : 6) : 0), + }; + this.textAlign = h.textAlign || (b ? (f ? 'right' : 'left') : 'center'); + }; + a.StackItem.prototype = { + destroy: function() { + f(this, this.axis); + }, + render: function(a) { + var e = this.options, + f = e.format, + f = f ? r(f, this) : e.formatter.call(this); + this.label + ? this.label.attr({ text: f, visibility: 'hidden' }) + : (this.label = this.axis.chart.renderer + .text(f, null, null, e.useHTML) + .css(e.style) + .attr({ + align: this.textAlign, + rotation: e.rotation, + visibility: 'hidden', + }) + .add(a)); + }, + setOffset: function(a, h) { + var e = this.axis, + d = e.chart, + c = e.translate(e.usePercentage ? 100 : this.total, 0, 0, 0, 1), + e = e.translate(0), + e = Math.abs(c - e); + a = d.xAxis[0].translate(this.x) + a; + c = this.getStackBox(d, this, a, c, h, e); + if ((h = this.label)) + h.align(this.alignOptions, null, c), + (c = h.alignAttr), + h[ + !1 === this.options.crop || d.isInsidePlot(c.x, c.y) + ? 'show' + : 'hide' + ](!0); + }, + getStackBox: function(a, h, f, d, c, b) { + var e = h.axis.reversed, + l = a.inverted; + a = a.plotHeight; + h = (h.isNegative && !e) || (!h.isNegative && e); + return { + x: l ? (h ? d : d - b) : f, + y: l ? a - f - c : h ? a - d - b : a - d, + width: l ? b : c, + height: l ? c : b, + }; + }, + }; + D.prototype.getStacks = function() { + var a = this; + l(a.yAxis, function(a) { + a.stacks && a.hasVisibleSeries && (a.oldStacks = a.stacks); + }); + l(a.series, function(e) { + !e.options.stacking || + (!0 !== e.visible && !1 !== a.options.chart.ignoreHiddenSeries) || + (e.stackKey = e.type + w(e.options.stack, '')); + }); + }; + E.prototype.buildStacks = function() { + var a = this.series, + h = w(this.options.reversedStacks, !0), + f = a.length, + d; + if (!this.isXAxis) { + this.usePercentage = !1; + for (d = f; d--; ) a[h ? d : f - d - 1].setStackedPoints(); + for (d = 0; d < f; d++) a[d].modifyStacks(); + } + }; + E.prototype.renderStackTotals = function() { + var a = this.chart, + h = a.renderer, + f = this.stacks, + d = this.stackTotalGroup; + d || + (this.stackTotalGroup = d = h + .g('stack-labels') + .attr({ visibility: 'visible', zIndex: 6 }) + .add()); + d.translate(a.plotLeft, a.plotTop); + n(f, function(a) { + n(a, function(a) { + a.render(d); + }); + }); + }; + E.prototype.resetStacks = function() { + var a = this, + h = a.stacks; + a.isXAxis || + n(h, function(e) { + n(e, function(d, c) { + d.touched < a.stacksTouched + ? (d.destroy(), delete e[c]) + : ((d.total = null), (d.cumulative = null)); + }); + }); + }; + E.prototype.cleanStacks = function() { + var a; + this.isXAxis || + (this.oldStacks && (a = this.stacks = this.oldStacks), + n(a, function(a) { + n(a, function(a) { + a.cumulative = a.total; + }); + })); + }; + u.prototype.setStackedPoints = function() { + if ( + this.options.stacking && + (!0 === this.visible || + !1 === this.chart.options.chart.ignoreHiddenSeries) + ) { + var e = this.processedXData, + h = this.processedYData, + f = [], + d = h.length, + c = this.options, + b = c.threshold, + k = w(c.startFromThreshold && b, 0), + l = c.stack, + c = c.stacking, + n = this.stackKey, + r = '-' + n, + x = this.negStacks, + u = this.yAxis, + t = u.stacks, + C = u.oldStacks, + N, + q, + A, + F, + G, + g, + v; + u.stacksTouched += 1; + for (G = 0; G < d; G++) + (g = e[G]), + (v = h[G]), + (N = this.getStackIndicator(N, g, this.index)), + (F = N.key), + (A = (q = x && v < (k ? 0 : b)) ? r : n), + t[A] || (t[A] = {}), + t[A][g] || + (C[A] && C[A][g] + ? ((t[A][g] = C[A][g]), (t[A][g].total = null)) + : (t[A][g] = new a.StackItem( + u, + u.options.stackLabels, + q, + g, + l, + ))), + (A = t[A][g]), + null !== v + ? ((A.points[F] = A.points[this.index] = [w(A.cumulative, k)]), + p(A.cumulative) || (A.base = F), + (A.touched = u.stacksTouched), + 0 < N.index && + !1 === this.singleStacks && + (A.points[F][0] = A.points[this.index + ',' + g + ',0'][0])) + : (A.points[F] = A.points[this.index] = null), + 'percent' === c + ? ((q = q ? n : r), + x && t[q] && t[q][g] + ? ((q = t[q][g]), + (A.total = q.total = + Math.max(q.total, A.total) + Math.abs(v) || 0)) + : (A.total = H(A.total + (Math.abs(v) || 0)))) + : (A.total = H(A.total + (v || 0))), + (A.cumulative = w(A.cumulative, k) + (v || 0)), + null !== v && + (A.points[F].push(A.cumulative), (f[G] = A.cumulative)); + 'percent' === c && (u.usePercentage = !0); + this.stackedYData = f; + u.oldStacks = {}; + } + }; + u.prototype.modifyStacks = function() { + var a = this, + h = a.stackKey, + f = a.yAxis.stacks, + d = a.processedXData, + c, + b = a.options.stacking; + a[b + 'Stacker'] && + l([h, '-' + h], function(e) { + for (var k = d.length, h, l; k--; ) + if ( + ((h = d[k]), + (c = a.getStackIndicator(c, h, a.index, e)), + (l = (h = f[e] && f[e][h]) && h.points[c.key])) + ) + a[b + 'Stacker'](l, h, k); + }); + }; + u.prototype.percentStacker = function(a, h, f) { + h = h.total ? 100 / h.total : 0; + a[0] = H(a[0] * h); + a[1] = H(a[1] * h); + this.stackedYData[f] = a[1]; + }; + u.prototype.getStackIndicator = function(a, h, f, d) { + !p(a) || a.x !== h || (d && a.key !== d) + ? (a = { x: h, index: 0, key: d }) + : a.index++; + a.key = [f, h, a.index].join(); + return a; + }; + })(M); + (function(a) { + var E = a.addEvent, + D = a.animate, + H = a.Axis, + p = a.createElement, + f = a.css, + l = a.defined, + r = a.each, + n = a.erase, + w = a.extend, + u = a.fireEvent, + e = a.inArray, + h = a.isNumber, + m = a.isObject, + d = a.isArray, + c = a.merge, + b = a.objectEach, + k = a.pick, + z = a.Point, + B = a.Series, + I = a.seriesTypes, + x = a.setAnimation, + K = a.splat; + w(a.Chart.prototype, { + addSeries: function(a, b, c) { + var d, + e = this; + a && + ((b = k(b, !0)), + u(e, 'addSeries', { options: a }, function() { + d = e.initSeries(a); + e.isDirtyLegend = !0; + e.linkSeries(); + b && e.redraw(c); + })); + return d; + }, + addAxis: function(a, b, d, e) { + var h = b ? 'xAxis' : 'yAxis', + f = this.options; + a = c(a, { index: this[h].length, isX: b }); + b = new H(this, a); + f[h] = K(f[h] || {}); + f[h].push(a); + k(d, !0) && this.redraw(e); + return b; + }, + showLoading: function(a) { + var b = this, + c = b.options, + d = b.loadingDiv, + e = c.loading, + k = function() { + d && + f(d, { + left: b.plotLeft + 'px', + top: b.plotTop + 'px', + width: b.plotWidth + 'px', + height: b.plotHeight + 'px', + }); + }; + d || + ((b.loadingDiv = d = p( + 'div', + { className: 'highcharts-loading highcharts-loading-hidden' }, + null, + b.container, + )), + (b.loadingSpan = p( + 'span', + { className: 'highcharts-loading-inner' }, + null, + d, + )), + E(b, 'redraw', k)); + d.className = 'highcharts-loading'; + b.loadingSpan.innerHTML = a || c.lang.loading; + f(d, w(e.style, { zIndex: 10 })); + f(b.loadingSpan, e.labelStyle); + b.loadingShown || + (f(d, { opacity: 0, display: '' }), + D( + d, + { opacity: e.style.opacity || 0.5 }, + { duration: e.showDuration || 0 }, + )); + b.loadingShown = !0; + k(); + }, + hideLoading: function() { + var a = this.options, + b = this.loadingDiv; + b && + ((b.className = 'highcharts-loading highcharts-loading-hidden'), + D( + b, + { opacity: 0 }, + { + duration: a.loading.hideDuration || 100, + complete: function() { + f(b, { display: 'none' }); + }, + }, + )); + this.loadingShown = !1; + }, + propsRequireDirtyBox: 'backgroundColor borderColor borderWidth margin marginTop marginRight marginBottom marginLeft spacing spacingTop spacingRight spacingBottom spacingLeft borderRadius plotBackgroundColor plotBackgroundImage plotBorderColor plotBorderWidth plotShadow shadow'.split( + ' ', + ), + propsRequireUpdateSeries: 'chart.inverted chart.polar chart.ignoreHiddenSeries chart.type colors plotOptions tooltip'.split( + ' ', + ), + update: function(a, d, f) { + var m = this, + n = { + credits: 'addCredits', + title: 'setTitle', + subtitle: 'setSubtitle', + }, + t = a.chart, + x, + g, + p = []; + if (t) { + c(!0, m.options.chart, t); + 'className' in t && m.setClassName(t.className); + if ('inverted' in t || 'polar' in t) m.propFromSeries(), (x = !0); + 'alignTicks' in t && (x = !0); + b(t, function(a, b) { + -1 !== e('chart.' + b, m.propsRequireUpdateSeries) && (g = !0); + -1 !== e(b, m.propsRequireDirtyBox) && (m.isDirtyBox = !0); + }); + 'style' in t && m.renderer.setStyle(t.style); + } + a.colors && (this.options.colors = a.colors); + a.plotOptions && c(!0, this.options.plotOptions, a.plotOptions); + b(a, function(a, b) { + if (m[b] && 'function' === typeof m[b].update) m[b].update(a, !1); + else if ('function' === typeof m[n[b]]) m[n[b]](a); + 'chart' !== b && -1 !== e(b, m.propsRequireUpdateSeries) && (g = !0); + }); + r('xAxis yAxis zAxis series colorAxis pane'.split(' '), function(b) { + a[b] && + (r(K(a[b]), function(a, c) { + (c = (l(a.id) && m.get(a.id)) || m[b][c]) && + c.coll === b && + (c.update(a, !1), f && (c.touched = !0)); + if (!c && f) + if ('series' === b) m.addSeries(a, !1).touched = !0; + else if ('xAxis' === b || 'yAxis' === b) + m.addAxis(a, 'xAxis' === b, !1).touched = !0; + }), + f && + r(m[b], function(a) { + a.touched ? delete a.touched : p.push(a); + })); + }); + r(p, function(a) { + a.remove(!1); + }); + x && + r(m.axes, function(a) { + a.update({}, !1); + }); + g && + r(m.series, function(a) { + a.update({}, !1); + }); + a.loading && c(!0, m.options.loading, a.loading); + x = t && t.width; + t = t && t.height; + (h(x) && x !== m.chartWidth) || (h(t) && t !== m.chartHeight) + ? m.setSize(x, t) + : k(d, !0) && m.redraw(); + }, + setSubtitle: function(a) { + this.setTitle(void 0, a); + }, + }); + w(z.prototype, { + update: function(a, b, c, d) { + function e() { + h.applyOptions(a); + null === h.y && g && (h.graphic = g.destroy()); + m(a, !0) && + (g && + g.element && + a && + a.marker && + void 0 !== a.marker.symbol && + (h.graphic = g.destroy()), + a && + a.dataLabels && + h.dataLabel && + (h.dataLabel = h.dataLabel.destroy()), + h.connector && (h.connector = h.connector.destroy())); + l = h.index; + f.updateParallelArrays(h, l); + t.data[l] = m(t.data[l], !0) || m(a, !0) ? h.options : a; + f.isDirty = f.isDirtyData = !0; + !f.fixedBox && f.hasCartesianSeries && (n.isDirtyBox = !0); + 'point' === t.legendType && (n.isDirtyLegend = !0); + b && n.redraw(c); + } + var h = this, + f = h.series, + g = h.graphic, + l, + n = f.chart, + t = f.options; + b = k(b, !0); + !1 === d ? e() : h.firePointEvent('update', { options: a }, e); + }, + remove: function(a, b) { + this.series.removePoint(e(this, this.series.data), a, b); + }, + }); + w(B.prototype, { + addPoint: function(a, b, c, d) { + var e = this.options, + h = this.data, + f = this.chart, + g = this.xAxis, + g = g && g.hasNames && g.names, + l = e.data, + m, + n, + t = this.xData, + q, + x; + b = k(b, !0); + m = { series: this }; + this.pointClass.prototype.applyOptions.apply(m, [a]); + x = m.x; + q = t.length; + if (this.requireSorting && x < t[q - 1]) + for (n = !0; q && t[q - 1] > x; ) q--; + this.updateParallelArrays(m, 'splice', q, 0, 0); + this.updateParallelArrays(m, q); + g && m.name && (g[x] = m.name); + l.splice(q, 0, a); + n && (this.data.splice(q, 0, null), this.processData()); + 'point' === e.legendType && this.generatePoints(); + c && + (h[0] && h[0].remove + ? h[0].remove(!1) + : (h.shift(), this.updateParallelArrays(m, 'shift'), l.shift())); + this.isDirtyData = this.isDirty = !0; + b && f.redraw(d); + }, + removePoint: function(a, b, c) { + var d = this, + e = d.data, + h = e[a], + f = d.points, + g = d.chart, + l = function() { + f && f.length === e.length && f.splice(a, 1); + e.splice(a, 1); + d.options.data.splice(a, 1); + d.updateParallelArrays(h || { series: d }, 'splice', a, 1); + h && h.destroy(); + d.isDirty = !0; + d.isDirtyData = !0; + b && g.redraw(); + }; + x(c, g); + b = k(b, !0); + h ? h.firePointEvent('remove', null, l) : l(); + }, + remove: function(a, b, c) { + function d() { + e.destroy(); + h.isDirtyLegend = h.isDirtyBox = !0; + h.linkSeries(); + k(a, !0) && h.redraw(b); + } + var e = this, + h = e.chart; + !1 !== c ? u(e, 'remove', null, d) : d(); + }, + update: function(a, b) { + var d = this, + e = d.chart, + h = d.userOptions, + f = d.oldType || d.type, + l = a.type || h.type || e.options.chart.type, + g = I[f].prototype, + m, + n = ['group', 'markerGroup', 'dataLabelsGroup'], + t = ['navigatorSeries', 'baseSeries'], + x = d.finishedAnimating && { animation: !1 }; + if (Object.keys && 'data' === Object.keys(a).toString()) + return this.setData(a.data, b); + t = n.concat(t); + r(t, function(a) { + t[a] = d[a]; + delete d[a]; + }); + a = c( + h, + x, + { index: d.index, pointStart: d.xData[0] }, + { data: d.options.data }, + a, + ); + d.remove(!1, null, !1); + for (m in g) d[m] = void 0; + w(d, I[l || f].prototype); + r(t, function(a) { + d[a] = t[a]; + }); + d.init(e, a); + a.zIndex !== h.zIndex && + r(n, function(b) { + d[b] && d[b].attr({ zIndex: a.zIndex }); + }); + d.oldType = f; + e.linkSeries(); + k(b, !0) && e.redraw(!1); + }, + }); + w(H.prototype, { + update: function(a, b) { + var d = this.chart; + a = d.options[this.coll][this.options.index] = c(this.userOptions, a); + this.destroy(!0); + this.init(d, w(a, { events: void 0 })); + d.isDirtyBox = !0; + k(b, !0) && d.redraw(); + }, + remove: function(a) { + for ( + var b = this.chart, c = this.coll, e = this.series, h = e.length; + h--; + + ) + e[h] && e[h].remove(!1); + n(b.axes, this); + n(b[c], this); + d(b.options[c]) + ? b.options[c].splice(this.options.index, 1) + : delete b.options[c]; + r(b[c], function(a, b) { + a.options.index = b; + }); + this.destroy(); + b.isDirtyBox = !0; + k(a, !0) && b.redraw(); + }, + setTitle: function(a, b) { + this.update({ title: a }, b); + }, + setCategories: function(a, b) { + this.update({ categories: a }, b); + }, + }); + })(M); + (function(a) { + var E = a.color, + D = a.each, + H = a.map, + p = a.pick, + f = a.Series, + l = a.seriesType; + l( + 'area', + 'line', + { softThreshold: !1, threshold: 0 }, + { + singleStacks: !1, + getStackPoints: function(f) { + var l = [], + r = [], + u = this.xAxis, + e = this.yAxis, + h = e.stacks[this.stackKey], + m = {}, + d = this.index, + c = e.series, + b = c.length, + k, + z = p(e.options.reversedStacks, !0) ? 1 : -1, + B; + f = f || this.points; + if (this.options.stacking) { + for (B = 0; B < f.length; B++) + (f[B].leftNull = f[B].rightNull = null), (m[f[B].x] = f[B]); + a.objectEach(h, function(a, b) { + null !== a.total && r.push(b); + }); + r.sort(function(a, b) { + return a - b; + }); + k = H(c, function() { + return this.visible; + }); + D(r, function(a, c) { + var f = 0, + n, + x; + if (m[a] && !m[a].isNull) + l.push(m[a]), + D([-1, 1], function(e) { + var f = 1 === e ? 'rightNull' : 'leftNull', + l = 0, + t = h[r[c + e]]; + if (t) + for (B = d; 0 <= B && B < b; ) + (n = t.points[B]), + n || + (B === d + ? (m[a][f] = !0) + : k[B] && + (x = h[a].points[B]) && + (l -= x[1] - x[0])), + (B += z); + m[a][1 === e ? 'rightCliff' : 'leftCliff'] = l; + }); + else { + for (B = d; 0 <= B && B < b; ) { + if ((n = h[a].points[B])) { + f = n[1]; + break; + } + B += z; + } + f = e.translate(f, 0, 1, 0, 1); + l.push({ + isNull: !0, + plotX: u.translate(a, 0, 0, 0, 1), + x: a, + plotY: f, + yBottom: f, + }); + } + }); + } + return l; + }, + getGraphPath: function(a) { + var l = f.prototype.getGraphPath, + r = this.options, + u = r.stacking, + e = this.yAxis, + h, + m, + d = [], + c = [], + b = this.index, + k, + z = e.stacks[this.stackKey], + B = r.threshold, + I = e.getThreshold(r.threshold), + x, + r = r.connectNulls || 'percent' === u, + K = function(h, f, l) { + var m = a[h]; + h = u && z[m.x].points[b]; + var n = m[l + 'Null'] || 0; + l = m[l + 'Cliff'] || 0; + var x, + t, + m = !0; + l || n + ? ((x = (n ? h[0] : h[1]) + l), (t = h[0] + l), (m = !!n)) + : !u && a[f] && a[f].isNull && (x = t = B); + void 0 !== x && + (c.push({ + plotX: k, + plotY: null === x ? I : e.getThreshold(x), + isNull: m, + isCliff: !0, + }), + d.push({ + plotX: k, + plotY: null === t ? I : e.getThreshold(t), + doCurve: !1, + })); + }; + a = a || this.points; + u && (a = this.getStackPoints(a)); + for (h = 0; h < a.length; h++) + if ( + ((m = a[h].isNull), + (k = p(a[h].rectPlotX, a[h].plotX)), + (x = p(a[h].yBottom, I)), + !m || r) + ) + r || K(h, h - 1, 'left'), + (m && !u && r) || + (c.push(a[h]), d.push({ x: h, plotX: k, plotY: x })), + r || K(h, h + 1, 'right'); + h = l.call(this, c, !0, !0); + d.reversed = !0; + m = l.call(this, d, !0, !0); + m.length && (m[0] = 'L'); + m = h.concat(m); + l = l.call(this, c, !1, r); + m.xMap = h.xMap; + this.areaPath = m; + return l; + }, + drawGraph: function() { + this.areaPath = []; + f.prototype.drawGraph.apply(this); + var a = this, + l = this.areaPath, + w = this.options, + u = [['area', 'highcharts-area', this.color, w.fillColor]]; + D(this.zones, function(e, h) { + u.push([ + 'zone-area-' + h, + 'highcharts-area highcharts-zone-area-' + h + ' ' + e.className, + e.color || a.color, + e.fillColor || w.fillColor, + ]); + }); + D(u, function(e) { + var h = e[0], + f = a[h]; + f + ? ((f.endX = a.preventGraphAnimation ? null : l.xMap), + f.animate({ d: l })) + : ((f = a[h] = a.chart.renderer + .path(l) + .addClass(e[1]) + .attr({ + fill: p( + e[3], + E(e[2]) + .setOpacity(p(w.fillOpacity, 0.75)) + .get(), + ), + zIndex: 0, + }) + .add(a.group)), + (f.isArea = !0)); + f.startX = l.xMap; + f.shiftUnit = w.step ? 2 : 1; + }); + }, + drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, + }, + ); + })(M); + (function(a) { + var E = a.pick; + a = a.seriesType; + a( + 'spline', + 'line', + {}, + { + getPointSpline: function(a, H, p) { + var f = H.plotX, + l = H.plotY, + r = a[p - 1]; + p = a[p + 1]; + var n, w, u, e; + if ( + r && + !r.isNull && + !1 !== r.doCurve && + !H.isCliff && + p && + !p.isNull && + !1 !== p.doCurve && + !H.isCliff + ) { + a = r.plotY; + u = p.plotX; + p = p.plotY; + var h = 0; + n = (1.5 * f + r.plotX) / 2.5; + w = (1.5 * l + a) / 2.5; + u = (1.5 * f + u) / 2.5; + e = (1.5 * l + p) / 2.5; + u !== n && (h = ((e - w) * (u - f)) / (u - n) + l - e); + w += h; + e += h; + w > a && w > l + ? ((w = Math.max(a, l)), (e = 2 * l - w)) + : w < a && w < l && ((w = Math.min(a, l)), (e = 2 * l - w)); + e > p && e > l + ? ((e = Math.max(p, l)), (w = 2 * l - e)) + : e < p && e < l && ((e = Math.min(p, l)), (w = 2 * l - e)); + H.rightContX = u; + H.rightContY = e; + } + H = [ + 'C', + E(r.rightContX, r.plotX), + E(r.rightContY, r.plotY), + E(n, f), + E(w, l), + f, + l, + ]; + r.rightContX = r.rightContY = null; + return H; + }, + }, + ); + })(M); + (function(a) { + var E = a.seriesTypes.area.prototype, + D = a.seriesType; + D('areaspline', 'spline', a.defaultPlotOptions.area, { + getStackPoints: E.getStackPoints, + getGraphPath: E.getGraphPath, + drawGraph: E.drawGraph, + drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, + }); + })(M); + (function(a) { + var E = a.animObject, + D = a.color, + H = a.each, + p = a.extend, + f = a.isNumber, + l = a.merge, + r = a.pick, + n = a.Series, + w = a.seriesType, + u = a.svg; + w( + 'column', + 'line', + { + borderRadius: 0, + crisp: !0, + groupPadding: 0.2, + marker: null, + pointPadding: 0.1, + minPointLength: 0, + cropThreshold: 50, + pointRange: null, + states: { + hover: { halo: !1, brightness: 0.1 }, + select: { color: '#cccccc', borderColor: '#000000' }, + }, + dataLabels: { align: null, verticalAlign: null, y: null }, + softThreshold: !1, + startFromThreshold: !0, + stickyTracking: !1, + tooltip: { distance: 6 }, + threshold: 0, + borderColor: '#ffffff', + }, + { + cropShoulder: 0, + directTouch: !0, + trackerGroups: ['group', 'dataLabelsGroup'], + negStacks: !0, + init: function() { + n.prototype.init.apply(this, arguments); + var a = this, + h = a.chart; + h.hasRendered && + H(h.series, function(e) { + e.type === a.type && (e.isDirty = !0); + }); + }, + getColumnMetrics: function() { + var a = this, + h = a.options, + f = a.xAxis, + d = a.yAxis, + c = f.reversed, + b, + k = {}, + l = 0; + !1 === h.grouping + ? (l = 1) + : H(a.chart.series, function(c) { + var e = c.options, + h = c.yAxis, + f; + c.type !== a.type || + (!c.visible && a.chart.options.chart.ignoreHiddenSeries) || + d.len !== h.len || + d.pos !== h.pos || + (e.stacking + ? ((b = c.stackKey), + void 0 === k[b] && (k[b] = l++), + (f = k[b])) + : !1 !== e.grouping && (f = l++), + (c.columnIndex = f)); + }); + var n = Math.min( + Math.abs(f.transA) * + (f.ordinalSlope || + h.pointRange || + f.closestPointRange || + f.tickInterval || + 1), + f.len, + ), + p = n * h.groupPadding, + x = (n - 2 * p) / (l || 1), + h = Math.min( + h.maxPointWidth || f.len, + r(h.pointWidth, x * (1 - 2 * h.pointPadding)), + ); + a.columnMetrics = { + width: h, + offset: + (x - h) / 2 + + (p + ((a.columnIndex || 0) + (c ? 1 : 0)) * x - n / 2) * + (c ? -1 : 1), + }; + return a.columnMetrics; + }, + crispCol: function(a, h, f, d) { + var c = this.chart, + b = this.borderWidth, + e = -(b % 2 ? 0.5 : 0), + b = b % 2 ? 0.5 : 1; + c.inverted && c.renderer.isVML && (b += 1); + this.options.crisp && + ((f = Math.round(a + f) + e), (a = Math.round(a) + e), (f -= a)); + d = Math.round(h + d) + b; + e = 0.5 >= Math.abs(h) && 0.5 < d; + h = Math.round(h) + b; + d -= h; + e && d && (--h, (d += 1)); + return { x: a, y: h, width: f, height: d }; + }, + translate: function() { + var a = this, + h = a.chart, + f = a.options, + d = (a.dense = 2 > a.closestPointRange * a.xAxis.transA), + d = (a.borderWidth = r(f.borderWidth, d ? 0 : 1)), + c = a.yAxis, + b = f.threshold, + k = (a.translatedThreshold = c.getThreshold(b)), + l = r(f.minPointLength, 5), + p = a.getColumnMetrics(), + u = p.width, + x = (a.barW = Math.max(u, 1 + 2 * d)), + w = (a.pointXOffset = p.offset); + h.inverted && (k -= 0.5); + f.pointPadding && (x = Math.ceil(x)); + n.prototype.translate.apply(a); + H(a.points, function(d) { + var e = r(d.yBottom, k), + f = 999 + Math.abs(e), + f = Math.min(Math.max(-f, d.plotY), c.len + f), + m = d.plotX + w, + n = x, + t = Math.min(f, e), + p, + g = Math.max(f, e) - t; + l && + Math.abs(g) < l && + ((g = l), + (p = (!c.reversed && !d.negative) || (c.reversed && d.negative)), + d.y === b && a.dataMax <= b && c.min < b && (p = !p), + (t = Math.abs(t - k) > l ? e - l : k - (p ? l : 0))); + d.barX = m; + d.pointWidth = u; + d.tooltipPos = h.inverted + ? [c.len + c.pos - h.plotLeft - f, a.xAxis.len - m - n / 2, g] + : [m + n / 2, f + c.pos - h.plotTop, g]; + d.shapeType = 'rect'; + d.shapeArgs = a.crispCol.apply( + a, + d.isNull ? [m, k, n, 0] : [m, t, n, g], + ); + }); + }, + getSymbol: a.noop, + drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, + drawGraph: function() { + this.group[this.dense ? 'addClass' : 'removeClass']( + 'highcharts-dense-data', + ); + }, + pointAttribs: function(a, f) { + var e = this.options, + d, + c = this.pointAttrToOptions || {}; + d = c.stroke || 'borderColor'; + var b = c['stroke-width'] || 'borderWidth', + k = (a && a.color) || this.color, + h = (a && a[d]) || e[d] || this.color || k, + n = (a && a[b]) || e[b] || this[b] || 0, + c = e.dashStyle; + a && + this.zones.length && + ((k = a.getZone()), + (k = a.options.color || (k && k.color) || this.color)); + f && + ((a = l( + e.states[f], + (a.options.states && a.options.states[f]) || {}, + )), + (f = a.brightness), + (k = + a.color || + (void 0 !== f && + D(k) + .brighten(a.brightness) + .get()) || + k), + (h = a[d] || h), + (n = a[b] || n), + (c = a.dashStyle || c)); + d = { fill: k, stroke: h, 'stroke-width': n }; + c && (d.dashstyle = c); + return d; + }, + drawPoints: function() { + var a = this, + h = this.chart, + m = a.options, + d = h.renderer, + c = m.animationLimit || 250, + b; + H(a.points, function(e) { + var k = e.graphic; + if (f(e.plotY) && null !== e.y) { + b = e.shapeArgs; + if (k) k[h.pointCount < c ? 'animate' : 'attr'](l(b)); + else e.graphic = k = d[e.shapeType](b).add(e.group || a.group); + m.borderRadius && k.attr({ r: m.borderRadius }); + k.attr(a.pointAttribs(e, e.selected && 'select')).shadow( + m.shadow, + null, + m.stacking && !m.borderRadius, + ); + k.addClass(e.getClassName(), !0); + } else k && (e.graphic = k.destroy()); + }); + }, + animate: function(a) { + var e = this, + f = this.yAxis, + d = e.options, + c = this.chart.inverted, + b = {}, + k = c ? 'translateX' : 'translateY', + l; + u && + (a + ? ((b.scaleY = 0.001), + (a = Math.min( + f.pos + f.len, + Math.max(f.pos, f.toPixels(d.threshold)), + )), + c ? (b.translateX = a - f.len) : (b.translateY = a), + e.group.attr(b)) + : ((l = e.group.attr(k)), + e.group.animate( + { scaleY: 1 }, + p(E(e.options.animation), { + step: function(a, c) { + b[k] = l + c.pos * (f.pos - l); + e.group.attr(b); + }, + }), + ), + (e.animate = null))); + }, + remove: function() { + var a = this, + f = a.chart; + f.hasRendered && + H(f.series, function(e) { + e.type === a.type && (e.isDirty = !0); + }); + n.prototype.remove.apply(a, arguments); + }, + }, + ); + })(M); + (function(a) { + a = a.seriesType; + a('bar', 'column', null, { inverted: !0 }); + })(M); + (function(a) { + var E = a.Series; + a = a.seriesType; + a( + 'scatter', + 'line', + { + lineWidth: 0, + findNearestPointBy: 'xy', + marker: { enabled: !0 }, + tooltip: { + headerFormat: + '\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e \x3cspan style\x3d"font-size: 0.85em"\x3e {series.name}\x3c/span\x3e\x3cbr/\x3e', + pointFormat: + 'x: \x3cb\x3e{point.x}\x3c/b\x3e\x3cbr/\x3ey: \x3cb\x3e{point.y}\x3c/b\x3e\x3cbr/\x3e', + }, + }, + { + sorted: !1, + requireSorting: !1, + noSharedTooltip: !0, + trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], + takeOrdinalPosition: !1, + drawGraph: function() { + this.options.lineWidth && E.prototype.drawGraph.call(this); + }, + }, + ); + })(M); + (function(a) { + var E = a.deg2rad, + D = a.isNumber, + H = a.pick, + p = a.relativeLength; + a.CenteredSeriesMixin = { + getCenter: function() { + var a = this.options, + l = this.chart, + r = 2 * (a.slicedOffset || 0), + n = l.plotWidth - 2 * r, + l = l.plotHeight - 2 * r, + w = a.center, + w = [ + H(w[0], '50%'), + H(w[1], '50%'), + a.size || '100%', + a.innerSize || 0, + ], + u = Math.min(n, l), + e, + h; + for (e = 0; 4 > e; ++e) + (h = w[e]), + (a = 2 > e || (2 === e && /%$/.test(h))), + (w[e] = p(h, [n, l, u, w[2]][e]) + (a ? r : 0)); + w[3] > w[2] && (w[3] = w[2]); + return w; + }, + getStartAndEndRadians: function(a, l) { + a = D(a) ? a : 0; + l = D(l) && l > a && 360 > l - a ? l : a + 360; + return { start: E * (a + -90), end: E * (l + -90) }; + }, + }; + })(M); + (function(a) { + var E = a.addEvent, + D = a.CenteredSeriesMixin, + H = a.defined, + p = a.each, + f = a.extend, + l = D.getStartAndEndRadians, + r = a.inArray, + n = a.noop, + w = a.pick, + u = a.Point, + e = a.Series, + h = a.seriesType, + m = a.setAnimation; + h( + 'pie', + 'line', + { + center: [null, null], + clip: !1, + colorByPoint: !0, + dataLabels: { + distance: 30, + enabled: !0, + formatter: function() { + return this.point.isNull ? void 0 : this.point.name; + }, + x: 0, + }, + ignoreHiddenPoint: !0, + legendType: 'point', + marker: null, + size: null, + showInLegend: !1, + slicedOffset: 10, + stickyTracking: !1, + tooltip: { followPointer: !0 }, + borderColor: '#ffffff', + borderWidth: 1, + states: { hover: { brightness: 0.1, shadow: !1 } }, + }, + { + isCartesian: !1, + requireSorting: !1, + directTouch: !0, + noSharedTooltip: !0, + trackerGroups: ['group', 'dataLabelsGroup'], + axisTypes: [], + pointAttribs: a.seriesTypes.column.prototype.pointAttribs, + animate: function(a) { + var c = this, + b = c.points, + d = c.startAngleRad; + a || + (p(b, function(a) { + var b = a.graphic, + e = a.shapeArgs; + b && + (b.attr({ r: a.startR || c.center[3] / 2, start: d, end: d }), + b.animate( + { r: e.r, start: e.start, end: e.end }, + c.options.animation, + )); + }), + (c.animate = null)); + }, + updateTotals: function() { + var a, + c = 0, + b = this.points, + e = b.length, + f, + h = this.options.ignoreHiddenPoint; + for (a = 0; a < e; a++) + (f = b[a]), (c += h && !f.visible ? 0 : f.isNull ? 0 : f.y); + this.total = c; + for (a = 0; a < e; a++) + (f = b[a]), + (f.percentage = 0 < c && (f.visible || !h) ? (f.y / c) * 100 : 0), + (f.total = c); + }, + generatePoints: function() { + e.prototype.generatePoints.call(this); + this.updateTotals(); + }, + translate: function(a) { + this.generatePoints(); + var c = 0, + b = this.options, + d = b.slicedOffset, + e = d + (b.borderWidth || 0), + f, + h, + m, + n = l(b.startAngle, b.endAngle), + t = (this.startAngleRad = n.start), + n = (this.endAngleRad = n.end) - t, + p = this.points, + u, + q = b.dataLabels.distance, + b = b.ignoreHiddenPoint, + r, + F = p.length, + G; + a || (this.center = a = this.getCenter()); + this.getX = function(b, c, d) { + m = Math.asin( + Math.min((b - a[1]) / (a[2] / 2 + d.labelDistance), 1), + ); + return ( + a[0] + (c ? -1 : 1) * Math.cos(m) * (a[2] / 2 + d.labelDistance) + ); + }; + for (r = 0; r < F; r++) { + G = p[r]; + G.labelDistance = w( + G.options.dataLabels && G.options.dataLabels.distance, + q, + ); + this.maxLabelDistance = Math.max( + this.maxLabelDistance || 0, + G.labelDistance, + ); + f = t + c * n; + if (!b || G.visible) c += G.percentage / 100; + h = t + c * n; + G.shapeType = 'arc'; + G.shapeArgs = { + x: a[0], + y: a[1], + r: a[2] / 2, + innerR: a[3] / 2, + start: Math.round(1e3 * f) / 1e3, + end: Math.round(1e3 * h) / 1e3, + }; + m = (h + f) / 2; + m > 1.5 * Math.PI + ? (m -= 2 * Math.PI) + : m < -Math.PI / 2 && (m += 2 * Math.PI); + G.slicedTranslation = { + translateX: Math.round(Math.cos(m) * d), + translateY: Math.round(Math.sin(m) * d), + }; + h = (Math.cos(m) * a[2]) / 2; + u = (Math.sin(m) * a[2]) / 2; + G.tooltipPos = [a[0] + 0.7 * h, a[1] + 0.7 * u]; + G.half = m < -Math.PI / 2 || m > Math.PI / 2 ? 1 : 0; + G.angle = m; + f = Math.min(e, G.labelDistance / 5); + G.labelPos = [ + a[0] + h + Math.cos(m) * G.labelDistance, + a[1] + u + Math.sin(m) * G.labelDistance, + a[0] + h + Math.cos(m) * f, + a[1] + u + Math.sin(m) * f, + a[0] + h, + a[1] + u, + 0 > G.labelDistance ? 'center' : G.half ? 'right' : 'left', + m, + ]; + } + }, + drawGraph: null, + drawPoints: function() { + var a = this, + c = a.chart.renderer, + b, + e, + h, + l, + m = a.options.shadow; + m && !a.shadowGroup && (a.shadowGroup = c.g('shadow').add(a.group)); + p(a.points, function(d) { + e = d.graphic; + if (d.isNull) e && (d.graphic = e.destroy()); + else { + l = d.shapeArgs; + b = d.getTranslate(); + var k = d.shadowGroup; + m && !k && (k = d.shadowGroup = c.g('shadow').add(a.shadowGroup)); + k && k.attr(b); + h = a.pointAttribs(d, d.selected && 'select'); + e + ? e + .setRadialReference(a.center) + .attr(h) + .animate(f(l, b)) + : ((d.graphic = e = c[d.shapeType](l) + .setRadialReference(a.center) + .attr(b) + .add(a.group)), + d.visible || e.attr({ visibility: 'hidden' }), + e + .attr(h) + .attr({ 'stroke-linejoin': 'round' }) + .shadow(m, k)); + e.addClass(d.getClassName()); + } + }); + }, + searchPoint: n, + sortByAngle: function(a, c) { + a.sort(function(a, d) { + return void 0 !== a.angle && (d.angle - a.angle) * c; + }); + }, + drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, + getCenter: D.getCenter, + getSymbol: n, + }, + { + init: function() { + u.prototype.init.apply(this, arguments); + var a = this, + c; + a.name = w(a.name, 'Slice'); + c = function(b) { + a.slice('select' === b.type); + }; + E(a, 'select', c); + E(a, 'unselect', c); + return a; + }, + isValid: function() { + return a.isNumber(this.y, !0) && 0 <= this.y; + }, + setVisible: function(a, c) { + var b = this, + d = b.series, + e = d.chart, + f = d.options.ignoreHiddenPoint; + c = w(c, f); + a !== b.visible && + ((b.visible = b.options.visible = a = + void 0 === a ? !b.visible : a), + (d.options.data[r(b, d.data)] = b.options), + p(['graphic', 'dataLabel', 'connector', 'shadowGroup'], function( + c, + ) { + if (b[c]) b[c][a ? 'show' : 'hide'](!0); + }), + b.legendItem && e.legend.colorizeItem(b, a), + a || 'hover' !== b.state || b.setState(''), + f && (d.isDirty = !0), + c && e.redraw()); + }, + slice: function(a, c, b) { + var d = this.series; + m(b, d.chart); + w(c, !0); + this.sliced = this.options.sliced = H(a) ? a : !this.sliced; + d.options.data[r(this, d.data)] = this.options; + this.graphic.animate(this.getTranslate()); + this.shadowGroup && this.shadowGroup.animate(this.getTranslate()); + }, + getTranslate: function() { + return this.sliced + ? this.slicedTranslation + : { translateX: 0, translateY: 0 }; + }, + haloPath: function(a) { + var c = this.shapeArgs; + return this.sliced || !this.visible + ? [] + : this.series.chart.renderer.symbols.arc( + c.x, + c.y, + c.r + a, + c.r + a, + { innerR: this.shapeArgs.r - 1, start: c.start, end: c.end }, + ); + }, + }, + ); + })(M); + (function(a) { + var E = a.addEvent, + D = a.arrayMax, + H = a.defined, + p = a.each, + f = a.extend, + l = a.format, + r = a.map, + n = a.merge, + w = a.noop, + u = a.pick, + e = a.relativeLength, + h = a.Series, + m = a.seriesTypes, + d = a.stableSort; + a.distribute = function(a, b) { + function c(a, b) { + return a.target - b.target; + } + var e, + f = !0, + h = a, + l = [], + m; + m = 0; + for (e = a.length; e--; ) m += a[e].size; + if (m > b) { + d(a, function(a, b) { + return (b.rank || 0) - (a.rank || 0); + }); + for (m = e = 0; m <= b; ) (m += a[e].size), e++; + l = a.splice(e - 1, a.length); + } + d(a, c); + for ( + a = r(a, function(a) { + return { size: a.size, targets: [a.target], align: u(a.align, 0.5) }; + }); + f; + + ) { + for (e = a.length; e--; ) + (f = a[e]), + (m = + (Math.min.apply(0, f.targets) + Math.max.apply(0, f.targets)) / + 2), + (f.pos = Math.min(Math.max(0, m - f.size * f.align), b - f.size)); + e = a.length; + for (f = !1; e--; ) + 0 < e && + a[e - 1].pos + a[e - 1].size > a[e].pos && + ((a[e - 1].size += a[e].size), + (a[e - 1].targets = a[e - 1].targets.concat(a[e].targets)), + (a[e - 1].align = 0.5), + a[e - 1].pos + a[e - 1].size > b && + (a[e - 1].pos = b - a[e - 1].size), + a.splice(e, 1), + (f = !0)); + } + e = 0; + p(a, function(a) { + var b = 0; + p(a.targets, function() { + h[e].pos = a.pos + b; + b += h[e].size; + e++; + }); + }); + h.push.apply(h, l); + d(h, c); + }; + h.prototype.drawDataLabels = function() { + function c(a, b) { + var c = b.filter; + return c + ? ((b = c.operator), + (a = a[c.property]), + (c = c.value), + ('\x3e' === b && a > c) || + ('\x3c' === b && a < c) || + ('\x3e\x3d' === b && a >= c) || + ('\x3c\x3d' === b && a <= c) || + ('\x3d\x3d' === b && a == c) || + ('\x3d\x3d\x3d' === b && a === c) + ? !0 + : !1) + : !0; + } + var b = this, + d = b.options, + e = d.dataLabels, + f = b.points, + h, + m, + r = b.hasRendered || 0, + t, + w, + D = u(e.defer, !!d.animation), + q = b.chart.renderer; + if (e.enabled || b._hasPointLabels) + b.dlProcessOptions && b.dlProcessOptions(e), + (w = b.plotGroup( + 'dataLabelsGroup', + 'data-labels', + D && !r ? 'hidden' : 'visible', + e.zIndex || 6, + )), + D && + (w.attr({ opacity: +r }), + r || + E(b, 'afterAnimate', function() { + b.visible && w.show(!0); + w[d.animation ? 'animate' : 'attr']( + { opacity: 1 }, + { duration: 200 }, + ); + })), + (m = e), + p(f, function(f) { + var k, + p = f.dataLabel, + g, + x, + r = f.connector, + z = !p, + C; + h = f.dlOptions || (f.options && f.options.dataLabels); + (k = u(h && h.enabled, m.enabled) && !f.isNull) && + (k = !0 === c(f, h || e)); + k && + ((e = n(m, h)), + (g = f.getLabelConfig()), + (C = e[f.formatPrefix + 'Format'] || e.format), + (t = H(C) + ? l(C, g) + : (e[f.formatPrefix + 'Formatter'] || e.formatter).call(g, e)), + (C = e.style), + (g = e.rotation), + (C.color = u(e.color, C.color, b.color, '#000000')), + 'contrast' === C.color && + ((f.contrastColor = q.getContrast(f.color || b.color)), + (C.color = + e.inside || 0 > u(f.labelDistance, e.distance) || d.stacking + ? f.contrastColor + : '#000000')), + d.cursor && (C.cursor = d.cursor), + (x = { + fill: e.backgroundColor, + stroke: e.borderColor, + 'stroke-width': e.borderWidth, + r: e.borderRadius || 0, + rotation: g, + padding: e.padding, + zIndex: 1, + }), + a.objectEach(x, function(a, b) { + void 0 === a && delete x[b]; + })); + !p || (k && H(t)) + ? k && + H(t) && + (p + ? (x.text = t) + : ((p = f.dataLabel = g + ? q.text(t, 0, -9999).addClass('highcharts-data-label') + : q.label( + t, + 0, + -9999, + e.shape, + null, + null, + e.useHTML, + null, + 'data-label', + )), + p.addClass( + ' highcharts-data-label-color-' + + f.colorIndex + + ' ' + + (e.className || '') + + (e.useHTML ? 'highcharts-tracker' : ''), + )), + p.attr(x), + p.css(C).shadow(e.shadow), + p.added || p.add(w), + b.alignDataLabel(f, p, e, null, z)) + : ((f.dataLabel = p = p.destroy()), + r && (f.connector = r.destroy())); + }); + }; + h.prototype.alignDataLabel = function(a, b, d, e, h) { + var c = this.chart, + k = c.inverted, + l = u(a.dlBox && a.dlBox.centerX, a.plotX, -9999), + m = u(a.plotY, -9999), + n = b.getBBox(), + p, + q = d.rotation, + r = d.align, + w = + this.visible && + (a.series.forceDL || + c.isInsidePlot(l, Math.round(m), k) || + (e && c.isInsidePlot(l, k ? e.x + 1 : e.y + e.height - 1, k))), + z = 'justify' === u(d.overflow, 'justify'); + if ( + w && + ((p = d.style.fontSize), + (p = c.renderer.fontMetrics(p, b).b), + (e = f( + { + x: k ? this.yAxis.len - m : l, + y: Math.round(k ? this.xAxis.len - l : m), + width: 0, + height: 0, + }, + e, + )), + f(d, { width: n.width, height: n.height }), + q + ? ((z = !1), + (l = c.renderer.rotCorr(p, q)), + (l = { + x: e.x + d.x + e.width / 2 + l.x, + y: + e.y + + d.y + + { top: 0, middle: 0.5, bottom: 1 }[d.verticalAlign] * e.height, + }), + b[h ? 'attr' : 'animate'](l).attr({ align: r }), + (m = (q + 720) % 360), + (m = 180 < m && 360 > m), + 'left' === r + ? (l.y -= m ? n.height : 0) + : 'center' === r + ? ((l.x -= n.width / 2), (l.y -= n.height / 2)) + : 'right' === r && ((l.x -= n.width), (l.y -= m ? 0 : n.height))) + : (b.align(d, null, e), (l = b.alignAttr)), + z + ? (a.isLabelJustified = this.justifyDataLabel(b, d, l, n, e, h)) + : u(d.crop, !0) && + (w = + c.isInsidePlot(l.x, l.y) && + c.isInsidePlot(l.x + n.width, l.y + n.height)), + d.shape && !q) + ) + b[h ? 'attr' : 'animate']({ + anchorX: k ? c.plotWidth - a.plotY : a.plotX, + anchorY: k ? c.plotHeight - a.plotX : a.plotY, + }); + w || (b.attr({ y: -9999 }), (b.placed = !1)); + }; + h.prototype.justifyDataLabel = function(a, b, d, e, f, h) { + var c = this.chart, + k = b.align, + l = b.verticalAlign, + m, + n, + p = a.box ? 0 : a.padding || 0; + m = d.x + p; + 0 > m && ('right' === k ? (b.align = 'left') : (b.x = -m), (n = !0)); + m = d.x + e.width - p; + m > c.plotWidth && + ('left' === k ? (b.align = 'right') : (b.x = c.plotWidth - m), + (n = !0)); + m = d.y + p; + 0 > m && + ('bottom' === l ? (b.verticalAlign = 'top') : (b.y = -m), (n = !0)); + m = d.y + e.height - p; + m > c.plotHeight && + ('top' === l ? (b.verticalAlign = 'bottom') : (b.y = c.plotHeight - m), + (n = !0)); + n && ((a.placed = !h), a.align(b, null, f)); + return n; + }; + m.pie && + ((m.pie.prototype.drawDataLabels = function() { + var c = this, + b = c.data, + d, + e = c.chart, + f = c.options.dataLabels, + l = u(f.connectorPadding, 10), + m = u(f.connectorWidth, 1), + n = e.plotWidth, + t = e.plotHeight, + r, + w = c.center, + q = w[2] / 2, + A = w[1], + F, + G, + g, + v, + E = [[], []], + L, + P, + J, + M, + y = [0, 0, 0, 0]; + c.visible && + (f.enabled || c._hasPointLabels) && + (p(b, function(a) { + a.dataLabel && + a.visible && + a.dataLabel.shortened && + (a.dataLabel + .attr({ width: 'auto' }) + .css({ width: 'auto', textOverflow: 'clip' }), + (a.dataLabel.shortened = !1)); + }), + h.prototype.drawDataLabels.apply(c), + p(b, function(a) { + a.dataLabel && + a.visible && + (E[a.half].push(a), (a.dataLabel._pos = null)); + }), + p(E, function(b, h) { + var k, + m, + x = b.length, + r = [], + z; + if (x) + for ( + c.sortByAngle(b, h - 0.5), + 0 < c.maxLabelDistance && + ((k = Math.max(0, A - q - c.maxLabelDistance)), + (m = Math.min(A + q + c.maxLabelDistance, e.plotHeight)), + p(b, function(a) { + 0 < a.labelDistance && + a.dataLabel && + ((a.top = Math.max(0, A - q - a.labelDistance)), + (a.bottom = Math.min( + A + q + a.labelDistance, + e.plotHeight, + )), + (z = a.dataLabel.getBBox().height || 21), + (a.positionsIndex = + r.push({ + target: a.labelPos[1] - a.top + z / 2, + size: z, + rank: a.y, + }) - 1)); + }), + a.distribute(r, m + z - k)), + M = 0; + M < x; + M++ + ) + (d = b[M]), + (m = d.positionsIndex), + (g = d.labelPos), + (F = d.dataLabel), + (J = !1 === d.visible ? 'hidden' : 'inherit'), + (P = k = g[1]), + r && + H(r[m]) && + (void 0 === r[m].pos + ? (J = 'hidden') + : ((v = r[m].size), (P = d.top + r[m].pos))), + delete d.positionIndex, + (L = f.justify + ? w[0] + (h ? -1 : 1) * (q + d.labelDistance) + : c.getX(P < d.top + 2 || P > d.bottom - 2 ? k : P, h, d)), + (F._attr = { visibility: J, align: g[6] }), + (F._pos = { + x: L + f.x + ({ left: l, right: -l }[g[6]] || 0), + y: P + f.y - 10, + }), + (g.x = L), + (g.y = P), + u(f.crop, !0) && + ((G = F.getBBox().width), + (k = null), + L - G < l + ? ((k = Math.round(G - L + l)), + (y[3] = Math.max(k, y[3]))) + : L + G > n - l && + ((k = Math.round(L + G - n + l)), + (y[1] = Math.max(k, y[1]))), + 0 > P - v / 2 + ? (y[0] = Math.max(Math.round(-P + v / 2), y[0])) + : P + v / 2 > t && + (y[2] = Math.max(Math.round(P + v / 2 - t), y[2])), + (F.sideOverflow = k)); + }), + 0 === D(y) || this.verifyDataLabelOverflow(y)) && + (this.placeDataLabels(), + m && + p(this.points, function(a) { + var b; + r = a.connector; + if ( + (F = a.dataLabel) && + F._pos && + a.visible && + 0 < a.labelDistance + ) { + J = F._attr.visibility; + if ((b = !r)) + (a.connector = r = e.renderer + .path() + .addClass( + 'highcharts-data-label-connector highcharts-color-' + + a.colorIndex, + ) + .add(c.dataLabelsGroup)), + r.attr({ + 'stroke-width': m, + stroke: f.connectorColor || a.color || '#666666', + }); + r[b ? 'attr' : 'animate']({ d: c.connectorPath(a.labelPos) }); + r.attr('visibility', J); + } else r && (a.connector = r.destroy()); + })); + }), + (m.pie.prototype.connectorPath = function(a) { + var b = a.x, + c = a.y; + return u(this.options.dataLabels.softConnector, !0) + ? [ + 'M', + b + ('left' === a[6] ? 5 : -5), + c, + 'C', + b, + c, + 2 * a[2] - a[4], + 2 * a[3] - a[5], + a[2], + a[3], + 'L', + a[4], + a[5], + ] + : [ + 'M', + b + ('left' === a[6] ? 5 : -5), + c, + 'L', + a[2], + a[3], + 'L', + a[4], + a[5], + ]; + }), + (m.pie.prototype.placeDataLabels = function() { + p( + this.points, + function(a) { + var b = a.dataLabel; + b && + a.visible && + ((a = b._pos) + ? (b.sideOverflow && + ((b._attr.width = b.getBBox().width - b.sideOverflow), + b.css({ + width: b._attr.width + 'px', + textOverflow: 'ellipsis', + }), + (b.shortened = !0)), + b.attr(b._attr), + b[b.moved ? 'animate' : 'attr'](a), + (b.moved = !0)) + : b && b.attr({ y: -9999 })); + }, + this, + ); + }), + (m.pie.prototype.alignDataLabel = w), + (m.pie.prototype.verifyDataLabelOverflow = function(a) { + var b = this.center, + c = this.options, + d = c.center, + f = c.minSize || 80, + h, + l = null !== c.size; + l || + (null !== d[0] + ? (h = Math.max(b[2] - Math.max(a[1], a[3]), f)) + : ((h = Math.max(b[2] - a[1] - a[3], f)), + (b[0] += (a[3] - a[1]) / 2)), + null !== d[1] + ? (h = Math.max(Math.min(h, b[2] - Math.max(a[0], a[2])), f)) + : ((h = Math.max(Math.min(h, b[2] - a[0] - a[2]), f)), + (b[1] += (a[0] - a[2]) / 2)), + h < b[2] + ? ((b[2] = h), + (b[3] = Math.min(e(c.innerSize || 0, h), h)), + this.translate(b), + this.drawDataLabels && this.drawDataLabels()) + : (l = !0)); + return l; + })); + m.column && + (m.column.prototype.alignDataLabel = function(a, b, d, e, f) { + var c = this.chart.inverted, + k = a.series, + l = a.dlBox || a.shapeArgs, + m = u(a.below, a.plotY > u(this.translatedThreshold, k.yAxis.len)), + p = u(d.inside, !!this.options.stacking); + l && + ((e = n(l)), + 0 > e.y && ((e.height += e.y), (e.y = 0)), + (l = e.y + e.height - k.yAxis.len), + 0 < l && (e.height -= l), + c && + (e = { + x: k.yAxis.len - e.y - e.height, + y: k.xAxis.len - e.x - e.width, + width: e.height, + height: e.width, + }), + p || + (c + ? ((e.x += m ? 0 : e.width), (e.width = 0)) + : ((e.y += m ? e.height : 0), (e.height = 0)))); + d.align = u(d.align, !c || p ? 'center' : m ? 'right' : 'left'); + d.verticalAlign = u( + d.verticalAlign, + c || p ? 'middle' : m ? 'top' : 'bottom', + ); + h.prototype.alignDataLabel.call(this, a, b, d, e, f); + a.isLabelJustified && + a.contrastColor && + a.dataLabel.css({ color: a.contrastColor }); + }); + })(M); + (function(a) { + var E = a.Chart, + D = a.each, + H = a.objectEach, + p = a.pick; + a = a.addEvent; + a(E.prototype, 'render', function() { + var a = []; + D(this.labelCollectors || [], function(f) { + a = a.concat(f()); + }); + D(this.yAxis || [], function(f) { + f.options.stackLabels && + !f.options.stackLabels.allowOverlap && + H(f.stacks, function(f) { + H(f, function(f) { + a.push(f.label); + }); + }); + }); + D(this.series || [], function(f) { + var l = f.options.dataLabels, + n = f.dataLabelCollections || ['dataLabel']; + (l.enabled || f._hasPointLabels) && + !l.allowOverlap && + f.visible && + D(n, function(l) { + D(f.points, function(f) { + f[l] && + ((f[l].labelrank = p( + f.labelrank, + f.shapeArgs && f.shapeArgs.height, + )), + a.push(f[l])); + }); + }); + }); + this.hideOverlappingLabels(a); + }); + E.prototype.hideOverlappingLabels = function(a) { + var f = a.length, + p, + n, + w, + u, + e, + h, + m, + d, + c, + b = function(a, b, c, d, e, f, h, l) { + return !(e > a + c || e + h < a || f > b + d || f + l < b); + }; + for (n = 0; n < f; n++) + if ((p = a[n])) + (p.oldOpacity = p.opacity), + (p.newOpacity = 1), + p.width || + ((w = p.getBBox()), (p.width = w.width), (p.height = w.height)); + a.sort(function(a, b) { + return (b.labelrank || 0) - (a.labelrank || 0); + }); + for (n = 0; n < f; n++) + for (w = a[n], p = n + 1; p < f; ++p) + if ( + ((u = a[p]), + w && + u && + w !== u && + w.placed && + u.placed && + 0 !== w.newOpacity && + 0 !== u.newOpacity && + ((e = w.alignAttr), + (h = u.alignAttr), + (m = w.parentGroup), + (d = u.parentGroup), + (c = 2 * (w.box ? 0 : w.padding || 0)), + (e = b( + e.x + m.translateX, + e.y + m.translateY, + w.width - c, + w.height - c, + h.x + d.translateX, + h.y + d.translateY, + u.width - c, + u.height - c, + )))) + ) + (w.labelrank < u.labelrank ? w : u).newOpacity = 0; + D(a, function(a) { + var b, c; + a && + ((c = a.newOpacity), + a.oldOpacity !== c && + a.placed && + (c + ? a.show(!0) + : (b = function() { + a.hide(); + }), + (a.alignAttr.opacity = c), + a[a.isOld ? 'animate' : 'attr'](a.alignAttr, null, b)), + (a.isOld = !0)); + }); + }; + })(M); + (function(a) { + var E = a.addEvent, + D = a.Chart, + H = a.createElement, + p = a.css, + f = a.defaultOptions, + l = a.defaultPlotOptions, + r = a.each, + n = a.extend, + w = a.fireEvent, + u = a.hasTouch, + e = a.inArray, + h = a.isObject, + m = a.Legend, + d = a.merge, + c = a.pick, + b = a.Point, + k = a.Series, + z = a.seriesTypes, + B = a.svg, + I; + I = a.TrackerMixin = { + drawTrackerPoint: function() { + var a = this, + b = a.chart.pointer, + c = function(a) { + var c = b.getPointFromEvent(a); + void 0 !== c && ((b.isDirectTouch = !0), c.onMouseOver(a)); + }; + r(a.points, function(a) { + a.graphic && (a.graphic.element.point = a); + a.dataLabel && + (a.dataLabel.div + ? (a.dataLabel.div.point = a) + : (a.dataLabel.element.point = a)); + }); + a._hasTracking || + (r(a.trackerGroups, function(d) { + if (a[d]) { + a[d] + .addClass('highcharts-tracker') + .on('mouseover', c) + .on('mouseout', function(a) { + b.onTrackerMouseOut(a); + }); + if (u) a[d].on('touchstart', c); + a.options.cursor && a[d].css(p).css({ cursor: a.options.cursor }); + } + }), + (a._hasTracking = !0)); + }, + drawTrackerGraph: function() { + var a = this, + b = a.options, + c = b.trackByArea, + d = [].concat(c ? a.areaPath : a.graphPath), + e = d.length, + f = a.chart, + h = f.pointer, + k = f.renderer, + l = f.options.tooltip.snap, + g = a.tracker, + m, + n = function() { + if (f.hoverSeries !== a) a.onMouseOver(); + }, + p = 'rgba(192,192,192,' + (B ? 0.0001 : 0.002) + ')'; + if (e && !c) + for (m = e + 1; m--; ) + 'M' === d[m] && d.splice(m + 1, 0, d[m + 1] - l, d[m + 2], 'L'), + ((m && 'M' === d[m]) || m === e) && + d.splice(m, 0, 'L', d[m - 2] + l, d[m - 1]); + g + ? g.attr({ d: d }) + : a.graph && + ((a.tracker = k + .path(d) + .attr({ + 'stroke-linejoin': 'round', + visibility: a.visible ? 'visible' : 'hidden', + stroke: p, + fill: c ? p : 'none', + 'stroke-width': a.graph.strokeWidth() + (c ? 0 : 2 * l), + zIndex: 2, + }) + .add(a.group)), + r([a.tracker, a.markerGroup], function(a) { + a.addClass('highcharts-tracker') + .on('mouseover', n) + .on('mouseout', function(a) { + h.onTrackerMouseOut(a); + }); + b.cursor && a.css({ cursor: b.cursor }); + if (u) a.on('touchstart', n); + })); + }, + }; + z.column && (z.column.prototype.drawTracker = I.drawTrackerPoint); + z.pie && (z.pie.prototype.drawTracker = I.drawTrackerPoint); + z.scatter && (z.scatter.prototype.drawTracker = I.drawTrackerPoint); + n(m.prototype, { + setItemEvents: function(a, c, e) { + var f = this, + h = f.chart.renderer.boxWrapper, + k = + 'highcharts-legend-' + + (a instanceof b ? 'point' : 'series') + + '-active'; + (e ? c : a.legendGroup) + .on('mouseover', function() { + a.setState('hover'); + h.addClass(k); + c.css(f.options.itemHoverStyle); + }) + .on('mouseout', function() { + c.css(d(a.visible ? f.itemStyle : f.itemHiddenStyle)); + h.removeClass(k); + a.setState(); + }) + .on('click', function(b) { + var c = function() { + a.setVisible && a.setVisible(); + }; + h.removeClass(k); + b = { browserEvent: b }; + a.firePointEvent + ? a.firePointEvent('legendItemClick', b, c) + : w(a, 'legendItemClick', b, c); + }); + }, + createCheckboxForItem: function(a) { + a.checkbox = H( + 'input', + { type: 'checkbox', checked: a.selected, defaultChecked: a.selected }, + this.options.itemCheckboxStyle, + this.chart.container, + ); + E(a.checkbox, 'click', function(b) { + w( + a.series || a, + 'checkboxClick', + { checked: b.target.checked, item: a }, + function() { + a.select(); + }, + ); + }); + }, + }); + f.legend.itemStyle.cursor = 'pointer'; + n(D.prototype, { + showResetZoom: function() { + var a = this, + b = f.lang, + c = a.options.chart.resetZoomButton, + d = c.theme, + e = d.states, + h = 'chart' === c.relativeTo ? null : 'plotBox'; + this.resetZoomButton = a.renderer + .button( + b.resetZoom, + null, + null, + function() { + a.zoomOut(); + }, + d, + e && e.hover, + ) + .attr({ align: c.position.align, title: b.resetZoomTitle }) + .addClass('highcharts-reset-zoom') + .add() + .align(c.position, !1, h); + }, + zoomOut: function() { + var a = this; + w(a, 'selection', { resetSelection: !0 }, function() { + a.zoom(); + }); + }, + zoom: function(a) { + var b, + d = this.pointer, + e = !1, + f; + !a || a.resetSelection + ? (r(this.axes, function(a) { + b = a.zoom(); + }), + (d.initiated = !1)) + : r(a.xAxis.concat(a.yAxis), function(a) { + var c = a.axis; + d[c.isXAxis ? 'zoomX' : 'zoomY'] && + ((b = c.zoom(a.min, a.max)), c.displayBtn && (e = !0)); + }); + f = this.resetZoomButton; + e && !f + ? this.showResetZoom() + : !e && h(f) && (this.resetZoomButton = f.destroy()); + b && + this.redraw( + c( + this.options.chart.animation, + a && a.animation, + 100 > this.pointCount, + ), + ); + }, + pan: function(a, b) { + var c = this, + d = c.hoverPoints, + e; + d && + r(d, function(a) { + a.setState(); + }); + r('xy' === b ? [1, 0] : [1], function(b) { + b = c[b ? 'xAxis' : 'yAxis'][0]; + var d = b.horiz, + f = a[d ? 'chartX' : 'chartY'], + d = d ? 'mouseDownX' : 'mouseDownY', + h = c[d], + g = (b.pointRange || 0) / 2, + k = b.getExtremes(), + l = b.toValue(h - f, !0) + g, + m = b.toValue(h + b.len - f, !0) - g, + n = m < l, + h = n ? m : l, + l = n ? l : m, + m = Math.min( + k.dataMin, + g ? k.min : b.toValue(b.toPixels(k.min) - b.minPixelPadding), + ), + g = Math.max( + k.dataMax, + g ? k.max : b.toValue(b.toPixels(k.max) + b.minPixelPadding), + ), + n = m - h; + 0 < n && ((l += n), (h = m)); + n = l - g; + 0 < n && ((l = g), (h -= n)); + b.series.length && + h !== k.min && + l !== k.max && + (b.setExtremes(h, l, !1, !1, { trigger: 'pan' }), (e = !0)); + c[d] = f; + }); + e && c.redraw(!1); + p(c.container, { cursor: 'move' }); + }, + }); + n(b.prototype, { + select: function(a, b) { + var d = this, + f = d.series, + h = f.chart; + a = c(a, !d.selected); + d.firePointEvent( + a ? 'select' : 'unselect', + { accumulate: b }, + function() { + d.selected = d.options.selected = a; + f.options.data[e(d, f.data)] = d.options; + d.setState(a && 'select'); + b || + r(h.getSelectedPoints(), function(a) { + a.selected && + a !== d && + ((a.selected = a.options.selected = !1), + (f.options.data[e(a, f.data)] = a.options), + a.setState(''), + a.firePointEvent('unselect')); + }); + }, + ); + }, + onMouseOver: function(a) { + var b = this.series.chart, + c = b.pointer; + a = a + ? c.normalize(a) + : c.getChartCoordinatesFromPoint(this, b.inverted); + c.runPointActions(a, this); + }, + onMouseOut: function() { + var a = this.series.chart; + this.firePointEvent('mouseOut'); + r(a.hoverPoints || [], function(a) { + a.setState(); + }); + a.hoverPoints = a.hoverPoint = null; + }, + importEvents: function() { + if (!this.hasImportedEvents) { + var b = this, + c = d(b.series.options.point, b.options).events; + b.events = c; + a.objectEach(c, function(a, c) { + E(b, c, a); + }); + this.hasImportedEvents = !0; + } + }, + setState: function(a, b) { + var d = Math.floor(this.plotX), + e = this.plotY, + f = this.series, + h = f.options.states[a] || {}, + k = l[f.type].marker && f.options.marker, + m = k && !1 === k.enabled, + p = (k && k.states && k.states[a]) || {}, + g = !1 === p.enabled, + r = f.stateMarkerGraphic, + u = this.marker || {}, + w = f.chart, + x = f.halo, + z, + B = k && f.markerAttribs; + a = a || ''; + if ( + !( + (a === this.state && !b) || + (this.selected && 'select' !== a) || + !1 === h.enabled || + (a && (g || (m && !1 === p.enabled))) || + (a && u.states && u.states[a] && !1 === u.states[a].enabled) + ) + ) { + B && (z = f.markerAttribs(this, a)); + if (this.graphic) + this.state && + this.graphic.removeClass('highcharts-point-' + this.state), + a && this.graphic.addClass('highcharts-point-' + a), + this.graphic.animate( + f.pointAttribs(this, a), + c(w.options.chart.animation, h.animation), + ), + z && + this.graphic.animate( + z, + c(w.options.chart.animation, p.animation, k.animation), + ), + r && r.hide(); + else { + if (a && p) { + k = u.symbol || f.symbol; + r && r.currentSymbol !== k && (r = r.destroy()); + if (r) r[b ? 'animate' : 'attr']({ x: z.x, y: z.y }); + else + k && + ((f.stateMarkerGraphic = r = w.renderer + .symbol(k, z.x, z.y, z.width, z.height) + .add(f.markerGroup)), + (r.currentSymbol = k)); + r && r.attr(f.pointAttribs(this, a)); + } + r && + (r[a && w.isInsidePlot(d, e, w.inverted) ? 'show' : 'hide'](), + (r.element.point = this)); + } + (d = h.halo) && d.size + ? (x || + (f.halo = x = w.renderer + .path() + .add((this.graphic || r).parentGroup)), + x[b ? 'animate' : 'attr']({ d: this.haloPath(d.size) }), + x.attr({ + class: + 'highcharts-halo highcharts-color-' + + c(this.colorIndex, f.colorIndex), + }), + (x.point = this), + x.attr( + n( + { + fill: this.color || f.color, + 'fill-opacity': d.opacity, + zIndex: -1, + }, + d.attributes, + ), + )) + : x && + x.point && + x.point.haloPath && + x.animate({ d: x.point.haloPath(0) }); + this.state = a; + } + }, + haloPath: function(a) { + return this.series.chart.renderer.symbols.circle( + Math.floor(this.plotX) - a, + this.plotY - a, + 2 * a, + 2 * a, + ); + }, + }); + n(k.prototype, { + onMouseOver: function() { + var a = this.chart, + b = a.hoverSeries; + if (b && b !== this) b.onMouseOut(); + this.options.events.mouseOver && w(this, 'mouseOver'); + this.setState('hover'); + a.hoverSeries = this; + }, + onMouseOut: function() { + var a = this.options, + b = this.chart, + c = b.tooltip, + d = b.hoverPoint; + b.hoverSeries = null; + if (d) d.onMouseOut(); + this && a.events.mouseOut && w(this, 'mouseOut'); + !c || + this.stickyTracking || + (c.shared && !this.noSharedTooltip) || + c.hide(); + this.setState(); + }, + setState: function(a) { + var b = this, + d = b.options, + e = b.graph, + f = d.states, + h = d.lineWidth, + d = 0; + a = a || ''; + if ( + b.state !== a && + (r([b.group, b.markerGroup, b.dataLabelsGroup], function(c) { + c && + (b.state && c.removeClass('highcharts-series-' + b.state), + a && c.addClass('highcharts-series-' + a)); + }), + (b.state = a), + !f[a] || !1 !== f[a].enabled) && + (a && (h = f[a].lineWidth || h + (f[a].lineWidthPlus || 0)), + e && !e.dashstyle) + ) + for ( + h = { 'stroke-width': h }, + e.animate( + h, + c(b.chart.options.chart.animation, f[a] && f[a].animation), + ); + b['zone-graph-' + d]; + + ) + b['zone-graph-' + d].attr(h), (d += 1); + }, + setVisible: function(a, b) { + var c = this, + d = c.chart, + e = c.legendItem, + f, + h = d.options.chart.ignoreHiddenSeries, + k = c.visible; + f = (c.visible = a = c.options.visible = c.userOptions.visible = + void 0 === a ? !k : a) + ? 'show' + : 'hide'; + r( + ['group', 'dataLabelsGroup', 'markerGroup', 'tracker', 'tt'], + function(a) { + if (c[a]) c[a][f](); + }, + ); + if (d.hoverSeries === c || (d.hoverPoint && d.hoverPoint.series) === c) + c.onMouseOut(); + e && d.legend.colorizeItem(c, a); + c.isDirty = !0; + c.options.stacking && + r(d.series, function(a) { + a.options.stacking && a.visible && (a.isDirty = !0); + }); + r(c.linkedSeries, function(b) { + b.setVisible(a, !1); + }); + h && (d.isDirtyBox = !0); + !1 !== b && d.redraw(); + w(c, f); + }, + show: function() { + this.setVisible(!0); + }, + hide: function() { + this.setVisible(!1); + }, + select: function(a) { + this.selected = a = void 0 === a ? !this.selected : a; + this.checkbox && (this.checkbox.checked = a); + w(this, a ? 'select' : 'unselect'); + }, + drawTracker: I.drawTrackerGraph, + }); + })(M); + (function(a) { + var E = a.Chart, + D = a.each, + H = a.inArray, + p = a.isArray, + f = a.isObject, + l = a.pick, + r = a.splat; + E.prototype.setResponsive = function(f) { + var l = this.options.responsive, + n = [], + e = this.currentResponsive; + l && + l.rules && + D( + l.rules, + function(e) { + void 0 === e._id && (e._id = a.uniqueKey()); + this.matchResponsiveRule(e, n, f); + }, + this, + ); + var h = a.merge.apply( + 0, + a.map(n, function(e) { + return a.find(l.rules, function(a) { + return a._id === e; + }).chartOptions; + }), + ), + n = n.toString() || void 0; + n !== (e && e.ruleIds) && + (e && this.update(e.undoOptions, f), + n + ? ((this.currentResponsive = { + ruleIds: n, + mergedOptions: h, + undoOptions: this.currentOptions(h), + }), + this.update(h, f)) + : (this.currentResponsive = void 0)); + }; + E.prototype.matchResponsiveRule = function(a, f) { + var n = a.condition; + ( + n.callback || + function() { + return ( + this.chartWidth <= l(n.maxWidth, Number.MAX_VALUE) && + this.chartHeight <= l(n.maxHeight, Number.MAX_VALUE) && + this.chartWidth >= l(n.minWidth, 0) && + this.chartHeight >= l(n.minHeight, 0) + ); + } + ).call(this) && f.push(a._id); + }; + E.prototype.currentOptions = function(l) { + function n(e, h, l, d) { + var c; + a.objectEach(e, function(a, e) { + if (!d && -1 < H(e, ['series', 'xAxis', 'yAxis'])) + for (a = r(a), l[e] = [], c = 0; c < a.length; c++) + h[e][c] && ((l[e][c] = {}), n(a[c], h[e][c], l[e][c], d + 1)); + else + f(a) + ? ((l[e] = p(a) ? [] : {}), n(a, h[e] || {}, l[e], d + 1)) + : (l[e] = h[e] || null); + }); + } + var u = {}; + n(l, this.options, u, 0); + return u; + }; + })(M); + return M; +}); From e9ead68e9458635101dcdb01d0bec8dc7ddd2af2 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Fri, 4 Jan 2019 18:17:27 +1300 Subject: [PATCH 259/267] Revert "Auto corrected by following Format Javascript Code" This reverts commit 334b33c555e4d53f60c7c4c2be8ec1fa11209f6d. --- app/assets/javascripts/highcharts.js | 11651 +------------------------ 1 file changed, 382 insertions(+), 11269 deletions(-) diff --git a/app/assets/javascripts/highcharts.js b/app/assets/javascripts/highcharts.js index c7136bafe..9554ef58b 100644 --- a/app/assets/javascripts/highcharts.js +++ b/app/assets/javascripts/highcharts.js @@ -5,11272 +5,385 @@ License: www.highcharts.com/license */ -(function(S, M) { - 'object' === typeof module && module.exports - ? (module.exports = S.document ? M(S) : M) - : (S.Highcharts = M(S)); -})('undefined' !== typeof window ? window : this, function(S) { - var M = (function() { - var a = 'undefined' === typeof S ? window : S, - E = a.document, - D = (a.navigator && a.navigator.userAgent) || '', - H = - E && - E.createElementNS && - !!E.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect, - p = /(edge|msie|trident)/i.test(D) && !a.opera, - f = /Firefox/.test(D), - l = f && 4 > parseInt(D.split('Firefox/')[1], 10); - return a.Highcharts - ? a.Highcharts.error(16, !0) - : { - product: 'Highcharts', - version: '6.0.4', - deg2rad: (2 * Math.PI) / 360, - doc: E, - hasBidiBug: l, - hasTouch: E && void 0 !== E.documentElement.ontouchstart, - isMS: p, - isWebKit: /AppleWebKit/.test(D), - isFirefox: f, - isTouchDevice: /(Mobile|Android|Windows Phone)/.test(D), - SVG_NS: 'http://www.w3.org/2000/svg', - chartCount: 0, - seriesTypes: {}, - symbolSizes: {}, - svg: H, - win: a, - marginNames: ['plotTop', 'marginRight', 'marginBottom', 'plotLeft'], - noop: function() {}, - charts: [], - }; - })(); - (function(a) { - a.timers = []; - var E = a.charts, - D = a.doc, - H = a.win; - a.error = function(p, f) { - p = a.isNumber(p) - ? 'Highcharts error #' + p + ': www.highcharts.com/errors/' + p - : p; - if (f) throw Error(p); - H.console && console.log(p); - }; - a.Fx = function(a, f, l) { - this.options = f; - this.elem = a; - this.prop = l; - }; - a.Fx.prototype = { - dSetter: function() { - var a = this.paths[0], - f = this.paths[1], - l = [], - r = this.now, - n = a.length, - w; - if (1 === r) l = this.toD; - else if (n === f.length && 1 > r) - for (; n--; ) - (w = parseFloat(a[n])), - (l[n] = isNaN(w) ? f[n] : r * parseFloat(f[n] - w) + w); - else l = f; - this.elem.attr('d', l, null, !0); - }, - update: function() { - var a = this.elem, - f = this.prop, - l = this.now, - r = this.options.step; - if (this[f + 'Setter']) this[f + 'Setter'](); - else - a.attr - ? a.element && a.attr(f, l, null, !0) - : (a.style[f] = l + this.unit); - r && r.call(a, l, this); - }, - run: function(p, f, l) { - var r = this, - n = r.options, - w = function(a) { - return w.stopped ? !1 : r.step(a); - }, - u = - H.requestAnimationFrame || - function(a) { - setTimeout(a, 13); - }, - e = function() { - for (var h = 0; h < a.timers.length; h++) - a.timers[h]() || a.timers.splice(h--, 1); - a.timers.length && u(e); - }; - p === f - ? (delete n.curAnim[this.prop], - n.complete && - 0 === a.keys(n.curAnim).length && - n.complete.call(this.elem)) - : ((this.startTime = +new Date()), - (this.start = p), - (this.end = f), - (this.unit = l), - (this.now = this.start), - (this.pos = 0), - (w.elem = this.elem), - (w.prop = this.prop), - w() && 1 === a.timers.push(w) && u(e)); - }, - step: function(p) { - var f = +new Date(), - l, - r = this.options, - n = this.elem, - w = r.complete, - u = r.duration, - e = r.curAnim; - n.attr && !n.element - ? (p = !1) - : p || f >= u + this.startTime - ? ((this.now = this.end), - (this.pos = 1), - this.update(), - (l = e[this.prop] = !0), - a.objectEach(e, function(a) { - !0 !== a && (l = !1); - }), - l && w && w.call(n), - (p = !1)) - : ((this.pos = r.easing((f - this.startTime) / u)), - (this.now = this.start + (this.end - this.start) * this.pos), - this.update(), - (p = !0)); - return p; - }, - initPath: function(p, f, l) { - function r(a) { - var b, c; - for (k = a.length; k--; ) - (b = 'M' === a[k] || 'L' === a[k]), - (c = /[a-zA-Z]/.test(a[k + 3])), - b && - c && - a.splice(k + 1, 0, a[k + 1], a[k + 2], a[k + 1], a[k + 2]); - } - function n(a, b) { - for (; a.length < c; ) { - a[0] = b[c - a.length]; - var e = a.slice(0, d); - [].splice.apply(a, [0, 0].concat(e)); - z && - ((e = a.slice(a.length - d)), - [].splice.apply(a, [a.length, 0].concat(e)), - k--); - } - a[0] = 'M'; - } - function w(a, k) { - for (var e = (c - a.length) / d; 0 < e && e--; ) - (b = a.slice().splice(a.length / B - d, d * B)), - (b[0] = k[c - d - e * d]), - m && ((b[d - 6] = b[d - 2]), (b[d - 5] = b[d - 1])), - [].splice.apply(a, [a.length / B, 0].concat(b)), - z && e--; - } - f = f || ''; - var u, - e = p.startX, - h = p.endX, - m = -1 < f.indexOf('C'), - d = m ? 7 : 3, - c, - b, - k; - f = f.split(' '); - l = l.slice(); - var z = p.isArea, - B = z ? 2 : 1, - I; - m && (r(f), r(l)); - if (e && h) { - for (k = 0; k < e.length; k++) - if (e[k] === h[0]) { - u = k; - break; - } else if (e[0] === h[h.length - e.length + k]) { - u = k; - I = !0; - break; - } - void 0 === u && (f = []); - } - f.length && - a.isNumber(u) && - ((c = l.length + u * B * d), - I ? (n(f, l), w(l, f)) : (n(l, f), w(f, l))); - return [f, l]; - }, - }; - a.Fx.prototype.fillSetter = a.Fx.prototype.strokeSetter = function() { - this.elem.attr( - this.prop, - a.color(this.start).tweenTo(a.color(this.end), this.pos), - null, - !0, - ); - }; - a.extend = function(a, f) { - var l; - a || (a = {}); - for (l in f) a[l] = f[l]; - return a; - }; - a.merge = function() { - var p, - f = arguments, - l, - r = {}, - n = function(l, p) { - 'object' !== typeof l && (l = {}); - a.objectEach(p, function(e, h) { - !a.isObject(e, !0) || a.isClass(e) || a.isDOMElement(e) - ? (l[h] = p[h]) - : (l[h] = n(l[h] || {}, e)); - }); - return l; - }; - !0 === f[0] && ((r = f[1]), (f = Array.prototype.slice.call(f, 2))); - l = f.length; - for (p = 0; p < l; p++) r = n(r, f[p]); - return r; - }; - a.pInt = function(a, f) { - return parseInt(a, f || 10); - }; - a.isString = function(a) { - return 'string' === typeof a; - }; - a.isArray = function(a) { - a = Object.prototype.toString.call(a); - return '[object Array]' === a || '[object Array Iterator]' === a; - }; - a.isObject = function(p, f) { - return !!p && 'object' === typeof p && (!f || !a.isArray(p)); - }; - a.isDOMElement = function(p) { - return a.isObject(p) && 'number' === typeof p.nodeType; - }; - a.isClass = function(p) { - var f = p && p.constructor; - return !( - !a.isObject(p, !0) || - a.isDOMElement(p) || - !f || - !f.name || - 'Object' === f.name - ); - }; - a.isNumber = function(a) { - return ( - 'number' === typeof a && !isNaN(a) && Infinity > a && -Infinity < a - ); - }; - a.erase = function(a, f) { - for (var l = a.length; l--; ) - if (a[l] === f) { - a.splice(l, 1); - break; - } - }; - a.defined = function(a) { - return void 0 !== a && null !== a; - }; - a.attr = function(p, f, l) { - var r; - a.isString(f) - ? a.defined(l) - ? p.setAttribute(f, l) - : p && p.getAttribute && (r = p.getAttribute(f)) - : a.defined(f) && - a.isObject(f) && - a.objectEach(f, function(a, l) { - p.setAttribute(l, a); - }); - return r; - }; - a.splat = function(p) { - return a.isArray(p) ? p : [p]; - }; - a.syncTimeout = function(a, f, l) { - if (f) return setTimeout(a, f, l); - a.call(0, l); - }; - a.pick = function() { - var a = arguments, - f, - l, - r = a.length; - for (f = 0; f < r; f++) - if (((l = a[f]), void 0 !== l && null !== l)) return l; - }; - a.css = function(p, f) { - a.isMS && - !a.svg && - f && - void 0 !== f.opacity && - (f.filter = 'alpha(opacity\x3d' + 100 * f.opacity + ')'); - a.extend(p.style, f); - }; - a.createElement = function(p, f, l, r, n) { - p = D.createElement(p); - var w = a.css; - f && a.extend(p, f); - n && w(p, { padding: 0, border: 'none', margin: 0 }); - l && w(p, l); - r && r.appendChild(p); - return p; - }; - a.extendClass = function(p, f) { - var l = function() {}; - l.prototype = new p(); - a.extend(l.prototype, f); - return l; - }; - a.pad = function(a, f, l) { - return Array((f || 2) + 1 - String(a).length).join(l || 0) + a; - }; - a.relativeLength = function(a, f, l) { - return /%$/.test(a) - ? (f * parseFloat(a)) / 100 + (l || 0) - : parseFloat(a); - }; - a.wrap = function(a, f, l) { - var p = a[f]; - a[f] = function() { - var a = Array.prototype.slice.call(arguments), - f = arguments, - u = this; - u.proceed = function() { - p.apply(u, arguments.length ? arguments : f); - }; - a.unshift(p); - a = l.apply(this, a); - u.proceed = null; - return a; - }; - }; - a.getTZOffset = function(p) { - var f = a.Date; - return ( - 6e4 * - ((f.hcGetTimezoneOffset && f.hcGetTimezoneOffset(p)) || - f.hcTimezoneOffset || - 0) - ); - }; - a.dateFormat = function(p, f, l) { - if (!a.defined(f) || isNaN(f)) - return a.defaultOptions.lang.invalidDate || ''; - p = a.pick(p, '%Y-%m-%d %H:%M:%S'); - var r = a.Date, - n = new r(f - a.getTZOffset(f)), - w = n[r.hcGetHours](), - u = n[r.hcGetDay](), - e = n[r.hcGetDate](), - h = n[r.hcGetMonth](), - m = n[r.hcGetFullYear](), - d = a.defaultOptions.lang, - c = d.weekdays, - b = d.shortWeekdays, - k = a.pad, - r = a.extend( - { - a: b ? b[u] : c[u].substr(0, 3), - A: c[u], - d: k(e), - e: k(e, 2, ' '), - w: u, - b: d.shortMonths[h], - B: d.months[h], - m: k(h + 1), - y: m.toString().substr(2, 2), - Y: m, - H: k(w), - k: w, - I: k(w % 12 || 12), - l: w % 12 || 12, - M: k(n[r.hcGetMinutes]()), - p: 12 > w ? 'AM' : 'PM', - P: 12 > w ? 'am' : 'pm', - S: k(n.getSeconds()), - L: k(Math.round(f % 1e3), 3), - }, - a.dateFormats, - ); - a.objectEach(r, function(a, b) { - for (; -1 !== p.indexOf('%' + b); ) - p = p.replace('%' + b, 'function' === typeof a ? a(f) : a); - }); - return l ? p.substr(0, 1).toUpperCase() + p.substr(1) : p; - }; - a.formatSingle = function(p, f) { - var l = /\.([0-9])/, - r = a.defaultOptions.lang; - /f$/.test(p) - ? ((l = (l = p.match(l)) ? l[1] : -1), - null !== f && - (f = a.numberFormat( - f, - l, - r.decimalPoint, - -1 < p.indexOf(',') ? r.thousandsSep : '', - ))) - : (f = a.dateFormat(p, f)); - return f; - }; - a.format = function(p, f) { - for (var l = '{', r = !1, n, w, u, e, h = [], m; p; ) { - l = p.indexOf(l); - if (-1 === l) break; - n = p.slice(0, l); - if (r) { - n = n.split(':'); - w = n.shift().split('.'); - e = w.length; - m = f; - for (u = 0; u < e; u++) m && (m = m[w[u]]); - n.length && (m = a.formatSingle(n.join(':'), m)); - h.push(m); - } else h.push(n); - p = p.slice(l + 1); - l = (r = !r) ? '}' : '{'; - } - h.push(p); - return h.join(''); - }; - a.getMagnitude = function(a) { - return Math.pow(10, Math.floor(Math.log(a) / Math.LN10)); - }; - a.normalizeTickInterval = function(p, f, l, r, n) { - var w, - u = p; - l = a.pick(l, 1); - w = p / l; - f || - ((f = n - ? [1, 1.2, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] - : [1, 2, 2.5, 5, 10]), - !1 === r && - (1 === l - ? (f = a.grep(f, function(a) { - return 0 === a % 1; - })) - : 0.1 >= l && (f = [1 / l]))); - for ( - r = 0; - r < f.length && - !((u = f[r]), - (n && u * l >= p) || (!n && w <= (f[r] + (f[r + 1] || f[r])) / 2)); - r++ - ); - return (u = a.correctFloat( - u * l, - -Math.round(Math.log(0.001) / Math.LN10), - )); - }; - a.stableSort = function(a, f) { - var l = a.length, - p, - n; - for (n = 0; n < l; n++) a[n].safeI = n; - a.sort(function(a, n) { - p = f(a, n); - return 0 === p ? a.safeI - n.safeI : p; - }); - for (n = 0; n < l; n++) delete a[n].safeI; - }; - a.arrayMin = function(a) { - for (var f = a.length, l = a[0]; f--; ) a[f] < l && (l = a[f]); - return l; - }; - a.arrayMax = function(a) { - for (var f = a.length, l = a[0]; f--; ) a[f] > l && (l = a[f]); - return l; - }; - a.destroyObjectProperties = function(p, f) { - a.objectEach(p, function(a, r) { - a && a !== f && a.destroy && a.destroy(); - delete p[r]; - }); - }; - a.discardElement = function(p) { - var f = a.garbageBin; - f || (f = a.createElement('div')); - p && f.appendChild(p); - f.innerHTML = ''; - }; - a.correctFloat = function(a, f) { - return parseFloat(a.toPrecision(f || 14)); - }; - a.setAnimation = function(p, f) { - f.renderer.globalAnimation = a.pick(p, f.options.chart.animation, !0); - }; - a.animObject = function(p) { - return a.isObject(p) ? a.merge(p) : { duration: p ? 500 : 0 }; - }; - a.timeUnits = { - millisecond: 1, - second: 1e3, - minute: 6e4, - hour: 36e5, - day: 864e5, - week: 6048e5, - month: 24192e5, - year: 314496e5, - }; - a.numberFormat = function(p, f, l, r) { - p = +p || 0; - f = +f; - var n = a.defaultOptions.lang, - w = (p.toString().split('.')[1] || '').split('e')[0].length, - u, - e, - h = p.toString().split('e'); - -1 === f - ? (f = Math.min(w, 20)) - : a.isNumber(f) - ? f && - h[1] && - 0 > h[1] && - ((u = f + +h[1]), - 0 <= u - ? ((h[0] = (+h[0]).toExponential(u).split('e')[0]), (f = u)) - : ((h[0] = h[0].split('.')[0] || 0), - (p = 20 > f ? (h[0] * Math.pow(10, h[1])).toFixed(f) : 0), - (h[1] = 0))) - : (f = 2); - e = ( - Math.abs(h[1] ? h[0] : p) + Math.pow(10, -Math.max(f, w) - 1) - ).toFixed(f); - w = String(a.pInt(e)); - u = 3 < w.length ? w.length % 3 : 0; - l = a.pick(l, n.decimalPoint); - r = a.pick(r, n.thousandsSep); - p = (0 > p ? '-' : '') + (u ? w.substr(0, u) + r : ''); - p += w.substr(u).replace(/(\d{3})(?=\d)/g, '$1' + r); - f && (p += l + e.slice(-f)); - h[1] && 0 !== +p && (p += 'e' + h[1]); - return p; - }; - Math.easeInOutSine = function(a) { - return -0.5 * (Math.cos(Math.PI * a) - 1); - }; - a.getStyle = function(p, f, l) { - if ('width' === f) - return ( - Math.min(p.offsetWidth, p.scrollWidth) - - a.getStyle(p, 'padding-left') - - a.getStyle(p, 'padding-right') - ); - if ('height' === f) - return ( - Math.min(p.offsetHeight, p.scrollHeight) - - a.getStyle(p, 'padding-top') - - a.getStyle(p, 'padding-bottom') - ); - H.getComputedStyle || a.error(27, !0); - if ((p = H.getComputedStyle(p, void 0))) - (p = p.getPropertyValue(f)), - a.pick(l, 'opacity' !== f) && (p = a.pInt(p)); - return p; - }; - a.inArray = function(p, f) { - return (a.indexOfPolyfill || Array.prototype.indexOf).call(f, p); - }; - a.grep = function(p, f) { - return (a.filterPolyfill || Array.prototype.filter).call(p, f); - }; - a.find = Array.prototype.find - ? function(a, f) { - return a.find(f); - } - : function(a, f) { - var l, - r = a.length; - for (l = 0; l < r; l++) if (f(a[l], l)) return a[l]; - }; - a.map = function(a, f) { - for (var l = [], r = 0, n = a.length; r < n; r++) - l[r] = f.call(a[r], a[r], r, a); - return l; - }; - a.keys = function(p) { - return (a.keysPolyfill || Object.keys).call(void 0, p); - }; - a.reduce = function(p, f, l) { - return (a.reducePolyfill || Array.prototype.reduce).call(p, f, l); - }; - a.offset = function(a) { - var f = D.documentElement; - a = a.parentElement ? a.getBoundingClientRect() : { top: 0, left: 0 }; - return { - top: a.top + (H.pageYOffset || f.scrollTop) - (f.clientTop || 0), - left: a.left + (H.pageXOffset || f.scrollLeft) - (f.clientLeft || 0), - }; - }; - a.stop = function(p, f) { - for (var l = a.timers.length; l--; ) - a.timers[l].elem !== p || - (f && f !== a.timers[l].prop) || - (a.timers[l].stopped = !0); - }; - a.each = function(p, f, l) { - return (a.forEachPolyfill || Array.prototype.forEach).call(p, f, l); - }; - a.objectEach = function(a, f, l) { - for (var r in a) a.hasOwnProperty(r) && f.call(l, a[r], r, a); - }; - a.addEvent = function(p, f, l) { - var r, - n, - w = p.addEventListener || a.addEventListenerPolyfill; - p.hcEvents && - !Object.prototype.hasOwnProperty.call(p, 'hcEvents') && - ((n = {}), - a.objectEach(p.hcEvents, function(a, e) { - n[e] = a.slice(0); - }), - (p.hcEvents = n)); - r = p.hcEvents = p.hcEvents || {}; - w && w.call(p, f, l, !1); - r[f] || (r[f] = []); - r[f].push(l); - return function() { - a.removeEvent(p, f, l); - }; - }; - a.removeEvent = function(p, f, l) { - function r(e, m) { - var d = p.removeEventListener || a.removeEventListenerPolyfill; - d && d.call(p, e, m, !1); - } - function n() { - var e, m; - p.nodeName && - (f ? ((e = {}), (e[f] = !0)) : (e = u), - a.objectEach(e, function(a, c) { - if (u[c]) for (m = u[c].length; m--; ) r(c, u[c][m]); - })); - } - var w, - u = p.hcEvents, - e; - u && - (f - ? ((w = u[f] || []), - l - ? ((e = a.inArray(l, w)), - -1 < e && (w.splice(e, 1), (u[f] = w)), - r(f, l)) - : (n(), (u[f] = []))) - : (n(), (p.hcEvents = {}))); - }; - a.fireEvent = function(p, f, l, r) { - var n; - n = p.hcEvents; - var w, u; - l = l || {}; - if (D.createEvent && (p.dispatchEvent || p.fireEvent)) - (n = D.createEvent('Events')), - n.initEvent(f, !0, !0), - a.extend(n, l), - p.dispatchEvent ? p.dispatchEvent(n) : p.fireEvent(f, n); - else if (n) - for ( - n = n[f] || [], - w = n.length, - l.target || - a.extend(l, { - preventDefault: function() { - l.defaultPrevented = !0; - }, - target: p, - type: f, - }), - f = 0; - f < w; - f++ - ) - (u = n[f]) && !1 === u.call(p, l) && l.preventDefault(); - r && !l.defaultPrevented && r(l); - }; - a.animate = function(p, f, l) { - var r, - n = '', - w, - u, - e; - a.isObject(l) || - ((e = arguments), - (l = { duration: e[2], easing: e[3], complete: e[4] })); - a.isNumber(l.duration) || (l.duration = 400); - l.easing = - 'function' === typeof l.easing - ? l.easing - : Math[l.easing] || Math.easeInOutSine; - l.curAnim = a.merge(f); - a.objectEach(f, function(e, m) { - a.stop(p, m); - u = new a.Fx(p, l, m); - w = null; - 'd' === m - ? ((u.paths = u.initPath(p, p.d, f.d)), - (u.toD = f.d), - (r = 0), - (w = 1)) - : p.attr - ? (r = p.attr(m)) - : ((r = parseFloat(a.getStyle(p, m)) || 0), - 'opacity' !== m && (n = 'px')); - w || (w = e); - w && w.match && w.match('px') && (w = w.replace(/px/g, '')); - u.run(r, w, n); - }); - }; - a.seriesType = function(p, f, l, r, n) { - var w = a.getOptions(), - u = a.seriesTypes; - w.plotOptions[p] = a.merge(w.plotOptions[f], l); - u[p] = a.extendClass(u[f] || function() {}, r); - u[p].prototype.type = p; - n && (u[p].prototype.pointClass = a.extendClass(a.Point, n)); - return u[p]; - }; - a.uniqueKey = (function() { - var a = Math.random() - .toString(36) - .substring(2, 9), - f = 0; - return function() { - return 'highcharts-' + a + '-' + f++; - }; - })(); - H.jQuery && - (H.jQuery.fn.highcharts = function() { - var p = [].slice.call(arguments); - if (this[0]) - return p[0] - ? (new a[a.isString(p[0]) ? p.shift() : 'Chart']( - this[0], - p[0], - p[1], - ), - this) - : E[a.attr(this[0], 'data-highcharts-chart')]; - }); - })(M); - (function(a) { - var E = a.each, - D = a.isNumber, - H = a.map, - p = a.merge, - f = a.pInt; - a.Color = function(l) { - if (!(this instanceof a.Color)) return new a.Color(l); - this.init(l); - }; - a.Color.prototype = { - parsers: [ - { - regex: /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]?(?:\.[0-9]+)?)\s*\)/, - parse: function(a) { - return [f(a[1]), f(a[2]), f(a[3]), parseFloat(a[4], 10)]; - }, - }, - { - regex: /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/, - parse: function(a) { - return [f(a[1]), f(a[2]), f(a[3]), 1]; - }, - }, - ], - names: { - none: 'rgba(255,255,255,0)', - white: '#ffffff', - black: '#000000', - }, - init: function(l) { - var f, n, w, u; - if ( - (this.input = l = - this.names[l && l.toLowerCase ? l.toLowerCase() : ''] || l) && - l.stops - ) - this.stops = H(l.stops, function(e) { - return new a.Color(e[1]); - }); - else if ( - (l && - l.charAt && - '#' === l.charAt() && - ((f = l.length), - (l = parseInt(l.substr(1), 16)), - 7 === f - ? (n = [(l & 16711680) >> 16, (l & 65280) >> 8, l & 255, 1]) - : 4 === f && - (n = [ - ((l & 3840) >> 4) | ((l & 3840) >> 8), - ((l & 240) >> 4) | (l & 240), - ((l & 15) << 4) | (l & 15), - 1, - ])), - !n) - ) - for (w = this.parsers.length; w-- && !n; ) - (u = this.parsers[w]), (f = u.regex.exec(l)) && (n = u.parse(f)); - this.rgba = n || []; - }, - get: function(a) { - var f = this.input, - n = this.rgba, - l; - this.stops - ? ((l = p(f)), - (l.stops = [].concat(l.stops)), - E(this.stops, function(n, e) { - l.stops[e] = [l.stops[e][0], n.get(a)]; - })) - : (l = - n && D(n[0]) - ? 'rgb' === a || (!a && 1 === n[3]) - ? 'rgb(' + n[0] + ',' + n[1] + ',' + n[2] + ')' - : 'a' === a - ? n[3] - : 'rgba(' + n.join(',') + ')' - : f); - return l; - }, - brighten: function(a) { - var l, - n = this.rgba; - if (this.stops) - E(this.stops, function(n) { - n.brighten(a); - }); - else if (D(a) && 0 !== a) - for (l = 0; 3 > l; l++) - (n[l] += f(255 * a)), - 0 > n[l] && (n[l] = 0), - 255 < n[l] && (n[l] = 255); - return this; - }, - setOpacity: function(a) { - this.rgba[3] = a; - return this; - }, - tweenTo: function(a, f) { - var n = this.rgba, - l = a.rgba; - l.length && n && n.length - ? ((a = 1 !== l[3] || 1 !== n[3]), - (f = - (a ? 'rgba(' : 'rgb(') + - Math.round(l[0] + (n[0] - l[0]) * (1 - f)) + - ',' + - Math.round(l[1] + (n[1] - l[1]) * (1 - f)) + - ',' + - Math.round(l[2] + (n[2] - l[2]) * (1 - f)) + - (a ? ',' + (l[3] + (n[3] - l[3]) * (1 - f)) : '') + - ')')) - : (f = a.input || 'none'); - return f; - }, - }; - a.color = function(l) { - return new a.Color(l); - }; - })(M); - (function(a) { - var E, - D, - H = a.addEvent, - p = a.animate, - f = a.attr, - l = a.charts, - r = a.color, - n = a.css, - w = a.createElement, - u = a.defined, - e = a.deg2rad, - h = a.destroyObjectProperties, - m = a.doc, - d = a.each, - c = a.extend, - b = a.erase, - k = a.grep, - z = a.hasTouch, - B = a.inArray, - I = a.isArray, - x = a.isFirefox, - K = a.isMS, - t = a.isObject, - C = a.isString, - N = a.isWebKit, - q = a.merge, - A = a.noop, - F = a.objectEach, - G = a.pick, - g = a.pInt, - v = a.removeEvent, - Q = a.stop, - L = a.svg, - P = a.SVG_NS, - J = a.symbolSizes, - R = a.win; - E = a.SVGElement = function() { - return this; - }; - c(E.prototype, { - opacity: 1, - SVG_NS: P, - textProps: 'direction fontSize fontWeight fontFamily fontStyle color lineHeight width textAlign textDecoration textOverflow textOutline'.split( - ' ', - ), - init: function(a, g) { - this.element = 'span' === g ? w(g) : m.createElementNS(this.SVG_NS, g); - this.renderer = a; - }, - animate: function(y, g, b) { - g = a.animObject(G(g, this.renderer.globalAnimation, !0)); - 0 !== g.duration - ? (b && (g.complete = b), p(this, y, g)) - : (this.attr(y, null, b), g.step && g.step.call(this)); - return this; - }, - colorGradient: function(y, g, b) { - var v = this.renderer, - c, - O, - k, - e, - z, - h, - m, - L, - A, - J, - t = [], - x; - y.radialGradient - ? (O = 'radialGradient') - : y.linearGradient && (O = 'linearGradient'); - O && - ((k = y[O]), - (z = v.gradients), - (m = y.stops), - (J = b.radialReference), - I(k) && - (y[O] = k = { - x1: k[0], - y1: k[1], - x2: k[2], - y2: k[3], - gradientUnits: 'userSpaceOnUse', - }), - 'radialGradient' === O && - J && - !u(k.gradientUnits) && - ((e = k), - (k = q(k, v.getRadialAttr(J, e), { - gradientUnits: 'userSpaceOnUse', - }))), - F(k, function(a, y) { - 'id' !== y && t.push(y, a); - }), - F(m, function(a) { - t.push(a); - }), - (t = t.join(',')), - z[t] - ? (J = z[t].attr('id')) - : ((k.id = J = a.uniqueKey()), - (z[t] = h = v - .createElement(O) - .attr(k) - .add(v.defs)), - (h.radAttr = e), - (h.stops = []), - d(m, function(y) { - 0 === y[1].indexOf('rgba') - ? ((c = a.color(y[1])), (L = c.get('rgb')), (A = c.get('a'))) - : ((L = y[1]), (A = 1)); - y = v - .createElement('stop') - .attr({ offset: y[0], 'stop-color': L, 'stop-opacity': A }) - .add(h); - h.stops.push(y); - })), - (x = 'url(' + v.url + '#' + J + ')'), - b.setAttribute(g, x), - (b.gradient = t), - (y.toString = function() { - return x; - })); - }, - applyTextOutline: function(y) { - var g = this.element, - v, - c, - k, - q, - e; - -1 !== y.indexOf('contrast') && - (y = y.replace(/contrast/g, this.renderer.getContrast(g.style.fill))); - y = y.split(' '); - c = y[y.length - 1]; - if ((k = y[0]) && 'none' !== k && a.svg) { - this.fakeTS = !0; - y = [].slice.call(g.getElementsByTagName('tspan')); - this.ySetter = this.xSetter; - k = k.replace(/(^[\d\.]+)(.*?)$/g, function(a, y, g) { - return 2 * y + g; - }); - for (e = y.length; e--; ) - (v = y[e]), - 'highcharts-text-outline' === v.getAttribute('class') && - b(y, g.removeChild(v)); - q = g.firstChild; - d(y, function(a, y) { - 0 === y && - (a.setAttribute('x', g.getAttribute('x')), - (y = g.getAttribute('y')), - a.setAttribute('y', y || 0), - null === y && g.setAttribute('y', 0)); - a = a.cloneNode(1); - f(a, { - class: 'highcharts-text-outline', - fill: c, - stroke: c, - 'stroke-width': k, - 'stroke-linejoin': 'round', - }); - g.insertBefore(a, q); - }); - } - }, - attr: function(a, g, b, v) { - var y, - c = this.element, - k, - d = this, - O, - q; - 'string' === typeof a && - void 0 !== g && - ((y = a), (a = {}), (a[y] = g)); - 'string' === typeof a - ? (d = (this[a + 'Getter'] || this._defaultGetter).call(this, a, c)) - : (F( - a, - function(y, g) { - O = !1; - v || Q(this, g); - this.symbolName && - /^(x|y|width|height|r|start|end|innerR|anchorX|anchorY)$/.test( - g, - ) && - (k || (this.symbolAttr(a), (k = !0)), (O = !0)); - !this.rotation || - ('x' !== g && 'y' !== g) || - (this.doTransform = !0); - O || - ((q = this[g + 'Setter'] || this._defaultSetter), - q.call(this, y, g, c), - this.shadows && - /^(width|height|visibility|x|y|d|transform|cx|cy|r)$/.test( - g, - ) && - this.updateShadows(g, y, q)); - }, - this, - ), - this.afterSetters()); - b && b(); - return d; - }, - afterSetters: function() { - this.doTransform && (this.updateTransform(), (this.doTransform = !1)); - }, - updateShadows: function(a, g, b) { - for (var y = this.shadows, v = y.length; v--; ) - b.call( - y[v], - 'height' === a - ? Math.max(g - (y[v].cutHeight || 0), 0) - : 'd' === a - ? this.d - : g, - a, - y[v], - ); - }, - addClass: function(a, g) { - var y = this.attr('class') || ''; - -1 === y.indexOf(a) && - (g || (a = (y + (y ? ' ' : '') + a).replace(' ', ' ')), - this.attr('class', a)); - return this; - }, - hasClass: function(a) { - return -1 !== B(a, (this.attr('class') || '').split(' ')); - }, - removeClass: function(a) { - return this.attr('class', (this.attr('class') || '').replace(a, '')); - }, - symbolAttr: function(a) { - var y = this; - d( - 'x y r start end width height innerR anchorX anchorY'.split(' '), - function(g) { - y[g] = G(a[g], y[g]); - }, - ); - y.attr({ - d: y.renderer.symbols[y.symbolName](y.x, y.y, y.width, y.height, y), - }); - }, - clip: function(a) { - return this.attr( - 'clip-path', - a ? 'url(' + this.renderer.url + '#' + a.id + ')' : 'none', - ); - }, - crisp: function(a, g) { - var y; - g = g || a.strokeWidth || 0; - y = (Math.round(g) % 2) / 2; - a.x = Math.floor(a.x || this.x || 0) + y; - a.y = Math.floor(a.y || this.y || 0) + y; - a.width = Math.floor((a.width || this.width || 0) - 2 * y); - a.height = Math.floor((a.height || this.height || 0) - 2 * y); - u(a.strokeWidth) && (a.strokeWidth = g); - return a; - }, - css: function(a) { - var y = this.styles, - b = {}, - v = this.element, - k, - d = '', - q, - e = !y, - z = ['textOutline', 'textOverflow', 'width']; - a && a.color && (a.fill = a.color); - y && - F(a, function(a, g) { - a !== y[g] && ((b[g] = a), (e = !0)); - }); - e && - (y && (a = c(y, b)), - (k = this.textWidth = - a && - a.width && - 'auto' !== a.width && - 'text' === v.nodeName.toLowerCase() && - g(a.width)), - (this.styles = a), - k && !L && this.renderer.forExport && delete a.width, - K && !L - ? n(this.element, a) - : ((q = function(a, y) { - return '-' + y.toLowerCase(); - }), - F(a, function(a, y) { - -1 === B(y, z) && - (d += y.replace(/([A-Z])/g, q) + ':' + a + ';'); - }), - d && f(v, 'style', d)), - this.added && - ('text' === this.element.nodeName && this.renderer.buildText(this), - a && a.textOutline && this.applyTextOutline(a.textOutline))); - return this; - }, - strokeWidth: function() { - return this['stroke-width'] || 0; - }, - on: function(a, g) { - var y = this, - b = y.element; - z && 'click' === a - ? ((b.ontouchstart = function(a) { - y.touchEventFired = Date.now(); - a.preventDefault(); - g.call(b, a); - }), - (b.onclick = function(a) { - (-1 === R.navigator.userAgent.indexOf('Android') || - 1100 < Date.now() - (y.touchEventFired || 0)) && - g.call(b, a); - })) - : (b['on' + a] = g); - return this; - }, - setRadialReference: function(a) { - var y = this.renderer.gradients[this.element.gradient]; - this.element.radialReference = a; - y && y.radAttr && y.animate(this.renderer.getRadialAttr(a, y.radAttr)); - return this; - }, - translate: function(a, g) { - return this.attr({ translateX: a, translateY: g }); - }, - invert: function(a) { - this.inverted = a; - this.updateTransform(); - return this; - }, - updateTransform: function() { - var a = this.translateX || 0, - g = this.translateY || 0, - b = this.scaleX, - v = this.scaleY, - c = this.inverted, - k = this.rotation, - d = this.matrix, - q = this.element; - c && ((a += this.width), (g += this.height)); - a = ['translate(' + a + ',' + g + ')']; - u(d) && a.push('matrix(' + d.join(',') + ')'); - c - ? a.push('rotate(90) scale(-1,1)') - : k && - a.push( - 'rotate(' + - k + - ' ' + - G(this.rotationOriginX, q.getAttribute('x'), 0) + - ' ' + - G(this.rotationOriginY, q.getAttribute('y') || 0) + - ')', - ); - (u(b) || u(v)) && a.push('scale(' + G(b, 1) + ' ' + G(v, 1) + ')'); - a.length && q.setAttribute('transform', a.join(' ')); - }, - toFront: function() { - var a = this.element; - a.parentNode.appendChild(a); - return this; - }, - align: function(a, g, v) { - var y, - c, - k, - d, - q = {}; - c = this.renderer; - k = c.alignedObjects; - var e, O; - if (a) { - if ( - ((this.alignOptions = a), (this.alignByTranslate = g), !v || C(v)) - ) - (this.alignTo = y = v || 'renderer'), - b(k, this), - k.push(this), - (v = null); - } else - (a = this.alignOptions), - (g = this.alignByTranslate), - (y = this.alignTo); - v = G(v, c[y], c); - y = a.align; - c = a.verticalAlign; - k = (v.x || 0) + (a.x || 0); - d = (v.y || 0) + (a.y || 0); - 'right' === y ? (e = 1) : 'center' === y && (e = 2); - e && (k += (v.width - (a.width || 0)) / e); - q[g ? 'translateX' : 'x'] = Math.round(k); - 'bottom' === c ? (O = 1) : 'middle' === c && (O = 2); - O && (d += (v.height - (a.height || 0)) / O); - q[g ? 'translateY' : 'y'] = Math.round(d); - this[this.placed ? 'animate' : 'attr'](q); - this.placed = !0; - this.alignAttr = q; - return this; - }, - getBBox: function(a, g) { - var y, - b = this.renderer, - v, - k = this.element, - q = this.styles, - O, - z = this.textStr, - h, - m = b.cache, - L = b.cacheKeys, - A; - g = G(g, this.rotation); - v = g * e; - O = q && q.fontSize; - u(z) && - ((A = z.toString()), - -1 === A.indexOf('\x3c') && (A = A.replace(/[0-9]/g, '0')), - (A += ['', g || 0, O, q && q.width, q && q.textOverflow].join())); - A && !a && (y = m[A]); - if (!y) { - if (k.namespaceURI === this.SVG_NS || b.forExport) { - try { - (h = - this.fakeTS && - function(a) { - d(k.querySelectorAll('.highcharts-text-outline'), function( - y, - ) { - y.style.display = a; - }); - }) && h('none'), - (y = k.getBBox - ? c({}, k.getBBox()) - : { width: k.offsetWidth, height: k.offsetHeight }), - h && h(''); - } catch (W) {} - if (!y || 0 > y.width) y = { width: 0, height: 0 }; - } else y = this.htmlGetBBox(); - b.isSVG && - ((a = y.width), - (b = y.height), - q && - '11px' === q.fontSize && - 17 === Math.round(b) && - (y.height = b = 14), - g && - ((y.width = - Math.abs(b * Math.sin(v)) + Math.abs(a * Math.cos(v))), - (y.height = - Math.abs(b * Math.cos(v)) + Math.abs(a * Math.sin(v))))); - if (A && 0 < y.height) { - for (; 250 < L.length; ) delete m[L.shift()]; - m[A] || L.push(A); - m[A] = y; - } - } - return y; - }, - show: function(a) { - return this.attr({ visibility: a ? 'inherit' : 'visible' }); - }, - hide: function() { - return this.attr({ visibility: 'hidden' }); - }, - fadeOut: function(a) { - var y = this; - y.animate( - { opacity: 0 }, - { - duration: a || 150, - complete: function() { - y.attr({ y: -9999 }); - }, - }, - ); - }, - add: function(a) { - var y = this.renderer, - g = this.element, - b; - a && (this.parentGroup = a); - this.parentInverted = a && a.inverted; - void 0 !== this.textStr && y.buildText(this); - this.added = !0; - if (!a || a.handleZ || this.zIndex) b = this.zIndexSetter(); - b || (a ? a.element : y.box).appendChild(g); - if (this.onAdd) this.onAdd(); - return this; - }, - safeRemoveChild: function(a) { - var y = a.parentNode; - y && y.removeChild(a); - }, - destroy: function() { - var a = this, - g = a.element || {}, - v = a.renderer.isSVG && 'SPAN' === g.nodeName && a.parentGroup, - c = g.ownerSVGElement; - g.onclick = g.onmouseout = g.onmouseover = g.onmousemove = g.point = null; - Q(a); - a.clipPath && - c && - (d(c.querySelectorAll('[clip-path],[CLIP-PATH]'), function(g) { - g - .getAttribute('clip-path') - .match(RegExp('[("]#' + a.clipPath.element.id + '[)"]')) && - g.removeAttribute('clip-path'); - }), - (a.clipPath = a.clipPath.destroy())); - if (a.stops) { - for (c = 0; c < a.stops.length; c++) - a.stops[c] = a.stops[c].destroy(); - a.stops = null; - } - a.safeRemoveChild(g); - for (a.destroyShadows(); v && v.div && 0 === v.div.childNodes.length; ) - (g = v.parentGroup), a.safeRemoveChild(v.div), delete v.div, (v = g); - a.alignTo && b(a.renderer.alignedObjects, a); - F(a, function(g, y) { - delete a[y]; - }); - return null; - }, - shadow: function(a, g, b) { - var y = [], - v, - c, - k = this.element, - d, - q, - e, - z; - if (!a) this.destroyShadows(); - else if (!this.shadows) { - q = G(a.width, 3); - e = (a.opacity || 0.15) / q; - z = this.parentInverted - ? '(-1,-1)' - : '(' + G(a.offsetX, 1) + ', ' + G(a.offsetY, 1) + ')'; - for (v = 1; v <= q; v++) - (c = k.cloneNode(0)), - (d = 2 * q + 1 - 2 * v), - f(c, { - isShadow: 'true', - stroke: a.color || '#000000', - 'stroke-opacity': e * v, - 'stroke-width': d, - transform: 'translate' + z, - fill: 'none', - }), - b && - (f(c, 'height', Math.max(f(c, 'height') - d, 0)), - (c.cutHeight = d)), - g - ? g.element.appendChild(c) - : k.parentNode && k.parentNode.insertBefore(c, k), - y.push(c); - this.shadows = y; - } - return this; - }, - destroyShadows: function() { - d( - this.shadows || [], - function(a) { - this.safeRemoveChild(a); - }, - this, - ); - this.shadows = void 0; - }, - xGetter: function(a) { - 'circle' === this.element.nodeName && - ('x' === a ? (a = 'cx') : 'y' === a && (a = 'cy')); - return this._defaultGetter(a); - }, - _defaultGetter: function(a) { - a = G( - this[a + 'Value'], - this[a], - this.element ? this.element.getAttribute(a) : null, - 0, - ); - /^[\-0-9\.]+$/.test(a) && (a = parseFloat(a)); - return a; - }, - dSetter: function(a, g, b) { - a && a.join && (a = a.join(' ')); - /(NaN| {2}|^$)/.test(a) && (a = 'M 0 0'); - this[g] !== a && (b.setAttribute(g, a), (this[g] = a)); - }, - dashstyleSetter: function(a) { - var b, - v = this['stroke-width']; - 'inherit' === v && (v = 1); - if ((a = a && a.toLowerCase())) { - a = a - .replace('shortdashdotdot', '3,1,1,1,1,1,') - .replace('shortdashdot', '3,1,1,1') - .replace('shortdot', '1,1,') - .replace('shortdash', '3,1,') - .replace('longdash', '8,3,') - .replace(/dot/g, '1,3,') - .replace('dash', '4,3,') - .replace(/,$/, '') - .split(','); - for (b = a.length; b--; ) a[b] = g(a[b]) * v; - a = a.join(',').replace(/NaN/g, 'none'); - this.element.setAttribute('stroke-dasharray', a); - } - }, - alignSetter: function(a) { - this.alignValue = a; - this.element.setAttribute( - 'text-anchor', - { left: 'start', center: 'middle', right: 'end' }[a], - ); - }, - opacitySetter: function(a, g, b) { - this[g] = a; - b.setAttribute(g, a); - }, - titleSetter: function(a) { - var g = this.element.getElementsByTagName('title')[0]; - g || - ((g = m.createElementNS(this.SVG_NS, 'title')), - this.element.appendChild(g)); - g.firstChild && g.removeChild(g.firstChild); - g.appendChild( - m.createTextNode(String(G(a), '').replace(/<[^>]*>/g, '')), - ); - }, - textSetter: function(a) { - a !== this.textStr && - (delete this.bBox, - (this.textStr = a), - this.added && this.renderer.buildText(this)); - }, - fillSetter: function(a, g, b) { - 'string' === typeof a - ? b.setAttribute(g, a) - : a && this.colorGradient(a, g, b); - }, - visibilitySetter: function(a, g, b) { - 'inherit' === a - ? b.removeAttribute(g) - : this[g] !== a && b.setAttribute(g, a); - this[g] = a; - }, - zIndexSetter: function(a, b) { - var v = this.renderer, - y = this.parentGroup, - c = (y || v).element || v.box, - k, - d = this.element, - q, - e, - v = c === v.box; - k = this.added; - var z; - u(a) && - ((d.zIndex = a), (a = +a), this[b] === a && (k = !1), (this[b] = a)); - if (k) { - (a = this.zIndex) && y && (y.handleZ = !0); - b = c.childNodes; - for (z = b.length - 1; 0 <= z && !q; z--) - if (((y = b[z]), (k = y.zIndex), (e = !u(k)), y !== d)) - if (0 > a && e && !v && !z) c.insertBefore(d, b[z]), (q = !0); - else if (g(k) <= a || (e && (!u(a) || 0 <= a))) - c.insertBefore(d, b[z + 1] || null), (q = !0); - q || (c.insertBefore(d, b[v ? 3 : 0] || null), (q = !0)); - } - return q; - }, - _defaultSetter: function(a, g, b) { - b.setAttribute(g, a); - }, - }); - E.prototype.yGetter = E.prototype.xGetter; - E.prototype.translateXSetter = E.prototype.translateYSetter = E.prototype.rotationSetter = E.prototype.verticalAlignSetter = E.prototype.rotationOriginXSetter = E.prototype.rotationOriginYSetter = E.prototype.scaleXSetter = E.prototype.scaleYSetter = E.prototype.matrixSetter = function( - a, - g, - ) { - this[g] = a; - this.doTransform = !0; - }; - E.prototype['stroke-widthSetter'] = E.prototype.strokeSetter = function( - a, - g, - b, - ) { - this[g] = a; - this.stroke && this['stroke-width'] - ? (E.prototype.fillSetter.call(this, this.stroke, 'stroke', b), - b.setAttribute('stroke-width', this['stroke-width']), - (this.hasStroke = !0)) - : 'stroke-width' === g && - 0 === a && - this.hasStroke && - (b.removeAttribute('stroke'), (this.hasStroke = !1)); - }; - D = a.SVGRenderer = function() { - this.init.apply(this, arguments); - }; - c(D.prototype, { - Element: E, - SVG_NS: P, - init: function(a, g, b, v, c, k) { - var y; - v = this.createElement('svg') - .attr({ version: '1.1', class: 'highcharts-root' }) - .css(this.getStyle(v)); - y = v.element; - a.appendChild(y); - f(a, 'dir', 'ltr'); - -1 === a.innerHTML.indexOf('xmlns') && f(y, 'xmlns', this.SVG_NS); - this.isSVG = !0; - this.box = y; - this.boxWrapper = v; - this.alignedObjects = []; - this.url = - (x || N) && m.getElementsByTagName('base').length - ? R.location.href - .replace(/#.*?$/, '') - .replace(/<[^>]*>/g, '') - .replace(/([\('\)])/g, '\\$1') - .replace(/ /g, '%20') - : ''; - this.createElement('desc') - .add() - .element.appendChild( - m.createTextNode('Created with Highcharts 6.0.4'), - ); - this.defs = this.createElement('defs').add(); - this.allowHTML = k; - this.forExport = c; - this.gradients = {}; - this.cache = {}; - this.cacheKeys = []; - this.imgCount = 0; - this.setSize(g, b, !1); - var d; - x && - a.getBoundingClientRect && - ((g = function() { - n(a, { left: 0, top: 0 }); - d = a.getBoundingClientRect(); - n(a, { - left: Math.ceil(d.left) - d.left + 'px', - top: Math.ceil(d.top) - d.top + 'px', - }); - }), - g(), - (this.unSubPixelFix = H(R, 'resize', g))); - }, - getStyle: function(a) { - return (this.style = c( - { - fontFamily: - '"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif', - fontSize: '12px', - }, - a, - )); - }, - setStyle: function(a) { - this.boxWrapper.css(this.getStyle(a)); - }, - isHidden: function() { - return !this.boxWrapper.getBBox().width; - }, - destroy: function() { - var a = this.defs; - this.box = null; - this.boxWrapper = this.boxWrapper.destroy(); - h(this.gradients || {}); - this.gradients = null; - a && (this.defs = a.destroy()); - this.unSubPixelFix && this.unSubPixelFix(); - return (this.alignedObjects = null); - }, - createElement: function(a) { - var g = new this.Element(); - g.init(this, a); - return g; - }, - draw: A, - getRadialAttr: function(a, g) { - return { - cx: a[0] - a[2] / 2 + g.cx * a[2], - cy: a[1] - a[2] / 2 + g.cy * a[2], - r: g.r * a[2], - }; - }, - getSpanWidth: function(a, g) { - var b = a.getBBox(!0).width; - !L && - this.forExport && - (b = this.measureSpanWidth(g.firstChild.data, a.styles)); - return b; - }, - applyEllipsis: function(a, g, b, v) { - var c = a.rotation, - y = b, - k, - d = 0, - q = b.length, - e = function(a) { - g.removeChild(g.firstChild); - a && g.appendChild(m.createTextNode(a)); - }, - z; - a.rotation = 0; - y = this.getSpanWidth(a, g); - if ((z = y > v)) { - for (; d <= q; ) - (k = Math.ceil((d + q) / 2)), - (y = b.substring(0, k) + '\u2026'), - e(y), - (y = this.getSpanWidth(a, g)), - d === q ? (d = q + 1) : y > v ? (q = k - 1) : (d = k); - 0 === q && e(''); - } - a.rotation = c; - return z; - }, - escapes: { - '\x26': '\x26amp;', - '\x3c': '\x26lt;', - '\x3e': '\x26gt;', - "'": '\x26#39;', - '"': '\x26quot;', - }, - buildText: function(a) { - var b = a.element, - v = this, - c = v.forExport, - y = G(a.textStr, '').toString(), - q = -1 !== y.indexOf('\x3c'), - e = b.childNodes, - z, - h, - A, - J, - t = f(b, 'x'), - x = a.styles, - B = a.textWidth, - l = x && x.lineHeight, - C = x && x.textOutline, - u = x && 'ellipsis' === x.textOverflow, - Q = x && 'nowrap' === x.whiteSpace, - w = x && x.fontSize, - R, - I, - r = e.length, - x = B && !a.added && this.box, - p = function(a) { - var c; - c = /(px|em)$/.test(a && a.style.fontSize) - ? a.style.fontSize - : w || v.style.fontSize || 12; - return l - ? g(l) - : v.fontMetrics(c, a.getAttribute('style') ? a : b).h; - }, - K = function(a) { - F(v.escapes, function(g, b) { - a = a.replace(new RegExp(g, 'g'), b); - }); - return a; - }; - R = [y, u, Q, l, C, w, B].join(); - if (R !== a.textCache) { - for (a.textCache = R; r--; ) b.removeChild(e[r]); - q || C || u || B || -1 !== y.indexOf(' ') - ? ((z = /<.*class="([^"]+)".*>/), - (h = /<.*style="([^"]+)".*>/), - (A = /<.*href="([^"]+)".*>/), - x && x.appendChild(b), - (y = q - ? y - .replace( - /<(b|strong)>/g, - '\x3cspan style\x3d"font-weight:bold"\x3e', - ) - .replace( - /<(i|em)>/g, - '\x3cspan style\x3d"font-style:italic"\x3e', - ) - .replace(//g, '\x3c/span\x3e') - .split(//g) - : [y]), - (y = k(y, function(a) { - return '' !== a; - })), - d(y, function(g, y) { - var k, - q = 0; - g = g - .replace(/^\s+|\s+$/g, '') - .replace(//g, '\x3c/span\x3e|||'); - k = g.split('|||'); - d(k, function(g) { - if ('' !== g || 1 === k.length) { - var d = {}, - e = m.createElementNS(v.SVG_NS, 'tspan'), - x, - F; - z.test(g) && ((x = g.match(z)[1]), f(e, 'class', x)); - h.test(g) && - ((F = g - .match(h)[1] - .replace(/(;| |^)color([ :])/, '$1fill$2')), - f(e, 'style', F)); - A.test(g) && - !c && - (f( - e, - 'onclick', - 'location.href\x3d"' + g.match(A)[1] + '"', - ), - f(e, 'class', 'highcharts-anchor'), - n(e, { cursor: 'pointer' })); - g = K(g.replace(/<[a-zA-Z\/](.|\n)*?>/g, '') || ' '); - if (' ' !== g) { - e.appendChild(m.createTextNode(g)); - q ? (d.dx = 0) : y && null !== t && (d.x = t); - f(e, d); - b.appendChild(e); - !q && - I && - (!L && c && n(e, { display: 'block' }), - f(e, 'dy', p(e))); - if (B) { - d = g.replace(/([^\^])-/g, '$1- ').split(' '); - x = 1 < k.length || y || (1 < d.length && !Q); - var O = [], - l, - C = p(e), - G = a.rotation; - for ( - u && (J = v.applyEllipsis(a, e, g, B)); - !u && x && (d.length || O.length); - - ) - (a.rotation = 0), - (l = v.getSpanWidth(a, e)), - (g = l > B), - void 0 === J && (J = g), - g && 1 !== d.length - ? (e.removeChild(e.firstChild), - O.unshift(d.pop())) - : ((d = O), - (O = []), - d.length && - !Q && - ((e = m.createElementNS(P, 'tspan')), - f(e, { dy: C, x: t }), - F && f(e, 'style', F), - b.appendChild(e)), - l > B && (B = l)), - d.length && - e.appendChild( - m.createTextNode( - d.join(' ').replace(/- /g, '-'), - ), - ); - a.rotation = G; - } - q++; - } - } - }); - I = I || b.childNodes.length; - }), - J && a.attr('title', a.textStr), - x && x.removeChild(b), - C && a.applyTextOutline && a.applyTextOutline(C)) - : b.appendChild(m.createTextNode(K(y))); - } - }, - getContrast: function(a) { - a = r(a).rgba; - return 510 < a[0] + a[1] + a[2] ? '#000000' : '#FFFFFF'; - }, - button: function(a, g, b, v, d, k, e, z, h) { - var y = this.label(a, g, b, h, null, null, null, null, 'button'), - m = 0; - y.attr(q({ padding: 8, r: 2 }, d)); - var A, L, J, t; - d = q( - { - fill: '#f7f7f7', - stroke: '#cccccc', - 'stroke-width': 1, - style: { - color: '#333333', - cursor: 'pointer', - fontWeight: 'normal', - }, - }, - d, - ); - A = d.style; - delete d.style; - k = q(d, { fill: '#e6e6e6' }, k); - L = k.style; - delete k.style; - e = q( - d, - { fill: '#e6ebf5', style: { color: '#000000', fontWeight: 'bold' } }, - e, - ); - J = e.style; - delete e.style; - z = q(d, { style: { color: '#cccccc' } }, z); - t = z.style; - delete z.style; - H(y.element, K ? 'mouseover' : 'mouseenter', function() { - 3 !== m && y.setState(1); - }); - H(y.element, K ? 'mouseout' : 'mouseleave', function() { - 3 !== m && y.setState(m); - }); - y.setState = function(a) { - 1 !== a && (y.state = m = a); - y.removeClass( - /highcharts-button-(normal|hover|pressed|disabled)/, - ).addClass( - 'highcharts-button-' + - ['normal', 'hover', 'pressed', 'disabled'][a || 0], - ); - y.attr([d, k, e, z][a || 0]).css([A, L, J, t][a || 0]); - }; - y.attr(d).css(c({ cursor: 'default' }, A)); - return y.on('click', function(a) { - 3 !== m && v.call(y, a); - }); - }, - crispLine: function(a, g) { - a[1] === a[4] && (a[1] = a[4] = Math.round(a[1]) - (g % 2) / 2); - a[2] === a[5] && (a[2] = a[5] = Math.round(a[2]) + (g % 2) / 2); - return a; - }, - path: function(a) { - var g = { fill: 'none' }; - I(a) ? (g.d = a) : t(a) && c(g, a); - return this.createElement('path').attr(g); - }, - circle: function(a, g, b) { - a = t(a) ? a : { x: a, y: g, r: b }; - g = this.createElement('circle'); - g.xSetter = g.ySetter = function(a, g, b) { - b.setAttribute('c' + g, a); - }; - return g.attr(a); - }, - arc: function(a, g, b, v, c, d) { - t(a) - ? ((v = a), (g = v.y), (b = v.r), (a = v.x)) - : (v = { innerR: v, start: c, end: d }); - a = this.symbol('arc', a, g, b, b, v); - a.r = b; - return a; - }, - rect: function(a, g, b, v, c, d) { - c = t(a) ? a.r : c; - var k = this.createElement('rect'); - a = t(a) - ? a - : void 0 === a - ? {} - : { x: a, y: g, width: Math.max(b, 0), height: Math.max(v, 0) }; - void 0 !== d && ((a.strokeWidth = d), (a = k.crisp(a))); - a.fill = 'none'; - c && (a.r = c); - k.rSetter = function(a, g, b) { - f(b, { rx: a, ry: a }); - }; - return k.attr(a); - }, - setSize: function(a, g, b) { - var v = this.alignedObjects, - c = v.length; - this.width = a; - this.height = g; - for ( - this.boxWrapper.animate( - { width: a, height: g }, - { - step: function() { - this.attr({ - viewBox: - '0 0 ' + this.attr('width') + ' ' + this.attr('height'), - }); - }, - duration: G(b, !0) ? void 0 : 0, - }, - ); - c--; - - ) - v[c].align(); - }, - g: function(a) { - var g = this.createElement('g'); - return a ? g.attr({ class: 'highcharts-' + a }) : g; - }, - image: function(a, g, b, v, d) { - var k = { preserveAspectRatio: 'none' }; - 1 < arguments.length && c(k, { x: g, y: b, width: v, height: d }); - k = this.createElement('image').attr(k); - k.element.setAttributeNS - ? k.element.setAttributeNS('http://www.w3.org/1999/xlink', 'href', a) - : k.element.setAttribute('hc-svg-href', a); - return k; - }, - symbol: function(a, g, b, v, k, q) { - var e = this, - y, - z = /^url\((.*?)\)$/, - h = z.test(a), - A = !h && (this.symbols[a] ? a : 'circle'), - L = A && this.symbols[A], - t = - u(g) && - L && - L.call(this.symbols, Math.round(g), Math.round(b), v, k, q), - x, - F; - L - ? ((y = this.path(t)), - y.attr('fill', 'none'), - c(y, { symbolName: A, x: g, y: b, width: v, height: k }), - q && c(y, q)) - : h && - ((x = a.match(z)[1]), - (y = this.image(x)), - (y.imgwidth = G(J[x] && J[x].width, q && q.width)), - (y.imgheight = G(J[x] && J[x].height, q && q.height)), - (F = function() { - y.attr({ width: y.width, height: y.height }); - }), - d(['width', 'height'], function(a) { - y[a + 'Setter'] = function(a, g) { - var b = {}, - v = this['img' + g], - c = 'width' === g ? 'translateX' : 'translateY'; - this[g] = a; - u(v) && - (this.element && this.element.setAttribute(g, v), - this.alignByTranslate || - ((b[c] = ((this[g] || 0) - v) / 2), this.attr(b))); - }; - }), - u(g) && y.attr({ x: g, y: b }), - (y.isImg = !0), - u(y.imgwidth) && u(y.imgheight) - ? F() - : (y.attr({ width: 0, height: 0 }), - w('img', { - onload: function() { - var a = l[e.chartIndex]; - 0 === this.width && - (n(this, { position: 'absolute', top: '-999em' }), - m.body.appendChild(this)); - J[x] = { width: this.width, height: this.height }; - y.imgwidth = this.width; - y.imgheight = this.height; - y.element && F(); - this.parentNode && this.parentNode.removeChild(this); - e.imgCount--; - if (!e.imgCount && a && a.onload) a.onload(); - }, - src: x, - }), - this.imgCount++)); - return y; - }, - symbols: { - circle: function(a, g, b, v) { - return this.arc(a + b / 2, g + v / 2, b / 2, v / 2, { - start: 0, - end: 2 * Math.PI, - open: !1, - }); - }, - square: function(a, g, b, v) { - return ['M', a, g, 'L', a + b, g, a + b, g + v, a, g + v, 'Z']; - }, - triangle: function(a, g, b, v) { - return ['M', a + b / 2, g, 'L', a + b, g + v, a, g + v, 'Z']; - }, - 'triangle-down': function(a, g, b, v) { - return ['M', a, g, 'L', a + b, g, a + b / 2, g + v, 'Z']; - }, - diamond: function(a, g, b, v) { - return [ - 'M', - a + b / 2, - g, - 'L', - a + b, - g + v / 2, - a + b / 2, - g + v, - a, - g + v / 2, - 'Z', - ]; - }, - arc: function(a, g, b, v, c) { - var k = c.start, - d = c.r || b, - q = c.r || v || b, - e = c.end - 0.001; - b = c.innerR; - v = G(c.open, 0.001 > Math.abs(c.end - c.start - 2 * Math.PI)); - var y = Math.cos(k), - z = Math.sin(k), - h = Math.cos(e), - e = Math.sin(e); - c = 0.001 > c.end - k - Math.PI ? 0 : 1; - d = [ - 'M', - a + d * y, - g + q * z, - 'A', - d, - q, - 0, - c, - 1, - a + d * h, - g + q * e, - ]; - u(b) && - d.push( - v ? 'M' : 'L', - a + b * h, - g + b * e, - 'A', - b, - b, - 0, - c, - 0, - a + b * y, - g + b * z, - ); - d.push(v ? '' : 'Z'); - return d; - }, - callout: function(a, g, b, v, c) { - var d = Math.min((c && c.r) || 0, b, v), - k = d + 6, - q = c && c.anchorX; - c = c && c.anchorY; - var e; - e = [ - 'M', - a + d, - g, - 'L', - a + b - d, - g, - 'C', - a + b, - g, - a + b, - g, - a + b, - g + d, - 'L', - a + b, - g + v - d, - 'C', - a + b, - g + v, - a + b, - g + v, - a + b - d, - g + v, - 'L', - a + d, - g + v, - 'C', - a, - g + v, - a, - g + v, - a, - g + v - d, - 'L', - a, - g + d, - 'C', - a, - g, - a, - g, - a + d, - g, - ]; - q && q > b - ? c > g + k && c < g + v - k - ? e.splice( - 13, - 3, - 'L', - a + b, - c - 6, - a + b + 6, - c, - a + b, - c + 6, - a + b, - g + v - d, - ) - : e.splice( - 13, - 3, - 'L', - a + b, - v / 2, - q, - c, - a + b, - v / 2, - a + b, - g + v - d, - ) - : q && 0 > q - ? c > g + k && c < g + v - k - ? e.splice(33, 3, 'L', a, c + 6, a - 6, c, a, c - 6, a, g + d) - : e.splice(33, 3, 'L', a, v / 2, q, c, a, v / 2, a, g + d) - : c && c > v && q > a + k && q < a + b - k - ? e.splice( - 23, - 3, - 'L', - q + 6, - g + v, - q, - g + v + 6, - q - 6, - g + v, - a + d, - g + v, - ) - : c && - 0 > c && - q > a + k && - q < a + b - k && - e.splice(3, 3, 'L', q - 6, g, q, g - 6, q + 6, g, b - d, g); - return e; - }, - }, - clipRect: function(g, b, v, c) { - var d = a.uniqueKey(), - k = this.createElement('clipPath') - .attr({ id: d }) - .add(this.defs); - g = this.rect(g, b, v, c, 0).add(k); - g.id = d; - g.clipPath = k; - g.count = 0; - return g; - }, - text: function(a, g, b, v) { - var c = {}; - if (v && (this.allowHTML || !this.forExport)) return this.html(a, g, b); - c.x = Math.round(g || 0); - b && (c.y = Math.round(b)); - if (a || 0 === a) c.text = a; - a = this.createElement('text').attr(c); - v || - (a.xSetter = function(a, g, b) { - var v = b.getElementsByTagName('tspan'), - c, - d = b.getAttribute(g), - k; - for (k = 0; k < v.length; k++) - (c = v[k]), c.getAttribute(g) === d && c.setAttribute(g, a); - b.setAttribute(g, a); - }); - return a; - }, - fontMetrics: function(a, b) { - a = - a || - (b && b.style && b.style.fontSize) || - (this.style && this.style.fontSize); - a = /px/.test(a) - ? g(a) - : /em/.test(a) - ? parseFloat(a) * (b ? this.fontMetrics(null, b.parentNode).f : 16) - : 12; - b = 24 > a ? a + 3 : Math.round(1.2 * a); - return { h: b, b: Math.round(0.8 * b), f: a }; - }, - rotCorr: function(a, g, b) { - var v = a; - g && b && (v = Math.max(v * Math.cos(g * e), 4)); - return { x: (-a / 3) * Math.sin(g * e), y: v }; - }, - label: function(g, b, k, e, z, h, m, A, L) { - var y = this, - J = y.g('button' !== L && 'label'), - t = (J.text = y.text('', 0, 0, m).attr({ zIndex: 1 })), - x, - F, - n = 0, - B = 3, - l = 0, - C, - f, - Q, - G, - w, - R = {}, - I, - P, - r = /^url\((.*?)\)$/.test(e), - p = r, - K, - O, - N, - T; - L && J.addClass('highcharts-' + L); - p = r; - K = function() { - return ((I || 0) % 2) / 2; - }; - O = function() { - var a = t.element.style, - g = {}; - F = - (void 0 === C || void 0 === f || w) && u(t.textStr) && t.getBBox(); - J.width = (C || F.width || 0) + 2 * B + l; - J.height = (f || F.height || 0) + 2 * B; - P = B + y.fontMetrics(a && a.fontSize, t).b; - p && - (x || - ((J.box = x = y.symbols[e] || r ? y.symbol(e) : y.rect()), - x.addClass( - ('button' === L ? '' : 'highcharts-label-box') + - (L ? ' highcharts-' + L + '-box' : ''), - ), - x.add(J), - (a = K()), - (g.x = a), - (g.y = (A ? -P : 0) + a)), - (g.width = Math.round(J.width)), - (g.height = Math.round(J.height)), - x.attr(c(g, R)), - (R = {})); - }; - N = function() { - var a = l + B, - g; - g = A ? 0 : P; - u(C) && - F && - ('center' === w || 'right' === w) && - (a += { center: 0.5, right: 1 }[w] * (C - F.width)); - if (a !== t.x || g !== t.y) - t.attr('x', a), void 0 !== g && t.attr('y', g); - t.x = a; - t.y = g; - }; - T = function(a, g) { - x ? x.attr(a, g) : (R[a] = g); - }; - J.onAdd = function() { - t.add(J); - J.attr({ text: g || 0 === g ? g : '', x: b, y: k }); - x && u(z) && J.attr({ anchorX: z, anchorY: h }); - }; - J.widthSetter = function(g) { - C = a.isNumber(g) ? g : null; - }; - J.heightSetter = function(a) { - f = a; - }; - J['text-alignSetter'] = function(a) { - w = a; - }; - J.paddingSetter = function(a) { - u(a) && a !== B && ((B = J.padding = a), N()); - }; - J.paddingLeftSetter = function(a) { - u(a) && a !== l && ((l = a), N()); - }; - J.alignSetter = function(a) { - a = { left: 0, center: 0.5, right: 1 }[a]; - a !== n && ((n = a), F && J.attr({ x: Q })); - }; - J.textSetter = function(a) { - void 0 !== a && t.textSetter(a); - O(); - N(); - }; - J['stroke-widthSetter'] = function(a, g) { - a && (p = !0); - I = this['stroke-width'] = a; - T(g, a); - }; - J.strokeSetter = J.fillSetter = J.rSetter = function(a, g) { - 'r' !== g && ('fill' === g && a && (p = !0), (J[g] = a)); - T(g, a); - }; - J.anchorXSetter = function(a, g) { - z = J.anchorX = a; - T(g, Math.round(a) - K() - Q); - }; - J.anchorYSetter = function(a, g) { - h = J.anchorY = a; - T(g, a - G); - }; - J.xSetter = function(a) { - J.x = a; - n && (a -= n * ((C || F.width) + 2 * B)); - Q = Math.round(a); - J.attr('translateX', Q); - }; - J.ySetter = function(a) { - G = J.y = Math.round(a); - J.attr('translateY', G); - }; - var U = J.css; - return c(J, { - css: function(a) { - if (a) { - var g = {}; - a = q(a); - d(J.textProps, function(b) { - void 0 !== a[b] && ((g[b] = a[b]), delete a[b]); - }); - t.css(g); - } - return U.call(J, a); - }, - getBBox: function() { - return { - width: F.width + 2 * B, - height: F.height + 2 * B, - x: F.x - B, - y: F.y - B, - }; - }, - shadow: function(a) { - a && (O(), x && x.shadow(a)); - return J; - }, - destroy: function() { - v(J.element, 'mouseenter'); - v(J.element, 'mouseleave'); - t && (t = t.destroy()); - x && (x = x.destroy()); - E.prototype.destroy.call(J); - J = y = O = N = T = null; - }, - }); - }, - }); - a.Renderer = D; - })(M); - (function(a) { - var E = a.attr, - D = a.createElement, - H = a.css, - p = a.defined, - f = a.each, - l = a.extend, - r = a.isFirefox, - n = a.isMS, - w = a.isWebKit, - u = a.pick, - e = a.pInt, - h = a.SVGRenderer, - m = a.win, - d = a.wrap; - l(a.SVGElement.prototype, { - htmlCss: function(a) { - var b = this.element; - if ((b = a && 'SPAN' === b.tagName && a.width)) - delete a.width, (this.textWidth = b), this.updateTransform(); - a && - 'ellipsis' === a.textOverflow && - ((a.whiteSpace = 'nowrap'), (a.overflow = 'hidden')); - this.styles = l(this.styles, a); - H(this.element, a); - return this; - }, - htmlGetBBox: function() { - var a = this.element; - return { - x: a.offsetLeft, - y: a.offsetTop, - width: a.offsetWidth, - height: a.offsetHeight, - }; - }, - htmlUpdateTransform: function() { - if (this.added) { - var a = this.renderer, - b = this.element, - d = this.translateX || 0, - z = this.translateY || 0, - h = this.x || 0, - m = this.y || 0, - x = this.textAlign || 'left', - n = { left: 0, center: 0.5, right: 1 }[x], - t = this.styles; - H(b, { marginLeft: d, marginTop: z }); - this.shadows && - f(this.shadows, function(a) { - H(a, { marginLeft: d + 1, marginTop: z + 1 }); - }); - this.inverted && - f(b.childNodes, function(c) { - a.invertChild(c, b); - }); - if ('SPAN' === b.tagName) { - var l = this.rotation, - u = e(this.textWidth), - q = t && t.whiteSpace, - A = [l, x, b.innerHTML, this.textWidth, this.textAlign].join(); - A !== this.cTT && - ((t = a.fontMetrics(b.style.fontSize).b), - p(l) && this.setSpanRotation(l, n, t), - H(b, { width: '', whiteSpace: q || 'nowrap' }), - b.offsetWidth > u && - /[ \-]/.test(b.textContent || b.innerText) && - H(b, { - width: u + 'px', - display: 'block', - whiteSpace: q || 'normal', - }), - this.getSpanCorrection(b.offsetWidth, t, n, l, x)); - H(b, { - left: h + (this.xCorr || 0) + 'px', - top: m + (this.yCorr || 0) + 'px', - }); - w && (t = b.offsetHeight); - this.cTT = A; - } - } else this.alignOnAdd = !0; - }, - setSpanRotation: function(a, b, d) { - var c = {}, - k = this.renderer.getTransformKey(); - c[k] = c.transform = 'rotate(' + a + 'deg)'; - c[k + (r ? 'Origin' : '-origin')] = c.transformOrigin = - 100 * b + '% ' + d + 'px'; - H(this.element, c); - }, - getSpanCorrection: function(a, b, d) { - this.xCorr = -a * d; - this.yCorr = -b; - }, - }); - l(h.prototype, { - getTransformKey: function() { - return n && !/Edge/.test(m.navigator.userAgent) - ? '-ms-transform' - : w - ? '-webkit-transform' - : r - ? 'MozTransform' - : m.opera - ? '-o-transform' - : ''; - }, - html: function(a, b, k) { - var c = this.createElement('span'), - e = c.element, - h = c.renderer, - m = h.isSVG, - w = function(a, b) { - f(['opacity', 'visibility'], function(c) { - d(a, c + 'Setter', function(a, c, d, k) { - a.call(this, c, d, k); - b[d] = c; - }); - }); - }; - c.textSetter = function(a) { - a !== e.innerHTML && delete this.bBox; - this.textStr = a; - e.innerHTML = u(a, ''); - c.htmlUpdateTransform(); - }; - m && w(c, c.element.style); - c.xSetter = c.ySetter = c.alignSetter = c.rotationSetter = function( - a, - b, - ) { - 'align' === b && (b = 'textAlign'); - c[b] = a; - c.htmlUpdateTransform(); - }; - c.attr({ text: a, x: Math.round(b), y: Math.round(k) }).css({ - fontFamily: this.style.fontFamily, - fontSize: this.style.fontSize, - position: 'absolute', - }); - e.style.whiteSpace = 'nowrap'; - c.css = c.htmlCss; - m && - (c.add = function(a) { - var b, - d = h.box.parentNode, - k = []; - if ((this.parentGroup = a)) { - if (((b = a.div), !b)) { - for (; a; ) k.push(a), (a = a.parentGroup); - f(k.reverse(), function(a) { - function e(g, b) { - a[b] = g; - n - ? (q[h.getTransformKey()] = - 'translate(' + - (a.x || a.translateX) + - 'px,' + - (a.y || a.translateY) + - 'px)') - : 'translateX' === b - ? (q.left = g + 'px') - : (q.top = g + 'px'); - a.doTransform = !0; - } - var q, - g = E(a.element, 'class'); - g && (g = { className: g }); - b = a.div = - a.div || - D( - 'div', - g, - { - position: 'absolute', - left: (a.translateX || 0) + 'px', - top: (a.translateY || 0) + 'px', - display: a.display, - opacity: a.opacity, - pointerEvents: a.styles && a.styles.pointerEvents, - }, - b || d, - ); - q = b.style; - l(a, { - classSetter: (function(a) { - return function(g) { - this.element.setAttribute('class', g); - a.className = g; - }; - })(b), - on: function() { - k[0].div && c.on.apply({ element: k[0].div }, arguments); - return a; - }, - translateXSetter: e, - translateYSetter: e, - }); - w(a, q); - }); - } - } else b = d; - b.appendChild(e); - c.added = !0; - c.alignOnAdd && c.htmlUpdateTransform(); - return c; - }); - return c; - }, - }); - })(M); - (function(a) { - function E() { - var n = a.defaultOptions.global, - l = r.moment; - if (n.timezone) { - if (l) - return function(a) { - return -l.tz(a, n.timezone).utcOffset(); - }; - a.error(25); - } - return n.useUTC && n.getTimezoneOffset; - } - function D() { - var n = a.defaultOptions.global, - f, - u = n.useUTC, - e = u ? 'getUTC' : 'get', - h = u ? 'setUTC' : 'set', - m = 'Minutes Hours Day Date Month FullYear'.split(' '), - d = m.concat(['Milliseconds', 'Seconds']); - a.Date = f = n.Date || r.Date; - f.hcTimezoneOffset = u && n.timezoneOffset; - f.hcGetTimezoneOffset = E(); - f.hcHasTimeZone = !(!f.hcTimezoneOffset && !f.hcGetTimezoneOffset); - f.hcMakeTime = function(a, b, d, e, h, m) { - var c; - u - ? ((c = f.UTC.apply(0, arguments)), (c += p(c))) - : (c = new f(a, b, l(d, 1), l(e, 0), l(h, 0), l(m, 0)).getTime()); - return c; - }; - for (n = 0; n < m.length; n++) f['hcGet' + m[n]] = e + m[n]; - for (n = 0; n < d.length; n++) f['hcSet' + d[n]] = h + d[n]; - } - var H = a.color, - p = a.getTZOffset, - f = a.merge, - l = a.pick, - r = a.win; - a.defaultOptions = { - colors: '#7cb5ec #434348 #90ed7d #f7a35c #8085e9 #f15c80 #e4d354 #2b908f #f45b5b #91e8e1'.split( - ' ', - ), - symbols: ['circle', 'diamond', 'square', 'triangle', 'triangle-down'], - lang: { - loading: 'Loading...', - months: 'January February March April May June July August September October November December'.split( - ' ', - ), - shortMonths: 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split( - ' ', - ), - weekdays: 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split( - ' ', - ), - decimalPoint: '.', - numericSymbols: 'kMGTPE'.split(''), - resetZoom: 'Reset zoom', - resetZoomTitle: 'Reset zoom level 1:1', - thousandsSep: ' ', - }, - global: { useUTC: !0 }, - chart: { - borderRadius: 0, - defaultSeriesType: 'line', - ignoreHiddenSeries: !0, - spacing: [10, 10, 15, 10], - resetZoomButton: { - theme: { zIndex: 6 }, - position: { align: 'right', x: -10, y: 10 }, - }, - width: null, - height: null, - borderColor: '#335cad', - backgroundColor: '#ffffff', - plotBorderColor: '#cccccc', - }, - title: { - text: 'Chart title', - align: 'center', - margin: 15, - widthAdjust: -44, - }, - subtitle: { text: '', align: 'center', widthAdjust: -44 }, - plotOptions: {}, - labels: { style: { position: 'absolute', color: '#333333' } }, - legend: { - enabled: !0, - align: 'center', - layout: 'horizontal', - labelFormatter: function() { - return this.name; - }, - borderColor: '#999999', - borderRadius: 0, - navigation: { activeColor: '#003399', inactiveColor: '#cccccc' }, - itemStyle: { - color: '#333333', - fontSize: '12px', - fontWeight: 'bold', - textOverflow: 'ellipsis', - }, - itemHoverStyle: { color: '#000000' }, - itemHiddenStyle: { color: '#cccccc' }, - shadow: !1, - itemCheckboxStyle: { - position: 'absolute', - width: '13px', - height: '13px', - }, - squareSymbol: !0, - symbolPadding: 5, - verticalAlign: 'bottom', - x: 0, - y: 0, - title: { style: { fontWeight: 'bold' } }, - }, - loading: { - labelStyle: { fontWeight: 'bold', position: 'relative', top: '45%' }, - style: { - position: 'absolute', - backgroundColor: '#ffffff', - opacity: 0.5, - textAlign: 'center', - }, - }, - tooltip: { - enabled: !0, - animation: a.svg, - borderRadius: 3, - dateTimeLabelFormats: { - millisecond: '%A, %b %e, %H:%M:%S.%L', - second: '%A, %b %e, %H:%M:%S', - minute: '%A, %b %e, %H:%M', - hour: '%A, %b %e, %H:%M', - day: '%A, %b %e, %Y', - week: 'Week from %A, %b %e, %Y', - month: '%B %Y', - year: '%Y', - }, - footerFormat: '', - padding: 8, - snap: a.isTouchDevice ? 25 : 10, - backgroundColor: H('#f7f7f7') - .setOpacity(0.85) - .get(), - borderWidth: 1, - headerFormat: - '\x3cspan style\x3d"font-size: 10px"\x3e{point.key}\x3c/span\x3e\x3cbr/\x3e', - pointFormat: - '\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e {series.name}: \x3cb\x3e{point.y}\x3c/b\x3e\x3cbr/\x3e', - shadow: !0, - style: { - color: '#333333', - cursor: 'default', - fontSize: '12px', - pointerEvents: 'none', - whiteSpace: 'nowrap', - }, - }, - credits: { - enabled: !0, - href: 'http://www.highcharts.com', - position: { align: 'right', x: -10, verticalAlign: 'bottom', y: -5 }, - style: { cursor: 'pointer', color: '#999999', fontSize: '9px' }, - text: 'Highcharts.com', - }, - }; - a.setOptions = function(n) { - a.defaultOptions = f(!0, a.defaultOptions, n); - D(); - return a.defaultOptions; - }; - a.getOptions = function() { - return a.defaultOptions; - }; - a.defaultPlotOptions = a.defaultOptions.plotOptions; - D(); - })(M); - (function(a) { - var E = a.correctFloat, - D = a.defined, - H = a.destroyObjectProperties, - p = a.isNumber, - f = a.merge, - l = a.pick, - r = a.deg2rad; - a.Tick = function(a, l, f, e) { - this.axis = a; - this.pos = l; - this.type = f || ''; - this.isNewLabel = this.isNew = !0; - f || e || this.addLabel(); - }; - a.Tick.prototype = { - addLabel: function() { - var a = this.axis, - w = a.options, - u = a.chart, - e = a.categories, - h = a.names, - m = this.pos, - d = w.labels, - c = a.tickPositions, - b = m === c[0], - k = m === c[c.length - 1], - h = e ? l(e[m], h[m], m) : m, - e = this.label, - c = c.info, - z; - a.isDatetimeAxis && - c && - (z = w.dateTimeLabelFormats[c.higherRanks[m] || c.unitName]); - this.isFirst = b; - this.isLast = k; - w = a.labelFormatter.call({ - axis: a, - chart: u, - isFirst: b, - isLast: k, - dateTimeLabelFormat: z, - value: a.isLog ? E(a.lin2log(h)) : h, - pos: m, - }); - D(e) - ? e && e.attr({ text: w }) - : ((this.labelLength = - (this.label = e = - D(w) && d.enabled - ? u.renderer - .text(w, 0, 0, d.useHTML) - .css(f(d.style)) - .add(a.labelGroup) - : null) && e.getBBox().width), - (this.rotation = 0)); - }, - getLabelSize: function() { - return this.label - ? this.label.getBBox()[this.axis.horiz ? 'height' : 'width'] - : 0; - }, - handleOverflow: function(a) { - var f = this.axis, - n = f.options.labels, - e = a.x, - h = f.chart.chartWidth, - m = f.chart.spacing, - d = l(f.labelLeft, Math.min(f.pos, m[3])), - m = l( - f.labelRight, - Math.max(f.isRadial ? 0 : f.pos + f.len, h - m[1]), - ), - c = this.label, - b = this.rotation, - k = { left: 0, center: 0.5, right: 1 }[ - f.labelAlign || c.attr('align') - ], - z = c.getBBox().width, - B = f.getSlotWidth(), - I = B, - x = 1, - p, - t = {}; - if (b || !1 === n.overflow) - 0 > b && e - k * z < d - ? (p = Math.round(e / Math.cos(b * r) - d)) - : 0 < b && - e + k * z > m && - (p = Math.round((h - e) / Math.cos(b * r))); - else if ( - ((h = e + (1 - k) * z), - e - k * z < d - ? (I = a.x + I * (1 - k) - d) - : h > m && ((I = m - a.x + I * k), (x = -1)), - (I = Math.min(B, I)), - I < B && - 'center' === f.labelAlign && - (a.x += x * (B - I - k * (B - Math.min(z, I)))), - z > I || (f.autoRotation && (c.styles || {}).width)) - ) - p = I; - p && - ((t.width = p), - (n.style || {}).textOverflow || (t.textOverflow = 'ellipsis'), - c.css(t)); - }, - getPosition: function(a, f, l, e) { - var h = this.axis, - m = h.chart, - d = (e && m.oldChartHeight) || m.chartHeight; - return { - x: a - ? h.translate(f + l, null, null, e) + h.transB - : h.left + - h.offset + - (h.opposite - ? ((e && m.oldChartWidth) || m.chartWidth) - h.right - h.left - : 0), - y: a - ? d - h.bottom + h.offset - (h.opposite ? h.height : 0) - : d - h.translate(f + l, null, null, e) - h.transB, - }; - }, - getLabelPosition: function(a, f, l, e, h, m, d, c) { - var b = this.axis, - k = b.transA, - z = b.reversed, - B = b.staggerLines, - n = b.tickRotCorr || { x: 0, y: 0 }, - x = h.y, - u = - e || b.reserveSpaceDefault - ? 0 - : -b.labelOffset * ('center' === b.labelAlign ? 0.5 : 1); - D(x) || - (x = - 0 === b.side - ? l.rotation - ? -8 - : -l.getBBox().height - : 2 === b.side - ? n.y + 8 - : Math.cos(l.rotation * r) * (n.y - l.getBBox(!1, 0).height / 2)); - a = a + h.x + u + n.x - (m && e ? m * k * (z ? -1 : 1) : 0); - f = f + x - (m && !e ? m * k * (z ? 1 : -1) : 0); - B && - ((l = (d / (c || 1)) % B), - b.opposite && (l = B - l - 1), - (f += (b.labelOffset / B) * l)); - return { x: a, y: Math.round(f) }; - }, - getMarkPath: function(a, f, l, e, h, m) { - return m.crispLine( - ['M', a, f, 'L', a + (h ? 0 : -l), f + (h ? l : 0)], - e, - ); - }, - renderGridLine: function(a, f, l) { - var e = this.axis, - h = e.options, - m = this.gridLine, - d = {}, - c = this.pos, - b = this.type, - k = e.tickmarkOffset, - z = e.chart.renderer, - B = b ? b + 'Grid' : 'grid', - n = h[B + 'LineWidth'], - x = h[B + 'LineColor'], - h = h[B + 'LineDashStyle']; - m || - ((d.stroke = x), - (d['stroke-width'] = n), - h && (d.dashstyle = h), - b || (d.zIndex = 1), - a && (d.opacity = 0), - (this.gridLine = m = z - .path() - .attr(d) - .addClass('highcharts-' + (b ? b + '-' : '') + 'grid-line') - .add(e.gridGroup))); - if ( - !a && - m && - (a = e.getPlotLinePath(c + k, m.strokeWidth() * l, a, !0)) - ) - m[this.isNew ? 'attr' : 'animate']({ d: a, opacity: f }); - }, - renderMark: function(a, f, u) { - var e = this.axis, - h = e.options, - m = e.chart.renderer, - d = this.type, - c = d ? d + 'Tick' : 'tick', - b = e.tickSize(c), - k = this.mark, - z = !k, - B = a.x; - a = a.y; - var n = l(h[c + 'Width'], !d && e.isXAxis ? 1 : 0), - h = h[c + 'Color']; - b && - (e.opposite && (b[0] = -b[0]), - z && - ((this.mark = k = m - .path() - .addClass('highcharts-' + (d ? d + '-' : '') + 'tick') - .add(e.axisGroup)), - k.attr({ stroke: h, 'stroke-width': n })), - k[z ? 'attr' : 'animate']({ - d: this.getMarkPath(B, a, b[0], k.strokeWidth() * u, e.horiz, m), - opacity: f, - })); - }, - renderLabel: function(a, f, u, e) { - var h = this.axis, - m = h.horiz, - d = h.options, - c = this.label, - b = d.labels, - k = b.step, - h = h.tickmarkOffset, - z = !0, - B = a.x; - a = a.y; - c && - p(B) && - ((c.xy = a = this.getLabelPosition(B, a, c, m, b, h, e, k)), - (this.isFirst && !this.isLast && !l(d.showFirstLabel, 1)) || - (this.isLast && !this.isFirst && !l(d.showLastLabel, 1)) - ? (z = !1) - : !m || - b.step || - b.rotation || - f || - 0 === u || - this.handleOverflow(a), - k && e % k && (z = !1), - z && p(a.y) - ? ((a.opacity = u), - c[this.isNewLabel ? 'attr' : 'animate'](a), - (this.isNewLabel = !1)) - : (c.attr('y', -9999), (this.isNewLabel = !0))); - }, - render: function(a, f, u) { - var e = this.axis, - h = e.horiz, - m = this.getPosition(h, this.pos, e.tickmarkOffset, f), - d = m.x, - c = m.y, - e = (h && d === e.pos + e.len) || (!h && c === e.pos) ? -1 : 1; - u = l(u, 1); - this.isActive = !0; - this.renderGridLine(f, u, e); - this.renderMark(m, u, e); - this.renderLabel(m, f, u, a); - this.isNew = !1; - }, - destroy: function() { - H(this, this.axis); - }, - }; - })(M); - var V = (function(a) { - var E = a.addEvent, - D = a.animObject, - H = a.arrayMax, - p = a.arrayMin, - f = a.color, - l = a.correctFloat, - r = a.defaultOptions, - n = a.defined, - w = a.deg2rad, - u = a.destroyObjectProperties, - e = a.each, - h = a.extend, - m = a.fireEvent, - d = a.format, - c = a.getMagnitude, - b = a.grep, - k = a.inArray, - z = a.isArray, - B = a.isNumber, - I = a.isString, - x = a.merge, - K = a.normalizeTickInterval, - t = a.objectEach, - C = a.pick, - N = a.removeEvent, - q = a.splat, - A = a.syncTimeout, - F = a.Tick, - G = function() { - this.init.apply(this, arguments); - }; - a.extend(G.prototype, { - defaultOptions: { - dateTimeLabelFormats: { - millisecond: '%H:%M:%S.%L', - second: '%H:%M:%S', - minute: '%H:%M', - hour: '%H:%M', - day: '%e. %b', - week: '%e. %b', - month: "%b '%y", - year: '%Y', - }, - endOnTick: !1, - labels: { - enabled: !0, - style: { color: '#666666', cursor: 'default', fontSize: '11px' }, - x: 0, - }, - maxPadding: 0.01, - minorTickLength: 2, - minorTickPosition: 'outside', - minPadding: 0.01, - startOfWeek: 1, - startOnTick: !1, - tickLength: 10, - tickmarkPlacement: 'between', - tickPixelInterval: 100, - tickPosition: 'outside', - title: { align: 'middle', style: { color: '#666666' } }, - type: 'linear', - minorGridLineColor: '#f2f2f2', - minorGridLineWidth: 1, - minorTickColor: '#999999', - lineColor: '#ccd6eb', - lineWidth: 1, - gridLineColor: '#e6e6e6', - tickColor: '#ccd6eb', - }, - defaultYAxisOptions: { - endOnTick: !0, - tickPixelInterval: 72, - showLastLabel: !0, - labels: { x: -8 }, - maxPadding: 0.05, - minPadding: 0.05, - startOnTick: !0, - title: { rotation: 270, text: 'Values' }, - stackLabels: { - allowOverlap: !1, - enabled: !1, - formatter: function() { - return a.numberFormat(this.total, -1); - }, - style: { - fontSize: '11px', - fontWeight: 'bold', - color: '#000000', - textOutline: '1px contrast', - }, - }, - gridLineWidth: 1, - lineWidth: 0, - }, - defaultLeftAxisOptions: { labels: { x: -15 }, title: { rotation: 270 } }, - defaultRightAxisOptions: { labels: { x: 15 }, title: { rotation: 90 } }, - defaultBottomAxisOptions: { - labels: { autoRotation: [-45], x: 0 }, - title: { rotation: 0 }, - }, - defaultTopAxisOptions: { - labels: { autoRotation: [-45], x: 0 }, - title: { rotation: 0 }, - }, - init: function(a, b) { - var g = b.isX, - v = this; - v.chart = a; - v.horiz = a.inverted && !v.isZAxis ? !g : g; - v.isXAxis = g; - v.coll = v.coll || (g ? 'xAxis' : 'yAxis'); - v.opposite = b.opposite; - v.side = - b.side || (v.horiz ? (v.opposite ? 0 : 2) : v.opposite ? 1 : 3); - v.setOptions(b); - var c = this.options, - d = c.type; - v.labelFormatter = c.labels.formatter || v.defaultLabelFormatter; - v.userOptions = b; - v.minPixelPadding = 0; - v.reversed = c.reversed; - v.visible = !1 !== c.visible; - v.zoomEnabled = !1 !== c.zoomEnabled; - v.hasNames = 'category' === d || !0 === c.categories; - v.categories = c.categories || v.hasNames; - v.names = v.names || []; - v.plotLinesAndBandsGroups = {}; - v.isLog = 'logarithmic' === d; - v.isDatetimeAxis = 'datetime' === d; - v.positiveValuesOnly = v.isLog && !v.allowNegativeLog; - v.isLinked = n(c.linkedTo); - v.ticks = {}; - v.labelEdge = []; - v.minorTicks = {}; - v.plotLinesAndBands = []; - v.alternateBands = {}; - v.len = 0; - v.minRange = v.userMinRange = c.minRange || c.maxZoom; - v.range = c.range; - v.offset = c.offset || 0; - v.stacks = {}; - v.oldStacks = {}; - v.stacksTouched = 0; - v.max = null; - v.min = null; - v.crosshair = C( - c.crosshair, - q(a.options.tooltip.crosshairs)[g ? 0 : 1], - !1, - ); - b = v.options.events; - -1 === k(v, a.axes) && - (g ? a.axes.splice(a.xAxis.length, 0, v) : a.axes.push(v), - a[v.coll].push(v)); - v.series = v.series || []; - a.inverted && - !v.isZAxis && - g && - void 0 === v.reversed && - (v.reversed = !0); - t(b, function(a, g) { - E(v, g, a); - }); - v.lin2log = c.linearToLogConverter || v.lin2log; - v.isLog && ((v.val2lin = v.log2lin), (v.lin2val = v.lin2log)); - }, - setOptions: function(a) { - this.options = x( - this.defaultOptions, - 'yAxis' === this.coll && this.defaultYAxisOptions, - [ - this.defaultTopAxisOptions, - this.defaultRightAxisOptions, - this.defaultBottomAxisOptions, - this.defaultLeftAxisOptions, - ][this.side], - x(r[this.coll], a), - ); - }, - defaultLabelFormatter: function() { - var g = this.axis, - b = this.value, - c = g.categories, - k = this.dateTimeLabelFormat, - e = r.lang, - q = e.numericSymbols, - e = e.numericSymbolMagnitude || 1e3, - h = q && q.length, - m, - z = g.options.labels.format, - g = g.isLog ? Math.abs(b) : g.tickInterval; - if (z) m = d(z, this); - else if (c) m = b; - else if (k) m = a.dateFormat(k, b); - else if (h && 1e3 <= g) - for (; h-- && void 0 === m; ) - (c = Math.pow(e, h + 1)), - g >= c && - 0 === (10 * b) % c && - null !== q[h] && - 0 !== b && - (m = a.numberFormat(b / c, -1) + q[h]); - void 0 === m && - (m = - 1e4 <= Math.abs(b) - ? a.numberFormat(b, -1) - : a.numberFormat(b, -1, void 0, '')); - return m; - }, - getSeriesExtremes: function() { - var a = this, - v = a.chart; - a.hasVisibleSeries = !1; - a.dataMin = a.dataMax = a.threshold = null; - a.softThreshold = !a.isXAxis; - a.buildStacks && a.buildStacks(); - e(a.series, function(g) { - if (g.visible || !v.options.chart.ignoreHiddenSeries) { - var c = g.options, - d = c.threshold, - k; - a.hasVisibleSeries = !0; - a.positiveValuesOnly && 0 >= d && (d = null); - if (a.isXAxis) - (c = g.xData), - c.length && - ((g = p(c)), - (k = H(c)), - B(g) || g instanceof Date || ((c = b(c, B)), (g = p(c))), - (a.dataMin = Math.min(C(a.dataMin, c[0], g), g)), - (a.dataMax = Math.max(C(a.dataMax, c[0], k), k))); - else if ( - (g.getExtremes(), - (k = g.dataMax), - (g = g.dataMin), - n(g) && - n(k) && - ((a.dataMin = Math.min(C(a.dataMin, g), g)), - (a.dataMax = Math.max(C(a.dataMax, k), k))), - n(d) && (a.threshold = d), - !c.softThreshold || a.positiveValuesOnly) - ) - a.softThreshold = !1; - } - }); - }, - translate: function(a, b, c, d, k, e) { - var g = this.linkedParent || this, - v = 1, - q = 0, - h = d ? g.oldTransA : g.transA; - d = d ? g.oldMin : g.min; - var m = g.minPixelPadding; - k = (g.isOrdinal || g.isBroken || (g.isLog && k)) && g.lin2val; - h || (h = g.transA); - c && ((v *= -1), (q = g.len)); - g.reversed && ((v *= -1), (q -= v * (g.sector || g.len))); - b - ? ((a = (a * v + q - m) / h + d), k && (a = g.lin2val(a))) - : (k && (a = g.val2lin(a)), - (a = B(d) - ? v * (a - d) * h + q + v * m + (B(e) ? h * e : 0) - : void 0)); - return a; - }, - toPixels: function(a, b) { - return ( - this.translate(a, !1, !this.horiz, null, !0) + (b ? 0 : this.pos) - ); - }, - toValue: function(a, b) { - return this.translate( - a - (b ? 0 : this.pos), - !0, - !this.horiz, - null, - !0, - ); - }, - getPlotLinePath: function(a, b, c, d, k) { - var g = this.chart, - v = this.left, - q = this.top, - e, - h, - m = (c && g.oldChartHeight) || g.chartHeight, - z = (c && g.oldChartWidth) || g.chartWidth, - A; - e = this.transB; - var t = function(a, g, b) { - if (a < g || a > b) d ? (a = Math.min(Math.max(g, a), b)) : (A = !0); - return a; - }; - k = C(k, this.translate(a, null, null, c)); - a = c = Math.round(k + e); - e = h = Math.round(m - k - e); - B(k) - ? this.horiz - ? ((e = q), - (h = m - this.bottom), - (a = c = t(a, v, v + this.width))) - : ((a = v), - (c = z - this.right), - (e = h = t(e, q, q + this.height))) - : ((A = !0), (d = !1)); - return A && !d - ? null - : g.renderer.crispLine(['M', a, e, 'L', c, h], b || 1); - }, - getLinearTickPositions: function(a, b, c) { - var g, - v = l(Math.floor(b / a) * a); - c = l(Math.ceil(c / a) * a); - var d = [], - k; - l(v + a) === v && (k = 20); - if (this.single) return [b]; - for (b = v; b <= c; ) { - d.push(b); - b = l(b + a, k); - if (b === g) break; - g = b; - } - return d; - }, - getMinorTickInterval: function() { - var a = this.options; - return !0 === a.minorTicks - ? C(a.minorTickInterval, 'auto') - : !1 === a.minorTicks - ? null - : a.minorTickInterval; - }, - getMinorTickPositions: function() { - var a = this, - b = a.options, - c = a.tickPositions, - d = a.minorTickInterval, - k = [], - q = a.pointRangePadding || 0, - h = a.min - q, - q = a.max + q, - m = q - h; - if (m && m / d < a.len / 3) - if (a.isLog) - e(this.paddedTicks, function(g, b, v) { - b && - k.push.apply(k, a.getLogTickPositions(d, v[b - 1], v[b], !0)); - }); - else if (a.isDatetimeAxis && 'auto' === this.getMinorTickInterval()) - k = k.concat( - a.getTimeTicks( - a.normalizeTimeTickInterval(d), - h, - q, - b.startOfWeek, - ), - ); - else - for (b = h + ((c[0] - h) % d); b <= q && b !== k[0]; b += d) - k.push(b); - 0 !== k.length && a.trimTicks(k); - return k; - }, - adjustForMinRange: function() { - var a = this.options, - b = this.min, - c = this.max, - d, - k, - q, - h, - m, - z, - A, - t; - this.isXAxis && - void 0 === this.minRange && - !this.isLog && - (n(a.min) || n(a.max) - ? (this.minRange = null) - : (e(this.series, function(a) { - z = a.xData; - for (h = A = a.xIncrement ? 1 : z.length - 1; 0 < h; h--) - if (((m = z[h] - z[h - 1]), void 0 === q || m < q)) q = m; - }), - (this.minRange = Math.min(5 * q, this.dataMax - this.dataMin)))); - c - b < this.minRange && - ((k = this.dataMax - this.dataMin >= this.minRange), - (t = this.minRange), - (d = (t - c + b) / 2), - (d = [b - d, C(a.min, b - d)]), - k && (d[2] = this.isLog ? this.log2lin(this.dataMin) : this.dataMin), - (b = H(d)), - (c = [b + t, C(a.max, b + t)]), - k && (c[2] = this.isLog ? this.log2lin(this.dataMax) : this.dataMax), - (c = p(c)), - c - b < t && ((d[0] = c - t), (d[1] = C(a.min, c - t)), (b = H(d)))); - this.min = b; - this.max = c; - }, - getClosest: function() { - var a; - this.categories - ? (a = 1) - : e(this.series, function(g) { - var b = g.closestPointRange, - v = g.visible || !g.chart.options.chart.ignoreHiddenSeries; - !g.noSharedTooltip && - n(b) && - v && - (a = n(a) ? Math.min(a, b) : b); - }); - return a; - }, - nameToX: function(a) { - var g = z(this.categories), - b = g ? this.categories : this.names, - c = a.options.x, - d; - a.series.requireSorting = !1; - n(c) || - (c = - !1 === this.options.uniqueNames - ? a.series.autoIncrement() - : k(a.name, b)); - -1 === c ? g || (d = b.length) : (d = c); - void 0 !== d && (this.names[d] = a.name); - return d; - }, - updateNames: function() { - var a = this; - 0 < this.names.length && - ((this.names.length = 0), - (this.minRange = this.userMinRange), - e(this.series || [], function(g) { - g.xIncrement = null; - if (!g.points || g.isDirtyData) g.processData(), g.generatePoints(); - e(g.points, function(b, v) { - var c; - b.options && - ((c = a.nameToX(b)), - void 0 !== c && c !== b.x && ((b.x = c), (g.xData[v] = c))); - }); - })); - }, - setAxisTranslation: function(a) { - var g = this, - b = g.max - g.min, - c = g.axisPointRange || 0, - d, - k = 0, - q = 0, - h = g.linkedParent, - m = !!g.categories, - z = g.transA, - A = g.isXAxis; - if (A || m || c) - (d = g.getClosest()), - h - ? ((k = h.minPointOffset), (q = h.pointRangePadding)) - : e(g.series, function(a) { - var b = m - ? 1 - : A - ? C(a.options.pointRange, d, 0) - : g.axisPointRange || 0; - a = a.options.pointPlacement; - c = Math.max(c, b); - g.single || - ((k = Math.max(k, I(a) ? 0 : b / 2)), - (q = Math.max(q, 'on' === a ? 0 : b))); - }), - (h = g.ordinalSlope && d ? g.ordinalSlope / d : 1), - (g.minPointOffset = k *= h), - (g.pointRangePadding = q *= h), - (g.pointRange = Math.min(c, b)), - A && (g.closestPointRange = d); - a && (g.oldTransA = z); - g.translationSlope = g.transA = z = - g.options.staticScale || g.len / (b + q || 1); - g.transB = g.horiz ? g.left : g.bottom; - g.minPixelPadding = z * k; - }, - minFromRange: function() { - return this.max - this.range; - }, - setTickInterval: function(g) { - var b = this, - d = b.chart, - k = b.options, - q = b.isLog, - h = b.log2lin, - z = b.isDatetimeAxis, - A = b.isXAxis, - t = b.isLinked, - x = k.maxPadding, - f = k.minPadding, - F = k.tickInterval, - u = k.tickPixelInterval, - G = b.categories, - p = b.threshold, - I = b.softThreshold, - r, - w, - N, - D; - z || G || t || this.getTickAmount(); - N = C(b.userMin, k.min); - D = C(b.userMax, k.max); - t - ? ((b.linkedParent = d[b.coll][k.linkedTo]), - (d = b.linkedParent.getExtremes()), - (b.min = C(d.min, d.dataMin)), - (b.max = C(d.max, d.dataMax)), - k.type !== b.linkedParent.options.type && a.error(11, 1)) - : (!I && - n(p) && - (b.dataMin >= p - ? ((r = p), (f = 0)) - : b.dataMax <= p && ((w = p), (x = 0))), - (b.min = C(N, r, b.dataMin)), - (b.max = C(D, w, b.dataMax))); - q && - (b.positiveValuesOnly && - !g && - 0 >= Math.min(b.min, C(b.dataMin, b.min)) && - a.error(10, 1), - (b.min = l(h(b.min), 15)), - (b.max = l(h(b.max), 15))); - b.range && - n(b.max) && - ((b.userMin = b.min = N = Math.max(b.dataMin, b.minFromRange())), - (b.userMax = D = b.max), - (b.range = null)); - m(b, 'foundExtremes'); - b.beforePadding && b.beforePadding(); - b.adjustForMinRange(); - !(G || b.axisPointRange || b.usePercentage || t) && - n(b.min) && - n(b.max) && - (h = b.max - b.min) && - (!n(N) && f && (b.min -= h * f), !n(D) && x && (b.max += h * x)); - B(k.softMin) && !B(b.userMin) && (b.min = Math.min(b.min, k.softMin)); - B(k.softMax) && !B(b.userMax) && (b.max = Math.max(b.max, k.softMax)); - B(k.floor) && (b.min = Math.max(b.min, k.floor)); - B(k.ceiling) && (b.max = Math.min(b.max, k.ceiling)); - I && - n(b.dataMin) && - ((p = p || 0), - !n(N) && b.min < p && b.dataMin >= p - ? (b.min = p) - : !n(D) && b.max > p && b.dataMax <= p && (b.max = p)); - b.tickInterval = - b.min === b.max || void 0 === b.min || void 0 === b.max - ? 1 - : t && !F && u === b.linkedParent.options.tickPixelInterval - ? (F = b.linkedParent.tickInterval) - : C( - F, - this.tickAmount - ? (b.max - b.min) / Math.max(this.tickAmount - 1, 1) - : void 0, - G ? 1 : ((b.max - b.min) * u) / Math.max(b.len, u), - ); - A && - !g && - e(b.series, function(a) { - a.processData(b.min !== b.oldMin || b.max !== b.oldMax); - }); - b.setAxisTranslation(!0); - b.beforeSetTickPositions && b.beforeSetTickPositions(); - b.postProcessTickInterval && - (b.tickInterval = b.postProcessTickInterval(b.tickInterval)); - b.pointRange && - !F && - (b.tickInterval = Math.max(b.pointRange, b.tickInterval)); - g = C(k.minTickInterval, b.isDatetimeAxis && b.closestPointRange); - !F && b.tickInterval < g && (b.tickInterval = g); - z || - q || - F || - (b.tickInterval = K( - b.tickInterval, - null, - c(b.tickInterval), - C( - k.allowDecimals, - !( - 0.5 < b.tickInterval && - 5 > b.tickInterval && - 1e3 < b.max && - 9999 > b.max - ), - ), - !!this.tickAmount, - )); - this.tickAmount || (b.tickInterval = b.unsquish()); - this.setTickPositions(); - }, - setTickPositions: function() { - var a = this.options, - b, - c = a.tickPositions; - b = this.getMinorTickInterval(); - var d = a.tickPositioner, - k = a.startOnTick, - q = a.endOnTick; - this.tickmarkOffset = - this.categories && - 'between' === a.tickmarkPlacement && - 1 === this.tickInterval - ? 0.5 - : 0; - this.minorTickInterval = - 'auto' === b && this.tickInterval ? this.tickInterval / 5 : b; - this.single = - this.min === this.max && - n(this.min) && - !this.tickAmount && - (parseInt(this.min, 10) === this.min || !1 !== a.allowDecimals); - this.tickPositions = b = c && c.slice(); - !b && - ((b = this.isDatetimeAxis - ? this.getTimeTicks( - this.normalizeTimeTickInterval(this.tickInterval, a.units), - this.min, - this.max, - a.startOfWeek, - this.ordinalPositions, - this.closestPointRange, - !0, - ) - : this.isLog - ? this.getLogTickPositions(this.tickInterval, this.min, this.max) - : this.getLinearTickPositions( - this.tickInterval, - this.min, - this.max, - )), - b.length > this.len && - ((b = [b[0], b.pop()]), b[0] === b[1] && (b.length = 1)), - (this.tickPositions = b), - d && (d = d.apply(this, [this.min, this.max]))) && - (this.tickPositions = b = d); - this.paddedTicks = b.slice(0); - this.trimTicks(b, k, q); - this.isLinked || - (this.single && - 2 > b.length && - ((this.min -= 0.5), (this.max += 0.5)), - c || d || this.adjustTickAmount()); - }, - trimTicks: function(a, b, c) { - var g = a[0], - d = a[a.length - 1], - k = this.minPointOffset || 0; - if (!this.isLinked) { - if (b && -Infinity !== g) this.min = g; - else for (; this.min - k > a[0]; ) a.shift(); - if (c) this.max = d; - else for (; this.max + k < a[a.length - 1]; ) a.pop(); - 0 === a.length && - n(g) && - !this.options.tickPositions && - a.push((d + g) / 2); - } - }, - alignToOthers: function() { - var a = {}, - b, - c = this.options; - !1 === this.chart.options.chart.alignTicks || - !1 === c.alignTicks || - this.isLog || - e(this.chart[this.coll], function(g) { - var c = g.options, - c = [g.horiz ? c.left : c.top, c.width, c.height, c.pane].join(); - g.series.length && (a[c] ? (b = !0) : (a[c] = 1)); - }); - return b; - }, - getTickAmount: function() { - var a = this.options, - b = a.tickAmount, - c = a.tickPixelInterval; - !n(a.tickInterval) && - this.len < c && - !this.isRadial && - !this.isLog && - a.startOnTick && - a.endOnTick && - (b = 2); - !b && this.alignToOthers() && (b = Math.ceil(this.len / c) + 1); - 4 > b && ((this.finalTickAmt = b), (b = 5)); - this.tickAmount = b; - }, - adjustTickAmount: function() { - var a = this.tickInterval, - b = this.tickPositions, - c = this.tickAmount, - d = this.finalTickAmt, - k = b && b.length, - q = C(this.threshold, this.softThreshold ? 0 : null); - if (this.hasData()) { - if (k < c) { - for (; b.length < c; ) - b.length % 2 || this.min === q - ? b.push(l(b[b.length - 1] + a)) - : b.unshift(l(b[0] - a)); - this.transA *= (k - 1) / (c - 1); - this.min = b[0]; - this.max = b[b.length - 1]; - } else k > c && ((this.tickInterval *= 2), this.setTickPositions()); - if (n(d)) { - for (a = c = b.length; a--; ) - ((3 === d && 1 === a % 2) || (2 >= d && 0 < a && a < c - 1)) && - b.splice(a, 1); - this.finalTickAmt = void 0; - } - } - }, - setScale: function() { - var a, b; - this.oldMin = this.min; - this.oldMax = this.max; - this.oldAxisLength = this.len; - this.setAxisSize(); - b = this.len !== this.oldAxisLength; - e(this.series, function(b) { - if (b.isDirtyData || b.isDirty || b.xAxis.isDirty) a = !0; - }); - b || - a || - this.isLinked || - this.forceRedraw || - this.userMin !== this.oldUserMin || - this.userMax !== this.oldUserMax || - this.alignToOthers() - ? (this.resetStacks && this.resetStacks(), - (this.forceRedraw = !1), - this.getSeriesExtremes(), - this.setTickInterval(), - (this.oldUserMin = this.userMin), - (this.oldUserMax = this.userMax), - this.isDirty || - (this.isDirty = - b || this.min !== this.oldMin || this.max !== this.oldMax)) - : this.cleanStacks && this.cleanStacks(); - }, - setExtremes: function(a, b, c, d, k) { - var g = this, - q = g.chart; - c = C(c, !0); - e(g.series, function(a) { - delete a.kdTree; - }); - k = h(k, { min: a, max: b }); - m(g, 'setExtremes', k, function() { - g.userMin = a; - g.userMax = b; - g.eventArgs = k; - c && q.redraw(d); - }); - }, - zoom: function(a, b) { - var g = this.dataMin, - c = this.dataMax, - d = this.options, - k = Math.min(g, C(d.min, g)), - d = Math.max(c, C(d.max, c)); - if (a !== this.min || b !== this.max) - this.allowZoomOutside || - (n(g) && (a < k && (a = k), a > d && (a = d)), - n(c) && (b < k && (b = k), b > d && (b = d))), - (this.displayBtn = void 0 !== a || void 0 !== b), - this.setExtremes(a, b, !1, void 0, { trigger: 'zoom' }); - return !0; - }, - setAxisSize: function() { - var b = this.chart, - c = this.options, - d = c.offsets || [0, 0, 0, 0], - k = this.horiz, - q = (this.width = Math.round( - a.relativeLength( - C(c.width, b.plotWidth - d[3] + d[1]), - b.plotWidth, - ), - )), - e = (this.height = Math.round( - a.relativeLength( - C(c.height, b.plotHeight - d[0] + d[2]), - b.plotHeight, - ), - )), - h = (this.top = Math.round( - a.relativeLength( - C(c.top, b.plotTop + d[0]), - b.plotHeight, - b.plotTop, - ), - )), - c = (this.left = Math.round( - a.relativeLength( - C(c.left, b.plotLeft + d[3]), - b.plotWidth, - b.plotLeft, - ), - )); - this.bottom = b.chartHeight - e - h; - this.right = b.chartWidth - q - c; - this.len = Math.max(k ? q : e, 0); - this.pos = k ? c : h; - }, - getExtremes: function() { - var a = this.isLog, - b = this.lin2log; - return { - min: a ? l(b(this.min)) : this.min, - max: a ? l(b(this.max)) : this.max, - dataMin: this.dataMin, - dataMax: this.dataMax, - userMin: this.userMin, - userMax: this.userMax, - }; - }, - getThreshold: function(a) { - var b = this.isLog, - g = this.lin2log, - c = b ? g(this.min) : this.min, - b = b ? g(this.max) : this.max; - null === a ? (a = c) : c > a ? (a = c) : b < a && (a = b); - return this.translate(a, 0, 1, 0, 1); - }, - autoLabelAlign: function(a) { - a = (C(a, 0) - 90 * this.side + 720) % 360; - return 15 < a && 165 > a - ? 'right' - : 195 < a && 345 > a - ? 'left' - : 'center'; - }, - tickSize: function(a) { - var b = this.options, - g = b[a + 'Length'], - c = C(b[a + 'Width'], 'tick' === a && this.isXAxis ? 1 : 0); - if (c && g) return 'inside' === b[a + 'Position'] && (g = -g), [g, c]; - }, - labelMetrics: function() { - var a = (this.tickPositions && this.tickPositions[0]) || 0; - return this.chart.renderer.fontMetrics( - this.options.labels.style && this.options.labels.style.fontSize, - this.ticks[a] && this.ticks[a].label, - ); - }, - unsquish: function() { - var a = this.options.labels, - b = this.horiz, - c = this.tickInterval, - d = c, - k = - this.len / (((this.categories ? 1 : 0) + this.max - this.min) / c), - q, - h = a.rotation, - m = this.labelMetrics(), - z, - A = Number.MAX_VALUE, - t, - x = function(a) { - a /= k || 1; - a = 1 < a ? Math.ceil(a) : 1; - return a * c; - }; - b - ? (t = - !a.staggerLines && - !a.step && - (n(h) - ? [h] - : k < C(a.autoRotationLimit, 80) && a.autoRotation)) && - e(t, function(a) { - var b; - if (a === h || (a && -90 <= a && 90 >= a)) - (z = x(Math.abs(m.h / Math.sin(w * a)))), - (b = z + Math.abs(a / 360)), - b < A && ((A = b), (q = a), (d = z)); - }) - : a.step || (d = x(m.h)); - this.autoRotation = t; - this.labelRotation = C(q, h); - return d; - }, - getSlotWidth: function() { - var a = this.chart, - b = this.horiz, - c = this.options.labels, - d = Math.max( - this.tickPositions.length - (this.categories ? 0 : 1), - 1, - ), - k = a.margin[3]; - return ( - (b && - 2 > (c.step || 0) && - !c.rotation && - ((this.staggerLines || 1) * this.len) / d) || - (!b && - ((c.style && parseInt(c.style.width, 10)) || - (k && k - a.spacing[3]) || - 0.33 * a.chartWidth)) - ); - }, - renderUnsquish: function() { - var a = this.chart, - b = a.renderer, - c = this.tickPositions, - d = this.ticks, - k = this.options.labels, - q = this.horiz, - h = this.getSlotWidth(), - m = Math.max(1, Math.round(h - 2 * (k.padding || 5))), - z = {}, - A = this.labelMetrics(), - t = k.style && k.style.textOverflow, - f, - F = 0, - l, - B; - I(k.rotation) || (z.rotation = k.rotation || 0); - e(c, function(a) { - (a = d[a]) && a.labelLength > F && (F = a.labelLength); - }); - this.maxLabelLength = F; - if (this.autoRotation) - F > m && F > A.h - ? (z.rotation = this.labelRotation) - : (this.labelRotation = 0); - else if (h && ((f = { width: m + 'px' }), !t)) - for (f.textOverflow = 'clip', l = c.length; !q && l--; ) - if (((B = c[l]), (m = d[B].label))) - m.styles && 'ellipsis' === m.styles.textOverflow - ? m.css({ textOverflow: 'clip' }) - : d[B].labelLength > h && m.css({ width: h + 'px' }), - m.getBBox().height > this.len / c.length - (A.h - A.f) && - (m.specCss = { textOverflow: 'ellipsis' }); - z.rotation && - ((f = { - width: - (F > 0.5 * a.chartHeight ? 0.33 * a.chartHeight : a.chartHeight) + - 'px', - }), - t || (f.textOverflow = 'ellipsis')); - if ( - (this.labelAlign = k.align || this.autoLabelAlign(this.labelRotation)) - ) - z.align = this.labelAlign; - e(c, function(a) { - var b = (a = d[a]) && a.label; - b && - (b.attr(z), - f && b.css(x(f, b.specCss)), - delete b.specCss, - (a.rotation = z.rotation)); - }); - this.tickRotCorr = b.rotCorr( - A.b, - this.labelRotation || 0, - 0 !== this.side, - ); - }, - hasData: function() { - return ( - this.hasVisibleSeries || - (n(this.min) && - n(this.max) && - this.tickPositions && - 0 < this.tickPositions.length) - ); - }, - addTitle: function(a) { - var b = this.chart.renderer, - g = this.horiz, - c = this.opposite, - d = this.options.title, - k; - this.axisTitle || - ((k = d.textAlign) || - (k = (g - ? { low: 'left', middle: 'center', high: 'right' } - : { - low: c ? 'right' : 'left', - middle: 'center', - high: c ? 'left' : 'right', - })[d.align]), - (this.axisTitle = b - .text(d.text, 0, 0, d.useHTML) - .attr({ zIndex: 7, rotation: d.rotation || 0, align: k }) - .addClass('highcharts-axis-title') - .css(d.style) - .add(this.axisGroup)), - (this.axisTitle.isNew = !0)); - d.style.width || - this.isRadial || - this.axisTitle.css({ width: this.len }); - this.axisTitle[a ? 'show' : 'hide'](!0); - }, - generateTick: function(a) { - var b = this.ticks; - b[a] ? b[a].addLabel() : (b[a] = new F(this, a)); - }, - getOffset: function() { - var a = this, - b = a.chart, - c = b.renderer, - d = a.options, - k = a.tickPositions, - q = a.ticks, - h = a.horiz, - m = a.side, - z = b.inverted && !a.isZAxis ? [1, 0, 3, 2][m] : m, - A, - x, - f = 0, - F, - l = 0, - B = d.title, - u = d.labels, - G = 0, - p = b.axisOffset, - b = b.clipOffset, - I = [-1, 1, 1, -1][m], - r = d.className, - w = a.axisParent, - K = this.tickSize('tick'); - A = a.hasData(); - a.showAxis = x = A || C(d.showEmpty, !0); - a.staggerLines = a.horiz && u.staggerLines; - a.axisGroup || - ((a.gridGroup = c - .g('grid') - .attr({ zIndex: d.gridZIndex || 1 }) - .addClass( - 'highcharts-' + this.coll.toLowerCase() + '-grid ' + (r || ''), - ) - .add(w)), - (a.axisGroup = c - .g('axis') - .attr({ zIndex: d.zIndex || 2 }) - .addClass('highcharts-' + this.coll.toLowerCase() + ' ' + (r || '')) - .add(w)), - (a.labelGroup = c - .g('axis-labels') - .attr({ zIndex: u.zIndex || 7 }) - .addClass( - 'highcharts-' + a.coll.toLowerCase() + '-labels ' + (r || ''), - ) - .add(w))); - A || a.isLinked - ? (e(k, function(b, c) { - a.generateTick(b, c); - }), - a.renderUnsquish(), - (a.reserveSpaceDefault = - 0 === m || - 2 === m || - { 1: 'left', 3: 'right' }[m] === a.labelAlign), - C( - u.reserveSpace, - 'center' === a.labelAlign ? !0 : null, - a.reserveSpaceDefault, - ) && - e(k, function(a) { - G = Math.max(q[a].getLabelSize(), G); - }), - a.staggerLines && (G *= a.staggerLines), - (a.labelOffset = G * (a.opposite ? -1 : 1))) - : t(q, function(a, b) { - a.destroy(); - delete q[b]; - }); - B && - B.text && - !1 !== B.enabled && - (a.addTitle(x), - x && - !1 !== B.reserveSpace && - ((a.titleOffset = f = a.axisTitle.getBBox()[ - h ? 'height' : 'width' - ]), - (F = B.offset), - (l = n(F) ? 0 : C(B.margin, h ? 5 : 10)))); - a.renderLine(); - a.offset = I * C(d.offset, p[m]); - a.tickRotCorr = a.tickRotCorr || { x: 0, y: 0 }; - c = 0 === m ? -a.labelMetrics().h : 2 === m ? a.tickRotCorr.y : 0; - l = Math.abs(G) + l; - G && (l = l - c + I * (h ? C(u.y, a.tickRotCorr.y + 8 * I) : u.x)); - a.axisTitleMargin = C(F, l); - p[m] = Math.max( - p[m], - a.axisTitleMargin + f + I * a.offset, - l, - A && k.length && K ? K[0] + I * a.offset : 0, - ); - d = d.offset ? 0 : 2 * Math.floor(a.axisLine.strokeWidth() / 2); - b[z] = Math.max(b[z], d); - }, - getLinePath: function(a) { - var b = this.chart, - c = this.opposite, - g = this.offset, - d = this.horiz, - k = this.left + (c ? this.width : 0) + g, - g = b.chartHeight - this.bottom - (c ? this.height : 0) + g; - c && (a *= -1); - return b.renderer.crispLine( - [ - 'M', - d ? this.left : k, - d ? g : this.top, - 'L', - d ? b.chartWidth - this.right : k, - d ? g : b.chartHeight - this.bottom, - ], - a, - ); - }, - renderLine: function() { - this.axisLine || - ((this.axisLine = this.chart.renderer - .path() - .addClass('highcharts-axis-line') - .add(this.axisGroup)), - this.axisLine.attr({ - stroke: this.options.lineColor, - 'stroke-width': this.options.lineWidth, - zIndex: 7, - })); - }, - getTitlePosition: function() { - var a = this.horiz, - b = this.left, - c = this.top, - d = this.len, - k = this.options.title, - q = a ? b : c, - e = this.opposite, - h = this.offset, - m = k.x || 0, - z = k.y || 0, - A = this.axisTitle, - t = this.chart.renderer.fontMetrics(k.style && k.style.fontSize, A), - A = Math.max(A.getBBox(null, 0).height - t.h - 1, 0), - d = { - low: q + (a ? 0 : d), - middle: q + d / 2, - high: q + (a ? d : 0), - }[k.align], - b = - (a ? c + this.height : b) + - (a ? 1 : -1) * (e ? -1 : 1) * this.axisTitleMargin + - [-A, A, t.f, -A][this.side]; - return { - x: a ? d + m : b + (e ? this.width : 0) + h + m, - y: a ? b + z - (e ? this.height : 0) + h : d + z, - }; - }, - renderMinorTick: function(a) { - var b = this.chart.hasRendered && B(this.oldMin), - c = this.minorTicks; - c[a] || (c[a] = new F(this, a, 'minor')); - b && c[a].isNew && c[a].render(null, !0); - c[a].render(null, !1, 1); - }, - renderTick: function(a, b) { - var c = this.isLinked, - g = this.ticks, - d = this.chart.hasRendered && B(this.oldMin); - if (!c || (a >= this.min && a <= this.max)) - g[a] || (g[a] = new F(this, a)), - d && g[a].isNew && g[a].render(b, !0, 0.1), - g[a].render(b); - }, - render: function() { - var b = this, - c = b.chart, - d = b.options, - k = b.isLog, - q = b.lin2log, - h = b.isLinked, - m = b.tickPositions, - z = b.axisTitle, - x = b.ticks, - f = b.minorTicks, - l = b.alternateBands, - C = d.stackLabels, - n = d.alternateGridColor, - u = b.tickmarkOffset, - G = b.axisLine, - p = b.showAxis, - I = D(c.renderer.globalAnimation), - r, - w; - b.labelEdge.length = 0; - b.overlap = !1; - e([x, f, l], function(a) { - t(a, function(a) { - a.isActive = !1; - }); - }); - if (b.hasData() || h) - b.minorTickInterval && - !b.categories && - e(b.getMinorTickPositions(), function(a) { - b.renderMinorTick(a); - }), - m.length && - (e(m, function(a, c) { - b.renderTick(a, c); - }), - u && - (0 === b.min || b.single) && - (x[-1] || (x[-1] = new F(b, -1, null, !0)), x[-1].render(-1))), - n && - e(m, function(d, g) { - w = void 0 !== m[g + 1] ? m[g + 1] + u : b.max - u; - 0 === g % 2 && - d < b.max && - w <= b.max + (c.polar ? -u : u) && - (l[d] || (l[d] = new a.PlotLineOrBand(b)), - (r = d + u), - (l[d].options = { - from: k ? q(r) : r, - to: k ? q(w) : w, - color: n, - }), - l[d].render(), - (l[d].isActive = !0)); - }), - b._addedPlotLB || - (e((d.plotLines || []).concat(d.plotBands || []), function(a) { - b.addPlotBandOrLine(a); - }), - (b._addedPlotLB = !0)); - e([x, f, l], function(a) { - var b, - d = [], - g = I.duration; - t(a, function(a, b) { - a.isActive || (a.render(b, !1, 0), (a.isActive = !1), d.push(b)); - }); - A( - function() { - for (b = d.length; b--; ) - a[d[b]] && - !a[d[b]].isActive && - (a[d[b]].destroy(), delete a[d[b]]); - }, - a !== l && c.hasRendered && g ? g : 0, - ); - }); - G && - (G[G.isPlaced ? 'animate' : 'attr']({ - d: this.getLinePath(G.strokeWidth()), - }), - (G.isPlaced = !0), - G[p ? 'show' : 'hide'](!0)); - z && - p && - ((d = b.getTitlePosition()), - B(d.y) - ? (z[z.isNew ? 'attr' : 'animate'](d), (z.isNew = !1)) - : (z.attr('y', -9999), (z.isNew = !0))); - C && C.enabled && b.renderStackTotals(); - b.isDirty = !1; - }, - redraw: function() { - this.visible && - (this.render(), - e(this.plotLinesAndBands, function(a) { - a.render(); - })); - e(this.series, function(a) { - a.isDirty = !0; - }); - }, - keepProps: 'extKey hcEvents names series userMax userMin'.split(' '), - destroy: function(a) { - var b = this, - c = b.stacks, - d = b.plotLinesAndBands, - g; - a || N(b); - t(c, function(a, b) { - u(a); - c[b] = null; - }); - e([b.ticks, b.minorTicks, b.alternateBands], function(a) { - u(a); - }); - if (d) for (a = d.length; a--; ) d[a].destroy(); - e( - 'stackTotalGroup axisLine axisTitle axisGroup gridGroup labelGroup cross'.split( - ' ', - ), - function(a) { - b[a] && (b[a] = b[a].destroy()); - }, - ); - for (g in b.plotLinesAndBandsGroups) - b.plotLinesAndBandsGroups[g] = b.plotLinesAndBandsGroups[g].destroy(); - t(b, function(a, c) { - -1 === k(c, b.keepProps) && delete b[c]; - }); - }, - drawCrosshair: function(a, b) { - var c, - d = this.crosshair, - g = C(d.snap, !0), - k, - q = this.cross; - a || (a = this.cross && this.cross.e); - this.crosshair && !1 !== (n(b) || !g) - ? (g - ? n(b) && (k = this.isXAxis ? b.plotX : this.len - b.plotY) - : (k = - a && - (this.horiz - ? a.chartX - this.pos - : this.len - a.chartY + this.pos)), - n(k) && - (c = - this.getPlotLinePath( - b && (this.isXAxis ? b.x : C(b.stackY, b.y)), - null, - null, - null, - k, - ) || null), - n(c) - ? ((b = this.categories && !this.isRadial), - q || - ((this.cross = q = this.chart.renderer - .path() - .addClass( - 'highcharts-crosshair highcharts-crosshair-' + - (b ? 'category ' : 'thin ') + - d.className, - ) - .attr({ zIndex: C(d.zIndex, 2) }) - .add()), - q - .attr({ - stroke: - d.color || - (b - ? f('#ccd6eb') - .setOpacity(0.25) - .get() - : '#cccccc'), - 'stroke-width': C(d.width, 1), - }) - .css({ 'pointer-events': 'none' }), - d.dashStyle && q.attr({ dashstyle: d.dashStyle })), - q.show().attr({ d: c }), - b && !d.width && q.attr({ 'stroke-width': this.transA }), - (this.cross.e = a)) - : this.hideCrosshair()) - : this.hideCrosshair(); - }, - hideCrosshair: function() { - this.cross && this.cross.hide(); - }, - }); - return (a.Axis = G); - })(M); - (function(a) { - var E = a.Axis, - D = a.Date, - H = a.dateFormat, - p = a.defaultOptions, - f = a.defined, - l = a.each, - r = a.extend, - n = a.getMagnitude, - w = a.getTZOffset, - u = a.normalizeTickInterval, - e = a.pick, - h = a.timeUnits; - E.prototype.getTimeTicks = function(a, d, c, b) { - var k = [], - m = {}, - B = p.global.useUTC, - n, - x = new D(d - Math.max(w(d), w(c))), - u = D.hcMakeTime, - t = a.unitRange, - C = a.count, - N, - q; - if (f(d)) { - x[D.hcSetMilliseconds]( - t >= h.second ? 0 : C * Math.floor(x.getMilliseconds() / C), - ); - if (t >= h.second) - x[D.hcSetSeconds]( - t >= h.minute ? 0 : C * Math.floor(x.getSeconds() / C), - ); - if (t >= h.minute) - x[D.hcSetMinutes]( - t >= h.hour ? 0 : C * Math.floor(x[D.hcGetMinutes]() / C), - ); - if (t >= h.hour) - x[D.hcSetHours]( - t >= h.day ? 0 : C * Math.floor(x[D.hcGetHours]() / C), - ); - if (t >= h.day) - x[D.hcSetDate]( - t >= h.month ? 1 : C * Math.floor(x[D.hcGetDate]() / C), - ); - t >= h.month && - (x[D.hcSetMonth]( - t >= h.year ? 0 : C * Math.floor(x[D.hcGetMonth]() / C), - ), - (n = x[D.hcGetFullYear]())); - if (t >= h.year) x[D.hcSetFullYear](n - (n % C)); - if (t === h.week) - x[D.hcSetDate](x[D.hcGetDate]() - x[D.hcGetDay]() + e(b, 1)); - n = x[D.hcGetFullYear](); - b = x[D.hcGetMonth](); - var A = x[D.hcGetDate](), - F = x[D.hcGetHours](); - d = x.getTime(); - D.hcHasTimeZone && - ((q = - (!B || !!D.hcGetTimezoneOffset) && - (c - d > 4 * h.month || w(d) !== w(c))), - (N = w(x)), - (x = new D(d + N))); - B = x.getTime(); - for (d = 1; B < c; ) - k.push(B), - (B = - t === h.year - ? u(n + d * C, 0) - : t === h.month - ? u(n, b + d * C) - : !q || (t !== h.day && t !== h.week) - ? q && t === h.hour - ? u(n, b, A, F + d * C, 0, 0, N) - N - : B + t * C - : u(n, b, A + d * C * (t === h.day ? 1 : 7))), - d++; - k.push(B); - t <= h.hour && - 1e4 > k.length && - l(k, function(a) { - 0 === a % 18e5 && - '000000000' === H('%H%M%S%L', a) && - (m[a] = 'day'); - }); - } - k.info = r(a, { higherRanks: m, totalRange: t * C }); - return k; - }; - E.prototype.normalizeTimeTickInterval = function(a, d) { - var c = d || [ - ['millisecond', [1, 2, 5, 10, 20, 25, 50, 100, 200, 500]], - ['second', [1, 2, 5, 10, 15, 30]], - ['minute', [1, 2, 5, 10, 15, 30]], - ['hour', [1, 2, 3, 4, 6, 8, 12]], - ['day', [1, 2]], - ['week', [1, 2]], - ['month', [1, 2, 3, 4, 6]], - ['year', null], - ]; - d = c[c.length - 1]; - var b = h[d[0]], - k = d[1], - e; - for ( - e = 0; - e < c.length && - !((d = c[e]), - (b = h[d[0]]), - (k = d[1]), - c[e + 1] && a <= (b * k[k.length - 1] + h[c[e + 1][0]]) / 2); - e++ - ); - b === h.year && a < 5 * b && (k = [1, 2, 5]); - a = u(a / b, k, 'year' === d[0] ? Math.max(n(a / b), 1) : 1); - return { unitRange: b, count: a, unitName: d[0] }; - }; - })(M); - (function(a) { - var E = a.Axis, - D = a.getMagnitude, - H = a.map, - p = a.normalizeTickInterval, - f = a.pick; - E.prototype.getLogTickPositions = function(a, r, n, w) { - var l = this.options, - e = this.len, - h = this.lin2log, - m = this.log2lin, - d = []; - w || (this._minorAutoInterval = null); - if (0.5 <= a) - (a = Math.round(a)), (d = this.getLinearTickPositions(a, r, n)); - else if (0.08 <= a) - for ( - var e = Math.floor(r), - c, - b, - k, - z, - B, - l = - 0.3 < a - ? [1, 2, 4] - : 0.15 < a - ? [1, 2, 4, 6, 8] - : [1, 2, 3, 4, 5, 6, 7, 8, 9]; - e < n + 1 && !B; - e++ - ) - for (b = l.length, c = 0; c < b && !B; c++) - (k = m(h(e) * l[c])), - k > r && (!w || z <= n) && void 0 !== z && d.push(z), - z > n && (B = !0), - (z = k); - else - (r = h(r)), - (n = h(n)), - (a = w ? this.getMinorTickInterval() : l.tickInterval), - (a = f( - 'auto' === a ? null : a, - this._minorAutoInterval, - ((l.tickPixelInterval / (w ? 5 : 1)) * (n - r)) / - ((w ? e / this.tickPositions.length : e) || 1), - )), - (a = p(a, null, D(a))), - (d = H(this.getLinearTickPositions(a, r, n), m)), - w || (this._minorAutoInterval = a / 5); - w || (this.tickInterval = a); - return d; - }; - E.prototype.log2lin = function(a) { - return Math.log(a) / Math.LN10; - }; - E.prototype.lin2log = function(a) { - return Math.pow(10, a); - }; - })(M); - (function(a, E) { - var D = a.arrayMax, - H = a.arrayMin, - p = a.defined, - f = a.destroyObjectProperties, - l = a.each, - r = a.erase, - n = a.merge, - w = a.pick; - a.PlotLineOrBand = function(a, e) { - this.axis = a; - e && ((this.options = e), (this.id = e.id)); - }; - a.PlotLineOrBand.prototype = { - render: function() { - var f = this, - e = f.axis, - h = e.horiz, - m = f.options, - d = m.label, - c = f.label, - b = m.to, - k = m.from, - z = m.value, - l = p(k) && p(b), - r = p(z), - x = f.svgElem, - K = !x, - t = [], - C = m.color, - N = w(m.zIndex, 0), - q = m.events, - t = { - class: - 'highcharts-plot-' + - (l ? 'band ' : 'line ') + - (m.className || ''), - }, - A = {}, - F = e.chart.renderer, - G = l ? 'bands' : 'lines', - g = e.log2lin; - e.isLog && ((k = g(k)), (b = g(b)), (z = g(z))); - r - ? ((t = { stroke: C, 'stroke-width': m.width }), - m.dashStyle && (t.dashstyle = m.dashStyle)) - : l && - (C && (t.fill = C), - m.borderWidth && - ((t.stroke = m.borderColor), - (t['stroke-width'] = m.borderWidth))); - A.zIndex = N; - G += '-' + N; - (C = e.plotLinesAndBandsGroups[G]) || - (e.plotLinesAndBandsGroups[G] = C = F.g('plot-' + G) - .attr(A) - .add()); - K && - (f.svgElem = x = F.path() - .attr(t) - .add(C)); - if (r) t = e.getPlotLinePath(z, x.strokeWidth()); - else if (l) t = e.getPlotBandPath(k, b, m); - else return; - K && t && t.length - ? (x.attr({ d: t }), - q && - a.objectEach(q, function(a, b) { - x.on(b, function(a) { - q[b].apply(f, [a]); - }); - })) - : x && - (t - ? (x.show(), x.animate({ d: t })) - : (x.hide(), c && (f.label = c = c.destroy()))); - d && - p(d.text) && - t && - t.length && - 0 < e.width && - 0 < e.height && - !t.flat - ? ((d = n( - { - align: h && l && 'center', - x: h ? !l && 4 : 10, - verticalAlign: !h && l && 'middle', - y: h ? (l ? 16 : 10) : l ? 6 : -4, - rotation: h && !l && 90, - }, - d, - )), - this.renderLabel(d, t, l, N)) - : c && c.hide(); - return f; - }, - renderLabel: function(a, e, h, m) { - var d = this.label, - c = this.axis.chart.renderer; - d || - ((d = { - align: a.textAlign || a.align, - rotation: a.rotation, - class: - 'highcharts-plot-' + - (h ? 'band' : 'line') + - '-label ' + - (a.className || ''), - }), - (d.zIndex = m), - (this.label = d = c - .text(a.text, 0, 0, a.useHTML) - .attr(d) - .add()), - d.css(a.style)); - m = e.xBounds || [e[1], e[4], h ? e[6] : e[1]]; - e = e.yBounds || [e[2], e[5], h ? e[7] : e[2]]; - h = H(m); - c = H(e); - d.align(a, !1, { x: h, y: c, width: D(m) - h, height: D(e) - c }); - d.show(); - }, - destroy: function() { - r(this.axis.plotLinesAndBands, this); - delete this.axis; - f(this); - }, - }; - a.extend(E.prototype, { - getPlotBandPath: function(a, e) { - var h = this.getPlotLinePath(e, null, null, !0), - m = this.getPlotLinePath(a, null, null, !0), - d = [], - c = this.horiz, - b = 1, - k; - a = (a < this.min && e < this.min) || (a > this.max && e > this.max); - if (m && h) - for ( - a && ((k = m.toString() === h.toString()), (b = 0)), a = 0; - a < m.length; - a += 6 - ) - c && h[a + 1] === m[a + 1] - ? ((h[a + 1] += b), (h[a + 4] += b)) - : c || - h[a + 2] !== m[a + 2] || - ((h[a + 2] += b), (h[a + 5] += b)), - d.push( - 'M', - m[a + 1], - m[a + 2], - 'L', - m[a + 4], - m[a + 5], - h[a + 4], - h[a + 5], - h[a + 1], - h[a + 2], - 'z', - ), - (d.flat = k); - return d; - }, - addPlotBand: function(a) { - return this.addPlotBandOrLine(a, 'plotBands'); - }, - addPlotLine: function(a) { - return this.addPlotBandOrLine(a, 'plotLines'); - }, - addPlotBandOrLine: function(f, e) { - var h = new a.PlotLineOrBand(this, f).render(), - m = this.userOptions; - h && - (e && ((m[e] = m[e] || []), m[e].push(f)), - this.plotLinesAndBands.push(h)); - return h; - }, - removePlotBandOrLine: function(a) { - for ( - var e = this.plotLinesAndBands, - h = this.options, - m = this.userOptions, - d = e.length; - d--; - - ) - e[d].id === a && e[d].destroy(); - l( - [ - h.plotLines || [], - m.plotLines || [], - h.plotBands || [], - m.plotBands || [], - ], - function(c) { - for (d = c.length; d--; ) c[d].id === a && r(c, c[d]); - }, - ); - }, - removePlotBand: function(a) { - this.removePlotBandOrLine(a); - }, - removePlotLine: function(a) { - this.removePlotBandOrLine(a); - }, - }); - })(M, V); - (function(a) { - var E = a.dateFormat, - D = a.each, - H = a.extend, - p = a.format, - f = a.isNumber, - l = a.map, - r = a.merge, - n = a.pick, - w = a.splat, - u = a.syncTimeout, - e = a.timeUnits; - a.Tooltip = function() { - this.init.apply(this, arguments); - }; - a.Tooltip.prototype = { - init: function(a, e) { - this.chart = a; - this.options = e; - this.crosshairs = []; - this.now = { x: 0, y: 0 }; - this.isHidden = !0; - this.split = e.split && !a.inverted; - this.shared = e.shared || this.split; - }, - cleanSplit: function(a) { - D(this.chart.series, function(e) { - var d = e && e.tt; - d && (!d.isActive || a ? (e.tt = d.destroy()) : (d.isActive = !1)); - }); - }, - getLabel: function() { - var a = this.chart.renderer, - e = this.options; - this.label || - (this.split - ? (this.label = a.g('tooltip')) - : ((this.label = a - .label( - '', - 0, - 0, - e.shape || 'callout', - null, - null, - e.useHTML, - null, - 'tooltip', - ) - .attr({ padding: e.padding, r: e.borderRadius })), - this.label - .attr({ - fill: e.backgroundColor, - 'stroke-width': e.borderWidth, - }) - .css(e.style) - .shadow(e.shadow)), - this.label.attr({ zIndex: 8 }).add()); - return this.label; - }, - update: function(a) { - this.destroy(); - r(!0, this.chart.options.tooltip.userOptions, a); - this.init(this.chart, r(!0, this.options, a)); - }, - destroy: function() { - this.label && (this.label = this.label.destroy()); - this.split && - this.tt && - (this.cleanSplit(this.chart, !0), (this.tt = this.tt.destroy())); - clearTimeout(this.hideTimer); - clearTimeout(this.tooltipTimeout); - }, - move: function(a, e, d, c) { - var b = this, - k = b.now, - h = - !1 !== b.options.animation && - !b.isHidden && - (1 < Math.abs(a - k.x) || 1 < Math.abs(e - k.y)), - m = b.followPointer || 1 < b.len; - H(k, { - x: h ? (2 * k.x + a) / 3 : a, - y: h ? (k.y + e) / 2 : e, - anchorX: m ? void 0 : h ? (2 * k.anchorX + d) / 3 : d, - anchorY: m ? void 0 : h ? (k.anchorY + c) / 2 : c, - }); - b.getLabel().attr(k); - h && - (clearTimeout(this.tooltipTimeout), - (this.tooltipTimeout = setTimeout(function() { - b && b.move(a, e, d, c); - }, 32))); - }, - hide: function(a) { - var e = this; - clearTimeout(this.hideTimer); - a = n(a, this.options.hideDelay, 500); - this.isHidden || - (this.hideTimer = u(function() { - e.getLabel()[a ? 'fadeOut' : 'hide'](); - e.isHidden = !0; - }, a)); - }, - getAnchor: function(a, e) { - var d, - c = this.chart, - b = c.inverted, - k = c.plotTop, - h = c.plotLeft, - m = 0, - f = 0, - x, - n; - a = w(a); - d = a[0].tooltipPos; - this.followPointer && - e && - (void 0 === e.chartX && (e = c.pointer.normalize(e)), - (d = [e.chartX - c.plotLeft, e.chartY - k])); - d || - (D(a, function(a) { - x = a.series.yAxis; - n = a.series.xAxis; - m += a.plotX + (!b && n ? n.left - h : 0); - f += - (a.plotLow ? (a.plotLow + a.plotHigh) / 2 : a.plotY) + - (!b && x ? x.top - k : 0); - }), - (m /= a.length), - (f /= a.length), - (d = [ - b ? c.plotWidth - f : m, - this.shared && !b && 1 < a.length && e - ? e.chartY - k - : b - ? c.plotHeight - m - : f, - ])); - return l(d, Math.round); - }, - getPosition: function(a, e, d) { - var c = this.chart, - b = this.distance, - k = {}, - h = (c.inverted && d.h) || 0, - m, - f = [ - 'y', - c.chartHeight, - e, - d.plotY + c.plotTop, - c.plotTop, - c.plotTop + c.plotHeight, - ], - x = [ - 'x', - c.chartWidth, - a, - d.plotX + c.plotLeft, - c.plotLeft, - c.plotLeft + c.plotWidth, - ], - l = !this.followPointer && n(d.ttBelow, !c.inverted === !!d.negative), - t = function(a, c, d, g, e, q) { - var m = d < g - b, - z = g + b + d < c, - A = g - b - d; - g += b; - if (l && z) k[a] = g; - else if (!l && m) k[a] = A; - else if (m) k[a] = Math.min(q - d, 0 > A - h ? A : A - h); - else if (z) k[a] = Math.max(e, g + h + d > c ? g : g + h); - else return !1; - }, - C = function(a, c, d, g) { - var e; - g < b || g > c - b - ? (e = !1) - : (k[a] = g < d / 2 ? 1 : g > c - d / 2 ? c - d - 2 : g - d / 2); - return e; - }, - p = function(a) { - var b = f; - f = x; - x = b; - m = a; - }, - q = function() { - !1 !== t.apply(0, f) - ? !1 !== C.apply(0, x) || m || (p(!0), q()) - : m - ? (k.x = k.y = 0) - : (p(!0), q()); - }; - (c.inverted || 1 < this.len) && p(); - q(); - return k; - }, - defaultFormatter: function(a) { - var e = this.points || w(this), - d; - d = [a.tooltipFooterHeaderFormatter(e[0])]; - d = d.concat(a.bodyFormatter(e)); - d.push(a.tooltipFooterHeaderFormatter(e[0], !0)); - return d; - }, - refresh: function(a, e) { - var d, - c = this.options, - b, - k = a, - h, - m = {}, - f = []; - d = c.formatter || this.defaultFormatter; - var m = this.shared, - x; - c.enabled && - (clearTimeout(this.hideTimer), - (this.followPointer = w(k)[0].series.tooltipOptions.followPointer), - (h = this.getAnchor(k, e)), - (e = h[0]), - (b = h[1]), - !m || (k.series && k.series.noSharedTooltip) - ? (m = k.getLabelConfig()) - : (D(k, function(a) { - a.setState('hover'); - f.push(a.getLabelConfig()); - }), - (m = { x: k[0].category, y: k[0].y }), - (m.points = f), - (k = k[0])), - (this.len = f.length), - (m = d.call(m, this)), - (x = k.series), - (this.distance = n(x.tooltipOptions.distance, 16)), - !1 === m - ? this.hide() - : ((d = this.getLabel()), - this.isHidden && d.attr({ opacity: 1 }).show(), - this.split - ? this.renderSplit(m, w(a)) - : (c.style.width || - d.css({ width: this.chart.spacingBox.width }), - d.attr({ text: m && m.join ? m.join('') : m }), - d - .removeClass(/highcharts-color-[\d]+/g) - .addClass( - 'highcharts-color-' + n(k.colorIndex, x.colorIndex), - ), - d.attr({ - stroke: c.borderColor || k.color || x.color || '#666666', - }), - this.updatePosition({ - plotX: e, - plotY: b, - negative: k.negative, - ttBelow: k.ttBelow, - h: h[2] || 0, - })), - (this.isHidden = !1))); - }, - renderSplit: function(e, m) { - var d = this, - c = [], - b = this.chart, - k = b.renderer, - h = !0, - f = this.options, - l = 0, - x = this.getLabel(); - a.isString(e) && (e = [!1, e]); - D(e.slice(0, m.length + 1), function(a, e) { - if (!1 !== a) { - e = m[e - 1] || { isHeader: !0, plotX: m[0].plotX }; - var z = e.series || d, - t = z.tt, - q = e.series || {}, - A = 'highcharts-color-' + n(e.colorIndex, q.colorIndex, 'none'); - t || - (z.tt = t = k - .label(null, null, null, 'callout', null, null, f.useHTML) - .addClass('highcharts-tooltip-box ' + A) - .attr({ - padding: f.padding, - r: f.borderRadius, - fill: f.backgroundColor, - stroke: f.borderColor || e.color || q.color || '#333333', - 'stroke-width': f.borderWidth, - }) - .add(x)); - t.isActive = !0; - t.attr({ text: a }); - t.css(f.style).shadow(f.shadow); - a = t.getBBox(); - q = a.width + t.strokeWidth(); - e.isHeader - ? ((l = a.height), - (q = Math.max( - 0, - Math.min(e.plotX + b.plotLeft - q / 2, b.chartWidth - q), - ))) - : (q = e.plotX + b.plotLeft - n(f.distance, 16) - q); - 0 > q && (h = !1); - a = - (e.series && e.series.yAxis && e.series.yAxis.pos) + - (e.plotY || 0); - a -= b.plotTop; - c.push({ - target: e.isHeader ? b.plotHeight + l : a, - rank: e.isHeader ? 1 : 0, - size: z.tt.getBBox().height + 1, - point: e, - x: q, - tt: t, - }); - } - }); - this.cleanSplit(); - a.distribute(c, b.plotHeight + l); - D(c, function(a) { - var c = a.point, - d = c.series; - a.tt.attr({ - visibility: void 0 === a.pos ? 'hidden' : 'inherit', - x: h || c.isHeader ? a.x : c.plotX + b.plotLeft + n(f.distance, 16), - y: a.pos + b.plotTop, - anchorX: c.isHeader ? c.plotX + b.plotLeft : c.plotX + d.xAxis.pos, - anchorY: c.isHeader - ? a.pos + b.plotTop - 15 - : c.plotY + d.yAxis.pos, - }); - }); - }, - updatePosition: function(a) { - var e = this.chart, - d = this.getLabel(), - d = (this.options.positioner || this.getPosition).call( - this, - d.width, - d.height, - a, - ); - this.move( - Math.round(d.x), - Math.round(d.y || 0), - a.plotX + e.plotLeft, - a.plotY + e.plotTop, - ); - }, - getDateFormat: function(a, m, d, c) { - var b = E('%m-%d %H:%M:%S.%L', m), - k, - h, - f = { millisecond: 15, second: 12, minute: 9, hour: 6, day: 3 }, - l = 'millisecond'; - for (h in e) { - if ( - a === e.week && - +E('%w', m) === d && - '00:00:00.000' === b.substr(6) - ) { - h = 'week'; - break; - } - if (e[h] > a) { - h = l; - break; - } - if (f[h] && b.substr(f[h]) !== '01-01 00:00:00.000'.substr(f[h])) - break; - 'week' !== h && (l = h); - } - h && (k = c[h]); - return k; - }, - getXDateFormat: function(a, e, d) { - e = e.dateTimeLabelFormats; - var c = d && d.closestPointRange; - return ( - (c ? this.getDateFormat(c, a.x, d.options.startOfWeek, e) : e.day) || - e.year - ); - }, - tooltipFooterHeaderFormatter: function(a, e) { - e = e ? 'footer' : 'header'; - var d = a.series, - c = d.tooltipOptions, - b = c.xDateFormat, - k = d.xAxis, - h = k && 'datetime' === k.options.type && f(a.key), - m = c[e + 'Format']; - h && !b && (b = this.getXDateFormat(a, c, k)); - h && - b && - D((a.point && a.point.tooltipDateKeys) || ['key'], function(a) { - m = m.replace('{point.' + a + '}', '{point.' + a + ':' + b + '}'); - }); - return p(m, { point: a, series: d }); - }, - bodyFormatter: function(a) { - return l(a, function(a) { - var d = a.series.tooltipOptions; - return ( - d[(a.point.formatPrefix || 'point') + 'Formatter'] || - a.point.tooltipFormatter - ).call(a.point, d[(a.point.formatPrefix || 'point') + 'Format']); - }); - }, - }; - })(M); - (function(a) { - var E = a.addEvent, - D = a.attr, - H = a.charts, - p = a.color, - f = a.css, - l = a.defined, - r = a.each, - n = a.extend, - w = a.find, - u = a.fireEvent, - e = a.isObject, - h = a.offset, - m = a.pick, - d = a.splat, - c = a.Tooltip; - a.Pointer = function(a, c) { - this.init(a, c); - }; - a.Pointer.prototype = { - init: function(a, d) { - this.options = d; - this.chart = a; - this.runChartClick = d.chart.events && !!d.chart.events.click; - this.pinchDown = []; - this.lastValidTouch = {}; - c && - ((a.tooltip = new c(a, d.tooltip)), - (this.followTouchMove = m(d.tooltip.followTouchMove, !0))); - this.setDOMEvents(); - }, - zoomOption: function(a) { - var b = this.chart, - c = b.options.chart, - d = c.zoomType || '', - b = b.inverted; - /touch/.test(a.type) && (d = m(c.pinchType, d)); - this.zoomX = a = /x/.test(d); - this.zoomY = d = /y/.test(d); - this.zoomHor = (a && !b) || (d && b); - this.zoomVert = (d && !b) || (a && b); - this.hasZoom = a || d; - }, - normalize: function(a, c) { - var b; - b = a.touches - ? a.touches.length - ? a.touches.item(0) - : a.changedTouches[0] - : a; - c || (this.chartPosition = c = h(this.chart.container)); - return n(a, { - chartX: Math.round(b.pageX - c.left), - chartY: Math.round(b.pageY - c.top), - }); - }, - getCoordinates: function(a) { - var b = { xAxis: [], yAxis: [] }; - r(this.chart.axes, function(c) { - b[c.isXAxis ? 'xAxis' : 'yAxis'].push({ - axis: c, - value: c.toValue(a[c.horiz ? 'chartX' : 'chartY']), - }); - }); - return b; - }, - findNearestKDPoint: function(a, c, d) { - var b; - r(a, function(a) { - var k = - !(a.noSharedTooltip && c) && - 0 > a.options.findNearestPointBy.indexOf('y'); - a = a.searchPoint(d, k); - if ((k = e(a, !0)) && !(k = !e(b, !0))) - var k = b.distX - a.distX, - h = b.dist - a.dist, - m = - (a.series.group && a.series.group.zIndex) - - (b.series.group && b.series.group.zIndex), - k = - 0 < - (0 !== k && c - ? k - : 0 !== h - ? h - : 0 !== m - ? m - : b.series.index > a.series.index - ? -1 - : 1); - k && (b = a); - }); - return b; - }, - getPointFromEvent: function(a) { - a = a.target; - for (var b; a && !b; ) (b = a.point), (a = a.parentNode); - return b; - }, - getChartCoordinatesFromPoint: function(a, c) { - var b = a.series, - d = b.xAxis, - b = b.yAxis, - k = m(a.clientX, a.plotX); - if (d && b) - return c - ? { chartX: d.len + d.pos - k, chartY: b.len + b.pos - a.plotY } - : { chartX: k + d.pos, chartY: a.plotY + b.pos }; - }, - getHoverData: function(b, c, d, h, f, l, n) { - var k, - z = [], - x = n && n.isBoosting; - h = !(!h || !b); - n = - c && !c.stickyTracking - ? [c] - : a.grep(d, function(a) { - return ( - a.visible && - !(!f && a.directTouch) && - m(a.options.enableMouseTracking, !0) && - a.stickyTracking - ); - }); - c = (k = h ? b : this.findNearestKDPoint(n, f, l)) && k.series; - k && - (f && !c.noSharedTooltip - ? ((n = a.grep(d, function(a) { - return ( - a.visible && - !(!f && a.directTouch) && - m(a.options.enableMouseTracking, !0) && - !a.noSharedTooltip - ); - })), - r(n, function(a) { - var b = w(a.points, function(a) { - return a.x === k.x && !a.isNull; - }); - e(b) && (x && (b = a.getPoint(b)), z.push(b)); - })) - : z.push(k)); - return { hoverPoint: k, hoverSeries: c, hoverPoints: z }; - }, - runPointActions: function(b, c) { - var d = this.chart, - k = d.tooltip && d.tooltip.options.enabled ? d.tooltip : void 0, - e = k ? k.shared : !1, - h = c || d.hoverPoint, - f = (h && h.series) || d.hoverSeries, - f = this.getHoverData( - h, - f, - d.series, - !!c || (f && f.directTouch && this.isDirectTouch), - e, - b, - { isBoosting: d.isBoosting }, - ), - l, - h = f.hoverPoint; - l = f.hoverPoints; - c = (f = f.hoverSeries) && f.tooltipOptions.followPointer; - e = e && f && !f.noSharedTooltip; - if (h && (h !== d.hoverPoint || (k && k.isHidden))) { - r(d.hoverPoints || [], function(b) { - -1 === a.inArray(b, l) && b.setState(); - }); - r(l || [], function(a) { - a.setState('hover'); - }); - if (d.hoverSeries !== f) f.onMouseOver(); - d.hoverPoint && d.hoverPoint.firePointEvent('mouseOut'); - if (!h.series) return; - h.firePointEvent('mouseOver'); - d.hoverPoints = l; - d.hoverPoint = h; - k && k.refresh(e ? l : h, b); - } else - c && - k && - !k.isHidden && - ((h = k.getAnchor([{}], b)), - k.updatePosition({ plotX: h[0], plotY: h[1] })); - this.unDocMouseMove || - (this.unDocMouseMove = E( - d.container.ownerDocument, - 'mousemove', - function(b) { - var c = H[a.hoverChartIndex]; - if (c) c.pointer.onDocumentMouseMove(b); - }, - )); - r(d.axes, function(c) { - var d = m(c.crosshair.snap, !0), - k = d - ? a.find(l, function(a) { - return a.series[c.coll] === c; - }) - : void 0; - k || !d ? c.drawCrosshair(b, k) : c.hideCrosshair(); - }); - }, - reset: function(a, c) { - var b = this.chart, - k = b.hoverSeries, - e = b.hoverPoint, - h = b.hoverPoints, - m = b.tooltip, - f = m && m.shared ? h : e; - a && - f && - r(d(f), function(b) { - b.series.isCartesian && void 0 === b.plotX && (a = !1); - }); - if (a) - m && - f && - (m.refresh(f), - e && - (e.setState(e.state, !0), - r(b.axes, function(a) { - a.crosshair && a.drawCrosshair(null, e); - }))); - else { - if (e) e.onMouseOut(); - h && - r(h, function(a) { - a.setState(); - }); - if (k) k.onMouseOut(); - m && m.hide(c); - this.unDocMouseMove && (this.unDocMouseMove = this.unDocMouseMove()); - r(b.axes, function(a) { - a.hideCrosshair(); - }); - this.hoverX = b.hoverPoints = b.hoverPoint = null; - } - }, - scaleGroups: function(a, c) { - var b = this.chart, - d; - r(b.series, function(k) { - d = a || k.getPlotBox(); - k.xAxis && - k.xAxis.zoomEnabled && - k.group && - (k.group.attr(d), - k.markerGroup && - (k.markerGroup.attr(d), - k.markerGroup.clip(c ? b.clipRect : null)), - k.dataLabelsGroup && k.dataLabelsGroup.attr(d)); - }); - b.clipRect.attr(c || b.clipBox); - }, - dragStart: function(a) { - var b = this.chart; - b.mouseIsDown = a.type; - b.cancelClick = !1; - b.mouseDownX = this.mouseDownX = a.chartX; - b.mouseDownY = this.mouseDownY = a.chartY; - }, - drag: function(a) { - var b = this.chart, - c = b.options.chart, - d = a.chartX, - e = a.chartY, - h = this.zoomHor, - m = this.zoomVert, - f = b.plotLeft, - l = b.plotTop, - n = b.plotWidth, - q = b.plotHeight, - A, - F = this.selectionMarker, - G = this.mouseDownX, - g = this.mouseDownY, - v = c.panKey && a[c.panKey + 'Key']; - (F && F.touch) || - (d < f ? (d = f) : d > f + n && (d = f + n), - e < l ? (e = l) : e > l + q && (e = l + q), - (this.hasDragged = Math.sqrt( - Math.pow(G - d, 2) + Math.pow(g - e, 2), - )), - 10 < this.hasDragged && - ((A = b.isInsidePlot(G - f, g - l)), - b.hasCartesianSeries && - (this.zoomX || this.zoomY) && - A && - !v && - !F && - (this.selectionMarker = F = b.renderer - .rect(f, l, h ? 1 : n, m ? 1 : q, 0) - .attr({ - fill: - c.selectionMarkerFill || - p('#335cad') - .setOpacity(0.25) - .get(), - class: 'highcharts-selection-marker', - zIndex: 7, - }) - .add()), - F && - h && - ((d -= G), - F.attr({ width: Math.abs(d), x: (0 < d ? 0 : d) + G })), - F && - m && - ((d = e - g), - F.attr({ height: Math.abs(d), y: (0 < d ? 0 : d) + g })), - A && !F && c.panning && b.pan(a, c.panning))); - }, - drop: function(a) { - var b = this, - c = this.chart, - d = this.hasPinched; - if (this.selectionMarker) { - var e = { originalEvent: a, xAxis: [], yAxis: [] }, - h = this.selectionMarker, - m = h.attr ? h.attr('x') : h.x, - t = h.attr ? h.attr('y') : h.y, - p = h.attr ? h.attr('width') : h.width, - w = h.attr ? h.attr('height') : h.height, - q; - if (this.hasDragged || d) - r(c.axes, function(c) { - if ( - c.zoomEnabled && - l(c.min) && - (d || b[{ xAxis: 'zoomX', yAxis: 'zoomY' }[c.coll]]) - ) { - var k = c.horiz, - h = 'touchend' === a.type ? c.minPixelPadding : 0, - g = c.toValue((k ? m : t) + h), - k = c.toValue((k ? m + p : t + w) - h); - e[c.coll].push({ - axis: c, - min: Math.min(g, k), - max: Math.max(g, k), - }); - q = !0; - } - }), - q && - u(c, 'selection', e, function(a) { - c.zoom(n(a, d ? { animation: !1 } : null)); - }); - this.selectionMarker = this.selectionMarker.destroy(); - d && this.scaleGroups(); - } - c && - (f(c.container, { cursor: c._cursor }), - (c.cancelClick = 10 < this.hasDragged), - (c.mouseIsDown = this.hasDragged = this.hasPinched = !1), - (this.pinchDown = [])); - }, - onContainerMouseDown: function(a) { - 2 !== a.button && - ((a = this.normalize(a)), - this.zoomOption(a), - a.preventDefault && a.preventDefault(), - this.dragStart(a)); - }, - onDocumentMouseUp: function(b) { - H[a.hoverChartIndex] && H[a.hoverChartIndex].pointer.drop(b); - }, - onDocumentMouseMove: function(a) { - var b = this.chart, - c = this.chartPosition; - a = this.normalize(a, c); - !c || - this.inClass(a.target, 'highcharts-tracker') || - b.isInsidePlot(a.chartX - b.plotLeft, a.chartY - b.plotTop) || - this.reset(); - }, - onContainerMouseLeave: function(b) { - var c = H[a.hoverChartIndex]; - c && - (b.relatedTarget || b.toElement) && - (c.pointer.reset(), (c.pointer.chartPosition = null)); - }, - onContainerMouseMove: function(b) { - var c = this.chart; - (l(a.hoverChartIndex) && - H[a.hoverChartIndex] && - H[a.hoverChartIndex].mouseIsDown) || - (a.hoverChartIndex = c.index); - b = this.normalize(b); - b.returnValue = !1; - 'mousedown' === c.mouseIsDown && this.drag(b); - (!this.inClass(b.target, 'highcharts-tracker') && - !c.isInsidePlot(b.chartX - c.plotLeft, b.chartY - c.plotTop)) || - c.openMenu || - this.runPointActions(b); - }, - inClass: function(a, c) { - for (var b; a; ) { - if ((b = D(a, 'class'))) { - if (-1 !== b.indexOf(c)) return !0; - if (-1 !== b.indexOf('highcharts-container')) return !1; - } - a = a.parentNode; - } - }, - onTrackerMouseOut: function(a) { - var b = this.chart.hoverSeries; - a = a.relatedTarget || a.toElement; - this.isDirectTouch = !1; - if ( - !( - !b || - !a || - b.stickyTracking || - this.inClass(a, 'highcharts-tooltip') || - (this.inClass(a, 'highcharts-series-' + b.index) && - this.inClass(a, 'highcharts-tracker')) - ) - ) - b.onMouseOut(); - }, - onContainerClick: function(a) { - var b = this.chart, - c = b.hoverPoint, - d = b.plotLeft, - e = b.plotTop; - a = this.normalize(a); - b.cancelClick || - (c && this.inClass(a.target, 'highcharts-tracker') - ? (u(c.series, 'click', n(a, { point: c })), - b.hoverPoint && c.firePointEvent('click', a)) - : (n(a, this.getCoordinates(a)), - b.isInsidePlot(a.chartX - d, a.chartY - e) && u(b, 'click', a))); - }, - setDOMEvents: function() { - var b = this, - c = b.chart.container, - d = c.ownerDocument; - c.onmousedown = function(a) { - b.onContainerMouseDown(a); - }; - c.onmousemove = function(a) { - b.onContainerMouseMove(a); - }; - c.onclick = function(a) { - b.onContainerClick(a); - }; - this.unbindContainerMouseLeave = E( - c, - 'mouseleave', - b.onContainerMouseLeave, - ); - a.unbindDocumentMouseUp || - (a.unbindDocumentMouseUp = E(d, 'mouseup', b.onDocumentMouseUp)); - a.hasTouch && - ((c.ontouchstart = function(a) { - b.onContainerTouchStart(a); - }), - (c.ontouchmove = function(a) { - b.onContainerTouchMove(a); - }), - a.unbindDocumentTouchEnd || - (a.unbindDocumentTouchEnd = E( - d, - 'touchend', - b.onDocumentTouchEnd, - ))); - }, - destroy: function() { - var b = this; - b.unDocMouseMove && b.unDocMouseMove(); - this.unbindContainerMouseLeave(); - a.chartCount || - (a.unbindDocumentMouseUp && - (a.unbindDocumentMouseUp = a.unbindDocumentMouseUp()), - a.unbindDocumentTouchEnd && - (a.unbindDocumentTouchEnd = a.unbindDocumentTouchEnd())); - clearInterval(b.tooltipTimeout); - a.objectEach(b, function(a, c) { - b[c] = null; - }); - }, - }; - })(M); - (function(a) { - var E = a.charts, - D = a.each, - H = a.extend, - p = a.map, - f = a.noop, - l = a.pick; - H(a.Pointer.prototype, { - pinchTranslate: function(a, f, l, p, e, h) { - this.zoomHor && this.pinchTranslateDirection(!0, a, f, l, p, e, h); - this.zoomVert && this.pinchTranslateDirection(!1, a, f, l, p, e, h); - }, - pinchTranslateDirection: function(a, f, l, p, e, h, m, d) { - var c = this.chart, - b = a ? 'x' : 'y', - k = a ? 'X' : 'Y', - z = 'chart' + k, - n = a ? 'width' : 'height', - r = c['plot' + (a ? 'Left' : 'Top')], - x, - w, - t = d || 1, - C = c.inverted, - u = c.bounds[a ? 'h' : 'v'], - q = 1 === f.length, - A = f[0][z], - F = l[0][z], - G = !q && f[1][z], - g = !q && l[1][z], - v; - l = function() { - !q && - 20 < Math.abs(A - G) && - (t = d || Math.abs(F - g) / Math.abs(A - G)); - w = (r - F) / t + A; - x = c['plot' + (a ? 'Width' : 'Height')] / t; - }; - l(); - f = w; - f < u.min - ? ((f = u.min), (v = !0)) - : f + x > u.max && ((f = u.max - x), (v = !0)); - v - ? ((F -= 0.8 * (F - m[b][0])), q || (g -= 0.8 * (g - m[b][1])), l()) - : (m[b] = [F, g]); - C || ((h[b] = w - r), (h[n] = x)); - h = C ? 1 / t : t; - e[n] = x; - e[b] = f; - p[C ? (a ? 'scaleY' : 'scaleX') : 'scale' + k] = t; - p['translate' + k] = h * r + (F - h * A); - }, - pinch: function(a) { - var n = this, - r = n.chart, - u = n.pinchDown, - e = a.touches, - h = e.length, - m = n.lastValidTouch, - d = n.hasZoom, - c = n.selectionMarker, - b = {}, - k = - 1 === h && - ((n.inClass(a.target, 'highcharts-tracker') && r.runTrackerClick) || - n.runChartClick), - z = {}; - 1 < h && (n.initiated = !0); - d && n.initiated && !k && a.preventDefault(); - p(e, function(a) { - return n.normalize(a); - }); - 'touchstart' === a.type - ? (D(e, function(a, b) { - u[b] = { chartX: a.chartX, chartY: a.chartY }; - }), - (m.x = [u[0].chartX, u[1] && u[1].chartX]), - (m.y = [u[0].chartY, u[1] && u[1].chartY]), - D(r.axes, function(a) { - if (a.zoomEnabled) { - var b = r.bounds[a.horiz ? 'h' : 'v'], - c = a.minPixelPadding, - d = a.toPixels(l(a.options.min, a.dataMin)), - e = a.toPixels(l(a.options.max, a.dataMax)), - k = Math.max(d, e); - b.min = Math.min(a.pos, Math.min(d, e) - c); - b.max = Math.max(a.pos + a.len, k + c); - } - }), - (n.res = !0)) - : n.followTouchMove && 1 === h - ? this.runPointActions(n.normalize(a)) - : u.length && - (c || - (n.selectionMarker = c = H({ destroy: f, touch: !0 }, r.plotBox)), - n.pinchTranslate(u, e, b, c, z, m), - (n.hasPinched = d), - n.scaleGroups(b, z), - n.res && ((n.res = !1), this.reset(!1, 0))); - }, - touch: function(f, n) { - var p = this.chart, - r, - e; - if (p.index !== a.hoverChartIndex) - this.onContainerMouseLeave({ relatedTarget: !0 }); - a.hoverChartIndex = p.index; - 1 === f.touches.length - ? ((f = this.normalize(f)), - (e = p.isInsidePlot(f.chartX - p.plotLeft, f.chartY - p.plotTop)) && - !p.openMenu - ? (n && this.runPointActions(f), - 'touchmove' === f.type && - ((n = this.pinchDown), - (r = n[0] - ? 4 <= - Math.sqrt( - Math.pow(n[0].chartX - f.chartX, 2) + - Math.pow(n[0].chartY - f.chartY, 2), - ) - : !1)), - l(r, !0) && this.pinch(f)) - : n && this.reset()) - : 2 === f.touches.length && this.pinch(f); - }, - onContainerTouchStart: function(a) { - this.zoomOption(a); - this.touch(a, !0); - }, - onContainerTouchMove: function(a) { - this.touch(a); - }, - onDocumentTouchEnd: function(f) { - E[a.hoverChartIndex] && E[a.hoverChartIndex].pointer.drop(f); - }, - }); - })(M); - (function(a) { - var E = a.addEvent, - D = a.charts, - H = a.css, - p = a.doc, - f = a.extend, - l = a.noop, - r = a.Pointer, - n = a.removeEvent, - w = a.win, - u = a.wrap; - if (!a.hasTouch && (w.PointerEvent || w.MSPointerEvent)) { - var e = {}, - h = !!w.PointerEvent, - m = function() { - var c = []; - c.item = function(a) { - return this[a]; - }; - a.objectEach(e, function(a) { - c.push({ pageX: a.pageX, pageY: a.pageY, target: a.target }); - }); - return c; - }, - d = function(c, b, d, e) { - ('touch' !== c.pointerType && - c.pointerType !== c.MSPOINTER_TYPE_TOUCH) || - !D[a.hoverChartIndex] || - (e(c), - (e = D[a.hoverChartIndex].pointer), - e[b]({ - type: d, - target: c.currentTarget, - preventDefault: l, - touches: m(), - })); - }; - f(r.prototype, { - onContainerPointerDown: function(a) { - d(a, 'onContainerTouchStart', 'touchstart', function(a) { - e[a.pointerId] = { - pageX: a.pageX, - pageY: a.pageY, - target: a.currentTarget, - }; - }); - }, - onContainerPointerMove: function(a) { - d(a, 'onContainerTouchMove', 'touchmove', function(a) { - e[a.pointerId] = { pageX: a.pageX, pageY: a.pageY }; - e[a.pointerId].target || (e[a.pointerId].target = a.currentTarget); - }); - }, - onDocumentPointerUp: function(a) { - d(a, 'onDocumentTouchEnd', 'touchend', function(a) { - delete e[a.pointerId]; - }); - }, - batchMSEvents: function(a) { - a( - this.chart.container, - h ? 'pointerdown' : 'MSPointerDown', - this.onContainerPointerDown, - ); - a( - this.chart.container, - h ? 'pointermove' : 'MSPointerMove', - this.onContainerPointerMove, - ); - a(p, h ? 'pointerup' : 'MSPointerUp', this.onDocumentPointerUp); - }, - }); - u(r.prototype, 'init', function(a, b, d) { - a.call(this, b, d); - this.hasZoom && - H(b.container, { - '-ms-touch-action': 'none', - 'touch-action': 'none', - }); - }); - u(r.prototype, 'setDOMEvents', function(a) { - a.apply(this); - (this.hasZoom || this.followTouchMove) && this.batchMSEvents(E); - }); - u(r.prototype, 'destroy', function(a) { - this.batchMSEvents(n); - a.call(this); - }); - } - })(M); - (function(a) { - var E = a.addEvent, - D = a.css, - H = a.discardElement, - p = a.defined, - f = a.each, - l = a.isFirefox, - r = a.marginNames, - n = a.merge, - w = a.pick, - u = a.setAnimation, - e = a.stableSort, - h = a.win, - m = a.wrap; - a.Legend = function(a, c) { - this.init(a, c); - }; - a.Legend.prototype = { - init: function(a, c) { - this.chart = a; - this.setOptions(c); - c.enabled && - (this.render(), - E(this.chart, 'endResize', function() { - this.legend.positionCheckboxes(); - })); - }, - setOptions: function(a) { - var c = w(a.padding, 8); - this.options = a; - this.itemStyle = a.itemStyle; - this.itemHiddenStyle = n(this.itemStyle, a.itemHiddenStyle); - this.itemMarginTop = a.itemMarginTop || 0; - this.padding = c; - this.initialItemY = c - 5; - this.itemHeight = this.maxItemWidth = 0; - this.symbolWidth = w(a.symbolWidth, 16); - this.pages = []; - }, - update: function(a, c) { - var b = this.chart; - this.setOptions(n(!0, this.options, a)); - this.destroy(); - b.isDirtyLegend = b.isDirtyBox = !0; - w(c, !0) && b.redraw(); - }, - colorizeItem: function(a, c) { - a.legendGroup[c ? 'removeClass' : 'addClass']( - 'highcharts-legend-item-hidden', - ); - var b = this.options, - d = a.legendItem, - e = a.legendLine, - h = a.legendSymbol, - f = this.itemHiddenStyle.color, - b = c ? b.itemStyle.color : f, - m = c ? a.color || f : f, - l = a.options && a.options.marker, - t = { fill: m }; - d && d.css({ fill: b, color: b }); - e && e.attr({ stroke: m }); - h && - (l && - h.isMarker && - ((t = a.pointAttribs()), c || (t.stroke = t.fill = f)), - h.attr(t)); - }, - positionItem: function(a) { - var c = this.options, - b = c.symbolPadding, - c = !c.rtl, - d = a._legendItemPos, - e = d[0], - d = d[1], - h = a.checkbox; - (a = a.legendGroup) && - a.element && - a.translate(c ? e : this.legendWidth - e - 2 * b - 4, d); - h && ((h.x = e), (h.y = d)); - }, - destroyItem: function(a) { - var c = a.checkbox; - f(['legendItem', 'legendLine', 'legendSymbol', 'legendGroup'], function( - b, - ) { - a[b] && (a[b] = a[b].destroy()); - }); - c && H(a.checkbox); - }, - destroy: function() { - function a(a) { - this[a] && (this[a] = this[a].destroy()); - } - f(this.getAllItems(), function(c) { - f(['legendItem', 'legendGroup'], a, c); - }); - f('clipRect up down pager nav box title group'.split(' '), a, this); - this.display = null; - }, - positionCheckboxes: function() { - var a = this.group && this.group.alignAttr, - c, - b = this.clipHeight || this.legendHeight, - e = this.titleHeight; - a && - ((c = a.translateY), - f( - this.allItems, - function(d) { - var k = d.checkbox, - h; - k && - ((h = c + e + k.y + (this.scrollOffset || 0) + 3), - D(k, { - left: a.translateX + d.checkboxOffset + k.x - 20 + 'px', - top: h + 'px', - display: h > c - 6 && h < c + b - 6 ? '' : 'none', - })); - }, - this, - )); - }, - renderTitle: function() { - var a = this.options, - c = this.padding, - b = a.title, - e = 0; - b.text && - (this.title || - (this.title = this.chart.renderer - .label( - b.text, - c - 3, - c - 4, - null, - null, - null, - a.useHTML, - null, - 'legend-title', - ) - .attr({ zIndex: 1 }) - .css(b.style) - .add(this.group)), - (a = this.title.getBBox()), - (e = a.height), - (this.offsetWidth = a.width), - this.contentGroup.attr({ translateY: e })); - this.titleHeight = e; - }, - setText: function(d) { - var c = this.options; - d.legendItem.attr({ - text: c.labelFormat - ? a.format(c.labelFormat, d) - : c.labelFormatter.call(d), - }); - }, - renderItem: function(a) { - var c = this.chart, - b = c.renderer, - d = this.options, - e = 'horizontal' === d.layout, - h = this.symbolWidth, - f = d.symbolPadding, - m = this.itemStyle, - l = this.itemHiddenStyle, - t = this.padding, - p = e ? w(d.itemDistance, 20) : 0, - r = !d.rtl, - q = d.width, - A = d.itemMarginBottom || 0, - F = this.itemMarginTop, - G = a.legendItem, - g = !a.series, - v = !g && a.series.drawLegendSymbol ? a.series : a, - u = v.options, - L = this.createCheckboxForItem && u && u.showCheckbox, - u = h + f + p + (L ? 20 : 0), - P = d.useHTML, - J = a.options.className; - G || - ((a.legendGroup = b - .g('legend-item') - .addClass( - 'highcharts-' + - v.type + - '-series highcharts-color-' + - a.colorIndex + - (J ? ' ' + J : '') + - (g ? ' highcharts-series-' + a.index : ''), - ) - .attr({ zIndex: 1 }) - .add(this.scrollGroup)), - (a.legendItem = G = b - .text('', r ? h + f : -f, this.baseline || 0, P) - .css(n(a.visible ? m : l)) - .attr({ align: r ? 'left' : 'right', zIndex: 2 }) - .add(a.legendGroup)), - this.baseline || - ((h = m.fontSize), - (this.fontMetrics = b.fontMetrics(h, G)), - (this.baseline = this.fontMetrics.f + 3 + F), - G.attr('y', this.baseline)), - (this.symbolHeight = d.symbolHeight || this.fontMetrics.f), - v.drawLegendSymbol(this, a), - this.setItemEvents && this.setItemEvents(a, G, P), - L && this.createCheckboxForItem(a)); - this.colorizeItem(a, a.visible); - m.width || - G.css({ width: (d.itemWidth || d.width || c.spacingBox.width) - u }); - this.setText(a); - b = G.getBBox(); - m = a.checkboxOffset = d.itemWidth || a.legendItemWidth || b.width + u; - this.itemHeight = b = Math.round( - a.legendItemHeight || b.height || this.symbolHeight, - ); - e && - this.itemX - t + m > (q || c.spacingBox.width - 2 * t - d.x) && - ((this.itemX = t), - (this.itemY += F + this.lastLineHeight + A), - (this.lastLineHeight = 0)); - this.maxItemWidth = Math.max(this.maxItemWidth, m); - this.lastItemY = F + this.itemY + A; - this.lastLineHeight = Math.max(b, this.lastLineHeight); - a._legendItemPos = [this.itemX, this.itemY]; - e - ? (this.itemX += m) - : ((this.itemY += F + b + A), (this.lastLineHeight = b)); - this.offsetWidth = - q || - Math.max( - (e ? this.itemX - t - (a.checkbox ? 0 : p) : m) + t, - this.offsetWidth, - ); - }, - getAllItems: function() { - var a = []; - f(this.chart.series, function(c) { - var b = c && c.options; - c && - w(b.showInLegend, p(b.linkedTo) ? !1 : void 0, !0) && - (a = a.concat( - c.legendItems || ('point' === b.legendType ? c.data : c), - )); - }); - return a; - }, - getAlignment: function() { - var a = this.options; - return a.floating - ? '' - : a.align.charAt(0) + a.verticalAlign.charAt(0) + a.layout.charAt(0); - }, - adjustMargins: function(a, c) { - var b = this.chart, - d = this.options, - e = this.getAlignment(); - e && - f( - [/(lth|ct|rth)/, /(rtv|rm|rbv)/, /(rbh|cb|lbh)/, /(lbv|lm|ltv)/], - function(k, h) { - k.test(e) && - !p(a[h]) && - (b[r[h]] = Math.max( - b[r[h]], - b.legend[(h + 1) % 2 ? 'legendHeight' : 'legendWidth'] + - [1, -1, -1, 1][h] * d[h % 2 ? 'x' : 'y'] + - w(d.margin, 12) + - c[h] + - (0 === h ? b.titleOffset + b.options.title.margin : 0), - )); - }, - ); - }, - render: function() { - var a = this, - c = a.chart, - b = c.renderer, - k = a.group, - h, - m, - l, - x, - p = a.box, - t = a.options, - C = a.padding; - a.itemX = C; - a.itemY = a.initialItemY; - a.offsetWidth = 0; - a.lastItemY = 0; - k || - ((a.group = k = b - .g('legend') - .attr({ zIndex: 7 }) - .add()), - (a.contentGroup = b - .g() - .attr({ zIndex: 1 }) - .add(k)), - (a.scrollGroup = b.g().add(a.contentGroup))); - a.renderTitle(); - h = a.getAllItems(); - e(h, function(a, b) { - return ( - ((a.options && a.options.legendIndex) || 0) - - ((b.options && b.options.legendIndex) || 0) - ); - }); - t.reversed && h.reverse(); - a.allItems = h; - a.display = m = !!h.length; - a.lastLineHeight = 0; - f(h, function(b) { - a.renderItem(b); - }); - l = (t.width || a.offsetWidth) + C; - x = a.lastItemY + a.lastLineHeight + a.titleHeight; - x = a.handleOverflow(x); - x += C; - p || - ((a.box = p = b - .rect() - .addClass('highcharts-legend-box') - .attr({ r: t.borderRadius }) - .add(k)), - (p.isNew = !0)); - p.attr({ - stroke: t.borderColor, - 'stroke-width': t.borderWidth || 0, - fill: t.backgroundColor || 'none', - }).shadow(t.shadow); - 0 < l && - 0 < x && - (p[p.isNew ? 'attr' : 'animate']( - p.crisp.call( - {}, - { x: 0, y: 0, width: l, height: x }, - p.strokeWidth(), - ), - ), - (p.isNew = !1)); - p[m ? 'show' : 'hide'](); - a.legendWidth = l; - a.legendHeight = x; - f(h, function(b) { - a.positionItem(b); - }); - m && - ((b = c.spacingBox), - /(lth|ct|rth)/.test(a.getAlignment()) && - (b = n(b, { y: b.y + c.titleOffset + c.options.title.margin })), - k.align(n(t, { width: l, height: x }), !0, b)); - c.isResizing || this.positionCheckboxes(); - }, - handleOverflow: function(a) { - var c = this, - b = this.chart, - d = b.renderer, - e = this.options, - h = e.y, - m = this.padding, - b = b.spacingBox.height + ('top' === e.verticalAlign ? -h : h) - m, - h = e.maxHeight, - l, - n = this.clipRect, - t = e.navigation, - p = w(t.animation, !0), - r = t.arrowSize || 12, - q = this.nav, - A = this.pages, - F, - G = this.allItems, - g = function(a) { - 'number' === typeof a - ? n.attr({ height: a }) - : n && ((c.clipRect = n.destroy()), c.contentGroup.clip()); - c.contentGroup.div && - (c.contentGroup.div.style.clip = a - ? 'rect(' + m + 'px,9999px,' + (m + a) + 'px,0)' - : 'auto'); - }; - 'horizontal' !== e.layout || - 'middle' === e.verticalAlign || - e.floating || - (b /= 2); - h && (b = Math.min(b, h)); - A.length = 0; - a > b && !1 !== t.enabled - ? ((this.clipHeight = l = Math.max(b - 20 - this.titleHeight - m, 0)), - (this.currentPage = w(this.currentPage, 1)), - (this.fullHeight = a), - f(G, function(a, b) { - var c = a._legendItemPos[1], - d = Math.round(a.legendItem.getBBox().height), - g = A.length; - if (!g || (c - A[g - 1] > l && (F || c) !== A[g - 1])) - A.push(F || c), g++; - a.pageIx = g - 1; - F && (G[b - 1].pageIx = g - 1); - b === G.length - 1 && - c + d - A[g - 1] > l && - (A.push(c), (a.pageIx = g)); - c !== F && (F = c); - }), - n || - ((n = c.clipRect = d.clipRect(0, m, 9999, 0)), - c.contentGroup.clip(n)), - g(l), - q || - ((this.nav = q = d - .g() - .attr({ zIndex: 1 }) - .add(this.group)), - (this.up = d - .symbol('triangle', 0, 0, r, r) - .on('click', function() { - c.scroll(-1, p); - }) - .add(q)), - (this.pager = d - .text('', 15, 10) - .addClass('highcharts-legend-navigation') - .css(t.style) - .add(q)), - (this.down = d - .symbol('triangle-down', 0, 0, r, r) - .on('click', function() { - c.scroll(1, p); - }) - .add(q))), - c.scroll(0), - (a = b)) - : q && - (g(), - (this.nav = q.destroy()), - this.scrollGroup.attr({ translateY: 1 }), - (this.clipHeight = 0)); - return a; - }, - scroll: function(a, c) { - var b = this.pages, - d = b.length; - a = this.currentPage + a; - var e = this.clipHeight, - h = this.options.navigation, - f = this.pager, - m = this.padding; - a > d && (a = d); - 0 < a && - (void 0 !== c && u(c, this.chart), - this.nav.attr({ - translateX: m, - translateY: e + this.padding + 7 + this.titleHeight, - visibility: 'visible', - }), - this.up.attr({ - class: - 1 === a - ? 'highcharts-legend-nav-inactive' - : 'highcharts-legend-nav-active', - }), - f.attr({ text: a + '/' + d }), - this.down.attr({ - x: 18 + this.pager.getBBox().width, - class: - a === d - ? 'highcharts-legend-nav-inactive' - : 'highcharts-legend-nav-active', - }), - this.up - .attr({ fill: 1 === a ? h.inactiveColor : h.activeColor }) - .css({ cursor: 1 === a ? 'default' : 'pointer' }), - this.down - .attr({ fill: a === d ? h.inactiveColor : h.activeColor }) - .css({ cursor: a === d ? 'default' : 'pointer' }), - (this.scrollOffset = -b[a - 1] + this.initialItemY), - this.scrollGroup.animate({ translateY: this.scrollOffset }), - (this.currentPage = a), - this.positionCheckboxes()); - }, - }; - a.LegendSymbolMixin = { - drawRectangle: function(a, c) { - var b = a.symbolHeight, - d = a.options.squareSymbol; - c.legendSymbol = this.chart.renderer - .rect( - d ? (a.symbolWidth - b) / 2 : 0, - a.baseline - b + 1, - d ? b : a.symbolWidth, - b, - w(a.options.symbolRadius, b / 2), - ) - .addClass('highcharts-point') - .attr({ zIndex: 3 }) - .add(c.legendGroup); - }, - drawLineMarker: function(a) { - var c = this.options, - b = c.marker, - d = a.symbolWidth, - e = a.symbolHeight, - h = e / 2, - f = this.chart.renderer, - m = this.legendGroup; - a = a.baseline - Math.round(0.3 * a.fontMetrics.b); - var l; - l = { 'stroke-width': c.lineWidth || 0 }; - c.dashStyle && (l.dashstyle = c.dashStyle); - this.legendLine = f - .path(['M', 0, a, 'L', d, a]) - .addClass('highcharts-graph') - .attr(l) - .add(m); - b && - !1 !== b.enabled && - ((c = Math.min(w(b.radius, h), h)), - 0 === this.symbol.indexOf('url') && - ((b = n(b, { width: e, height: e })), (c = 0)), - (this.legendSymbol = b = f - .symbol(this.symbol, d / 2 - c, a - c, 2 * c, 2 * c, b) - .addClass('highcharts-point') - .add(m)), - (b.isMarker = !0)); - }, - }; - (/Trident\/7\.0/.test(h.navigator.userAgent) || l) && - m(a.Legend.prototype, 'positionItem', function(a, c) { - var b = this, - d = function() { - c._legendItemPos && a.call(b, c); - }; - d(); - setTimeout(d); - }); - })(M); - (function(a) { - var E = a.addEvent, - D = a.animate, - H = a.animObject, - p = a.attr, - f = a.doc, - l = a.Axis, - r = a.createElement, - n = a.defaultOptions, - w = a.discardElement, - u = a.charts, - e = a.css, - h = a.defined, - m = a.each, - d = a.extend, - c = a.find, - b = a.fireEvent, - k = a.grep, - z = a.isNumber, - B = a.isObject, - I = a.isString, - x = a.Legend, - K = a.marginNames, - t = a.merge, - C = a.objectEach, - N = a.Pointer, - q = a.pick, - A = a.pInt, - F = a.removeEvent, - G = a.seriesTypes, - g = a.splat, - v = a.svg, - Q = a.syncTimeout, - L = a.win, - P = (a.Chart = function() { - this.getArgs.apply(this, arguments); - }); - a.chart = function(a, b, c) { - return new P(a, b, c); - }; - d(P.prototype, { - callbacks: [], - getArgs: function() { - var a = [].slice.call(arguments); - if (I(a[0]) || a[0].nodeName) this.renderTo = a.shift(); - this.init(a[0], a[1]); - }, - init: function(b, c) { - var d, - g, - e = b.series, - k = b.plotOptions || {}; - b.series = null; - d = t(n, b); - for (g in d.plotOptions) - d.plotOptions[g].tooltip = (k[g] && t(k[g].tooltip)) || void 0; - d.tooltip.userOptions = - (b.chart && b.chart.forExport && b.tooltip.userOptions) || b.tooltip; - d.series = b.series = e; - this.userOptions = b; - b = d.chart; - g = b.events; - this.margin = []; - this.spacing = []; - this.bounds = { h: {}, v: {} }; - this.labelCollectors = []; - this.callback = c; - this.isResizing = 0; - this.options = d; - this.axes = []; - this.series = []; - this.hasCartesianSeries = b.showAxes; - var q = this; - q.index = u.length; - u.push(q); - a.chartCount++; - g && - C(g, function(a, b) { - E(q, b, a); - }); - q.xAxis = []; - q.yAxis = []; - q.pointCount = q.colorCounter = q.symbolCounter = 0; - q.firstRender(); - }, - initSeries: function(b) { - var c = this.options.chart; - (c = G[b.type || c.type || c.defaultSeriesType]) || a.error(17, !0); - c = new c(); - c.init(this, b); - return c; - }, - orderSeries: function(a) { - var b = this.series; - for (a = a || 0; a < b.length; a++) - b[a] && - ((b[a].index = a), - (b[a].name = b[a].name || 'Series ' + (b[a].index + 1))); - }, - isInsidePlot: function(a, b, c) { - var d = c ? b : a; - a = c ? a : b; - return 0 <= d && d <= this.plotWidth && 0 <= a && a <= this.plotHeight; - }, - redraw: function(c) { - var g = this.axes, - e = this.series, - k = this.pointer, - q = this.legend, - h = this.isDirtyLegend, - f, - l, - v = this.hasCartesianSeries, - A = this.isDirtyBox, - F, - t = this.renderer, - x = t.isHidden(), - n = []; - this.setResponsive && this.setResponsive(!1); - a.setAnimation(c, this); - x && this.temporaryDisplay(); - this.layOutTitles(); - for (c = e.length; c--; ) - if (((F = e[c]), F.options.stacking && ((f = !0), F.isDirty))) { - l = !0; - break; - } - if (l) - for (c = e.length; c--; ) - (F = e[c]), F.options.stacking && (F.isDirty = !0); - m(e, function(a) { - a.isDirty && - 'point' === a.options.legendType && - (a.updateTotals && a.updateTotals(), (h = !0)); - a.isDirtyData && b(a, 'updatedData'); - }); - h && q.options.enabled && (q.render(), (this.isDirtyLegend = !1)); - f && this.getStacks(); - v && - m(g, function(a) { - a.updateNames(); - a.setScale(); - }); - this.getMargins(); - v && - (m(g, function(a) { - a.isDirty && (A = !0); - }), - m(g, function(a) { - var c = a.min + ',' + a.max; - a.extKey !== c && - ((a.extKey = c), - n.push(function() { - b(a, 'afterSetExtremes', d(a.eventArgs, a.getExtremes())); - delete a.eventArgs; - })); - (A || f) && a.redraw(); - })); - A && this.drawChartBox(); - b(this, 'predraw'); - m(e, function(a) { - (A || a.isDirty) && a.visible && a.redraw(); - a.isDirtyData = !1; - }); - k && k.reset(!0); - t.draw(); - b(this, 'redraw'); - b(this, 'render'); - x && this.temporaryDisplay(!0); - m(n, function(a) { - a.call(); - }); - }, - get: function(a) { - function b(b) { - return b.id === a || (b.options && b.options.id === a); - } - var d, - g = this.series, - e; - d = c(this.axes, b) || c(this.series, b); - for (e = 0; !d && e < g.length; e++) d = c(g[e].points || [], b); - return d; - }, - getAxes: function() { - var a = this, - b = this.options, - c = (b.xAxis = g(b.xAxis || {})), - b = (b.yAxis = g(b.yAxis || {})); - m(c, function(a, b) { - a.index = b; - a.isX = !0; - }); - m(b, function(a, b) { - a.index = b; - }); - c = c.concat(b); - m(c, function(b) { - new l(a, b); - }); - }, - getSelectedPoints: function() { - var a = []; - m(this.series, function(b) { - a = a.concat( - k(b.data || [], function(a) { - return a.selected; - }), - ); - }); - return a; - }, - getSelectedSeries: function() { - return k(this.series, function(a) { - return a.selected; - }); - }, - setTitle: function(a, b, c) { - var d = this, - g = d.options, - e; - e = g.title = t( - { - style: { color: '#333333', fontSize: g.isStock ? '16px' : '18px' }, - }, - g.title, - a, - ); - g = g.subtitle = t({ style: { color: '#666666' } }, g.subtitle, b); - m([['title', a, e], ['subtitle', b, g]], function(a, b) { - var c = a[0], - g = d[c], - e = a[1]; - a = a[2]; - g && e && (d[c] = g = g.destroy()); - a && - !g && - ((d[c] = d.renderer - .text(a.text, 0, 0, a.useHTML) - .attr({ - align: a.align, - class: 'highcharts-' + c, - zIndex: a.zIndex || 4, - }) - .add()), - (d[c].update = function(a) { - d.setTitle(!b && a, b && a); - }), - d[c].css(a.style)); - }); - d.layOutTitles(c); - }, - layOutTitles: function(a) { - var b = 0, - c, - g = this.renderer, - e = this.spacingBox; - m( - ['title', 'subtitle'], - function(a) { - var c = this[a], - k = this.options[a]; - a = 'title' === a ? -3 : k.verticalAlign ? 0 : b + 2; - var q; - c && - ((q = k.style.fontSize), - (q = g.fontMetrics(q, c).b), - c - .css({ width: (k.width || e.width + k.widthAdjust) + 'px' }) - .align(d({ y: a + q }, k), !1, 'spacingBox'), - k.floating || - k.verticalAlign || - (b = Math.ceil(b + c.getBBox(k.useHTML).height))); - }, - this, - ); - c = this.titleOffset !== b; - this.titleOffset = b; - !this.isDirtyBox && - c && - ((this.isDirtyBox = c), - this.hasRendered && q(a, !0) && this.isDirtyBox && this.redraw()); - }, - getChartSize: function() { - var b = this.options.chart, - c = b.width, - b = b.height, - d = this.renderTo; - h(c) || (this.containerWidth = a.getStyle(d, 'width')); - h(b) || (this.containerHeight = a.getStyle(d, 'height')); - this.chartWidth = Math.max(0, c || this.containerWidth || 600); - this.chartHeight = Math.max( - 0, - a.relativeLength(b, this.chartWidth) || - (1 < this.containerHeight ? this.containerHeight : 400), - ); - }, - temporaryDisplay: function(b) { - var c = this.renderTo; - if (b) - for (; c && c.style; ) - c.hcOrigStyle && (a.css(c, c.hcOrigStyle), delete c.hcOrigStyle), - c.hcOrigDetached && - (f.body.removeChild(c), (c.hcOrigDetached = !1)), - (c = c.parentNode); - else - for (; c && c.style; ) { - f.body.contains(c) || - c.parentNode || - ((c.hcOrigDetached = !0), f.body.appendChild(c)); - if ('none' === a.getStyle(c, 'display', !1) || c.hcOricDetached) - (c.hcOrigStyle = { - display: c.style.display, - height: c.style.height, - overflow: c.style.overflow, - }), - (b = { display: 'block', overflow: 'hidden' }), - c !== this.renderTo && (b.height = 0), - a.css(c, b), - c.offsetWidth || - c.style.setProperty('display', 'block', 'important'); - c = c.parentNode; - if (c === f.body) break; - } - }, - setClassName: function(a) { - this.container.className = 'highcharts-container ' + (a || ''); - }, - getContainer: function() { - var b, - c = this.options, - g = c.chart, - e, - k; - b = this.renderTo; - var q = a.uniqueKey(), - h; - b || (this.renderTo = b = g.renderTo); - I(b) && (this.renderTo = b = f.getElementById(b)); - b || a.error(13, !0); - e = A(p(b, 'data-highcharts-chart')); - z(e) && u[e] && u[e].hasRendered && u[e].destroy(); - p(b, 'data-highcharts-chart', this.index); - b.innerHTML = ''; - g.skipClone || b.offsetWidth || this.temporaryDisplay(); - this.getChartSize(); - e = this.chartWidth; - k = this.chartHeight; - h = d( - { - position: 'relative', - overflow: 'hidden', - width: e + 'px', - height: k + 'px', - textAlign: 'left', - lineHeight: 'normal', - zIndex: 0, - '-webkit-tap-highlight-color': 'rgba(0,0,0,0)', - }, - g.style, - ); - this.container = b = r('div', { id: q }, h, b); - this._cursor = b.style.cursor; - this.renderer = new (a[g.renderer] || a.Renderer)( - b, - e, - k, - null, - g.forExport, - c.exporting && c.exporting.allowHTML, - ); - this.setClassName(g.className); - this.renderer.setStyle(g.style); - this.renderer.chartIndex = this.index; - }, - getMargins: function(a) { - var b = this.spacing, - c = this.margin, - d = this.titleOffset; - this.resetMargins(); - d && - !h(c[0]) && - (this.plotTop = Math.max( - this.plotTop, - d + this.options.title.margin + b[0], - )); - this.legend && this.legend.display && this.legend.adjustMargins(c, b); - this.extraMargin && - (this[this.extraMargin.type] = - (this[this.extraMargin.type] || 0) + this.extraMargin.value); - this.adjustPlotArea && this.adjustPlotArea(); - a || this.getAxisMargins(); - }, - getAxisMargins: function() { - var a = this, - b = (a.axisOffset = [0, 0, 0, 0]), - c = a.margin; - a.hasCartesianSeries && - m(a.axes, function(a) { - a.visible && a.getOffset(); - }); - m(K, function(d, g) { - h(c[g]) || (a[d] += b[g]); - }); - a.setChartSize(); - }, - reflow: function(b) { - var c = this, - d = c.options.chart, - g = c.renderTo, - e = h(d.width) && h(d.height), - k = d.width || a.getStyle(g, 'width'), - d = d.height || a.getStyle(g, 'height'), - g = b ? b.target : L; - if (!e && !c.isPrinting && k && d && (g === L || g === f)) { - if (k !== c.containerWidth || d !== c.containerHeight) - clearTimeout(c.reflowTimeout), - (c.reflowTimeout = Q( - function() { - c.container && c.setSize(void 0, void 0, !1); - }, - b ? 100 : 0, - )); - c.containerWidth = k; - c.containerHeight = d; - } - }, - initReflow: function() { - var a = this, - b; - b = E(L, 'resize', function(b) { - a.reflow(b); - }); - E(a, 'destroy', b); - }, - setSize: function(c, d, g) { - var k = this, - q = k.renderer; - k.isResizing += 1; - a.setAnimation(g, k); - k.oldChartHeight = k.chartHeight; - k.oldChartWidth = k.chartWidth; - void 0 !== c && (k.options.chart.width = c); - void 0 !== d && (k.options.chart.height = d); - k.getChartSize(); - c = q.globalAnimation; - (c ? D : e)( - k.container, - { width: k.chartWidth + 'px', height: k.chartHeight + 'px' }, - c, - ); - k.setChartSize(!0); - q.setSize(k.chartWidth, k.chartHeight, g); - m(k.axes, function(a) { - a.isDirty = !0; - a.setScale(); - }); - k.isDirtyLegend = !0; - k.isDirtyBox = !0; - k.layOutTitles(); - k.getMargins(); - k.redraw(g); - k.oldChartHeight = null; - b(k, 'resize'); - Q(function() { - k && - b(k, 'endResize', null, function() { - --k.isResizing; - }); - }, H(c).duration); - }, - setChartSize: function(a) { - var b = this.inverted, - c = this.renderer, - d = this.chartWidth, - g = this.chartHeight, - e = this.options.chart, - k = this.spacing, - q = this.clipOffset, - h, - f, - l, - v; - this.plotLeft = h = Math.round(this.plotLeft); - this.plotTop = f = Math.round(this.plotTop); - this.plotWidth = l = Math.max(0, Math.round(d - h - this.marginRight)); - this.plotHeight = v = Math.max( - 0, - Math.round(g - f - this.marginBottom), - ); - this.plotSizeX = b ? v : l; - this.plotSizeY = b ? l : v; - this.plotBorderWidth = e.plotBorderWidth || 0; - this.spacingBox = c.spacingBox = { - x: k[3], - y: k[0], - width: d - k[3] - k[1], - height: g - k[0] - k[2], - }; - this.plotBox = c.plotBox = { x: h, y: f, width: l, height: v }; - d = 2 * Math.floor(this.plotBorderWidth / 2); - b = Math.ceil(Math.max(d, q[3]) / 2); - c = Math.ceil(Math.max(d, q[0]) / 2); - this.clipBox = { - x: b, - y: c, - width: Math.floor(this.plotSizeX - Math.max(d, q[1]) / 2 - b), - height: Math.max( - 0, - Math.floor(this.plotSizeY - Math.max(d, q[2]) / 2 - c), - ), - }; - a || - m(this.axes, function(a) { - a.setAxisSize(); - a.setAxisTranslation(); - }); - }, - resetMargins: function() { - var a = this, - b = a.options.chart; - m(['margin', 'spacing'], function(c) { - var d = b[c], - g = B(d) ? d : [d, d, d, d]; - m(['Top', 'Right', 'Bottom', 'Left'], function(d, e) { - a[c][e] = q(b[c + d], g[e]); - }); - }); - m(K, function(b, c) { - a[b] = q(a.margin[c], a.spacing[c]); - }); - a.axisOffset = [0, 0, 0, 0]; - a.clipOffset = [0, 0, 0, 0]; - }, - drawChartBox: function() { - var a = this.options.chart, - b = this.renderer, - c = this.chartWidth, - d = this.chartHeight, - g = this.chartBackground, - e = this.plotBackground, - k = this.plotBorder, - q, - h = this.plotBGImage, - f = a.backgroundColor, - m = a.plotBackgroundColor, - l = a.plotBackgroundImage, - v, - A = this.plotLeft, - F = this.plotTop, - t = this.plotWidth, - x = this.plotHeight, - n = this.plotBox, - p = this.clipRect, - z = this.clipBox, - G = 'animate'; - g || - ((this.chartBackground = g = b - .rect() - .addClass('highcharts-background') - .add()), - (G = 'attr')); - q = a.borderWidth || 0; - v = q + (a.shadow ? 8 : 0); - f = { fill: f || 'none' }; - if (q || g['stroke-width']) - (f.stroke = a.borderColor), (f['stroke-width'] = q); - g.attr(f).shadow(a.shadow); - g[G]({ - x: v / 2, - y: v / 2, - width: c - v - (q % 2), - height: d - v - (q % 2), - r: a.borderRadius, - }); - G = 'animate'; - e || - ((G = 'attr'), - (this.plotBackground = e = b - .rect() - .addClass('highcharts-plot-background') - .add())); - e[G](n); - e.attr({ fill: m || 'none' }).shadow(a.plotShadow); - l && - (h - ? h.animate(n) - : (this.plotBGImage = b.image(l, A, F, t, x).add())); - p - ? p.animate({ width: z.width, height: z.height }) - : (this.clipRect = b.clipRect(z)); - G = 'animate'; - k || - ((G = 'attr'), - (this.plotBorder = k = b - .rect() - .addClass('highcharts-plot-border') - .attr({ zIndex: 1 }) - .add())); - k.attr({ - stroke: a.plotBorderColor, - 'stroke-width': a.plotBorderWidth || 0, - fill: 'none', - }); - k[G](k.crisp({ x: A, y: F, width: t, height: x }, -k.strokeWidth())); - this.isDirtyBox = !1; - }, - propFromSeries: function() { - var a = this, - b = a.options.chart, - c, - d = a.options.series, - g, - e; - m(['inverted', 'angular', 'polar'], function(k) { - c = G[b.type || b.defaultSeriesType]; - e = b[k] || (c && c.prototype[k]); - for (g = d && d.length; !e && g--; ) - (c = G[d[g].type]) && c.prototype[k] && (e = !0); - a[k] = e; - }); - }, - linkSeries: function() { - var a = this, - b = a.series; - m(b, function(a) { - a.linkedSeries.length = 0; - }); - m(b, function(b) { - var c = b.options.linkedTo; - I(c) && - (c = ':previous' === c ? a.series[b.index - 1] : a.get(c)) && - c.linkedParent !== b && - (c.linkedSeries.push(b), - (b.linkedParent = c), - (b.visible = q(b.options.visible, c.options.visible, b.visible))); - }); - }, - renderSeries: function() { - m(this.series, function(a) { - a.translate(); - a.render(); - }); - }, - renderLabels: function() { - var a = this, - b = a.options.labels; - b.items && - m(b.items, function(c) { - var g = d(b.style, c.style), - e = A(g.left) + a.plotLeft, - k = A(g.top) + a.plotTop + 12; - delete g.left; - delete g.top; - a.renderer - .text(c.html, e, k) - .attr({ zIndex: 2 }) - .css(g) - .add(); - }); - }, - render: function() { - var a = this.axes, - b = this.renderer, - c = this.options, - d, - g, - e; - this.setTitle(); - this.legend = new x(this, c.legend); - this.getStacks && this.getStacks(); - this.getMargins(!0); - this.setChartSize(); - c = this.plotWidth; - d = this.plotHeight = Math.max(this.plotHeight - 21, 0); - m(a, function(a) { - a.setScale(); - }); - this.getAxisMargins(); - g = 1.1 < c / this.plotWidth; - e = 1.05 < d / this.plotHeight; - if (g || e) - m(a, function(a) { - ((a.horiz && g) || (!a.horiz && e)) && a.setTickInterval(!0); - }), - this.getMargins(); - this.drawChartBox(); - this.hasCartesianSeries && - m(a, function(a) { - a.visible && a.render(); - }); - this.seriesGroup || - (this.seriesGroup = b - .g('series-group') - .attr({ zIndex: 3 }) - .add()); - this.renderSeries(); - this.renderLabels(); - this.addCredits(); - this.setResponsive && this.setResponsive(); - this.hasRendered = !0; - }, - addCredits: function(a) { - var b = this; - a = t(!0, this.options.credits, a); - a.enabled && - !this.credits && - ((this.credits = this.renderer - .text(a.text + (this.mapCredits || ''), 0, 0) - .addClass('highcharts-credits') - .on('click', function() { - a.href && (L.location.href = a.href); - }) - .attr({ align: a.position.align, zIndex: 8 }) - .css(a.style) - .add() - .align(a.position)), - (this.credits.update = function(a) { - b.credits = b.credits.destroy(); - b.addCredits(a); - })); - }, - destroy: function() { - var c = this, - d = c.axes, - g = c.series, - e = c.container, - k, - q = e && e.parentNode; - b(c, 'destroy'); - c.renderer.forExport ? a.erase(u, c) : (u[c.index] = void 0); - a.chartCount--; - c.renderTo.removeAttribute('data-highcharts-chart'); - F(c); - for (k = d.length; k--; ) d[k] = d[k].destroy(); - this.scroller && this.scroller.destroy && this.scroller.destroy(); - for (k = g.length; k--; ) g[k] = g[k].destroy(); - m( - 'title subtitle chartBackground plotBackground plotBGImage plotBorder seriesGroup clipRect credits pointer rangeSelector legend resetZoomButton tooltip renderer'.split( - ' ', - ), - function(a) { - var b = c[a]; - b && b.destroy && (c[a] = b.destroy()); - }, - ); - e && ((e.innerHTML = ''), F(e), q && w(e)); - C(c, function(a, b) { - delete c[b]; - }); - }, - isReadyToRender: function() { - var a = this; - return v || L != L.top || 'complete' === f.readyState - ? !0 - : (f.attachEvent('onreadystatechange', function() { - f.detachEvent('onreadystatechange', a.firstRender); - 'complete' === f.readyState && a.firstRender(); - }), - !1); - }, - firstRender: function() { - var a = this, - c = a.options; - if (a.isReadyToRender()) { - a.getContainer(); - b(a, 'init'); - a.resetMargins(); - a.setChartSize(); - a.propFromSeries(); - a.getAxes(); - m(c.series || [], function(b) { - a.initSeries(b); - }); - a.linkSeries(); - b(a, 'beforeRender'); - N && (a.pointer = new N(a, c)); - a.render(); - if (!a.renderer.imgCount && a.onload) a.onload(); - a.temporaryDisplay(!0); - } - }, - onload: function() { - m( - [this.callback].concat(this.callbacks), - function(a) { - a && void 0 !== this.index && a.apply(this, [this]); - }, - this, - ); - b(this, 'load'); - b(this, 'render'); - h(this.index) && !1 !== this.options.chart.reflow && this.initReflow(); - this.onload = null; - }, - }); - })(M); - (function(a) { - var E, - D = a.each, - H = a.extend, - p = a.erase, - f = a.fireEvent, - l = a.format, - r = a.isArray, - n = a.isNumber, - w = a.pick, - u = a.removeEvent; - a.Point = E = function() {}; - a.Point.prototype = { - init: function(a, h, f) { - this.series = a; - this.color = a.color; - this.applyOptions(h, f); - a.options.colorByPoint - ? ((h = a.options.colors || a.chart.options.colors), - (this.color = this.color || h[a.colorCounter]), - (h = h.length), - (f = a.colorCounter), - a.colorCounter++, - a.colorCounter === h && (a.colorCounter = 0)) - : (f = a.colorIndex); - this.colorIndex = w(this.colorIndex, f); - a.chart.pointCount++; - return this; - }, - applyOptions: function(a, h) { - var e = this.series, - d = e.options.pointValKey || e.pointValKey; - a = E.prototype.optionsToObject.call(this, a); - H(this, a); - this.options = this.options ? H(this.options, a) : a; - a.group && delete this.group; - d && (this.y = this[d]); - this.isNull = w( - this.isValid && !this.isValid(), - null === this.x || !n(this.y, !0), - ); - this.selected && (this.state = 'select'); - 'name' in this && - void 0 === h && - e.xAxis && - e.xAxis.hasNames && - (this.x = e.xAxis.nameToX(this)); - void 0 === this.x && - e && - (this.x = void 0 === h ? e.autoIncrement(this) : h); - return this; - }, - optionsToObject: function(a) { - var e = {}, - f = this.series, - d = f.options.keys, - c = d || f.pointArrayMap || ['y'], - b = c.length, - k = 0, - l = 0; - if (n(a) || null === a) e[c[0]] = a; - else if (r(a)) - for ( - !d && - a.length > b && - ((f = typeof a[0]), - 'string' === f ? (e.name = a[0]) : 'number' === f && (e.x = a[0]), - k++); - l < b; - - ) - (d && void 0 === a[k]) || (e[c[l]] = a[k]), k++, l++; - else - 'object' === typeof a && - ((e = a), - a.dataLabels && (f._hasPointLabels = !0), - a.marker && (f._hasPointMarkers = !0)); - return e; - }, - getClassName: function() { - return ( - 'highcharts-point' + - (this.selected ? ' highcharts-point-select' : '') + - (this.negative ? ' highcharts-negative' : '') + - (this.isNull ? ' highcharts-null-point' : '') + - (void 0 !== this.colorIndex - ? ' highcharts-color-' + this.colorIndex - : '') + - (this.options.className ? ' ' + this.options.className : '') + - (this.zone && this.zone.className - ? ' ' + this.zone.className.replace('highcharts-negative', '') - : '') - ); - }, - getZone: function() { - var a = this.series, - h = a.zones, - a = a.zoneAxis || 'y', - f = 0, - d; - for (d = h[f]; this[a] >= d.value; ) d = h[++f]; - d && d.color && !this.options.color && (this.color = d.color); - return d; - }, - destroy: function() { - var a = this.series.chart, - h = a.hoverPoints, - f; - a.pointCount--; - h && (this.setState(), p(h, this), h.length || (a.hoverPoints = null)); - if (this === a.hoverPoint) this.onMouseOut(); - if (this.graphic || this.dataLabel) u(this), this.destroyElements(); - this.legendItem && a.legend.destroyItem(this); - for (f in this) this[f] = null; - }, - destroyElements: function() { - for ( - var a = [ - 'graphic', - 'dataLabel', - 'dataLabelUpper', - 'connector', - 'shadowGroup', - ], - h, - f = 6; - f--; - - ) - (h = a[f]), this[h] && (this[h] = this[h].destroy()); - }, - getLabelConfig: function() { - return { - x: this.category, - y: this.y, - color: this.color, - colorIndex: this.colorIndex, - key: this.name || this.category, - series: this.series, - point: this, - percentage: this.percentage, - total: this.total || this.stackTotal, - }; - }, - tooltipFormatter: function(a) { - var e = this.series, - f = e.tooltipOptions, - d = w(f.valueDecimals, ''), - c = f.valuePrefix || '', - b = f.valueSuffix || ''; - D(e.pointArrayMap || ['y'], function(e) { - e = '{point.' + e; - if (c || b) a = a.replace(e + '}', c + e + '}' + b); - a = a.replace(e + '}', e + ':,.' + d + 'f}'); - }); - return l(a, { point: this, series: this.series }); - }, - firePointEvent: function(a, h, m) { - var d = this, - c = this.series.options; - (c.point.events[a] || - (d.options && d.options.events && d.options.events[a])) && - this.importEvents(); - 'click' === a && - c.allowPointSelect && - (m = function(a) { - d.select && d.select(null, a.ctrlKey || a.metaKey || a.shiftKey); - }); - f(this, a, h, m); - }, - visible: !0, - }; - })(M); - (function(a) { - var E = a.addEvent, - D = a.animObject, - H = a.arrayMax, - p = a.arrayMin, - f = a.correctFloat, - l = a.Date, - r = a.defaultOptions, - n = a.defaultPlotOptions, - w = a.defined, - u = a.each, - e = a.erase, - h = a.extend, - m = a.fireEvent, - d = a.grep, - c = a.isArray, - b = a.isNumber, - k = a.isString, - z = a.merge, - B = a.objectEach, - I = a.pick, - x = a.removeEvent, - K = a.splat, - t = a.SVGElement, - C = a.syncTimeout, - N = a.win; - a.Series = a.seriesType( - 'line', - null, - { - lineWidth: 2, - allowPointSelect: !1, - showCheckbox: !1, - animation: { duration: 1e3 }, - events: {}, - marker: { - lineWidth: 0, - lineColor: '#ffffff', - radius: 4, - states: { - hover: { - animation: { duration: 50 }, - enabled: !0, - radiusPlus: 2, - lineWidthPlus: 1, - }, - select: { - fillColor: '#cccccc', - lineColor: '#000000', - lineWidth: 2, - }, - }, - }, - point: { events: {} }, - dataLabels: { - align: 'center', - formatter: function() { - return null === this.y ? '' : a.numberFormat(this.y, -1); - }, - style: { - fontSize: '11px', - fontWeight: 'bold', - color: 'contrast', - textOutline: '1px contrast', - }, - verticalAlign: 'bottom', - x: 0, - y: 0, - padding: 5, - }, - cropThreshold: 300, - pointRange: 0, - softThreshold: !0, - states: { - hover: { - animation: { duration: 50 }, - lineWidthPlus: 1, - marker: {}, - halo: { size: 10, opacity: 0.25 }, - }, - select: { marker: {} }, - }, - stickyTracking: !0, - turboThreshold: 1e3, - findNearestPointBy: 'x', - }, - { - isCartesian: !0, - pointClass: a.Point, - sorted: !0, - requireSorting: !0, - directTouch: !1, - axisTypes: ['xAxis', 'yAxis'], - colorCounter: 0, - parallelArrays: ['x', 'y'], - coll: 'series', - init: function(a, b) { - var c = this, - d, - g = a.series, - e; - c.chart = a; - c.options = b = c.setOptions(b); - c.linkedSeries = []; - c.bindAxes(); - h(c, { - name: b.name, - state: '', - visible: !1 !== b.visible, - selected: !0 === b.selected, - }); - d = b.events; - B(d, function(a, b) { - E(c, b, a); - }); - if ( - (d && d.click) || - (b.point && b.point.events && b.point.events.click) || - b.allowPointSelect - ) - a.runTrackerClick = !0; - c.getColor(); - c.getSymbol(); - u(c.parallelArrays, function(a) { - c[a + 'Data'] = []; - }); - c.setData(b.data, !1); - c.isCartesian && (a.hasCartesianSeries = !0); - g.length && (e = g[g.length - 1]); - c._i = I(e && e._i, -1) + 1; - a.orderSeries(this.insert(g)); - }, - insert: function(a) { - var c = this.options.index, - d; - if (b(c)) { - for (d = a.length; d--; ) - if (c >= I(a[d].options.index, a[d]._i)) { - a.splice(d + 1, 0, this); - break; - } - -1 === d && a.unshift(this); - d += 1; - } else a.push(this); - return I(d, a.length - 1); - }, - bindAxes: function() { - var b = this, - c = b.options, - d = b.chart, - e; - u(b.axisTypes || [], function(g) { - u(d[g], function(a) { - e = a.options; - if ( - c[g] === e.index || - (void 0 !== c[g] && c[g] === e.id) || - (void 0 === c[g] && 0 === e.index) - ) - b.insert(a.series), (b[g] = a), (a.isDirty = !0); - }); - b[g] || b.optionalAxis === g || a.error(18, !0); - }); - }, - updateParallelArrays: function(a, c) { - var d = a.series, - e = arguments, - g = b(c) - ? function(b) { - var g = 'y' === b && d.toYData ? d.toYData(a) : a[b]; - d[b + 'Data'][c] = g; - } - : function(a) { - Array.prototype[c].apply( - d[a + 'Data'], - Array.prototype.slice.call(e, 2), - ); - }; - u(d.parallelArrays, g); - }, - autoIncrement: function() { - var b = this.options, - c = this.xIncrement, - d, - e = b.pointIntervalUnit, - g = 0, - c = I(c, b.pointStart, 0); - this.pointInterval = d = I(this.pointInterval, b.pointInterval, 1); - e && - ((b = new l(c)), - 'day' === e - ? (b = +b[l.hcSetDate](b[l.hcGetDate]() + d)) - : 'month' === e - ? (b = +b[l.hcSetMonth](b[l.hcGetMonth]() + d)) - : 'year' === e && - (b = +b[l.hcSetFullYear](b[l.hcGetFullYear]() + d)), - l.hcHasTimeZone && (g = a.getTZOffset(b) - a.getTZOffset(c)), - (d = b - c + g)); - this.xIncrement = c + d; - return c; - }, - setOptions: function(a) { - var b = this.chart, - c = b.options, - d = c.plotOptions, - g = (b.userOptions || {}).plotOptions || {}, - e = d[this.type]; - this.userOptions = a; - b = z(e, d.series, a); - this.tooltipOptions = z( - r.tooltip, - r.plotOptions.series && r.plotOptions.series.tooltip, - r.plotOptions[this.type].tooltip, - c.tooltip.userOptions, - d.series && d.series.tooltip, - d[this.type].tooltip, - a.tooltip, - ); - this.stickyTracking = I( - a.stickyTracking, - g[this.type] && g[this.type].stickyTracking, - g.series && g.series.stickyTracking, - this.tooltipOptions.shared && !this.noSharedTooltip - ? !0 - : b.stickyTracking, - ); - null === e.marker && delete b.marker; - this.zoneAxis = b.zoneAxis; - a = this.zones = (b.zones || []).slice(); - (!b.negativeColor && !b.negativeFillColor) || - b.zones || - a.push({ - value: b[this.zoneAxis + 'Threshold'] || b.threshold || 0, - className: 'highcharts-negative', - color: b.negativeColor, - fillColor: b.negativeFillColor, - }); - a.length && - w(a[a.length - 1].value) && - a.push({ color: this.color, fillColor: this.fillColor }); - return b; - }, - getCyclic: function(a, b, c) { - var d, - g = this.chart, - e = this.userOptions, - k = a + 'Index', - h = a + 'Counter', - q = c ? c.length : I(g.options.chart[a + 'Count'], g[a + 'Count']); - b || - ((d = I(e[k], e['_' + k])), - w(d) || - (g.series.length || (g[h] = 0), - (e['_' + k] = d = g[h] % q), - (g[h] += 1)), - c && (b = c[d])); - void 0 !== d && (this[k] = d); - this[a] = b; - }, - getColor: function() { - this.options.colorByPoint - ? (this.options.color = null) - : this.getCyclic( - 'color', - this.options.color || n[this.type].color, - this.chart.options.colors, - ); - }, - getSymbol: function() { - this.getCyclic( - 'symbol', - this.options.marker.symbol, - this.chart.options.symbols, - ); - }, - drawLegendSymbol: a.LegendSymbolMixin.drawLineMarker, - setData: function(d, e, h, f) { - var g = this, - q = g.points, - m = (q && q.length) || 0, - l, - A = g.options, - t = g.chart, - x = null, - n = g.xAxis, - p = A.turboThreshold, - z = this.xData, - F = this.yData, - C = (l = g.pointArrayMap) && l.length; - d = d || []; - l = d.length; - e = I(e, !0); - if ( - !1 !== f && - l && - m === l && - !g.cropped && - !g.hasGroupedData && - g.visible - ) - u(d, function(a, b) { - q[b].update && a !== A.data[b] && q[b].update(a, !1, null, !1); - }); - else { - g.xIncrement = null; - g.colorCounter = 0; - u(this.parallelArrays, function(a) { - g[a + 'Data'].length = 0; - }); - if (p && l > p) { - for (h = 0; null === x && h < l; ) (x = d[h]), h++; - if (b(x)) - for (h = 0; h < l; h++) - (z[h] = this.autoIncrement()), (F[h] = d[h]); - else if (c(x)) - if (C) - for (h = 0; h < l; h++) - (x = d[h]), (z[h] = x[0]), (F[h] = x.slice(1, C + 1)); - else - for (h = 0; h < l; h++) - (x = d[h]), (z[h] = x[0]), (F[h] = x[1]); - else a.error(12); - } else - for (h = 0; h < l; h++) - void 0 !== d[h] && - ((x = { series: g }), - g.pointClass.prototype.applyOptions.apply(x, [d[h]]), - g.updateParallelArrays(x, h)); - F && k(F[0]) && a.error(14, !0); - g.data = []; - g.options.data = g.userOptions.data = d; - for (h = m; h--; ) q[h] && q[h].destroy && q[h].destroy(); - n && (n.minRange = n.userMinRange); - g.isDirty = t.isDirtyBox = !0; - g.isDirtyData = !!q; - h = !1; - } - 'point' === A.legendType && - (this.processData(), this.generatePoints()); - e && t.redraw(h); - }, - processData: function(b) { - var c = this.xData, - d = this.yData, - e = c.length, - g; - g = 0; - var k, - h, - q = this.xAxis, - f, - m = this.options; - f = m.cropThreshold; - var l = this.getExtremesFromAll || m.getExtremesFromAll, - t = this.isCartesian, - m = q && q.val2lin, - x = q && q.isLog, - n = this.requireSorting, - p, - z; - if (t && !this.isDirty && !q.isDirty && !this.yAxis.isDirty && !b) - return !1; - q && ((b = q.getExtremes()), (p = b.min), (z = b.max)); - if (t && this.sorted && !l && (!f || e > f || this.forceCrop)) - if (c[e - 1] < p || c[0] > z) (c = []), (d = []); - else if (c[0] < p || c[e - 1] > z) - (g = this.cropData(this.xData, this.yData, p, z)), - (c = g.xData), - (d = g.yData), - (g = g.start), - (k = !0); - for (f = c.length || 1; --f; ) - (e = x ? m(c[f]) - m(c[f - 1]) : c[f] - c[f - 1]), - 0 < e && (void 0 === h || e < h) - ? (h = e) - : 0 > e && n && (a.error(15), (n = !1)); - this.cropped = k; - this.cropStart = g; - this.processedXData = c; - this.processedYData = d; - this.closestPointRange = h; - }, - cropData: function(a, b, c, d) { - var g = a.length, - e = 0, - k = g, - h = I(this.cropShoulder, 1), - f; - for (f = 0; f < g; f++) - if (a[f] >= c) { - e = Math.max(0, f - h); - break; - } - for (c = f; c < g; c++) - if (a[c] > d) { - k = c + h; - break; - } - return { - xData: a.slice(e, k), - yData: b.slice(e, k), - start: e, - end: k, - }; - }, - generatePoints: function() { - var a = this.options, - b = a.data, - c = this.data, - d, - g = this.processedXData, - e = this.processedYData, - k = this.pointClass, - h = g.length, - f = this.cropStart || 0, - m, - l = this.hasGroupedData, - a = a.keys, - t, - x = [], - n; - c || l || ((c = []), (c.length = b.length), (c = this.data = c)); - a && l && (this.options.keys = !1); - for (n = 0; n < h; n++) - (m = f + n), - l - ? ((t = new k().init(this, [g[n]].concat(K(e[n])))), - (t.dataGroup = this.groupMap[n])) - : (t = c[m]) || - void 0 === b[m] || - (c[m] = t = new k().init(this, b[m], g[n])), - t && ((t.index = m), (x[n] = t)); - this.options.keys = a; - if (c && (h !== (d = c.length) || l)) - for (n = 0; n < d; n++) - n !== f || l || (n += h), - c[n] && (c[n].destroyElements(), (c[n].plotX = void 0)); - this.data = c; - this.points = x; - }, - getExtremes: function(a) { - var d = this.yAxis, - e = this.processedXData, - k, - g = [], - h = 0; - k = this.xAxis.getExtremes(); - var f = k.min, - q = k.max, - m, - l, - t, - n; - a = a || this.stackedYData || this.processedYData || []; - k = a.length; - for (n = 0; n < k; n++) - if ( - ((l = e[n]), - (t = a[n]), - (m = - (b(t, !0) || c(t)) && - (!d.positiveValuesOnly || t.length || 0 < t)), - (l = - this.getExtremesFromAll || - this.options.getExtremesFromAll || - this.cropped || - ((e[n + 1] || l) >= f && (e[n - 1] || l) <= q)), - m && l) - ) - if ((m = t.length)) - for (; m--; ) 'number' === typeof t[m] && (g[h++] = t[m]); - else g[h++] = t; - this.dataMin = p(g); - this.dataMax = H(g); - }, - translate: function() { - this.processedXData || this.processData(); - this.generatePoints(); - var a = this.options, - c = a.stacking, - d = this.xAxis, - e = d.categories, - g = this.yAxis, - k = this.points, - h = k.length, - m = !!this.modifyValue, - l = a.pointPlacement, - t = 'between' === l || b(l), - n = a.threshold, - x = a.startFromThreshold ? n : 0, - p, - z, - C, - r, - u = Number.MAX_VALUE; - 'between' === l && (l = 0.5); - b(l) && (l *= I(a.pointRange || d.pointRange)); - for (a = 0; a < h; a++) { - var B = k[a], - N = B.x, - K = B.y; - z = B.low; - var D = - c && - g.stacks[ - (this.negStacks && K < (x ? 0 : n) ? '-' : '') + this.stackKey - ], - E; - g.positiveValuesOnly && null !== K && 0 >= K && (B.isNull = !0); - B.plotX = p = f( - Math.min( - Math.max( - -1e5, - d.translate(N, 0, 0, 0, 1, l, 'flags' === this.type), - ), - 1e5, - ), - ); - c && - this.visible && - !B.isNull && - D && - D[N] && - ((r = this.getStackIndicator(r, N, this.index)), - (E = D[N]), - (K = E.points[r.key]), - (z = K[0]), - (K = K[1]), - z === x && r.key === D[N].base && (z = I(n, g.min)), - g.positiveValuesOnly && 0 >= z && (z = null), - (B.total = B.stackTotal = E.total), - (B.percentage = E.total && (B.y / E.total) * 100), - (B.stackY = K), - E.setOffset(this.pointXOffset || 0, this.barW || 0)); - B.yBottom = w(z) ? g.translate(z, 0, 1, 0, 1) : null; - m && (K = this.modifyValue(K, B)); - B.plotY = z = - 'number' === typeof K && Infinity !== K - ? Math.min(Math.max(-1e5, g.translate(K, 0, 1, 0, 1)), 1e5) - : void 0; - B.isInside = - void 0 !== z && 0 <= z && z <= g.len && 0 <= p && p <= d.len; - B.clientX = t ? f(d.translate(N, 0, 0, 0, 1, l)) : p; - B.negative = B.y < (n || 0); - B.category = e && void 0 !== e[B.x] ? e[B.x] : B.x; - B.isNull || - (void 0 !== C && (u = Math.min(u, Math.abs(p - C))), (C = p)); - B.zone = this.zones.length && B.getZone(); - } - this.closestPointRangePx = u; - }, - getValidPoints: function(a, b) { - var c = this.chart; - return d(a || this.points || [], function(a) { - return b && !c.isInsidePlot(a.plotX, a.plotY, c.inverted) - ? !1 - : !a.isNull; - }); - }, - setClip: function(a) { - var b = this.chart, - c = this.options, - d = b.renderer, - g = b.inverted, - e = this.clipBox, - k = e || b.clipBox, - h = - this.sharedClipKey || - [ - '_sharedClip', - a && a.duration, - a && a.easing, - k.height, - c.xAxis, - c.yAxis, - ].join(), - f = b[h], - q = b[h + 'm']; - f || - (a && - ((k.width = 0), - g && (k.x = b.plotSizeX), - (b[h + 'm'] = q = d.clipRect( - g ? b.plotSizeX + 99 : -99, - g ? -b.plotLeft : -b.plotTop, - 99, - g ? b.chartWidth : b.chartHeight, - ))), - (b[h] = f = d.clipRect(k)), - (f.count = { length: 0 })); - a && - !f.count[this.index] && - ((f.count[this.index] = !0), (f.count.length += 1)); - !1 !== c.clip && - (this.group.clip(a || e ? f : b.clipRect), - this.markerGroup.clip(q), - (this.sharedClipKey = h)); - a || - (f.count[this.index] && - (delete f.count[this.index], --f.count.length), - 0 === f.count.length && - h && - b[h] && - (e || (b[h] = b[h].destroy()), - b[h + 'm'] && (b[h + 'm'] = b[h + 'm'].destroy()))); - }, - animate: function(a) { - var b = this.chart, - c = D(this.options.animation), - d; - a - ? this.setClip(c) - : ((d = this.sharedClipKey), - (a = b[d]) && a.animate({ width: b.plotSizeX, x: 0 }, c), - b[d + 'm'] && - b[d + 'm'].animate({ width: b.plotSizeX + 99, x: 0 }, c), - (this.animate = null)); - }, - afterAnimate: function() { - this.setClip(); - m(this, 'afterAnimate'); - this.finishedAnimating = !0; - }, - drawPoints: function() { - var a = this.points, - b = this.chart, - c, - d, - g, - e, - k = this.options.marker, - h, - f, - l, - m = this[this.specialGroup] || this.markerGroup, - t, - n = I( - k.enabled, - this.xAxis.isRadial ? !0 : null, - this.closestPointRangePx >= 2 * k.radius, - ); - if (!1 !== k.enabled || this._hasPointMarkers) - for (c = 0; c < a.length; c++) - (d = a[c]), - (e = d.graphic), - (h = d.marker || {}), - (f = !!d.marker), - (g = (n && void 0 === h.enabled) || h.enabled), - (l = d.isInside), - g && !d.isNull - ? ((g = I(h.symbol, this.symbol)), - (d.hasImage = 0 === g.indexOf('url')), - (t = this.markerAttribs(d, d.selected && 'select')), - e - ? e[l ? 'show' : 'hide'](!0).animate(t) - : l && - (0 < t.width || d.hasImage) && - (d.graphic = e = b.renderer - .symbol(g, t.x, t.y, t.width, t.height, f ? h : k) - .add(m)), - e && e.attr(this.pointAttribs(d, d.selected && 'select')), - e && e.addClass(d.getClassName(), !0)) - : e && (d.graphic = e.destroy()); - }, - markerAttribs: function(a, b) { - var c = this.options.marker, - d = a.marker || {}, - g = I(d.radius, c.radius); - b && - ((c = c.states[b]), - (b = d.states && d.states[b]), - (g = I( - b && b.radius, - c && c.radius, - g + ((c && c.radiusPlus) || 0), - ))); - a.hasImage && (g = 0); - a = { x: Math.floor(a.plotX) - g, y: a.plotY - g }; - g && (a.width = a.height = 2 * g); - return a; - }, - pointAttribs: function(a, b) { - var c = this.options.marker, - d = a && a.options, - g = (d && d.marker) || {}, - e = this.color, - k = d && d.color, - h = a && a.color, - d = I(g.lineWidth, c.lineWidth); - a = a && a.zone && a.zone.color; - e = k || a || h || e; - a = g.fillColor || c.fillColor || e; - e = g.lineColor || c.lineColor || e; - b && - ((c = c.states[b]), - (b = (g.states && g.states[b]) || {}), - (d = I( - b.lineWidth, - c.lineWidth, - d + I(b.lineWidthPlus, c.lineWidthPlus, 0), - )), - (a = b.fillColor || c.fillColor || a), - (e = b.lineColor || c.lineColor || e)); - return { stroke: e, 'stroke-width': d, fill: a }; - }, - destroy: function() { - var a = this, - b = a.chart, - c = /AppleWebKit\/533/.test(N.navigator.userAgent), - d, - g, - k = a.data || [], - h, - f; - m(a, 'destroy'); - x(a); - u(a.axisTypes || [], function(b) { - (f = a[b]) && - f.series && - (e(f.series, a), (f.isDirty = f.forceRedraw = !0)); - }); - a.legendItem && a.chart.legend.destroyItem(a); - for (g = k.length; g--; ) (h = k[g]) && h.destroy && h.destroy(); - a.points = null; - clearTimeout(a.animationTimeout); - B(a, function(a, b) { - a instanceof t && - !a.survive && - ((d = c && 'group' === b ? 'hide' : 'destroy'), a[d]()); - }); - b.hoverSeries === a && (b.hoverSeries = null); - e(b.series, a); - b.orderSeries(); - B(a, function(b, c) { - delete a[c]; - }); - }, - getGraphPath: function(a, b, c) { - var d = this, - g = d.options, - e = g.step, - k, - h = [], - f = [], - l; - a = a || d.points; - (k = a.reversed) && a.reverse(); - (e = { right: 1, center: 2 }[e] || (e && 3)) && k && (e = 4 - e); - !g.connectNulls || b || c || (a = this.getValidPoints(a)); - u(a, function(k, m) { - var q = k.plotX, - t = k.plotY, - n = a[m - 1]; - (k.leftCliff || (n && n.rightCliff)) && !c && (l = !0); - k.isNull && !w(b) && 0 < m - ? (l = !g.connectNulls) - : k.isNull && !b - ? (l = !0) - : (0 === m || l - ? (m = ['M', k.plotX, k.plotY]) - : d.getPointSpline - ? (m = d.getPointSpline(a, k, m)) - : e - ? ((m = - 1 === e - ? ['L', n.plotX, t] - : 2 === e - ? [ - 'L', - (n.plotX + q) / 2, - n.plotY, - 'L', - (n.plotX + q) / 2, - t, - ] - : ['L', q, n.plotY]), - m.push('L', q, t)) - : (m = ['L', q, t]), - f.push(k.x), - e && f.push(k.x), - h.push.apply(h, m), - (l = !1)); - }); - h.xMap = f; - return (d.graphPath = h); - }, - drawGraph: function() { - var a = this, - b = this.options, - c = (this.gappedPath || this.getGraphPath).call(this), - d = [ - [ - 'graph', - 'highcharts-graph', - b.lineColor || this.color, - b.dashStyle, - ], - ]; - u(this.zones, function(c, e) { - d.push([ - 'zone-graph-' + e, - 'highcharts-graph highcharts-zone-graph-' + - e + - ' ' + - (c.className || ''), - c.color || a.color, - c.dashStyle || b.dashStyle, - ]); - }); - u(d, function(d, e) { - var g = d[0], - k = a[g]; - k - ? ((k.endX = a.preventGraphAnimation ? null : c.xMap), - k.animate({ d: c })) - : c.length && - ((a[g] = a.chart.renderer - .path(c) - .addClass(d[1]) - .attr({ zIndex: 1 }) - .add(a.group)), - (k = { - stroke: d[2], - 'stroke-width': b.lineWidth, - fill: (a.fillGraph && a.color) || 'none', - }), - d[3] - ? (k.dashstyle = d[3]) - : 'square' !== b.linecap && - (k['stroke-linecap'] = k['stroke-linejoin'] = 'round'), - (k = a[g].attr(k).shadow(2 > e && b.shadow))); - k && ((k.startX = c.xMap), (k.isArea = c.isArea)); - }); - }, - applyZones: function() { - var a = this, - b = this.chart, - c = b.renderer, - d = this.zones, - e, - k, - h = this.clips || [], - f, - m = this.graph, - l = this.area, - t = Math.max(b.chartWidth, b.chartHeight), - n = this[(this.zoneAxis || 'y') + 'Axis'], - x, - p, - z = b.inverted, - C, - r, - w, - B, - K = !1; - d.length && - (m || l) && - n && - void 0 !== n.min && - ((p = n.reversed), - (C = n.horiz), - m && m.hide(), - l && l.hide(), - (x = n.getExtremes()), - u(d, function(d, g) { - e = p ? (C ? b.plotWidth : 0) : C ? 0 : n.toPixels(x.min); - e = Math.min(Math.max(I(k, e), 0), t); - k = Math.min( - Math.max(Math.round(n.toPixels(I(d.value, x.max), !0)), 0), - t, - ); - K && (e = k = n.toPixels(x.max)); - r = Math.abs(e - k); - w = Math.min(e, k); - B = Math.max(e, k); - n.isXAxis - ? ((f = { x: z ? B : w, y: 0, width: r, height: t }), - C || (f.x = b.plotHeight - f.x)) - : ((f = { x: 0, y: z ? B : w, width: t, height: r }), - C && (f.y = b.plotWidth - f.y)); - z && - c.isVML && - (f = n.isXAxis - ? { x: 0, y: p ? w : B, height: f.width, width: b.chartWidth } - : { - x: f.y - b.plotLeft - b.spacingBox.x, - y: 0, - width: f.height, - height: b.chartHeight, - }); - h[g] - ? h[g].animate(f) - : ((h[g] = c.clipRect(f)), - m && a['zone-graph-' + g].clip(h[g]), - l && a['zone-area-' + g].clip(h[g])); - K = d.value > x.max; - }), - (this.clips = h)); - }, - invertGroups: function(a) { - function b() { - u(['group', 'markerGroup'], function(b) { - c[b] && - (d.renderer.isVML && - c[b].attr({ width: c.yAxis.len, height: c.xAxis.len }), - (c[b].width = c.yAxis.len), - (c[b].height = c.xAxis.len), - c[b].invert(a)); - }); - } - var c = this, - d = c.chart, - e; - c.xAxis && - ((e = E(d, 'resize', b)), - E(c, 'destroy', e), - b(a), - (c.invertGroups = b)); - }, - plotGroup: function(a, b, c, d, e) { - var g = this[a], - k = !g; - k && - (this[a] = g = this.chart.renderer - .g() - .attr({ zIndex: d || 0.1 }) - .add(e)); - g.addClass( - 'highcharts-' + - b + - ' highcharts-series-' + - this.index + - ' highcharts-' + - this.type + - '-series ' + - (w(this.colorIndex) - ? 'highcharts-color-' + this.colorIndex + ' ' - : '') + - (this.options.className || '') + - (g.hasClass('highcharts-tracker') ? ' highcharts-tracker' : ''), - !0, - ); - g.attr({ visibility: c })[k ? 'attr' : 'animate'](this.getPlotBox()); - return g; - }, - getPlotBox: function() { - var a = this.chart, - b = this.xAxis, - c = this.yAxis; - a.inverted && ((b = c), (c = this.xAxis)); - return { - translateX: b ? b.left : a.plotLeft, - translateY: c ? c.top : a.plotTop, - scaleX: 1, - scaleY: 1, - }; - }, - render: function() { - var a = this, - b = a.chart, - c, - d = a.options, - e = !!a.animate && b.renderer.isSVG && D(d.animation).duration, - k = a.visible ? 'inherit' : 'hidden', - h = d.zIndex, - f = a.hasRendered, - m = b.seriesGroup, - l = b.inverted; - c = a.plotGroup('group', 'series', k, h, m); - a.markerGroup = a.plotGroup('markerGroup', 'markers', k, h, m); - e && a.animate(!0); - c.inverted = a.isCartesian ? l : !1; - a.drawGraph && (a.drawGraph(), a.applyZones()); - a.drawDataLabels && a.drawDataLabels(); - a.visible && a.drawPoints(); - a.drawTracker && - !1 !== a.options.enableMouseTracking && - a.drawTracker(); - a.invertGroups(l); - !1 === d.clip || a.sharedClipKey || f || c.clip(b.clipRect); - e && a.animate(); - f || - (a.animationTimeout = C(function() { - a.afterAnimate(); - }, e)); - a.isDirty = !1; - a.hasRendered = !0; - }, - redraw: function() { - var a = this.chart, - b = this.isDirty || this.isDirtyData, - c = this.group, - d = this.xAxis, - e = this.yAxis; - c && - (a.inverted && c.attr({ width: a.plotWidth, height: a.plotHeight }), - c.animate({ - translateX: I(d && d.left, a.plotLeft), - translateY: I(e && e.top, a.plotTop), - })); - this.translate(); - this.render(); - b && delete this.kdTree; - }, - kdAxisArray: ['clientX', 'plotY'], - searchPoint: function(a, b) { - var c = this.xAxis, - d = this.yAxis, - e = this.chart.inverted; - return this.searchKDTree( - { - clientX: e ? c.len - a.chartY + c.pos : a.chartX - c.pos, - plotY: e ? d.len - a.chartX + d.pos : a.chartY - d.pos, - }, - b, - ); - }, - buildKDTree: function() { - function a(c, d, e) { - var g, k; - if ((k = c && c.length)) - return ( - (g = b.kdAxisArray[d % e]), - c.sort(function(a, b) { - return a[g] - b[g]; - }), - (k = Math.floor(k / 2)), - { - point: c[k], - left: a(c.slice(0, k), d + 1, e), - right: a(c.slice(k + 1), d + 1, e), - } - ); - } - this.buildingKdTree = !0; - var b = this, - c = -1 < b.options.findNearestPointBy.indexOf('y') ? 2 : 1; - delete b.kdTree; - C( - function() { - b.kdTree = a(b.getValidPoints(null, !b.directTouch), c, c); - b.buildingKdTree = !1; - }, - b.options.kdNow ? 0 : 1, - ); - }, - searchKDTree: function(a, b) { - function c(a, b, g, f) { - var m = b.point, - l = d.kdAxisArray[g % f], - q, - t, - n = m; - t = w(a[e]) && w(m[e]) ? Math.pow(a[e] - m[e], 2) : null; - q = w(a[k]) && w(m[k]) ? Math.pow(a[k] - m[k], 2) : null; - q = (t || 0) + (q || 0); - m.dist = w(q) ? Math.sqrt(q) : Number.MAX_VALUE; - m.distX = w(t) ? Math.sqrt(t) : Number.MAX_VALUE; - l = a[l] - m[l]; - q = 0 > l ? 'left' : 'right'; - t = 0 > l ? 'right' : 'left'; - b[q] && ((q = c(a, b[q], g + 1, f)), (n = q[h] < n[h] ? q : m)); - b[t] && - Math.sqrt(l * l) < n[h] && - ((a = c(a, b[t], g + 1, f)), (n = a[h] < n[h] ? a : n)); - return n; - } - var d = this, - e = this.kdAxisArray[0], - k = this.kdAxisArray[1], - h = b ? 'distX' : 'dist'; - b = -1 < d.options.findNearestPointBy.indexOf('y') ? 2 : 1; - this.kdTree || this.buildingKdTree || this.buildKDTree(); - if (this.kdTree) return c(a, this.kdTree, b, b); - }, - }, - ); - })(M); - (function(a) { - var E = a.Axis, - D = a.Chart, - H = a.correctFloat, - p = a.defined, - f = a.destroyObjectProperties, - l = a.each, - r = a.format, - n = a.objectEach, - w = a.pick, - u = a.Series; - a.StackItem = function(a, h, f, d, c) { - var b = a.chart.inverted; - this.axis = a; - this.isNegative = f; - this.options = h; - this.x = d; - this.total = null; - this.points = {}; - this.stack = c; - this.rightCliff = this.leftCliff = 0; - this.alignOptions = { - align: h.align || (b ? (f ? 'left' : 'right') : 'center'), - verticalAlign: h.verticalAlign || (b ? 'middle' : f ? 'bottom' : 'top'), - y: w(h.y, b ? 4 : f ? 14 : -6), - x: w(h.x, b ? (f ? -6 : 6) : 0), - }; - this.textAlign = h.textAlign || (b ? (f ? 'right' : 'left') : 'center'); - }; - a.StackItem.prototype = { - destroy: function() { - f(this, this.axis); - }, - render: function(a) { - var e = this.options, - f = e.format, - f = f ? r(f, this) : e.formatter.call(this); - this.label - ? this.label.attr({ text: f, visibility: 'hidden' }) - : (this.label = this.axis.chart.renderer - .text(f, null, null, e.useHTML) - .css(e.style) - .attr({ - align: this.textAlign, - rotation: e.rotation, - visibility: 'hidden', - }) - .add(a)); - }, - setOffset: function(a, h) { - var e = this.axis, - d = e.chart, - c = e.translate(e.usePercentage ? 100 : this.total, 0, 0, 0, 1), - e = e.translate(0), - e = Math.abs(c - e); - a = d.xAxis[0].translate(this.x) + a; - c = this.getStackBox(d, this, a, c, h, e); - if ((h = this.label)) - h.align(this.alignOptions, null, c), - (c = h.alignAttr), - h[ - !1 === this.options.crop || d.isInsidePlot(c.x, c.y) - ? 'show' - : 'hide' - ](!0); - }, - getStackBox: function(a, h, f, d, c, b) { - var e = h.axis.reversed, - l = a.inverted; - a = a.plotHeight; - h = (h.isNegative && !e) || (!h.isNegative && e); - return { - x: l ? (h ? d : d - b) : f, - y: l ? a - f - c : h ? a - d - b : a - d, - width: l ? b : c, - height: l ? c : b, - }; - }, - }; - D.prototype.getStacks = function() { - var a = this; - l(a.yAxis, function(a) { - a.stacks && a.hasVisibleSeries && (a.oldStacks = a.stacks); - }); - l(a.series, function(e) { - !e.options.stacking || - (!0 !== e.visible && !1 !== a.options.chart.ignoreHiddenSeries) || - (e.stackKey = e.type + w(e.options.stack, '')); - }); - }; - E.prototype.buildStacks = function() { - var a = this.series, - h = w(this.options.reversedStacks, !0), - f = a.length, - d; - if (!this.isXAxis) { - this.usePercentage = !1; - for (d = f; d--; ) a[h ? d : f - d - 1].setStackedPoints(); - for (d = 0; d < f; d++) a[d].modifyStacks(); - } - }; - E.prototype.renderStackTotals = function() { - var a = this.chart, - h = a.renderer, - f = this.stacks, - d = this.stackTotalGroup; - d || - (this.stackTotalGroup = d = h - .g('stack-labels') - .attr({ visibility: 'visible', zIndex: 6 }) - .add()); - d.translate(a.plotLeft, a.plotTop); - n(f, function(a) { - n(a, function(a) { - a.render(d); - }); - }); - }; - E.prototype.resetStacks = function() { - var a = this, - h = a.stacks; - a.isXAxis || - n(h, function(e) { - n(e, function(d, c) { - d.touched < a.stacksTouched - ? (d.destroy(), delete e[c]) - : ((d.total = null), (d.cumulative = null)); - }); - }); - }; - E.prototype.cleanStacks = function() { - var a; - this.isXAxis || - (this.oldStacks && (a = this.stacks = this.oldStacks), - n(a, function(a) { - n(a, function(a) { - a.cumulative = a.total; - }); - })); - }; - u.prototype.setStackedPoints = function() { - if ( - this.options.stacking && - (!0 === this.visible || - !1 === this.chart.options.chart.ignoreHiddenSeries) - ) { - var e = this.processedXData, - h = this.processedYData, - f = [], - d = h.length, - c = this.options, - b = c.threshold, - k = w(c.startFromThreshold && b, 0), - l = c.stack, - c = c.stacking, - n = this.stackKey, - r = '-' + n, - x = this.negStacks, - u = this.yAxis, - t = u.stacks, - C = u.oldStacks, - N, - q, - A, - F, - G, - g, - v; - u.stacksTouched += 1; - for (G = 0; G < d; G++) - (g = e[G]), - (v = h[G]), - (N = this.getStackIndicator(N, g, this.index)), - (F = N.key), - (A = (q = x && v < (k ? 0 : b)) ? r : n), - t[A] || (t[A] = {}), - t[A][g] || - (C[A] && C[A][g] - ? ((t[A][g] = C[A][g]), (t[A][g].total = null)) - : (t[A][g] = new a.StackItem( - u, - u.options.stackLabels, - q, - g, - l, - ))), - (A = t[A][g]), - null !== v - ? ((A.points[F] = A.points[this.index] = [w(A.cumulative, k)]), - p(A.cumulative) || (A.base = F), - (A.touched = u.stacksTouched), - 0 < N.index && - !1 === this.singleStacks && - (A.points[F][0] = A.points[this.index + ',' + g + ',0'][0])) - : (A.points[F] = A.points[this.index] = null), - 'percent' === c - ? ((q = q ? n : r), - x && t[q] && t[q][g] - ? ((q = t[q][g]), - (A.total = q.total = - Math.max(q.total, A.total) + Math.abs(v) || 0)) - : (A.total = H(A.total + (Math.abs(v) || 0)))) - : (A.total = H(A.total + (v || 0))), - (A.cumulative = w(A.cumulative, k) + (v || 0)), - null !== v && - (A.points[F].push(A.cumulative), (f[G] = A.cumulative)); - 'percent' === c && (u.usePercentage = !0); - this.stackedYData = f; - u.oldStacks = {}; - } - }; - u.prototype.modifyStacks = function() { - var a = this, - h = a.stackKey, - f = a.yAxis.stacks, - d = a.processedXData, - c, - b = a.options.stacking; - a[b + 'Stacker'] && - l([h, '-' + h], function(e) { - for (var k = d.length, h, l; k--; ) - if ( - ((h = d[k]), - (c = a.getStackIndicator(c, h, a.index, e)), - (l = (h = f[e] && f[e][h]) && h.points[c.key])) - ) - a[b + 'Stacker'](l, h, k); - }); - }; - u.prototype.percentStacker = function(a, h, f) { - h = h.total ? 100 / h.total : 0; - a[0] = H(a[0] * h); - a[1] = H(a[1] * h); - this.stackedYData[f] = a[1]; - }; - u.prototype.getStackIndicator = function(a, h, f, d) { - !p(a) || a.x !== h || (d && a.key !== d) - ? (a = { x: h, index: 0, key: d }) - : a.index++; - a.key = [f, h, a.index].join(); - return a; - }; - })(M); - (function(a) { - var E = a.addEvent, - D = a.animate, - H = a.Axis, - p = a.createElement, - f = a.css, - l = a.defined, - r = a.each, - n = a.erase, - w = a.extend, - u = a.fireEvent, - e = a.inArray, - h = a.isNumber, - m = a.isObject, - d = a.isArray, - c = a.merge, - b = a.objectEach, - k = a.pick, - z = a.Point, - B = a.Series, - I = a.seriesTypes, - x = a.setAnimation, - K = a.splat; - w(a.Chart.prototype, { - addSeries: function(a, b, c) { - var d, - e = this; - a && - ((b = k(b, !0)), - u(e, 'addSeries', { options: a }, function() { - d = e.initSeries(a); - e.isDirtyLegend = !0; - e.linkSeries(); - b && e.redraw(c); - })); - return d; - }, - addAxis: function(a, b, d, e) { - var h = b ? 'xAxis' : 'yAxis', - f = this.options; - a = c(a, { index: this[h].length, isX: b }); - b = new H(this, a); - f[h] = K(f[h] || {}); - f[h].push(a); - k(d, !0) && this.redraw(e); - return b; - }, - showLoading: function(a) { - var b = this, - c = b.options, - d = b.loadingDiv, - e = c.loading, - k = function() { - d && - f(d, { - left: b.plotLeft + 'px', - top: b.plotTop + 'px', - width: b.plotWidth + 'px', - height: b.plotHeight + 'px', - }); - }; - d || - ((b.loadingDiv = d = p( - 'div', - { className: 'highcharts-loading highcharts-loading-hidden' }, - null, - b.container, - )), - (b.loadingSpan = p( - 'span', - { className: 'highcharts-loading-inner' }, - null, - d, - )), - E(b, 'redraw', k)); - d.className = 'highcharts-loading'; - b.loadingSpan.innerHTML = a || c.lang.loading; - f(d, w(e.style, { zIndex: 10 })); - f(b.loadingSpan, e.labelStyle); - b.loadingShown || - (f(d, { opacity: 0, display: '' }), - D( - d, - { opacity: e.style.opacity || 0.5 }, - { duration: e.showDuration || 0 }, - )); - b.loadingShown = !0; - k(); - }, - hideLoading: function() { - var a = this.options, - b = this.loadingDiv; - b && - ((b.className = 'highcharts-loading highcharts-loading-hidden'), - D( - b, - { opacity: 0 }, - { - duration: a.loading.hideDuration || 100, - complete: function() { - f(b, { display: 'none' }); - }, - }, - )); - this.loadingShown = !1; - }, - propsRequireDirtyBox: 'backgroundColor borderColor borderWidth margin marginTop marginRight marginBottom marginLeft spacing spacingTop spacingRight spacingBottom spacingLeft borderRadius plotBackgroundColor plotBackgroundImage plotBorderColor plotBorderWidth plotShadow shadow'.split( - ' ', - ), - propsRequireUpdateSeries: 'chart.inverted chart.polar chart.ignoreHiddenSeries chart.type colors plotOptions tooltip'.split( - ' ', - ), - update: function(a, d, f) { - var m = this, - n = { - credits: 'addCredits', - title: 'setTitle', - subtitle: 'setSubtitle', - }, - t = a.chart, - x, - g, - p = []; - if (t) { - c(!0, m.options.chart, t); - 'className' in t && m.setClassName(t.className); - if ('inverted' in t || 'polar' in t) m.propFromSeries(), (x = !0); - 'alignTicks' in t && (x = !0); - b(t, function(a, b) { - -1 !== e('chart.' + b, m.propsRequireUpdateSeries) && (g = !0); - -1 !== e(b, m.propsRequireDirtyBox) && (m.isDirtyBox = !0); - }); - 'style' in t && m.renderer.setStyle(t.style); - } - a.colors && (this.options.colors = a.colors); - a.plotOptions && c(!0, this.options.plotOptions, a.plotOptions); - b(a, function(a, b) { - if (m[b] && 'function' === typeof m[b].update) m[b].update(a, !1); - else if ('function' === typeof m[n[b]]) m[n[b]](a); - 'chart' !== b && -1 !== e(b, m.propsRequireUpdateSeries) && (g = !0); - }); - r('xAxis yAxis zAxis series colorAxis pane'.split(' '), function(b) { - a[b] && - (r(K(a[b]), function(a, c) { - (c = (l(a.id) && m.get(a.id)) || m[b][c]) && - c.coll === b && - (c.update(a, !1), f && (c.touched = !0)); - if (!c && f) - if ('series' === b) m.addSeries(a, !1).touched = !0; - else if ('xAxis' === b || 'yAxis' === b) - m.addAxis(a, 'xAxis' === b, !1).touched = !0; - }), - f && - r(m[b], function(a) { - a.touched ? delete a.touched : p.push(a); - })); - }); - r(p, function(a) { - a.remove(!1); - }); - x && - r(m.axes, function(a) { - a.update({}, !1); - }); - g && - r(m.series, function(a) { - a.update({}, !1); - }); - a.loading && c(!0, m.options.loading, a.loading); - x = t && t.width; - t = t && t.height; - (h(x) && x !== m.chartWidth) || (h(t) && t !== m.chartHeight) - ? m.setSize(x, t) - : k(d, !0) && m.redraw(); - }, - setSubtitle: function(a) { - this.setTitle(void 0, a); - }, - }); - w(z.prototype, { - update: function(a, b, c, d) { - function e() { - h.applyOptions(a); - null === h.y && g && (h.graphic = g.destroy()); - m(a, !0) && - (g && - g.element && - a && - a.marker && - void 0 !== a.marker.symbol && - (h.graphic = g.destroy()), - a && - a.dataLabels && - h.dataLabel && - (h.dataLabel = h.dataLabel.destroy()), - h.connector && (h.connector = h.connector.destroy())); - l = h.index; - f.updateParallelArrays(h, l); - t.data[l] = m(t.data[l], !0) || m(a, !0) ? h.options : a; - f.isDirty = f.isDirtyData = !0; - !f.fixedBox && f.hasCartesianSeries && (n.isDirtyBox = !0); - 'point' === t.legendType && (n.isDirtyLegend = !0); - b && n.redraw(c); - } - var h = this, - f = h.series, - g = h.graphic, - l, - n = f.chart, - t = f.options; - b = k(b, !0); - !1 === d ? e() : h.firePointEvent('update', { options: a }, e); - }, - remove: function(a, b) { - this.series.removePoint(e(this, this.series.data), a, b); - }, - }); - w(B.prototype, { - addPoint: function(a, b, c, d) { - var e = this.options, - h = this.data, - f = this.chart, - g = this.xAxis, - g = g && g.hasNames && g.names, - l = e.data, - m, - n, - t = this.xData, - q, - x; - b = k(b, !0); - m = { series: this }; - this.pointClass.prototype.applyOptions.apply(m, [a]); - x = m.x; - q = t.length; - if (this.requireSorting && x < t[q - 1]) - for (n = !0; q && t[q - 1] > x; ) q--; - this.updateParallelArrays(m, 'splice', q, 0, 0); - this.updateParallelArrays(m, q); - g && m.name && (g[x] = m.name); - l.splice(q, 0, a); - n && (this.data.splice(q, 0, null), this.processData()); - 'point' === e.legendType && this.generatePoints(); - c && - (h[0] && h[0].remove - ? h[0].remove(!1) - : (h.shift(), this.updateParallelArrays(m, 'shift'), l.shift())); - this.isDirtyData = this.isDirty = !0; - b && f.redraw(d); - }, - removePoint: function(a, b, c) { - var d = this, - e = d.data, - h = e[a], - f = d.points, - g = d.chart, - l = function() { - f && f.length === e.length && f.splice(a, 1); - e.splice(a, 1); - d.options.data.splice(a, 1); - d.updateParallelArrays(h || { series: d }, 'splice', a, 1); - h && h.destroy(); - d.isDirty = !0; - d.isDirtyData = !0; - b && g.redraw(); - }; - x(c, g); - b = k(b, !0); - h ? h.firePointEvent('remove', null, l) : l(); - }, - remove: function(a, b, c) { - function d() { - e.destroy(); - h.isDirtyLegend = h.isDirtyBox = !0; - h.linkSeries(); - k(a, !0) && h.redraw(b); - } - var e = this, - h = e.chart; - !1 !== c ? u(e, 'remove', null, d) : d(); - }, - update: function(a, b) { - var d = this, - e = d.chart, - h = d.userOptions, - f = d.oldType || d.type, - l = a.type || h.type || e.options.chart.type, - g = I[f].prototype, - m, - n = ['group', 'markerGroup', 'dataLabelsGroup'], - t = ['navigatorSeries', 'baseSeries'], - x = d.finishedAnimating && { animation: !1 }; - if (Object.keys && 'data' === Object.keys(a).toString()) - return this.setData(a.data, b); - t = n.concat(t); - r(t, function(a) { - t[a] = d[a]; - delete d[a]; - }); - a = c( - h, - x, - { index: d.index, pointStart: d.xData[0] }, - { data: d.options.data }, - a, - ); - d.remove(!1, null, !1); - for (m in g) d[m] = void 0; - w(d, I[l || f].prototype); - r(t, function(a) { - d[a] = t[a]; - }); - d.init(e, a); - a.zIndex !== h.zIndex && - r(n, function(b) { - d[b] && d[b].attr({ zIndex: a.zIndex }); - }); - d.oldType = f; - e.linkSeries(); - k(b, !0) && e.redraw(!1); - }, - }); - w(H.prototype, { - update: function(a, b) { - var d = this.chart; - a = d.options[this.coll][this.options.index] = c(this.userOptions, a); - this.destroy(!0); - this.init(d, w(a, { events: void 0 })); - d.isDirtyBox = !0; - k(b, !0) && d.redraw(); - }, - remove: function(a) { - for ( - var b = this.chart, c = this.coll, e = this.series, h = e.length; - h--; - - ) - e[h] && e[h].remove(!1); - n(b.axes, this); - n(b[c], this); - d(b.options[c]) - ? b.options[c].splice(this.options.index, 1) - : delete b.options[c]; - r(b[c], function(a, b) { - a.options.index = b; - }); - this.destroy(); - b.isDirtyBox = !0; - k(a, !0) && b.redraw(); - }, - setTitle: function(a, b) { - this.update({ title: a }, b); - }, - setCategories: function(a, b) { - this.update({ categories: a }, b); - }, - }); - })(M); - (function(a) { - var E = a.color, - D = a.each, - H = a.map, - p = a.pick, - f = a.Series, - l = a.seriesType; - l( - 'area', - 'line', - { softThreshold: !1, threshold: 0 }, - { - singleStacks: !1, - getStackPoints: function(f) { - var l = [], - r = [], - u = this.xAxis, - e = this.yAxis, - h = e.stacks[this.stackKey], - m = {}, - d = this.index, - c = e.series, - b = c.length, - k, - z = p(e.options.reversedStacks, !0) ? 1 : -1, - B; - f = f || this.points; - if (this.options.stacking) { - for (B = 0; B < f.length; B++) - (f[B].leftNull = f[B].rightNull = null), (m[f[B].x] = f[B]); - a.objectEach(h, function(a, b) { - null !== a.total && r.push(b); - }); - r.sort(function(a, b) { - return a - b; - }); - k = H(c, function() { - return this.visible; - }); - D(r, function(a, c) { - var f = 0, - n, - x; - if (m[a] && !m[a].isNull) - l.push(m[a]), - D([-1, 1], function(e) { - var f = 1 === e ? 'rightNull' : 'leftNull', - l = 0, - t = h[r[c + e]]; - if (t) - for (B = d; 0 <= B && B < b; ) - (n = t.points[B]), - n || - (B === d - ? (m[a][f] = !0) - : k[B] && - (x = h[a].points[B]) && - (l -= x[1] - x[0])), - (B += z); - m[a][1 === e ? 'rightCliff' : 'leftCliff'] = l; - }); - else { - for (B = d; 0 <= B && B < b; ) { - if ((n = h[a].points[B])) { - f = n[1]; - break; - } - B += z; - } - f = e.translate(f, 0, 1, 0, 1); - l.push({ - isNull: !0, - plotX: u.translate(a, 0, 0, 0, 1), - x: a, - plotY: f, - yBottom: f, - }); - } - }); - } - return l; - }, - getGraphPath: function(a) { - var l = f.prototype.getGraphPath, - r = this.options, - u = r.stacking, - e = this.yAxis, - h, - m, - d = [], - c = [], - b = this.index, - k, - z = e.stacks[this.stackKey], - B = r.threshold, - I = e.getThreshold(r.threshold), - x, - r = r.connectNulls || 'percent' === u, - K = function(h, f, l) { - var m = a[h]; - h = u && z[m.x].points[b]; - var n = m[l + 'Null'] || 0; - l = m[l + 'Cliff'] || 0; - var x, - t, - m = !0; - l || n - ? ((x = (n ? h[0] : h[1]) + l), (t = h[0] + l), (m = !!n)) - : !u && a[f] && a[f].isNull && (x = t = B); - void 0 !== x && - (c.push({ - plotX: k, - plotY: null === x ? I : e.getThreshold(x), - isNull: m, - isCliff: !0, - }), - d.push({ - plotX: k, - plotY: null === t ? I : e.getThreshold(t), - doCurve: !1, - })); - }; - a = a || this.points; - u && (a = this.getStackPoints(a)); - for (h = 0; h < a.length; h++) - if ( - ((m = a[h].isNull), - (k = p(a[h].rectPlotX, a[h].plotX)), - (x = p(a[h].yBottom, I)), - !m || r) - ) - r || K(h, h - 1, 'left'), - (m && !u && r) || - (c.push(a[h]), d.push({ x: h, plotX: k, plotY: x })), - r || K(h, h + 1, 'right'); - h = l.call(this, c, !0, !0); - d.reversed = !0; - m = l.call(this, d, !0, !0); - m.length && (m[0] = 'L'); - m = h.concat(m); - l = l.call(this, c, !1, r); - m.xMap = h.xMap; - this.areaPath = m; - return l; - }, - drawGraph: function() { - this.areaPath = []; - f.prototype.drawGraph.apply(this); - var a = this, - l = this.areaPath, - w = this.options, - u = [['area', 'highcharts-area', this.color, w.fillColor]]; - D(this.zones, function(e, h) { - u.push([ - 'zone-area-' + h, - 'highcharts-area highcharts-zone-area-' + h + ' ' + e.className, - e.color || a.color, - e.fillColor || w.fillColor, - ]); - }); - D(u, function(e) { - var h = e[0], - f = a[h]; - f - ? ((f.endX = a.preventGraphAnimation ? null : l.xMap), - f.animate({ d: l })) - : ((f = a[h] = a.chart.renderer - .path(l) - .addClass(e[1]) - .attr({ - fill: p( - e[3], - E(e[2]) - .setOpacity(p(w.fillOpacity, 0.75)) - .get(), - ), - zIndex: 0, - }) - .add(a.group)), - (f.isArea = !0)); - f.startX = l.xMap; - f.shiftUnit = w.step ? 2 : 1; - }); - }, - drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, - }, - ); - })(M); - (function(a) { - var E = a.pick; - a = a.seriesType; - a( - 'spline', - 'line', - {}, - { - getPointSpline: function(a, H, p) { - var f = H.plotX, - l = H.plotY, - r = a[p - 1]; - p = a[p + 1]; - var n, w, u, e; - if ( - r && - !r.isNull && - !1 !== r.doCurve && - !H.isCliff && - p && - !p.isNull && - !1 !== p.doCurve && - !H.isCliff - ) { - a = r.plotY; - u = p.plotX; - p = p.plotY; - var h = 0; - n = (1.5 * f + r.plotX) / 2.5; - w = (1.5 * l + a) / 2.5; - u = (1.5 * f + u) / 2.5; - e = (1.5 * l + p) / 2.5; - u !== n && (h = ((e - w) * (u - f)) / (u - n) + l - e); - w += h; - e += h; - w > a && w > l - ? ((w = Math.max(a, l)), (e = 2 * l - w)) - : w < a && w < l && ((w = Math.min(a, l)), (e = 2 * l - w)); - e > p && e > l - ? ((e = Math.max(p, l)), (w = 2 * l - e)) - : e < p && e < l && ((e = Math.min(p, l)), (w = 2 * l - e)); - H.rightContX = u; - H.rightContY = e; - } - H = [ - 'C', - E(r.rightContX, r.plotX), - E(r.rightContY, r.plotY), - E(n, f), - E(w, l), - f, - l, - ]; - r.rightContX = r.rightContY = null; - return H; - }, - }, - ); - })(M); - (function(a) { - var E = a.seriesTypes.area.prototype, - D = a.seriesType; - D('areaspline', 'spline', a.defaultPlotOptions.area, { - getStackPoints: E.getStackPoints, - getGraphPath: E.getGraphPath, - drawGraph: E.drawGraph, - drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, - }); - })(M); - (function(a) { - var E = a.animObject, - D = a.color, - H = a.each, - p = a.extend, - f = a.isNumber, - l = a.merge, - r = a.pick, - n = a.Series, - w = a.seriesType, - u = a.svg; - w( - 'column', - 'line', - { - borderRadius: 0, - crisp: !0, - groupPadding: 0.2, - marker: null, - pointPadding: 0.1, - minPointLength: 0, - cropThreshold: 50, - pointRange: null, - states: { - hover: { halo: !1, brightness: 0.1 }, - select: { color: '#cccccc', borderColor: '#000000' }, - }, - dataLabels: { align: null, verticalAlign: null, y: null }, - softThreshold: !1, - startFromThreshold: !0, - stickyTracking: !1, - tooltip: { distance: 6 }, - threshold: 0, - borderColor: '#ffffff', - }, - { - cropShoulder: 0, - directTouch: !0, - trackerGroups: ['group', 'dataLabelsGroup'], - negStacks: !0, - init: function() { - n.prototype.init.apply(this, arguments); - var a = this, - h = a.chart; - h.hasRendered && - H(h.series, function(e) { - e.type === a.type && (e.isDirty = !0); - }); - }, - getColumnMetrics: function() { - var a = this, - h = a.options, - f = a.xAxis, - d = a.yAxis, - c = f.reversed, - b, - k = {}, - l = 0; - !1 === h.grouping - ? (l = 1) - : H(a.chart.series, function(c) { - var e = c.options, - h = c.yAxis, - f; - c.type !== a.type || - (!c.visible && a.chart.options.chart.ignoreHiddenSeries) || - d.len !== h.len || - d.pos !== h.pos || - (e.stacking - ? ((b = c.stackKey), - void 0 === k[b] && (k[b] = l++), - (f = k[b])) - : !1 !== e.grouping && (f = l++), - (c.columnIndex = f)); - }); - var n = Math.min( - Math.abs(f.transA) * - (f.ordinalSlope || - h.pointRange || - f.closestPointRange || - f.tickInterval || - 1), - f.len, - ), - p = n * h.groupPadding, - x = (n - 2 * p) / (l || 1), - h = Math.min( - h.maxPointWidth || f.len, - r(h.pointWidth, x * (1 - 2 * h.pointPadding)), - ); - a.columnMetrics = { - width: h, - offset: - (x - h) / 2 + - (p + ((a.columnIndex || 0) + (c ? 1 : 0)) * x - n / 2) * - (c ? -1 : 1), - }; - return a.columnMetrics; - }, - crispCol: function(a, h, f, d) { - var c = this.chart, - b = this.borderWidth, - e = -(b % 2 ? 0.5 : 0), - b = b % 2 ? 0.5 : 1; - c.inverted && c.renderer.isVML && (b += 1); - this.options.crisp && - ((f = Math.round(a + f) + e), (a = Math.round(a) + e), (f -= a)); - d = Math.round(h + d) + b; - e = 0.5 >= Math.abs(h) && 0.5 < d; - h = Math.round(h) + b; - d -= h; - e && d && (--h, (d += 1)); - return { x: a, y: h, width: f, height: d }; - }, - translate: function() { - var a = this, - h = a.chart, - f = a.options, - d = (a.dense = 2 > a.closestPointRange * a.xAxis.transA), - d = (a.borderWidth = r(f.borderWidth, d ? 0 : 1)), - c = a.yAxis, - b = f.threshold, - k = (a.translatedThreshold = c.getThreshold(b)), - l = r(f.minPointLength, 5), - p = a.getColumnMetrics(), - u = p.width, - x = (a.barW = Math.max(u, 1 + 2 * d)), - w = (a.pointXOffset = p.offset); - h.inverted && (k -= 0.5); - f.pointPadding && (x = Math.ceil(x)); - n.prototype.translate.apply(a); - H(a.points, function(d) { - var e = r(d.yBottom, k), - f = 999 + Math.abs(e), - f = Math.min(Math.max(-f, d.plotY), c.len + f), - m = d.plotX + w, - n = x, - t = Math.min(f, e), - p, - g = Math.max(f, e) - t; - l && - Math.abs(g) < l && - ((g = l), - (p = (!c.reversed && !d.negative) || (c.reversed && d.negative)), - d.y === b && a.dataMax <= b && c.min < b && (p = !p), - (t = Math.abs(t - k) > l ? e - l : k - (p ? l : 0))); - d.barX = m; - d.pointWidth = u; - d.tooltipPos = h.inverted - ? [c.len + c.pos - h.plotLeft - f, a.xAxis.len - m - n / 2, g] - : [m + n / 2, f + c.pos - h.plotTop, g]; - d.shapeType = 'rect'; - d.shapeArgs = a.crispCol.apply( - a, - d.isNull ? [m, k, n, 0] : [m, t, n, g], - ); - }); - }, - getSymbol: a.noop, - drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, - drawGraph: function() { - this.group[this.dense ? 'addClass' : 'removeClass']( - 'highcharts-dense-data', - ); - }, - pointAttribs: function(a, f) { - var e = this.options, - d, - c = this.pointAttrToOptions || {}; - d = c.stroke || 'borderColor'; - var b = c['stroke-width'] || 'borderWidth', - k = (a && a.color) || this.color, - h = (a && a[d]) || e[d] || this.color || k, - n = (a && a[b]) || e[b] || this[b] || 0, - c = e.dashStyle; - a && - this.zones.length && - ((k = a.getZone()), - (k = a.options.color || (k && k.color) || this.color)); - f && - ((a = l( - e.states[f], - (a.options.states && a.options.states[f]) || {}, - )), - (f = a.brightness), - (k = - a.color || - (void 0 !== f && - D(k) - .brighten(a.brightness) - .get()) || - k), - (h = a[d] || h), - (n = a[b] || n), - (c = a.dashStyle || c)); - d = { fill: k, stroke: h, 'stroke-width': n }; - c && (d.dashstyle = c); - return d; - }, - drawPoints: function() { - var a = this, - h = this.chart, - m = a.options, - d = h.renderer, - c = m.animationLimit || 250, - b; - H(a.points, function(e) { - var k = e.graphic; - if (f(e.plotY) && null !== e.y) { - b = e.shapeArgs; - if (k) k[h.pointCount < c ? 'animate' : 'attr'](l(b)); - else e.graphic = k = d[e.shapeType](b).add(e.group || a.group); - m.borderRadius && k.attr({ r: m.borderRadius }); - k.attr(a.pointAttribs(e, e.selected && 'select')).shadow( - m.shadow, - null, - m.stacking && !m.borderRadius, - ); - k.addClass(e.getClassName(), !0); - } else k && (e.graphic = k.destroy()); - }); - }, - animate: function(a) { - var e = this, - f = this.yAxis, - d = e.options, - c = this.chart.inverted, - b = {}, - k = c ? 'translateX' : 'translateY', - l; - u && - (a - ? ((b.scaleY = 0.001), - (a = Math.min( - f.pos + f.len, - Math.max(f.pos, f.toPixels(d.threshold)), - )), - c ? (b.translateX = a - f.len) : (b.translateY = a), - e.group.attr(b)) - : ((l = e.group.attr(k)), - e.group.animate( - { scaleY: 1 }, - p(E(e.options.animation), { - step: function(a, c) { - b[k] = l + c.pos * (f.pos - l); - e.group.attr(b); - }, - }), - ), - (e.animate = null))); - }, - remove: function() { - var a = this, - f = a.chart; - f.hasRendered && - H(f.series, function(e) { - e.type === a.type && (e.isDirty = !0); - }); - n.prototype.remove.apply(a, arguments); - }, - }, - ); - })(M); - (function(a) { - a = a.seriesType; - a('bar', 'column', null, { inverted: !0 }); - })(M); - (function(a) { - var E = a.Series; - a = a.seriesType; - a( - 'scatter', - 'line', - { - lineWidth: 0, - findNearestPointBy: 'xy', - marker: { enabled: !0 }, - tooltip: { - headerFormat: - '\x3cspan style\x3d"color:{point.color}"\x3e\u25cf\x3c/span\x3e \x3cspan style\x3d"font-size: 0.85em"\x3e {series.name}\x3c/span\x3e\x3cbr/\x3e', - pointFormat: - 'x: \x3cb\x3e{point.x}\x3c/b\x3e\x3cbr/\x3ey: \x3cb\x3e{point.y}\x3c/b\x3e\x3cbr/\x3e', - }, - }, - { - sorted: !1, - requireSorting: !1, - noSharedTooltip: !0, - trackerGroups: ['group', 'markerGroup', 'dataLabelsGroup'], - takeOrdinalPosition: !1, - drawGraph: function() { - this.options.lineWidth && E.prototype.drawGraph.call(this); - }, - }, - ); - })(M); - (function(a) { - var E = a.deg2rad, - D = a.isNumber, - H = a.pick, - p = a.relativeLength; - a.CenteredSeriesMixin = { - getCenter: function() { - var a = this.options, - l = this.chart, - r = 2 * (a.slicedOffset || 0), - n = l.plotWidth - 2 * r, - l = l.plotHeight - 2 * r, - w = a.center, - w = [ - H(w[0], '50%'), - H(w[1], '50%'), - a.size || '100%', - a.innerSize || 0, - ], - u = Math.min(n, l), - e, - h; - for (e = 0; 4 > e; ++e) - (h = w[e]), - (a = 2 > e || (2 === e && /%$/.test(h))), - (w[e] = p(h, [n, l, u, w[2]][e]) + (a ? r : 0)); - w[3] > w[2] && (w[3] = w[2]); - return w; - }, - getStartAndEndRadians: function(a, l) { - a = D(a) ? a : 0; - l = D(l) && l > a && 360 > l - a ? l : a + 360; - return { start: E * (a + -90), end: E * (l + -90) }; - }, - }; - })(M); - (function(a) { - var E = a.addEvent, - D = a.CenteredSeriesMixin, - H = a.defined, - p = a.each, - f = a.extend, - l = D.getStartAndEndRadians, - r = a.inArray, - n = a.noop, - w = a.pick, - u = a.Point, - e = a.Series, - h = a.seriesType, - m = a.setAnimation; - h( - 'pie', - 'line', - { - center: [null, null], - clip: !1, - colorByPoint: !0, - dataLabels: { - distance: 30, - enabled: !0, - formatter: function() { - return this.point.isNull ? void 0 : this.point.name; - }, - x: 0, - }, - ignoreHiddenPoint: !0, - legendType: 'point', - marker: null, - size: null, - showInLegend: !1, - slicedOffset: 10, - stickyTracking: !1, - tooltip: { followPointer: !0 }, - borderColor: '#ffffff', - borderWidth: 1, - states: { hover: { brightness: 0.1, shadow: !1 } }, - }, - { - isCartesian: !1, - requireSorting: !1, - directTouch: !0, - noSharedTooltip: !0, - trackerGroups: ['group', 'dataLabelsGroup'], - axisTypes: [], - pointAttribs: a.seriesTypes.column.prototype.pointAttribs, - animate: function(a) { - var c = this, - b = c.points, - d = c.startAngleRad; - a || - (p(b, function(a) { - var b = a.graphic, - e = a.shapeArgs; - b && - (b.attr({ r: a.startR || c.center[3] / 2, start: d, end: d }), - b.animate( - { r: e.r, start: e.start, end: e.end }, - c.options.animation, - )); - }), - (c.animate = null)); - }, - updateTotals: function() { - var a, - c = 0, - b = this.points, - e = b.length, - f, - h = this.options.ignoreHiddenPoint; - for (a = 0; a < e; a++) - (f = b[a]), (c += h && !f.visible ? 0 : f.isNull ? 0 : f.y); - this.total = c; - for (a = 0; a < e; a++) - (f = b[a]), - (f.percentage = 0 < c && (f.visible || !h) ? (f.y / c) * 100 : 0), - (f.total = c); - }, - generatePoints: function() { - e.prototype.generatePoints.call(this); - this.updateTotals(); - }, - translate: function(a) { - this.generatePoints(); - var c = 0, - b = this.options, - d = b.slicedOffset, - e = d + (b.borderWidth || 0), - f, - h, - m, - n = l(b.startAngle, b.endAngle), - t = (this.startAngleRad = n.start), - n = (this.endAngleRad = n.end) - t, - p = this.points, - u, - q = b.dataLabels.distance, - b = b.ignoreHiddenPoint, - r, - F = p.length, - G; - a || (this.center = a = this.getCenter()); - this.getX = function(b, c, d) { - m = Math.asin( - Math.min((b - a[1]) / (a[2] / 2 + d.labelDistance), 1), - ); - return ( - a[0] + (c ? -1 : 1) * Math.cos(m) * (a[2] / 2 + d.labelDistance) - ); - }; - for (r = 0; r < F; r++) { - G = p[r]; - G.labelDistance = w( - G.options.dataLabels && G.options.dataLabels.distance, - q, - ); - this.maxLabelDistance = Math.max( - this.maxLabelDistance || 0, - G.labelDistance, - ); - f = t + c * n; - if (!b || G.visible) c += G.percentage / 100; - h = t + c * n; - G.shapeType = 'arc'; - G.shapeArgs = { - x: a[0], - y: a[1], - r: a[2] / 2, - innerR: a[3] / 2, - start: Math.round(1e3 * f) / 1e3, - end: Math.round(1e3 * h) / 1e3, - }; - m = (h + f) / 2; - m > 1.5 * Math.PI - ? (m -= 2 * Math.PI) - : m < -Math.PI / 2 && (m += 2 * Math.PI); - G.slicedTranslation = { - translateX: Math.round(Math.cos(m) * d), - translateY: Math.round(Math.sin(m) * d), - }; - h = (Math.cos(m) * a[2]) / 2; - u = (Math.sin(m) * a[2]) / 2; - G.tooltipPos = [a[0] + 0.7 * h, a[1] + 0.7 * u]; - G.half = m < -Math.PI / 2 || m > Math.PI / 2 ? 1 : 0; - G.angle = m; - f = Math.min(e, G.labelDistance / 5); - G.labelPos = [ - a[0] + h + Math.cos(m) * G.labelDistance, - a[1] + u + Math.sin(m) * G.labelDistance, - a[0] + h + Math.cos(m) * f, - a[1] + u + Math.sin(m) * f, - a[0] + h, - a[1] + u, - 0 > G.labelDistance ? 'center' : G.half ? 'right' : 'left', - m, - ]; - } - }, - drawGraph: null, - drawPoints: function() { - var a = this, - c = a.chart.renderer, - b, - e, - h, - l, - m = a.options.shadow; - m && !a.shadowGroup && (a.shadowGroup = c.g('shadow').add(a.group)); - p(a.points, function(d) { - e = d.graphic; - if (d.isNull) e && (d.graphic = e.destroy()); - else { - l = d.shapeArgs; - b = d.getTranslate(); - var k = d.shadowGroup; - m && !k && (k = d.shadowGroup = c.g('shadow').add(a.shadowGroup)); - k && k.attr(b); - h = a.pointAttribs(d, d.selected && 'select'); - e - ? e - .setRadialReference(a.center) - .attr(h) - .animate(f(l, b)) - : ((d.graphic = e = c[d.shapeType](l) - .setRadialReference(a.center) - .attr(b) - .add(a.group)), - d.visible || e.attr({ visibility: 'hidden' }), - e - .attr(h) - .attr({ 'stroke-linejoin': 'round' }) - .shadow(m, k)); - e.addClass(d.getClassName()); - } - }); - }, - searchPoint: n, - sortByAngle: function(a, c) { - a.sort(function(a, d) { - return void 0 !== a.angle && (d.angle - a.angle) * c; - }); - }, - drawLegendSymbol: a.LegendSymbolMixin.drawRectangle, - getCenter: D.getCenter, - getSymbol: n, - }, - { - init: function() { - u.prototype.init.apply(this, arguments); - var a = this, - c; - a.name = w(a.name, 'Slice'); - c = function(b) { - a.slice('select' === b.type); - }; - E(a, 'select', c); - E(a, 'unselect', c); - return a; - }, - isValid: function() { - return a.isNumber(this.y, !0) && 0 <= this.y; - }, - setVisible: function(a, c) { - var b = this, - d = b.series, - e = d.chart, - f = d.options.ignoreHiddenPoint; - c = w(c, f); - a !== b.visible && - ((b.visible = b.options.visible = a = - void 0 === a ? !b.visible : a), - (d.options.data[r(b, d.data)] = b.options), - p(['graphic', 'dataLabel', 'connector', 'shadowGroup'], function( - c, - ) { - if (b[c]) b[c][a ? 'show' : 'hide'](!0); - }), - b.legendItem && e.legend.colorizeItem(b, a), - a || 'hover' !== b.state || b.setState(''), - f && (d.isDirty = !0), - c && e.redraw()); - }, - slice: function(a, c, b) { - var d = this.series; - m(b, d.chart); - w(c, !0); - this.sliced = this.options.sliced = H(a) ? a : !this.sliced; - d.options.data[r(this, d.data)] = this.options; - this.graphic.animate(this.getTranslate()); - this.shadowGroup && this.shadowGroup.animate(this.getTranslate()); - }, - getTranslate: function() { - return this.sliced - ? this.slicedTranslation - : { translateX: 0, translateY: 0 }; - }, - haloPath: function(a) { - var c = this.shapeArgs; - return this.sliced || !this.visible - ? [] - : this.series.chart.renderer.symbols.arc( - c.x, - c.y, - c.r + a, - c.r + a, - { innerR: this.shapeArgs.r - 1, start: c.start, end: c.end }, - ); - }, - }, - ); - })(M); - (function(a) { - var E = a.addEvent, - D = a.arrayMax, - H = a.defined, - p = a.each, - f = a.extend, - l = a.format, - r = a.map, - n = a.merge, - w = a.noop, - u = a.pick, - e = a.relativeLength, - h = a.Series, - m = a.seriesTypes, - d = a.stableSort; - a.distribute = function(a, b) { - function c(a, b) { - return a.target - b.target; - } - var e, - f = !0, - h = a, - l = [], - m; - m = 0; - for (e = a.length; e--; ) m += a[e].size; - if (m > b) { - d(a, function(a, b) { - return (b.rank || 0) - (a.rank || 0); - }); - for (m = e = 0; m <= b; ) (m += a[e].size), e++; - l = a.splice(e - 1, a.length); - } - d(a, c); - for ( - a = r(a, function(a) { - return { size: a.size, targets: [a.target], align: u(a.align, 0.5) }; - }); - f; - - ) { - for (e = a.length; e--; ) - (f = a[e]), - (m = - (Math.min.apply(0, f.targets) + Math.max.apply(0, f.targets)) / - 2), - (f.pos = Math.min(Math.max(0, m - f.size * f.align), b - f.size)); - e = a.length; - for (f = !1; e--; ) - 0 < e && - a[e - 1].pos + a[e - 1].size > a[e].pos && - ((a[e - 1].size += a[e].size), - (a[e - 1].targets = a[e - 1].targets.concat(a[e].targets)), - (a[e - 1].align = 0.5), - a[e - 1].pos + a[e - 1].size > b && - (a[e - 1].pos = b - a[e - 1].size), - a.splice(e, 1), - (f = !0)); - } - e = 0; - p(a, function(a) { - var b = 0; - p(a.targets, function() { - h[e].pos = a.pos + b; - b += h[e].size; - e++; - }); - }); - h.push.apply(h, l); - d(h, c); - }; - h.prototype.drawDataLabels = function() { - function c(a, b) { - var c = b.filter; - return c - ? ((b = c.operator), - (a = a[c.property]), - (c = c.value), - ('\x3e' === b && a > c) || - ('\x3c' === b && a < c) || - ('\x3e\x3d' === b && a >= c) || - ('\x3c\x3d' === b && a <= c) || - ('\x3d\x3d' === b && a == c) || - ('\x3d\x3d\x3d' === b && a === c) - ? !0 - : !1) - : !0; - } - var b = this, - d = b.options, - e = d.dataLabels, - f = b.points, - h, - m, - r = b.hasRendered || 0, - t, - w, - D = u(e.defer, !!d.animation), - q = b.chart.renderer; - if (e.enabled || b._hasPointLabels) - b.dlProcessOptions && b.dlProcessOptions(e), - (w = b.plotGroup( - 'dataLabelsGroup', - 'data-labels', - D && !r ? 'hidden' : 'visible', - e.zIndex || 6, - )), - D && - (w.attr({ opacity: +r }), - r || - E(b, 'afterAnimate', function() { - b.visible && w.show(!0); - w[d.animation ? 'animate' : 'attr']( - { opacity: 1 }, - { duration: 200 }, - ); - })), - (m = e), - p(f, function(f) { - var k, - p = f.dataLabel, - g, - x, - r = f.connector, - z = !p, - C; - h = f.dlOptions || (f.options && f.options.dataLabels); - (k = u(h && h.enabled, m.enabled) && !f.isNull) && - (k = !0 === c(f, h || e)); - k && - ((e = n(m, h)), - (g = f.getLabelConfig()), - (C = e[f.formatPrefix + 'Format'] || e.format), - (t = H(C) - ? l(C, g) - : (e[f.formatPrefix + 'Formatter'] || e.formatter).call(g, e)), - (C = e.style), - (g = e.rotation), - (C.color = u(e.color, C.color, b.color, '#000000')), - 'contrast' === C.color && - ((f.contrastColor = q.getContrast(f.color || b.color)), - (C.color = - e.inside || 0 > u(f.labelDistance, e.distance) || d.stacking - ? f.contrastColor - : '#000000')), - d.cursor && (C.cursor = d.cursor), - (x = { - fill: e.backgroundColor, - stroke: e.borderColor, - 'stroke-width': e.borderWidth, - r: e.borderRadius || 0, - rotation: g, - padding: e.padding, - zIndex: 1, - }), - a.objectEach(x, function(a, b) { - void 0 === a && delete x[b]; - })); - !p || (k && H(t)) - ? k && - H(t) && - (p - ? (x.text = t) - : ((p = f.dataLabel = g - ? q.text(t, 0, -9999).addClass('highcharts-data-label') - : q.label( - t, - 0, - -9999, - e.shape, - null, - null, - e.useHTML, - null, - 'data-label', - )), - p.addClass( - ' highcharts-data-label-color-' + - f.colorIndex + - ' ' + - (e.className || '') + - (e.useHTML ? 'highcharts-tracker' : ''), - )), - p.attr(x), - p.css(C).shadow(e.shadow), - p.added || p.add(w), - b.alignDataLabel(f, p, e, null, z)) - : ((f.dataLabel = p = p.destroy()), - r && (f.connector = r.destroy())); - }); - }; - h.prototype.alignDataLabel = function(a, b, d, e, h) { - var c = this.chart, - k = c.inverted, - l = u(a.dlBox && a.dlBox.centerX, a.plotX, -9999), - m = u(a.plotY, -9999), - n = b.getBBox(), - p, - q = d.rotation, - r = d.align, - w = - this.visible && - (a.series.forceDL || - c.isInsidePlot(l, Math.round(m), k) || - (e && c.isInsidePlot(l, k ? e.x + 1 : e.y + e.height - 1, k))), - z = 'justify' === u(d.overflow, 'justify'); - if ( - w && - ((p = d.style.fontSize), - (p = c.renderer.fontMetrics(p, b).b), - (e = f( - { - x: k ? this.yAxis.len - m : l, - y: Math.round(k ? this.xAxis.len - l : m), - width: 0, - height: 0, - }, - e, - )), - f(d, { width: n.width, height: n.height }), - q - ? ((z = !1), - (l = c.renderer.rotCorr(p, q)), - (l = { - x: e.x + d.x + e.width / 2 + l.x, - y: - e.y + - d.y + - { top: 0, middle: 0.5, bottom: 1 }[d.verticalAlign] * e.height, - }), - b[h ? 'attr' : 'animate'](l).attr({ align: r }), - (m = (q + 720) % 360), - (m = 180 < m && 360 > m), - 'left' === r - ? (l.y -= m ? n.height : 0) - : 'center' === r - ? ((l.x -= n.width / 2), (l.y -= n.height / 2)) - : 'right' === r && ((l.x -= n.width), (l.y -= m ? 0 : n.height))) - : (b.align(d, null, e), (l = b.alignAttr)), - z - ? (a.isLabelJustified = this.justifyDataLabel(b, d, l, n, e, h)) - : u(d.crop, !0) && - (w = - c.isInsidePlot(l.x, l.y) && - c.isInsidePlot(l.x + n.width, l.y + n.height)), - d.shape && !q) - ) - b[h ? 'attr' : 'animate']({ - anchorX: k ? c.plotWidth - a.plotY : a.plotX, - anchorY: k ? c.plotHeight - a.plotX : a.plotY, - }); - w || (b.attr({ y: -9999 }), (b.placed = !1)); - }; - h.prototype.justifyDataLabel = function(a, b, d, e, f, h) { - var c = this.chart, - k = b.align, - l = b.verticalAlign, - m, - n, - p = a.box ? 0 : a.padding || 0; - m = d.x + p; - 0 > m && ('right' === k ? (b.align = 'left') : (b.x = -m), (n = !0)); - m = d.x + e.width - p; - m > c.plotWidth && - ('left' === k ? (b.align = 'right') : (b.x = c.plotWidth - m), - (n = !0)); - m = d.y + p; - 0 > m && - ('bottom' === l ? (b.verticalAlign = 'top') : (b.y = -m), (n = !0)); - m = d.y + e.height - p; - m > c.plotHeight && - ('top' === l ? (b.verticalAlign = 'bottom') : (b.y = c.plotHeight - m), - (n = !0)); - n && ((a.placed = !h), a.align(b, null, f)); - return n; - }; - m.pie && - ((m.pie.prototype.drawDataLabels = function() { - var c = this, - b = c.data, - d, - e = c.chart, - f = c.options.dataLabels, - l = u(f.connectorPadding, 10), - m = u(f.connectorWidth, 1), - n = e.plotWidth, - t = e.plotHeight, - r, - w = c.center, - q = w[2] / 2, - A = w[1], - F, - G, - g, - v, - E = [[], []], - L, - P, - J, - M, - y = [0, 0, 0, 0]; - c.visible && - (f.enabled || c._hasPointLabels) && - (p(b, function(a) { - a.dataLabel && - a.visible && - a.dataLabel.shortened && - (a.dataLabel - .attr({ width: 'auto' }) - .css({ width: 'auto', textOverflow: 'clip' }), - (a.dataLabel.shortened = !1)); - }), - h.prototype.drawDataLabels.apply(c), - p(b, function(a) { - a.dataLabel && - a.visible && - (E[a.half].push(a), (a.dataLabel._pos = null)); - }), - p(E, function(b, h) { - var k, - m, - x = b.length, - r = [], - z; - if (x) - for ( - c.sortByAngle(b, h - 0.5), - 0 < c.maxLabelDistance && - ((k = Math.max(0, A - q - c.maxLabelDistance)), - (m = Math.min(A + q + c.maxLabelDistance, e.plotHeight)), - p(b, function(a) { - 0 < a.labelDistance && - a.dataLabel && - ((a.top = Math.max(0, A - q - a.labelDistance)), - (a.bottom = Math.min( - A + q + a.labelDistance, - e.plotHeight, - )), - (z = a.dataLabel.getBBox().height || 21), - (a.positionsIndex = - r.push({ - target: a.labelPos[1] - a.top + z / 2, - size: z, - rank: a.y, - }) - 1)); - }), - a.distribute(r, m + z - k)), - M = 0; - M < x; - M++ - ) - (d = b[M]), - (m = d.positionsIndex), - (g = d.labelPos), - (F = d.dataLabel), - (J = !1 === d.visible ? 'hidden' : 'inherit'), - (P = k = g[1]), - r && - H(r[m]) && - (void 0 === r[m].pos - ? (J = 'hidden') - : ((v = r[m].size), (P = d.top + r[m].pos))), - delete d.positionIndex, - (L = f.justify - ? w[0] + (h ? -1 : 1) * (q + d.labelDistance) - : c.getX(P < d.top + 2 || P > d.bottom - 2 ? k : P, h, d)), - (F._attr = { visibility: J, align: g[6] }), - (F._pos = { - x: L + f.x + ({ left: l, right: -l }[g[6]] || 0), - y: P + f.y - 10, - }), - (g.x = L), - (g.y = P), - u(f.crop, !0) && - ((G = F.getBBox().width), - (k = null), - L - G < l - ? ((k = Math.round(G - L + l)), - (y[3] = Math.max(k, y[3]))) - : L + G > n - l && - ((k = Math.round(L + G - n + l)), - (y[1] = Math.max(k, y[1]))), - 0 > P - v / 2 - ? (y[0] = Math.max(Math.round(-P + v / 2), y[0])) - : P + v / 2 > t && - (y[2] = Math.max(Math.round(P + v / 2 - t), y[2])), - (F.sideOverflow = k)); - }), - 0 === D(y) || this.verifyDataLabelOverflow(y)) && - (this.placeDataLabels(), - m && - p(this.points, function(a) { - var b; - r = a.connector; - if ( - (F = a.dataLabel) && - F._pos && - a.visible && - 0 < a.labelDistance - ) { - J = F._attr.visibility; - if ((b = !r)) - (a.connector = r = e.renderer - .path() - .addClass( - 'highcharts-data-label-connector highcharts-color-' + - a.colorIndex, - ) - .add(c.dataLabelsGroup)), - r.attr({ - 'stroke-width': m, - stroke: f.connectorColor || a.color || '#666666', - }); - r[b ? 'attr' : 'animate']({ d: c.connectorPath(a.labelPos) }); - r.attr('visibility', J); - } else r && (a.connector = r.destroy()); - })); - }), - (m.pie.prototype.connectorPath = function(a) { - var b = a.x, - c = a.y; - return u(this.options.dataLabels.softConnector, !0) - ? [ - 'M', - b + ('left' === a[6] ? 5 : -5), - c, - 'C', - b, - c, - 2 * a[2] - a[4], - 2 * a[3] - a[5], - a[2], - a[3], - 'L', - a[4], - a[5], - ] - : [ - 'M', - b + ('left' === a[6] ? 5 : -5), - c, - 'L', - a[2], - a[3], - 'L', - a[4], - a[5], - ]; - }), - (m.pie.prototype.placeDataLabels = function() { - p( - this.points, - function(a) { - var b = a.dataLabel; - b && - a.visible && - ((a = b._pos) - ? (b.sideOverflow && - ((b._attr.width = b.getBBox().width - b.sideOverflow), - b.css({ - width: b._attr.width + 'px', - textOverflow: 'ellipsis', - }), - (b.shortened = !0)), - b.attr(b._attr), - b[b.moved ? 'animate' : 'attr'](a), - (b.moved = !0)) - : b && b.attr({ y: -9999 })); - }, - this, - ); - }), - (m.pie.prototype.alignDataLabel = w), - (m.pie.prototype.verifyDataLabelOverflow = function(a) { - var b = this.center, - c = this.options, - d = c.center, - f = c.minSize || 80, - h, - l = null !== c.size; - l || - (null !== d[0] - ? (h = Math.max(b[2] - Math.max(a[1], a[3]), f)) - : ((h = Math.max(b[2] - a[1] - a[3], f)), - (b[0] += (a[3] - a[1]) / 2)), - null !== d[1] - ? (h = Math.max(Math.min(h, b[2] - Math.max(a[0], a[2])), f)) - : ((h = Math.max(Math.min(h, b[2] - a[0] - a[2]), f)), - (b[1] += (a[0] - a[2]) / 2)), - h < b[2] - ? ((b[2] = h), - (b[3] = Math.min(e(c.innerSize || 0, h), h)), - this.translate(b), - this.drawDataLabels && this.drawDataLabels()) - : (l = !0)); - return l; - })); - m.column && - (m.column.prototype.alignDataLabel = function(a, b, d, e, f) { - var c = this.chart.inverted, - k = a.series, - l = a.dlBox || a.shapeArgs, - m = u(a.below, a.plotY > u(this.translatedThreshold, k.yAxis.len)), - p = u(d.inside, !!this.options.stacking); - l && - ((e = n(l)), - 0 > e.y && ((e.height += e.y), (e.y = 0)), - (l = e.y + e.height - k.yAxis.len), - 0 < l && (e.height -= l), - c && - (e = { - x: k.yAxis.len - e.y - e.height, - y: k.xAxis.len - e.x - e.width, - width: e.height, - height: e.width, - }), - p || - (c - ? ((e.x += m ? 0 : e.width), (e.width = 0)) - : ((e.y += m ? e.height : 0), (e.height = 0)))); - d.align = u(d.align, !c || p ? 'center' : m ? 'right' : 'left'); - d.verticalAlign = u( - d.verticalAlign, - c || p ? 'middle' : m ? 'top' : 'bottom', - ); - h.prototype.alignDataLabel.call(this, a, b, d, e, f); - a.isLabelJustified && - a.contrastColor && - a.dataLabel.css({ color: a.contrastColor }); - }); - })(M); - (function(a) { - var E = a.Chart, - D = a.each, - H = a.objectEach, - p = a.pick; - a = a.addEvent; - a(E.prototype, 'render', function() { - var a = []; - D(this.labelCollectors || [], function(f) { - a = a.concat(f()); - }); - D(this.yAxis || [], function(f) { - f.options.stackLabels && - !f.options.stackLabels.allowOverlap && - H(f.stacks, function(f) { - H(f, function(f) { - a.push(f.label); - }); - }); - }); - D(this.series || [], function(f) { - var l = f.options.dataLabels, - n = f.dataLabelCollections || ['dataLabel']; - (l.enabled || f._hasPointLabels) && - !l.allowOverlap && - f.visible && - D(n, function(l) { - D(f.points, function(f) { - f[l] && - ((f[l].labelrank = p( - f.labelrank, - f.shapeArgs && f.shapeArgs.height, - )), - a.push(f[l])); - }); - }); - }); - this.hideOverlappingLabels(a); - }); - E.prototype.hideOverlappingLabels = function(a) { - var f = a.length, - p, - n, - w, - u, - e, - h, - m, - d, - c, - b = function(a, b, c, d, e, f, h, l) { - return !(e > a + c || e + h < a || f > b + d || f + l < b); - }; - for (n = 0; n < f; n++) - if ((p = a[n])) - (p.oldOpacity = p.opacity), - (p.newOpacity = 1), - p.width || - ((w = p.getBBox()), (p.width = w.width), (p.height = w.height)); - a.sort(function(a, b) { - return (b.labelrank || 0) - (a.labelrank || 0); - }); - for (n = 0; n < f; n++) - for (w = a[n], p = n + 1; p < f; ++p) - if ( - ((u = a[p]), - w && - u && - w !== u && - w.placed && - u.placed && - 0 !== w.newOpacity && - 0 !== u.newOpacity && - ((e = w.alignAttr), - (h = u.alignAttr), - (m = w.parentGroup), - (d = u.parentGroup), - (c = 2 * (w.box ? 0 : w.padding || 0)), - (e = b( - e.x + m.translateX, - e.y + m.translateY, - w.width - c, - w.height - c, - h.x + d.translateX, - h.y + d.translateY, - u.width - c, - u.height - c, - )))) - ) - (w.labelrank < u.labelrank ? w : u).newOpacity = 0; - D(a, function(a) { - var b, c; - a && - ((c = a.newOpacity), - a.oldOpacity !== c && - a.placed && - (c - ? a.show(!0) - : (b = function() { - a.hide(); - }), - (a.alignAttr.opacity = c), - a[a.isOld ? 'animate' : 'attr'](a.alignAttr, null, b)), - (a.isOld = !0)); - }); - }; - })(M); - (function(a) { - var E = a.addEvent, - D = a.Chart, - H = a.createElement, - p = a.css, - f = a.defaultOptions, - l = a.defaultPlotOptions, - r = a.each, - n = a.extend, - w = a.fireEvent, - u = a.hasTouch, - e = a.inArray, - h = a.isObject, - m = a.Legend, - d = a.merge, - c = a.pick, - b = a.Point, - k = a.Series, - z = a.seriesTypes, - B = a.svg, - I; - I = a.TrackerMixin = { - drawTrackerPoint: function() { - var a = this, - b = a.chart.pointer, - c = function(a) { - var c = b.getPointFromEvent(a); - void 0 !== c && ((b.isDirectTouch = !0), c.onMouseOver(a)); - }; - r(a.points, function(a) { - a.graphic && (a.graphic.element.point = a); - a.dataLabel && - (a.dataLabel.div - ? (a.dataLabel.div.point = a) - : (a.dataLabel.element.point = a)); - }); - a._hasTracking || - (r(a.trackerGroups, function(d) { - if (a[d]) { - a[d] - .addClass('highcharts-tracker') - .on('mouseover', c) - .on('mouseout', function(a) { - b.onTrackerMouseOut(a); - }); - if (u) a[d].on('touchstart', c); - a.options.cursor && a[d].css(p).css({ cursor: a.options.cursor }); - } - }), - (a._hasTracking = !0)); - }, - drawTrackerGraph: function() { - var a = this, - b = a.options, - c = b.trackByArea, - d = [].concat(c ? a.areaPath : a.graphPath), - e = d.length, - f = a.chart, - h = f.pointer, - k = f.renderer, - l = f.options.tooltip.snap, - g = a.tracker, - m, - n = function() { - if (f.hoverSeries !== a) a.onMouseOver(); - }, - p = 'rgba(192,192,192,' + (B ? 0.0001 : 0.002) + ')'; - if (e && !c) - for (m = e + 1; m--; ) - 'M' === d[m] && d.splice(m + 1, 0, d[m + 1] - l, d[m + 2], 'L'), - ((m && 'M' === d[m]) || m === e) && - d.splice(m, 0, 'L', d[m - 2] + l, d[m - 1]); - g - ? g.attr({ d: d }) - : a.graph && - ((a.tracker = k - .path(d) - .attr({ - 'stroke-linejoin': 'round', - visibility: a.visible ? 'visible' : 'hidden', - stroke: p, - fill: c ? p : 'none', - 'stroke-width': a.graph.strokeWidth() + (c ? 0 : 2 * l), - zIndex: 2, - }) - .add(a.group)), - r([a.tracker, a.markerGroup], function(a) { - a.addClass('highcharts-tracker') - .on('mouseover', n) - .on('mouseout', function(a) { - h.onTrackerMouseOut(a); - }); - b.cursor && a.css({ cursor: b.cursor }); - if (u) a.on('touchstart', n); - })); - }, - }; - z.column && (z.column.prototype.drawTracker = I.drawTrackerPoint); - z.pie && (z.pie.prototype.drawTracker = I.drawTrackerPoint); - z.scatter && (z.scatter.prototype.drawTracker = I.drawTrackerPoint); - n(m.prototype, { - setItemEvents: function(a, c, e) { - var f = this, - h = f.chart.renderer.boxWrapper, - k = - 'highcharts-legend-' + - (a instanceof b ? 'point' : 'series') + - '-active'; - (e ? c : a.legendGroup) - .on('mouseover', function() { - a.setState('hover'); - h.addClass(k); - c.css(f.options.itemHoverStyle); - }) - .on('mouseout', function() { - c.css(d(a.visible ? f.itemStyle : f.itemHiddenStyle)); - h.removeClass(k); - a.setState(); - }) - .on('click', function(b) { - var c = function() { - a.setVisible && a.setVisible(); - }; - h.removeClass(k); - b = { browserEvent: b }; - a.firePointEvent - ? a.firePointEvent('legendItemClick', b, c) - : w(a, 'legendItemClick', b, c); - }); - }, - createCheckboxForItem: function(a) { - a.checkbox = H( - 'input', - { type: 'checkbox', checked: a.selected, defaultChecked: a.selected }, - this.options.itemCheckboxStyle, - this.chart.container, - ); - E(a.checkbox, 'click', function(b) { - w( - a.series || a, - 'checkboxClick', - { checked: b.target.checked, item: a }, - function() { - a.select(); - }, - ); - }); - }, - }); - f.legend.itemStyle.cursor = 'pointer'; - n(D.prototype, { - showResetZoom: function() { - var a = this, - b = f.lang, - c = a.options.chart.resetZoomButton, - d = c.theme, - e = d.states, - h = 'chart' === c.relativeTo ? null : 'plotBox'; - this.resetZoomButton = a.renderer - .button( - b.resetZoom, - null, - null, - function() { - a.zoomOut(); - }, - d, - e && e.hover, - ) - .attr({ align: c.position.align, title: b.resetZoomTitle }) - .addClass('highcharts-reset-zoom') - .add() - .align(c.position, !1, h); - }, - zoomOut: function() { - var a = this; - w(a, 'selection', { resetSelection: !0 }, function() { - a.zoom(); - }); - }, - zoom: function(a) { - var b, - d = this.pointer, - e = !1, - f; - !a || a.resetSelection - ? (r(this.axes, function(a) { - b = a.zoom(); - }), - (d.initiated = !1)) - : r(a.xAxis.concat(a.yAxis), function(a) { - var c = a.axis; - d[c.isXAxis ? 'zoomX' : 'zoomY'] && - ((b = c.zoom(a.min, a.max)), c.displayBtn && (e = !0)); - }); - f = this.resetZoomButton; - e && !f - ? this.showResetZoom() - : !e && h(f) && (this.resetZoomButton = f.destroy()); - b && - this.redraw( - c( - this.options.chart.animation, - a && a.animation, - 100 > this.pointCount, - ), - ); - }, - pan: function(a, b) { - var c = this, - d = c.hoverPoints, - e; - d && - r(d, function(a) { - a.setState(); - }); - r('xy' === b ? [1, 0] : [1], function(b) { - b = c[b ? 'xAxis' : 'yAxis'][0]; - var d = b.horiz, - f = a[d ? 'chartX' : 'chartY'], - d = d ? 'mouseDownX' : 'mouseDownY', - h = c[d], - g = (b.pointRange || 0) / 2, - k = b.getExtremes(), - l = b.toValue(h - f, !0) + g, - m = b.toValue(h + b.len - f, !0) - g, - n = m < l, - h = n ? m : l, - l = n ? l : m, - m = Math.min( - k.dataMin, - g ? k.min : b.toValue(b.toPixels(k.min) - b.minPixelPadding), - ), - g = Math.max( - k.dataMax, - g ? k.max : b.toValue(b.toPixels(k.max) + b.minPixelPadding), - ), - n = m - h; - 0 < n && ((l += n), (h = m)); - n = l - g; - 0 < n && ((l = g), (h -= n)); - b.series.length && - h !== k.min && - l !== k.max && - (b.setExtremes(h, l, !1, !1, { trigger: 'pan' }), (e = !0)); - c[d] = f; - }); - e && c.redraw(!1); - p(c.container, { cursor: 'move' }); - }, - }); - n(b.prototype, { - select: function(a, b) { - var d = this, - f = d.series, - h = f.chart; - a = c(a, !d.selected); - d.firePointEvent( - a ? 'select' : 'unselect', - { accumulate: b }, - function() { - d.selected = d.options.selected = a; - f.options.data[e(d, f.data)] = d.options; - d.setState(a && 'select'); - b || - r(h.getSelectedPoints(), function(a) { - a.selected && - a !== d && - ((a.selected = a.options.selected = !1), - (f.options.data[e(a, f.data)] = a.options), - a.setState(''), - a.firePointEvent('unselect')); - }); - }, - ); - }, - onMouseOver: function(a) { - var b = this.series.chart, - c = b.pointer; - a = a - ? c.normalize(a) - : c.getChartCoordinatesFromPoint(this, b.inverted); - c.runPointActions(a, this); - }, - onMouseOut: function() { - var a = this.series.chart; - this.firePointEvent('mouseOut'); - r(a.hoverPoints || [], function(a) { - a.setState(); - }); - a.hoverPoints = a.hoverPoint = null; - }, - importEvents: function() { - if (!this.hasImportedEvents) { - var b = this, - c = d(b.series.options.point, b.options).events; - b.events = c; - a.objectEach(c, function(a, c) { - E(b, c, a); - }); - this.hasImportedEvents = !0; - } - }, - setState: function(a, b) { - var d = Math.floor(this.plotX), - e = this.plotY, - f = this.series, - h = f.options.states[a] || {}, - k = l[f.type].marker && f.options.marker, - m = k && !1 === k.enabled, - p = (k && k.states && k.states[a]) || {}, - g = !1 === p.enabled, - r = f.stateMarkerGraphic, - u = this.marker || {}, - w = f.chart, - x = f.halo, - z, - B = k && f.markerAttribs; - a = a || ''; - if ( - !( - (a === this.state && !b) || - (this.selected && 'select' !== a) || - !1 === h.enabled || - (a && (g || (m && !1 === p.enabled))) || - (a && u.states && u.states[a] && !1 === u.states[a].enabled) - ) - ) { - B && (z = f.markerAttribs(this, a)); - if (this.graphic) - this.state && - this.graphic.removeClass('highcharts-point-' + this.state), - a && this.graphic.addClass('highcharts-point-' + a), - this.graphic.animate( - f.pointAttribs(this, a), - c(w.options.chart.animation, h.animation), - ), - z && - this.graphic.animate( - z, - c(w.options.chart.animation, p.animation, k.animation), - ), - r && r.hide(); - else { - if (a && p) { - k = u.symbol || f.symbol; - r && r.currentSymbol !== k && (r = r.destroy()); - if (r) r[b ? 'animate' : 'attr']({ x: z.x, y: z.y }); - else - k && - ((f.stateMarkerGraphic = r = w.renderer - .symbol(k, z.x, z.y, z.width, z.height) - .add(f.markerGroup)), - (r.currentSymbol = k)); - r && r.attr(f.pointAttribs(this, a)); - } - r && - (r[a && w.isInsidePlot(d, e, w.inverted) ? 'show' : 'hide'](), - (r.element.point = this)); - } - (d = h.halo) && d.size - ? (x || - (f.halo = x = w.renderer - .path() - .add((this.graphic || r).parentGroup)), - x[b ? 'animate' : 'attr']({ d: this.haloPath(d.size) }), - x.attr({ - class: - 'highcharts-halo highcharts-color-' + - c(this.colorIndex, f.colorIndex), - }), - (x.point = this), - x.attr( - n( - { - fill: this.color || f.color, - 'fill-opacity': d.opacity, - zIndex: -1, - }, - d.attributes, - ), - )) - : x && - x.point && - x.point.haloPath && - x.animate({ d: x.point.haloPath(0) }); - this.state = a; - } - }, - haloPath: function(a) { - return this.series.chart.renderer.symbols.circle( - Math.floor(this.plotX) - a, - this.plotY - a, - 2 * a, - 2 * a, - ); - }, - }); - n(k.prototype, { - onMouseOver: function() { - var a = this.chart, - b = a.hoverSeries; - if (b && b !== this) b.onMouseOut(); - this.options.events.mouseOver && w(this, 'mouseOver'); - this.setState('hover'); - a.hoverSeries = this; - }, - onMouseOut: function() { - var a = this.options, - b = this.chart, - c = b.tooltip, - d = b.hoverPoint; - b.hoverSeries = null; - if (d) d.onMouseOut(); - this && a.events.mouseOut && w(this, 'mouseOut'); - !c || - this.stickyTracking || - (c.shared && !this.noSharedTooltip) || - c.hide(); - this.setState(); - }, - setState: function(a) { - var b = this, - d = b.options, - e = b.graph, - f = d.states, - h = d.lineWidth, - d = 0; - a = a || ''; - if ( - b.state !== a && - (r([b.group, b.markerGroup, b.dataLabelsGroup], function(c) { - c && - (b.state && c.removeClass('highcharts-series-' + b.state), - a && c.addClass('highcharts-series-' + a)); - }), - (b.state = a), - !f[a] || !1 !== f[a].enabled) && - (a && (h = f[a].lineWidth || h + (f[a].lineWidthPlus || 0)), - e && !e.dashstyle) - ) - for ( - h = { 'stroke-width': h }, - e.animate( - h, - c(b.chart.options.chart.animation, f[a] && f[a].animation), - ); - b['zone-graph-' + d]; - - ) - b['zone-graph-' + d].attr(h), (d += 1); - }, - setVisible: function(a, b) { - var c = this, - d = c.chart, - e = c.legendItem, - f, - h = d.options.chart.ignoreHiddenSeries, - k = c.visible; - f = (c.visible = a = c.options.visible = c.userOptions.visible = - void 0 === a ? !k : a) - ? 'show' - : 'hide'; - r( - ['group', 'dataLabelsGroup', 'markerGroup', 'tracker', 'tt'], - function(a) { - if (c[a]) c[a][f](); - }, - ); - if (d.hoverSeries === c || (d.hoverPoint && d.hoverPoint.series) === c) - c.onMouseOut(); - e && d.legend.colorizeItem(c, a); - c.isDirty = !0; - c.options.stacking && - r(d.series, function(a) { - a.options.stacking && a.visible && (a.isDirty = !0); - }); - r(c.linkedSeries, function(b) { - b.setVisible(a, !1); - }); - h && (d.isDirtyBox = !0); - !1 !== b && d.redraw(); - w(c, f); - }, - show: function() { - this.setVisible(!0); - }, - hide: function() { - this.setVisible(!1); - }, - select: function(a) { - this.selected = a = void 0 === a ? !this.selected : a; - this.checkbox && (this.checkbox.checked = a); - w(this, a ? 'select' : 'unselect'); - }, - drawTracker: I.drawTrackerGraph, - }); - })(M); - (function(a) { - var E = a.Chart, - D = a.each, - H = a.inArray, - p = a.isArray, - f = a.isObject, - l = a.pick, - r = a.splat; - E.prototype.setResponsive = function(f) { - var l = this.options.responsive, - n = [], - e = this.currentResponsive; - l && - l.rules && - D( - l.rules, - function(e) { - void 0 === e._id && (e._id = a.uniqueKey()); - this.matchResponsiveRule(e, n, f); - }, - this, - ); - var h = a.merge.apply( - 0, - a.map(n, function(e) { - return a.find(l.rules, function(a) { - return a._id === e; - }).chartOptions; - }), - ), - n = n.toString() || void 0; - n !== (e && e.ruleIds) && - (e && this.update(e.undoOptions, f), - n - ? ((this.currentResponsive = { - ruleIds: n, - mergedOptions: h, - undoOptions: this.currentOptions(h), - }), - this.update(h, f)) - : (this.currentResponsive = void 0)); - }; - E.prototype.matchResponsiveRule = function(a, f) { - var n = a.condition; - ( - n.callback || - function() { - return ( - this.chartWidth <= l(n.maxWidth, Number.MAX_VALUE) && - this.chartHeight <= l(n.maxHeight, Number.MAX_VALUE) && - this.chartWidth >= l(n.minWidth, 0) && - this.chartHeight >= l(n.minHeight, 0) - ); - } - ).call(this) && f.push(a._id); - }; - E.prototype.currentOptions = function(l) { - function n(e, h, l, d) { - var c; - a.objectEach(e, function(a, e) { - if (!d && -1 < H(e, ['series', 'xAxis', 'yAxis'])) - for (a = r(a), l[e] = [], c = 0; c < a.length; c++) - h[e][c] && ((l[e][c] = {}), n(a[c], h[e][c], l[e][c], d + 1)); - else - f(a) - ? ((l[e] = p(a) ? [] : {}), n(a, h[e] || {}, l[e], d + 1)) - : (l[e] = h[e] || null); - }); - } - var u = {}; - n(l, this.options, u, 0); - return u; - }; - })(M); - return M; -}); +(function(S,M){"object"===typeof module&&module.exports?module.exports=S.document?M(S):M:S.Highcharts=M(S)})("undefined"!==typeof window?window:this,function(S){var M=function(){var a="undefined"===typeof S?window:S,E=a.document,D=a.navigator&&a.navigator.userAgent||"",H=E&&E.createElementNS&&!!E.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect,p=/(edge|msie|trident)/i.test(D)&&!a.opera,f=/Firefox/.test(D),l=f&&4>parseInt(D.split("Firefox/")[1],10);return a.Highcharts?a.Highcharts.error(16, +!0):{product:"Highcharts",version:"6.0.4",deg2rad:2*Math.PI/360,doc:E,hasBidiBug:l,hasTouch:E&&void 0!==E.documentElement.ontouchstart,isMS:p,isWebKit:/AppleWebKit/.test(D),isFirefox:f,isTouchDevice:/(Mobile|Android|Windows Phone)/.test(D),SVG_NS:"http://www.w3.org/2000/svg",chartCount:0,seriesTypes:{},symbolSizes:{},svg:H,win:a,marginNames:["plotTop","marginRight","marginBottom","plotLeft"],noop:function(){},charts:[]}}();(function(a){a.timers=[];var E=a.charts,D=a.doc,H=a.win;a.error=function(p, +f){p=a.isNumber(p)?"Highcharts error #"+p+": www.highcharts.com/errors/"+p:p;if(f)throw Error(p);H.console&&console.log(p)};a.Fx=function(a,f,l){this.options=f;this.elem=a;this.prop=l};a.Fx.prototype={dSetter:function(){var a=this.paths[0],f=this.paths[1],l=[],r=this.now,n=a.length,w;if(1===r)l=this.toD;else if(n===f.length&&1>r)for(;n--;)w=parseFloat(a[n]),l[n]=isNaN(w)?f[n]:r*parseFloat(f[n]-w)+w;else l=f;this.elem.attr("d",l,null,!0)},update:function(){var a=this.elem,f=this.prop,l=this.now,r= +this.options.step;if(this[f+"Setter"])this[f+"Setter"]();else a.attr?a.element&&a.attr(f,l,null,!0):a.style[f]=l+this.unit;r&&r.call(a,l,this)},run:function(p,f,l){var r=this,n=r.options,w=function(a){return w.stopped?!1:r.step(a)},u=H.requestAnimationFrame||function(a){setTimeout(a,13)},e=function(){for(var h=0;h=u+this.startTime?(this.now=this.end,this.pos=1,this.update(),l=e[this.prop]=!0,a.objectEach(e,function(a){!0!==a&&(l=!1)}),l&&w&&w.call(n),p=!1):(this.pos=r.easing((f-this.startTime)/u),this.now=this.start+(this.end- +this.start)*this.pos,this.update(),p=!0);return p},initPath:function(p,f,l){function r(a){var b,c;for(k=a.length;k--;)b="M"===a[k]||"L"===a[k],c=/[a-zA-Z]/.test(a[k+3]),b&&c&&a.splice(k+1,0,a[k+1],a[k+2],a[k+1],a[k+2])}function n(a,b){for(;a.lengtha&&-Infinityw?"AM":"PM",P:12>w?"am":"pm",S:k(n.getSeconds()),L:k(Math.round(f%1E3),3)},a.dateFormats);a.objectEach(r,function(a,b){for(;-1!==p.indexOf("%"+b);)p=p.replace("%"+b,"function"===typeof a?a(f):a)});return l?p.substr(0,1).toUpperCase()+p.substr(1):p};a.formatSingle=function(p,f){var l=/\.([0-9])/,r=a.defaultOptions.lang;/f$/.test(p)?(l=(l=p.match(l))?l[1]:-1,null!==f&&(f=a.numberFormat(f,l,r.decimalPoint,-1=l&&(f=[1/l])));for(r=0;r=p||!n&&w<=(f[r]+(f[r+1]||f[r]))/2);r++);return u=a.correctFloat(u*l,-Math.round(Math.log(.001)/Math.LN10))};a.stableSort=function(a,f){var l=a.length,p,n;for(n=0;nl&&(l=a[f]);return l};a.destroyObjectProperties=function(p,f){a.objectEach(p,function(a,r){a&&a!==f&&a.destroy&&a.destroy();delete p[r]})};a.discardElement=function(p){var f=a.garbageBin;f||(f=a.createElement("div"));p&&f.appendChild(p);f.innerHTML=""};a.correctFloat=function(a,f){return parseFloat(a.toPrecision(f||14))};a.setAnimation=function(p,f){f.renderer.globalAnimation=a.pick(p,f.options.chart.animation, +!0)};a.animObject=function(p){return a.isObject(p)?a.merge(p):{duration:p?500:0}};a.timeUnits={millisecond:1,second:1E3,minute:6E4,hour:36E5,day:864E5,week:6048E5,month:24192E5,year:314496E5};a.numberFormat=function(p,f,l,r){p=+p||0;f=+f;var n=a.defaultOptions.lang,w=(p.toString().split(".")[1]||"").split("e")[0].length,u,e,h=p.toString().split("e");-1===f?f=Math.min(w,20):a.isNumber(f)?f&&h[1]&&0>h[1]&&(u=f+ +h[1],0<=u?(h[0]=(+h[0]).toExponential(u).split("e")[0],f=u):(h[0]=h[0].split(".")[0]||0, +p=20>f?(h[0]*Math.pow(10,h[1])).toFixed(f):0,h[1]=0)):f=2;e=(Math.abs(h[1]?h[0]:p)+Math.pow(10,-Math.max(f,w)-1)).toFixed(f);w=String(a.pInt(e));u=3p?"-":"")+(u?w.substr(0,u)+r:"");p+=w.substr(u).replace(/(\d{3})(?=\d)/g,"$1"+r);f&&(p+=l+e.slice(-f));h[1]&&0!==+p&&(p+="e"+h[1]);return p};Math.easeInOutSine=function(a){return-.5*(Math.cos(Math.PI*a)-1)};a.getStyle=function(p,f,l){if("width"===f)return Math.min(p.offsetWidth, +p.scrollWidth)-a.getStyle(p,"padding-left")-a.getStyle(p,"padding-right");if("height"===f)return Math.min(p.offsetHeight,p.scrollHeight)-a.getStyle(p,"padding-top")-a.getStyle(p,"padding-bottom");H.getComputedStyle||a.error(27,!0);if(p=H.getComputedStyle(p,void 0))p=p.getPropertyValue(f),a.pick(l,"opacity"!==f)&&(p=a.pInt(p));return p};a.inArray=function(p,f){return(a.indexOfPolyfill||Array.prototype.indexOf).call(f,p)};a.grep=function(p,f){return(a.filterPolyfill||Array.prototype.filter).call(p, +f)};a.find=Array.prototype.find?function(a,f){return a.find(f)}:function(a,f){var l,r=a.length;for(l=0;l>16,(l&65280)>> +8,l&255,1]:4===f&&(n=[(l&3840)>>4|(l&3840)>>8,(l&240)>>4|l&240,(l&15)<<4|l&15,1])),!n)for(w=this.parsers.length;w--&&!n;)u=this.parsers[w],(f=u.regex.exec(l))&&(n=u.parse(f));this.rgba=n||[]},get:function(a){var f=this.input,n=this.rgba,l;this.stops?(l=p(f),l.stops=[].concat(l.stops),E(this.stops,function(n,e){l.stops[e]=[l.stops[e][0],n.get(a)]})):l=n&&D(n[0])?"rgb"===a||!a&&1===n[3]?"rgb("+n[0]+","+n[1]+","+n[2]+")":"a"===a?n[3]:"rgba("+n.join(",")+")":f;return l},brighten:function(a){var l,n=this.rgba; +if(this.stops)E(this.stops,function(n){n.brighten(a)});else if(D(a)&&0!==a)for(l=0;3>l;l++)n[l]+=f(255*a),0>n[l]&&(n[l]=0),255y.width)y={width:0,height:0}}else y=this.htmlGetBBox();b.isSVG&& +(a=y.width,b=y.height,q&&"11px"===q.fontSize&&17===Math.round(b)&&(y.height=b=14),g&&(y.width=Math.abs(b*Math.sin(v))+Math.abs(a*Math.cos(v)),y.height=Math.abs(b*Math.cos(v))+Math.abs(a*Math.sin(v))));if(A&&0]*>/g,"")))},textSetter:function(a){a!==this.textStr&&(delete this.bBox,this.textStr=a,this.added&&this.renderer.buildText(this))},fillSetter:function(a,g,b){"string"===typeof a?b.setAttribute(g,a):a&&this.colorGradient(a,g,b)},visibilitySetter:function(a,g,b){"inherit"===a?b.removeAttribute(g):this[g]!==a&&b.setAttribute(g,a);this[g]=a},zIndexSetter:function(a,b){var v=this.renderer,y=this.parentGroup,c=(y||v).element||v.box,k,d=this.element,q,e,v=c===v.box;k=this.added;var z;u(a)&& +(d.zIndex=a,a=+a,this[b]===a&&(k=!1),this[b]=a);if(k){(a=this.zIndex)&&y&&(y.handleZ=!0);b=c.childNodes;for(z=b.length-1;0<=z&&!q;z--)if(y=b[z],k=y.zIndex,e=!u(k),y!==d)if(0>a&&e&&!v&&!z)c.insertBefore(d,b[z]),q=!0;else if(g(k)<=a||e&&(!u(a)||0<=a))c.insertBefore(d,b[z+1]||null),q=!0;q||(c.insertBefore(d,b[v?3:0]||null),q=!0)}return q},_defaultSetter:function(a,g,b){b.setAttribute(g,a)}});E.prototype.yGetter=E.prototype.xGetter;E.prototype.translateXSetter=E.prototype.translateYSetter=E.prototype.rotationSetter= +E.prototype.verticalAlignSetter=E.prototype.rotationOriginXSetter=E.prototype.rotationOriginYSetter=E.prototype.scaleXSetter=E.prototype.scaleYSetter=E.prototype.matrixSetter=function(a,g){this[g]=a;this.doTransform=!0};E.prototype["stroke-widthSetter"]=E.prototype.strokeSetter=function(a,g,b){this[g]=a;this.stroke&&this["stroke-width"]?(E.prototype.fillSetter.call(this,this.stroke,"stroke",b),b.setAttribute("stroke-width",this["stroke-width"]),this.hasStroke=!0):"stroke-width"===g&&0===a&&this.hasStroke&& +(b.removeAttribute("stroke"),this.hasStroke=!1)};D=a.SVGRenderer=function(){this.init.apply(this,arguments)};c(D.prototype,{Element:E,SVG_NS:P,init:function(a,g,b,v,c,k){var y;v=this.createElement("svg").attr({version:"1.1","class":"highcharts-root"}).css(this.getStyle(v));y=v.element;a.appendChild(y);f(a,"dir","ltr");-1===a.innerHTML.indexOf("xmlns")&&f(y,"xmlns",this.SVG_NS);this.isSVG=!0;this.box=y;this.boxWrapper=v;this.alignedObjects=[];this.url=(x||N)&&m.getElementsByTagName("base").length? +R.location.href.replace(/#.*?$/,"").replace(/<[^>]*>/g,"").replace(/([\('\)])/g,"\\$1").replace(/ /g,"%20"):"";this.createElement("desc").add().element.appendChild(m.createTextNode("Created with Highcharts 6.0.4"));this.defs=this.createElement("defs").add();this.allowHTML=k;this.forExport=c;this.gradients={};this.cache={};this.cacheKeys=[];this.imgCount=0;this.setSize(g,b,!1);var d;x&&a.getBoundingClientRect&&(g=function(){n(a,{left:0,top:0});d=a.getBoundingClientRect();n(a,{left:Math.ceil(d.left)- +d.left+"px",top:Math.ceil(d.top)-d.top+"px"})},g(),this.unSubPixelFix=H(R,"resize",g))},getStyle:function(a){return this.style=c({fontFamily:'"Lucida Grande", "Lucida Sans Unicode", Arial, Helvetica, sans-serif',fontSize:"12px"},a)},setStyle:function(a){this.boxWrapper.css(this.getStyle(a))},isHidden:function(){return!this.boxWrapper.getBBox().width},destroy:function(){var a=this.defs;this.box=null;this.boxWrapper=this.boxWrapper.destroy();h(this.gradients||{});this.gradients=null;a&&(this.defs=a.destroy()); +this.unSubPixelFix&&this.unSubPixelFix();return this.alignedObjects=null},createElement:function(a){var g=new this.Element;g.init(this,a);return g},draw:A,getRadialAttr:function(a,g){return{cx:a[0]-a[2]/2+g.cx*a[2],cy:a[1]-a[2]/2+g.cy*a[2],r:g.r*a[2]}},getSpanWidth:function(a,g){var b=a.getBBox(!0).width;!L&&this.forExport&&(b=this.measureSpanWidth(g.firstChild.data,a.styles));return b},applyEllipsis:function(a,g,b,v){var c=a.rotation,y=b,k,d=0,q=b.length,e=function(a){g.removeChild(g.firstChild); +a&&g.appendChild(m.createTextNode(a))},z;a.rotation=0;y=this.getSpanWidth(a,g);if(z=y>v){for(;d<=q;)k=Math.ceil((d+q)/2),y=b.substring(0,k)+"\u2026",e(y),y=this.getSpanWidth(a,g),d===q?d=q+1:y>v?q=k-1:d=k;0===q&&e("")}a.rotation=c;return z},escapes:{"\x26":"\x26amp;","\x3c":"\x26lt;","\x3e":"\x26gt;","'":"\x26#39;",'"':"\x26quot;"},buildText:function(a){var b=a.element,v=this,c=v.forExport,y=G(a.textStr,"").toString(),q=-1!==y.indexOf("\x3c"),e=b.childNodes,z,h,A,J,t=f(b,"x"),x=a.styles,B=a.textWidth, +l=x&&x.lineHeight,C=x&&x.textOutline,u=x&&"ellipsis"===x.textOverflow,Q=x&&"nowrap"===x.whiteSpace,w=x&&x.fontSize,R,I,r=e.length,x=B&&!a.added&&this.box,p=function(a){var c;c=/(px|em)$/.test(a&&a.style.fontSize)?a.style.fontSize:w||v.style.fontSize||12;return l?g(l):v.fontMetrics(c,a.getAttribute("style")?a:b).h},K=function(a){F(v.escapes,function(g,b){a=a.replace(new RegExp(g,"g"),b)});return a};R=[y,u,Q,l,C,w,B].join();if(R!==a.textCache){for(a.textCache=R;r--;)b.removeChild(e[r]);q||C||u||B|| +-1!==y.indexOf(" ")?(z=/<.*class="([^"]+)".*>/,h=/<.*style="([^"]+)".*>/,A=/<.*href="([^"]+)".*>/,x&&x.appendChild(b),y=q?y.replace(/<(b|strong)>/g,'\x3cspan style\x3d"font-weight:bold"\x3e').replace(/<(i|em)>/g,'\x3cspan style\x3d"font-style:italic"\x3e').replace(//g,"\x3c/span\x3e").split(//g):[y],y=k(y,function(a){return""!==a}),d(y,function(g,y){var k,q=0;g=g.replace(/^\s+|\s+$/g,"").replace(//g,"\x3c/span\x3e|||"); +k=g.split("|||");d(k,function(g){if(""!==g||1===k.length){var d={},e=m.createElementNS(v.SVG_NS,"tspan"),x,F;z.test(g)&&(x=g.match(z)[1],f(e,"class",x));h.test(g)&&(F=g.match(h)[1].replace(/(;| |^)color([ :])/,"$1fill$2"),f(e,"style",F));A.test(g)&&!c&&(f(e,"onclick",'location.href\x3d"'+g.match(A)[1]+'"'),f(e,"class","highcharts-anchor"),n(e,{cursor:"pointer"}));g=K(g.replace(/<[a-zA-Z\/](.|\n)*?>/g,"")||" ");if(" "!==g){e.appendChild(m.createTextNode(g));q?d.dx=0:y&&null!==t&&(d.x=t);f(e,d);b.appendChild(e); +!q&&I&&(!L&&c&&n(e,{display:"block"}),f(e,"dy",p(e)));if(B){d=g.replace(/([^\^])-/g,"$1- ").split(" ");x=1B,void 0===J&&(J=g),g&&1!==d.length?(e.removeChild(e.firstChild),O.unshift(d.pop())):(d=O,O=[],d.length&&!Q&&(e=m.createElementNS(P,"tspan"),f(e,{dy:C,x:t}),F&&f(e,"style",F),b.appendChild(e)),l>B&&(B=l)),d.length&&e.appendChild(m.createTextNode(d.join(" ").replace(/- /g, +"-")));a.rotation=G}q++}}});I=I||b.childNodes.length}),J&&a.attr("title",a.textStr),x&&x.removeChild(b),C&&a.applyTextOutline&&a.applyTextOutline(C)):b.appendChild(m.createTextNode(K(y)))}},getContrast:function(a){a=r(a).rgba;return 510Math.abs(c.end-c.start-2*Math.PI));var y=Math.cos(k),z=Math.sin(k),h=Math.cos(e),e=Math.sin(e);c=.001>c.end-k-Math.PI?0:1;d=["M",a+d*y,g+q*z,"A",d,q,0,c,1,a+d*h,g+q*e];u(b)&&d.push(v?"M":"L",a+b* +h,g+b*e,"A",b,b,0,c,0,a+b*y,g+b*z);d.push(v?"":"Z");return d},callout:function(a,g,b,v,c){var d=Math.min(c&&c.r||0,b,v),k=d+6,q=c&&c.anchorX;c=c&&c.anchorY;var e;e=["M",a+d,g,"L",a+b-d,g,"C",a+b,g,a+b,g,a+b,g+d,"L",a+b,g+v-d,"C",a+b,g+v,a+b,g+v,a+b-d,g+v,"L",a+d,g+v,"C",a,g+v,a,g+v,a,g+v-d,"L",a,g+d,"C",a,g,a,g,a+d,g];q&&q>b?c>g+k&&cq?c>g+k&&cv&&q>a+k&&qc&&q>a+k&&qa?a+3:Math.round(1.2*a);return{h:b,b:Math.round(.8* +b),f:a}},rotCorr:function(a,g,b){var v=a;g&&b&&(v=Math.max(v*Math.cos(g*e),4));return{x:-a/3*Math.sin(g*e),y:v}},label:function(g,b,k,e,z,h,m,A,L){var y=this,J=y.g("button"!==L&&"label"),t=J.text=y.text("",0,0,m).attr({zIndex:1}),x,F,n=0,B=3,l=0,C,f,Q,G,w,R={},I,P,r=/^url\((.*?)\)$/.test(e),p=r,K,O,N,T;L&&J.addClass("highcharts-"+L);p=r;K=function(){return(I||0)%2/2};O=function(){var a=t.element.style,g={};F=(void 0===C||void 0===f||w)&&u(t.textStr)&&t.getBBox();J.width=(C||F.width||0)+2*B+l;J.height= +(f||F.height||0)+2*B;P=B+y.fontMetrics(a&&a.fontSize,t).b;p&&(x||(J.box=x=y.symbols[e]||r?y.symbol(e):y.rect(),x.addClass(("button"===L?"":"highcharts-label-box")+(L?" highcharts-"+L+"-box":"")),x.add(J),a=K(),g.x=a,g.y=(A?-P:0)+a),g.width=Math.round(J.width),g.height=Math.round(J.height),x.attr(c(g,R)),R={})};N=function(){var a=l+B,g;g=A?0:P;u(C)&&F&&("center"===w||"right"===w)&&(a+={center:.5,right:1}[w]*(C-F.width));if(a!==t.x||g!==t.y)t.attr("x",a),void 0!==g&&t.attr("y",g);t.x=a;t.y=g};T=function(a, +g){x?x.attr(a,g):R[a]=g};J.onAdd=function(){t.add(J);J.attr({text:g||0===g?g:"",x:b,y:k});x&&u(z)&&J.attr({anchorX:z,anchorY:h})};J.widthSetter=function(g){C=a.isNumber(g)?g:null};J.heightSetter=function(a){f=a};J["text-alignSetter"]=function(a){w=a};J.paddingSetter=function(a){u(a)&&a!==B&&(B=J.padding=a,N())};J.paddingLeftSetter=function(a){u(a)&&a!==l&&(l=a,N())};J.alignSetter=function(a){a={left:0,center:.5,right:1}[a];a!==n&&(n=a,F&&J.attr({x:Q}))};J.textSetter=function(a){void 0!==a&&t.textSetter(a); +O();N()};J["stroke-widthSetter"]=function(a,g){a&&(p=!0);I=this["stroke-width"]=a;T(g,a)};J.strokeSetter=J.fillSetter=J.rSetter=function(a,g){"r"!==g&&("fill"===g&&a&&(p=!0),J[g]=a);T(g,a)};J.anchorXSetter=function(a,g){z=J.anchorX=a;T(g,Math.round(a)-K()-Q)};J.anchorYSetter=function(a,g){h=J.anchorY=a;T(g,a-G)};J.xSetter=function(a){J.x=a;n&&(a-=n*((C||F.width)+2*B));Q=Math.round(a);J.attr("translateX",Q)};J.ySetter=function(a){G=J.y=Math.round(a);J.attr("translateY",G)};var U=J.css;return c(J,{css:function(a){if(a){var g= +{};a=q(a);d(J.textProps,function(b){void 0!==a[b]&&(g[b]=a[b],delete a[b])});t.css(g)}return U.call(J,a)},getBBox:function(){return{width:F.width+2*B,height:F.height+2*B,x:F.x-B,y:F.y-B}},shadow:function(a){a&&(O(),x&&x.shadow(a));return J},destroy:function(){v(J.element,"mouseenter");v(J.element,"mouseleave");t&&(t=t.destroy());x&&(x=x.destroy());E.prototype.destroy.call(J);J=y=O=N=T=null}})}});a.Renderer=D})(M);(function(a){var E=a.attr,D=a.createElement,H=a.css,p=a.defined,f=a.each,l=a.extend, +r=a.isFirefox,n=a.isMS,w=a.isWebKit,u=a.pick,e=a.pInt,h=a.SVGRenderer,m=a.win,d=a.wrap;l(a.SVGElement.prototype,{htmlCss:function(a){var b=this.element;if(b=a&&"SPAN"===b.tagName&&a.width)delete a.width,this.textWidth=b,this.updateTransform();a&&"ellipsis"===a.textOverflow&&(a.whiteSpace="nowrap",a.overflow="hidden");this.styles=l(this.styles,a);H(this.element,a);return this},htmlGetBBox:function(){var a=this.element;return{x:a.offsetLeft,y:a.offsetTop,width:a.offsetWidth,height:a.offsetHeight}}, +htmlUpdateTransform:function(){if(this.added){var a=this.renderer,b=this.element,d=this.translateX||0,z=this.translateY||0,h=this.x||0,m=this.y||0,x=this.textAlign||"left",n={left:0,center:.5,right:1}[x],t=this.styles;H(b,{marginLeft:d,marginTop:z});this.shadows&&f(this.shadows,function(a){H(a,{marginLeft:d+1,marginTop:z+1})});this.inverted&&f(b.childNodes,function(c){a.invertChild(c,b)});if("SPAN"===b.tagName){var l=this.rotation,u=e(this.textWidth),q=t&&t.whiteSpace,A=[l,x,b.innerHTML,this.textWidth, +this.textAlign].join();A!==this.cTT&&(t=a.fontMetrics(b.style.fontSize).b,p(l)&&this.setSpanRotation(l,n,t),H(b,{width:"",whiteSpace:q||"nowrap"}),b.offsetWidth>u&&/[ \-]/.test(b.textContent||b.innerText)&&H(b,{width:u+"px",display:"block",whiteSpace:q||"normal"}),this.getSpanCorrection(b.offsetWidth,t,n,l,x));H(b,{left:h+(this.xCorr||0)+"px",top:m+(this.yCorr||0)+"px"});w&&(t=b.offsetHeight);this.cTT=A}}else this.alignOnAdd=!0},setSpanRotation:function(a,b,d){var c={},k=this.renderer.getTransformKey(); +c[k]=c.transform="rotate("+a+"deg)";c[k+(r?"Origin":"-origin")]=c.transformOrigin=100*b+"% "+d+"px";H(this.element,c)},getSpanCorrection:function(a,b,d){this.xCorr=-a*d;this.yCorr=-b}});l(h.prototype,{getTransformKey:function(){return n&&!/Edge/.test(m.navigator.userAgent)?"-ms-transform":w?"-webkit-transform":r?"MozTransform":m.opera?"-o-transform":""},html:function(a,b,k){var c=this.createElement("span"),e=c.element,h=c.renderer,m=h.isSVG,w=function(a,b){f(["opacity","visibility"],function(c){d(a, +c+"Setter",function(a,c,d,k){a.call(this,c,d,k);b[d]=c})})};c.textSetter=function(a){a!==e.innerHTML&&delete this.bBox;this.textStr=a;e.innerHTML=u(a,"");c.htmlUpdateTransform()};m&&w(c,c.element.style);c.xSetter=c.ySetter=c.alignSetter=c.rotationSetter=function(a,b){"align"===b&&(b="textAlign");c[b]=a;c.htmlUpdateTransform()};c.attr({text:a,x:Math.round(b),y:Math.round(k)}).css({fontFamily:this.style.fontFamily,fontSize:this.style.fontSize,position:"absolute"});e.style.whiteSpace="nowrap";c.css= +c.htmlCss;m&&(c.add=function(a){var b,d=h.box.parentNode,k=[];if(this.parentGroup=a){if(b=a.div,!b){for(;a;)k.push(a),a=a.parentGroup;f(k.reverse(),function(a){function e(g,b){a[b]=g;n?q[h.getTransformKey()]="translate("+(a.x||a.translateX)+"px,"+(a.y||a.translateY)+"px)":"translateX"===b?q.left=g+"px":q.top=g+"px";a.doTransform=!0}var q,g=E(a.element,"class");g&&(g={className:g});b=a.div=a.div||D("div",g,{position:"absolute",left:(a.translateX||0)+"px",top:(a.translateY||0)+"px",display:a.display, +opacity:a.opacity,pointerEvents:a.styles&&a.styles.pointerEvents},b||d);q=b.style;l(a,{classSetter:function(a){return function(g){this.element.setAttribute("class",g);a.className=g}}(b),on:function(){k[0].div&&c.on.apply({element:k[0].div},arguments);return a},translateXSetter:e,translateYSetter:e});w(a,q)})}}else b=d;b.appendChild(e);c.added=!0;c.alignOnAdd&&c.htmlUpdateTransform();return c});return c}})})(M);(function(a){function E(){var n=a.defaultOptions.global,l=r.moment;if(n.timezone){if(l)return function(a){return-l.tz(a, +n.timezone).utcOffset()};a.error(25)}return n.useUTC&&n.getTimezoneOffset}function D(){var n=a.defaultOptions.global,f,u=n.useUTC,e=u?"getUTC":"get",h=u?"setUTC":"set",m="Minutes Hours Day Date Month FullYear".split(" "),d=m.concat(["Milliseconds","Seconds"]);a.Date=f=n.Date||r.Date;f.hcTimezoneOffset=u&&n.timezoneOffset;f.hcGetTimezoneOffset=E();f.hcHasTimeZone=!(!f.hcTimezoneOffset&&!f.hcGetTimezoneOffset);f.hcMakeTime=function(a,b,d,e,h,m){var c;u?(c=f.UTC.apply(0,arguments),c+=p(c)):c=(new f(a, +b,l(d,1),l(e,0),l(h,0),l(m,0))).getTime();return c};for(n=0;nb&&e-k*zm&&(p=Math.round((h-e)/Math.cos(b*r)));else if(h=e+(1-k)*z,e-k*zm&&(I=m-a.x+I*k,x=-1),I=Math.min(B,I),II||f.autoRotation&&(c.styles||{}).width)p=I;p&&(t.width=p,(n.style||{}).textOverflow||(t.textOverflow="ellipsis"),c.css(t))},getPosition:function(a,f,l,e){var h=this.axis,m=h.chart,d=e&&m.oldChartHeight||m.chartHeight;return{x:a?h.translate(f+l,null,null,e)+h.transB:h.left+h.offset+(h.opposite?(e&&m.oldChartWidth||m.chartWidth)-h.right-h.left:0),y:a?d-h.bottom+h.offset-(h.opposite?h.height:0):d-h.translate(f+l,null,null,e)-h.transB}},getLabelPosition:function(a, +f,l,e,h,m,d,c){var b=this.axis,k=b.transA,z=b.reversed,B=b.staggerLines,n=b.tickRotCorr||{x:0,y:0},x=h.y,u=e||b.reserveSpaceDefault?0:-b.labelOffset*("center"===b.labelAlign?.5:1);D(x)||(x=0===b.side?l.rotation?-8:-l.getBBox().height:2===b.side?n.y+8:Math.cos(l.rotation*r)*(n.y-l.getBBox(!1,0).height/2));a=a+h.x+u+n.x-(m&&e?m*k*(z?-1:1):0);f=f+x-(m&&!e?m*k*(z?1:-1):0);B&&(l=d/(c||1)%B,b.opposite&&(l=B-l-1),f+=b.labelOffset/B*l);return{x:a,y:Math.round(f)}},getMarkPath:function(a,f,l,e,h,m){return m.crispLine(["M", +a,f,"L",a+(h?0:-l),f+(h?l:0)],e)},renderGridLine:function(a,f,l){var e=this.axis,h=e.options,m=this.gridLine,d={},c=this.pos,b=this.type,k=e.tickmarkOffset,z=e.chart.renderer,B=b?b+"Grid":"grid",n=h[B+"LineWidth"],x=h[B+"LineColor"],h=h[B+"LineDashStyle"];m||(d.stroke=x,d["stroke-width"]=n,h&&(d.dashstyle=h),b||(d.zIndex=1),a&&(d.opacity=0),this.gridLine=m=z.path().attr(d).addClass("highcharts-"+(b?b+"-":"")+"grid-line").add(e.gridGroup));if(!a&&m&&(a=e.getPlotLinePath(c+k,m.strokeWidth()*l,a,!0)))m[this.isNew? +"attr":"animate"]({d:a,opacity:f})},renderMark:function(a,f,u){var e=this.axis,h=e.options,m=e.chart.renderer,d=this.type,c=d?d+"Tick":"tick",b=e.tickSize(c),k=this.mark,z=!k,B=a.x;a=a.y;var n=l(h[c+"Width"],!d&&e.isXAxis?1:0),h=h[c+"Color"];b&&(e.opposite&&(b[0]=-b[0]),z&&(this.mark=k=m.path().addClass("highcharts-"+(d?d+"-":"")+"tick").add(e.axisGroup),k.attr({stroke:h,"stroke-width":n})),k[z?"attr":"animate"]({d:this.getMarkPath(B,a,b[0],k.strokeWidth()*u,e.horiz,m),opacity:f}))},renderLabel:function(a, +f,u,e){var h=this.axis,m=h.horiz,d=h.options,c=this.label,b=d.labels,k=b.step,h=h.tickmarkOffset,z=!0,B=a.x;a=a.y;c&&p(B)&&(c.xy=a=this.getLabelPosition(B,a,c,m,b,h,e,k),this.isFirst&&!this.isLast&&!l(d.showFirstLabel,1)||this.isLast&&!this.isFirst&&!l(d.showLastLabel,1)?z=!1:!m||b.step||b.rotation||f||0===u||this.handleOverflow(a),k&&e%k&&(z=!1),z&&p(a.y)?(a.opacity=u,c[this.isNewLabel?"attr":"animate"](a),this.isNewLabel=!1):(c.attr("y",-9999),this.isNewLabel=!0))},render:function(a,f,u){var e= +this.axis,h=e.horiz,m=this.getPosition(h,this.pos,e.tickmarkOffset,f),d=m.x,c=m.y,e=h&&d===e.pos+e.len||!h&&c===e.pos?-1:1;u=l(u,1);this.isActive=!0;this.renderGridLine(f,u,e);this.renderMark(m,u,e);this.renderLabel(m,f,u,a);this.isNew=!1},destroy:function(){H(this,this.axis)}}})(M);var V=function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.color,l=a.correctFloat,r=a.defaultOptions,n=a.defined,w=a.deg2rad,u=a.destroyObjectProperties,e=a.each,h=a.extend,m=a.fireEvent,d=a.format, +c=a.getMagnitude,b=a.grep,k=a.inArray,z=a.isArray,B=a.isNumber,I=a.isString,x=a.merge,K=a.normalizeTickInterval,t=a.objectEach,C=a.pick,N=a.removeEvent,q=a.splat,A=a.syncTimeout,F=a.Tick,G=function(){this.init.apply(this,arguments)};a.extend(G.prototype,{defaultOptions:{dateTimeLabelFormats:{millisecond:"%H:%M:%S.%L",second:"%H:%M:%S",minute:"%H:%M",hour:"%H:%M",day:"%e. %b",week:"%e. %b",month:"%b '%y",year:"%Y"},endOnTick:!1,labels:{enabled:!0,style:{color:"#666666",cursor:"default",fontSize:"11px"}, +x:0},maxPadding:.01,minorTickLength:2,minorTickPosition:"outside",minPadding:.01,startOfWeek:1,startOnTick:!1,tickLength:10,tickmarkPlacement:"between",tickPixelInterval:100,tickPosition:"outside",title:{align:"middle",style:{color:"#666666"}},type:"linear",minorGridLineColor:"#f2f2f2",minorGridLineWidth:1,minorTickColor:"#999999",lineColor:"#ccd6eb",lineWidth:1,gridLineColor:"#e6e6e6",tickColor:"#ccd6eb"},defaultYAxisOptions:{endOnTick:!0,tickPixelInterval:72,showLastLabel:!0,labels:{x:-8},maxPadding:.05, +minPadding:.05,startOnTick:!0,title:{rotation:270,text:"Values"},stackLabels:{allowOverlap:!1,enabled:!1,formatter:function(){return a.numberFormat(this.total,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"#000000",textOutline:"1px contrast"}},gridLineWidth:1,lineWidth:0},defaultLeftAxisOptions:{labels:{x:-15},title:{rotation:270}},defaultRightAxisOptions:{labels:{x:15},title:{rotation:90}},defaultBottomAxisOptions:{labels:{autoRotation:[-45],x:0},title:{rotation:0}},defaultTopAxisOptions:{labels:{autoRotation:[-45], +x:0},title:{rotation:0}},init:function(a,b){var g=b.isX,v=this;v.chart=a;v.horiz=a.inverted&&!v.isZAxis?!g:g;v.isXAxis=g;v.coll=v.coll||(g?"xAxis":"yAxis");v.opposite=b.opposite;v.side=b.side||(v.horiz?v.opposite?0:2:v.opposite?1:3);v.setOptions(b);var c=this.options,d=c.type;v.labelFormatter=c.labels.formatter||v.defaultLabelFormatter;v.userOptions=b;v.minPixelPadding=0;v.reversed=c.reversed;v.visible=!1!==c.visible;v.zoomEnabled=!1!==c.zoomEnabled;v.hasNames="category"===d||!0===c.categories;v.categories= +c.categories||v.hasNames;v.names=v.names||[];v.plotLinesAndBandsGroups={};v.isLog="logarithmic"===d;v.isDatetimeAxis="datetime"===d;v.positiveValuesOnly=v.isLog&&!v.allowNegativeLog;v.isLinked=n(c.linkedTo);v.ticks={};v.labelEdge=[];v.minorTicks={};v.plotLinesAndBands=[];v.alternateBands={};v.len=0;v.minRange=v.userMinRange=c.minRange||c.maxZoom;v.range=c.range;v.offset=c.offset||0;v.stacks={};v.oldStacks={};v.stacksTouched=0;v.max=null;v.min=null;v.crosshair=C(c.crosshair,q(a.options.tooltip.crosshairs)[g? +0:1],!1);b=v.options.events;-1===k(v,a.axes)&&(g?a.axes.splice(a.xAxis.length,0,v):a.axes.push(v),a[v.coll].push(v));v.series=v.series||[];a.inverted&&!v.isZAxis&&g&&void 0===v.reversed&&(v.reversed=!0);t(b,function(a,g){E(v,g,a)});v.lin2log=c.linearToLogConverter||v.lin2log;v.isLog&&(v.val2lin=v.log2lin,v.lin2val=v.lin2log)},setOptions:function(a){this.options=x(this.defaultOptions,"yAxis"===this.coll&&this.defaultYAxisOptions,[this.defaultTopAxisOptions,this.defaultRightAxisOptions,this.defaultBottomAxisOptions, +this.defaultLeftAxisOptions][this.side],x(r[this.coll],a))},defaultLabelFormatter:function(){var g=this.axis,b=this.value,c=g.categories,k=this.dateTimeLabelFormat,e=r.lang,q=e.numericSymbols,e=e.numericSymbolMagnitude||1E3,h=q&&q.length,m,z=g.options.labels.format,g=g.isLog?Math.abs(b):g.tickInterval;if(z)m=d(z,this);else if(c)m=b;else if(k)m=a.dateFormat(k,b);else if(h&&1E3<=g)for(;h--&&void 0===m;)c=Math.pow(e,h+1),g>=c&&0===10*b%c&&null!==q[h]&&0!==b&&(m=a.numberFormat(b/c,-1)+q[h]);void 0=== +m&&(m=1E4<=Math.abs(b)?a.numberFormat(b,-1):a.numberFormat(b,-1,void 0,""));return m},getSeriesExtremes:function(){var a=this,v=a.chart;a.hasVisibleSeries=!1;a.dataMin=a.dataMax=a.threshold=null;a.softThreshold=!a.isXAxis;a.buildStacks&&a.buildStacks();e(a.series,function(g){if(g.visible||!v.options.chart.ignoreHiddenSeries){var c=g.options,d=c.threshold,k;a.hasVisibleSeries=!0;a.positiveValuesOnly&&0>=d&&(d=null);if(a.isXAxis)c=g.xData,c.length&&(g=p(c),k=H(c),B(g)||g instanceof Date||(c=b(c,B), +g=p(c)),a.dataMin=Math.min(C(a.dataMin,c[0],g),g),a.dataMax=Math.max(C(a.dataMax,c[0],k),k));else if(g.getExtremes(),k=g.dataMax,g=g.dataMin,n(g)&&n(k)&&(a.dataMin=Math.min(C(a.dataMin,g),g),a.dataMax=Math.max(C(a.dataMax,k),k)),n(d)&&(a.threshold=d),!c.softThreshold||a.positiveValuesOnly)a.softThreshold=!1}})},translate:function(a,b,c,d,k,e){var g=this.linkedParent||this,v=1,q=0,h=d?g.oldTransA:g.transA;d=d?g.oldMin:g.min;var m=g.minPixelPadding;k=(g.isOrdinal||g.isBroken||g.isLog&&k)&&g.lin2val; +h||(h=g.transA);c&&(v*=-1,q=g.len);g.reversed&&(v*=-1,q-=v*(g.sector||g.len));b?(a=(a*v+q-m)/h+d,k&&(a=g.lin2val(a))):(k&&(a=g.val2lin(a)),a=B(d)?v*(a-d)*h+q+v*m+(B(e)?h*e:0):void 0);return a},toPixels:function(a,b){return this.translate(a,!1,!this.horiz,null,!0)+(b?0:this.pos)},toValue:function(a,b){return this.translate(a-(b?0:this.pos),!0,!this.horiz,null,!0)},getPlotLinePath:function(a,b,c,d,k){var g=this.chart,v=this.left,q=this.top,e,h,m=c&&g.oldChartHeight||g.chartHeight,z=c&&g.oldChartWidth|| +g.chartWidth,A;e=this.transB;var t=function(a,g,b){if(ab)d?a=Math.min(Math.max(g,a),b):A=!0;return a};k=C(k,this.translate(a,null,null,c));a=c=Math.round(k+e);e=h=Math.round(m-k-e);B(k)?this.horiz?(e=q,h=m-this.bottom,a=c=t(a,v,v+this.width)):(a=v,c=z-this.right,e=h=t(e,q,q+this.height)):(A=!0,d=!1);return A&&!d?null:g.renderer.crispLine(["M",a,e,"L",c,h],b||1)},getLinearTickPositions:function(a,b,c){var g,v=l(Math.floor(b/a)*a);c=l(Math.ceil(c/a)*a);var d=[],k;l(v+a)===v&&(k=20);if(this.single)return[b]; +for(b=v;b<=c;){d.push(b);b=l(b+a,k);if(b===g)break;g=b}return d},getMinorTickInterval:function(){var a=this.options;return!0===a.minorTicks?C(a.minorTickInterval,"auto"):!1===a.minorTicks?null:a.minorTickInterval},getMinorTickPositions:function(){var a=this,b=a.options,c=a.tickPositions,d=a.minorTickInterval,k=[],q=a.pointRangePadding||0,h=a.min-q,q=a.max+q,m=q-h;if(m&&m/d=this.minRange,t=this.minRange,d=(t-c+b)/2,d=[b-d,C(a.min,b-d)],k&&(d[2]=this.isLog?this.log2lin(this.dataMin):this.dataMin),b=H(d),c=[b+t,C(a.max,b+t)],k&&(c[2]=this.isLog?this.log2lin(this.dataMax):this.dataMax),c=p(c),c-b=p?(r=p,f=0):b.dataMax<=p&&(w=p,x=0)),b.min= +C(N,r,b.dataMin),b.max=C(D,w,b.dataMax));q&&(b.positiveValuesOnly&&!g&&0>=Math.min(b.min,C(b.dataMin,b.min))&&a.error(10,1),b.min=l(h(b.min),15),b.max=l(h(b.max),15));b.range&&n(b.max)&&(b.userMin=b.min=N=Math.max(b.dataMin,b.minFromRange()),b.userMax=D=b.max,b.range=null);m(b,"foundExtremes");b.beforePadding&&b.beforePadding();b.adjustForMinRange();!(G||b.axisPointRange||b.usePercentage||t)&&n(b.min)&&n(b.max)&&(h=b.max-b.min)&&(!n(N)&&f&&(b.min-=h*f),!n(D)&&x&&(b.max+=h*x));B(k.softMin)&&!B(b.userMin)&& +(b.min=Math.min(b.min,k.softMin));B(k.softMax)&&!B(b.userMax)&&(b.max=Math.max(b.max,k.softMax));B(k.floor)&&(b.min=Math.max(b.min,k.floor));B(k.ceiling)&&(b.max=Math.min(b.max,k.ceiling));I&&n(b.dataMin)&&(p=p||0,!n(N)&&b.min=p?b.min=p:!n(D)&&b.max>p&&b.dataMax<=p&&(b.max=p));b.tickInterval=b.min===b.max||void 0===b.min||void 0===b.max?1:t&&!F&&u===b.linkedParent.options.tickPixelInterval?F=b.linkedParent.tickInterval:C(F,this.tickAmount?(b.max-b.min)/Math.max(this.tickAmount-1,1): +void 0,G?1:(b.max-b.min)*u/Math.max(b.len,u));A&&!g&&e(b.series,function(a){a.processData(b.min!==b.oldMin||b.max!==b.oldMax)});b.setAxisTranslation(!0);b.beforeSetTickPositions&&b.beforeSetTickPositions();b.postProcessTickInterval&&(b.tickInterval=b.postProcessTickInterval(b.tickInterval));b.pointRange&&!F&&(b.tickInterval=Math.max(b.pointRange,b.tickInterval));g=C(k.minTickInterval,b.isDatetimeAxis&&b.closestPointRange);!F&&b.tickIntervalb.tickInterval&&1E3b.max)),!!this.tickAmount));this.tickAmount||(b.tickInterval=b.unsquish());this.setTickPositions()},setTickPositions:function(){var a=this.options,b,c=a.tickPositions;b=this.getMinorTickInterval();var d=a.tickPositioner,k=a.startOnTick,q=a.endOnTick;this.tickmarkOffset=this.categories&&"between"===a.tickmarkPlacement&&1===this.tickInterval?.5:0;this.minorTickInterval="auto"===b&&this.tickInterval?this.tickInterval/ +5:b;this.single=this.min===this.max&&n(this.min)&&!this.tickAmount&&(parseInt(this.min,10)===this.min||!1!==a.allowDecimals);this.tickPositions=b=c&&c.slice();!b&&(b=this.isDatetimeAxis?this.getTimeTicks(this.normalizeTimeTickInterval(this.tickInterval,a.units),this.min,this.max,a.startOfWeek,this.ordinalPositions,this.closestPointRange,!0):this.isLog?this.getLogTickPositions(this.tickInterval,this.min,this.max):this.getLinearTickPositions(this.tickInterval,this.min,this.max),b.length>this.len&&(b= +[b[0],b.pop()],b[0]===b[1]&&(b.length=1)),this.tickPositions=b,d&&(d=d.apply(this,[this.min,this.max])))&&(this.tickPositions=b=d);this.paddedTicks=b.slice(0);this.trimTicks(b,k,q);this.isLinked||(this.single&&2>b.length&&(this.min-=.5,this.max+=.5),c||d||this.adjustTickAmount())},trimTicks:function(a,b,c){var g=a[0],d=a[a.length-1],k=this.minPointOffset||0;if(!this.isLinked){if(b&&-Infinity!==g)this.min=g;else for(;this.min-k>a[0];)a.shift();if(c)this.max=d;else for(;this.max+kb&&(this.finalTickAmt=b,b=5);this.tickAmount=b},adjustTickAmount:function(){var a=this.tickInterval,b=this.tickPositions,c=this.tickAmount,d=this.finalTickAmt,k=b&&b.length,q=C(this.threshold,this.softThreshold?0:null);if(this.hasData()){if(kc&&(this.tickInterval*= +2,this.setTickPositions());if(n(d)){for(a=c=b.length;a--;)(3===d&&1===a%2||2>=d&&0d&&(a=d)),n(c)&&(bd&&(b=d))),this.displayBtn=void 0!==a||void 0!==b,this.setExtremes(a,b,!1,void 0,{trigger:"zoom"});return!0},setAxisSize:function(){var b=this.chart,c=this.options,d=c.offsets||[0,0,0,0],k=this.horiz,q=this.width=Math.round(a.relativeLength(C(c.width,b.plotWidth-d[3]+d[1]),b.plotWidth)),e=this.height=Math.round(a.relativeLength(C(c.height, +b.plotHeight-d[0]+d[2]),b.plotHeight)),h=this.top=Math.round(a.relativeLength(C(c.top,b.plotTop+d[0]),b.plotHeight,b.plotTop)),c=this.left=Math.round(a.relativeLength(C(c.left,b.plotLeft+d[3]),b.plotWidth,b.plotLeft));this.bottom=b.chartHeight-e-h;this.right=b.chartWidth-q-c;this.len=Math.max(k?q:e,0);this.pos=k?c:h},getExtremes:function(){var a=this.isLog,b=this.lin2log;return{min:a?l(b(this.min)):this.min,max:a?l(b(this.max)):this.max,dataMin:this.dataMin,dataMax:this.dataMax,userMin:this.userMin, +userMax:this.userMax}},getThreshold:function(a){var b=this.isLog,g=this.lin2log,c=b?g(this.min):this.min,b=b?g(this.max):this.max;null===a?a=c:c>a?a=c:ba?"right":195a?"left":"center"},tickSize:function(a){var b=this.options,g=b[a+"Length"],c=C(b[a+"Width"],"tick"===a&&this.isXAxis?1:0);if(c&&g)return"inside"===b[a+"Position"]&&(g=-g),[g,c]},labelMetrics:function(){var a= +this.tickPositions&&this.tickPositions[0]||0;return this.chart.renderer.fontMetrics(this.options.labels.style&&this.options.labels.style.fontSize,this.ticks[a]&&this.ticks[a].label)},unsquish:function(){var a=this.options.labels,b=this.horiz,c=this.tickInterval,d=c,k=this.len/(((this.categories?1:0)+this.max-this.min)/c),q,h=a.rotation,m=this.labelMetrics(),z,A=Number.MAX_VALUE,t,x=function(a){a/=k||1;a=1=a)z=x(Math.abs(m.h/Math.sin(w*a))),b=z+Math.abs(a/360),b(c.step||0)&&!c.rotation&&(this.staggerLines||1)*this.len/d||!b&&(c.style&&parseInt(c.style.width,10)||k&&k-a.spacing[3]|| +.33*a.chartWidth)},renderUnsquish:function(){var a=this.chart,b=a.renderer,c=this.tickPositions,d=this.ticks,k=this.options.labels,q=this.horiz,h=this.getSlotWidth(),m=Math.max(1,Math.round(h-2*(k.padding||5))),z={},A=this.labelMetrics(),t=k.style&&k.style.textOverflow,f,F=0,l,B;I(k.rotation)||(z.rotation=k.rotation||0);e(c,function(a){(a=d[a])&&a.labelLength>F&&(F=a.labelLength)});this.maxLabelLength=F;if(this.autoRotation)F>m&&F>A.h?z.rotation=this.labelRotation:this.labelRotation=0;else if(h&& +(f={width:m+"px"},!t))for(f.textOverflow="clip",l=c.length;!q&&l--;)if(B=c[l],m=d[B].label)m.styles&&"ellipsis"===m.styles.textOverflow?m.css({textOverflow:"clip"}):d[B].labelLength>h&&m.css({width:h+"px"}),m.getBBox().height>this.len/c.length-(A.h-A.f)&&(m.specCss={textOverflow:"ellipsis"});z.rotation&&(f={width:(F>.5*a.chartHeight?.33*a.chartHeight:a.chartHeight)+"px"},t||(f.textOverflow="ellipsis"));if(this.labelAlign=k.align||this.autoLabelAlign(this.labelRotation))z.align=this.labelAlign;e(c, +function(a){var b=(a=d[a])&&a.label;b&&(b.attr(z),f&&b.css(x(f,b.specCss)),delete b.specCss,a.rotation=z.rotation)});this.tickRotCorr=b.rotCorr(A.b,this.labelRotation||0,0!==this.side)},hasData:function(){return this.hasVisibleSeries||n(this.min)&&n(this.max)&&this.tickPositions&&0=this.min&&a<=this.max)g[a]||(g[a]=new F(this,a)),d&&g[a].isNew&&g[a].render(b,!0,.1),g[a].render(b)},render:function(){var b= +this,c=b.chart,d=b.options,k=b.isLog,q=b.lin2log,h=b.isLinked,m=b.tickPositions,z=b.axisTitle,x=b.ticks,f=b.minorTicks,l=b.alternateBands,C=d.stackLabels,n=d.alternateGridColor,u=b.tickmarkOffset,G=b.axisLine,p=b.showAxis,I=D(c.renderer.globalAnimation),r,w;b.labelEdge.length=0;b.overlap=!1;e([x,f,l],function(a){t(a,function(a){a.isActive=!1})});if(b.hasData()||h)b.minorTickInterval&&!b.categories&&e(b.getMinorTickPositions(),function(a){b.renderMinorTick(a)}),m.length&&(e(m,function(a,c){b.renderTick(a, +c)}),u&&(0===b.min||b.single)&&(x[-1]||(x[-1]=new F(b,-1,null,!0)),x[-1].render(-1))),n&&e(m,function(d,g){w=void 0!==m[g+1]?m[g+1]+u:b.max-u;0===g%2&&d=h.second?0:C*Math.floor(x.getMilliseconds()/C));if(t>=h.second)x[D.hcSetSeconds](t>=h.minute? +0:C*Math.floor(x.getSeconds()/C));if(t>=h.minute)x[D.hcSetMinutes](t>=h.hour?0:C*Math.floor(x[D.hcGetMinutes]()/C));if(t>=h.hour)x[D.hcSetHours](t>=h.day?0:C*Math.floor(x[D.hcGetHours]()/C));if(t>=h.day)x[D.hcSetDate](t>=h.month?1:C*Math.floor(x[D.hcGetDate]()/C));t>=h.month&&(x[D.hcSetMonth](t>=h.year?0:C*Math.floor(x[D.hcGetMonth]()/C)),n=x[D.hcGetFullYear]());if(t>=h.year)x[D.hcSetFullYear](n-n%C);if(t===h.week)x[D.hcSetDate](x[D.hcGetDate]()-x[D.hcGetDay]()+e(b,1));n=x[D.hcGetFullYear]();b=x[D.hcGetMonth](); +var A=x[D.hcGetDate](),F=x[D.hcGetHours]();d=x.getTime();D.hcHasTimeZone&&(q=(!B||!!D.hcGetTimezoneOffset)&&(c-d>4*h.month||w(d)!==w(c)),N=w(x),x=new D(d+N));B=x.getTime();for(d=1;Bk.length&&l(k,function(a){0===a%18E5&&"000000000"===H("%H%M%S%L",a)&&(m[a]="day")})}k.info=r(a,{higherRanks:m,totalRange:t*C});return k}; +E.prototype.normalizeTimeTickInterval=function(a,d){var c=d||[["millisecond",[1,2,5,10,20,25,50,100,200,500]],["second",[1,2,5,10,15,30]],["minute",[1,2,5,10,15,30]],["hour",[1,2,3,4,6,8,12]],["day",[1,2]],["week",[1,2]],["month",[1,2,3,4,6]],["year",null]];d=c[c.length-1];var b=h[d[0]],k=d[1],e;for(e=0;er&&(!w||z<=n)&&void 0!==z&&d.push(z),z>n&& +(B=!0),z=k;else r=h(r),n=h(n),a=w?this.getMinorTickInterval():l.tickInterval,a=f("auto"===a?null:a,this._minorAutoInterval,l.tickPixelInterval/(w?5:1)*(n-r)/((w?e/this.tickPositions.length:e)||1)),a=p(a,null,D(a)),d=H(this.getLinearTickPositions(a,r,n),m),w||(this._minorAutoInterval=a/5);w||(this.tickInterval=a);return d};E.prototype.log2lin=function(a){return Math.log(a)/Math.LN10};E.prototype.lin2log=function(a){return Math.pow(10,a)}})(M);(function(a,E){var D=a.arrayMax,H=a.arrayMin,p=a.defined, +f=a.destroyObjectProperties,l=a.each,r=a.erase,n=a.merge,w=a.pick;a.PlotLineOrBand=function(a,e){this.axis=a;e&&(this.options=e,this.id=e.id)};a.PlotLineOrBand.prototype={render:function(){var f=this,e=f.axis,h=e.horiz,m=f.options,d=m.label,c=f.label,b=m.to,k=m.from,z=m.value,l=p(k)&&p(b),r=p(z),x=f.svgElem,K=!x,t=[],C=m.color,N=w(m.zIndex,0),q=m.events,t={"class":"highcharts-plot-"+(l?"band ":"line ")+(m.className||"")},A={},F=e.chart.renderer,G=l?"bands":"lines",g=e.log2lin;e.isLog&&(k=g(k),b=g(b), +z=g(z));r?(t={stroke:C,"stroke-width":m.width},m.dashStyle&&(t.dashstyle=m.dashStyle)):l&&(C&&(t.fill=C),m.borderWidth&&(t.stroke=m.borderColor,t["stroke-width"]=m.borderWidth));A.zIndex=N;G+="-"+N;(C=e.plotLinesAndBandsGroups[G])||(e.plotLinesAndBandsGroups[G]=C=F.g("plot-"+G).attr(A).add());K&&(f.svgElem=x=F.path().attr(t).add(C));if(r)t=e.getPlotLinePath(z,x.strokeWidth());else if(l)t=e.getPlotBandPath(k,b,m);else return;K&&t&&t.length?(x.attr({d:t}),q&&a.objectEach(q,function(a,b){x.on(b,function(a){q[b].apply(f, +[a])})})):x&&(t?(x.show(),x.animate({d:t})):(x.hide(),c&&(f.label=c=c.destroy())));d&&p(d.text)&&t&&t.length&&0this.max&& +e>this.max;if(m&&h)for(a&&(k=m.toString()===h.toString(),b=0),a=0;aA-h?A:A-h);else if(z)k[a]=Math.max(e,g+h+d>c?g:g+h);else return!1},C=function(a,c,d,g){var e;gc-b?e=!1:k[a]=gc-d/2?c-d-2:g-d/2;return e},p=function(a){var b=f;f=x;x=b;m=a},q=function(){!1!==t.apply(0,f)?!1!==C.apply(0,x)||m||(p(!0),q()):m?k.x=k.y=0:(p(!0),q())};(c.inverted||1q&&(h=!1);a=(e.series&& +e.series.yAxis&&e.series.yAxis.pos)+(e.plotY||0);a-=b.plotTop;c.push({target:e.isHeader?b.plotHeight+l:a,rank:e.isHeader?1:0,size:z.tt.getBBox().height+1,point:e,x:q,tt:t})}});this.cleanSplit();a.distribute(c,b.plotHeight+l);D(c,function(a){var c=a.point,d=c.series;a.tt.attr({visibility:void 0===a.pos?"hidden":"inherit",x:h||c.isHeader?a.x:c.plotX+b.plotLeft+n(f.distance,16),y:a.pos+b.plotTop,anchorX:c.isHeader?c.plotX+b.plotLeft:c.plotX+d.xAxis.pos,anchorY:c.isHeader?a.pos+b.plotTop-15:c.plotY+d.yAxis.pos})})}, +updatePosition:function(a){var e=this.chart,d=this.getLabel(),d=(this.options.positioner||this.getPosition).call(this,d.width,d.height,a);this.move(Math.round(d.x),Math.round(d.y||0),a.plotX+e.plotLeft,a.plotY+e.plotTop)},getDateFormat:function(a,m,d,c){var b=E("%m-%d %H:%M:%S.%L",m),k,h,f={millisecond:15,second:12,minute:9,hour:6,day:3},l="millisecond";for(h in e){if(a===e.week&&+E("%w",m)===d&&"00:00:00.000"===b.substr(6)){h="week";break}if(e[h]>a){h=l;break}if(f[h]&&b.substr(f[h])!=="01-01 00:00:00.000".substr(f[h]))break; +"week"!==h&&(l=h)}h&&(k=c[h]);return k},getXDateFormat:function(a,e,d){e=e.dateTimeLabelFormats;var c=d&&d.closestPointRange;return(c?this.getDateFormat(c,a.x,d.options.startOfWeek,e):e.day)||e.year},tooltipFooterHeaderFormatter:function(a,e){e=e?"footer":"header";var d=a.series,c=d.tooltipOptions,b=c.xDateFormat,k=d.xAxis,h=k&&"datetime"===k.options.type&&f(a.key),m=c[e+"Format"];h&&!b&&(b=this.getXDateFormat(a,c,k));h&&b&&D(a.point&&a.point.tooltipDateKeys||["key"],function(a){m=m.replace("{point."+ +a+"}","{point."+a+":"+b+"}")});return p(m,{point:a,series:d})},bodyFormatter:function(a){return l(a,function(a){var d=a.series.tooltipOptions;return(d[(a.point.formatPrefix||"point")+"Formatter"]||a.point.tooltipFormatter).call(a.point,d[(a.point.formatPrefix||"point")+"Format"])})}}})(M);(function(a){var E=a.addEvent,D=a.attr,H=a.charts,p=a.color,f=a.css,l=a.defined,r=a.each,n=a.extend,w=a.find,u=a.fireEvent,e=a.isObject,h=a.offset,m=a.pick,d=a.splat,c=a.Tooltip;a.Pointer=function(a,c){this.init(a, +c)};a.Pointer.prototype={init:function(a,d){this.options=d;this.chart=a;this.runChartClick=d.chart.events&&!!d.chart.events.click;this.pinchDown=[];this.lastValidTouch={};c&&(a.tooltip=new c(a,d.tooltip),this.followTouchMove=m(d.tooltip.followTouchMove,!0));this.setDOMEvents()},zoomOption:function(a){var b=this.chart,c=b.options.chart,d=c.zoomType||"",b=b.inverted;/touch/.test(a.type)&&(d=m(c.pinchType,d));this.zoomX=a=/x/.test(d);this.zoomY=d=/y/.test(d);this.zoomHor=a&&!b||d&&b;this.zoomVert=d&& +!b||a&&b;this.hasZoom=a||d},normalize:function(a,c){var b;b=a.touches?a.touches.length?a.touches.item(0):a.changedTouches[0]:a;c||(this.chartPosition=c=h(this.chart.container));return n(a,{chartX:Math.round(b.pageX-c.left),chartY:Math.round(b.pageY-c.top)})},getCoordinates:function(a){var b={xAxis:[],yAxis:[]};r(this.chart.axes,function(c){b[c.isXAxis?"xAxis":"yAxis"].push({axis:c,value:c.toValue(a[c.horiz?"chartX":"chartY"])})});return b},findNearestKDPoint:function(a,c,d){var b;r(a,function(a){var k= +!(a.noSharedTooltip&&c)&&0>a.options.findNearestPointBy.indexOf("y");a=a.searchPoint(d,k);if((k=e(a,!0))&&!(k=!e(b,!0)))var k=b.distX-a.distX,h=b.dist-a.dist,m=(a.series.group&&a.series.group.zIndex)-(b.series.group&&b.series.group.zIndex),k=0<(0!==k&&c?k:0!==h?h:0!==m?m:b.series.index>a.series.index?-1:1);k&&(b=a)});return b},getPointFromEvent:function(a){a=a.target;for(var b;a&&!b;)b=a.point,a=a.parentNode;return b},getChartCoordinatesFromPoint:function(a,c){var b=a.series,d=b.xAxis,b=b.yAxis,k= +m(a.clientX,a.plotX);if(d&&b)return c?{chartX:d.len+d.pos-k,chartY:b.len+b.pos-a.plotY}:{chartX:k+d.pos,chartY:a.plotY+b.pos}},getHoverData:function(b,c,d,h,f,l,n){var k,z=[],x=n&&n.isBoosting;h=!(!h||!b);n=c&&!c.stickyTracking?[c]:a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking,!0)&&a.stickyTracking});c=(k=h?b:this.findNearestKDPoint(n,f,l))&&k.series;k&&(f&&!c.noSharedTooltip?(n=a.grep(d,function(a){return a.visible&&!(!f&&a.directTouch)&&m(a.options.enableMouseTracking, +!0)&&!a.noSharedTooltip}),r(n,function(a){var b=w(a.points,function(a){return a.x===k.x&&!a.isNull});e(b)&&(x&&(b=a.getPoint(b)),z.push(b))})):z.push(k));return{hoverPoint:k,hoverSeries:c,hoverPoints:z}},runPointActions:function(b,c){var d=this.chart,k=d.tooltip&&d.tooltip.options.enabled?d.tooltip:void 0,e=k?k.shared:!1,h=c||d.hoverPoint,f=h&&h.series||d.hoverSeries,f=this.getHoverData(h,f,d.series,!!c||f&&f.directTouch&&this.isDirectTouch,e,b,{isBoosting:d.isBoosting}),l,h=f.hoverPoint;l=f.hoverPoints; +c=(f=f.hoverSeries)&&f.tooltipOptions.followPointer;e=e&&f&&!f.noSharedTooltip;if(h&&(h!==d.hoverPoint||k&&k.isHidden)){r(d.hoverPoints||[],function(b){-1===a.inArray(b,l)&&b.setState()});r(l||[],function(a){a.setState("hover")});if(d.hoverSeries!==f)f.onMouseOver();d.hoverPoint&&d.hoverPoint.firePointEvent("mouseOut");if(!h.series)return;h.firePointEvent("mouseOver");d.hoverPoints=l;d.hoverPoint=h;k&&k.refresh(e?l:h,b)}else c&&k&&!k.isHidden&&(h=k.getAnchor([{}],b),k.updatePosition({plotX:h[0],plotY:h[1]})); +this.unDocMouseMove||(this.unDocMouseMove=E(d.container.ownerDocument,"mousemove",function(b){var c=H[a.hoverChartIndex];if(c)c.pointer.onDocumentMouseMove(b)}));r(d.axes,function(c){var d=m(c.crosshair.snap,!0),k=d?a.find(l,function(a){return a.series[c.coll]===c}):void 0;k||!d?c.drawCrosshair(b,k):c.hideCrosshair()})},reset:function(a,c){var b=this.chart,k=b.hoverSeries,e=b.hoverPoint,h=b.hoverPoints,m=b.tooltip,f=m&&m.shared?h:e;a&&f&&r(d(f),function(b){b.series.isCartesian&&void 0===b.plotX&& +(a=!1)});if(a)m&&f&&(m.refresh(f),e&&(e.setState(e.state,!0),r(b.axes,function(a){a.crosshair&&a.drawCrosshair(null,e)})));else{if(e)e.onMouseOut();h&&r(h,function(a){a.setState()});if(k)k.onMouseOut();m&&m.hide(c);this.unDocMouseMove&&(this.unDocMouseMove=this.unDocMouseMove());r(b.axes,function(a){a.hideCrosshair()});this.hoverX=b.hoverPoints=b.hoverPoint=null}},scaleGroups:function(a,c){var b=this.chart,d;r(b.series,function(k){d=a||k.getPlotBox();k.xAxis&&k.xAxis.zoomEnabled&&k.group&&(k.group.attr(d), +k.markerGroup&&(k.markerGroup.attr(d),k.markerGroup.clip(c?b.clipRect:null)),k.dataLabelsGroup&&k.dataLabelsGroup.attr(d))});b.clipRect.attr(c||b.clipBox)},dragStart:function(a){var b=this.chart;b.mouseIsDown=a.type;b.cancelClick=!1;b.mouseDownX=this.mouseDownX=a.chartX;b.mouseDownY=this.mouseDownY=a.chartY},drag:function(a){var b=this.chart,c=b.options.chart,d=a.chartX,e=a.chartY,h=this.zoomHor,m=this.zoomVert,f=b.plotLeft,l=b.plotTop,n=b.plotWidth,q=b.plotHeight,A,F=this.selectionMarker,G=this.mouseDownX, +g=this.mouseDownY,v=c.panKey&&a[c.panKey+"Key"];F&&F.touch||(df+n&&(d=f+n),el+q&&(e=l+q),this.hasDragged=Math.sqrt(Math.pow(G-d,2)+Math.pow(g-e,2)),10u.max&&(f=u.max-x,v=!0);v?(F-=.8*(F-m[b][0]),q||(g-=.8*(g-m[b][1])),l()):m[b]=[F,g];C||(h[b]=w-r,h[n]=x);h=C?1/t:t;e[n]=x;e[b]=f;p[C?a?"scaleY":"scaleX":"scale"+k]=t;p["translate"+k]=h*r+(F-h*A)},pinch:function(a){var n=this,r=n.chart,u=n.pinchDown,e=a.touches,h=e.length,m=n.lastValidTouch, +d=n.hasZoom,c=n.selectionMarker,b={},k=1===h&&(n.inClass(a.target,"highcharts-tracker")&&r.runTrackerClick||n.runChartClick),z={};1c-6&&h(q||c.spacingBox.width-2*t-d.x)&&(this.itemX=t,this.itemY+=F+this.lastLineHeight+A,this.lastLineHeight=0);this.maxItemWidth=Math.max(this.maxItemWidth,m);this.lastItemY=F+this.itemY+A;this.lastLineHeight=Math.max(b,this.lastLineHeight);a._legendItemPos=[this.itemX,this.itemY];e?this.itemX+=m:(this.itemY+=F+b+A,this.lastLineHeight=b);this.offsetWidth=q||Math.max((e?this.itemX-t-(a.checkbox?0:p):m)+t,this.offsetWidth)}, +getAllItems:function(){var a=[];f(this.chart.series,function(c){var b=c&&c.options;c&&w(b.showInLegend,p(b.linkedTo)?!1:void 0,!0)&&(a=a.concat(c.legendItems||("point"===b.legendType?c.data:c)))});return a},getAlignment:function(){var a=this.options;return a.floating?"":a.align.charAt(0)+a.verticalAlign.charAt(0)+a.layout.charAt(0)},adjustMargins:function(a,c){var b=this.chart,d=this.options,e=this.getAlignment();e&&f([/(lth|ct|rth)/,/(rtv|rm|rbv)/,/(rbh|cb|lbh)/,/(lbv|lm|ltv)/],function(k,h){k.test(e)&& +!p(a[h])&&(b[r[h]]=Math.max(b[r[h]],b.legend[(h+1)%2?"legendHeight":"legendWidth"]+[1,-1,-1,1][h]*d[h%2?"x":"y"]+w(d.margin,12)+c[h]+(0===h?b.titleOffset+b.options.title.margin:0)))})},render:function(){var a=this,c=a.chart,b=c.renderer,k=a.group,h,m,l,x,p=a.box,t=a.options,C=a.padding;a.itemX=C;a.itemY=a.initialItemY;a.offsetWidth=0;a.lastItemY=0;k||(a.group=k=b.g("legend").attr({zIndex:7}).add(),a.contentGroup=b.g().attr({zIndex:1}).add(k),a.scrollGroup=b.g().add(a.contentGroup));a.renderTitle(); +h=a.getAllItems();e(h,function(a,b){return(a.options&&a.options.legendIndex||0)-(b.options&&b.options.legendIndex||0)});t.reversed&&h.reverse();a.allItems=h;a.display=m=!!h.length;a.lastLineHeight=0;f(h,function(b){a.renderItem(b)});l=(t.width||a.offsetWidth)+C;x=a.lastItemY+a.lastLineHeight+a.titleHeight;x=a.handleOverflow(x);x+=C;p||(a.box=p=b.rect().addClass("highcharts-legend-box").attr({r:t.borderRadius}).add(k),p.isNew=!0);p.attr({stroke:t.borderColor,"stroke-width":t.borderWidth||0,fill:t.backgroundColor|| +"none"}).shadow(t.shadow);0b&&!1!==t.enabled?(this.clipHeight=l=Math.max(b-20-this.titleHeight-m,0),this.currentPage=w(this.currentPage,1),this.fullHeight=a,f(G,function(a,b){var c=a._legendItemPos[1],d=Math.round(a.legendItem.getBBox().height),g=A.length;if(!g||c-A[g-1]>l&&(F||c)!==A[g-1])A.push(F||c),g++;a.pageIx=g-1;F&&(G[b-1].pageIx=g-1);b===G.length-1&&c+d-A[g-1]>l&&(A.push(c),a.pageIx=g);c!==F&&(F=c)}),n||(n=c.clipRect=d.clipRect(0,m,9999,0),c.contentGroup.clip(n)),g(l),q||(this.nav=q=d.g().attr({zIndex:1}).add(this.group), +this.up=d.symbol("triangle",0,0,r,r).on("click",function(){c.scroll(-1,p)}).add(q),this.pager=d.text("",15,10).addClass("highcharts-legend-navigation").css(t.style).add(q),this.down=d.symbol("triangle-down",0,0,r,r).on("click",function(){c.scroll(1,p)}).add(q)),c.scroll(0),a=b):q&&(g(),this.nav=q.destroy(),this.scrollGroup.attr({translateY:1}),this.clipHeight=0);return a},scroll:function(a,c){var b=this.pages,d=b.length;a=this.currentPage+a;var e=this.clipHeight,h=this.options.navigation,f=this.pager, +m=this.padding;a>d&&(a=d);0b&&(f=typeof a[0],"string"===f?e.name=a[0]:"number"===f&&(e.x=a[0]),k++);l=d.value;)d=h[++f];d&&d.color&&!this.options.color&&(this.color=d.color);return d},destroy:function(){var a=this.series.chart,h=a.hoverPoints,f;a.pointCount--;h&&(this.setState(),p(h,this),h.length||(a.hoverPoints=null));if(this===a.hoverPoint)this.onMouseOut();if(this.graphic||this.dataLabel)u(this),this.destroyElements();this.legendItem&&a.legend.destroyItem(this);for(f in this)this[f]=null},destroyElements:function(){for(var a=["graphic","dataLabel", +"dataLabelUpper","connector","shadowGroup"],h,f=6;f--;)h=a[f],this[h]&&(this[h]=this[h].destroy())},getLabelConfig:function(){return{x:this.category,y:this.y,color:this.color,colorIndex:this.colorIndex,key:this.name||this.category,series:this.series,point:this,percentage:this.percentage,total:this.total||this.stackTotal}},tooltipFormatter:function(a){var e=this.series,f=e.tooltipOptions,d=w(f.valueDecimals,""),c=f.valuePrefix||"",b=f.valueSuffix||"";D(e.pointArrayMap||["y"],function(e){e="{point."+ +e;if(c||b)a=a.replace(e+"}",c+e+"}"+b);a=a.replace(e+"}",e+":,."+d+"f}")});return l(a,{point:this,series:this.series})},firePointEvent:function(a,h,m){var d=this,c=this.series.options;(c.point.events[a]||d.options&&d.options.events&&d.options.events[a])&&this.importEvents();"click"===a&&c.allowPointSelect&&(m=function(a){d.select&&d.select(null,a.ctrlKey||a.metaKey||a.shiftKey)});f(this,a,h,m)},visible:!0}})(M);(function(a){var E=a.addEvent,D=a.animObject,H=a.arrayMax,p=a.arrayMin,f=a.correctFloat, +l=a.Date,r=a.defaultOptions,n=a.defaultPlotOptions,w=a.defined,u=a.each,e=a.erase,h=a.extend,m=a.fireEvent,d=a.grep,c=a.isArray,b=a.isNumber,k=a.isString,z=a.merge,B=a.objectEach,I=a.pick,x=a.removeEvent,K=a.splat,t=a.SVGElement,C=a.syncTimeout,N=a.win;a.Series=a.seriesType("line",null,{lineWidth:2,allowPointSelect:!1,showCheckbox:!1,animation:{duration:1E3},events:{},marker:{lineWidth:0,lineColor:"#ffffff",radius:4,states:{hover:{animation:{duration:50},enabled:!0,radiusPlus:2,lineWidthPlus:1},select:{fillColor:"#cccccc", +lineColor:"#000000",lineWidth:2}}},point:{events:{}},dataLabels:{align:"center",formatter:function(){return null===this.y?"":a.numberFormat(this.y,-1)},style:{fontSize:"11px",fontWeight:"bold",color:"contrast",textOutline:"1px contrast"},verticalAlign:"bottom",x:0,y:0,padding:5},cropThreshold:300,pointRange:0,softThreshold:!0,states:{hover:{animation:{duration:50},lineWidthPlus:1,marker:{},halo:{size:10,opacity:.25}},select:{marker:{}}},stickyTracking:!0,turboThreshold:1E3,findNearestPointBy:"x"}, +{isCartesian:!0,pointClass:a.Point,sorted:!0,requireSorting:!0,directTouch:!1,axisTypes:["xAxis","yAxis"],colorCounter:0,parallelArrays:["x","y"],coll:"series",init:function(a,b){var c=this,d,g=a.series,e;c.chart=a;c.options=b=c.setOptions(b);c.linkedSeries=[];c.bindAxes();h(c,{name:b.name,state:"",visible:!1!==b.visible,selected:!0===b.selected});d=b.events;B(d,function(a,b){E(c,b,a)});if(d&&d.click||b.point&&b.point.events&&b.point.events.click||b.allowPointSelect)a.runTrackerClick=!0;c.getColor(); +c.getSymbol();u(c.parallelArrays,function(a){c[a+"Data"]=[]});c.setData(b.data,!1);c.isCartesian&&(a.hasCartesianSeries=!0);g.length&&(e=g[g.length-1]);c._i=I(e&&e._i,-1)+1;a.orderSeries(this.insert(g))},insert:function(a){var c=this.options.index,d;if(b(c)){for(d=a.length;d--;)if(c>=I(a[d].options.index,a[d]._i)){a.splice(d+1,0,this);break}-1===d&&a.unshift(this);d+=1}else a.push(this);return I(d,a.length-1)},bindAxes:function(){var b=this,c=b.options,d=b.chart,e;u(b.axisTypes||[],function(g){u(d[g], +function(a){e=a.options;if(c[g]===e.index||void 0!==c[g]&&c[g]===e.id||void 0===c[g]&&0===e.index)b.insert(a.series),b[g]=a,a.isDirty=!0});b[g]||b.optionalAxis===g||a.error(18,!0)})},updateParallelArrays:function(a,c){var d=a.series,e=arguments,g=b(c)?function(b){var g="y"===b&&d.toYData?d.toYData(a):a[b];d[b+"Data"][c]=g}:function(a){Array.prototype[c].apply(d[a+"Data"],Array.prototype.slice.call(e,2))};u(d.parallelArrays,g)},autoIncrement:function(){var b=this.options,c=this.xIncrement,d,e=b.pointIntervalUnit, +g=0,c=I(c,b.pointStart,0);this.pointInterval=d=I(this.pointInterval,b.pointInterval,1);e&&(b=new l(c),"day"===e?b=+b[l.hcSetDate](b[l.hcGetDate]()+d):"month"===e?b=+b[l.hcSetMonth](b[l.hcGetMonth]()+d):"year"===e&&(b=+b[l.hcSetFullYear](b[l.hcGetFullYear]()+d)),l.hcHasTimeZone&&(g=a.getTZOffset(b)-a.getTZOffset(c)),d=b-c+g);this.xIncrement=c+d;return c},setOptions:function(a){var b=this.chart,c=b.options,d=c.plotOptions,g=(b.userOptions||{}).plotOptions||{},e=d[this.type];this.userOptions=a;b=z(e, +d.series,a);this.tooltipOptions=z(r.tooltip,r.plotOptions.series&&r.plotOptions.series.tooltip,r.plotOptions[this.type].tooltip,c.tooltip.userOptions,d.series&&d.series.tooltip,d[this.type].tooltip,a.tooltip);this.stickyTracking=I(a.stickyTracking,g[this.type]&&g[this.type].stickyTracking,g.series&&g.series.stickyTracking,this.tooltipOptions.shared&&!this.noSharedTooltip?!0:b.stickyTracking);null===e.marker&&delete b.marker;this.zoneAxis=b.zoneAxis;a=this.zones=(b.zones||[]).slice();!b.negativeColor&& +!b.negativeFillColor||b.zones||a.push({value:b[this.zoneAxis+"Threshold"]||b.threshold||0,className:"highcharts-negative",color:b.negativeColor,fillColor:b.negativeFillColor});a.length&&w(a[a.length-1].value)&&a.push({color:this.color,fillColor:this.fillColor});return b},getCyclic:function(a,b,c){var d,g=this.chart,e=this.userOptions,k=a+"Index",h=a+"Counter",q=c?c.length:I(g.options.chart[a+"Count"],g[a+"Count"]);b||(d=I(e[k],e["_"+k]),w(d)||(g.series.length||(g[h]=0),e["_"+k]=d=g[h]%q,g[h]+=1), +c&&(b=c[d]));void 0!==d&&(this[k]=d);this[a]=b},getColor:function(){this.options.colorByPoint?this.options.color=null:this.getCyclic("color",this.options.color||n[this.type].color,this.chart.options.colors)},getSymbol:function(){this.getCyclic("symbol",this.options.marker.symbol,this.chart.options.symbols)},drawLegendSymbol:a.LegendSymbolMixin.drawLineMarker,setData:function(d,e,h,f){var g=this,q=g.points,m=q&&q.length||0,l,A=g.options,t=g.chart,x=null,n=g.xAxis,p=A.turboThreshold,z=this.xData,F= +this.yData,C=(l=g.pointArrayMap)&&l.length;d=d||[];l=d.length;e=I(e,!0);if(!1!==f&&l&&m===l&&!g.cropped&&!g.hasGroupedData&&g.visible)u(d,function(a,b){q[b].update&&a!==A.data[b]&&q[b].update(a,!1,null,!1)});else{g.xIncrement=null;g.colorCounter=0;u(this.parallelArrays,function(a){g[a+"Data"].length=0});if(p&&l>p){for(h=0;null===x&&hf||this.forceCrop))if(c[e-1]z)c=[],d=[];else if(c[0]z)g=this.cropData(this.xData,this.yData,p,z),c=g.xData,d=g.yData,g=g.start,k=!0;for(f=c.length|| +1;--f;)e=x?m(c[f])-m(c[f-1]):c[f]-c[f-1],0e&&n&&(a.error(15),n=!1);this.cropped=k;this.cropStart=g;this.processedXData=c;this.processedYData=d;this.closestPointRange=h},cropData:function(a,b,c,d){var g=a.length,e=0,k=g,h=I(this.cropShoulder,1),f;for(f=0;f=c){e=Math.max(0,f-h);break}for(c=f;cd){k=c+h;break}return{xData:a.slice(e,k),yData:b.slice(e,k),start:e,end:k}},generatePoints:function(){var a=this.options,b=a.data,c=this.data,d,g=this.processedXData, +e=this.processedYData,k=this.pointClass,h=g.length,f=this.cropStart||0,m,l=this.hasGroupedData,a=a.keys,t,x=[],n;c||l||(c=[],c.length=b.length,c=this.data=c);a&&l&&(this.options.keys=!1);for(n=0;n=f&&(e[n-1]||l)<=q,m&&l)if(m=t.length)for(;m--;)"number"===typeof t[m]&&(g[h++]=t[m]);else g[h++]=t;this.dataMin= +p(g);this.dataMax=H(g)},translate:function(){this.processedXData||this.processData();this.generatePoints();var a=this.options,c=a.stacking,d=this.xAxis,e=d.categories,g=this.yAxis,k=this.points,h=k.length,m=!!this.modifyValue,l=a.pointPlacement,t="between"===l||b(l),n=a.threshold,x=a.startFromThreshold?n:0,p,z,C,r,u=Number.MAX_VALUE;"between"===l&&(l=.5);b(l)&&(l*=I(a.pointRange||d.pointRange));for(a=0;a=K&&(B.isNull=!0);B.plotX=p=f(Math.min(Math.max(-1E5,d.translate(N,0,0,0,1,l,"flags"===this.type)),1E5));c&&this.visible&&!B.isNull&&D&&D[N]&&(r=this.getStackIndicator(r,N,this.index),E=D[N],K=E.points[r.key],z=K[0],K=K[1],z===x&&r.key===D[N].base&&(z=I(n,g.min)),g.positiveValuesOnly&&0>=z&&(z=null),B.total=B.stackTotal=E.total,B.percentage=E.total&&B.y/E.total*100,B.stackY=K,E.setOffset(this.pointXOffset||0,this.barW||0));B.yBottom=w(z)?g.translate(z,0,1,0,1): +null;m&&(K=this.modifyValue(K,B));B.plotY=z="number"===typeof K&&Infinity!==K?Math.min(Math.max(-1E5,g.translate(K,0,1,0,1)),1E5):void 0;B.isInside=void 0!==z&&0<=z&&z<=g.len&&0<=p&&p<=d.len;B.clientX=t?f(d.translate(N,0,0,0,1,l)):p;B.negative=B.y<(n||0);B.category=e&&void 0!==e[B.x]?e[B.x]:B.x;B.isNull||(void 0!==C&&(u=Math.min(u,Math.abs(p-C))),C=p);B.zone=this.zones.length&&B.getZone()}this.closestPointRangePx=u},getValidPoints:function(a,b){var c=this.chart;return d(a||this.points||[],function(a){return b&& +!c.isInsidePlot(a.plotX,a.plotY,c.inverted)?!1:!a.isNull})},setClip:function(a){var b=this.chart,c=this.options,d=b.renderer,g=b.inverted,e=this.clipBox,k=e||b.clipBox,h=this.sharedClipKey||["_sharedClip",a&&a.duration,a&&a.easing,k.height,c.xAxis,c.yAxis].join(),f=b[h],q=b[h+"m"];f||(a&&(k.width=0,g&&(k.x=b.plotSizeX),b[h+"m"]=q=d.clipRect(g?b.plotSizeX+99:-99,g?-b.plotLeft:-b.plotTop,99,g?b.chartWidth:b.chartHeight)),b[h]=f=d.clipRect(k),f.count={length:0});a&&!f.count[this.index]&&(f.count[this.index]= +!0,f.count.length+=1);!1!==c.clip&&(this.group.clip(a||e?f:b.clipRect),this.markerGroup.clip(q),this.sharedClipKey=h);a||(f.count[this.index]&&(delete f.count[this.index],--f.count.length),0===f.count.length&&h&&b[h]&&(e||(b[h]=b[h].destroy()),b[h+"m"]&&(b[h+"m"]=b[h+"m"].destroy())))},animate:function(a){var b=this.chart,c=D(this.options.animation),d;a?this.setClip(c):(d=this.sharedClipKey,(a=b[d])&&a.animate({width:b.plotSizeX,x:0},c),b[d+"m"]&&b[d+"m"].animate({width:b.plotSizeX+99,x:0},c),this.animate= +null)},afterAnimate:function(){this.setClip();m(this,"afterAnimate");this.finishedAnimating=!0},drawPoints:function(){var a=this.points,b=this.chart,c,d,g,e,k=this.options.marker,h,f,l,m=this[this.specialGroup]||this.markerGroup,t,n=I(k.enabled,this.xAxis.isRadial?!0:null,this.closestPointRangePx>=2*k.radius);if(!1!==k.enabled||this._hasPointMarkers)for(c=0;ce&&b.shadow));k&&(k.startX=c.xMap,k.isArea=c.isArea)})}, +applyZones:function(){var a=this,b=this.chart,c=b.renderer,d=this.zones,e,k,h=this.clips||[],f,m=this.graph,l=this.area,t=Math.max(b.chartWidth,b.chartHeight),n=this[(this.zoneAxis||"y")+"Axis"],x,p,z=b.inverted,C,r,w,B,K=!1;d.length&&(m||l)&&n&&void 0!==n.min&&(p=n.reversed,C=n.horiz,m&&m.hide(),l&&l.hide(),x=n.getExtremes(),u(d,function(d,g){e=p?C?b.plotWidth:0:C?0:n.toPixels(x.min);e=Math.min(Math.max(I(k,e),0),t);k=Math.min(Math.max(Math.round(n.toPixels(I(d.value,x.max),!0)),0),t);K&&(e=k=n.toPixels(x.max)); +r=Math.abs(e-k);w=Math.min(e,k);B=Math.max(e,k);n.isXAxis?(f={x:z?B:w,y:0,width:r,height:t},C||(f.x=b.plotHeight-f.x)):(f={x:0,y:z?B:w,width:t,height:r},C&&(f.y=b.plotWidth-f.y));z&&c.isVML&&(f=n.isXAxis?{x:0,y:p?w:B,height:f.width,width:b.chartWidth}:{x:f.y-b.plotLeft-b.spacingBox.x,y:0,width:f.height,height:b.chartHeight});h[g]?h[g].animate(f):(h[g]=c.clipRect(f),m&&a["zone-graph-"+g].clip(h[g]),l&&a["zone-area-"+g].clip(h[g]));K=d.value>x.max}),this.clips=h)},invertGroups:function(a){function b(){u(["group", +"markerGroup"],function(b){c[b]&&(d.renderer.isVML&&c[b].attr({width:c.yAxis.len,height:c.xAxis.len}),c[b].width=c.yAxis.len,c[b].height=c.xAxis.len,c[b].invert(a))})}var c=this,d=c.chart,e;c.xAxis&&(e=E(d,"resize",b),E(c,"destroy",e),b(a),c.invertGroups=b)},plotGroup:function(a,b,c,d,e){var g=this[a],k=!g;k&&(this[a]=g=this.chart.renderer.g().attr({zIndex:d||.1}).add(e));g.addClass("highcharts-"+b+" highcharts-series-"+this.index+" highcharts-"+this.type+"-series "+(w(this.colorIndex)?"highcharts-color-"+ +this.colorIndex+" ":"")+(this.options.className||"")+(g.hasClass("highcharts-tracker")?" highcharts-tracker":""),!0);g.attr({visibility:c})[k?"attr":"animate"](this.getPlotBox());return g},getPlotBox:function(){var a=this.chart,b=this.xAxis,c=this.yAxis;a.inverted&&(b=c,c=this.xAxis);return{translateX:b?b.left:a.plotLeft,translateY:c?c.top:a.plotTop,scaleX:1,scaleY:1}},render:function(){var a=this,b=a.chart,c,d=a.options,e=!!a.animate&&b.renderer.isSVG&&D(d.animation).duration,k=a.visible?"inherit": +"hidden",h=d.zIndex,f=a.hasRendered,m=b.seriesGroup,l=b.inverted;c=a.plotGroup("group","series",k,h,m);a.markerGroup=a.plotGroup("markerGroup","markers",k,h,m);e&&a.animate(!0);c.inverted=a.isCartesian?l:!1;a.drawGraph&&(a.drawGraph(),a.applyZones());a.drawDataLabels&&a.drawDataLabels();a.visible&&a.drawPoints();a.drawTracker&&!1!==a.options.enableMouseTracking&&a.drawTracker();a.invertGroups(l);!1===d.clip||a.sharedClipKey||f||c.clip(b.clipRect);e&&a.animate();f||(a.animationTimeout=C(function(){a.afterAnimate()}, +e));a.isDirty=!1;a.hasRendered=!0},redraw:function(){var a=this.chart,b=this.isDirty||this.isDirtyData,c=this.group,d=this.xAxis,e=this.yAxis;c&&(a.inverted&&c.attr({width:a.plotWidth,height:a.plotHeight}),c.animate({translateX:I(d&&d.left,a.plotLeft),translateY:I(e&&e.top,a.plotTop)}));this.translate();this.render();b&&delete this.kdTree},kdAxisArray:["clientX","plotY"],searchPoint:function(a,b){var c=this.xAxis,d=this.yAxis,e=this.chart.inverted;return this.searchKDTree({clientX:e?c.len-a.chartY+ +c.pos:a.chartX-c.pos,plotY:e?d.len-a.chartX+d.pos:a.chartY-d.pos},b)},buildKDTree:function(){function a(c,d,e){var g,k;if(k=c&&c.length)return g=b.kdAxisArray[d%e],c.sort(function(a,b){return a[g]-b[g]}),k=Math.floor(k/2),{point:c[k],left:a(c.slice(0,k),d+1,e),right:a(c.slice(k+1),d+1,e)}}this.buildingKdTree=!0;var b=this,c=-1l?"left":"right";t=0>l?"right":"left";b[q]&&(q=c(a,b[q],g+1,f),n=q[h]x;)q--;this.updateParallelArrays(m,"splice",q,0,0);this.updateParallelArrays(m,q);g&&m.name&&(g[x]=m.name);l.splice(q,0,a);n&&(this.data.splice(q,0,null),this.processData());"point"===e.legendType&&this.generatePoints();c&&(h[0]&&h[0].remove?h[0].remove(!1):(h.shift(),this.updateParallelArrays(m,"shift"),l.shift()));this.isDirtyData=this.isDirty=!0;b&&f.redraw(d)},removePoint:function(a,b,c){var d=this,e=d.data,h=e[a],f=d.points,g=d.chart,l=function(){f&&f.length===e.length&& +f.splice(a,1);e.splice(a,1);d.options.data.splice(a,1);d.updateParallelArrays(h||{series:d},"splice",a,1);h&&h.destroy();d.isDirty=!0;d.isDirtyData=!0;b&&g.redraw()};x(c,g);b=k(b,!0);h?h.firePointEvent("remove",null,l):l()},remove:function(a,b,c){function d(){e.destroy();h.isDirtyLegend=h.isDirtyBox=!0;h.linkSeries();k(a,!0)&&h.redraw(b)}var e=this,h=e.chart;!1!==c?u(e,"remove",null,d):d()},update:function(a,b){var d=this,e=d.chart,h=d.userOptions,f=d.oldType||d.type,l=a.type||h.type||e.options.chart.type, +g=I[f].prototype,m,n=["group","markerGroup","dataLabelsGroup"],t=["navigatorSeries","baseSeries"],x=d.finishedAnimating&&{animation:!1};if(Object.keys&&"data"===Object.keys(a).toString())return this.setData(a.data,b);t=n.concat(t);r(t,function(a){t[a]=d[a];delete d[a]});a=c(h,x,{index:d.index,pointStart:d.xData[0]},{data:d.options.data},a);d.remove(!1,null,!1);for(m in g)d[m]=void 0;w(d,I[l||f].prototype);r(t,function(a){d[a]=t[a]});d.init(e,a);a.zIndex!==h.zIndex&&r(n,function(b){d[b]&&d[b].attr({zIndex:a.zIndex})}); +d.oldType=f;e.linkSeries();k(b,!0)&&e.redraw(!1)}});w(H.prototype,{update:function(a,b){var d=this.chart;a=d.options[this.coll][this.options.index]=c(this.userOptions,a);this.destroy(!0);this.init(d,w(a,{events:void 0}));d.isDirtyBox=!0;k(b,!0)&&d.redraw()},remove:function(a){for(var b=this.chart,c=this.coll,e=this.series,h=e.length;h--;)e[h]&&e[h].remove(!1);n(b.axes,this);n(b[c],this);d(b.options[c])?b.options[c].splice(this.options.index,1):delete b.options[c];r(b[c],function(a,b){a.options.index= +b});this.destroy();b.isDirtyBox=!0;k(a,!0)&&b.redraw()},setTitle:function(a,b){this.update({title:a},b)},setCategories:function(a,b){this.update({categories:a},b)}})})(M);(function(a){var E=a.color,D=a.each,H=a.map,p=a.pick,f=a.Series,l=a.seriesType;l("area","line",{softThreshold:!1,threshold:0},{singleStacks:!1,getStackPoints:function(f){var l=[],r=[],u=this.xAxis,e=this.yAxis,h=e.stacks[this.stackKey],m={},d=this.index,c=e.series,b=c.length,k,z=p(e.options.reversedStacks,!0)?1:-1,B;f=f||this.points; +if(this.options.stacking){for(B=0;Ba&&w>l?(w=Math.max(a,l),e=2*l-w):wp&&e>l?(e=Math.max(p,l),w=2*l-e):e=Math.abs(h)&&.5a.closestPointRange*a.xAxis.transA,d=a.borderWidth=r(f.borderWidth,d?0:1),c=a.yAxis,b=f.threshold,k=a.translatedThreshold=c.getThreshold(b),l=r(f.minPointLength,5),p=a.getColumnMetrics(),u=p.width,x=a.barW=Math.max(u,1+2*d),w=a.pointXOffset=p.offset;h.inverted&&(k-=.5);f.pointPadding&&(x=Math.ceil(x));n.prototype.translate.apply(a);H(a.points,function(d){var e=r(d.yBottom,k),f=999+Math.abs(e),f=Math.min(Math.max(-f,d.plotY),c.len+f),m=d.plotX+w,n=x,t=Math.min(f,e),p,g=Math.max(f,e)-t;l&& +Math.abs(g)l?e-l:k-(p?l:0));d.barX=m;d.pointWidth=u;d.tooltipPos=h.inverted?[c.len+c.pos-h.plotLeft-f,a.xAxis.len-m-n/2,g]:[m+n/2,f+c.pos-h.plotTop,g];d.shapeType="rect";d.shapeArgs=a.crispCol.apply(a,d.isNull?[m,k,n,0]:[m,t,n,g])})},getSymbol:a.noop,drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,drawGraph:function(){this.group[this.dense?"addClass":"removeClass"]("highcharts-dense-data")}, +pointAttribs:function(a,f){var e=this.options,d,c=this.pointAttrToOptions||{};d=c.stroke||"borderColor";var b=c["stroke-width"]||"borderWidth",k=a&&a.color||this.color,h=a&&a[d]||e[d]||this.color||k,n=a&&a[b]||e[b]||this[b]||0,c=e.dashStyle;a&&this.zones.length&&(k=a.getZone(),k=a.options.color||k&&k.color||this.color);f&&(a=l(e.states[f],a.options.states&&a.options.states[f]||{}),f=a.brightness,k=a.color||void 0!==f&&D(k).brighten(a.brightness).get()||k,h=a[d]||h,n=a[b]||n,c=a.dashStyle||c);d={fill:k, +stroke:h,"stroke-width":n};c&&(d.dashstyle=c);return d},drawPoints:function(){var a=this,h=this.chart,m=a.options,d=h.renderer,c=m.animationLimit||250,b;H(a.points,function(e){var k=e.graphic;if(f(e.plotY)&&null!==e.y){b=e.shapeArgs;if(k)k[h.pointCounte;++e)h=w[e],a=2>e||2===e&&/%$/.test(h),w[e]=p(h,[n,l,u,w[2]][e])+(a?r:0);w[3]>w[2]&&(w[3]=w[2]);return w},getStartAndEndRadians:function(a,l){a=D(a)?a:0;l=D(l)&&l>a&&360>l-a?l:a+360;return{start:E*(a+-90),end:E*(l+-90)}}}})(M);(function(a){var E=a.addEvent,D=a.CenteredSeriesMixin,H=a.defined,p=a.each,f=a.extend,l=D.getStartAndEndRadians,r=a.inArray,n=a.noop,w=a.pick,u=a.Point,e=a.Series,h=a.seriesType,m=a.setAnimation;h("pie","line",{center:[null,null],clip:!1,colorByPoint:!0,dataLabels:{distance:30, +enabled:!0,formatter:function(){return this.point.isNull?void 0:this.point.name},x:0},ignoreHiddenPoint:!0,legendType:"point",marker:null,size:null,showInLegend:!1,slicedOffset:10,stickyTracking:!1,tooltip:{followPointer:!0},borderColor:"#ffffff",borderWidth:1,states:{hover:{brightness:.1,shadow:!1}}},{isCartesian:!1,requireSorting:!1,directTouch:!0,noSharedTooltip:!0,trackerGroups:["group","dataLabelsGroup"],axisTypes:[],pointAttribs:a.seriesTypes.column.prototype.pointAttribs,animate:function(a){var c= +this,b=c.points,d=c.startAngleRad;a||(p(b,function(a){var b=a.graphic,e=a.shapeArgs;b&&(b.attr({r:a.startR||c.center[3]/2,start:d,end:d}),b.animate({r:e.r,start:e.start,end:e.end},c.options.animation))}),c.animate=null)},updateTotals:function(){var a,c=0,b=this.points,e=b.length,f,h=this.options.ignoreHiddenPoint;for(a=0;a1.5*Math.PI?m-=2*Math.PI:m<-Math.PI/2&&(m+=2*Math.PI);G.slicedTranslation={translateX:Math.round(Math.cos(m)*d),translateY:Math.round(Math.sin(m)*d)};h=Math.cos(m)*a[2]/ +2;u=Math.sin(m)*a[2]/2;G.tooltipPos=[a[0]+.7*h,a[1]+.7*u];G.half=m<-Math.PI/2||m>Math.PI/2?1:0;G.angle=m;f=Math.min(e,G.labelDistance/5);G.labelPos=[a[0]+h+Math.cos(m)*G.labelDistance,a[1]+u+Math.sin(m)*G.labelDistance,a[0]+h+Math.cos(m)*f,a[1]+u+Math.sin(m)*f,a[0]+h,a[1]+u,0>G.labelDistance?"center":G.half?"right":"left",m]}},drawGraph:null,drawPoints:function(){var a=this,c=a.chart.renderer,b,e,h,l,m=a.options.shadow;m&&!a.shadowGroup&&(a.shadowGroup=c.g("shadow").add(a.group));p(a.points,function(d){e= +d.graphic;if(d.isNull)e&&(d.graphic=e.destroy());else{l=d.shapeArgs;b=d.getTranslate();var k=d.shadowGroup;m&&!k&&(k=d.shadowGroup=c.g("shadow").add(a.shadowGroup));k&&k.attr(b);h=a.pointAttribs(d,d.selected&&"select");e?e.setRadialReference(a.center).attr(h).animate(f(l,b)):(d.graphic=e=c[d.shapeType](l).setRadialReference(a.center).attr(b).add(a.group),d.visible||e.attr({visibility:"hidden"}),e.attr(h).attr({"stroke-linejoin":"round"}).shadow(m,k));e.addClass(d.getClassName())}})},searchPoint:n, +sortByAngle:function(a,c){a.sort(function(a,d){return void 0!==a.angle&&(d.angle-a.angle)*c})},drawLegendSymbol:a.LegendSymbolMixin.drawRectangle,getCenter:D.getCenter,getSymbol:n},{init:function(){u.prototype.init.apply(this,arguments);var a=this,c;a.name=w(a.name,"Slice");c=function(b){a.slice("select"===b.type)};E(a,"select",c);E(a,"unselect",c);return a},isValid:function(){return a.isNumber(this.y,!0)&&0<=this.y},setVisible:function(a,c){var b=this,d=b.series,e=d.chart,f=d.options.ignoreHiddenPoint; +c=w(c,f);a!==b.visible&&(b.visible=b.options.visible=a=void 0===a?!b.visible:a,d.options.data[r(b,d.data)]=b.options,p(["graphic","dataLabel","connector","shadowGroup"],function(c){if(b[c])b[c][a?"show":"hide"](!0)}),b.legendItem&&e.legend.colorizeItem(b,a),a||"hover"!==b.state||b.setState(""),f&&(d.isDirty=!0),c&&e.redraw())},slice:function(a,c,b){var d=this.series;m(b,d.chart);w(c,!0);this.sliced=this.options.sliced=H(a)?a:!this.sliced;d.options.data[r(this,d.data)]=this.options;this.graphic.animate(this.getTranslate()); +this.shadowGroup&&this.shadowGroup.animate(this.getTranslate())},getTranslate:function(){return this.sliced?this.slicedTranslation:{translateX:0,translateY:0}},haloPath:function(a){var c=this.shapeArgs;return this.sliced||!this.visible?[]:this.series.chart.renderer.symbols.arc(c.x,c.y,c.r+a,c.r+a,{innerR:this.shapeArgs.r-1,start:c.start,end:c.end})}})})(M);(function(a){var E=a.addEvent,D=a.arrayMax,H=a.defined,p=a.each,f=a.extend,l=a.format,r=a.map,n=a.merge,w=a.noop,u=a.pick,e=a.relativeLength,h= +a.Series,m=a.seriesTypes,d=a.stableSort;a.distribute=function(a,b){function c(a,b){return a.target-b.target}var e,f=!0,h=a,l=[],m;m=0;for(e=a.length;e--;)m+=a[e].size;if(m>b){d(a,function(a,b){return(b.rank||0)-(a.rank||0)});for(m=e=0;m<=b;)m+=a[e].size,e++;l=a.splice(e-1,a.length)}d(a,c);for(a=r(a,function(a){return{size:a.size,targets:[a.target],align:u(a.align,.5)}});f;){for(e=a.length;e--;)f=a[e],m=(Math.min.apply(0,f.targets)+Math.max.apply(0,f.targets))/2,f.pos=Math.min(Math.max(0,m-f.size* +f.align),b-f.size);e=a.length;for(f=!1;e--;)0a[e].pos&&(a[e-1].size+=a[e].size,a[e-1].targets=a[e-1].targets.concat(a[e].targets),a[e-1].align=.5,a[e-1].pos+a[e-1].size>b&&(a[e-1].pos=b-a[e-1].size),a.splice(e,1),f=!0)}e=0;p(a,function(a){var b=0;p(a.targets,function(){h[e].pos=a.pos+b;b+=h[e].size;e++})});h.push.apply(h,l);d(h,c)};h.prototype.drawDataLabels=function(){function c(a,b){var c=b.filter;return c?(b=c.operator,a=a[c.property],c=c.value,"\x3e"===b&&a>c||"\x3c"=== +b&&a=c||"\x3c\x3d"===b&&a<=c||"\x3d\x3d"===b&&a==c||"\x3d\x3d\x3d"===b&&a===c?!0:!1):!0}var b=this,d=b.options,e=d.dataLabels,f=b.points,h,m,r=b.hasRendered||0,t,w,D=u(e.defer,!!d.animation),q=b.chart.renderer;if(e.enabled||b._hasPointLabels)b.dlProcessOptions&&b.dlProcessOptions(e),w=b.plotGroup("dataLabelsGroup","data-labels",D&&!r?"hidden":"visible",e.zIndex||6),D&&(w.attr({opacity:+r}),r||E(b,"afterAnimate",function(){b.visible&&w.show(!0);w[d.animation?"animate":"attr"]({opacity:1}, +{duration:200})})),m=e,p(f,function(f){var k,p=f.dataLabel,g,x,r=f.connector,z=!p,C;h=f.dlOptions||f.options&&f.options.dataLabels;(k=u(h&&h.enabled,m.enabled)&&!f.isNull)&&(k=!0===c(f,h||e));k&&(e=n(m,h),g=f.getLabelConfig(),C=e[f.formatPrefix+"Format"]||e.format,t=H(C)?l(C,g):(e[f.formatPrefix+"Formatter"]||e.formatter).call(g,e),C=e.style,g=e.rotation,C.color=u(e.color,C.color,b.color,"#000000"),"contrast"===C.color&&(f.contrastColor=q.getContrast(f.color||b.color),C.color=e.inside||0>u(f.labelDistance, +e.distance)||d.stacking?f.contrastColor:"#000000"),d.cursor&&(C.cursor=d.cursor),x={fill:e.backgroundColor,stroke:e.borderColor,"stroke-width":e.borderWidth,r:e.borderRadius||0,rotation:g,padding:e.padding,zIndex:1},a.objectEach(x,function(a,b){void 0===a&&delete x[b]}));!p||k&&H(t)?k&&H(t)&&(p?x.text=t:(p=f.dataLabel=g?q.text(t,0,-9999).addClass("highcharts-data-label"):q.label(t,0,-9999,e.shape,null,null,e.useHTML,null,"data-label"),p.addClass(" highcharts-data-label-color-"+f.colorIndex+" "+(e.className|| +"")+(e.useHTML?"highcharts-tracker":""))),p.attr(x),p.css(C).shadow(e.shadow),p.added||p.add(w),b.alignDataLabel(f,p,e,null,z)):(f.dataLabel=p=p.destroy(),r&&(f.connector=r.destroy()))})};h.prototype.alignDataLabel=function(a,b,d,e,h){var c=this.chart,k=c.inverted,l=u(a.dlBox&&a.dlBox.centerX,a.plotX,-9999),m=u(a.plotY,-9999),n=b.getBBox(),p,q=d.rotation,r=d.align,w=this.visible&&(a.series.forceDL||c.isInsidePlot(l,Math.round(m),k)||e&&c.isInsidePlot(l,k?e.x+1:e.y+e.height-1,k)),z="justify"===u(d.overflow, +"justify");if(w&&(p=d.style.fontSize,p=c.renderer.fontMetrics(p,b).b,e=f({x:k?this.yAxis.len-m:l,y:Math.round(k?this.xAxis.len-l:m),width:0,height:0},e),f(d,{width:n.width,height:n.height}),q?(z=!1,l=c.renderer.rotCorr(p,q),l={x:e.x+d.x+e.width/2+l.x,y:e.y+d.y+{top:0,middle:.5,bottom:1}[d.verticalAlign]*e.height},b[h?"attr":"animate"](l).attr({align:r}),m=(q+720)%360,m=180m,"left"===r?l.y-=m?n.height:0:"center"===r?(l.x-=n.width/2,l.y-=n.height/2):"right"===r&&(l.x-=n.width,l.y-=m?0:n.height)): +(b.align(d,null,e),l=b.alignAttr),z?a.isLabelJustified=this.justifyDataLabel(b,d,l,n,e,h):u(d.crop,!0)&&(w=c.isInsidePlot(l.x,l.y)&&c.isInsidePlot(l.x+n.width,l.y+n.height)),d.shape&&!q))b[h?"attr":"animate"]({anchorX:k?c.plotWidth-a.plotY:a.plotX,anchorY:k?c.plotHeight-a.plotX:a.plotY});w||(b.attr({y:-9999}),b.placed=!1)};h.prototype.justifyDataLabel=function(a,b,d,e,f,h){var c=this.chart,k=b.align,l=b.verticalAlign,m,n,p=a.box?0:a.padding||0;m=d.x+p;0>m&&("right"===k?b.align="left":b.x=-m,n=!0); +m=d.x+e.width-p;m>c.plotWidth&&("left"===k?b.align="right":b.x=c.plotWidth-m,n=!0);m=d.y+p;0>m&&("bottom"===l?b.verticalAlign="top":b.y=-m,n=!0);m=d.y+e.height-p;m>c.plotHeight&&("top"===l?b.verticalAlign="bottom":b.y=c.plotHeight-m,n=!0);n&&(a.placed=!h,a.align(b,null,f));return n};m.pie&&(m.pie.prototype.drawDataLabels=function(){var c=this,b=c.data,d,e=c.chart,f=c.options.dataLabels,l=u(f.connectorPadding,10),m=u(f.connectorWidth,1),n=e.plotWidth,t=e.plotHeight,r,w=c.center,q=w[2]/2,A=w[1],F,G, +g,v,E=[[],[]],L,P,J,M,y=[0,0,0,0];c.visible&&(f.enabled||c._hasPointLabels)&&(p(b,function(a){a.dataLabel&&a.visible&&a.dataLabel.shortened&&(a.dataLabel.attr({width:"auto"}).css({width:"auto",textOverflow:"clip"}),a.dataLabel.shortened=!1)}),h.prototype.drawDataLabels.apply(c),p(b,function(a){a.dataLabel&&a.visible&&(E[a.half].push(a),a.dataLabel._pos=null)}),p(E,function(b,h){var k,m,x=b.length,r=[],z;if(x)for(c.sortByAngle(b,h-.5),0d.bottom-2?k:P,h,d),F._attr={visibility:J,align:g[6]},F._pos={x:L+f.x+({left:l,right:-l}[g[6]]||0),y:P+f.y-10},g.x=L,g.y=P,u(f.crop,!0)&&(G=F.getBBox().width,k=null,L-Gn-l&&(k=Math.round(L+G-n+l),y[1]=Math.max(k,y[1])),0>P-v/2?y[0]=Math.max(Math.round(-P+v/2),y[0]):P+v/2>t&&(y[2]=Math.max(Math.round(P+v/2-t),y[2])),F.sideOverflow=k)}),0===D(y)||this.verifyDataLabelOverflow(y))&&(this.placeDataLabels(), +m&&p(this.points,function(a){var b;r=a.connector;if((F=a.dataLabel)&&F._pos&&a.visible&&0u(this.translatedThreshold,k.yAxis.len)),p=u(d.inside,!!this.options.stacking);l&&(e=n(l),0>e.y&&(e.height+=e.y,e.y=0),l=e.y+e.height-k.yAxis.len,0a+c||e+hb+d||f+lthis.pointCount))},pan:function(a,b){var c=this,d=c.hoverPoints,e;d&&r(d,function(a){a.setState()});r("xy"===b?[1,0]:[1],function(b){b= +c[b?"xAxis":"yAxis"][0];var d=b.horiz,f=a[d?"chartX":"chartY"],d=d?"mouseDownX":"mouseDownY",h=c[d],g=(b.pointRange||0)/2,k=b.getExtremes(),l=b.toValue(h-f,!0)+g,m=b.toValue(h+b.len-f,!0)-g,n=m=l(n.minWidth,0)&&this.chartHeight>=l(n.minHeight,0)}).call(this)&&f.push(a._id)};E.prototype.currentOptions=function(l){function n(e,h,l,d){var c;a.objectEach(e,function(a,e){if(!d&&-1 Date: Fri, 4 Jan 2019 09:24:41 +0000 Subject: [PATCH 260/267] Bump jsonapi-resources from 0.9.3 to 0.9.4 Bumps [jsonapi-resources](https://github.com/cerebris/jsonapi-resources) from 0.9.3 to 0.9.4. - [Release notes](https://github.com/cerebris/jsonapi-resources/releases) - [Commits](https://github.com/cerebris/jsonapi-resources/compare/v0.9.3...v0.9.4) Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 90f82ad2e..eff940a2d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -221,7 +221,7 @@ GEM httparty (0.16.3) mime-types (~> 3.0) multi_xml (>= 0.5.2) - i18n (1.3.0) + i18n (1.4.0) concurrent-ruby (~> 1.0) i18n-tasks (0.9.28) activesupport (>= 4.0.2) @@ -244,7 +244,7 @@ GEM railties (>= 3.2) sprockets-rails json (2.1.0) - jsonapi-resources (0.9.3) + jsonapi-resources (0.9.4) activerecord (>= 4.1) concurrent-ruby railties (>= 4.1) From cecc032dee5eaa3d03e11b8ad14877aa12e86363 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Fri, 4 Jan 2019 10:12:16 +0000 Subject: [PATCH 261/267] Bump chartkick from 3.0.1 to 3.0.2 Bumps [chartkick](https://github.com/ankane/chartkick) from 3.0.1 to 3.0.2. - [Release notes](https://github.com/ankane/chartkick/releases) - [Changelog](https://github.com/ankane/chartkick/blob/master/CHANGELOG.md) - [Commits](https://github.com/ankane/chartkick/compare/v3.0.1...v3.0.2) Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index eff940a2d..52f222fc7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -94,7 +94,7 @@ GEM capybara-screenshot (1.0.22) capybara (>= 1.0, < 4) launchy - chartkick (3.0.1) + chartkick (3.0.2) childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) cliver (0.3.2) From de8eba738e813cf6c20b8b02ab8a8cfd5128202f Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sat, 5 Jan 2019 19:44:40 +1300 Subject: [PATCH 262/267] Fix modified schema deploy error --- db/schema.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/schema.rb b/db/schema.rb index 6640ce490..9878cdb86 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180401220637) do +ActiveRecord::Schema.define(version: 2018_04_01_220637) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" From 798b4a8b47de50ea1752b18a150472b4eadf35e2 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 6 Jan 2019 08:57:57 +1300 Subject: [PATCH 263/267] Switching to yarn --- package-lock.json | 1380 ------------------------------------- script/install_linters.sh | 2 +- yarn.lock | 1052 ++++++++++++++++++++++++++++ 3 files changed, 1053 insertions(+), 1381 deletions(-) delete mode 100644 package-lock.json create mode 100644 yarn.lock diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 0aebca689..000000000 --- a/package-lock.json +++ /dev/null @@ -1,1380 +0,0 @@ -{ - "name": "growstuff", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "acorn": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", - "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==", - "dev": true - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", - "dev": true - }, - "ansi-escapes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.1.0", - "escape-string-regexp": "^1.0.5", - "supports-color": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", - "dev": true, - "requires": { - "has-flag": "^2.0.0" - } - } - } - }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", - "dev": true - }, - "cli": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", - "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", - "dev": true, - "requires": { - "exit": "0.1.2", - "glob": "^7.1.1" - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "clone": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", - "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=", - "dev": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "coffeelint": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/coffeelint/-/coffeelint-2.0.7.tgz", - "integrity": "sha1-lg/VuXVrhFGU6fl6R1bmKGEha3Q=", - "dev": true, - "requires": { - "coffeescript": "~2.0.x", - "glob": "^7.0.6", - "ignore": "^3.0.9", - "optimist": "^0.6.1", - "resolve": "^0.6.3", - "strip-json-comments": "^1.0.2" - } - }, - "coffeescript": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.0.3.tgz", - "integrity": "sha1-dg8Cck9fCRG+fO+jSo4OEMXYUSo=", - "dev": true - }, - "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", - "dev": true, - "requires": { - "color-name": "^1.1.1" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "csslint": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/csslint/-/csslint-1.0.5.tgz", - "integrity": "sha1-Gcw+2jIhYP0/cjKvHLKjYOiYouk=", - "dev": true, - "requires": { - "clone": "~2.1.0", - "parserlib": "~1.1.1" - } - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "requires": { - "globby": "^5.0.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "rimraf": "^2.2.8" - } - }, - "doctrine": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.2.tgz", - "integrity": "sha512-y0tm5Pq6ywp3qSTZ1vPgVdAnbDEoeoc5wlOHXoY1c4Wug/a7JvqHIl7BTvwodaHmejWkK/9dSb3sCYfyo/om8A==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, - "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", - "dev": true - } - } - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true - }, - "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", - "dev": true, - "requires": { - "domelementtype": "1" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.14.0.tgz", - "integrity": "sha512-Ul6CSGRjKscEyg0X/EeNs7o2XdnbTEOD1OM8cTjmx85RPcBJQrEhZLevhuJZNAE/vS2iVl5Uhgiqf3h5uLMCJQ==", - "dev": true, - "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", - "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.0.2", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.2", - "esquery": "^1.0.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", - "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "^4.0.1", - "text-table": "~0.2.0" - }, - "dependencies": { - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - } - } - }, - "eslint-config-google": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.9.1.tgz", - "integrity": "sha512-5A83D+lH0PA81QMESKbLJd/a3ic8tPZtwUmqNrxMRo54nfFaUvtt89q/+icQ+fd66c2xQHn0KyFkzJDoAUfpZA==", - "dev": true - }, - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha1-PzGA+y4pEBdxastMnW1bXDSmqB0=", - "dev": true - }, - "espree": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", - "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", - "dev": true, - "requires": { - "acorn": "^5.2.1", - "acorn-jsx": "^3.0.0" - } - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", - "dev": true - }, - "esquery": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", - "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", - "dev": true, - "requires": { - "estraverse": "^4.1.0", - "object-assign": "^4.0.1" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, - "external-editor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", - "integrity": "sha1-PQJqIbf5W1cmOH1CAKwWDTcsO0g=", - "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - } - }, - "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "flat-cache": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", - "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", - "dev": true, - "requires": { - "circular-json": "^0.3.1", - "del": "^2.0.2", - "graceful-fs": "^4.1.2", - "write": "^0.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "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" - } - }, - "globals": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.1.0.tgz", - "integrity": "sha512-uEuWt9mqTlPDwSqi+sHjD4nWU/1N+q0fiWI9T1mZpD2UENqX20CFD5T/ziLZvztPaBKl7ZylUi1q6Qfm7E2CiQ==", - "dev": true - }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", - "dev": true - }, - "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", - "dev": true, - "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=", - "dev": true - }, - "ignore": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", - "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true, - "requires": { - "is-path-inside": "^1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-resolvable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.1.tgz", - "integrity": "sha512-y5CXYbzvB3jTnWAZH1Nl7ykUWb6T3BcTs56HUruwBf8MhF56n1HWqhDWnVFo8GHrUPDgvUUNVhrc2U8W7iqz5g==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jshint": { - "version": "2.9.5", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.5.tgz", - "integrity": "sha1-HnJSkVzmgbQIJ+4UJIxG006apiw=", - "dev": true, - "requires": { - "cli": "~1.0.0", - "console-browserify": "1.1.x", - "exit": "0.1.x", - "htmlparser2": "3.8.x", - "lodash": "3.7.x", - "minimatch": "~3.0.2", - "shelljs": "0.3.x", - "strip-json-comments": "1.0.x" - }, - "dependencies": { - "lodash": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz", - "integrity": "sha1-Nni9irmVBXwHreg27S7wh9qBHUU=", - "dev": true - }, - "shelljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", - "dev": true - } - } - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "mimic-fn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - }, - "dependencies": { - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - } - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "parserlib": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/parserlib/-/parserlib-1.1.1.tgz", - "integrity": "sha1-pkz6ckBiQ0/fw1HJpOwtkrlMBvQ=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "progress": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", - "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", - "dev": true, - "requires": { - "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" - } - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, - "resolve": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz", - "integrity": "sha1-3ZV5gufnNt699TtYpN2RdUV13UY=", - "dev": true - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, - "requires": { - "rx-lite": "*" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", - "dev": true - }, - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - } - } - }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true, - "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } -} diff --git a/script/install_linters.sh b/script/install_linters.sh index 159aaa05e..0cfce4486 100755 --- a/script/install_linters.sh +++ b/script/install_linters.sh @@ -2,7 +2,7 @@ if [ "${STATIC_CHECKS}" = "true" ]; then set -euv - npm install; + yarn install; gem install --update overcommit haml-lint bundler-audit; diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..98460c8ce --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1052 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= + dependencies: + acorn "^3.0.4" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= + +acorn@^5.5.0: + version "5.7.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" + integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== + +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= + +ajv@^5.2.3, ajv@^5.3.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ansi-escapes@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.1.0.tgz#f73207bb81207d75fd6c83f125af26eea378ca30" + integrity sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw== + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +babel-code-frame@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.1.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chardet@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" + integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + +cli@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cli/-/cli-1.0.1.tgz#22817534f24bfa4950c34d532d48ecbc621b8c14" + integrity sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ= + dependencies: + exit "0.1.2" + glob "^7.1.1" + +clone@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + +coffeelint@^2.0.7: + version "2.1.0" + resolved "https://registry.yarnpkg.com/coffeelint/-/coffeelint-2.1.0.tgz#af65df3634e999d9ac01480736c36d3cd2f5dad8" + integrity sha1-r2XfNjTpmdmsAUgHNsNtPNL12tg= + dependencies: + coffeescript "^2.1.0" + glob "^7.0.6" + ignore "^3.0.9" + optimist "^0.6.1" + resolve "^0.6.3" + strip-json-comments "^1.0.2" + +coffeescript@^2.1.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/coffeescript/-/coffeescript-2.3.2.tgz#e854a7020dfe47b7cf4dd412042e32ef1e269810" + integrity sha512-YObiFDoukx7qPBi/K0kUKyntEZDfBQiqs/DbrR1xzASKOBjGT7auD85/DiPeRr9k++lRj7l3uA9TNMLfyfcD/Q== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +console-browserify@1.1.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA= + dependencies: + date-now "^0.1.4" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +csslint@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/csslint/-/csslint-1.0.5.tgz#19cc3eda322160fd3f7232af1cb2a360e898a2e9" + integrity sha1-Gcw+2jIhYP0/cjKvHLKjYOiYouk= + dependencies: + clone "~2.1.0" + parserlib "~1.1.1" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= + +debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII= + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domelementtype@1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs= + +domhandler@2.3: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.3.0.tgz#2de59a0822d5027fabff6f032c2b25a2a8abe738" + integrity sha1-LeWaCCLVAn+r/28DLCsloqir5zg= + dependencies: + domelementtype "1" + +domutils@1.5: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= + dependencies: + dom-serializer "0" + domelementtype "1" + +entities@1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" + integrity sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY= + +entities@~1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-config-google@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/eslint-config-google/-/eslint-config-google-0.9.1.tgz#83353c3dba05f72bb123169a4094f4ff120391eb" + integrity sha512-5A83D+lH0PA81QMESKbLJd/a3ic8tPZtwUmqNrxMRo54nfFaUvtt89q/+icQ+fd66c2xQHn0KyFkzJDoAUfpZA== + +eslint-scope@^3.7.1: + version "3.7.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" + integrity sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-visitor-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== + +eslint@^4.14.0: + version "4.19.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" + integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== + dependencies: + ajv "^5.3.0" + babel-code-frame "^6.22.0" + chalk "^2.1.0" + concat-stream "^1.6.0" + cross-spawn "^5.1.0" + debug "^3.1.0" + doctrine "^2.1.0" + eslint-scope "^3.7.1" + eslint-visitor-keys "^1.0.0" + espree "^3.5.4" + esquery "^1.0.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.0.1" + ignore "^3.3.3" + imurmurhash "^0.1.4" + inquirer "^3.0.6" + is-resolvable "^1.0.0" + js-yaml "^3.9.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^7.0.0" + progress "^2.0.0" + regexpp "^1.0.1" + require-uncached "^1.0.3" + semver "^5.3.0" + strip-ansi "^4.0.0" + strip-json-comments "~2.0.1" + table "4.0.2" + text-table "~0.2.0" + +espree@^3.5.4: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" + integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== + dependencies: + acorn "^5.5.0" + acorn-jsx "^3.0.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM= + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs= + +exit@0.1.2, exit@0.1.x: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + +external-editor@^2.0.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" + integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== + dependencies: + chardet "^0.4.0" + iconv-lite "^0.4.17" + tmp "^0.0.33" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +flat-cache@^1.2.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" + integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== + dependencies: + circular-json "^0.3.1" + graceful-fs "^4.1.2" + rimraf "~2.6.2" + write "^0.2.1" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +glob@^7.0.6, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + 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" + +globals@^11.0.1: + version "11.9.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.9.0.tgz#bde236808e987f290768a93d065060d78e6ab249" + integrity sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg== + +graceful-fs@^4.1.2: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +htmlparser2@3.8.x: + version "3.8.3" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.8.3.tgz#996c28b191516a8be86501a7d79757e5c70c1068" + integrity sha1-mWwosZFRaovoZQGn15dX5ccMEGg= + dependencies: + domelementtype "1" + domhandler "2.3" + domutils "1.5" + entities "1.0" + readable-stream "1.1" + +iconv-lite@^0.4.17: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore@^3.0.9, ignore@^3.3.3: + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +inquirer@^3.0.6: + version "3.3.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" + integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + +js-yaml@^3.9.1: + version "3.12.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.1.tgz#295c8632a18a23e054cf5c9d3cecafe678167600" + integrity sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jshint@^2.9.4: + version "2.9.7" + resolved "https://registry.yarnpkg.com/jshint/-/jshint-2.9.7.tgz#038a3fa5c328fa3ab03ddfd85df88d3d87bedcbd" + integrity sha512-Q8XN38hGsVQhdlM+4gd1Xl7OB1VieSuCJf+fEJjpo59JH99bVJhXRXAh26qQ15wfdd1VPMuDWNeSWoNl53T4YA== + dependencies: + cli "~1.0.0" + console-browserify "1.1.x" + exit "0.1.x" + htmlparser2 "3.8.x" + lodash "~4.17.10" + minimatch "~3.0.2" + shelljs "0.3.x" + strip-json-comments "1.0.x" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lodash@^4.17.4, lodash@^4.3.0, lodash@~4.17.10: + version "4.17.11" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" + integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +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" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= + +mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +object-assign@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +parserlib@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/parserlib/-/parserlib-1.1.1.tgz#a64cfa724062434fdfc351c9a4ec2d92b94c06f4" + integrity sha1-pkz6ckBiQ0/fw1HJpOwtkrlMBvQ= + +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" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +readable-stream@1.1: + version "1.1.13" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" + integrity sha1-9u73ZPUUyJ4rniMUanW6EGdW0j4= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.2.2: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +regexpp@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" + integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== + +require-uncached@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= + +resolve@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46" + integrity sha1-3ZV5gufnNt699TtYpN2RdUV13UY= + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= + dependencies: + is-promise "^2.1.0" + +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^5.3.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shelljs@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" + integrity sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E= + +signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== + dependencies: + is-fullwidth-code-point "^2.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +string-width@^2.1.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-json-comments@1.0.x, strip-json-comments@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" + integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E= + +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" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +table@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" + integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== + dependencies: + ajv "^5.2.3" + ajv-keywords "^2.1.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= + dependencies: + mkdirp "^0.5.1" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= From 88ccdadeb1087737739cad92736cb0970d4c460b Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 6 Jan 2019 08:58:06 +1300 Subject: [PATCH 264/267] Tidy up .gitignore --- .gitignore | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index b09a40bc6..dfd273d9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,30 @@ -/log/* +.byebug_history +.bundle + +# Folders to ignore +/log /doc +/tmp +/vendor +/coverage +/public +/node_modules + +# Dev database (if they use sqlite) /db/*.sqlite3 -/tmp/* -coverage + +# Editor and file system droppings .pt .*.sw* *~ *.DS_Store +.idea/** + +# Dev config files config/application.yml config/database.yml -credentials*.sh -Pathogen: -custom_plan.rb -zeus.json -.bundle -.idea/** -public/** -node_modules \ No newline at end of file + +# Files that are created on Travis +cc-test-reporter +elasticsearch-*.deb +elasticsearch-*.deb.sha512 From 7c354c98725295711de2ff33b12d3b4e4cf0ab09 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 6 Jan 2019 09:53:25 +1300 Subject: [PATCH 265/267] Re-enable linters on Travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 20b9a58a0..d8959f060 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ env: matrix: - GROWSTUFF_ELASTICSEARCH=true RSPEC_TAG=elasticsearch COVERAGE=true - GROWSTUFF_ELASTICSEARCH=false RSPEC_TAG=~elasticsearch COVERAGE=false - # - STATIC_CHECKS=true + - STATIC_CHECKS=true global: - secure: "Z5TpM2jEX4UCvNePnk/LwltQX48U2u9BRc+Iypr1x9QW2o228QJhPIOH39a8RMUrepGnkQIq9q3ZRUn98RfrJz1yThtlNFL3NmzdQ57gKgjGwfpa0e4Dwj/ZJqV2D84tDGjvdVYLP7zzaYZxQcwk/cgNpzKf/jq97HLNP7CYuf4=" - GROWSTUFF_EMAIL="noreply@test.growstuff.org" @@ -19,7 +19,7 @@ before_install: - ./script/install_phantomjs.sh - export PATH=$PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64/bin:$PATH - ./script/install_codeclimate.sh - # - ./script/install_linters.sh + - ./script/install_linters.sh - VERSION="6.2.3" ./script/install_elasticsearch.sh before_script: - > From 97b377cf8343eb1ae5507c5e3a77190e83dab860 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 6 Jan 2019 16:17:34 +1300 Subject: [PATCH 266/267] Add --no-document to install of linters as suggested in https://github.com/brigade/overcommit/issues/610 --- script/install_linters.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/install_linters.sh b/script/install_linters.sh index 0cfce4486..ca51cd1cb 100755 --- a/script/install_linters.sh +++ b/script/install_linters.sh @@ -4,7 +4,7 @@ if [ "${STATIC_CHECKS}" = "true" ]; then set -euv yarn install; - gem install --update overcommit haml-lint bundler-audit; + gem install --update overcommit haml-lint bundler-audit --no-document; pip install --upgrade pip; pip install yamllint --user; From 99ac99b399b2f0ffbb49e20ba8b94a3d79dd43e7 Mon Sep 17 00:00:00 2001 From: Brenda Wallace Date: Sun, 6 Jan 2019 16:19:58 +1300 Subject: [PATCH 267/267] Can't update pip on travis, so don't --- script/install_linters.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/install_linters.sh b/script/install_linters.sh index ca51cd1cb..cfc91f2c8 100755 --- a/script/install_linters.sh +++ b/script/install_linters.sh @@ -6,7 +6,7 @@ if [ "${STATIC_CHECKS}" = "true" ]; then gem install --update overcommit haml-lint bundler-audit --no-document; - pip install --upgrade pip; + # pip install --upgrade pip; pip install yamllint --user; overcommit --install;