From e866605910191ecccad6b497a37ef3e0afecea11 Mon Sep 17 00:00:00 2001 From: Daniel Lee Date: Wed, 21 Nov 2018 02:07:46 +0100 Subject: [PATCH] convert to typescript and webpack --- .eslintignore | 2 - .eslintrc | 45 - .jshintrc | 38 - Gruntfile.js | 65 - dist/LICENSE | 21 + dist/clock_ctrl.js | 250 - dist/clock_ctrl.js.map | 1 - dist/css/clock-panel.css | 6 - dist/external/moment-duration-format.js | 1673 ----- dist/{src => }/img/clock_panel_logo.svg | 0 dist/{src => }/img/countdown1.png | Bin .../img/screenshot-clock-options.png | Bin dist/{src => }/img/screenshot-clocks.png | Bin dist/{src => }/img/screenshot-showcase.png | Bin dist/module.js | 36 +- dist/module.js.map | 2 +- dist/{ => partials}/module.html | 0 dist/{editor => partials}/options.html | 0 dist/{editor => partials}/refresh.html | 0 dist/plugin.json | 8 +- package.json | 44 +- src/{clock_ctrl.js => clock_ctrl.ts} | 87 +- src/{module.js => module.ts} | 0 src/{ => partials}/module.html | 0 src/{editor => partials}/options.html | 0 src/{editor => partials}/refresh.html | 0 plugin.json => src/plugin.json | 8 +- tsconfig.json | 23 + tslint.json | 58 + webpack.config.js | 75 + webpack.config.prod.js | 15 + yarn.lock | 6577 +++++++++++++++++ 32 files changed, 6874 insertions(+), 2160 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc delete mode 100644 .jshintrc delete mode 100644 Gruntfile.js create mode 100644 dist/LICENSE delete mode 100644 dist/clock_ctrl.js delete mode 100644 dist/clock_ctrl.js.map delete mode 100644 dist/css/clock-panel.css delete mode 100644 dist/external/moment-duration-format.js rename dist/{src => }/img/clock_panel_logo.svg (100%) rename dist/{src => }/img/countdown1.png (100%) rename dist/{src => }/img/screenshot-clock-options.png (100%) rename dist/{src => }/img/screenshot-clocks.png (100%) rename dist/{src => }/img/screenshot-showcase.png (100%) rename dist/{ => partials}/module.html (100%) rename dist/{editor => partials}/options.html (100%) rename dist/{editor => partials}/refresh.html (100%) rename src/{clock_ctrl.js => clock_ctrl.ts} (73%) rename src/{module.js => module.ts} (100%) rename src/{ => partials}/module.html (100%) rename src/{editor => partials}/options.html (100%) rename src/{editor => partials}/refresh.html (100%) rename plugin.json => src/plugin.json (72%) create mode 100644 tsconfig.json create mode 100644 tslint.json create mode 100644 webpack.config.js create mode 100644 webpack.config.prod.js create mode 100644 yarn.lock diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 3d1ae50..0000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -dist/* -src/external/* \ No newline at end of file diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index c311c57..0000000 --- a/.eslintrc +++ /dev/null @@ -1,45 +0,0 @@ -{ - "root": true, - "extends": "airbnb/base", - "env": { - "browser": true - }, - "parser": "babel-eslint", - "ecmaVersion": 6, - "rules": { - "array-bracket-spacing": 0, - "arrow-body-style": 0, - "comma-dangle": 0, // not sure why airbnb turned this on. gross! - "computed-property-spacing": 0, - "consistent-return": 0, - "id-length": [2, {"min": 2, "max": 30, "properties": "never", "exceptions": ["_", "t", "a", "b"]}], - "import/default": 0, - "import/named": 0, - "import/namespace": 0, - "import/no-duplicates": 0, - "import/no-named-as-default": 2, - "import/no-unresolved": 0, - "indent": [2, 2, {"SwitchCase": 1}], - "max-len": [0, 120, 2], - "no-alert": 0, - "no-console": 0, - "no-param-reassign": [2, {"props": false}], - "no-use-before-define": 0, // disabled until https://github.com/babel/babel-eslint/issues/249 is fixed - "object-curly-spacing": 0, - "object-shorthand": 0, - "prefer-arrow-callback": 0, - "prefer-template": 0, - "quote-props": [2, "consistent"] - }, - "plugins": [ - "import" - ], - "settings": { - "import/parser": "babel-eslint", - "import/resolve": { - "moduleDirectory": ["node_modules", "src"] - } - }, - "globals": { - } -} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index bca0bd0..0000000 --- a/.jshintrc +++ /dev/null @@ -1,38 +0,0 @@ -{ - "browser": true, - "esnext": true, - - "bitwise":false, - "curly": true, - "eqnull": true, - "strict": true, - "devel": true, - "eqeqeq": true, - "forin": false, - "immed": true, - "supernew": true, - "expr": true, - "indent": 2, - "latedef": false, - "newcap": true, - "noarg": true, - "noempty": true, - "undef": true, - "boss": true, - "trailing": true, - "laxbreak": true, - "laxcomma": true, - "sub": true, - "unused": true, - "maxdepth": 6, - "maxlen": 140, - - "globals": { - "System": true, - "Promise": true, - "define": true, - "require": true, - "Chromath": false, - "setImmediate": true - } -} diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 3cbc18a..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,65 +0,0 @@ -module.exports = (grunt) => { - require('load-grunt-tasks')(grunt); - - grunt.loadNpmTasks('grunt-execute'); - grunt.loadNpmTasks('grunt-contrib-clean'); - - grunt.initConfig({ - - clean: ['dist/**/*'], - - copy: { - src_to_dist: { - cwd: 'src', - expand: true, - src: ['**/*', '!**/*.js', '!**/*.scss', '!img/**/*'], - dest: 'dist' - }, - pluginDef: { - expand: true, - src: ['plugin.json', 'README.md'], - dest: 'dist', - }, - img_to_dist: { - cwd: 'src', - expand: true, - src: ['img/**/*'], - dest: 'dist/src/' - }, - externals: { - cwd: 'src', - expand: true, - src: ['**/external/*'], - dest: 'dist' - } - }, - - watch: { - rebuild_all: { - files: ['src/**/*', 'plugin.json'], - tasks: ['default'], - options: {spawn: false} - }, - }, - - babel: { - options: { - sourceMap: true, - presets: ['es2015'], - plugins: ['transform-es2015-modules-systemjs', 'transform-es2015-for-of'], - }, - dist: { - files: [{ - cwd: 'src', - expand: true, - src: ['*.js'], - dest: 'dist', - ext: '.js' - }] - }, - }, - - }); - - grunt.registerTask('default', ['clean', 'copy:src_to_dist', 'copy:pluginDef', 'copy:img_to_dist', 'copy:externals', 'babel']); -}; diff --git a/dist/LICENSE b/dist/LICENSE new file mode 100644 index 0000000..4644c8c --- /dev/null +++ b/dist/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Grafana + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dist/clock_ctrl.js b/dist/clock_ctrl.js deleted file mode 100644 index 2976a6f..0000000 --- a/dist/clock_ctrl.js +++ /dev/null @@ -1,250 +0,0 @@ -'use strict'; - -System.register(['app/plugins/sdk', 'moment', './external/moment-duration-format', 'lodash', './css/clock-panel.css!'], function (_export, _context) { - var PanelCtrl, moment, _, _createClass, panelDefaults, ClockCtrl; - - function _classCallCheck(instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - } - - function _possibleConstructorReturn(self, call) { - if (!self) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - - return call && (typeof call === "object" || typeof call === "function") ? call : self; - } - - function _inherits(subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true - } - }); - if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; - } - - return { - setters: [function (_appPluginsSdk) { - PanelCtrl = _appPluginsSdk.PanelCtrl; - }, function (_moment) { - moment = _moment.default; - }, function (_externalMomentDurationFormat) {}, function (_lodash) { - _ = _lodash.default; - }, function (_cssClockPanelCss) {}], - execute: function () { - _createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; - }(); - - panelDefaults = { - mode: 'time', - clockType: '24 hour', - offsetFromUtc: null, - offsetFromUtcMinutes: null, - bgColor: null, - countdownSettings: { - endCountdownTime: moment().seconds(0).milliseconds(0).add(1, 'day').toDate(), - endText: '00:00:00', - customFormat: null - }, - dateSettings: { - showDate: false, - dateFormat: 'YYYY-MM-DD', - fontSize: '20px', - fontWeight: 'normal' - }, - timeSettings: { - customFormat: 'HH:mm:ss', - fontSize: '60px', - fontWeight: 'normal' - }, - refreshSettings: { - syncWithDashboard: false - } - }; - - _export('ClockCtrl', ClockCtrl = function (_PanelCtrl) { - _inherits(ClockCtrl, _PanelCtrl); - - function ClockCtrl($scope, $injector) { - _classCallCheck(this, ClockCtrl); - - var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(ClockCtrl).call(this, $scope, $injector)); - - _.defaultsDeep(_this.panel, panelDefaults); - - if (!(_this.panel.countdownSettings.endCountdownTime instanceof Date)) { - _this.panel.countdownSettings.endCountdownTime = moment(_this.panel.countdownSettings.endCountdownTime).toDate(); - } - - _this.events.on('init-edit-mode', _this.onInitEditMode.bind(_this)); - _this.events.on('panel-teardown', _this.onPanelTeardown.bind(_this)); - _this.events.on('panel-initialized', _this.render.bind(_this)); - _this.events.on('refresh', _this.updateClock.bind(_this)); - _this.events.on('render', _this.updateClock.bind(_this)); - - _this.updateClock(); - return _this; - } - - _createClass(ClockCtrl, [{ - key: 'onInitEditMode', - value: function onInitEditMode() { - this.addEditorTab('Options', 'public/plugins/grafana-clock-panel/editor/options.html', 2); - this.addEditorTab('Refresh', 'public/plugins/grafana-clock-panel/editor/refresh.html', 2); - } - }, { - key: 'onPanelTeardown', - value: function onPanelTeardown() { - this.$timeout.cancel(this.nextTickPromise); - } - }, { - key: 'updateClock', - value: function updateClock() { - this.$timeout.cancel(this.nextTickPromise); - if (this.panel.mode === 'time') { - this.renderTime(); - } else { - this.renderCountdown(); - } - - if (!this.panel.refreshSettings.syncWithDashboard) { - this.nextTickPromise = this.$timeout(this.updateClock.bind(this), 1000); - } - } - }, { - key: 'renderTime', - value: function renderTime() { - var now = void 0; - - if (this.panel.offsetFromUtc && this.panel.offsetFromUtcMinutes) { - var offsetInMinutes = parseInt(this.panel.offsetFromUtc, 10) * 60 + parseInt(this.panel.offsetFromUtcMinutes, 10); - now = moment().utcOffset(offsetInMinutes); - } else if (this.panel.offsetFromUtc && !this.panel.offsetFromUtcMinutes) { - now = moment().utcOffset(parseInt(this.panel.offsetFromUtc, 10)); - } else { - now = moment(); - } - - if (this.panel.dateSettings.showDate) { - this.date = now.format(this.panel.dateSettings.dateFormat); - } - - this.time = now.format(this.getTimeFormat()); - } - }, { - key: 'getTimeFormat', - value: function getTimeFormat() { - if (this.panel.clockType === '24 hour') { - return 'HH:mm:ss'; - } - - if (this.panel.clockType === '12 hour') { - return 'h:mm:ss A'; - } - - return this.panel.timeSettings.customFormat; - } - }, { - key: 'renderCountdown', - value: function renderCountdown() { - if (!this.panel.countdownSettings.endCountdownTime) { - this.time = this.panel.countdownSettings.endText; - } - - var now = moment(); - var timeLeft = moment.duration(moment(this.panel.countdownSettings.endCountdownTime).diff(now)); - var formattedTimeLeft = ''; - - if (timeLeft.asSeconds() <= 0) { - this.time = this.panel.countdownSettings.endText; - return; - } - - if (this.panel.countdownSettings.customFormat === 'auto') { - this.time = timeLeft.format(); - return; - } - - if (this.panel.countdownSettings.customFormat) { - this.time = timeLeft.format(this.panel.countdownSettings.customFormat); - return; - } - - var previous = ''; - - if (timeLeft.years() > 0) { - formattedTimeLeft = timeLeft.years() === 1 ? '1 year, ' : timeLeft.years() + ' years, '; - previous = 'years'; - } - if (timeLeft.months() > 0 || previous === 'years') { - formattedTimeLeft += timeLeft.months() === 1 ? '1 month, ' : timeLeft.months() + ' months, '; - previous = 'month'; - } - if (timeLeft.days() > 0 || previous === 'months') { - formattedTimeLeft += timeLeft.days() === 1 ? '1 day, ' : timeLeft.days() + ' days, '; - previous = 'days'; - } - if (timeLeft.hours() > 0 || previous === 'days') { - formattedTimeLeft += timeLeft.hours() === 1 ? '1 hour, ' : timeLeft.hours() + ' hours, '; - previous = 'hours'; - } - - if (timeLeft.minutes() > 0 || previous === 'hours') { - formattedTimeLeft += timeLeft.minutes() === 1 ? '1 minute, ' : timeLeft.minutes() + ' minutes, '; - } - - formattedTimeLeft += timeLeft.seconds() === 1 ? '1 second ' : timeLeft.seconds() + ' seconds'; - this.time = formattedTimeLeft; - } - }, { - key: 'link', - value: function link(scope, elem) { - var _this2 = this; - - this.events.on('render', function () { - var $panelContainer = elem.find('.panel-container'); - - if (_this2.panel.bgColor) { - $panelContainer.css('background-color', _this2.panel.bgColor); - } else { - $panelContainer.css('background-color', ''); - } - }); - } - }]); - - return ClockCtrl; - }(PanelCtrl)); - - _export('ClockCtrl', ClockCtrl); - - ClockCtrl.templateUrl = 'module.html'; - } - }; -}); -//# sourceMappingURL=clock_ctrl.js.map diff --git a/dist/clock_ctrl.js.map b/dist/clock_ctrl.js.map deleted file mode 100644 index 9b4c908..0000000 --- a/dist/clock_ctrl.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["../src/clock_ctrl.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAQ;;AACD;;AAEA;;;;;;;;;;;;;;;;;;;;;AAGD,sBAAgB;AACpB,cAAM,MAAN;AACA,mBAAW,SAAX;AACA,uBAAe,IAAf;AACA,8BAAsB,IAAtB;AACA,iBAAS,IAAT;AACA,2BAAmB;AACjB,4BAAkB,SAAS,OAAT,CAAiB,CAAjB,EAAoB,YAApB,CAAiC,CAAjC,EAAoC,GAApC,CAAwC,CAAxC,EAA2C,KAA3C,EAAkD,MAAlD,EAAlB;AACA,mBAAS,UAAT;AACA,wBAAc,IAAd;SAHF;AAKA,sBAAc;AACZ,oBAAU,KAAV;AACA,sBAAY,YAAZ;AACA,oBAAU,MAAV;AACA,sBAAY,QAAZ;SAJF;AAMA,sBAAc;AACZ,wBAAc,UAAd;AACA,oBAAU,MAAV;AACA,sBAAY,QAAZ;SAHF;AAKA,yBAAiB;AACf,6BAAmB,KAAnB;SADF;;;2BAKW;;;AACX,iBADW,SACX,CAAY,MAAZ,EAAoB,SAApB,EAA+B;gCADpB,WACoB;;6EADpB,sBAEH,QAAQ,YADe;;AAE7B,YAAE,YAAF,CAAe,MAAK,KAAL,EAAY,aAA3B,EAF6B;;AAI7B,cAAI,EAAE,MAAK,KAAL,CAAW,iBAAX,CAA6B,gBAA7B,YAAyD,IAAzD,CAAF,EAAkE;AACpE,kBAAK,KAAL,CAAW,iBAAX,CAA6B,gBAA7B,GAAgD,OAAO,MAAK,KAAL,CAAW,iBAAX,CAA6B,gBAA7B,CAAP,CAAsD,MAAtD,EAAhD,CADoE;WAAtE;;AAIA,gBAAK,MAAL,CAAY,EAAZ,CAAe,gBAAf,EAAiC,MAAK,cAAL,CAAoB,IAApB,OAAjC,EAR6B;AAS7B,gBAAK,MAAL,CAAY,EAAZ,CAAe,gBAAf,EAAiC,MAAK,eAAL,CAAqB,IAArB,OAAjC,EAT6B;AAU7B,gBAAK,MAAL,CAAY,EAAZ,CAAe,mBAAf,EAAoC,MAAK,MAAL,CAAY,IAAZ,OAApC,EAV6B;AAW7B,gBAAK,MAAL,CAAY,EAAZ,CAAe,SAAf,EAA0B,MAAK,WAAL,CAAiB,IAAjB,OAA1B,EAX6B;AAY7B,gBAAK,MAAL,CAAY,EAAZ,CAAe,QAAf,EAAyB,MAAK,WAAL,CAAiB,IAAjB,OAAzB,EAZ6B;;AAc7B,gBAAK,WAAL,GAd6B;;SAA/B;;qBADW;;2CAkBM;AACf,iBAAK,YAAL,CAAkB,SAAlB,EAA6B,wDAA7B,EAAuF,CAAvF,EADe;AAEf,iBAAK,YAAL,CAAkB,SAAlB,EAA6B,wDAA7B,EAAuF,CAAvF,EAFe;;;;4CAKC;AAChB,iBAAK,QAAL,CAAc,MAAd,CAAqB,KAAK,eAAL,CAArB,CADgB;;;;wCAIJ;AACZ,iBAAK,QAAL,CAAc,MAAd,CAAqB,KAAK,eAAL,CAArB,CADY;AAEZ,gBAAI,KAAK,KAAL,CAAW,IAAX,KAAoB,MAApB,EAA4B;AAC9B,mBAAK,UAAL,GAD8B;aAAhC,MAEO;AACL,mBAAK,eAAL,GADK;aAFP;;AAMA,gBAAI,CAAC,KAAK,KAAL,CAAW,eAAX,CAA2B,iBAA3B,EAA8C;AACjD,mBAAK,eAAL,GAAuB,KAAK,QAAL,CAAc,KAAK,WAAL,CAAiB,IAAjB,CAAsB,IAAtB,CAAd,EAA2C,IAA3C,CAAvB,CADiD;aAAnD;;;;uCAKW;AACX,gBAAI,YAAJ,CADW;;AAGX,gBAAI,KAAK,KAAL,CAAW,aAAX,IAA4B,KAAK,KAAL,CAAW,oBAAX,EAAiC;AAC/D,kBAAM,kBAAkB,QAAC,CAAS,KAAK,KAAL,CAAW,aAAX,EAA0B,EAAnC,IAAyC,EAAzC,GAA+C,SAAS,KAAK,KAAL,CAAW,oBAAX,EAAiC,EAA1C,CAAhD,CADuC;AAE/D,oBAAM,SAAS,SAAT,CAAmB,eAAnB,CAAN,CAF+D;aAAjE,MAGO,IAAI,KAAK,KAAL,CAAW,aAAX,IAA4B,CAAC,KAAK,KAAL,CAAW,oBAAX,EAAiC;AACvE,oBAAM,SAAS,SAAT,CAAmB,SAAS,KAAK,KAAL,CAAW,aAAX,EAA0B,EAAnC,CAAnB,CAAN,CADuE;aAAlE,MAEA;AACL,oBAAM,QAAN,CADK;aAFA;;AAMP,gBAAI,KAAK,KAAL,CAAW,YAAX,CAAwB,QAAxB,EAAkC;AACpC,mBAAK,IAAL,GAAY,IAAI,MAAJ,CAAW,KAAK,KAAL,CAAW,YAAX,CAAwB,UAAxB,CAAvB,CADoC;aAAtC;;AAIA,iBAAK,IAAL,GAAY,IAAI,MAAJ,CAAW,KAAK,aAAL,EAAX,CAAZ,CAhBW;;;;0CAmBG;AACd,gBAAI,KAAK,KAAL,CAAW,SAAX,KAAyB,SAAzB,EAAoC;AACtC,qBAAO,UAAP,CADsC;aAAxC;;AAIA,gBAAI,KAAK,KAAL,CAAW,SAAX,KAAyB,SAAzB,EAAoC;AACtC,qBAAO,WAAP,CADsC;aAAxC;;AAIA,mBAAO,KAAK,KAAL,CAAW,YAAX,CAAwB,YAAxB,CATO;;;;4CAYE;AAChB,gBAAI,CAAC,KAAK,KAAL,CAAW,iBAAX,CAA6B,gBAA7B,EAA+C;AAClD,mBAAK,IAAL,GAAY,KAAK,KAAL,CAAW,iBAAX,CAA6B,OAA7B,CADsC;aAApD;;AAIA,gBAAM,MAAM,QAAN,CALU;AAMhB,gBAAM,WAAW,OAAO,QAAP,CAAgB,OAAO,KAAK,KAAL,CAAW,iBAAX,CAA6B,gBAA7B,CAAP,CAAsD,IAAtD,CAA2D,GAA3D,CAAhB,CAAX,CANU;AAOhB,gBAAI,oBAAoB,EAApB,CAPY;;AAShB,gBAAI,SAAS,SAAT,MAAwB,CAAxB,EAA2B;AAC7B,mBAAK,IAAL,GAAY,KAAK,KAAL,CAAW,iBAAX,CAA6B,OAA7B,CADiB;AAE7B,qBAF6B;aAA/B;;AAKA,gBAAI,KAAK,KAAL,CAAW,iBAAX,CAA6B,YAA7B,KAA8C,MAA9C,EAAsD;AACxD,mBAAK,IAAL,GAAY,SAAS,MAAT,EAAZ,CADwD;AAExD,qBAFwD;aAA1D;;AAKA,gBAAI,KAAK,KAAL,CAAW,iBAAX,CAA6B,YAA7B,EAA2C;AAC7C,mBAAK,IAAL,GAAY,SAAS,MAAT,CAAgB,KAAK,KAAL,CAAW,iBAAX,CAA6B,YAA7B,CAA5B,CAD6C;AAE7C,qBAF6C;aAA/C;;AAKA,gBAAI,WAAW,EAAX,CAxBY;;AA0BhB,gBAAI,SAAS,KAAT,KAAmB,CAAnB,EAAsB;AACxB,kCAAoB,SAAS,KAAT,OAAqB,CAArB,GAAyB,UAAzB,GAAsC,SAAS,KAAT,KAAmB,UAAnB,CADlC;AAExB,yBAAW,OAAX,CAFwB;aAA1B;AAIA,gBAAI,SAAS,MAAT,KAAoB,CAApB,IAAyB,aAAa,OAAb,EAAsB;AACjD,mCAAqB,SAAS,MAAT,OAAsB,CAAtB,GAA0B,WAA1B,GAAwC,SAAS,MAAT,KAAoB,WAApB,CADZ;AAEjD,yBAAW,OAAX,CAFiD;aAAnD;AAIA,gBAAI,SAAS,IAAT,KAAkB,CAAlB,IAAuB,aAAa,QAAb,EAAuB;AAChD,mCAAqB,SAAS,IAAT,OAAoB,CAApB,GAAwB,SAAxB,GAAoC,SAAS,IAAT,KAAkB,SAAlB,CADT;AAEhD,yBAAW,MAAX,CAFgD;aAAlD;AAIA,gBAAI,SAAS,KAAT,KAAmB,CAAnB,IAAwB,aAAa,MAAb,EAAqB;AAC/C,mCAAqB,SAAS,KAAT,OAAqB,CAArB,GAAyB,UAAzB,GAAsC,SAAS,KAAT,KAAmB,UAAnB,CADZ;AAE/C,yBAAW,OAAX,CAF+C;aAAjD;;AAKA,gBAAI,SAAS,OAAT,KAAqB,CAArB,IAA0B,aAAa,OAAb,EAAsB;AAClD,mCAAqB,SAAS,OAAT,OAAuB,CAAvB,GAA2B,YAA3B,GAA0C,SAAS,OAAT,KAAqB,YAArB,CADb;aAApD;;AAIA,iCAAqB,SAAS,OAAT,OAAuB,CAAvB,GAA2B,WAA3B,GAAyC,SAAS,OAAT,KAAqB,UAArB,CA/C9C;AAgDhB,iBAAK,IAAL,GAAY,iBAAZ,CAhDgB;;;;+BAmDb,OAAO,MAAM;;;AAChB,iBAAK,MAAL,CAAY,EAAZ,CAAe,QAAf,EAAyB,YAAM;AAC7B,kBAAM,kBAAkB,KAAK,IAAL,CAAU,kBAAV,CAAlB,CADuB;;AAG7B,kBAAI,OAAK,KAAL,CAAW,OAAX,EAAoB;AACtB,gCAAgB,GAAhB,CAAoB,kBAApB,EAAwC,OAAK,KAAL,CAAW,OAAX,CAAxC,CADsB;eAAxB,MAEO;AACL,gCAAgB,GAAhB,CAAoB,kBAApB,EAAwC,EAAxC,EADK;eAFP;aAHuB,CAAzB,CADgB;;;;eA1HP;QAAkB;;;;AAuI/B,gBAAU,WAAV,GAAwB,aAAxB","file":"clock_ctrl.js","sourcesContent":["import {PanelCtrl} from 'app/plugins/sdk';\nimport moment from 'moment';\nimport './external/moment-duration-format';\nimport _ from 'lodash';\nimport './css/clock-panel.css!';\n\nconst panelDefaults = {\n mode: 'time',\n clockType: '24 hour',\n offsetFromUtc: null,\n offsetFromUtcMinutes: null,\n bgColor: null,\n countdownSettings: {\n endCountdownTime: moment().seconds(0).milliseconds(0).add(1, 'day').toDate(),\n endText: '00:00:00',\n customFormat: null\n },\n dateSettings: {\n showDate: false,\n dateFormat: 'YYYY-MM-DD',\n fontSize: '20px',\n fontWeight: 'normal'\n },\n timeSettings: {\n customFormat: 'HH:mm:ss',\n fontSize: '60px',\n fontWeight: 'normal'\n },\n refreshSettings: {\n syncWithDashboard: false,\n }\n};\n\nexport class ClockCtrl extends PanelCtrl {\n constructor($scope, $injector) {\n super($scope, $injector);\n _.defaultsDeep(this.panel, panelDefaults);\n\n if (!(this.panel.countdownSettings.endCountdownTime instanceof Date)) {\n this.panel.countdownSettings.endCountdownTime = moment(this.panel.countdownSettings.endCountdownTime).toDate();\n }\n\n this.events.on('init-edit-mode', this.onInitEditMode.bind(this));\n this.events.on('panel-teardown', this.onPanelTeardown.bind(this));\n this.events.on('panel-initialized', this.render.bind(this));\n this.events.on('refresh', this.updateClock.bind(this));\n this.events.on('render', this.updateClock.bind(this))\n\n this.updateClock();\n }\n\n onInitEditMode() {\n this.addEditorTab('Options', 'public/plugins/grafana-clock-panel/editor/options.html', 2);\n this.addEditorTab('Refresh', 'public/plugins/grafana-clock-panel/editor/refresh.html', 2);\n }\n\n onPanelTeardown() {\n this.$timeout.cancel(this.nextTickPromise);\n }\n\n updateClock() {\n this.$timeout.cancel(this.nextTickPromise);\n if (this.panel.mode === 'time') {\n this.renderTime();\n } else {\n this.renderCountdown();\n }\n\n if (!this.panel.refreshSettings.syncWithDashboard) {\n this.nextTickPromise = this.$timeout(this.updateClock.bind(this), 1000);\n }\n }\n\n renderTime() {\n let now;\n\n if (this.panel.offsetFromUtc && this.panel.offsetFromUtcMinutes) {\n const offsetInMinutes = (parseInt(this.panel.offsetFromUtc, 10) * 60) + parseInt(this.panel.offsetFromUtcMinutes, 10);\n now = moment().utcOffset(offsetInMinutes);\n } else if (this.panel.offsetFromUtc && !this.panel.offsetFromUtcMinutes) {\n now = moment().utcOffset(parseInt(this.panel.offsetFromUtc, 10));\n } else {\n now = moment();\n }\n\n if (this.panel.dateSettings.showDate) {\n this.date = now.format(this.panel.dateSettings.dateFormat);\n }\n\n this.time = now.format(this.getTimeFormat());\n }\n\n getTimeFormat() {\n if (this.panel.clockType === '24 hour') {\n return 'HH:mm:ss';\n }\n\n if (this.panel.clockType === '12 hour') {\n return 'h:mm:ss A';\n }\n\n return this.panel.timeSettings.customFormat;\n }\n\n renderCountdown() {\n if (!this.panel.countdownSettings.endCountdownTime) {\n this.time = this.panel.countdownSettings.endText;\n }\n\n const now = moment();\n const timeLeft = moment.duration(moment(this.panel.countdownSettings.endCountdownTime).diff(now));\n let formattedTimeLeft = '';\n\n if (timeLeft.asSeconds() <= 0) {\n this.time = this.panel.countdownSettings.endText;\n return;\n }\n\n if (this.panel.countdownSettings.customFormat === 'auto') {\n this.time = timeLeft.format();\n return;\n }\n\n if (this.panel.countdownSettings.customFormat) {\n this.time = timeLeft.format(this.panel.countdownSettings.customFormat);\n return;\n }\n\n let previous = '';\n\n if (timeLeft.years() > 0) {\n formattedTimeLeft = timeLeft.years() === 1 ? '1 year, ' : timeLeft.years() + ' years, ';\n previous = 'years';\n }\n if (timeLeft.months() > 0 || previous === 'years') {\n formattedTimeLeft += timeLeft.months() === 1 ? '1 month, ' : timeLeft.months() + ' months, ';\n previous = 'month';\n }\n if (timeLeft.days() > 0 || previous === 'months') {\n formattedTimeLeft += timeLeft.days() === 1 ? '1 day, ' : timeLeft.days() + ' days, ';\n previous = 'days';\n }\n if (timeLeft.hours() > 0 || previous === 'days') {\n formattedTimeLeft += timeLeft.hours() === 1 ? '1 hour, ' : timeLeft.hours() + ' hours, ';\n previous = 'hours';\n }\n\n if (timeLeft.minutes() > 0 || previous === 'hours') {\n formattedTimeLeft += timeLeft.minutes() === 1 ? '1 minute, ' : timeLeft.minutes() + ' minutes, ';\n }\n\n formattedTimeLeft += timeLeft.seconds() === 1 ? '1 second ' : timeLeft.seconds() + ' seconds';\n this.time = formattedTimeLeft;\n }\n\n link(scope, elem) {\n this.events.on('render', () => {\n const $panelContainer = elem.find('.panel-container');\n\n if (this.panel.bgColor) {\n $panelContainer.css('background-color', this.panel.bgColor);\n } else {\n $panelContainer.css('background-color', '');\n }\n });\n }\n}\n\nClockCtrl.templateUrl = 'module.html';\n"]} \ No newline at end of file diff --git a/dist/css/clock-panel.css b/dist/css/clock-panel.css deleted file mode 100644 index a686b06..0000000 --- a/dist/css/clock-panel.css +++ /dev/null @@ -1,6 +0,0 @@ -.clock-panel { - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; -} diff --git a/dist/external/moment-duration-format.js b/dist/external/moment-duration-format.js deleted file mode 100644 index 34a7afa..0000000 --- a/dist/external/moment-duration-format.js +++ /dev/null @@ -1,1673 +0,0 @@ -/*! Moment Duration Format v2.2.1 - * https://github.com/jsmreese/moment-duration-format - * Date: 2018-01-21 - * - * Duration format plugin function for the Moment.js library - * http://momentjs.com/ - * - * Copyright 2018 John Madhavan-Reese - * Released under the MIT license - */ - -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define(['moment'], factory); - } else if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but only CommonJS-like - // enviroments that support module.exports, like Node. - try { - module.exports = factory(require('moment')); - } catch (e) { - // If moment is not available, leave the setup up to the user. - // Like when using moment-timezone or similar moment-based package. - module.exports = factory; - } - } - - if (root) { - // Globals. - root.momentDurationFormatSetup = root.moment ? factory(root.moment) : factory; - } -})(this, function (moment) { - // `Number#tolocaleString` is tested on plugin initialization. - // If the feature test passes, `toLocaleStringWorks` will be set to `true` and the - // native function will be used to generate formatted output. If the feature - // test fails, the fallback format function internal to this plugin will be - // used. - var toLocaleStringWorks = false; - - // `Number#toLocaleString` rounds incorrectly for select numbers in Microsoft - // environments (Edge, IE11, Windows Phone) and possibly other environments. - // If the rounding test fails and `toLocaleString` will be used for formatting, - // the plugin will "pre-round" number values using the fallback number format - // function before passing them to `toLocaleString` for final formatting. - var toLocaleStringRoundingWorks = false; - - // Token type names in order of descending magnitude. - var types = "escape years months weeks days hours minutes seconds milliseconds general".split(" "); - - var bubbles = [ - { - type: "seconds", - targets: [ - { type: "minutes", value: 60 }, - { type: "hours", value: 3600 }, - { type: "days", value: 86400 }, - { type: "weeks", value: 604800 }, - { type: "months", value: 2678400 }, - { type: "years", value: 31536000 } - ] - }, - { - type: "minutes", - targets: [ - { type: "hours", value: 60 }, - { type: "days", value: 1440 }, - { type: "weeks", value: 10080 }, - { type: "months", value: 44640 }, - { type: "years", value: 525600 } - ] - }, - { - type: "hours", - targets: [ - { type: "days", value: 24 }, - { type: "weeks", value: 168 }, - { type: "months", value: 744 }, - { type: "years", value: 8760 } - ] - }, - { - type: "days", - targets: [ - { type: "weeks", value: 7 }, - { type: "months", value: 31 }, - { type: "years", value: 365 } - ] - }, - { - type: "months", - targets: [ - { type: "years", value: 12 } - ] - } - ]; - - // stringIncludes - function stringIncludes(str, search) { - if (search.length > str.length) { - return false; - } - - return str.indexOf(search) !== -1; - } - - // repeatZero(qty) - // Returns "0" repeated `qty` times. - // `qty` must be a integer >= 0. - function repeatZero(qty) { - var result = ""; - - while (qty) { - result += "0"; - qty -= 1; - } - - return result; - } - - function stringRound(digits) { - var digitsArray = digits.split("").reverse(); - var i = 0; - var carry = true; - - while (carry && i < digitsArray.length) { - if (i) { - if (digitsArray[i] === "9") { - digitsArray[i] = "0"; - } else { - digitsArray[i] = (parseInt(digitsArray[i], 10) + 1).toString(); - carry = false; - } - } else { - if (parseInt(digitsArray[i], 10) < 5) { - carry = false; - } - - digitsArray[i] = "0"; - } - - i += 1; - } - - if (carry) { - digitsArray.push("1"); - } - - return digitsArray.reverse().join(""); - } - - // formatNumber - // Formats any number greater than or equal to zero using these options: - // - userLocale - // - useToLocaleString - // - useGrouping - // - grouping - // - maximumSignificantDigits - // - minimumIntegerDigits - // - fractionDigits - // - groupingSeparator - // - decimalSeparator - // - // `useToLocaleString` will use `toLocaleString` for formatting. - // `userLocale` option is passed through to `toLocaleString`. - // `fractionDigits` is passed through to `maximumFractionDigits` and `minimumFractionDigits` - // Using `maximumSignificantDigits` will override `minimumIntegerDigits` and `fractionDigits`. - function formatNumber(number, options, userLocale) { - var useToLocaleString = options.useToLocaleString; - var useGrouping = options.useGrouping; - var grouping = useGrouping && options.grouping.slice(); - var maximumSignificantDigits = options.maximumSignificantDigits; - var minimumIntegerDigits = options.minimumIntegerDigits || 1; - var fractionDigits = options.fractionDigits || 0; - var groupingSeparator = options.groupingSeparator; - var decimalSeparator = options.decimalSeparator; - - if (useToLocaleString && userLocale) { - var localeStringOptions = { - minimumIntegerDigits: minimumIntegerDigits, - useGrouping: useGrouping - }; - - if (fractionDigits) { - localeStringOptions.maximumFractionDigits = fractionDigits; - localeStringOptions.minimumFractionDigits = fractionDigits; - } - - // toLocaleString output is "0.0" instead of "0" for HTC browsers - // when maximumSignificantDigits is set. See #96. - if (maximumSignificantDigits && number > 0) { - localeStringOptions.maximumSignificantDigits = maximumSignificantDigits; - } - - if (!toLocaleStringRoundingWorks) { - var roundingOptions = extend({}, options); - roundingOptions.useGrouping = false; - roundingOptions.decimalSeparator = "."; - number = parseFloat(formatNumber(number, roundingOptions), 10); - } - - return number.toLocaleString(userLocale, localeStringOptions); - } - - var numberString; - - // Add 1 to digit output length for floating point errors workaround. See below. - if (maximumSignificantDigits) { - numberString = number.toPrecision(maximumSignificantDigits + 1); - } else { - numberString = number.toFixed(fractionDigits + 1); - } - - var integerString; - var fractionString; - var exponentString; - - var temp = numberString.split("e"); - - exponentString = temp[1] || ""; - - temp = temp[0].split("."); - - fractionString = temp[1] || ""; - integerString = temp[0] || ""; - - // Workaround for floating point errors in `toFixed` and `toPrecision`. - // (3.55).toFixed(1); --> "3.5" - // (123.55 - 120).toPrecision(2); --> "3.5" - // (123.55 - 120); --> 3.549999999999997 - // (123.55 - 120).toFixed(2); --> "3.55" - // Round by examing the string output of the next digit. - - // *************** Implement String Rounding here *********************** - // Check integerString + fractionString length of toPrecision before rounding. - // Check length of fractionString from toFixed output before rounding. - var integerLength = integerString.length; - var fractionLength = fractionString.length; - var digitCount = integerLength + fractionLength; - var digits = integerString + fractionString; - - if (maximumSignificantDigits && digitCount === (maximumSignificantDigits + 1) || !maximumSignificantDigits && fractionLength === (fractionDigits + 1)) { - // Round digits. - digits = stringRound(digits); - - if (digits.length === digitCount + 1) { - integerLength = integerLength + 1; - } - - // Discard final fractionDigit. - if (fractionLength) { - digits = digits.slice(0, -1); - } - - // Separate integer and fraction. - integerString = digits.slice(0, integerLength); - fractionString = digits.slice(integerLength); - } - - // Trim trailing zeroes from fractionString because toPrecision outputs - // precision, not significant digits. - if (maximumSignificantDigits) { - fractionString = fractionString.replace(/0*$/, ""); - } - - // Handle exponent. - var exponent = parseInt(exponentString, 10); - - if (exponent > 0) { - if (fractionString.length <= exponent) { - fractionString = fractionString + repeatZero(exponent - fractionString.length); - - integerString = integerString + fractionString; - fractionString = ""; - } else { - integerString = integerString + fractionString.slice(0, exponent); - fractionString = fractionString.slice(exponent); - } - } else if (exponent < 0) { - fractionString = (repeatZero(Math.abs(exponent) - integerString.length) + integerString + fractionString); - - integerString = "0"; - } - - if (!maximumSignificantDigits) { - // Trim or pad fraction when not using maximumSignificantDigits. - fractionString = fractionString.slice(0, fractionDigits); - - if (fractionString.length < fractionDigits) { - fractionString = fractionString + repeatZero(fractionDigits - fractionString.length); - } - - // Pad integer when using minimumIntegerDigits - // and not using maximumSignificantDigits. - if (integerString.length < minimumIntegerDigits) { - integerString = repeatZero(minimumIntegerDigits - integerString.length) + integerString; - } - } - - var formattedString = ""; - - // Handle grouping. - if (useGrouping) { - temp = integerString; - var group; - - while (temp.length) { - if (grouping.length) { - group = grouping.shift(); - } - - if (formattedString) { - formattedString = groupingSeparator + formattedString; - } - - formattedString = temp.slice(-group) + formattedString; - - temp = temp.slice(0, -group); - } - } else { - formattedString = integerString; - } - - // Add decimalSeparator and fraction. - if (fractionString) { - formattedString = formattedString + decimalSeparator + fractionString; - } - - return formattedString; - } - - // durationLabelCompare - function durationLabelCompare(a, b) { - if (a.label.length > b.label.length) { - return -1; - } - - if (a.label.length < b.label.length) { - return 1; - } - - // a must be equal to b - return 0; - } - - // durationGetLabels - function durationGetLabels(token, localeData) { - var labels = []; - - each(keys(localeData), function (localeDataKey) { - if (localeDataKey.slice(0, 15) !== "_durationLabels") { - return; - } - - var labelType = localeDataKey.slice(15).toLowerCase(); - - each(keys(localeData[localeDataKey]), function (labelKey) { - if (labelKey.slice(0, 1) === token) { - labels.push({ - type: labelType, - key: labelKey, - label: localeData[localeDataKey][labelKey] - }); - } - }); - }); - - return labels; - } - - // durationPluralKey - function durationPluralKey(token, integerValue, decimalValue) { - // Singular for a value of `1`, but not for `1.0`. - if (integerValue === 1 && decimalValue === null) { - return token; - } - - return token + token; - } - - var engLocale = { - durationLabelsStandard: { - S: 'millisecond', - SS: 'milliseconds', - s: 'second', - ss: 'seconds', - m: 'minute', - mm: 'minutes', - h: 'hour', - hh: 'hours', - d: 'day', - dd: 'days', - w: 'week', - ww: 'weeks', - M: 'month', - MM: 'months', - y: 'year', - yy: 'years' - }, - durationLabelsShort: { - S: 'msec', - SS: 'msecs', - s: 'sec', - ss: 'secs', - m: 'min', - mm: 'mins', - h: 'hr', - hh: 'hrs', - d: 'dy', - dd: 'dys', - w: 'wk', - ww: 'wks', - M: 'mo', - MM: 'mos', - y: 'yr', - yy: 'yrs' - }, - durationTimeTemplates: { - HMS: 'h:mm:ss', - HM: 'h:mm', - MS: 'm:ss' - }, - durationLabelTypes: [ - { type: "standard", string: "__" }, - { type: "short", string: "_" } - ], - durationPluralKey: durationPluralKey - }; - - // isArray - function isArray(array) { - return Object.prototype.toString.call(array) === "[object Array]"; - } - - // isObject - function isObject(obj) { - return Object.prototype.toString.call(obj) === "[object Object]"; - } - - // findLast - function findLast(array, callback) { - var index = array.length; - - while (index -= 1) { - if (callback(array[index])) { return array[index]; } - } - } - - // find - function find(array, callback) { - var index = 0; - - var max = array && array.length || 0; - - var match; - - if (typeof callback !== "function") { - match = callback; - callback = function (item) { - return item === match; - }; - } - - while (index < max) { - if (callback(array[index])) { return array[index]; } - index += 1; - } - } - - // each - function each(array, callback) { - var index = 0, - max = array.length; - - if (!array || !max) { return; } - - while (index < max) { - if (callback(array[index], index) === false) { return; } - index += 1; - } - } - - // map - function map(array, callback) { - var index = 0, - max = array.length, - ret = []; - - if (!array || !max) { return ret; } - - while (index < max) { - ret[index] = callback(array[index], index); - index += 1; - } - - return ret; - } - - // pluck - function pluck(array, prop) { - return map(array, function (item) { - return item[prop]; - }); - } - - // compact - function compact(array) { - var ret = []; - - each(array, function (item) { - if (item) { ret.push(item); } - }); - - return ret; - } - - // unique - function unique(array) { - var ret = []; - - each(array, function (_a) { - if (!find(ret, _a)) { ret.push(_a); } - }); - - return ret; - } - - // intersection - function intersection(a, b) { - var ret = []; - - each(a, function (_a) { - each(b, function (_b) { - if (_a === _b) { ret.push(_a); } - }); - }); - - return unique(ret); - } - - // rest - function rest(array, callback) { - var ret = []; - - each(array, function (item, index) { - if (!callback(item)) { - ret = array.slice(index); - return false; - } - }); - - return ret; - } - - // initial - function initial(array, callback) { - var reversed = array.slice().reverse(); - - return rest(reversed, callback).reverse(); - } - - // extend - function extend(a, b) { - for (var key in b) { - if (b.hasOwnProperty(key)) { a[key] = b[key]; } - } - - return a; - } - - // keys - function keys(a) { - var ret = []; - - for (var key in a) { - if (a.hasOwnProperty(key)) { ret.push(key); } - } - - return ret; - } - - // any - function any(array, callback) { - var index = 0, - max = array.length; - - if (!array || !max) { return false; } - - while (index < max) { - if (callback(array[index], index) === true) { return true; } - index += 1; - } - - return false; - } - - // flatten - function flatten(array) { - var ret = []; - - each(array, function(child) { - ret = ret.concat(child); - }); - - return ret; - } - - function toLocaleStringSupportsLocales() { - var number = 0; - try { - number.toLocaleString('i'); - } catch (e) { - return e.name === 'RangeError'; - } - return false; - } - - function featureTestToLocaleStringRounding() { - return (3.55).toLocaleString("en", { - useGrouping: false, - minimumIntegerDigits: 1, - minimumFractionDigits: 1, - maximumFractionDigits: 1 - }) === "3.6"; - } - - function featureTestToLocaleString() { - var passed = true; - - // Test locale. - passed = passed && toLocaleStringSupportsLocales(); - if (!passed) { return false; } - - // Test minimumIntegerDigits. - passed = passed && (1).toLocaleString("en", { minimumIntegerDigits: 1 }) === "1"; - passed = passed && (1).toLocaleString("en", { minimumIntegerDigits: 2 }) === "01"; - passed = passed && (1).toLocaleString("en", { minimumIntegerDigits: 3 }) === "001"; - if (!passed) { return false; } - - // Test maximumFractionDigits and minimumFractionDigits. - passed = passed && (99.99).toLocaleString("en", { maximumFractionDigits: 0, minimumFractionDigits: 0 }) === "100"; - passed = passed && (99.99).toLocaleString("en", { maximumFractionDigits: 1, minimumFractionDigits: 1 }) === "100.0"; - passed = passed && (99.99).toLocaleString("en", { maximumFractionDigits: 2, minimumFractionDigits: 2 }) === "99.99"; - passed = passed && (99.99).toLocaleString("en", { maximumFractionDigits: 3, minimumFractionDigits: 3 }) === "99.990"; - if (!passed) { return false; } - - // Test maximumSignificantDigits. - passed = passed && (99.99).toLocaleString("en", { maximumSignificantDigits: 1 }) === "100"; - passed = passed && (99.99).toLocaleString("en", { maximumSignificantDigits: 2 }) === "100"; - passed = passed && (99.99).toLocaleString("en", { maximumSignificantDigits: 3 }) === "100"; - passed = passed && (99.99).toLocaleString("en", { maximumSignificantDigits: 4 }) === "99.99"; - passed = passed && (99.99).toLocaleString("en", { maximumSignificantDigits: 5 }) === "99.99"; - if (!passed) { return false; } - - // Test grouping. - passed = passed && (1000).toLocaleString("en", { useGrouping: true }) === "1,000"; - passed = passed && (1000).toLocaleString("en", { useGrouping: false }) === "1000"; - if (!passed) { return false; } - - return true; - } - - // durationsFormat(durations [, template] [, precision] [, settings]) - function durationsFormat() { - var args = [].slice.call(arguments); - var settings = {}; - var durations; - - // Parse arguments. - each(args, function (arg, index) { - if (!index) { - if (!isArray(arg)) { - throw "Expected array as the first argument to durationsFormat."; - } - - durations = arg; - } - - if (typeof arg === "string" || typeof arg === "function") { - settings.template = arg; - return; - } - - if (typeof arg === "number") { - settings.precision = arg; - return; - } - - if (isObject(arg)) { - extend(settings, arg); - } - }); - - if (!durations || !durations.length) { - return []; - } - - settings.returnMomentTypes = true; - - var formattedDurations = map(durations, function (dur) { - return dur.format(settings); - }); - - // Merge token types from all durations. - var outputTypes = intersection(types, unique(pluck(flatten(formattedDurations), "type"))); - - var largest = settings.largest; - - if (largest) { - outputTypes = outputTypes.slice(0, largest); - } - - settings.returnMomentTypes = false; - settings.outputTypes = outputTypes; - - return map(durations, function (dur) { - return dur.format(settings); - }); - } - - // durationFormat([template] [, precision] [, settings]) - function durationFormat() { - - var args = [].slice.call(arguments); - var settings = extend({}, this.format.defaults); - - // Keep a shadow copy of this moment for calculating remainders. - // Perform all calculations on positive duration value, handle negative - // sign at the very end. - var asMilliseconds = this.asMilliseconds(); - var asMonths = this.asMonths(); - - // Treat invalid durations as having a value of 0 milliseconds. - if (this.isValid() === false) { - asMilliseconds = 0; - asMonths = 0; - } - - var isNegative = asMilliseconds < 0; - - // Two shadow copies are needed because of the way moment.js handles - // duration arithmetic for years/months and for weeks/days/hours/minutes/seconds. - var remainder = moment.duration(Math.abs(asMilliseconds), "milliseconds"); - var remainderMonths = moment.duration(Math.abs(asMonths), "months"); - - // Parse arguments. - each(args, function (arg) { - if (typeof arg === "string" || typeof arg === "function") { - settings.template = arg; - return; - } - - if (typeof arg === "number") { - settings.precision = arg; - return; - } - - if (isObject(arg)) { - extend(settings, arg); - } - }); - - var momentTokens = { - years: "y", - months: "M", - weeks: "w", - days: "d", - hours: "h", - minutes: "m", - seconds: "s", - milliseconds: "S" - }; - - var tokenDefs = { - escape: /\[(.+?)\]/, - years: /\*?[Yy]+/, - months: /\*?M+/, - weeks: /\*?[Ww]+/, - days: /\*?[Dd]+/, - hours: /\*?[Hh]+/, - minutes: /\*?m+/, - seconds: /\*?s+/, - milliseconds: /\*?S+/, - general: /.+?/ - }; - - // Types array is available in the template function. - settings.types = types; - - var typeMap = function (token) { - return find(types, function (type) { - return tokenDefs[type].test(token); - }); - }; - - var tokenizer = new RegExp(map(types, function (type) { - return tokenDefs[type].source; - }).join("|"), "g"); - - // Current duration object is available in the template function. - settings.duration = this; - - // Eval template function and cache template string. - var template = typeof settings.template === "function" ? settings.template.apply(settings) : settings.template; - - // outputTypes and returnMomentTypes are settings to support durationsFormat(). - - // outputTypes is an array of moment token types that determines - // the tokens returned in formatted output. This option overrides - // trim, largest, stopTrim, etc. - var outputTypes = settings.outputTypes; - - // returnMomentTypes is a boolean that sets durationFormat to return - // the processed momentTypes instead of formatted output. - var returnMomentTypes = settings.returnMomentTypes; - - var largest = settings.largest; - - // Setup stopTrim array of token types. - var stopTrim = []; - - if (!outputTypes) { - if (isArray(settings.stopTrim)) { - settings.stopTrim = settings.stopTrim.join(""); - } - - // Parse stopTrim string to create token types array. - if (settings.stopTrim) { - each(settings.stopTrim.match(tokenizer), function (token) { - var type = typeMap(token); - - if (type === "escape" || type === "general") { - return; - } - - stopTrim.push(type); - }); - } - } - - // Cache moment's locale data. - var localeData = moment.localeData(); - - if (!localeData) { - localeData = {}; - } - - // Fall back to this plugin's `eng` extension. - each(keys(engLocale), function (key) { - if (typeof engLocale[key] === "function") { - if (!localeData[key]) { - localeData[key] = engLocale[key]; - } - - return; - } - - if (!localeData["_" + key]) { - localeData["_" + key] = engLocale[key]; - } - }); - - // Replace Duration Time Template strings. - // For locale `eng`: `_HMS_`, `_HM_`, and `_MS_`. - each(keys(localeData._durationTimeTemplates), function (item) { - template = template.replace("_" + item + "_", localeData._durationTimeTemplates[item]); - }); - - // Determine user's locale. - var userLocale = settings.userLocale || moment.locale(); - - var useLeftUnits = settings.useLeftUnits; - var usePlural = settings.usePlural; - var precision = settings.precision; - var forceLength = settings.forceLength; - var useGrouping = settings.useGrouping; - var trunc = settings.trunc; - - // Use significant digits only when precision is greater than 0. - var useSignificantDigits = settings.useSignificantDigits && precision > 0; - var significantDigits = useSignificantDigits ? settings.precision : 0; - var significantDigitsCache = significantDigits; - - var minValue = settings.minValue; - var isMinValue = false; - - var maxValue = settings.maxValue; - var isMaxValue = false; - - // formatNumber fallback options. - var useToLocaleString = settings.useToLocaleString; - var groupingSeparator = settings.groupingSeparator; - var decimalSeparator = settings.decimalSeparator; - var grouping = settings.grouping; - - useToLocaleString = useToLocaleString && toLocaleStringWorks; - - // Trim options. - var trim = settings.trim; - - if (isArray(trim)) { - trim = trim.join(" "); - } - - if (trim === null && (largest || maxValue || useSignificantDigits)) { - trim = "all"; - } - - if (trim === null || trim === true || trim === "left" || trim === "right") { - trim = "large"; - } - - if (trim === false) { - trim = ""; - } - - var trimIncludes = function (item) { - return item.test(trim); - }; - - var rLarge = /large/; - var rSmall = /small/; - var rBoth = /both/; - var rMid = /mid/; - var rAll = /^all|[^sm]all/; - var rFinal = /final/; - - var trimLarge = largest > 0 || any([rLarge, rBoth, rAll], trimIncludes); - var trimSmall = any([rSmall, rBoth, rAll], trimIncludes); - var trimMid = any([rMid, rAll], trimIncludes); - var trimFinal = any([rFinal, rAll], trimIncludes); - - // Parse format string to create raw tokens array. - var rawTokens = map(template.match(tokenizer), function (token, index) { - var type = typeMap(token); - - if (token.slice(0, 1) === "*") { - token = token.slice(1); - - if (type !== "escape" && type !== "general") { - stopTrim.push(type); - } - } - - return { - index: index, - length: token.length, - text: "", - - // Replace escaped tokens with the non-escaped token text. - token: (type === "escape" ? token.replace(tokenDefs.escape, "$1") : token), - - // Ignore type on non-moment tokens. - type: ((type === "escape" || type === "general") ? null : type) - }; - }); - - // Associate text tokens with moment tokens. - var currentToken = { - index: 0, - length: 0, - token: "", - text: "", - type: null - }; - - var tokens = []; - - if (useLeftUnits) { - rawTokens.reverse(); - } - - each(rawTokens, function (token) { - if (token.type) { - if (currentToken.type || currentToken.text) { - tokens.push(currentToken); - } - - currentToken = token; - - return; - } - - if (useLeftUnits) { - currentToken.text = token.token + currentToken.text; - } else { - currentToken.text += token.token; - } - }); - - if (currentToken.type || currentToken.text) { - tokens.push(currentToken); - } - - if (useLeftUnits) { - tokens.reverse(); - } - - // Find unique moment token types in the template in order of - // descending magnitude. - var momentTypes = intersection(types, unique(compact(pluck(tokens, "type")))); - - // Exit early if there are no moment token types. - if (!momentTypes.length) { - return pluck(tokens, "text").join(""); - } - - // Calculate values for each moment type in the template. - // For processing the settings, values are associated with moment types. - // Values will be assigned to tokens at the last step in order to - // assume nothing about frequency or order of tokens in the template. - momentTypes = map(momentTypes, function (momentType, index) { - // Is this the least-magnitude moment token found? - var isSmallest = ((index + 1) === momentTypes.length); - - // Is this the greatest-magnitude moment token found? - var isLargest = (!index); - - // Get the raw value in the current units. - var rawValue; - - if (momentType === "years" || momentType === "months") { - rawValue = remainderMonths.as(momentType); - } else { - rawValue = remainder.as(momentType); - } - - var wholeValue = Math.floor(rawValue); - var decimalValue = rawValue - wholeValue; - - var token = find(tokens, function (token) { - return momentType === token.type; - }); - - if (isLargest && maxValue && rawValue > maxValue) { - isMaxValue = true; - } - - if (isSmallest && minValue && Math.abs(settings.duration.as(momentType)) < minValue) { - isMinValue = true; - } - - // Note the length of the largest-magnitude moment token: - // if it is greater than one and forceLength is not set, - // then default forceLength to `true`. - // - // Rationale is this: If the template is "h:mm:ss" and the - // moment value is 5 minutes, the user-friendly output is - // "5:00", not "05:00". We shouldn't pad the `minutes` token - // even though it has length of two if the template is "h:mm:ss"; - // - // If the minutes output should always include the leading zero - // even when the hour is trimmed then set `{ forceLength: true }` - // to output "05:00". If the template is "hh:mm:ss", the user - // clearly wanted everything padded so we should output "05:00"; - // - // If the user wants the full padded output, they can use - // template "hh:mm:ss" and set `{ trim: false }` to output - // "00:05:00". - if (isLargest && forceLength === null && token.length > 1) { - forceLength = true; - } - - // Update remainder. - remainder.subtract(wholeValue, momentType); - remainderMonths.subtract(wholeValue, momentType); - - return { - rawValue: rawValue, - wholeValue: wholeValue, - // Decimal value is only retained for the least-magnitude - // moment type in the format template. - decimalValue: isSmallest ? decimalValue : 0, - isSmallest: isSmallest, - isLargest: isLargest, - type: momentType, - // Tokens can appear multiple times in a template string, - // but all instances must share the same length. - tokenLength: token.length - }; - }); - - var truncMethod = trunc ? Math.floor : Math.round; - var truncate = function (value, places) { - var factor = Math.pow(10, places); - return truncMethod(value * factor) / factor; - }; - - var foundFirst = false; - var bubbled = false; - - var formatValue = function (momentType, index) { - var formatOptions = { - useGrouping: useGrouping, - groupingSeparator: groupingSeparator, - decimalSeparator: decimalSeparator, - grouping: grouping, - useToLocaleString: useToLocaleString - }; - - if (useSignificantDigits) { - if (significantDigits <= 0) { - momentType.rawValue = 0; - momentType.wholeValue = 0; - momentType.decimalValue = 0; - } else { - formatOptions.maximumSignificantDigits = significantDigits; - momentType.significantDigits = significantDigits; - } - } - - if (isMaxValue && !bubbled) { - if (momentType.isLargest) { - momentType.wholeValue = maxValue; - momentType.decimalValue = 0; - } else { - momentType.wholeValue = 0; - momentType.decimalValue = 0; - } - } - - if (isMinValue && !bubbled) { - if (momentType.isSmallest) { - momentType.wholeValue = minValue; - momentType.decimalValue = 0; - } else { - momentType.wholeValue = 0; - momentType.decimalValue = 0; - } - } - - if (momentType.isSmallest || momentType.significantDigits && momentType.significantDigits - momentType.wholeValue.toString().length <= 0) { - // Apply precision to least significant token value. - if (precision < 0) { - momentType.value = truncate(momentType.wholeValue, precision); - } else if (precision === 0) { - momentType.value = truncMethod(momentType.wholeValue + momentType.decimalValue); - } else { // precision > 0 - if (useSignificantDigits) { - if (trunc) { - momentType.value = truncate(momentType.rawValue, significantDigits - momentType.wholeValue.toString().length); - } else { - momentType.value = momentType.rawValue; - } - - if (momentType.wholeValue) { - significantDigits -= momentType.wholeValue.toString().length; - } - } else { - formatOptions.fractionDigits = precision; - - if (trunc) { - momentType.value = momentType.wholeValue + truncate(momentType.decimalValue, precision); - } else { - momentType.value = momentType.wholeValue + momentType.decimalValue; - } - } - } - } else { - if (useSignificantDigits && momentType.wholeValue) { - // Outer Math.round required here to handle floating point errors. - momentType.value = Math.round(truncate(momentType.wholeValue, momentType.significantDigits - momentType.wholeValue.toString().length)); - - significantDigits -= momentType.wholeValue.toString().length; - } else { - momentType.value = momentType.wholeValue; - } - } - - if (momentType.tokenLength > 1 && (forceLength || foundFirst)) { - formatOptions.minimumIntegerDigits = momentType.tokenLength; - - if (bubbled && formatOptions.maximumSignificantDigits < momentType.tokenLength) { - delete formatOptions.maximumSignificantDigits; - } - } - - if (!foundFirst && (momentType.value > 0 || trim === "" /* trim: false */ || find(stopTrim, momentType.type) || find(outputTypes, momentType.type))) { - foundFirst = true; - } - - momentType.formattedValue = formatNumber(momentType.value, formatOptions, userLocale); - - formatOptions.useGrouping = false; - formatOptions.decimalSeparator = "."; - momentType.formattedValueEn = formatNumber(momentType.value, formatOptions, "en"); - - if (momentType.tokenLength === 2 && momentType.type === "milliseconds") { - momentType.formattedValueMS = formatNumber(momentType.value, { - minimumIntegerDigits: 3, - useGrouping: false - }, "en").slice(0, 2); - } - - return momentType; - }; - - // Calculate formatted values. - momentTypes = map(momentTypes, formatValue); - momentTypes = compact(momentTypes); - - // Bubble rounded values. - if (momentTypes.length > 1) { - var findType = function (type) { - return find(momentTypes, function (momentType) { - return momentType.type === type; - }); - }; - - var bubbleTypes = function (bubble) { - var bubbleMomentType = findType(bubble.type); - - if (!bubbleMomentType) { - return; - } - - each(bubble.targets, function (target) { - var targetMomentType = findType(target.type); - - if (!targetMomentType) { - return; - } - - if (parseInt(bubbleMomentType.formattedValueEn, 10) === target.value) { - bubbleMomentType.rawValue = 0; - bubbleMomentType.wholeValue = 0; - bubbleMomentType.decimalValue = 0; - targetMomentType.rawValue += 1; - targetMomentType.wholeValue += 1; - targetMomentType.decimalValue = 0; - targetMomentType.formattedValueEn = targetMomentType.wholeValue.toString(); - bubbled = true; - } - }); - }; - - each(bubbles, bubbleTypes); - } - - // Recalculate formatted values. - if (bubbled) { - foundFirst = false; - significantDigits = significantDigitsCache; - momentTypes = map(momentTypes, formatValue); - momentTypes = compact(momentTypes); - } - - if (outputTypes && !(isMaxValue && !settings.trim)) { - momentTypes = map(momentTypes, function (momentType) { - if (find(outputTypes, function (outputType) { - return momentType.type === outputType; - })) { - return momentType; - } - - return null; - }); - - momentTypes = compact(momentTypes); - } else { - // Trim Large. - if (trimLarge) { - momentTypes = rest(momentTypes, function (momentType) { - // Stop trimming on: - // - the smallest moment type - // - a type marked for stopTrim - // - a type that has a whole value - return !momentType.isSmallest && !momentType.wholeValue && !find(stopTrim, momentType.type); - }); - } - - // Largest. - if (largest && momentTypes.length) { - momentTypes = momentTypes.slice(0, largest); - } - - // Trim Small. - if (trimSmall && momentTypes.length > 1) { - momentTypes = initial(momentTypes, function (momentType) { - // Stop trimming on: - // - a type marked for stopTrim - // - a type that has a whole value - // - the largest momentType - return !momentType.wholeValue && !find(stopTrim, momentType.type) && !momentType.isLargest; - }); - } - - // Trim Mid. - if (trimMid) { - momentTypes = map(momentTypes, function (momentType, index) { - if (index > 0 && index < momentTypes.length - 1 && !momentType.wholeValue) { - return null; - } - - return momentType; - }); - - momentTypes = compact(momentTypes); - } - - // Trim Final. - if (trimFinal && momentTypes.length === 1 && !momentTypes[0].wholeValue && !(!trunc && momentTypes[0].isSmallest && momentTypes[0].rawValue < minValue)) { - momentTypes = []; - } - } - - if (returnMomentTypes) { - return momentTypes; - } - - // Localize and pluralize unit labels. - each(tokens, function (token) { - var key = momentTokens[token.type]; - - var momentType = find(momentTypes, function (momentType) { - return momentType.type === token.type; - }); - - if (!key || !momentType) { - return; - } - - var values = momentType.formattedValueEn.split("."); - - values[0] = parseInt(values[0], 10); - - if (values[1]) { - values[1] = parseFloat("0." + values[1], 10); - } else { - values[1] = null; - } - - var pluralKey = localeData.durationPluralKey(key, values[0], values[1]); - - var labels = durationGetLabels(key, localeData); - - var autoLocalized = false; - - var pluralizedLabels = {}; - - // Auto-Localized unit labels. - each(localeData._durationLabelTypes, function (labelType) { - var label = find(labels, function (label) { - return label.type === labelType.type && label.key === pluralKey; - }); - - if (label) { - pluralizedLabels[label.type] = label.label; - - if (stringIncludes(token.text, labelType.string)) { - token.text = token.text.replace(labelType.string, label.label); - autoLocalized = true; - } - } - }); - - // Auto-pluralized unit labels. - if (usePlural && !autoLocalized) { - labels.sort(durationLabelCompare); - - each(labels, function (label) { - if (pluralizedLabels[label.type] === label.label) { - if (stringIncludes(token.text, label.label)) { - // Stop checking this token if its label is already - // correctly pluralized. - return false; - } - - // Skip this label if it is correct, but not present in - // the token's text. - return; - } - - if (stringIncludes(token.text, label.label)) { - // Replece this token's label and stop checking. - token.text = token.text.replace(label.label, pluralizedLabels[label.type]); - return false; - } - }); - } - }); - - // Build ouptut. - tokens = map(tokens, function (token) { - if (!token.type) { - return token.text; - } - - var momentType = find(momentTypes, function (momentType) { - return momentType.type === token.type; - }); - - if (!momentType) { - return ""; - } - - var out = ""; - - if (useLeftUnits) { - out += token.text; - } - - if (isNegative && isMaxValue || !isNegative && isMinValue) { - out += "< "; - isMaxValue = false; - isMinValue = false; - } - - if (isNegative && isMinValue || !isNegative && isMaxValue) { - out += "> "; - isMaxValue = false; - isMinValue = false; - } - - if (isNegative && (momentType.value > 0 || find(stopTrim, momentType.type) || find(outputTypes, momentType.type))) { - out += "-"; - isNegative = false; - } - - if (token.type === "milliseconds" && momentType.formattedValueMS) { - out += momentType.formattedValueMS; - } else { - out += momentType.formattedValue; - } - - if (!useLeftUnits) { - out += token.text; - } - - return out; - }); - - // Trim leading and trailing comma, space, colon, and dot. - return tokens.join("").replace(/(,| |:|\.)*$/, "").replace(/^(,| |:|\.)*/, ""); - } - - // defaultFormatTemplate - function defaultFormatTemplate() { - var dur = this.duration; - - var findType = function findType(type) { - return dur._data[type]; - }; - - var firstType = find(this.types, findType); - - var lastType = findLast(this.types, findType); - - // Default template strings for each duration dimension type. - switch (firstType) { - case "milliseconds": - return "S __"; - case "seconds": // Fallthrough. - case "minutes": - return "*_MS_"; - case "hours": - return "_HMS_"; - case "days": // Possible Fallthrough. - if (firstType === lastType) { - return "d __"; - } - case "weeks": - if (firstType === lastType) { - return "w __"; - } - - if (this.trim === null) { - this.trim = "both"; - } - - return "w __, d __, h __"; - case "months": // Possible Fallthrough. - if (firstType === lastType) { - return "M __"; - } - case "years": - if (firstType === lastType) { - return "y __"; - } - - if (this.trim === null) { - this.trim = "both"; - } - - return "y __, M __, d __"; - default: - if (this.trim === null) { - this.trim = "both"; - } - - return "y __, d __, h __, m __, s __"; - } - } - - // init - function init(context) { - if (!context) { - throw "Moment Duration Format init cannot find moment instance."; - } - - context.duration.format = durationsFormat; - context.duration.fn.format = durationFormat; - - context.duration.fn.format.defaults = { - // Many options are defaulted to `null` to distinguish between - // 'not set' and 'set to `false`' - - // trim - // Can be a string, a delimited list of strings, an array of strings, - // or a boolean. - // "large" - will trim largest-magnitude zero-value tokens until - // finding a token with a value, a token identified as 'stopTrim', or - // the final token of the format string. - // "small" - will trim smallest-magnitude zero-value tokens until - // finding a token with a value, a token identified as 'stopTrim', or - // the final token of the format string. - // "both" - will execute "large" trim then "small" trim. - // "mid" - will trim any zero-value tokens that are not the first or - // last tokens. Usually used in conjunction with "large" or "both". - // e.g. "large mid" or "both mid". - // "final" - will trim the final token if it is zero-value. Use this - // option with "large" or "both" to output an empty string when - // formatting a zero-value duration. e.g. "large final" or "both final". - // "all" - Will trim all zero-value tokens. Shorthand for "both mid final". - // "left" - maps to "large" to support plugin's version 1 API. - // "right" - maps to "large" to support plugin's version 1 API. - // `false` - template tokens are not trimmed. - // `true` - treated as "large". - // `null` - treated as "large". - trim: null, - - // stopTrim - // A moment token string, a delimited set of moment token strings, - // or an array of moment token strings. Trimming will stop when a token - // listed in this option is reached. A "*" character in the format - // template string will also mark a moment token as stopTrim. - // e.g. "d [days] *h:mm:ss" will always stop trimming at the 'hours' token. - stopTrim: null, - - // largest - // Set to a positive integer to output only the "n" largest-magnitude - // moment tokens that have a value. All lesser-magnitude moment tokens - // will be ignored. This option takes effect even if `trim` is set - // to `false`. - largest: null, - - // maxValue - // Use `maxValue` to render generalized output for large duration values, - // e.g. `"> 60 days"`. `maxValue` must be a positive integer and is - /// applied to the greatest-magnitude moment token in the format template. - maxValue: null, - - // minValue - // Use `minValue` to render generalized output for small duration values, - // e.g. `"< 5 minutes"`. `minValue` must be a positive integer and is - // applied to the least-magnitude moment token in the format template. - minValue: null, - - // precision - // If a positive integer, number of decimal fraction digits to render. - // If a negative integer, number of integer place digits to truncate to 0. - // If `useSignificantDigits` is set to `true` and `precision` is a positive - // integer, sets the maximum number of significant digits used in the - // formatted output. - precision: 0, - - // trunc - // Default behavior rounds final token value. Set to `true` to - // truncate final token value, which was the default behavior in - // version 1 of this plugin. - trunc: false, - - // forceLength - // Force first moment token with a value to render at full length - // even when template is trimmed and first moment token has length of 1. - forceLength: null, - - // userLocale - // Formatted numerical output is rendered using `toLocaleString` - // and the locale of the user's environment. Set this option to render - // numerical output using a different locale. Unit names are rendered - // and detected using the locale set in moment.js, which can be different - // from the locale of user's environment. - userLocale: null, - - // usePlural - // Will automatically singularize or pluralize unit names when they - // appear in the text associated with each moment token. Standard and - // short unit labels are singularized and pluralized, based on locale. - // e.g. in english, "1 second" or "1 sec" would be rendered instead - // of "1 seconds" or "1 secs". The default pluralization function - // renders a plural label for a value with decimal precision. - // e.g. "1.0 seconds" is never rendered as "1.0 second". - // Label types and pluralization function are configurable in the - // localeData extensions. - usePlural: true, - - // useLeftUnits - // The text to the right of each moment token in a format string - // is treated as that token's units for the purposes of trimming, - // singularizing, and auto-localizing. - // e.g. "h [hours], m [minutes], s [seconds]". - // To properly singularize or localize a format string such as - // "[hours] h, [minutes] m, [seconds] s", where the units appear - // to the left of each moment token, set useLeftUnits to `true`. - // This plugin is not tested in the context of rtl text. - useLeftUnits: false, - - // useGrouping - // Enables locale-based digit grouping in the formatted output. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString - useGrouping: true, - - // useSignificantDigits - // Treat the `precision` option as the maximum significant digits - // to be rendered. Precision must be a positive integer. Significant - // digits extend across unit types, - // e.g. "6 hours 37.5 minutes" represents 4 significant digits. - // Enabling this option causes token length to be ignored. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString - useSignificantDigits: false, - - // template - // The template string used to format the duration. May be a function - // or a string. Template functions are executed with the `this` binding - // of the settings object so that template strings may be dynamically - // generated based on the duration object (accessible via `this.duration`) - // or any of the other settings. Leading and trailing space, comma, - // period, and colon characters are trimmed from the resulting string. - template: defaultFormatTemplate, - - // useToLocaleString - // Set this option to `false` to ignore the `toLocaleString` feature - // test and force the use of the `formatNumber` fallback function - // included in this plugin. - useToLocaleString: true, - - // formatNumber fallback options. - // When `toLocaleString` is detected and passes the feature test, the - // following options will have no effect: `toLocaleString` will be used - // for formatting and the grouping separator, decimal separator, and - // integer digit grouping will be determined by the user locale. - - // groupingSeparator - // The integer digit grouping separator used when using the fallback - // formatNumber function. - groupingSeparator: ",", - - // decimalSeparator - // The decimal separator used when using the fallback formatNumber - // function. - decimalSeparator: ".", - - // grouping - // The integer digit grouping used when using the fallback formatNumber - // function. Must be an array. The default value of `[3]` gives the - // standard 3-digit thousand/million/billion digit groupings for the - // "en" locale. Setting this option to `[3, 2]` would generate the - // thousand/lakh/crore digit groupings used in the "en-IN" locale. - grouping: [3] - }; - - context.updateLocale('en', engLocale); - } - - // Run feature tests for `Number#toLocaleString`. - toLocaleStringWorks = featureTestToLocaleString(); - toLocaleStringRoundingWorks = toLocaleStringWorks && featureTestToLocaleStringRounding(); - - // Initialize duration format on the global moment instance. - init(moment); - - // Return the init function so that duration format can be - // initialized on other moment instances. - return init; -}); diff --git a/dist/src/img/clock_panel_logo.svg b/dist/img/clock_panel_logo.svg similarity index 100% rename from dist/src/img/clock_panel_logo.svg rename to dist/img/clock_panel_logo.svg diff --git a/dist/src/img/countdown1.png b/dist/img/countdown1.png similarity index 100% rename from dist/src/img/countdown1.png rename to dist/img/countdown1.png diff --git a/dist/src/img/screenshot-clock-options.png b/dist/img/screenshot-clock-options.png similarity index 100% rename from dist/src/img/screenshot-clock-options.png rename to dist/img/screenshot-clock-options.png diff --git a/dist/src/img/screenshot-clocks.png b/dist/img/screenshot-clocks.png similarity index 100% rename from dist/src/img/screenshot-clocks.png rename to dist/img/screenshot-clocks.png diff --git a/dist/src/img/screenshot-showcase.png b/dist/img/screenshot-showcase.png similarity index 100% rename from dist/src/img/screenshot-showcase.png rename to dist/img/screenshot-showcase.png diff --git a/dist/module.js b/dist/module.js index 995a7cb..7c82963 100644 --- a/dist/module.js +++ b/dist/module.js @@ -1,14 +1,22 @@ -'use strict'; - -System.register(['./clock_ctrl'], function (_export, _context) { - var ClockCtrl; - return { - setters: [function (_clock_ctrl) { - ClockCtrl = _clock_ctrl.ClockCtrl; - }], - execute: function () { - _export('PanelCtrl', ClockCtrl); - } - }; -}); -//# sourceMappingURL=module.js.map +define(["moment","app/plugins/sdk","lodash"],function(t,e,n){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=1)}([function(e,n){e.exports=t},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.PanelCtrl=void 0;var r=n(2);e.PanelCtrl=r.ClockCtrl},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ClockCtrl=void 0;var r=n(3),i=a(n(0));n(4);var o=a(n(5));function a(t){return t&&t.__esModule?t:{default:t}}n(6);var s=function(){var t=function(e,n){return(t=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n])})(e,n)};return function(e,n){function r(){this.constructor=e}t(e,n),e.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),u=function(t){function e(e,n){var r=t.call(this,e,n)||this;return r.panelDefaults={mode:"time",clockType:"24 hour",offsetFromUtc:null,offsetFromUtcMinutes:null,bgColor:null,countdownSettings:{endCountdownTime:(0,i.default)().seconds(0).milliseconds(0).add(1,"day").toDate(),endText:"00:00:00",customFormat:null},dateSettings:{showDate:!1,dateFormat:"YYYY-MM-DD",fontSize:"20px",fontWeight:"normal"},timeSettings:{customFormat:"HH:mm:ss",fontSize:"60px",fontWeight:"normal"},refreshSettings:{syncWithDashboard:!1}},o.default.defaultsDeep(r.panel,r.panelDefaults),r.panel.countdownSettings.endCountdownTime instanceof Date||(r.panel.countdownSettings.endCountdownTime=(0,i.default)(r.panel.countdownSettings.endCountdownTime).toDate()),r.events.on("init-edit-mode",r.onInitEditMode.bind(r)),r.events.on("panel-teardown",r.onPanelTeardown.bind(r)),r.events.on("component-did-mount",r.render.bind(r)),r.events.on("refresh",r.updateClock.bind(r)),r.events.on("render",r.updateClock.bind(r)),r.updateClock(),r}return s(e,t),e.$inject=["$scope","$injector"],e.prototype.onInitEditMode=function(){this.addEditorTab("Options","public/plugins/grafana-clock-panel/partials/options.html",2),this.addEditorTab("Refresh","public/plugins/grafana-clock-panel/partials/refresh.html",2)},e.prototype.onPanelTeardown=function(){this.$timeout.cancel(this.nextTickPromise)},e.prototype.updateClock=function(){this.$timeout.cancel(this.nextTickPromise),"time"===this.panel.mode?this.renderTime():this.renderCountdown(),this.panel.refreshSettings.syncWithDashboard||(this.nextTickPromise=this.$timeout(this.updateClock.bind(this),1e3))},e.prototype.renderTime=function(){var t;if(this.panel.offsetFromUtc&&this.panel.offsetFromUtcMinutes){var e=60*parseInt(this.panel.offsetFromUtc,10)+parseInt(this.panel.offsetFromUtcMinutes,10);t=(0,i.default)().utcOffset(e)}else t=this.panel.offsetFromUtc&&!this.panel.offsetFromUtcMinutes?(0,i.default)().utcOffset(parseInt(this.panel.offsetFromUtc,10)):(0,i.default)();this.panel.dateSettings.showDate&&(this.date=t.format(this.panel.dateSettings.dateFormat)),this.time=t.format(this.getTimeFormat())},e.prototype.getTimeFormat=function(){return"24 hour"===this.panel.clockType?"HH:mm:ss":"12 hour"===this.panel.clockType?"h:mm:ss A":this.panel.timeSettings.customFormat},e.prototype.renderCountdown=function(){this.panel.countdownSettings.endCountdownTime||(this.time=this.panel.countdownSettings.endText);var t=(0,i.default)(),e=i.default.duration((0,i.default)(this.panel.countdownSettings.endCountdownTime).diff(t)),n="";if(e.asSeconds()<=0)this.time=this.panel.countdownSettings.endText;else if("auto"!==this.panel.countdownSettings.customFormat)if(this.panel.countdownSettings.customFormat)this.time=e.format(this.panel.countdownSettings.customFormat);else{var r="";e.years()>0&&(n=1===e.years()?"1 year, ":e.years()+" years, ",r="years"),(e.months()>0||"years"===r)&&(n+=1===e.months()?"1 month, ":e.months()+" months, ",r="month"),(e.days()>0||"months"===r)&&(n+=1===e.days()?"1 day, ":e.days()+" days, ",r="days"),(e.hours()>0||"days"===r)&&(n+=1===e.hours()?"1 hour, ":e.hours()+" hours, ",r="hours"),(e.minutes()>0||"hours"===r)&&(n+=1===e.minutes()?"1 minute, ":e.minutes()+" minutes, "),n+=1===e.seconds()?"1 second ":e.seconds()+" seconds",this.time=n}else this.time=e.format()},e.prototype.link=function(t,e){var n=this;this.events.on("render",function(){var t=e.find(".panel-container");n.panel.bgColor?t.css("background-color",n.panel.bgColor):t.css("background-color","")})},e.templateUrl="partials/module.html",e}(r.PanelCtrl);e.ClockCtrl=u},function(t,n){t.exports=e},function(t,e,n){var r,i,o,a,s; +/*! Moment Duration Format v2.2.1 + * https://github.com/jsmreese/moment-duration-format + * Date: 2018-01-21 + * + * Duration format plugin function for the Moment.js library + * http://momentjs.com/ + * + * Copyright 2018 John Madhavan-Reese + * Released under the MIT license + */ +/*! Moment Duration Format v2.2.1 + * https://github.com/jsmreese/moment-duration-format + * Date: 2018-01-21 + * + * Duration format plugin function for the Moment.js library + * http://momentjs.com/ + * + * Copyright 2018 John Madhavan-Reese + * Released under the MIT license + */a=this,s=function(t){var e=!1,n=!1,r="escape years months weeks days hours minutes seconds milliseconds general".split(" "),i=[{type:"seconds",targets:[{type:"minutes",value:60},{type:"hours",value:3600},{type:"days",value:86400},{type:"weeks",value:604800},{type:"months",value:2678400},{type:"years",value:31536e3}]},{type:"minutes",targets:[{type:"hours",value:60},{type:"days",value:1440},{type:"weeks",value:10080},{type:"months",value:44640},{type:"years",value:525600}]},{type:"hours",targets:[{type:"days",value:24},{type:"weeks",value:168},{type:"months",value:744},{type:"years",value:8760}]},{type:"days",targets:[{type:"weeks",value:7},{type:"months",value:31},{type:"years",value:365}]},{type:"months",targets:[{type:"years",value:12}]}];function o(t,e){return!(e.length>t.length)&&-1!==t.indexOf(e)}function a(t){for(var e="";t;)e+="0",t-=1;return e}function s(t,e,r){var i,o,u,l=e.useToLocaleString,c=e.useGrouping,f=c&&e.grouping.slice(),p=e.maximumSignificantDigits,m=e.minimumIntegerDigits||1,d=e.fractionDigits||0,h=e.groupingSeparator,g=e.decimalSeparator;if(l&&r){var y={minimumIntegerDigits:m,useGrouping:c};if(d&&(y.maximumFractionDigits=d,y.minimumFractionDigits=d),p&&t>0&&(y.maximumSignificantDigits=p),!n){var v=b({},e);v.useGrouping=!1,v.decimalSeparator=".",t=parseFloat(s(t,v),10)}return t.toLocaleString(r,y)}var w=(p?t.toPrecision(p+1):t.toFixed(d+1)).split("e");u=w[1]||"",o=(w=w[0].split("."))[1]||"";var S=(i=w[0]||"").length,x=o.length,_=S+x,L=i+o;(p&&_===p+1||!p&&x===d+1)&&((L=function(t){for(var e=L.split("").reverse(),n=0,r=!0;r&&n0?o.length<=M?(i+=o+=a(M-o.length),o=""):(i+=o.slice(0,M),o=o.slice(M)):M<0&&(o=a(Math.abs(M)-i.length)+i+o,i="0"),p||((o=o.slice(0,d)).lengthe.label.length?-1:t.label.length0,Y=W?a.precision:0,q=Y,J=a.minValue,z=!1,K=a.maxValue,Q=!1,X=a.useToLocaleString,Z=a.groupingSeparator,tt=a.decimalSeparator,et=a.grouping;X=X&&e;var nt=a.trim;c(nt)&&(nt=nt.join(" ")),null===nt&&(U||K||W)&&(nt="all"),null!==nt&&!0!==nt&&"left"!==nt&&"right"!==nt||(nt="large"),!1===nt&&(nt="");var rt=function(t){return t.test(nt)},it=/both/,ot=/^all|[^sm]all/,at=U>0||x([/large/,it,ot],rt),st=x([/small/,it,ot],rt),ut=x([/mid/,ot],rt),lt=x([/final/,ot],rt),ct=d(F.match(j),function(t,e){var n=C(t);return"*"===t.slice(0,1)&&(t=t.slice(1),"escape"!==n&&"general"!==n&&I.push(n)),{index:e,length:t.length,text:"",token:"escape"===n?t.replace(k.escape,"$1"):t,type:"escape"===n||"general"===n?null:n}}),ft={index:0,length:0,token:"",text:"",type:null},pt=[];R&&ct.reverse(),m(ct,function(t){if(t.type)return(ft.type||ft.text)&&pt.push(ft),void(ft=t);R?ft.text=t.token+ft.text:ft.text+=t.token}),(ft.type||ft.text)&&pt.push(ft),R&&pt.reverse();var mt=v(r,y(g(h(pt,"type"))));if(!mt.length)return h(pt,"text").join("");mt=d(mt,function(t,e){var n,r=e+1===mt.length,i=!e;n="years"===t||"months"===t?V.as(t):T.as(t);var o=Math.floor(n),s=n-o,u=p(pt,function(e){return t===e.type});return i&&K&&n>K&&(Q=!0),r&&J&&Math.abs(a.duration.as(t))1&&($=!0),T.subtract(o,t),V.subtract(o,t),{rawValue:n,wholeValue:o,decimalValue:r?s:0,isSmallest:r,isLargest:i,type:t,tokenLength:u.length}});var dt=N?Math.floor:Math.round,ht=function(t,e){var n=Math.pow(10,e);return dt(t*n)/n},gt=!1,yt=!1,vt=function(t,e){var n={useGrouping:H,groupingSeparator:Z,decimalSeparator:tt,grouping:et,useToLocaleString:X};return W&&(Y<=0?(t.rawValue=0,t.wholeValue=0,t.decimalValue=0):(n.maximumSignificantDigits=Y,t.significantDigits=Y)),Q&&!yt&&(t.isLargest?(t.wholeValue=K,t.decimalValue=0):(t.wholeValue=0,t.decimalValue=0)),z&&!yt&&(t.isSmallest?(t.wholeValue=J,t.decimalValue=0):(t.wholeValue=0,t.decimalValue=0)),t.isSmallest||t.significantDigits&&t.significantDigits-t.wholeValue.toString().length<=0?G<0?t.value=ht(t.wholeValue,G):0===G?t.value=dt(t.wholeValue+t.decimalValue):W?(t.value=N?ht(t.rawValue,Y-t.wholeValue.toString().length):t.rawValue,t.wholeValue&&(Y-=t.wholeValue.toString().length)):(n.fractionDigits=G,t.value=N?t.wholeValue+ht(t.decimalValue,G):t.wholeValue+t.decimalValue):W&&t.wholeValue?(t.value=Math.round(ht(t.wholeValue,t.significantDigits-t.wholeValue.toString().length)),Y-=t.wholeValue.toString().length):t.value=t.wholeValue,t.tokenLength>1&&($||gt)&&(n.minimumIntegerDigits=t.tokenLength,yt&&n.maximumSignificantDigits0||""===nt||p(I,t.type)||p(O,t.type))&&(gt=!0),t.formattedValue=s(t.value,n,P),n.useGrouping=!1,n.decimalSeparator=".",t.formattedValueEn=s(t.value,n,"en"),2===t.tokenLength&&"milliseconds"===t.type&&(t.formattedValueMS=s(t.value,{minimumIntegerDigits:3,useGrouping:!1},"en").slice(0,2)),t};if((mt=g(mt=d(mt,vt))).length>1){var wt=function(t){return p(mt,function(e){return e.type===t})};m(i,function(t){var e=wt(t.type);e&&m(t.targets,function(t){var n=wt(t.type);n&&parseInt(e.formattedValueEn,10)===t.value&&(e.rawValue=0,e.wholeValue=0,e.decimalValue=0,n.rawValue+=1,n.wholeValue+=1,n.decimalValue=0,n.formattedValueEn=n.wholeValue.toString(),yt=!0)})})}return yt&&(gt=!1,Y=q,mt=g(mt=d(mt,vt))),!O||Q&&!a.trim?(at&&(mt=w(mt,function(t){return!t.isSmallest&&!t.wholeValue&&!p(I,t.type)})),U&&mt.length&&(mt=mt.slice(0,U)),st&&mt.length>1&&(mt=w(mt.slice().reverse(),function(t){return!t.wholeValue&&!p(I,t.type)&&!t.isLargest}).reverse()),ut&&(mt=g(mt=d(mt,function(t,e){return e>0&&e ",Q=!1,z=!1),M&&(e.value>0||p(I,e.type)||p(O,e.type))&&(n+="-",M=!1),"milliseconds"===t.type&&e.formattedValueMS?n+=e.formattedValueMS:n+=e.formattedValue,R||(n+=t.text),n})).join("").replace(/(,| |:|\.)*$/,"").replace(/^(,| |:|\.)*/,""))}function M(){var t=this.duration,e=function(e){return t._data[e]},n=p(this.types,e),r=function(t,e){for(var n=t.length;n-=1;)if(e(t[n]))return t[n]}(this.types,e);switch(n){case"milliseconds":return"S __";case"seconds":case"minutes":return"*_MS_";case"hours":return"_HMS_";case"days":if(n===r)return"d __";case"weeks":return n===r?"w __":(null===this.trim&&(this.trim="both"),"w __, d __, h __");case"months":if(n===r)return"M __";case"years":return n===r?"y __":(null===this.trim&&(this.trim="both"),"y __, M __, d __");default:return null===this.trim&&(this.trim="both"),"y __, d __, h __, m __, s __"}}function T(t){if(!t)throw"Moment Duration Format init cannot find moment instance.";t.duration.format=_,t.duration.fn.format=L,t.duration.fn.format.defaults={trim:null,stopTrim:null,largest:null,maxValue:null,minValue:null,precision:0,trunc:!1,forceLength:null,userLocale:null,usePlural:!0,useLeftUnits:!1,useGrouping:!0,useSignificantDigits:!1,template:M,useToLocaleString:!0,groupingSeparator:",",decimalSeparator:".",grouping:[3]},t.updateLocale("en",l)}return e=function(){var t=!0;return!!((t=t&&function(){try{(0).toLocaleString("i")}catch(t){return"RangeError"===t.name}return!1}())&&(t=(t=(t=t&&"1"===1..toLocaleString("en",{minimumIntegerDigits:1}))&&"01"===1..toLocaleString("en",{minimumIntegerDigits:2}))&&"001"===1..toLocaleString("en",{minimumIntegerDigits:3}))&&(t=(t=(t=(t=t&&"100"===99.99.toLocaleString("en",{maximumFractionDigits:0,minimumFractionDigits:0}))&&"100.0"===99.99.toLocaleString("en",{maximumFractionDigits:1,minimumFractionDigits:1}))&&"99.99"===99.99.toLocaleString("en",{maximumFractionDigits:2,minimumFractionDigits:2}))&&"99.990"===99.99.toLocaleString("en",{maximumFractionDigits:3,minimumFractionDigits:3}))&&(t=(t=(t=(t=(t=t&&"100"===99.99.toLocaleString("en",{maximumSignificantDigits:1}))&&"100"===99.99.toLocaleString("en",{maximumSignificantDigits:2}))&&"100"===99.99.toLocaleString("en",{maximumSignificantDigits:3}))&&"99.99"===99.99.toLocaleString("en",{maximumSignificantDigits:4}))&&"99.99"===99.99.toLocaleString("en",{maximumSignificantDigits:5}))&&(t=(t=t&&"1,000"===1e3.toLocaleString("en",{useGrouping:!0}))&&"1000"===1e3.toLocaleString("en",{useGrouping:!1})))}(),n=e&&"3.6"===3.55.toLocaleString("en",{useGrouping:!1,minimumIntegerDigits:1,minimumFractionDigits:1,maximumFractionDigits:1}),T(t),T},i=[n(0)],void 0===(o="function"==typeof(r=s)?r.apply(e,i):r)||(t.exports=o),a&&(a.momentDurationFormatSetup=a.moment?s(a.moment):s)},function(t,e){t.exports=n},function(t,e,n){var r=n(7);"string"==typeof r&&(r=[[t.i,r,""]]);n(9)(r,{hmr:!0,transform:void 0,insertInto:void 0}),r.locals&&(t.exports=r.locals)},function(t,e,n){(t.exports=n(8)(!0)).push([t.i,".clock-panel {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n}\n","",{version:3,sources:["/home/daniel/dev/go/src/github.com/grafana/grafana/data/plugins/clock-panel/src/css/clock-panel.css"],names:[],mappings:"AAAA;EACE,cAAc;EACd,oBAAoB;EACpB,wBAAwB;EACxB,uBAAuB;CACxB",file:"clock-panel.css",sourcesContent:[".clock-panel {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n}\n"],sourceRoot:""}])},function(t,e){t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var n=function(t,e){var n=t[1]||"",r=t[3];if(!r)return n;if(e&&"function"==typeof btoa){var i=function(t){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(t))))+" */"}(r),o=r.sources.map(function(t){return"/*# sourceURL="+r.sourceRoot+t+" */"});return[n].concat(o).concat([i]).join("\n")}return[n].join("\n")}(e,t);return e[2]?"@media "+e[2]+"{"+n+"}":n}).join("")},e.i=function(t,n){"string"==typeof t&&(t=[[null,t,""]]);for(var r={},i=0;i=0&&u.splice(e,1)}function d(t){var e=document.createElement("style");if(void 0===t.attrs.type&&(t.attrs.type="text/css"),void 0===t.attrs.nonce){var r=n.nc;r&&(t.attrs.nonce=r)}return h(e,t.attrs),p(t,e),e}function h(t,e){Object.keys(e).forEach(function(n){t.setAttribute(n,e[n])})}function g(t,e){var n,r,i,o;if(e.transform&&t.css){if(!(o="function"==typeof e.transform?e.transform(t.css):e.transform.default(t.css)))return function(){};t.css=o}if(e.singleton){var u=s++;n=a||(a=d(e)),r=v.bind(null,n,u,!1),i=v.bind(null,n,u,!0)}else t.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(n=function(t){var e=document.createElement("link");return void 0===t.attrs.type&&(t.attrs.type="text/css"),t.attrs.rel="stylesheet",h(e,t.attrs),p(t,e),e}(e),r=function(t,e,n){var r=n.css,i=n.sourceMap,o=void 0===e.convertToAbsoluteUrls&&i;(e.convertToAbsoluteUrls||o)&&(r=l(r)),i&&(r+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(i))))+" */");var a=new Blob([r],{type:"text/css"}),s=t.href;t.href=URL.createObjectURL(a),s&&URL.revokeObjectURL(s)}.bind(null,n,e),i=function(){m(n),n.href&&URL.revokeObjectURL(n.href)}):(n=d(e),r=function(t,e){var n=e.css,r=e.media;if(r&&t.setAttribute("media",r),t.styleSheet)t.styleSheet.cssText=n;else{for(;t.firstChild;)t.removeChild(t.firstChild);t.appendChild(document.createTextNode(n))}}.bind(null,n),i=function(){m(n)});return r(t),function(e){if(e){if(e.css===t.css&&e.media===t.media&&e.sourceMap===t.sourceMap)return;r(t=e)}else i()}}t.exports=function(t,e){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(e=e||{}).attrs="object"==typeof e.attrs?e.attrs:{},e.singleton||"boolean"==typeof e.singleton||(e.singleton=i()),e.insertInto||(e.insertInto="head"),e.insertAt||(e.insertAt="bottom");var n=f(t,e);return c(n,e),function(t){for(var i=[],o=0;o 0) {\n formattedTimeLeft = timeLeft.years() === 1 ? '1 year, ' : timeLeft.years() + ' years, ';\n previous = 'years';\n }\n if (timeLeft.months() > 0 || previous === 'years') {\n formattedTimeLeft += timeLeft.months() === 1 ? '1 month, ' : timeLeft.months() + ' months, ';\n previous = 'month';\n }\n if (timeLeft.days() > 0 || previous === 'months') {\n formattedTimeLeft += timeLeft.days() === 1 ? '1 day, ' : timeLeft.days() + ' days, ';\n previous = 'days';\n }\n if (timeLeft.hours() > 0 || previous === 'days') {\n formattedTimeLeft += timeLeft.hours() === 1 ? '1 hour, ' : timeLeft.hours() + ' hours, ';\n previous = 'hours';\n }\n\n if (timeLeft.minutes() > 0 || previous === 'hours') {\n formattedTimeLeft += timeLeft.minutes() === 1 ? '1 minute, ' : timeLeft.minutes() + ' minutes, ';\n }\n\n formattedTimeLeft += timeLeft.seconds() === 1 ? '1 second ' : timeLeft.seconds() + ' seconds';\n this.time = formattedTimeLeft;\n }\n\n link(scope, elem) {\n this.events.on('render', () => {\n const $panelContainer = elem.find('.panel-container');\n\n if (this.panel.bgColor) {\n $panelContainer.css('background-color', this.panel.bgColor);\n } else {\n $panelContainer.css('background-color', '');\n }\n });\n }\n}\n","/*! Moment Duration Format v2.2.1\n * https://github.com/jsmreese/moment-duration-format\n * Date: 2018-01-21\n *\n * Duration format plugin function for the Moment.js library\n * http://momentjs.com/\n *\n * Copyright 2018 John Madhavan-Reese\n * Released under the MIT license\n */\n\n(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define(['moment'], factory);\n } else if (typeof exports === 'object') {\n // Node. Does not work with strict CommonJS, but only CommonJS-like\n // enviroments that support module.exports, like Node.\n try {\n module.exports = factory(require('moment'));\n } catch (e) {\n // If moment is not available, leave the setup up to the user.\n // Like when using moment-timezone or similar moment-based package.\n module.exports = factory;\n }\n }\n\n if (root) {\n // Globals.\n root.momentDurationFormatSetup = root.moment ? factory(root.moment) : factory;\n }\n})(this, function (moment) {\n // `Number#tolocaleString` is tested on plugin initialization.\n // If the feature test passes, `toLocaleStringWorks` will be set to `true` and the\n // native function will be used to generate formatted output. If the feature\n // test fails, the fallback format function internal to this plugin will be\n // used.\n var toLocaleStringWorks = false;\n\n // `Number#toLocaleString` rounds incorrectly for select numbers in Microsoft\n // environments (Edge, IE11, Windows Phone) and possibly other environments.\n // If the rounding test fails and `toLocaleString` will be used for formatting,\n // the plugin will \"pre-round\" number values using the fallback number format\n // function before passing them to `toLocaleString` for final formatting.\n var toLocaleStringRoundingWorks = false;\n\n // Token type names in order of descending magnitude.\n var types = \"escape years months weeks days hours minutes seconds milliseconds general\".split(\" \");\n\n var bubbles = [\n {\n type: \"seconds\",\n targets: [\n { type: \"minutes\", value: 60 },\n { type: \"hours\", value: 3600 },\n { type: \"days\", value: 86400 },\n { type: \"weeks\", value: 604800 },\n { type: \"months\", value: 2678400 },\n { type: \"years\", value: 31536000 }\n ]\n },\n {\n type: \"minutes\",\n targets: [\n { type: \"hours\", value: 60 },\n { type: \"days\", value: 1440 },\n { type: \"weeks\", value: 10080 },\n { type: \"months\", value: 44640 },\n { type: \"years\", value: 525600 }\n ]\n },\n {\n type: \"hours\",\n targets: [\n { type: \"days\", value: 24 },\n { type: \"weeks\", value: 168 },\n { type: \"months\", value: 744 },\n { type: \"years\", value: 8760 }\n ]\n },\n {\n type: \"days\",\n targets: [\n { type: \"weeks\", value: 7 },\n { type: \"months\", value: 31 },\n { type: \"years\", value: 365 }\n ]\n },\n {\n type: \"months\",\n targets: [\n { type: \"years\", value: 12 }\n ]\n }\n ];\n\n // stringIncludes\n function stringIncludes(str, search) {\n if (search.length > str.length) {\n return false;\n }\n\n return str.indexOf(search) !== -1;\n }\n\n // repeatZero(qty)\n // Returns \"0\" repeated `qty` times.\n // `qty` must be a integer >= 0.\n function repeatZero(qty) {\n var result = \"\";\n\n while (qty) {\n result += \"0\";\n qty -= 1;\n }\n\n return result;\n }\n\n function stringRound(digits) {\n var digitsArray = digits.split(\"\").reverse();\n var i = 0;\n var carry = true;\n\n while (carry && i < digitsArray.length) {\n if (i) {\n if (digitsArray[i] === \"9\") {\n digitsArray[i] = \"0\";\n } else {\n digitsArray[i] = (parseInt(digitsArray[i], 10) + 1).toString();\n carry = false;\n }\n } else {\n if (parseInt(digitsArray[i], 10) < 5) {\n carry = false;\n }\n\n digitsArray[i] = \"0\";\n }\n\n i += 1;\n }\n\n if (carry) {\n digitsArray.push(\"1\");\n }\n\n return digitsArray.reverse().join(\"\");\n }\n\n // formatNumber\n // Formats any number greater than or equal to zero using these options:\n // - userLocale\n // - useToLocaleString\n // - useGrouping\n // - grouping\n // - maximumSignificantDigits\n // - minimumIntegerDigits\n // - fractionDigits\n // - groupingSeparator\n // - decimalSeparator\n //\n // `useToLocaleString` will use `toLocaleString` for formatting.\n // `userLocale` option is passed through to `toLocaleString`.\n // `fractionDigits` is passed through to `maximumFractionDigits` and `minimumFractionDigits`\n // Using `maximumSignificantDigits` will override `minimumIntegerDigits` and `fractionDigits`.\n function formatNumber(number, options, userLocale) {\n var useToLocaleString = options.useToLocaleString;\n var useGrouping = options.useGrouping;\n var grouping = useGrouping && options.grouping.slice();\n var maximumSignificantDigits = options.maximumSignificantDigits;\n var minimumIntegerDigits = options.minimumIntegerDigits || 1;\n var fractionDigits = options.fractionDigits || 0;\n var groupingSeparator = options.groupingSeparator;\n var decimalSeparator = options.decimalSeparator;\n\n if (useToLocaleString && userLocale) {\n var localeStringOptions = {\n minimumIntegerDigits: minimumIntegerDigits,\n useGrouping: useGrouping\n };\n\n if (fractionDigits) {\n localeStringOptions.maximumFractionDigits = fractionDigits;\n localeStringOptions.minimumFractionDigits = fractionDigits;\n }\n\n // toLocaleString output is \"0.0\" instead of \"0\" for HTC browsers\n // when maximumSignificantDigits is set. See #96.\n if (maximumSignificantDigits && number > 0) {\n localeStringOptions.maximumSignificantDigits = maximumSignificantDigits;\n }\n\n if (!toLocaleStringRoundingWorks) {\n var roundingOptions = extend({}, options);\n roundingOptions.useGrouping = false;\n roundingOptions.decimalSeparator = \".\";\n number = parseFloat(formatNumber(number, roundingOptions), 10);\n }\n\n return number.toLocaleString(userLocale, localeStringOptions);\n }\n\n var numberString;\n\n // Add 1 to digit output length for floating point errors workaround. See below.\n if (maximumSignificantDigits) {\n numberString = number.toPrecision(maximumSignificantDigits + 1);\n } else {\n numberString = number.toFixed(fractionDigits + 1);\n }\n\n var integerString;\n var fractionString;\n var exponentString;\n\n var temp = numberString.split(\"e\");\n\n exponentString = temp[1] || \"\";\n\n temp = temp[0].split(\".\");\n\n fractionString = temp[1] || \"\";\n integerString = temp[0] || \"\";\n\n // Workaround for floating point errors in `toFixed` and `toPrecision`.\n // (3.55).toFixed(1); --> \"3.5\"\n // (123.55 - 120).toPrecision(2); --> \"3.5\"\n // (123.55 - 120); --> 3.549999999999997\n // (123.55 - 120).toFixed(2); --> \"3.55\"\n // Round by examing the string output of the next digit.\n\n // *************** Implement String Rounding here ***********************\n // Check integerString + fractionString length of toPrecision before rounding.\n // Check length of fractionString from toFixed output before rounding.\n var integerLength = integerString.length;\n var fractionLength = fractionString.length;\n var digitCount = integerLength + fractionLength;\n var digits = integerString + fractionString;\n\n if (maximumSignificantDigits && digitCount === (maximumSignificantDigits + 1) || !maximumSignificantDigits && fractionLength === (fractionDigits + 1)) {\n // Round digits.\n digits = stringRound(digits);\n\n if (digits.length === digitCount + 1) {\n integerLength = integerLength + 1;\n }\n\n // Discard final fractionDigit.\n if (fractionLength) {\n digits = digits.slice(0, -1);\n }\n\n // Separate integer and fraction.\n integerString = digits.slice(0, integerLength);\n fractionString = digits.slice(integerLength);\n }\n\n // Trim trailing zeroes from fractionString because toPrecision outputs\n // precision, not significant digits.\n if (maximumSignificantDigits) {\n fractionString = fractionString.replace(/0*$/, \"\");\n }\n\n // Handle exponent.\n var exponent = parseInt(exponentString, 10);\n\n if (exponent > 0) {\n if (fractionString.length <= exponent) {\n fractionString = fractionString + repeatZero(exponent - fractionString.length);\n\n integerString = integerString + fractionString;\n fractionString = \"\";\n } else {\n integerString = integerString + fractionString.slice(0, exponent);\n fractionString = fractionString.slice(exponent);\n }\n } else if (exponent < 0) {\n fractionString = (repeatZero(Math.abs(exponent) - integerString.length) + integerString + fractionString);\n\n integerString = \"0\";\n }\n\n if (!maximumSignificantDigits) {\n // Trim or pad fraction when not using maximumSignificantDigits.\n fractionString = fractionString.slice(0, fractionDigits);\n\n if (fractionString.length < fractionDigits) {\n fractionString = fractionString + repeatZero(fractionDigits - fractionString.length);\n }\n\n // Pad integer when using minimumIntegerDigits\n // and not using maximumSignificantDigits.\n if (integerString.length < minimumIntegerDigits) {\n integerString = repeatZero(minimumIntegerDigits - integerString.length) + integerString;\n }\n }\n\n var formattedString = \"\";\n\n // Handle grouping.\n if (useGrouping) {\n temp = integerString;\n var group;\n\n while (temp.length) {\n if (grouping.length) {\n group = grouping.shift();\n }\n\n if (formattedString) {\n formattedString = groupingSeparator + formattedString;\n }\n\n formattedString = temp.slice(-group) + formattedString;\n\n temp = temp.slice(0, -group);\n }\n } else {\n formattedString = integerString;\n }\n\n // Add decimalSeparator and fraction.\n if (fractionString) {\n formattedString = formattedString + decimalSeparator + fractionString;\n }\n\n return formattedString;\n }\n\n // durationLabelCompare\n function durationLabelCompare(a, b) {\n if (a.label.length > b.label.length) {\n return -1;\n }\n\n if (a.label.length < b.label.length) {\n return 1;\n }\n\n // a must be equal to b\n return 0;\n }\n\n // durationGetLabels\n function durationGetLabels(token, localeData) {\n var labels = [];\n\n each(keys(localeData), function (localeDataKey) {\n if (localeDataKey.slice(0, 15) !== \"_durationLabels\") {\n return;\n }\n\n var labelType = localeDataKey.slice(15).toLowerCase();\n\n each(keys(localeData[localeDataKey]), function (labelKey) {\n if (labelKey.slice(0, 1) === token) {\n labels.push({\n type: labelType,\n key: labelKey,\n label: localeData[localeDataKey][labelKey]\n });\n }\n });\n });\n\n return labels;\n }\n\n // durationPluralKey\n function durationPluralKey(token, integerValue, decimalValue) {\n // Singular for a value of `1`, but not for `1.0`.\n if (integerValue === 1 && decimalValue === null) {\n return token;\n }\n\n return token + token;\n }\n\n var engLocale = {\n durationLabelsStandard: {\n S: 'millisecond',\n SS: 'milliseconds',\n s: 'second',\n ss: 'seconds',\n m: 'minute',\n mm: 'minutes',\n h: 'hour',\n hh: 'hours',\n d: 'day',\n dd: 'days',\n w: 'week',\n ww: 'weeks',\n M: 'month',\n MM: 'months',\n y: 'year',\n yy: 'years'\n },\n durationLabelsShort: {\n S: 'msec',\n SS: 'msecs',\n s: 'sec',\n ss: 'secs',\n m: 'min',\n mm: 'mins',\n h: 'hr',\n hh: 'hrs',\n d: 'dy',\n dd: 'dys',\n w: 'wk',\n ww: 'wks',\n M: 'mo',\n MM: 'mos',\n y: 'yr',\n yy: 'yrs'\n },\n durationTimeTemplates: {\n HMS: 'h:mm:ss',\n HM: 'h:mm',\n MS: 'm:ss'\n },\n durationLabelTypes: [\n { type: \"standard\", string: \"__\" },\n { type: \"short\", string: \"_\" }\n ],\n durationPluralKey: durationPluralKey\n };\n\n // isArray\n function isArray(array) {\n return Object.prototype.toString.call(array) === \"[object Array]\";\n }\n\n // isObject\n function isObject(obj) {\n return Object.prototype.toString.call(obj) === \"[object Object]\";\n }\n\n // findLast\n function findLast(array, callback) {\n var index = array.length;\n\n while (index -= 1) {\n if (callback(array[index])) { return array[index]; }\n }\n }\n\n // find\n function find(array, callback) {\n var index = 0;\n\n var max = array && array.length || 0;\n\n var match;\n\n if (typeof callback !== \"function\") {\n match = callback;\n callback = function (item) {\n return item === match;\n };\n }\n\n while (index < max) {\n if (callback(array[index])) { return array[index]; }\n index += 1;\n }\n }\n\n // each\n function each(array, callback) {\n var index = 0,\n max = array.length;\n\n if (!array || !max) { return; }\n\n while (index < max) {\n if (callback(array[index], index) === false) { return; }\n index += 1;\n }\n }\n\n // map\n function map(array, callback) {\n var index = 0,\n max = array.length,\n ret = [];\n\n if (!array || !max) { return ret; }\n\n while (index < max) {\n ret[index] = callback(array[index], index);\n index += 1;\n }\n\n return ret;\n }\n\n // pluck\n function pluck(array, prop) {\n return map(array, function (item) {\n return item[prop];\n });\n }\n\n // compact\n function compact(array) {\n var ret = [];\n\n each(array, function (item) {\n if (item) { ret.push(item); }\n });\n\n return ret;\n }\n\n // unique\n function unique(array) {\n var ret = [];\n\n each(array, function (_a) {\n if (!find(ret, _a)) { ret.push(_a); }\n });\n\n return ret;\n }\n\n // intersection\n function intersection(a, b) {\n var ret = [];\n\n each(a, function (_a) {\n each(b, function (_b) {\n if (_a === _b) { ret.push(_a); }\n });\n });\n\n return unique(ret);\n }\n\n // rest\n function rest(array, callback) {\n var ret = [];\n\n each(array, function (item, index) {\n if (!callback(item)) {\n ret = array.slice(index);\n return false;\n }\n });\n\n return ret;\n }\n\n // initial\n function initial(array, callback) {\n var reversed = array.slice().reverse();\n\n return rest(reversed, callback).reverse();\n }\n\n // extend\n function extend(a, b) {\n for (var key in b) {\n if (b.hasOwnProperty(key)) { a[key] = b[key]; }\n }\n\n return a;\n }\n\n // keys\n function keys(a) {\n var ret = [];\n\n for (var key in a) {\n if (a.hasOwnProperty(key)) { ret.push(key); }\n }\n\n return ret;\n }\n\n // any\n function any(array, callback) {\n var index = 0,\n max = array.length;\n\n if (!array || !max) { return false; }\n\n while (index < max) {\n if (callback(array[index], index) === true) { return true; }\n index += 1;\n }\n\n return false;\n }\n\n // flatten\n function flatten(array) {\n var ret = [];\n\n each(array, function(child) {\n ret = ret.concat(child);\n });\n\n return ret;\n }\n\n function toLocaleStringSupportsLocales() {\n var number = 0;\n try {\n number.toLocaleString('i');\n } catch (e) {\n return e.name === 'RangeError';\n }\n return false;\n }\n\n function featureTestToLocaleStringRounding() {\n return (3.55).toLocaleString(\"en\", {\n useGrouping: false,\n minimumIntegerDigits: 1,\n minimumFractionDigits: 1,\n maximumFractionDigits: 1\n }) === \"3.6\";\n }\n\n function featureTestToLocaleString() {\n var passed = true;\n\n // Test locale.\n passed = passed && toLocaleStringSupportsLocales();\n if (!passed) { return false; }\n\n // Test minimumIntegerDigits.\n passed = passed && (1).toLocaleString(\"en\", { minimumIntegerDigits: 1 }) === \"1\";\n passed = passed && (1).toLocaleString(\"en\", { minimumIntegerDigits: 2 }) === \"01\";\n passed = passed && (1).toLocaleString(\"en\", { minimumIntegerDigits: 3 }) === \"001\";\n if (!passed) { return false; }\n\n // Test maximumFractionDigits and minimumFractionDigits.\n passed = passed && (99.99).toLocaleString(\"en\", { maximumFractionDigits: 0, minimumFractionDigits: 0 }) === \"100\";\n passed = passed && (99.99).toLocaleString(\"en\", { maximumFractionDigits: 1, minimumFractionDigits: 1 }) === \"100.0\";\n passed = passed && (99.99).toLocaleString(\"en\", { maximumFractionDigits: 2, minimumFractionDigits: 2 }) === \"99.99\";\n passed = passed && (99.99).toLocaleString(\"en\", { maximumFractionDigits: 3, minimumFractionDigits: 3 }) === \"99.990\";\n if (!passed) { return false; }\n\n // Test maximumSignificantDigits.\n passed = passed && (99.99).toLocaleString(\"en\", { maximumSignificantDigits: 1 }) === \"100\";\n passed = passed && (99.99).toLocaleString(\"en\", { maximumSignificantDigits: 2 }) === \"100\";\n passed = passed && (99.99).toLocaleString(\"en\", { maximumSignificantDigits: 3 }) === \"100\";\n passed = passed && (99.99).toLocaleString(\"en\", { maximumSignificantDigits: 4 }) === \"99.99\";\n passed = passed && (99.99).toLocaleString(\"en\", { maximumSignificantDigits: 5 }) === \"99.99\";\n if (!passed) { return false; }\n\n // Test grouping.\n passed = passed && (1000).toLocaleString(\"en\", { useGrouping: true }) === \"1,000\";\n passed = passed && (1000).toLocaleString(\"en\", { useGrouping: false }) === \"1000\";\n if (!passed) { return false; }\n\n return true;\n }\n\n // durationsFormat(durations [, template] [, precision] [, settings])\n function durationsFormat() {\n var args = [].slice.call(arguments);\n var settings = {};\n var durations;\n\n // Parse arguments.\n each(args, function (arg, index) {\n if (!index) {\n if (!isArray(arg)) {\n throw \"Expected array as the first argument to durationsFormat.\";\n }\n\n durations = arg;\n }\n\n if (typeof arg === \"string\" || typeof arg === \"function\") {\n settings.template = arg;\n return;\n }\n\n if (typeof arg === \"number\") {\n settings.precision = arg;\n return;\n }\n\n if (isObject(arg)) {\n extend(settings, arg);\n }\n });\n\n if (!durations || !durations.length) {\n return [];\n }\n\n settings.returnMomentTypes = true;\n\n var formattedDurations = map(durations, function (dur) {\n return dur.format(settings);\n });\n\n // Merge token types from all durations.\n var outputTypes = intersection(types, unique(pluck(flatten(formattedDurations), \"type\")));\n\n var largest = settings.largest;\n\n if (largest) {\n outputTypes = outputTypes.slice(0, largest);\n }\n\n settings.returnMomentTypes = false;\n settings.outputTypes = outputTypes;\n\n return map(durations, function (dur) {\n return dur.format(settings);\n });\n }\n\n // durationFormat([template] [, precision] [, settings])\n function durationFormat() {\n\n var args = [].slice.call(arguments);\n var settings = extend({}, this.format.defaults);\n\n // Keep a shadow copy of this moment for calculating remainders.\n // Perform all calculations on positive duration value, handle negative\n // sign at the very end.\n var asMilliseconds = this.asMilliseconds();\n var asMonths = this.asMonths();\n\n // Treat invalid durations as having a value of 0 milliseconds.\n if (this.isValid() === false) {\n asMilliseconds = 0;\n asMonths = 0;\n }\n\n var isNegative = asMilliseconds < 0;\n\n // Two shadow copies are needed because of the way moment.js handles\n // duration arithmetic for years/months and for weeks/days/hours/minutes/seconds.\n var remainder = moment.duration(Math.abs(asMilliseconds), \"milliseconds\");\n var remainderMonths = moment.duration(Math.abs(asMonths), \"months\");\n\n // Parse arguments.\n each(args, function (arg) {\n if (typeof arg === \"string\" || typeof arg === \"function\") {\n settings.template = arg;\n return;\n }\n\n if (typeof arg === \"number\") {\n settings.precision = arg;\n return;\n }\n\n if (isObject(arg)) {\n extend(settings, arg);\n }\n });\n\n var momentTokens = {\n years: \"y\",\n months: \"M\",\n weeks: \"w\",\n days: \"d\",\n hours: \"h\",\n minutes: \"m\",\n seconds: \"s\",\n milliseconds: \"S\"\n };\n\n var tokenDefs = {\n escape: /\\[(.+?)\\]/,\n years: /\\*?[Yy]+/,\n months: /\\*?M+/,\n weeks: /\\*?[Ww]+/,\n days: /\\*?[Dd]+/,\n hours: /\\*?[Hh]+/,\n minutes: /\\*?m+/,\n seconds: /\\*?s+/,\n milliseconds: /\\*?S+/,\n general: /.+?/\n };\n\n // Types array is available in the template function.\n settings.types = types;\n\n var typeMap = function (token) {\n return find(types, function (type) {\n return tokenDefs[type].test(token);\n });\n };\n\n var tokenizer = new RegExp(map(types, function (type) {\n return tokenDefs[type].source;\n }).join(\"|\"), \"g\");\n\n // Current duration object is available in the template function.\n settings.duration = this;\n\n // Eval template function and cache template string.\n var template = typeof settings.template === \"function\" ? settings.template.apply(settings) : settings.template;\n\n // outputTypes and returnMomentTypes are settings to support durationsFormat().\n\n // outputTypes is an array of moment token types that determines\n // the tokens returned in formatted output. This option overrides\n // trim, largest, stopTrim, etc.\n var outputTypes = settings.outputTypes;\n\n // returnMomentTypes is a boolean that sets durationFormat to return\n // the processed momentTypes instead of formatted output.\n var returnMomentTypes = settings.returnMomentTypes;\n\n var largest = settings.largest;\n\n // Setup stopTrim array of token types.\n var stopTrim = [];\n\n if (!outputTypes) {\n if (isArray(settings.stopTrim)) {\n settings.stopTrim = settings.stopTrim.join(\"\");\n }\n\n // Parse stopTrim string to create token types array.\n if (settings.stopTrim) {\n each(settings.stopTrim.match(tokenizer), function (token) {\n var type = typeMap(token);\n\n if (type === \"escape\" || type === \"general\") {\n return;\n }\n\n stopTrim.push(type);\n });\n }\n }\n\n // Cache moment's locale data.\n var localeData = moment.localeData();\n\n if (!localeData) {\n localeData = {};\n }\n\n // Fall back to this plugin's `eng` extension.\n each(keys(engLocale), function (key) {\n if (typeof engLocale[key] === \"function\") {\n if (!localeData[key]) {\n localeData[key] = engLocale[key];\n }\n\n return;\n }\n\n if (!localeData[\"_\" + key]) {\n localeData[\"_\" + key] = engLocale[key];\n }\n });\n\n // Replace Duration Time Template strings.\n // For locale `eng`: `_HMS_`, `_HM_`, and `_MS_`.\n each(keys(localeData._durationTimeTemplates), function (item) {\n template = template.replace(\"_\" + item + \"_\", localeData._durationTimeTemplates[item]);\n });\n\n // Determine user's locale.\n var userLocale = settings.userLocale || moment.locale();\n\n var useLeftUnits = settings.useLeftUnits;\n var usePlural = settings.usePlural;\n var precision = settings.precision;\n var forceLength = settings.forceLength;\n var useGrouping = settings.useGrouping;\n var trunc = settings.trunc;\n\n // Use significant digits only when precision is greater than 0.\n var useSignificantDigits = settings.useSignificantDigits && precision > 0;\n var significantDigits = useSignificantDigits ? settings.precision : 0;\n var significantDigitsCache = significantDigits;\n\n var minValue = settings.minValue;\n var isMinValue = false;\n\n var maxValue = settings.maxValue;\n var isMaxValue = false;\n\n // formatNumber fallback options.\n var useToLocaleString = settings.useToLocaleString;\n var groupingSeparator = settings.groupingSeparator;\n var decimalSeparator = settings.decimalSeparator;\n var grouping = settings.grouping;\n\n useToLocaleString = useToLocaleString && toLocaleStringWorks;\n\n // Trim options.\n var trim = settings.trim;\n\n if (isArray(trim)) {\n trim = trim.join(\" \");\n }\n\n if (trim === null && (largest || maxValue || useSignificantDigits)) {\n trim = \"all\";\n }\n\n if (trim === null || trim === true || trim === \"left\" || trim === \"right\") {\n trim = \"large\";\n }\n\n if (trim === false) {\n trim = \"\";\n }\n\n var trimIncludes = function (item) {\n return item.test(trim);\n };\n\n var rLarge = /large/;\n var rSmall = /small/;\n var rBoth = /both/;\n var rMid = /mid/;\n var rAll = /^all|[^sm]all/;\n var rFinal = /final/;\n\n var trimLarge = largest > 0 || any([rLarge, rBoth, rAll], trimIncludes);\n var trimSmall = any([rSmall, rBoth, rAll], trimIncludes);\n var trimMid = any([rMid, rAll], trimIncludes);\n var trimFinal = any([rFinal, rAll], trimIncludes);\n\n // Parse format string to create raw tokens array.\n var rawTokens = map(template.match(tokenizer), function (token, index) {\n var type = typeMap(token);\n\n if (token.slice(0, 1) === \"*\") {\n token = token.slice(1);\n\n if (type !== \"escape\" && type !== \"general\") {\n stopTrim.push(type);\n }\n }\n\n return {\n index: index,\n length: token.length,\n text: \"\",\n\n // Replace escaped tokens with the non-escaped token text.\n token: (type === \"escape\" ? token.replace(tokenDefs.escape, \"$1\") : token),\n\n // Ignore type on non-moment tokens.\n type: ((type === \"escape\" || type === \"general\") ? null : type)\n };\n });\n\n // Associate text tokens with moment tokens.\n var currentToken = {\n index: 0,\n length: 0,\n token: \"\",\n text: \"\",\n type: null\n };\n\n var tokens = [];\n\n if (useLeftUnits) {\n rawTokens.reverse();\n }\n\n each(rawTokens, function (token) {\n if (token.type) {\n if (currentToken.type || currentToken.text) {\n tokens.push(currentToken);\n }\n\n currentToken = token;\n\n return;\n }\n\n if (useLeftUnits) {\n currentToken.text = token.token + currentToken.text;\n } else {\n currentToken.text += token.token;\n }\n });\n\n if (currentToken.type || currentToken.text) {\n tokens.push(currentToken);\n }\n\n if (useLeftUnits) {\n tokens.reverse();\n }\n\n // Find unique moment token types in the template in order of\n // descending magnitude.\n var momentTypes = intersection(types, unique(compact(pluck(tokens, \"type\"))));\n\n // Exit early if there are no moment token types.\n if (!momentTypes.length) {\n return pluck(tokens, \"text\").join(\"\");\n }\n\n // Calculate values for each moment type in the template.\n // For processing the settings, values are associated with moment types.\n // Values will be assigned to tokens at the last step in order to\n // assume nothing about frequency or order of tokens in the template.\n momentTypes = map(momentTypes, function (momentType, index) {\n // Is this the least-magnitude moment token found?\n var isSmallest = ((index + 1) === momentTypes.length);\n\n // Is this the greatest-magnitude moment token found?\n var isLargest = (!index);\n\n // Get the raw value in the current units.\n var rawValue;\n\n if (momentType === \"years\" || momentType === \"months\") {\n rawValue = remainderMonths.as(momentType);\n } else {\n rawValue = remainder.as(momentType);\n }\n\n var wholeValue = Math.floor(rawValue);\n var decimalValue = rawValue - wholeValue;\n\n var token = find(tokens, function (token) {\n return momentType === token.type;\n });\n\n if (isLargest && maxValue && rawValue > maxValue) {\n isMaxValue = true;\n }\n\n if (isSmallest && minValue && Math.abs(settings.duration.as(momentType)) < minValue) {\n isMinValue = true;\n }\n\n // Note the length of the largest-magnitude moment token:\n // if it is greater than one and forceLength is not set,\n // then default forceLength to `true`.\n //\n // Rationale is this: If the template is \"h:mm:ss\" and the\n // moment value is 5 minutes, the user-friendly output is\n // \"5:00\", not \"05:00\". We shouldn't pad the `minutes` token\n // even though it has length of two if the template is \"h:mm:ss\";\n //\n // If the minutes output should always include the leading zero\n // even when the hour is trimmed then set `{ forceLength: true }`\n // to output \"05:00\". If the template is \"hh:mm:ss\", the user\n // clearly wanted everything padded so we should output \"05:00\";\n //\n // If the user wants the full padded output, they can use\n // template \"hh:mm:ss\" and set `{ trim: false }` to output\n // \"00:05:00\".\n if (isLargest && forceLength === null && token.length > 1) {\n forceLength = true;\n }\n\n // Update remainder.\n remainder.subtract(wholeValue, momentType);\n remainderMonths.subtract(wholeValue, momentType);\n\n return {\n rawValue: rawValue,\n wholeValue: wholeValue,\n // Decimal value is only retained for the least-magnitude\n // moment type in the format template.\n decimalValue: isSmallest ? decimalValue : 0,\n isSmallest: isSmallest,\n isLargest: isLargest,\n type: momentType,\n // Tokens can appear multiple times in a template string,\n // but all instances must share the same length.\n tokenLength: token.length\n };\n });\n\n var truncMethod = trunc ? Math.floor : Math.round;\n var truncate = function (value, places) {\n var factor = Math.pow(10, places);\n return truncMethod(value * factor) / factor;\n };\n\n var foundFirst = false;\n var bubbled = false;\n\n var formatValue = function (momentType, index) {\n var formatOptions = {\n useGrouping: useGrouping,\n groupingSeparator: groupingSeparator,\n decimalSeparator: decimalSeparator,\n grouping: grouping,\n useToLocaleString: useToLocaleString\n };\n\n if (useSignificantDigits) {\n if (significantDigits <= 0) {\n momentType.rawValue = 0;\n momentType.wholeValue = 0;\n momentType.decimalValue = 0;\n } else {\n formatOptions.maximumSignificantDigits = significantDigits;\n momentType.significantDigits = significantDigits;\n }\n }\n\n if (isMaxValue && !bubbled) {\n if (momentType.isLargest) {\n momentType.wholeValue = maxValue;\n momentType.decimalValue = 0;\n } else {\n momentType.wholeValue = 0;\n momentType.decimalValue = 0;\n }\n }\n\n if (isMinValue && !bubbled) {\n if (momentType.isSmallest) {\n momentType.wholeValue = minValue;\n momentType.decimalValue = 0;\n } else {\n momentType.wholeValue = 0;\n momentType.decimalValue = 0;\n }\n }\n\n if (momentType.isSmallest || momentType.significantDigits && momentType.significantDigits - momentType.wholeValue.toString().length <= 0) {\n // Apply precision to least significant token value.\n if (precision < 0) {\n momentType.value = truncate(momentType.wholeValue, precision);\n } else if (precision === 0) {\n momentType.value = truncMethod(momentType.wholeValue + momentType.decimalValue);\n } else { // precision > 0\n if (useSignificantDigits) {\n if (trunc) {\n momentType.value = truncate(momentType.rawValue, significantDigits - momentType.wholeValue.toString().length);\n } else {\n momentType.value = momentType.rawValue;\n }\n\n if (momentType.wholeValue) {\n significantDigits -= momentType.wholeValue.toString().length;\n }\n } else {\n formatOptions.fractionDigits = precision;\n\n if (trunc) {\n momentType.value = momentType.wholeValue + truncate(momentType.decimalValue, precision);\n } else {\n momentType.value = momentType.wholeValue + momentType.decimalValue;\n }\n }\n }\n } else {\n if (useSignificantDigits && momentType.wholeValue) {\n // Outer Math.round required here to handle floating point errors.\n momentType.value = Math.round(truncate(momentType.wholeValue, momentType.significantDigits - momentType.wholeValue.toString().length));\n\n significantDigits -= momentType.wholeValue.toString().length;\n } else {\n momentType.value = momentType.wholeValue;\n }\n }\n\n if (momentType.tokenLength > 1 && (forceLength || foundFirst)) {\n formatOptions.minimumIntegerDigits = momentType.tokenLength;\n\n if (bubbled && formatOptions.maximumSignificantDigits < momentType.tokenLength) {\n delete formatOptions.maximumSignificantDigits;\n }\n }\n\n if (!foundFirst && (momentType.value > 0 || trim === \"\" /* trim: false */ || find(stopTrim, momentType.type) || find(outputTypes, momentType.type))) {\n foundFirst = true;\n }\n\n momentType.formattedValue = formatNumber(momentType.value, formatOptions, userLocale);\n\n formatOptions.useGrouping = false;\n formatOptions.decimalSeparator = \".\";\n momentType.formattedValueEn = formatNumber(momentType.value, formatOptions, \"en\");\n\n if (momentType.tokenLength === 2 && momentType.type === \"milliseconds\") {\n momentType.formattedValueMS = formatNumber(momentType.value, {\n minimumIntegerDigits: 3,\n useGrouping: false\n }, \"en\").slice(0, 2);\n }\n\n return momentType;\n };\n\n // Calculate formatted values.\n momentTypes = map(momentTypes, formatValue);\n momentTypes = compact(momentTypes);\n\n // Bubble rounded values.\n if (momentTypes.length > 1) {\n var findType = function (type) {\n return find(momentTypes, function (momentType) {\n return momentType.type === type;\n });\n };\n\n var bubbleTypes = function (bubble) {\n var bubbleMomentType = findType(bubble.type);\n\n if (!bubbleMomentType) {\n return;\n }\n\n each(bubble.targets, function (target) {\n var targetMomentType = findType(target.type);\n\n if (!targetMomentType) {\n return;\n }\n\n if (parseInt(bubbleMomentType.formattedValueEn, 10) === target.value) {\n bubbleMomentType.rawValue = 0;\n bubbleMomentType.wholeValue = 0;\n bubbleMomentType.decimalValue = 0;\n targetMomentType.rawValue += 1;\n targetMomentType.wholeValue += 1;\n targetMomentType.decimalValue = 0;\n targetMomentType.formattedValueEn = targetMomentType.wholeValue.toString();\n bubbled = true;\n }\n });\n };\n\n each(bubbles, bubbleTypes);\n }\n\n // Recalculate formatted values.\n if (bubbled) {\n foundFirst = false;\n significantDigits = significantDigitsCache;\n momentTypes = map(momentTypes, formatValue);\n momentTypes = compact(momentTypes);\n }\n\n if (outputTypes && !(isMaxValue && !settings.trim)) {\n momentTypes = map(momentTypes, function (momentType) {\n if (find(outputTypes, function (outputType) {\n return momentType.type === outputType;\n })) {\n return momentType;\n }\n\n return null;\n });\n\n momentTypes = compact(momentTypes);\n } else {\n // Trim Large.\n if (trimLarge) {\n momentTypes = rest(momentTypes, function (momentType) {\n // Stop trimming on:\n // - the smallest moment type\n // - a type marked for stopTrim\n // - a type that has a whole value\n return !momentType.isSmallest && !momentType.wholeValue && !find(stopTrim, momentType.type);\n });\n }\n\n // Largest.\n if (largest && momentTypes.length) {\n momentTypes = momentTypes.slice(0, largest);\n }\n\n // Trim Small.\n if (trimSmall && momentTypes.length > 1) {\n momentTypes = initial(momentTypes, function (momentType) {\n // Stop trimming on:\n // - a type marked for stopTrim\n // - a type that has a whole value\n // - the largest momentType\n return !momentType.wholeValue && !find(stopTrim, momentType.type) && !momentType.isLargest;\n });\n }\n\n // Trim Mid.\n if (trimMid) {\n momentTypes = map(momentTypes, function (momentType, index) {\n if (index > 0 && index < momentTypes.length - 1 && !momentType.wholeValue) {\n return null;\n }\n\n return momentType;\n });\n\n momentTypes = compact(momentTypes);\n }\n\n // Trim Final.\n if (trimFinal && momentTypes.length === 1 && !momentTypes[0].wholeValue && !(!trunc && momentTypes[0].isSmallest && momentTypes[0].rawValue < minValue)) {\n momentTypes = [];\n }\n }\n\n if (returnMomentTypes) {\n return momentTypes;\n }\n\n // Localize and pluralize unit labels.\n each(tokens, function (token) {\n var key = momentTokens[token.type];\n\n var momentType = find(momentTypes, function (momentType) {\n return momentType.type === token.type;\n });\n\n if (!key || !momentType) {\n return;\n }\n\n var values = momentType.formattedValueEn.split(\".\");\n\n values[0] = parseInt(values[0], 10);\n\n if (values[1]) {\n values[1] = parseFloat(\"0.\" + values[1], 10);\n } else {\n values[1] = null;\n }\n\n var pluralKey = localeData.durationPluralKey(key, values[0], values[1]);\n\n var labels = durationGetLabels(key, localeData);\n\n var autoLocalized = false;\n\n var pluralizedLabels = {};\n\n // Auto-Localized unit labels.\n each(localeData._durationLabelTypes, function (labelType) {\n var label = find(labels, function (label) {\n return label.type === labelType.type && label.key === pluralKey;\n });\n\n if (label) {\n pluralizedLabels[label.type] = label.label;\n\n if (stringIncludes(token.text, labelType.string)) {\n token.text = token.text.replace(labelType.string, label.label);\n autoLocalized = true;\n }\n }\n });\n\n // Auto-pluralized unit labels.\n if (usePlural && !autoLocalized) {\n labels.sort(durationLabelCompare);\n\n each(labels, function (label) {\n if (pluralizedLabels[label.type] === label.label) {\n if (stringIncludes(token.text, label.label)) {\n // Stop checking this token if its label is already\n // correctly pluralized.\n return false;\n }\n\n // Skip this label if it is correct, but not present in\n // the token's text.\n return;\n }\n\n if (stringIncludes(token.text, label.label)) {\n // Replece this token's label and stop checking.\n token.text = token.text.replace(label.label, pluralizedLabels[label.type]);\n return false;\n }\n });\n }\n });\n\n // Build ouptut.\n tokens = map(tokens, function (token) {\n if (!token.type) {\n return token.text;\n }\n\n var momentType = find(momentTypes, function (momentType) {\n return momentType.type === token.type;\n });\n\n if (!momentType) {\n return \"\";\n }\n\n var out = \"\";\n\n if (useLeftUnits) {\n out += token.text;\n }\n\n if (isNegative && isMaxValue || !isNegative && isMinValue) {\n out += \"< \";\n isMaxValue = false;\n isMinValue = false;\n }\n\n if (isNegative && isMinValue || !isNegative && isMaxValue) {\n out += \"> \";\n isMaxValue = false;\n isMinValue = false;\n }\n\n if (isNegative && (momentType.value > 0 || find(stopTrim, momentType.type) || find(outputTypes, momentType.type))) {\n out += \"-\";\n isNegative = false;\n }\n\n if (token.type === \"milliseconds\" && momentType.formattedValueMS) {\n out += momentType.formattedValueMS;\n } else {\n out += momentType.formattedValue;\n }\n\n if (!useLeftUnits) {\n out += token.text;\n }\n\n return out;\n });\n\n // Trim leading and trailing comma, space, colon, and dot.\n return tokens.join(\"\").replace(/(,| |:|\\.)*$/, \"\").replace(/^(,| |:|\\.)*/, \"\");\n }\n\n // defaultFormatTemplate\n function defaultFormatTemplate() {\n var dur = this.duration;\n\n var findType = function findType(type) {\n return dur._data[type];\n };\n\n var firstType = find(this.types, findType);\n\n var lastType = findLast(this.types, findType);\n\n // Default template strings for each duration dimension type.\n switch (firstType) {\n case \"milliseconds\":\n return \"S __\";\n case \"seconds\": // Fallthrough.\n case \"minutes\":\n return \"*_MS_\";\n case \"hours\":\n return \"_HMS_\";\n case \"days\": // Possible Fallthrough.\n if (firstType === lastType) {\n return \"d __\";\n }\n case \"weeks\":\n if (firstType === lastType) {\n return \"w __\";\n }\n\n if (this.trim === null) {\n this.trim = \"both\";\n }\n\n return \"w __, d __, h __\";\n case \"months\": // Possible Fallthrough.\n if (firstType === lastType) {\n return \"M __\";\n }\n case \"years\":\n if (firstType === lastType) {\n return \"y __\";\n }\n\n if (this.trim === null) {\n this.trim = \"both\";\n }\n\n return \"y __, M __, d __\";\n default:\n if (this.trim === null) {\n this.trim = \"both\";\n }\n\n return \"y __, d __, h __, m __, s __\";\n }\n }\n\n // init\n function init(context) {\n if (!context) {\n throw \"Moment Duration Format init cannot find moment instance.\";\n }\n\n context.duration.format = durationsFormat;\n context.duration.fn.format = durationFormat;\n\n context.duration.fn.format.defaults = {\n // Many options are defaulted to `null` to distinguish between\n // 'not set' and 'set to `false`'\n\n // trim\n // Can be a string, a delimited list of strings, an array of strings,\n // or a boolean.\n // \"large\" - will trim largest-magnitude zero-value tokens until\n // finding a token with a value, a token identified as 'stopTrim', or\n // the final token of the format string.\n // \"small\" - will trim smallest-magnitude zero-value tokens until\n // finding a token with a value, a token identified as 'stopTrim', or\n // the final token of the format string.\n // \"both\" - will execute \"large\" trim then \"small\" trim.\n // \"mid\" - will trim any zero-value tokens that are not the first or\n // last tokens. Usually used in conjunction with \"large\" or \"both\".\n // e.g. \"large mid\" or \"both mid\".\n // \"final\" - will trim the final token if it is zero-value. Use this\n // option with \"large\" or \"both\" to output an empty string when\n // formatting a zero-value duration. e.g. \"large final\" or \"both final\".\n // \"all\" - Will trim all zero-value tokens. Shorthand for \"both mid final\".\n // \"left\" - maps to \"large\" to support plugin's version 1 API.\n // \"right\" - maps to \"large\" to support plugin's version 1 API.\n // `false` - template tokens are not trimmed.\n // `true` - treated as \"large\".\n // `null` - treated as \"large\".\n trim: null,\n\n // stopTrim\n // A moment token string, a delimited set of moment token strings,\n // or an array of moment token strings. Trimming will stop when a token\n // listed in this option is reached. A \"*\" character in the format\n // template string will also mark a moment token as stopTrim.\n // e.g. \"d [days] *h:mm:ss\" will always stop trimming at the 'hours' token.\n stopTrim: null,\n\n // largest\n // Set to a positive integer to output only the \"n\" largest-magnitude\n // moment tokens that have a value. All lesser-magnitude moment tokens\n // will be ignored. This option takes effect even if `trim` is set\n // to `false`.\n largest: null,\n\n // maxValue\n // Use `maxValue` to render generalized output for large duration values,\n // e.g. `\"> 60 days\"`. `maxValue` must be a positive integer and is\n /// applied to the greatest-magnitude moment token in the format template.\n maxValue: null,\n\n // minValue\n // Use `minValue` to render generalized output for small duration values,\n // e.g. `\"< 5 minutes\"`. `minValue` must be a positive integer and is\n // applied to the least-magnitude moment token in the format template.\n minValue: null,\n\n // precision\n // If a positive integer, number of decimal fraction digits to render.\n // If a negative integer, number of integer place digits to truncate to 0.\n // If `useSignificantDigits` is set to `true` and `precision` is a positive\n // integer, sets the maximum number of significant digits used in the\n // formatted output.\n precision: 0,\n\n // trunc\n // Default behavior rounds final token value. Set to `true` to\n // truncate final token value, which was the default behavior in\n // version 1 of this plugin.\n trunc: false,\n\n // forceLength\n // Force first moment token with a value to render at full length\n // even when template is trimmed and first moment token has length of 1.\n forceLength: null,\n\n // userLocale\n // Formatted numerical output is rendered using `toLocaleString`\n // and the locale of the user's environment. Set this option to render\n // numerical output using a different locale. Unit names are rendered\n // and detected using the locale set in moment.js, which can be different\n // from the locale of user's environment.\n userLocale: null,\n\n // usePlural\n // Will automatically singularize or pluralize unit names when they\n // appear in the text associated with each moment token. Standard and\n // short unit labels are singularized and pluralized, based on locale.\n // e.g. in english, \"1 second\" or \"1 sec\" would be rendered instead\n // of \"1 seconds\" or \"1 secs\". The default pluralization function\n // renders a plural label for a value with decimal precision.\n // e.g. \"1.0 seconds\" is never rendered as \"1.0 second\".\n // Label types and pluralization function are configurable in the\n // localeData extensions.\n usePlural: true,\n\n // useLeftUnits\n // The text to the right of each moment token in a format string\n // is treated as that token's units for the purposes of trimming,\n // singularizing, and auto-localizing.\n // e.g. \"h [hours], m [minutes], s [seconds]\".\n // To properly singularize or localize a format string such as\n // \"[hours] h, [minutes] m, [seconds] s\", where the units appear\n // to the left of each moment token, set useLeftUnits to `true`.\n // This plugin is not tested in the context of rtl text.\n useLeftUnits: false,\n\n // useGrouping\n // Enables locale-based digit grouping in the formatted output. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString\n useGrouping: true,\n\n // useSignificantDigits\n // Treat the `precision` option as the maximum significant digits\n // to be rendered. Precision must be a positive integer. Significant\n // digits extend across unit types,\n // e.g. \"6 hours 37.5 minutes\" represents 4 significant digits.\n // Enabling this option causes token length to be ignored. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString\n useSignificantDigits: false,\n\n // template\n // The template string used to format the duration. May be a function\n // or a string. Template functions are executed with the `this` binding\n // of the settings object so that template strings may be dynamically\n // generated based on the duration object (accessible via `this.duration`)\n // or any of the other settings. Leading and trailing space, comma,\n // period, and colon characters are trimmed from the resulting string.\n template: defaultFormatTemplate,\n\n // useToLocaleString\n // Set this option to `false` to ignore the `toLocaleString` feature\n // test and force the use of the `formatNumber` fallback function\n // included in this plugin.\n useToLocaleString: true,\n\n // formatNumber fallback options.\n // When `toLocaleString` is detected and passes the feature test, the\n // following options will have no effect: `toLocaleString` will be used\n // for formatting and the grouping separator, decimal separator, and\n // integer digit grouping will be determined by the user locale.\n\n // groupingSeparator\n // The integer digit grouping separator used when using the fallback\n // formatNumber function.\n groupingSeparator: \",\",\n\n // decimalSeparator\n // The decimal separator used when using the fallback formatNumber\n // function.\n decimalSeparator: \".\",\n\n // grouping\n // The integer digit grouping used when using the fallback formatNumber\n // function. Must be an array. The default value of `[3]` gives the\n // standard 3-digit thousand/million/billion digit groupings for the\n // \"en\" locale. Setting this option to `[3, 2]` would generate the\n // thousand/lakh/crore digit groupings used in the \"en-IN\" locale.\n grouping: [3]\n };\n\n context.updateLocale('en', engLocale);\n }\n\n // Run feature tests for `Number#toLocaleString`.\n toLocaleStringWorks = featureTestToLocaleString();\n toLocaleStringRoundingWorks = toLocaleStringWorks && featureTestToLocaleStringRounding();\n\n // Initialize duration format on the global moment instance.\n init(moment);\n\n // Return the init function so that duration format can be\n // initialized on other moment instances.\n return init;\n});\n","\nvar content = require(\"!!../../node_modules/css-loader/index.js??ref--5-1!./clock-panel.css\");\n\nif(typeof content === 'string') content = [[module.id, content, '']];\n\nvar transform;\nvar insertInto;\n\n\n\nvar options = {\"hmr\":true}\n\noptions.transform = transform\noptions.insertInto = undefined;\n\nvar update = require(\"!../../node_modules/style-loader/lib/addStyles.js\")(content, options);\n\nif(content.locals) module.exports = content.locals;\n\nif(module.hot) {\n\tmodule.hot.accept(\"!!../../node_modules/css-loader/index.js??ref--5-1!./clock-panel.css\", function() {\n\t\tvar newContent = require(\"!!../../node_modules/css-loader/index.js??ref--5-1!./clock-panel.css\");\n\n\t\tif(typeof newContent === 'string') newContent = [[module.id, newContent, '']];\n\n\t\tvar locals = (function(a, b) {\n\t\t\tvar key, idx = 0;\n\n\t\t\tfor(key in a) {\n\t\t\t\tif(!b || a[key] !== b[key]) return false;\n\t\t\t\tidx++;\n\t\t\t}\n\n\t\t\tfor(key in b) idx--;\n\n\t\t\treturn idx === 0;\n\t\t}(content.locals, newContent.locals));\n\n\t\tif(!locals) throw new Error('Aborting CSS HMR due to changed css-modules locals.');\n\n\t\tupdate(newContent);\n\t});\n\n\tmodule.hot.dispose(function() { update(); });\n}","exports = module.exports = require(\"../../node_modules/css-loader/lib/css-base.js\")(true);\n// imports\n\n\n// module\nexports.push([module.id, \".clock-panel {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n flex-direction: column;\\n}\\n\", \"\", {\"version\":3,\"sources\":[\"/home/daniel/dev/go/src/github.com/grafana/grafana/data/plugins/clock-panel/src/css/clock-panel.css\"],\"names\":[],\"mappings\":\"AAAA;EACE,cAAc;EACd,oBAAoB;EACpB,wBAAwB;EACxB,uBAAuB;CACxB\",\"file\":\"clock-panel.css\",\"sourcesContent\":[\".clock-panel {\\n display: flex;\\n align-items: center;\\n justify-content: center;\\n flex-direction: column;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n\n// exports\n","/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n// css base code, injected by the css-loader\nmodule.exports = function(useSourceMap) {\n\tvar list = [];\n\n\t// return the list of modules as css string\n\tlist.toString = function toString() {\n\t\treturn this.map(function (item) {\n\t\t\tvar content = cssWithMappingToString(item, useSourceMap);\n\t\t\tif(item[2]) {\n\t\t\t\treturn \"@media \" + item[2] + \"{\" + content + \"}\";\n\t\t\t} else {\n\t\t\t\treturn content;\n\t\t\t}\n\t\t}).join(\"\");\n\t};\n\n\t// import a list of modules into the list\n\tlist.i = function(modules, mediaQuery) {\n\t\tif(typeof modules === \"string\")\n\t\t\tmodules = [[null, modules, \"\"]];\n\t\tvar alreadyImportedModules = {};\n\t\tfor(var i = 0; i < this.length; i++) {\n\t\t\tvar id = this[i][0];\n\t\t\tif(typeof id === \"number\")\n\t\t\t\talreadyImportedModules[id] = true;\n\t\t}\n\t\tfor(i = 0; i < modules.length; i++) {\n\t\t\tvar item = modules[i];\n\t\t\t// skip already imported module\n\t\t\t// this implementation is not 100% perfect for weird media query combinations\n\t\t\t// when a module is imported multiple times with different media queries.\n\t\t\t// I hope this will never occur (Hey this way we have smaller bundles)\n\t\t\tif(typeof item[0] !== \"number\" || !alreadyImportedModules[item[0]]) {\n\t\t\t\tif(mediaQuery && !item[2]) {\n\t\t\t\t\titem[2] = mediaQuery;\n\t\t\t\t} else if(mediaQuery) {\n\t\t\t\t\titem[2] = \"(\" + item[2] + \") and (\" + mediaQuery + \")\";\n\t\t\t\t}\n\t\t\t\tlist.push(item);\n\t\t\t}\n\t\t}\n\t};\n\treturn list;\n};\n\nfunction cssWithMappingToString(item, useSourceMap) {\n\tvar content = item[1] || '';\n\tvar cssMapping = item[3];\n\tif (!cssMapping) {\n\t\treturn content;\n\t}\n\n\tif (useSourceMap && typeof btoa === 'function') {\n\t\tvar sourceMapping = toComment(cssMapping);\n\t\tvar sourceURLs = cssMapping.sources.map(function (source) {\n\t\t\treturn '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'\n\t\t});\n\n\t\treturn [content].concat(sourceURLs).concat([sourceMapping]).join('\\n');\n\t}\n\n\treturn [content].join('\\n');\n}\n\n// Adapted from convert-source-map (MIT)\nfunction toComment(sourceMap) {\n\t// eslint-disable-next-line no-undef\n\tvar base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));\n\tvar data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;\n\n\treturn '/*# ' + data + ' */';\n}\n","/*\n\tMIT License http://www.opensource.org/licenses/mit-license.php\n\tAuthor Tobias Koppers @sokra\n*/\n\nvar stylesInDom = {};\n\nvar\tmemoize = function (fn) {\n\tvar memo;\n\n\treturn function () {\n\t\tif (typeof memo === \"undefined\") memo = fn.apply(this, arguments);\n\t\treturn memo;\n\t};\n};\n\nvar isOldIE = memoize(function () {\n\t// Test for IE <= 9 as proposed by Browserhacks\n\t// @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805\n\t// Tests for existence of standard globals is to allow style-loader\n\t// to operate correctly into non-standard environments\n\t// @see https://github.com/webpack-contrib/style-loader/issues/177\n\treturn window && document && document.all && !window.atob;\n});\n\nvar getTarget = function (target, parent) {\n if (parent){\n return parent.querySelector(target);\n }\n return document.querySelector(target);\n};\n\nvar getElement = (function (fn) {\n\tvar memo = {};\n\n\treturn function(target, parent) {\n // If passing function in options, then use it for resolve \"head\" element.\n // Useful for Shadow Root style i.e\n // {\n // insertInto: function () { return document.querySelector(\"#foo\").shadowRoot }\n // }\n if (typeof target === 'function') {\n return target();\n }\n if (typeof memo[target] === \"undefined\") {\n\t\t\tvar styleTarget = getTarget.call(this, target, parent);\n\t\t\t// Special case to return head of iframe instead of iframe itself\n\t\t\tif (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) {\n\t\t\t\ttry {\n\t\t\t\t\t// This will throw an exception if access to iframe is blocked\n\t\t\t\t\t// due to cross-origin restrictions\n\t\t\t\t\tstyleTarget = styleTarget.contentDocument.head;\n\t\t\t\t} catch(e) {\n\t\t\t\t\tstyleTarget = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\tmemo[target] = styleTarget;\n\t\t}\n\t\treturn memo[target]\n\t};\n})();\n\nvar singleton = null;\nvar\tsingletonCounter = 0;\nvar\tstylesInsertedAtTop = [];\n\nvar\tfixUrls = require(\"./urls\");\n\nmodule.exports = function(list, options) {\n\tif (typeof DEBUG !== \"undefined\" && DEBUG) {\n\t\tif (typeof document !== \"object\") throw new Error(\"The style-loader cannot be used in a non-browser environment\");\n\t}\n\n\toptions = options || {};\n\n\toptions.attrs = typeof options.attrs === \"object\" ? options.attrs : {};\n\n\t// Force single-tag solution on IE6-9, which has a hard limit on the # of