{"version":3,"file":"common.js","sources":["webpack:///./node_modules/@fortawesome/fontawesome-svg-core/index.es.js","webpack:///./node_modules/@fortawesome/free-solid-svg-icons/faChevronLeft.js","webpack:///./node_modules/@fortawesome/free-solid-svg-icons/faEnvelope.js","webpack:///./node_modules/@fortawesome/free-solid-svg-icons/faFax.js","webpack:///./node_modules/@fortawesome/free-solid-svg-icons/faInfoCircle.js","webpack:///./node_modules/@fortawesome/free-solid-svg-icons/faMapMarkerAlt.js","webpack:///./node_modules/@fortawesome/free-solid-svg-icons/faMinus.js","webpack:///./node_modules/@fortawesome/free-solid-svg-icons/faPhone.js","webpack:///./node_modules/@fortawesome/free-solid-svg-icons/faPlus.js","webpack:///./node_modules/@fortawesome/free-solid-svg-icons/faSearch.js","webpack:///./node_modules/@fortawesome/free-solid-svg-icons/faUser.js","webpack:///./node_modules/@progress/kendo-ui/js/aspnetmvc/kendo.combobox.aspnetmvc.js","webpack:///./node_modules/@progress/kendo-ui/js/aspnetmvc/kendo.data.aspnetmvc.js","webpack:///./node_modules/@progress/kendo-ui/js/aspnetmvc/kendo.dropdownlist.aspnetmvc.js","webpack:///./node_modules/@progress/kendo-ui/js/aspnetmvc/kendo.dropdowntree.aspnetmvc.js","webpack:///./node_modules/@progress/kendo-ui/js/aspnetmvc/kendo.filemanager.aspnetmvc.js","webpack:///./node_modules/@progress/kendo-ui/js/aspnetmvc/kendo.imagebrowser.aspnetmvc.js","webpack:///./node_modules/@progress/kendo-ui/js/aspnetmvc/kendo.multicolumncombobox.aspnetmvc.js","webpack:///./node_modules/@progress/kendo-ui/js/aspnetmvc/kendo.multiselect.aspnetmvc.js","webpack:///./node_modules/@progress/kendo-ui/js/aspnetmvc/kendo.validator.aspnetmvc.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/chart/chart.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/chart/kendo-chart.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/core/core.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/core/kendo-core.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/diagram/dom.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/diagram/layout.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/diagram/math.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/diagram/services.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/diagram/svg.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/diagram/utils.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/gauge/kendo-gauges.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/gauge/main.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/attribution.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/crs.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/layers/base.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/layers/bing.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/layers/bubble.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/layers/marker.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/layers/shape.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/layers/tile.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/location.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/main.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/navigator.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/map/zoom.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/sparkline/kendo-sparkline.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/sparkline/sparkline.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/stock/kendo-stock-chart.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/stock/stock-chart.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/themes/auto-theme.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/themes/chart-base-theme.js","webpack:///./node_modules/@progress/kendo-ui/js/dataviz/themes/themes.js","webpack:///./node_modules/@progress/kendo-ui/js/drawing/html.js","webpack:///./node_modules/@progress/kendo-ui/js/drawing/kendo-drawing.js","webpack:///./node_modules/@progress/kendo-ui/js/drawing/surface-tooltip.js","webpack:///./node_modules/@progress/kendo-ui/js/drawing/surface.js","webpack:///./node_modules/@progress/kendo-ui/js/drawing/util.js","webpack:///./node_modules/@progress/kendo-ui/js/dropdowntree/treeview.js","webpack:///./node_modules/@progress/kendo-ui/js/excel/kendo-excel.js","webpack:///./node_modules/@progress/kendo-ui/js/excel/main.js","webpack:///./node_modules/@progress/kendo-ui/js/excel/mixins.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.angular.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.aspnetmvc.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.autocomplete.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.binder.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.calendar.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.color.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.columnmenu.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.columnsorter.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.combobox.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.core.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.data.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.data.odata.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.data.signalr.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.data.xml.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.barcode.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.chart.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.core.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.diagram.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.gauge.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.map.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.qrcode.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.sparkline.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.stock.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.themes.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dataviz.treemap.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dateinput.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.datepicker.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dialog.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.draganddrop.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.drawing.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dropdownlist.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.dropdowntree.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.editable.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.excel.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.filtermenu.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.floatinglabel.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.fx.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.grid.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.groupable.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.list.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.menu.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.mobile.scroller.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.multiselect.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.numerictextbox.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.ooxml.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.pager.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.pane.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.pdf.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.popup.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.progressbar.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.reorderable.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.resizable.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.router.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.selectable.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.sortable.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.switch.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.toolbar.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.tooltip.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.treeview.draganddrop.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.treeview.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.userevents.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.validator.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.view.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.virtuallist.js","webpack:///./node_modules/@progress/kendo-ui/js/kendo.window.js","webpack:///./node_modules/@progress/kendo-ui/js/ooxml/kendo-ooxml.js","webpack:///./node_modules/@progress/kendo-ui/js/ooxml/main.js","webpack:///./node_modules/@progress/kendo-ui/js/ooxml/utils.js","webpack:///./node_modules/@progress/kendo-ui/js/pdf/core.js","webpack:///./node_modules/@progress/kendo-ui/js/pdf/mixins.js","webpack:///./node_modules/@progress/kendo-ui/js/pdf/pako.js","webpack:///./node_modules/@progress/kendo-ui/js/util/main.js","webpack:///./node_modules/@progress/kendo-ui/js/util/text-metrics.js","webpack:///./node_modules/@progress/kendo-ui/node_modules/jquery/dist/jquery.js","webpack:///./node_modules/base64-js/index.js","webpack:///./node_modules/bootstrap/js/dist/alert.js","webpack:///./node_modules/bootstrap/js/dist/collapse.js","webpack:///./node_modules/bootstrap/js/dist/modal.js","webpack:///./node_modules/bootstrap/js/dist/util.js","webpack:///./node_modules/buffer/index.js","webpack:///./node_modules/expose-loader/dist/runtime/getGlobalThis.js","webpack:///./node_modules/ieee754/index.js","webpack:///./node_modules/isarray/index.js","webpack:///./node_modules/jquery-validation-unobtrusive/dist/jquery.validate.unobtrusive.js","webpack:///./node_modules/jquery-validation/dist/jquery.validate.js","webpack:///./node_modules/jquery/dist/jquery-exposed.js","webpack:///./node_modules/jquery/dist/jquery.js","webpack:///./node_modules/jszip/dist/jszip.js","webpack:///./node_modules/process/browser.js","webpack:///./node_modules/setimmediate/setImmediate.js","webpack:///./node_modules/timers-browserify/main.js","webpack:///(webpack)/buildin/global.js","webpack:///./wwwroot/scripts/components/cookies.js","webpack:///./wwwroot/scripts/components/disclaimers.js","webpack:///./wwwroot/scripts/components/dynamic-grid.js","webpack:///./wwwroot/scripts/components/footer.js","webpack:///./wwwroot/scripts/components/header.js","webpack:///./wwwroot/scripts/components/top-menu.js","webpack:///./wwwroot/scripts/selectedIcons.js"],"sourcesContent":["function _typeof(obj) {\n if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n _typeof = function (obj) {\n return typeof obj;\n };\n } else {\n _typeof = function (obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n };\n }\n\n return _typeof(obj);\n}\n\nfunction _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}\n\nfunction _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\n\nfunction _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}\n\nfunction _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}\n\nfunction _objectSpread(target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i] != null ? arguments[i] : {};\n var ownKeys = Object.keys(source);\n\n if (typeof Object.getOwnPropertySymbols === 'function') {\n ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {\n return Object.getOwnPropertyDescriptor(source, sym).enumerable;\n }));\n }\n\n ownKeys.forEach(function (key) {\n _defineProperty(target, key, source[key]);\n });\n }\n\n return target;\n}\n\nfunction _slicedToArray(arr, i) {\n return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();\n}\n\nfunction _toConsumableArray(arr) {\n return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();\n}\n\nfunction _arrayWithoutHoles(arr) {\n if (Array.isArray(arr)) {\n for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];\n\n return arr2;\n }\n}\n\nfunction _arrayWithHoles(arr) {\n if (Array.isArray(arr)) return arr;\n}\n\nfunction _iterableToArray(iter) {\n if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter);\n}\n\nfunction _iterableToArrayLimit(arr, i) {\n var _arr = [];\n var _n = true;\n var _d = false;\n var _e = undefined;\n\n try {\n for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {\n _arr.push(_s.value);\n\n if (i && _arr.length === i) break;\n }\n } catch (err) {\n _d = true;\n _e = err;\n } finally {\n try {\n if (!_n && _i[\"return\"] != null) _i[\"return\"]();\n } finally {\n if (_d) throw _e;\n }\n }\n\n return _arr;\n}\n\nfunction _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance\");\n}\n\nfunction _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance\");\n}\n\nvar noop = function noop() {};\n\nvar _WINDOW = {};\nvar _DOCUMENT = {};\nvar _MUTATION_OBSERVER = null;\nvar _PERFORMANCE = {\n mark: noop,\n measure: noop\n};\n\ntry {\n if (typeof window !== 'undefined') _WINDOW = window;\n if (typeof document !== 'undefined') _DOCUMENT = document;\n if (typeof MutationObserver !== 'undefined') _MUTATION_OBSERVER = MutationObserver;\n if (typeof performance !== 'undefined') _PERFORMANCE = performance;\n} catch (e) {}\n\nvar _ref = _WINDOW.navigator || {},\n _ref$userAgent = _ref.userAgent,\n userAgent = _ref$userAgent === void 0 ? '' : _ref$userAgent;\n\nvar WINDOW = _WINDOW;\nvar DOCUMENT = _DOCUMENT;\nvar MUTATION_OBSERVER = _MUTATION_OBSERVER;\nvar PERFORMANCE = _PERFORMANCE;\nvar IS_BROWSER = !!WINDOW.document;\nvar IS_DOM = !!DOCUMENT.documentElement && !!DOCUMENT.head && typeof DOCUMENT.addEventListener === 'function' && typeof DOCUMENT.createElement === 'function';\nvar IS_IE = ~userAgent.indexOf('MSIE') || ~userAgent.indexOf('Trident/');\n\nvar NAMESPACE_IDENTIFIER = '___FONT_AWESOME___';\nvar UNITS_IN_GRID = 16;\nvar DEFAULT_FAMILY_PREFIX = 'fa';\nvar DEFAULT_REPLACEMENT_CLASS = 'svg-inline--fa';\nvar DATA_FA_I2SVG = 'data-fa-i2svg';\nvar DATA_FA_PSEUDO_ELEMENT = 'data-fa-pseudo-element';\nvar DATA_FA_PSEUDO_ELEMENT_PENDING = 'data-fa-pseudo-element-pending';\nvar DATA_PREFIX = 'data-prefix';\nvar DATA_ICON = 'data-icon';\nvar HTML_CLASS_I2SVG_BASE_CLASS = 'fontawesome-i2svg';\nvar MUTATION_APPROACH_ASYNC = 'async';\nvar TAGNAMES_TO_SKIP_FOR_PSEUDOELEMENTS = ['HTML', 'HEAD', 'STYLE', 'SCRIPT'];\nvar PRODUCTION = function () {\n try {\n return process.env.NODE_ENV === 'production';\n } catch (e) {\n return false;\n }\n}();\nvar PREFIX_TO_STYLE = {\n 'fas': 'solid',\n 'far': 'regular',\n 'fal': 'light',\n 'fad': 'duotone',\n 'fab': 'brands',\n 'fa': 'solid'\n};\nvar STYLE_TO_PREFIX = {\n 'solid': 'fas',\n 'regular': 'far',\n 'light': 'fal',\n 'duotone': 'fad',\n 'brands': 'fab'\n};\nvar LAYERS_TEXT_CLASSNAME = 'fa-layers-text';\nvar FONT_FAMILY_PATTERN = /Font Awesome 5 (Solid|Regular|Light|Duotone|Brands|Free|Pro)/;\nvar FONT_WEIGHT_TO_PREFIX = {\n '900': 'fas',\n '400': 'far',\n 'normal': 'far',\n '300': 'fal'\n};\nvar oneToTen = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\nvar oneToTwenty = oneToTen.concat([11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);\nvar ATTRIBUTES_WATCHED_FOR_MUTATION = ['class', 'data-prefix', 'data-icon', 'data-fa-transform', 'data-fa-mask'];\nvar DUOTONE_CLASSES = {\n GROUP: 'group',\n SWAP_OPACITY: 'swap-opacity',\n PRIMARY: 'primary',\n SECONDARY: 'secondary'\n};\nvar RESERVED_CLASSES = ['xs', 'sm', 'lg', 'fw', 'ul', 'li', 'border', 'pull-left', 'pull-right', 'spin', 'pulse', 'rotate-90', 'rotate-180', 'rotate-270', 'flip-horizontal', 'flip-vertical', 'flip-both', 'stack', 'stack-1x', 'stack-2x', 'inverse', 'layers', 'layers-text', 'layers-counter', DUOTONE_CLASSES.GROUP, DUOTONE_CLASSES.SWAP_OPACITY, DUOTONE_CLASSES.PRIMARY, DUOTONE_CLASSES.SECONDARY].concat(oneToTen.map(function (n) {\n return \"\".concat(n, \"x\");\n})).concat(oneToTwenty.map(function (n) {\n return \"w-\".concat(n);\n}));\n\nvar initial = WINDOW.FontAwesomeConfig || {};\n\nfunction getAttrConfig(attr) {\n var element = DOCUMENT.querySelector('script[' + attr + ']');\n\n if (element) {\n return element.getAttribute(attr);\n }\n}\n\nfunction coerce(val) {\n // Getting an empty string will occur if the attribute is set on the HTML tag but without a value\n // We'll assume that this is an indication that it should be toggled to true\n // For example \n if (val === '') return true;\n if (val === 'false') return false;\n if (val === 'true') return true;\n return val;\n}\n\nif (DOCUMENT && typeof DOCUMENT.querySelector === 'function') {\n var attrs = [['data-family-prefix', 'familyPrefix'], ['data-replacement-class', 'replacementClass'], ['data-auto-replace-svg', 'autoReplaceSvg'], ['data-auto-add-css', 'autoAddCss'], ['data-auto-a11y', 'autoA11y'], ['data-search-pseudo-elements', 'searchPseudoElements'], ['data-observe-mutations', 'observeMutations'], ['data-mutate-approach', 'mutateApproach'], ['data-keep-original-source', 'keepOriginalSource'], ['data-measure-performance', 'measurePerformance'], ['data-show-missing-icons', 'showMissingIcons']];\n attrs.forEach(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n attr = _ref2[0],\n key = _ref2[1];\n\n var val = coerce(getAttrConfig(attr));\n\n if (val !== undefined && val !== null) {\n initial[key] = val;\n }\n });\n}\n\nvar _default = {\n familyPrefix: DEFAULT_FAMILY_PREFIX,\n replacementClass: DEFAULT_REPLACEMENT_CLASS,\n autoReplaceSvg: true,\n autoAddCss: true,\n autoA11y: true,\n searchPseudoElements: false,\n observeMutations: true,\n mutateApproach: 'async',\n keepOriginalSource: true,\n measurePerformance: false,\n showMissingIcons: true\n};\n\nvar _config = _objectSpread({}, _default, initial);\n\nif (!_config.autoReplaceSvg) _config.observeMutations = false;\n\nvar config = _objectSpread({}, _config);\n\nWINDOW.FontAwesomeConfig = config;\n\nvar w = WINDOW || {};\nif (!w[NAMESPACE_IDENTIFIER]) w[NAMESPACE_IDENTIFIER] = {};\nif (!w[NAMESPACE_IDENTIFIER].styles) w[NAMESPACE_IDENTIFIER].styles = {};\nif (!w[NAMESPACE_IDENTIFIER].hooks) w[NAMESPACE_IDENTIFIER].hooks = {};\nif (!w[NAMESPACE_IDENTIFIER].shims) w[NAMESPACE_IDENTIFIER].shims = [];\nvar namespace = w[NAMESPACE_IDENTIFIER];\n\nvar functions = [];\n\nvar listener = function listener() {\n DOCUMENT.removeEventListener('DOMContentLoaded', listener);\n loaded = 1;\n functions.map(function (fn) {\n return fn();\n });\n};\n\nvar loaded = false;\n\nif (IS_DOM) {\n loaded = (DOCUMENT.documentElement.doScroll ? /^loaded|^c/ : /^loaded|^i|^c/).test(DOCUMENT.readyState);\n if (!loaded) DOCUMENT.addEventListener('DOMContentLoaded', listener);\n}\n\nfunction domready (fn) {\n if (!IS_DOM) return;\n loaded ? setTimeout(fn, 0) : functions.push(fn);\n}\n\nvar PENDING = 'pending';\nvar SETTLED = 'settled';\nvar FULFILLED = 'fulfilled';\nvar REJECTED = 'rejected';\n\nvar NOOP = function NOOP() {};\n\nvar isNode = typeof global !== 'undefined' && typeof global.process !== 'undefined' && typeof global.process.emit === 'function';\nvar asyncSetTimer = typeof setImmediate === 'undefined' ? setTimeout : setImmediate;\nvar asyncQueue = [];\nvar asyncTimer;\n\nfunction asyncFlush() {\n // run promise callbacks\n for (var i = 0; i < asyncQueue.length; i++) {\n asyncQueue[i][0](asyncQueue[i][1]);\n } // reset async asyncQueue\n\n\n asyncQueue = [];\n asyncTimer = false;\n}\n\nfunction asyncCall(callback, arg) {\n asyncQueue.push([callback, arg]);\n\n if (!asyncTimer) {\n asyncTimer = true;\n asyncSetTimer(asyncFlush, 0);\n }\n}\n\nfunction invokeResolver(resolver, promise) {\n function resolvePromise(value) {\n resolve(promise, value);\n }\n\n function rejectPromise(reason) {\n reject(promise, reason);\n }\n\n try {\n resolver(resolvePromise, rejectPromise);\n } catch (e) {\n rejectPromise(e);\n }\n}\n\nfunction invokeCallback(subscriber) {\n var owner = subscriber.owner;\n var settled = owner._state;\n var value = owner._data;\n var callback = subscriber[settled];\n var promise = subscriber.then;\n\n if (typeof callback === 'function') {\n settled = FULFILLED;\n\n try {\n value = callback(value);\n } catch (e) {\n reject(promise, e);\n }\n }\n\n if (!handleThenable(promise, value)) {\n if (settled === FULFILLED) {\n resolve(promise, value);\n }\n\n if (settled === REJECTED) {\n reject(promise, value);\n }\n }\n}\n\nfunction handleThenable(promise, value) {\n var resolved;\n\n try {\n if (promise === value) {\n throw new TypeError('A promises callback cannot return that same promise.');\n }\n\n if (value && (typeof value === 'function' || _typeof(value) === 'object')) {\n // then should be retrieved only once\n var then = value.then;\n\n if (typeof then === 'function') {\n then.call(value, function (val) {\n if (!resolved) {\n resolved = true;\n\n if (value === val) {\n fulfill(promise, val);\n } else {\n resolve(promise, val);\n }\n }\n }, function (reason) {\n if (!resolved) {\n resolved = true;\n reject(promise, reason);\n }\n });\n return true;\n }\n }\n } catch (e) {\n if (!resolved) {\n reject(promise, e);\n }\n\n return true;\n }\n\n return false;\n}\n\nfunction resolve(promise, value) {\n if (promise === value || !handleThenable(promise, value)) {\n fulfill(promise, value);\n }\n}\n\nfunction fulfill(promise, value) {\n if (promise._state === PENDING) {\n promise._state = SETTLED;\n promise._data = value;\n asyncCall(publishFulfillment, promise);\n }\n}\n\nfunction reject(promise, reason) {\n if (promise._state === PENDING) {\n promise._state = SETTLED;\n promise._data = reason;\n asyncCall(publishRejection, promise);\n }\n}\n\nfunction publish(promise) {\n promise._then = promise._then.forEach(invokeCallback);\n}\n\nfunction publishFulfillment(promise) {\n promise._state = FULFILLED;\n publish(promise);\n}\n\nfunction publishRejection(promise) {\n promise._state = REJECTED;\n publish(promise);\n\n if (!promise._handled && isNode) {\n global.process.emit('unhandledRejection', promise._data, promise);\n }\n}\n\nfunction notifyRejectionHandled(promise) {\n global.process.emit('rejectionHandled', promise);\n}\n/**\n * @class\n */\n\n\nfunction P(resolver) {\n if (typeof resolver !== 'function') {\n throw new TypeError('Promise resolver ' + resolver + ' is not a function');\n }\n\n if (this instanceof P === false) {\n throw new TypeError('Failed to construct \\'Promise\\': Please use the \\'new\\' operator, this object constructor cannot be called as a function.');\n }\n\n this._then = [];\n invokeResolver(resolver, this);\n}\n\nP.prototype = {\n constructor: P,\n _state: PENDING,\n _then: null,\n _data: undefined,\n _handled: false,\n then: function then(onFulfillment, onRejection) {\n var subscriber = {\n owner: this,\n then: new this.constructor(NOOP),\n fulfilled: onFulfillment,\n rejected: onRejection\n };\n\n if ((onRejection || onFulfillment) && !this._handled) {\n this._handled = true;\n\n if (this._state === REJECTED && isNode) {\n asyncCall(notifyRejectionHandled, this);\n }\n }\n\n if (this._state === FULFILLED || this._state === REJECTED) {\n // already resolved, call callback async\n asyncCall(invokeCallback, subscriber);\n } else {\n // subscribe\n this._then.push(subscriber);\n }\n\n return subscriber.then;\n },\n catch: function _catch(onRejection) {\n return this.then(null, onRejection);\n }\n};\n\nP.all = function (promises) {\n if (!Array.isArray(promises)) {\n throw new TypeError('You must pass an array to Promise.all().');\n }\n\n return new P(function (resolve, reject) {\n var results = [];\n var remaining = 0;\n\n function resolver(index) {\n remaining++;\n return function (value) {\n results[index] = value;\n\n if (! --remaining) {\n resolve(results);\n }\n };\n }\n\n for (var i = 0, promise; i < promises.length; i++) {\n promise = promises[i];\n\n if (promise && typeof promise.then === 'function') {\n promise.then(resolver(i), reject);\n } else {\n results[i] = promise;\n }\n }\n\n if (!remaining) {\n resolve(results);\n }\n });\n};\n\nP.race = function (promises) {\n if (!Array.isArray(promises)) {\n throw new TypeError('You must pass an array to Promise.race().');\n }\n\n return new P(function (resolve, reject) {\n for (var i = 0, promise; i < promises.length; i++) {\n promise = promises[i];\n\n if (promise && typeof promise.then === 'function') {\n promise.then(resolve, reject);\n } else {\n resolve(promise);\n }\n }\n });\n};\n\nP.resolve = function (value) {\n if (value && _typeof(value) === 'object' && value.constructor === P) {\n return value;\n }\n\n return new P(function (resolve) {\n resolve(value);\n });\n};\n\nP.reject = function (reason) {\n return new P(function (resolve, reject) {\n reject(reason);\n });\n};\n\nvar picked = typeof Promise === 'function' ? Promise : P;\n\nvar d = UNITS_IN_GRID;\nvar meaninglessTransform = {\n size: 16,\n x: 0,\n y: 0,\n rotate: 0,\n flipX: false,\n flipY: false\n};\n\nfunction isReserved(name) {\n return ~RESERVED_CLASSES.indexOf(name);\n}\nfunction insertCss(css) {\n if (!css || !IS_DOM) {\n return;\n }\n\n var style = DOCUMENT.createElement('style');\n style.setAttribute('type', 'text/css');\n style.innerHTML = css;\n var headChildren = DOCUMENT.head.childNodes;\n var beforeChild = null;\n\n for (var i = headChildren.length - 1; i > -1; i--) {\n var child = headChildren[i];\n var tagName = (child.tagName || '').toUpperCase();\n\n if (['STYLE', 'LINK'].indexOf(tagName) > -1) {\n beforeChild = child;\n }\n }\n\n DOCUMENT.head.insertBefore(style, beforeChild);\n return css;\n}\nvar idPool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\nfunction nextUniqueId() {\n var size = 12;\n var id = '';\n\n while (size-- > 0) {\n id += idPool[Math.random() * 62 | 0];\n }\n\n return id;\n}\nfunction toArray(obj) {\n var array = [];\n\n for (var i = (obj || []).length >>> 0; i--;) {\n array[i] = obj[i];\n }\n\n return array;\n}\nfunction classArray(node) {\n if (node.classList) {\n return toArray(node.classList);\n } else {\n return (node.getAttribute('class') || '').split(' ').filter(function (i) {\n return i;\n });\n }\n}\nfunction getIconName(familyPrefix, cls) {\n var parts = cls.split('-');\n var prefix = parts[0];\n var iconName = parts.slice(1).join('-');\n\n if (prefix === familyPrefix && iconName !== '' && !isReserved(iconName)) {\n return iconName;\n } else {\n return null;\n }\n}\nfunction htmlEscape(str) {\n return \"\".concat(str).replace(/&/g, '&').replace(/\"/g, '"').replace(/'/g, ''').replace(//g, '>');\n}\nfunction joinAttributes(attributes) {\n return Object.keys(attributes || {}).reduce(function (acc, attributeName) {\n return acc + \"\".concat(attributeName, \"=\\\"\").concat(htmlEscape(attributes[attributeName]), \"\\\" \");\n }, '').trim();\n}\nfunction joinStyles(styles) {\n return Object.keys(styles || {}).reduce(function (acc, styleName) {\n return acc + \"\".concat(styleName, \": \").concat(styles[styleName], \";\");\n }, '');\n}\nfunction transformIsMeaningful(transform) {\n return transform.size !== meaninglessTransform.size || transform.x !== meaninglessTransform.x || transform.y !== meaninglessTransform.y || transform.rotate !== meaninglessTransform.rotate || transform.flipX || transform.flipY;\n}\nfunction transformForSvg(_ref) {\n var transform = _ref.transform,\n containerWidth = _ref.containerWidth,\n iconWidth = _ref.iconWidth;\n var outer = {\n transform: \"translate(\".concat(containerWidth / 2, \" 256)\")\n };\n var innerTranslate = \"translate(\".concat(transform.x * 32, \", \").concat(transform.y * 32, \") \");\n var innerScale = \"scale(\".concat(transform.size / 16 * (transform.flipX ? -1 : 1), \", \").concat(transform.size / 16 * (transform.flipY ? -1 : 1), \") \");\n var innerRotate = \"rotate(\".concat(transform.rotate, \" 0 0)\");\n var inner = {\n transform: \"\".concat(innerTranslate, \" \").concat(innerScale, \" \").concat(innerRotate)\n };\n var path = {\n transform: \"translate(\".concat(iconWidth / 2 * -1, \" -256)\")\n };\n return {\n outer: outer,\n inner: inner,\n path: path\n };\n}\nfunction transformForCss(_ref2) {\n var transform = _ref2.transform,\n _ref2$width = _ref2.width,\n width = _ref2$width === void 0 ? UNITS_IN_GRID : _ref2$width,\n _ref2$height = _ref2.height,\n height = _ref2$height === void 0 ? UNITS_IN_GRID : _ref2$height,\n _ref2$startCentered = _ref2.startCentered,\n startCentered = _ref2$startCentered === void 0 ? false : _ref2$startCentered;\n var val = '';\n\n if (startCentered && IS_IE) {\n val += \"translate(\".concat(transform.x / d - width / 2, \"em, \").concat(transform.y / d - height / 2, \"em) \");\n } else if (startCentered) {\n val += \"translate(calc(-50% + \".concat(transform.x / d, \"em), calc(-50% + \").concat(transform.y / d, \"em)) \");\n } else {\n val += \"translate(\".concat(transform.x / d, \"em, \").concat(transform.y / d, \"em) \");\n }\n\n val += \"scale(\".concat(transform.size / d * (transform.flipX ? -1 : 1), \", \").concat(transform.size / d * (transform.flipY ? -1 : 1), \") \");\n val += \"rotate(\".concat(transform.rotate, \"deg) \");\n return val;\n}\n\nvar ALL_SPACE = {\n x: 0,\n y: 0,\n width: '100%',\n height: '100%'\n};\n\nfunction fillBlack(abstract) {\n var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n if (abstract.attributes && (abstract.attributes.fill || force)) {\n abstract.attributes.fill = 'black';\n }\n\n return abstract;\n}\n\nfunction deGroup(abstract) {\n if (abstract.tag === 'g') {\n return abstract.children;\n } else {\n return [abstract];\n }\n}\n\nfunction makeIconMasking (_ref) {\n var children = _ref.children,\n attributes = _ref.attributes,\n main = _ref.main,\n mask = _ref.mask,\n explicitMaskId = _ref.maskId,\n transform = _ref.transform;\n var mainWidth = main.width,\n mainPath = main.icon;\n var maskWidth = mask.width,\n maskPath = mask.icon;\n var trans = transformForSvg({\n transform: transform,\n containerWidth: maskWidth,\n iconWidth: mainWidth\n });\n var maskRect = {\n tag: 'rect',\n attributes: _objectSpread({}, ALL_SPACE, {\n fill: 'white'\n })\n };\n var maskInnerGroupChildrenMixin = mainPath.children ? {\n children: mainPath.children.map(fillBlack)\n } : {};\n var maskInnerGroup = {\n tag: 'g',\n attributes: _objectSpread({}, trans.inner),\n children: [fillBlack(_objectSpread({\n tag: mainPath.tag,\n attributes: _objectSpread({}, mainPath.attributes, trans.path)\n }, maskInnerGroupChildrenMixin))]\n };\n var maskOuterGroup = {\n tag: 'g',\n attributes: _objectSpread({}, trans.outer),\n children: [maskInnerGroup]\n };\n var maskId = \"mask-\".concat(explicitMaskId || nextUniqueId());\n var clipId = \"clip-\".concat(explicitMaskId || nextUniqueId());\n var maskTag = {\n tag: 'mask',\n attributes: _objectSpread({}, ALL_SPACE, {\n id: maskId,\n maskUnits: 'userSpaceOnUse',\n maskContentUnits: 'userSpaceOnUse'\n }),\n children: [maskRect, maskOuterGroup]\n };\n var defs = {\n tag: 'defs',\n children: [{\n tag: 'clipPath',\n attributes: {\n id: clipId\n },\n children: deGroup(maskPath)\n }, maskTag]\n };\n children.push(defs, {\n tag: 'rect',\n attributes: _objectSpread({\n fill: 'currentColor',\n 'clip-path': \"url(#\".concat(clipId, \")\"),\n mask: \"url(#\".concat(maskId, \")\")\n }, ALL_SPACE)\n });\n return {\n children: children,\n attributes: attributes\n };\n}\n\nfunction makeIconStandard (_ref) {\n var children = _ref.children,\n attributes = _ref.attributes,\n main = _ref.main,\n transform = _ref.transform,\n styles = _ref.styles;\n var styleString = joinStyles(styles);\n\n if (styleString.length > 0) {\n attributes['style'] = styleString;\n }\n\n if (transformIsMeaningful(transform)) {\n var trans = transformForSvg({\n transform: transform,\n containerWidth: main.width,\n iconWidth: main.width\n });\n children.push({\n tag: 'g',\n attributes: _objectSpread({}, trans.outer),\n children: [{\n tag: 'g',\n attributes: _objectSpread({}, trans.inner),\n children: [{\n tag: main.icon.tag,\n children: main.icon.children,\n attributes: _objectSpread({}, main.icon.attributes, trans.path)\n }]\n }]\n });\n } else {\n children.push(main.icon);\n }\n\n return {\n children: children,\n attributes: attributes\n };\n}\n\nfunction asIcon (_ref) {\n var children = _ref.children,\n main = _ref.main,\n mask = _ref.mask,\n attributes = _ref.attributes,\n styles = _ref.styles,\n transform = _ref.transform;\n\n if (transformIsMeaningful(transform) && main.found && !mask.found) {\n var width = main.width,\n height = main.height;\n var offset = {\n x: width / height / 2,\n y: 0.5\n };\n attributes['style'] = joinStyles(_objectSpread({}, styles, {\n 'transform-origin': \"\".concat(offset.x + transform.x / 16, \"em \").concat(offset.y + transform.y / 16, \"em\")\n }));\n }\n\n return [{\n tag: 'svg',\n attributes: attributes,\n children: children\n }];\n}\n\nfunction asSymbol (_ref) {\n var prefix = _ref.prefix,\n iconName = _ref.iconName,\n children = _ref.children,\n attributes = _ref.attributes,\n symbol = _ref.symbol;\n var id = symbol === true ? \"\".concat(prefix, \"-\").concat(config.familyPrefix, \"-\").concat(iconName) : symbol;\n return [{\n tag: 'svg',\n attributes: {\n style: 'display: none;'\n },\n children: [{\n tag: 'symbol',\n attributes: _objectSpread({}, attributes, {\n id: id\n }),\n children: children\n }]\n }];\n}\n\nfunction makeInlineSvgAbstract(params) {\n var _params$icons = params.icons,\n main = _params$icons.main,\n mask = _params$icons.mask,\n prefix = params.prefix,\n iconName = params.iconName,\n transform = params.transform,\n symbol = params.symbol,\n title = params.title,\n maskId = params.maskId,\n titleId = params.titleId,\n extra = params.extra,\n _params$watchable = params.watchable,\n watchable = _params$watchable === void 0 ? false : _params$watchable;\n\n var _ref = mask.found ? mask : main,\n width = _ref.width,\n height = _ref.height;\n\n var widthClass = \"fa-w-\".concat(Math.ceil(width / height * 16));\n var attrClass = [config.replacementClass, iconName ? \"\".concat(config.familyPrefix, \"-\").concat(iconName) : '', widthClass].filter(function (c) {\n return extra.classes.indexOf(c) === -1;\n }).concat(extra.classes).join(' ');\n var content = {\n children: [],\n attributes: _objectSpread({}, extra.attributes, {\n 'data-prefix': prefix,\n 'data-icon': iconName,\n 'class': attrClass,\n 'role': extra.attributes.role || 'img',\n 'xmlns': 'http://www.w3.org/2000/svg',\n 'viewBox': \"0 0 \".concat(width, \" \").concat(height)\n })\n };\n\n if (watchable) {\n content.attributes[DATA_FA_I2SVG] = '';\n }\n\n if (title) content.children.push({\n tag: 'title',\n attributes: {\n id: content.attributes['aria-labelledby'] || \"title-\".concat(titleId || nextUniqueId())\n },\n children: [title]\n });\n\n var args = _objectSpread({}, content, {\n prefix: prefix,\n iconName: iconName,\n main: main,\n mask: mask,\n maskId: maskId,\n transform: transform,\n symbol: symbol,\n styles: extra.styles\n });\n\n var _ref2 = mask.found && main.found ? makeIconMasking(args) : makeIconStandard(args),\n children = _ref2.children,\n attributes = _ref2.attributes;\n\n args.children = children;\n args.attributes = attributes;\n\n if (symbol) {\n return asSymbol(args);\n } else {\n return asIcon(args);\n }\n}\nfunction makeLayersTextAbstract(params) {\n var content = params.content,\n width = params.width,\n height = params.height,\n transform = params.transform,\n title = params.title,\n extra = params.extra,\n _params$watchable2 = params.watchable,\n watchable = _params$watchable2 === void 0 ? false : _params$watchable2;\n\n var attributes = _objectSpread({}, extra.attributes, title ? {\n 'title': title\n } : {}, {\n 'class': extra.classes.join(' ')\n });\n\n if (watchable) {\n attributes[DATA_FA_I2SVG] = '';\n }\n\n var styles = _objectSpread({}, extra.styles);\n\n if (transformIsMeaningful(transform)) {\n styles['transform'] = transformForCss({\n transform: transform,\n startCentered: true,\n width: width,\n height: height\n });\n styles['-webkit-transform'] = styles['transform'];\n }\n\n var styleString = joinStyles(styles);\n\n if (styleString.length > 0) {\n attributes['style'] = styleString;\n }\n\n var val = [];\n val.push({\n tag: 'span',\n attributes: attributes,\n children: [content]\n });\n\n if (title) {\n val.push({\n tag: 'span',\n attributes: {\n class: 'sr-only'\n },\n children: [title]\n });\n }\n\n return val;\n}\nfunction makeLayersCounterAbstract(params) {\n var content = params.content,\n title = params.title,\n extra = params.extra;\n\n var attributes = _objectSpread({}, extra.attributes, title ? {\n 'title': title\n } : {}, {\n 'class': extra.classes.join(' ')\n });\n\n var styleString = joinStyles(extra.styles);\n\n if (styleString.length > 0) {\n attributes['style'] = styleString;\n }\n\n var val = [];\n val.push({\n tag: 'span',\n attributes: attributes,\n children: [content]\n });\n\n if (title) {\n val.push({\n tag: 'span',\n attributes: {\n class: 'sr-only'\n },\n children: [title]\n });\n }\n\n return val;\n}\n\nvar noop$1 = function noop() {};\n\nvar p = config.measurePerformance && PERFORMANCE && PERFORMANCE.mark && PERFORMANCE.measure ? PERFORMANCE : {\n mark: noop$1,\n measure: noop$1\n};\nvar preamble = \"FA \\\"5.14.0\\\"\";\n\nvar begin = function begin(name) {\n p.mark(\"\".concat(preamble, \" \").concat(name, \" begins\"));\n return function () {\n return end(name);\n };\n};\n\nvar end = function end(name) {\n p.mark(\"\".concat(preamble, \" \").concat(name, \" ends\"));\n p.measure(\"\".concat(preamble, \" \").concat(name), \"\".concat(preamble, \" \").concat(name, \" begins\"), \"\".concat(preamble, \" \").concat(name, \" ends\"));\n};\n\nvar perf = {\n begin: begin,\n end: end\n};\n\n/**\n * Internal helper to bind a function known to have 4 arguments\n * to a given context.\n */\n\nvar bindInternal4 = function bindInternal4(func, thisContext) {\n return function (a, b, c, d) {\n return func.call(thisContext, a, b, c, d);\n };\n};\n\n/**\n * # Reduce\n *\n * A fast object `.reduce()` implementation.\n *\n * @param {Object} subject The object to reduce over.\n * @param {Function} fn The reducer function.\n * @param {mixed} initialValue The initial value for the reducer, defaults to subject[0].\n * @param {Object} thisContext The context for the reducer.\n * @return {mixed} The final result.\n */\n\n\nvar reduce = function fastReduceObject(subject, fn, initialValue, thisContext) {\n var keys = Object.keys(subject),\n length = keys.length,\n iterator = thisContext !== undefined ? bindInternal4(fn, thisContext) : fn,\n i,\n key,\n result;\n\n if (initialValue === undefined) {\n i = 1;\n result = subject[keys[0]];\n } else {\n i = 0;\n result = initialValue;\n }\n\n for (; i < length; i++) {\n key = keys[i];\n result = iterator(result, subject[key], key, subject);\n }\n\n return result;\n};\n\nfunction toHex(unicode) {\n var result = '';\n\n for (var i = 0; i < unicode.length; i++) {\n var hex = unicode.charCodeAt(i).toString(16);\n result += ('000' + hex).slice(-4);\n }\n\n return result;\n}\n\nfunction defineIcons(prefix, icons) {\n var params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n var _params$skipHooks = params.skipHooks,\n skipHooks = _params$skipHooks === void 0 ? false : _params$skipHooks;\n var normalized = Object.keys(icons).reduce(function (acc, iconName) {\n var icon = icons[iconName];\n var expanded = !!icon.icon;\n\n if (expanded) {\n acc[icon.iconName] = icon.icon;\n } else {\n acc[iconName] = icon;\n }\n\n return acc;\n }, {});\n\n if (typeof namespace.hooks.addPack === 'function' && !skipHooks) {\n namespace.hooks.addPack(prefix, normalized);\n } else {\n namespace.styles[prefix] = _objectSpread({}, namespace.styles[prefix] || {}, normalized);\n }\n /**\n * Font Awesome 4 used the prefix of `fa` for all icons. With the introduction\n * of new styles we needed to differentiate between them. Prefix `fa` is now an alias\n * for `fas` so we'll easy the upgrade process for our users by automatically defining\n * this as well.\n */\n\n\n if (prefix === 'fas') {\n defineIcons('fa', icons);\n }\n}\n\nvar styles = namespace.styles,\n shims = namespace.shims;\nvar _byUnicode = {};\nvar _byLigature = {};\nvar _byOldName = {};\nvar build = function build() {\n var lookup = function lookup(reducer) {\n return reduce(styles, function (o, style, prefix) {\n o[prefix] = reduce(style, reducer, {});\n return o;\n }, {});\n };\n\n _byUnicode = lookup(function (acc, icon, iconName) {\n if (icon[3]) {\n acc[icon[3]] = iconName;\n }\n\n return acc;\n });\n _byLigature = lookup(function (acc, icon, iconName) {\n var ligatures = icon[2];\n acc[iconName] = iconName;\n ligatures.forEach(function (ligature) {\n acc[ligature] = iconName;\n });\n return acc;\n });\n var hasRegular = 'far' in styles;\n _byOldName = reduce(shims, function (acc, shim) {\n var oldName = shim[0];\n var prefix = shim[1];\n var iconName = shim[2];\n\n if (prefix === 'far' && !hasRegular) {\n prefix = 'fas';\n }\n\n acc[oldName] = {\n prefix: prefix,\n iconName: iconName\n };\n return acc;\n }, {});\n};\nbuild();\nfunction byUnicode(prefix, unicode) {\n return (_byUnicode[prefix] || {})[unicode];\n}\nfunction byLigature(prefix, ligature) {\n return (_byLigature[prefix] || {})[ligature];\n}\nfunction byOldName(name) {\n return _byOldName[name] || {\n prefix: null,\n iconName: null\n };\n}\n\nvar styles$1 = namespace.styles;\nvar emptyCanonicalIcon = function emptyCanonicalIcon() {\n return {\n prefix: null,\n iconName: null,\n rest: []\n };\n};\nfunction getCanonicalIcon(values) {\n return values.reduce(function (acc, cls) {\n var iconName = getIconName(config.familyPrefix, cls);\n\n if (styles$1[cls]) {\n acc.prefix = cls;\n } else if (config.autoFetchSvg && ['fas', 'far', 'fal', 'fad', 'fab', 'fa'].indexOf(cls) > -1) {\n acc.prefix = cls;\n } else if (iconName) {\n var shim = acc.prefix === 'fa' ? byOldName(iconName) : {};\n acc.iconName = shim.iconName || iconName;\n acc.prefix = shim.prefix || acc.prefix;\n } else if (cls !== config.replacementClass && cls.indexOf('fa-w-') !== 0) {\n acc.rest.push(cls);\n }\n\n return acc;\n }, emptyCanonicalIcon());\n}\nfunction iconFromMapping(mapping, prefix, iconName) {\n if (mapping && mapping[prefix] && mapping[prefix][iconName]) {\n return {\n prefix: prefix,\n iconName: iconName,\n icon: mapping[prefix][iconName]\n };\n }\n}\n\nfunction toHtml(abstractNodes) {\n var tag = abstractNodes.tag,\n _abstractNodes$attrib = abstractNodes.attributes,\n attributes = _abstractNodes$attrib === void 0 ? {} : _abstractNodes$attrib,\n _abstractNodes$childr = abstractNodes.children,\n children = _abstractNodes$childr === void 0 ? [] : _abstractNodes$childr;\n\n if (typeof abstractNodes === 'string') {\n return htmlEscape(abstractNodes);\n } else {\n return \"<\".concat(tag, \" \").concat(joinAttributes(attributes), \">\").concat(children.map(toHtml).join(''), \"\").concat(tag, \">\");\n }\n}\n\nvar noop$2 = function noop() {};\n\nfunction isWatched(node) {\n var i2svg = node.getAttribute ? node.getAttribute(DATA_FA_I2SVG) : null;\n return typeof i2svg === 'string';\n}\n\nfunction getMutator() {\n if (config.autoReplaceSvg === true) {\n return mutators.replace;\n }\n\n var mutator = mutators[config.autoReplaceSvg];\n return mutator || mutators.replace;\n}\n\nvar mutators = {\n replace: function replace(mutation) {\n var node = mutation[0];\n var abstract = mutation[1];\n var newOuterHTML = abstract.map(function (a) {\n return toHtml(a);\n }).join('\\n');\n\n if (node.parentNode && node.outerHTML) {\n node.outerHTML = newOuterHTML + (config.keepOriginalSource && node.tagName.toLowerCase() !== 'svg' ? \"\") : '');\n } else if (node.parentNode) {\n var newNode = document.createElement('span');\n node.parentNode.replaceChild(newNode, node);\n newNode.outerHTML = newOuterHTML;\n }\n },\n nest: function nest(mutation) {\n var node = mutation[0];\n var abstract = mutation[1]; // If we already have a replaced node we do not want to continue nesting within it.\n // Short-circuit to the standard replacement\n\n if (~classArray(node).indexOf(config.replacementClass)) {\n return mutators.replace(mutation);\n }\n\n var forSvg = new RegExp(\"\".concat(config.familyPrefix, \"-.*\"));\n delete abstract[0].attributes.style;\n delete abstract[0].attributes.id;\n var splitClasses = abstract[0].attributes.class.split(' ').reduce(function (acc, cls) {\n if (cls === config.replacementClass || cls.match(forSvg)) {\n acc.toSvg.push(cls);\n } else {\n acc.toNode.push(cls);\n }\n\n return acc;\n }, {\n toNode: [],\n toSvg: []\n });\n abstract[0].attributes.class = splitClasses.toSvg.join(' ');\n var newInnerHTML = abstract.map(function (a) {\n return toHtml(a);\n }).join('\\n');\n node.setAttribute('class', splitClasses.toNode.join(' '));\n node.setAttribute(DATA_FA_I2SVG, '');\n node.innerHTML = newInnerHTML;\n }\n};\n\nfunction performOperationSync(op) {\n op();\n}\n\nfunction perform(mutations, callback) {\n var callbackFunction = typeof callback === 'function' ? callback : noop$2;\n\n if (mutations.length === 0) {\n callbackFunction();\n } else {\n var frame = performOperationSync;\n\n if (config.mutateApproach === MUTATION_APPROACH_ASYNC) {\n frame = WINDOW.requestAnimationFrame || performOperationSync;\n }\n\n frame(function () {\n var mutator = getMutator();\n var mark = perf.begin('mutate');\n mutations.map(mutator);\n mark();\n callbackFunction();\n });\n }\n}\nvar disabled = false;\nfunction disableObservation() {\n disabled = true;\n}\nfunction enableObservation() {\n disabled = false;\n}\nvar mo = null;\nfunction observe(options) {\n if (!MUTATION_OBSERVER) {\n return;\n }\n\n if (!config.observeMutations) {\n return;\n }\n\n var treeCallback = options.treeCallback,\n nodeCallback = options.nodeCallback,\n pseudoElementsCallback = options.pseudoElementsCallback,\n _options$observeMutat = options.observeMutationsRoot,\n observeMutationsRoot = _options$observeMutat === void 0 ? DOCUMENT : _options$observeMutat;\n mo = new MUTATION_OBSERVER(function (objects) {\n if (disabled) return;\n toArray(objects).forEach(function (mutationRecord) {\n if (mutationRecord.type === 'childList' && mutationRecord.addedNodes.length > 0 && !isWatched(mutationRecord.addedNodes[0])) {\n if (config.searchPseudoElements) {\n pseudoElementsCallback(mutationRecord.target);\n }\n\n treeCallback(mutationRecord.target);\n }\n\n if (mutationRecord.type === 'attributes' && mutationRecord.target.parentNode && config.searchPseudoElements) {\n pseudoElementsCallback(mutationRecord.target.parentNode);\n }\n\n if (mutationRecord.type === 'attributes' && isWatched(mutationRecord.target) && ~ATTRIBUTES_WATCHED_FOR_MUTATION.indexOf(mutationRecord.attributeName)) {\n if (mutationRecord.attributeName === 'class') {\n var _getCanonicalIcon = getCanonicalIcon(classArray(mutationRecord.target)),\n prefix = _getCanonicalIcon.prefix,\n iconName = _getCanonicalIcon.iconName;\n\n if (prefix) mutationRecord.target.setAttribute('data-prefix', prefix);\n if (iconName) mutationRecord.target.setAttribute('data-icon', iconName);\n } else {\n nodeCallback(mutationRecord.target);\n }\n }\n });\n });\n if (!IS_DOM) return;\n mo.observe(observeMutationsRoot, {\n childList: true,\n attributes: true,\n characterData: true,\n subtree: true\n });\n}\nfunction disconnect() {\n if (!mo) return;\n mo.disconnect();\n}\n\nfunction styleParser (node) {\n var style = node.getAttribute('style');\n var val = [];\n\n if (style) {\n val = style.split(';').reduce(function (acc, style) {\n var styles = style.split(':');\n var prop = styles[0];\n var value = styles.slice(1);\n\n if (prop && value.length > 0) {\n acc[prop] = value.join(':').trim();\n }\n\n return acc;\n }, {});\n }\n\n return val;\n}\n\nfunction classParser (node) {\n var existingPrefix = node.getAttribute('data-prefix');\n var existingIconName = node.getAttribute('data-icon');\n var innerText = node.innerText !== undefined ? node.innerText.trim() : '';\n var val = getCanonicalIcon(classArray(node));\n\n if (existingPrefix && existingIconName) {\n val.prefix = existingPrefix;\n val.iconName = existingIconName;\n }\n\n if (val.prefix && innerText.length > 1) {\n val.iconName = byLigature(val.prefix, node.innerText);\n } else if (val.prefix && innerText.length === 1) {\n val.iconName = byUnicode(val.prefix, toHex(node.innerText));\n }\n\n return val;\n}\n\nvar parseTransformString = function parseTransformString(transformString) {\n var transform = {\n size: 16,\n x: 0,\n y: 0,\n flipX: false,\n flipY: false,\n rotate: 0\n };\n\n if (!transformString) {\n return transform;\n } else {\n return transformString.toLowerCase().split(' ').reduce(function (acc, n) {\n var parts = n.toLowerCase().split('-');\n var first = parts[0];\n var rest = parts.slice(1).join('-');\n\n if (first && rest === 'h') {\n acc.flipX = true;\n return acc;\n }\n\n if (first && rest === 'v') {\n acc.flipY = true;\n return acc;\n }\n\n rest = parseFloat(rest);\n\n if (isNaN(rest)) {\n return acc;\n }\n\n switch (first) {\n case 'grow':\n acc.size = acc.size + rest;\n break;\n\n case 'shrink':\n acc.size = acc.size - rest;\n break;\n\n case 'left':\n acc.x = acc.x - rest;\n break;\n\n case 'right':\n acc.x = acc.x + rest;\n break;\n\n case 'up':\n acc.y = acc.y - rest;\n break;\n\n case 'down':\n acc.y = acc.y + rest;\n break;\n\n case 'rotate':\n acc.rotate = acc.rotate + rest;\n break;\n }\n\n return acc;\n }, transform);\n }\n};\nfunction transformParser (node) {\n return parseTransformString(node.getAttribute('data-fa-transform'));\n}\n\nfunction symbolParser (node) {\n var symbol = node.getAttribute('data-fa-symbol');\n return symbol === null ? false : symbol === '' ? true : symbol;\n}\n\nfunction attributesParser (node) {\n var extraAttributes = toArray(node.attributes).reduce(function (acc, attr) {\n if (acc.name !== 'class' && acc.name !== 'style') {\n acc[attr.name] = attr.value;\n }\n\n return acc;\n }, {});\n var title = node.getAttribute('title');\n var titleId = node.getAttribute('data-fa-title-id');\n\n if (config.autoA11y) {\n if (title) {\n extraAttributes['aria-labelledby'] = \"\".concat(config.replacementClass, \"-title-\").concat(titleId || nextUniqueId());\n } else {\n extraAttributes['aria-hidden'] = 'true';\n extraAttributes['focusable'] = 'false';\n }\n }\n\n return extraAttributes;\n}\n\nfunction maskParser (node) {\n var mask = node.getAttribute('data-fa-mask');\n\n if (!mask) {\n return emptyCanonicalIcon();\n } else {\n return getCanonicalIcon(mask.split(' ').map(function (i) {\n return i.trim();\n }));\n }\n}\n\nfunction blankMeta() {\n return {\n iconName: null,\n title: null,\n titleId: null,\n prefix: null,\n transform: meaninglessTransform,\n symbol: false,\n mask: null,\n maskId: null,\n extra: {\n classes: [],\n styles: {},\n attributes: {}\n }\n };\n}\nfunction parseMeta(node) {\n var _classParser = classParser(node),\n iconName = _classParser.iconName,\n prefix = _classParser.prefix,\n extraClasses = _classParser.rest;\n\n var extraStyles = styleParser(node);\n var transform = transformParser(node);\n var symbol = symbolParser(node);\n var extraAttributes = attributesParser(node);\n var mask = maskParser(node);\n return {\n iconName: iconName,\n title: node.getAttribute('title'),\n titleId: node.getAttribute('data-fa-title-id'),\n prefix: prefix,\n transform: transform,\n symbol: symbol,\n mask: mask,\n maskId: node.getAttribute('data-fa-mask-id'),\n extra: {\n classes: extraClasses,\n styles: extraStyles,\n attributes: extraAttributes\n }\n };\n}\n\nfunction MissingIcon(error) {\n this.name = 'MissingIcon';\n this.message = error || 'Icon unavailable';\n this.stack = new Error().stack;\n}\nMissingIcon.prototype = Object.create(Error.prototype);\nMissingIcon.prototype.constructor = MissingIcon;\n\nvar FILL = {\n fill: 'currentColor'\n};\nvar ANIMATION_BASE = {\n attributeType: 'XML',\n repeatCount: 'indefinite',\n dur: '2s'\n};\nvar RING = {\n tag: 'path',\n attributes: _objectSpread({}, FILL, {\n d: 'M156.5,447.7l-12.6,29.5c-18.7-9.5-35.9-21.2-51.5-34.9l22.7-22.7C127.6,430.5,141.5,440,156.5,447.7z M40.6,272H8.5 c1.4,21.2,5.4,41.7,11.7,61.1L50,321.2C45.1,305.5,41.8,289,40.6,272z M40.6,240c1.4-18.8,5.2-37,11.1-54.1l-29.5-12.6 C14.7,194.3,10,216.7,8.5,240H40.6z M64.3,156.5c7.8-14.9,17.2-28.8,28.1-41.5L69.7,92.3c-13.7,15.6-25.5,32.8-34.9,51.5 L64.3,156.5z M397,419.6c-13.9,12-29.4,22.3-46.1,30.4l11.9,29.8c20.7-9.9,39.8-22.6,56.9-37.6L397,419.6z M115,92.4 c13.9-12,29.4-22.3,46.1-30.4l-11.9-29.8c-20.7,9.9-39.8,22.6-56.8,37.6L115,92.4z M447.7,355.5c-7.8,14.9-17.2,28.8-28.1,41.5 l22.7,22.7c13.7-15.6,25.5-32.9,34.9-51.5L447.7,355.5z M471.4,272c-1.4,18.8-5.2,37-11.1,54.1l29.5,12.6 c7.5-21.1,12.2-43.5,13.6-66.8H471.4z M321.2,462c-15.7,5-32.2,8.2-49.2,9.4v32.1c21.2-1.4,41.7-5.4,61.1-11.7L321.2,462z M240,471.4c-18.8-1.4-37-5.2-54.1-11.1l-12.6,29.5c21.1,7.5,43.5,12.2,66.8,13.6V471.4z M462,190.8c5,15.7,8.2,32.2,9.4,49.2h32.1 c-1.4-21.2-5.4-41.7-11.7-61.1L462,190.8z M92.4,397c-12-13.9-22.3-29.4-30.4-46.1l-29.8,11.9c9.9,20.7,22.6,39.8,37.6,56.9 L92.4,397z M272,40.6c18.8,1.4,36.9,5.2,54.1,11.1l12.6-29.5C317.7,14.7,295.3,10,272,8.5V40.6z M190.8,50 c15.7-5,32.2-8.2,49.2-9.4V8.5c-21.2,1.4-41.7,5.4-61.1,11.7L190.8,50z M442.3,92.3L419.6,115c12,13.9,22.3,29.4,30.5,46.1 l29.8-11.9C470,128.5,457.3,109.4,442.3,92.3z M397,92.4l22.7-22.7c-15.6-13.7-32.8-25.5-51.5-34.9l-12.6,29.5 C370.4,72.1,384.4,81.5,397,92.4z'\n })\n};\n\nvar OPACITY_ANIMATE = _objectSpread({}, ANIMATION_BASE, {\n attributeName: 'opacity'\n});\n\nvar DOT = {\n tag: 'circle',\n attributes: _objectSpread({}, FILL, {\n cx: '256',\n cy: '364',\n r: '28'\n }),\n children: [{\n tag: 'animate',\n attributes: _objectSpread({}, ANIMATION_BASE, {\n attributeName: 'r',\n values: '28;14;28;28;14;28;'\n })\n }, {\n tag: 'animate',\n attributes: _objectSpread({}, OPACITY_ANIMATE, {\n values: '1;0;1;1;0;1;'\n })\n }]\n};\nvar QUESTION = {\n tag: 'path',\n attributes: _objectSpread({}, FILL, {\n opacity: '1',\n d: 'M263.7,312h-16c-6.6,0-12-5.4-12-12c0-71,77.4-63.9,77.4-107.8c0-20-17.8-40.2-57.4-40.2c-29.1,0-44.3,9.6-59.2,28.7 c-3.9,5-11.1,6-16.2,2.4l-13.1-9.2c-5.6-3.9-6.9-11.8-2.6-17.2c21.2-27.2,46.4-44.7,91.2-44.7c52.3,0,97.4,29.8,97.4,80.2 c0,67.6-77.4,63.5-77.4,107.8C275.7,306.6,270.3,312,263.7,312z'\n }),\n children: [{\n tag: 'animate',\n attributes: _objectSpread({}, OPACITY_ANIMATE, {\n values: '1;0;0;0;0;1;'\n })\n }]\n};\nvar EXCLAMATION = {\n tag: 'path',\n attributes: _objectSpread({}, FILL, {\n opacity: '0',\n d: 'M232.5,134.5l7,168c0.3,6.4,5.6,11.5,12,11.5h9c6.4,0,11.7-5.1,12-11.5l7-168c0.3-6.8-5.2-12.5-12-12.5h-23 C237.7,122,232.2,127.7,232.5,134.5z'\n }),\n children: [{\n tag: 'animate',\n attributes: _objectSpread({}, OPACITY_ANIMATE, {\n values: '0;0;1;1;0;0;'\n })\n }]\n};\nvar missing = {\n tag: 'g',\n children: [RING, DOT, QUESTION, EXCLAMATION]\n};\n\nvar styles$2 = namespace.styles;\nfunction asFoundIcon(icon) {\n var width = icon[0];\n var height = icon[1];\n\n var _icon$slice = icon.slice(4),\n _icon$slice2 = _slicedToArray(_icon$slice, 1),\n vectorData = _icon$slice2[0];\n\n var element = null;\n\n if (Array.isArray(vectorData)) {\n element = {\n tag: 'g',\n attributes: {\n class: \"\".concat(config.familyPrefix, \"-\").concat(DUOTONE_CLASSES.GROUP)\n },\n children: [{\n tag: 'path',\n attributes: {\n class: \"\".concat(config.familyPrefix, \"-\").concat(DUOTONE_CLASSES.SECONDARY),\n fill: 'currentColor',\n d: vectorData[0]\n }\n }, {\n tag: 'path',\n attributes: {\n class: \"\".concat(config.familyPrefix, \"-\").concat(DUOTONE_CLASSES.PRIMARY),\n fill: 'currentColor',\n d: vectorData[1]\n }\n }]\n };\n } else {\n element = {\n tag: 'path',\n attributes: {\n fill: 'currentColor',\n d: vectorData\n }\n };\n }\n\n return {\n found: true,\n width: width,\n height: height,\n icon: element\n };\n}\nfunction findIcon(iconName, prefix) {\n return new picked(function (resolve, reject) {\n var val = {\n found: false,\n width: 512,\n height: 512,\n icon: missing\n };\n\n if (iconName && prefix && styles$2[prefix] && styles$2[prefix][iconName]) {\n var icon = styles$2[prefix][iconName];\n return resolve(asFoundIcon(icon));\n }\n\n var headers = {};\n\n if (_typeof(WINDOW.FontAwesomeKitConfig) === 'object' && typeof window.FontAwesomeKitConfig.token === 'string') {\n headers['fa-kit-token'] = WINDOW.FontAwesomeKitConfig.token;\n }\n\n if (iconName && prefix && !config.showMissingIcons) {\n reject(new MissingIcon(\"Icon is missing for prefix \".concat(prefix, \" with icon name \").concat(iconName)));\n } else {\n resolve(val);\n }\n });\n}\n\nvar styles$3 = namespace.styles;\n\nfunction generateSvgReplacementMutation(node, nodeMeta) {\n var iconName = nodeMeta.iconName,\n title = nodeMeta.title,\n titleId = nodeMeta.titleId,\n prefix = nodeMeta.prefix,\n transform = nodeMeta.transform,\n symbol = nodeMeta.symbol,\n mask = nodeMeta.mask,\n maskId = nodeMeta.maskId,\n extra = nodeMeta.extra;\n return new picked(function (resolve, reject) {\n picked.all([findIcon(iconName, prefix), findIcon(mask.iconName, mask.prefix)]).then(function (_ref) {\n var _ref2 = _slicedToArray(_ref, 2),\n main = _ref2[0],\n mask = _ref2[1];\n\n resolve([node, makeInlineSvgAbstract({\n icons: {\n main: main,\n mask: mask\n },\n prefix: prefix,\n iconName: iconName,\n transform: transform,\n symbol: symbol,\n mask: mask,\n maskId: maskId,\n title: title,\n titleId: titleId,\n extra: extra,\n watchable: true\n })]);\n });\n });\n}\n\nfunction generateLayersText(node, nodeMeta) {\n var title = nodeMeta.title,\n transform = nodeMeta.transform,\n extra = nodeMeta.extra;\n var width = null;\n var height = null;\n\n if (IS_IE) {\n var computedFontSize = parseInt(getComputedStyle(node).fontSize, 10);\n var boundingClientRect = node.getBoundingClientRect();\n width = boundingClientRect.width / computedFontSize;\n height = boundingClientRect.height / computedFontSize;\n }\n\n if (config.autoA11y && !title) {\n extra.attributes['aria-hidden'] = 'true';\n }\n\n return picked.resolve([node, makeLayersTextAbstract({\n content: node.innerHTML,\n width: width,\n height: height,\n transform: transform,\n title: title,\n extra: extra,\n watchable: true\n })]);\n}\n\nfunction generateMutation(node) {\n var nodeMeta = parseMeta(node);\n\n if (~nodeMeta.extra.classes.indexOf(LAYERS_TEXT_CLASSNAME)) {\n return generateLayersText(node, nodeMeta);\n } else {\n return generateSvgReplacementMutation(node, nodeMeta);\n }\n}\n\nfunction onTree(root) {\n var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n if (!IS_DOM) return;\n var htmlClassList = DOCUMENT.documentElement.classList;\n\n var hclAdd = function hclAdd(suffix) {\n return htmlClassList.add(\"\".concat(HTML_CLASS_I2SVG_BASE_CLASS, \"-\").concat(suffix));\n };\n\n var hclRemove = function hclRemove(suffix) {\n return htmlClassList.remove(\"\".concat(HTML_CLASS_I2SVG_BASE_CLASS, \"-\").concat(suffix));\n };\n\n var prefixes = config.autoFetchSvg ? Object.keys(PREFIX_TO_STYLE) : Object.keys(styles$3);\n var prefixesDomQuery = [\".\".concat(LAYERS_TEXT_CLASSNAME, \":not([\").concat(DATA_FA_I2SVG, \"])\")].concat(prefixes.map(function (p) {\n return \".\".concat(p, \":not([\").concat(DATA_FA_I2SVG, \"])\");\n })).join(', ');\n\n if (prefixesDomQuery.length === 0) {\n return;\n }\n\n var candidates = [];\n\n try {\n candidates = toArray(root.querySelectorAll(prefixesDomQuery));\n } catch (e) {// noop\n }\n\n if (candidates.length > 0) {\n hclAdd('pending');\n hclRemove('complete');\n } else {\n return;\n }\n\n var mark = perf.begin('onTree');\n var mutations = candidates.reduce(function (acc, node) {\n try {\n var mutation = generateMutation(node);\n\n if (mutation) {\n acc.push(mutation);\n }\n } catch (e) {\n if (!PRODUCTION) {\n if (e instanceof MissingIcon) {\n console.error(e);\n }\n }\n }\n\n return acc;\n }, []);\n return new picked(function (resolve, reject) {\n picked.all(mutations).then(function (resolvedMutations) {\n perform(resolvedMutations, function () {\n hclAdd('active');\n hclAdd('complete');\n hclRemove('pending');\n if (typeof callback === 'function') callback();\n mark();\n resolve();\n });\n }).catch(function () {\n mark();\n reject();\n });\n });\n}\nfunction onNode(node) {\n var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n generateMutation(node).then(function (mutation) {\n if (mutation) {\n perform([mutation], callback);\n }\n });\n}\n\nfunction replaceForPosition(node, position) {\n var pendingAttribute = \"\".concat(DATA_FA_PSEUDO_ELEMENT_PENDING).concat(position.replace(':', '-'));\n return new picked(function (resolve, reject) {\n if (node.getAttribute(pendingAttribute) !== null) {\n // This node is already being processed\n return resolve();\n }\n\n var children = toArray(node.children);\n var alreadyProcessedPseudoElement = children.filter(function (c) {\n return c.getAttribute(DATA_FA_PSEUDO_ELEMENT) === position;\n })[0];\n var styles = WINDOW.getComputedStyle(node, position);\n var fontFamily = styles.getPropertyValue('font-family').match(FONT_FAMILY_PATTERN);\n var fontWeight = styles.getPropertyValue('font-weight');\n var content = styles.getPropertyValue('content');\n\n if (alreadyProcessedPseudoElement && !fontFamily) {\n // If we've already processed it but the current computed style does not result in a font-family,\n // that probably means that a class name that was previously present to make the icon has been\n // removed. So we now should delete the icon.\n node.removeChild(alreadyProcessedPseudoElement);\n return resolve();\n } else if (fontFamily && content !== 'none' && content !== '') {\n var prefix = ~['Solid', 'Regular', 'Light', 'Duotone', 'Brands'].indexOf(fontFamily[1]) ? STYLE_TO_PREFIX[fontFamily[1].toLowerCase()] : FONT_WEIGHT_TO_PREFIX[fontWeight];\n var hexValue = toHex(content.length === 3 ? content.substr(1, 1) : content);\n var iconName = byUnicode(prefix, hexValue);\n var iconIdentifier = iconName; // Only convert the pseudo element in this :before/:after position into an icon if we haven't\n // already done so with the same prefix and iconName\n\n if (iconName && (!alreadyProcessedPseudoElement || alreadyProcessedPseudoElement.getAttribute(DATA_PREFIX) !== prefix || alreadyProcessedPseudoElement.getAttribute(DATA_ICON) !== iconIdentifier)) {\n node.setAttribute(pendingAttribute, iconIdentifier);\n\n if (alreadyProcessedPseudoElement) {\n // Delete the old one, since we're replacing it with a new one\n node.removeChild(alreadyProcessedPseudoElement);\n }\n\n var meta = blankMeta();\n var extra = meta.extra;\n extra.attributes[DATA_FA_PSEUDO_ELEMENT] = position;\n findIcon(iconName, prefix).then(function (main) {\n var abstract = makeInlineSvgAbstract(_objectSpread({}, meta, {\n icons: {\n main: main,\n mask: emptyCanonicalIcon()\n },\n prefix: prefix,\n iconName: iconIdentifier,\n extra: extra,\n watchable: true\n }));\n var element = DOCUMENT.createElement('svg');\n\n if (position === ':before') {\n node.insertBefore(element, node.firstChild);\n } else {\n node.appendChild(element);\n }\n\n element.outerHTML = abstract.map(function (a) {\n return toHtml(a);\n }).join('\\n');\n node.removeAttribute(pendingAttribute);\n resolve();\n }).catch(reject);\n } else {\n resolve();\n }\n } else {\n resolve();\n }\n });\n}\n\nfunction replace(node) {\n return picked.all([replaceForPosition(node, ':before'), replaceForPosition(node, ':after')]);\n}\n\nfunction processable(node) {\n return node.parentNode !== document.head && !~TAGNAMES_TO_SKIP_FOR_PSEUDOELEMENTS.indexOf(node.tagName.toUpperCase()) && !node.getAttribute(DATA_FA_PSEUDO_ELEMENT) && (!node.parentNode || node.parentNode.tagName !== 'svg');\n}\n\nfunction searchPseudoElements (root) {\n if (!IS_DOM) return;\n return new picked(function (resolve, reject) {\n var operations = toArray(root.querySelectorAll('*')).filter(processable).map(replace);\n var end = perf.begin('searchPseudoElements');\n disableObservation();\n picked.all(operations).then(function () {\n end();\n enableObservation();\n resolve();\n }).catch(function () {\n end();\n enableObservation();\n reject();\n });\n });\n}\n\nvar baseStyles = \"svg:not(:root).svg-inline--fa {\\n overflow: visible;\\n}\\n\\n.svg-inline--fa {\\n display: inline-block;\\n font-size: inherit;\\n height: 1em;\\n overflow: visible;\\n vertical-align: -0.125em;\\n}\\n.svg-inline--fa.fa-lg {\\n vertical-align: -0.225em;\\n}\\n.svg-inline--fa.fa-w-1 {\\n width: 0.0625em;\\n}\\n.svg-inline--fa.fa-w-2 {\\n width: 0.125em;\\n}\\n.svg-inline--fa.fa-w-3 {\\n width: 0.1875em;\\n}\\n.svg-inline--fa.fa-w-4 {\\n width: 0.25em;\\n}\\n.svg-inline--fa.fa-w-5 {\\n width: 0.3125em;\\n}\\n.svg-inline--fa.fa-w-6 {\\n width: 0.375em;\\n}\\n.svg-inline--fa.fa-w-7 {\\n width: 0.4375em;\\n}\\n.svg-inline--fa.fa-w-8 {\\n width: 0.5em;\\n}\\n.svg-inline--fa.fa-w-9 {\\n width: 0.5625em;\\n}\\n.svg-inline--fa.fa-w-10 {\\n width: 0.625em;\\n}\\n.svg-inline--fa.fa-w-11 {\\n width: 0.6875em;\\n}\\n.svg-inline--fa.fa-w-12 {\\n width: 0.75em;\\n}\\n.svg-inline--fa.fa-w-13 {\\n width: 0.8125em;\\n}\\n.svg-inline--fa.fa-w-14 {\\n width: 0.875em;\\n}\\n.svg-inline--fa.fa-w-15 {\\n width: 0.9375em;\\n}\\n.svg-inline--fa.fa-w-16 {\\n width: 1em;\\n}\\n.svg-inline--fa.fa-w-17 {\\n width: 1.0625em;\\n}\\n.svg-inline--fa.fa-w-18 {\\n width: 1.125em;\\n}\\n.svg-inline--fa.fa-w-19 {\\n width: 1.1875em;\\n}\\n.svg-inline--fa.fa-w-20 {\\n width: 1.25em;\\n}\\n.svg-inline--fa.fa-pull-left {\\n margin-right: 0.3em;\\n width: auto;\\n}\\n.svg-inline--fa.fa-pull-right {\\n margin-left: 0.3em;\\n width: auto;\\n}\\n.svg-inline--fa.fa-border {\\n height: 1.5em;\\n}\\n.svg-inline--fa.fa-li {\\n width: 2em;\\n}\\n.svg-inline--fa.fa-fw {\\n width: 1.25em;\\n}\\n\\n.fa-layers svg.svg-inline--fa {\\n bottom: 0;\\n left: 0;\\n margin: auto;\\n position: absolute;\\n right: 0;\\n top: 0;\\n}\\n\\n.fa-layers {\\n display: inline-block;\\n height: 1em;\\n position: relative;\\n text-align: center;\\n vertical-align: -0.125em;\\n width: 1em;\\n}\\n.fa-layers svg.svg-inline--fa {\\n -webkit-transform-origin: center center;\\n transform-origin: center center;\\n}\\n\\n.fa-layers-counter, .fa-layers-text {\\n display: inline-block;\\n position: absolute;\\n text-align: center;\\n}\\n\\n.fa-layers-text {\\n left: 50%;\\n top: 50%;\\n -webkit-transform: translate(-50%, -50%);\\n transform: translate(-50%, -50%);\\n -webkit-transform-origin: center center;\\n transform-origin: center center;\\n}\\n\\n.fa-layers-counter {\\n background-color: #ff253a;\\n border-radius: 1em;\\n -webkit-box-sizing: border-box;\\n box-sizing: border-box;\\n color: #fff;\\n height: 1.5em;\\n line-height: 1;\\n max-width: 5em;\\n min-width: 1.5em;\\n overflow: hidden;\\n padding: 0.25em;\\n right: 0;\\n text-overflow: ellipsis;\\n top: 0;\\n -webkit-transform: scale(0.25);\\n transform: scale(0.25);\\n -webkit-transform-origin: top right;\\n transform-origin: top right;\\n}\\n\\n.fa-layers-bottom-right {\\n bottom: 0;\\n right: 0;\\n top: auto;\\n -webkit-transform: scale(0.25);\\n transform: scale(0.25);\\n -webkit-transform-origin: bottom right;\\n transform-origin: bottom right;\\n}\\n\\n.fa-layers-bottom-left {\\n bottom: 0;\\n left: 0;\\n right: auto;\\n top: auto;\\n -webkit-transform: scale(0.25);\\n transform: scale(0.25);\\n -webkit-transform-origin: bottom left;\\n transform-origin: bottom left;\\n}\\n\\n.fa-layers-top-right {\\n right: 0;\\n top: 0;\\n -webkit-transform: scale(0.25);\\n transform: scale(0.25);\\n -webkit-transform-origin: top right;\\n transform-origin: top right;\\n}\\n\\n.fa-layers-top-left {\\n left: 0;\\n right: auto;\\n top: 0;\\n -webkit-transform: scale(0.25);\\n transform: scale(0.25);\\n -webkit-transform-origin: top left;\\n transform-origin: top left;\\n}\\n\\n.fa-lg {\\n font-size: 1.3333333333em;\\n line-height: 0.75em;\\n vertical-align: -0.0667em;\\n}\\n\\n.fa-xs {\\n font-size: 0.75em;\\n}\\n\\n.fa-sm {\\n font-size: 0.875em;\\n}\\n\\n.fa-1x {\\n font-size: 1em;\\n}\\n\\n.fa-2x {\\n font-size: 2em;\\n}\\n\\n.fa-3x {\\n font-size: 3em;\\n}\\n\\n.fa-4x {\\n font-size: 4em;\\n}\\n\\n.fa-5x {\\n font-size: 5em;\\n}\\n\\n.fa-6x {\\n font-size: 6em;\\n}\\n\\n.fa-7x {\\n font-size: 7em;\\n}\\n\\n.fa-8x {\\n font-size: 8em;\\n}\\n\\n.fa-9x {\\n font-size: 9em;\\n}\\n\\n.fa-10x {\\n font-size: 10em;\\n}\\n\\n.fa-fw {\\n text-align: center;\\n width: 1.25em;\\n}\\n\\n.fa-ul {\\n list-style-type: none;\\n margin-left: 2.5em;\\n padding-left: 0;\\n}\\n.fa-ul > li {\\n position: relative;\\n}\\n\\n.fa-li {\\n left: -2em;\\n position: absolute;\\n text-align: center;\\n width: 2em;\\n line-height: inherit;\\n}\\n\\n.fa-border {\\n border: solid 0.08em #eee;\\n border-radius: 0.1em;\\n padding: 0.2em 0.25em 0.15em;\\n}\\n\\n.fa-pull-left {\\n float: left;\\n}\\n\\n.fa-pull-right {\\n float: right;\\n}\\n\\n.fa.fa-pull-left,\\n.fas.fa-pull-left,\\n.far.fa-pull-left,\\n.fal.fa-pull-left,\\n.fab.fa-pull-left {\\n margin-right: 0.3em;\\n}\\n.fa.fa-pull-right,\\n.fas.fa-pull-right,\\n.far.fa-pull-right,\\n.fal.fa-pull-right,\\n.fab.fa-pull-right {\\n margin-left: 0.3em;\\n}\\n\\n.fa-spin {\\n -webkit-animation: fa-spin 2s infinite linear;\\n animation: fa-spin 2s infinite linear;\\n}\\n\\n.fa-pulse {\\n -webkit-animation: fa-spin 1s infinite steps(8);\\n animation: fa-spin 1s infinite steps(8);\\n}\\n\\n@-webkit-keyframes fa-spin {\\n 0% {\\n -webkit-transform: rotate(0deg);\\n transform: rotate(0deg);\\n }\\n 100% {\\n -webkit-transform: rotate(360deg);\\n transform: rotate(360deg);\\n }\\n}\\n\\n@keyframes fa-spin {\\n 0% {\\n -webkit-transform: rotate(0deg);\\n transform: rotate(0deg);\\n }\\n 100% {\\n -webkit-transform: rotate(360deg);\\n transform: rotate(360deg);\\n }\\n}\\n.fa-rotate-90 {\\n -ms-filter: \\\"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)\\\";\\n -webkit-transform: rotate(90deg);\\n transform: rotate(90deg);\\n}\\n\\n.fa-rotate-180 {\\n -ms-filter: \\\"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)\\\";\\n -webkit-transform: rotate(180deg);\\n transform: rotate(180deg);\\n}\\n\\n.fa-rotate-270 {\\n -ms-filter: \\\"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)\\\";\\n -webkit-transform: rotate(270deg);\\n transform: rotate(270deg);\\n}\\n\\n.fa-flip-horizontal {\\n -ms-filter: \\\"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)\\\";\\n -webkit-transform: scale(-1, 1);\\n transform: scale(-1, 1);\\n}\\n\\n.fa-flip-vertical {\\n -ms-filter: \\\"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)\\\";\\n -webkit-transform: scale(1, -1);\\n transform: scale(1, -1);\\n}\\n\\n.fa-flip-both, .fa-flip-horizontal.fa-flip-vertical {\\n -ms-filter: \\\"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)\\\";\\n -webkit-transform: scale(-1, -1);\\n transform: scale(-1, -1);\\n}\\n\\n:root .fa-rotate-90,\\n:root .fa-rotate-180,\\n:root .fa-rotate-270,\\n:root .fa-flip-horizontal,\\n:root .fa-flip-vertical,\\n:root .fa-flip-both {\\n -webkit-filter: none;\\n filter: none;\\n}\\n\\n.fa-stack {\\n display: inline-block;\\n height: 2em;\\n position: relative;\\n width: 2.5em;\\n}\\n\\n.fa-stack-1x,\\n.fa-stack-2x {\\n bottom: 0;\\n left: 0;\\n margin: auto;\\n position: absolute;\\n right: 0;\\n top: 0;\\n}\\n\\n.svg-inline--fa.fa-stack-1x {\\n height: 1em;\\n width: 1.25em;\\n}\\n.svg-inline--fa.fa-stack-2x {\\n height: 2em;\\n width: 2.5em;\\n}\\n\\n.fa-inverse {\\n color: #fff;\\n}\\n\\n.sr-only {\\n border: 0;\\n clip: rect(0, 0, 0, 0);\\n height: 1px;\\n margin: -1px;\\n overflow: hidden;\\n padding: 0;\\n position: absolute;\\n width: 1px;\\n}\\n\\n.sr-only-focusable:active, .sr-only-focusable:focus {\\n clip: auto;\\n height: auto;\\n margin: 0;\\n overflow: visible;\\n position: static;\\n width: auto;\\n}\\n\\n.svg-inline--fa .fa-primary {\\n fill: var(--fa-primary-color, currentColor);\\n opacity: 1;\\n opacity: var(--fa-primary-opacity, 1);\\n}\\n\\n.svg-inline--fa .fa-secondary {\\n fill: var(--fa-secondary-color, currentColor);\\n opacity: 0.4;\\n opacity: var(--fa-secondary-opacity, 0.4);\\n}\\n\\n.svg-inline--fa.fa-swap-opacity .fa-primary {\\n opacity: 0.4;\\n opacity: var(--fa-secondary-opacity, 0.4);\\n}\\n\\n.svg-inline--fa.fa-swap-opacity .fa-secondary {\\n opacity: 1;\\n opacity: var(--fa-primary-opacity, 1);\\n}\\n\\n.svg-inline--fa mask .fa-primary,\\n.svg-inline--fa mask .fa-secondary {\\n fill: black;\\n}\\n\\n.fad.fa-inverse {\\n color: #fff;\\n}\";\n\nfunction css () {\n var dfp = DEFAULT_FAMILY_PREFIX;\n var drc = DEFAULT_REPLACEMENT_CLASS;\n var fp = config.familyPrefix;\n var rc = config.replacementClass;\n var s = baseStyles;\n\n if (fp !== dfp || rc !== drc) {\n var dPatt = new RegExp(\"\\\\.\".concat(dfp, \"\\\\-\"), 'g');\n var customPropPatt = new RegExp(\"\\\\--\".concat(dfp, \"\\\\-\"), 'g');\n var rPatt = new RegExp(\"\\\\.\".concat(drc), 'g');\n s = s.replace(dPatt, \".\".concat(fp, \"-\")).replace(customPropPatt, \"--\".concat(fp, \"-\")).replace(rPatt, \".\".concat(rc));\n }\n\n return s;\n}\n\nvar Library =\n/*#__PURE__*/\nfunction () {\n function Library() {\n _classCallCheck(this, Library);\n\n this.definitions = {};\n }\n\n _createClass(Library, [{\n key: \"add\",\n value: function add() {\n var _this = this;\n\n for (var _len = arguments.length, definitions = new Array(_len), _key = 0; _key < _len; _key++) {\n definitions[_key] = arguments[_key];\n }\n\n var additions = definitions.reduce(this._pullDefinitions, {});\n Object.keys(additions).forEach(function (key) {\n _this.definitions[key] = _objectSpread({}, _this.definitions[key] || {}, additions[key]);\n defineIcons(key, additions[key]);\n build();\n });\n }\n }, {\n key: \"reset\",\n value: function reset() {\n this.definitions = {};\n }\n }, {\n key: \"_pullDefinitions\",\n value: function _pullDefinitions(additions, definition) {\n var normalized = definition.prefix && definition.iconName && definition.icon ? {\n 0: definition\n } : definition;\n Object.keys(normalized).map(function (key) {\n var _normalized$key = normalized[key],\n prefix = _normalized$key.prefix,\n iconName = _normalized$key.iconName,\n icon = _normalized$key.icon;\n if (!additions[prefix]) additions[prefix] = {};\n additions[prefix][iconName] = icon;\n });\n return additions;\n }\n }]);\n\n return Library;\n}();\n\nfunction ensureCss() {\n if (config.autoAddCss && !_cssInserted) {\n insertCss(css());\n\n _cssInserted = true;\n }\n}\n\nfunction apiObject(val, abstractCreator) {\n Object.defineProperty(val, 'abstract', {\n get: abstractCreator\n });\n Object.defineProperty(val, 'html', {\n get: function get() {\n return val.abstract.map(function (a) {\n return toHtml(a);\n });\n }\n });\n Object.defineProperty(val, 'node', {\n get: function get() {\n if (!IS_DOM) return;\n var container = DOCUMENT.createElement('div');\n container.innerHTML = val.html;\n return container.children;\n }\n });\n return val;\n}\n\nfunction findIconDefinition(iconLookup) {\n var _iconLookup$prefix = iconLookup.prefix,\n prefix = _iconLookup$prefix === void 0 ? 'fa' : _iconLookup$prefix,\n iconName = iconLookup.iconName;\n if (!iconName) return;\n return iconFromMapping(library.definitions, prefix, iconName) || iconFromMapping(namespace.styles, prefix, iconName);\n}\n\nfunction resolveIcons(next) {\n return function (maybeIconDefinition) {\n var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var iconDefinition = (maybeIconDefinition || {}).icon ? maybeIconDefinition : findIconDefinition(maybeIconDefinition || {});\n var mask = params.mask;\n\n if (mask) {\n mask = (mask || {}).icon ? mask : findIconDefinition(mask || {});\n }\n\n return next(iconDefinition, _objectSpread({}, params, {\n mask: mask\n }));\n };\n}\n\nvar library = new Library();\nvar noAuto = function noAuto() {\n config.autoReplaceSvg = false;\n config.observeMutations = false;\n disconnect();\n};\nvar _cssInserted = false;\nvar dom = {\n i2svg: function i2svg() {\n var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n if (IS_DOM) {\n ensureCss();\n var _params$node = params.node,\n node = _params$node === void 0 ? DOCUMENT : _params$node,\n _params$callback = params.callback,\n callback = _params$callback === void 0 ? function () {} : _params$callback;\n\n if (config.searchPseudoElements) {\n searchPseudoElements(node);\n }\n\n return onTree(node, callback);\n } else {\n return picked.reject('Operation requires a DOM of some kind.');\n }\n },\n css: css,\n insertCss: function insertCss$$1() {\n if (!_cssInserted) {\n insertCss(css());\n\n _cssInserted = true;\n }\n },\n watch: function watch() {\n var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n var autoReplaceSvgRoot = params.autoReplaceSvgRoot,\n observeMutationsRoot = params.observeMutationsRoot;\n\n if (config.autoReplaceSvg === false) {\n config.autoReplaceSvg = true;\n }\n\n config.observeMutations = true;\n domready(function () {\n autoReplace({\n autoReplaceSvgRoot: autoReplaceSvgRoot\n });\n observe({\n treeCallback: onTree,\n nodeCallback: onNode,\n pseudoElementsCallback: searchPseudoElements,\n observeMutationsRoot: observeMutationsRoot\n });\n });\n }\n};\nvar parse = {\n transform: function transform(transformString) {\n return parseTransformString(transformString);\n }\n};\nvar icon = resolveIcons(function (iconDefinition) {\n var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var _params$transform = params.transform,\n transform = _params$transform === void 0 ? meaninglessTransform : _params$transform,\n _params$symbol = params.symbol,\n symbol = _params$symbol === void 0 ? false : _params$symbol,\n _params$mask = params.mask,\n mask = _params$mask === void 0 ? null : _params$mask,\n _params$maskId = params.maskId,\n maskId = _params$maskId === void 0 ? null : _params$maskId,\n _params$title = params.title,\n title = _params$title === void 0 ? null : _params$title,\n _params$titleId = params.titleId,\n titleId = _params$titleId === void 0 ? null : _params$titleId,\n _params$classes = params.classes,\n classes = _params$classes === void 0 ? [] : _params$classes,\n _params$attributes = params.attributes,\n attributes = _params$attributes === void 0 ? {} : _params$attributes,\n _params$styles = params.styles,\n styles = _params$styles === void 0 ? {} : _params$styles;\n if (!iconDefinition) return;\n var prefix = iconDefinition.prefix,\n iconName = iconDefinition.iconName,\n icon = iconDefinition.icon;\n return apiObject(_objectSpread({\n type: 'icon'\n }, iconDefinition), function () {\n ensureCss();\n\n if (config.autoA11y) {\n if (title) {\n attributes['aria-labelledby'] = \"\".concat(config.replacementClass, \"-title-\").concat(titleId || nextUniqueId());\n } else {\n attributes['aria-hidden'] = 'true';\n attributes['focusable'] = 'false';\n }\n }\n\n return makeInlineSvgAbstract({\n icons: {\n main: asFoundIcon(icon),\n mask: mask ? asFoundIcon(mask.icon) : {\n found: false,\n width: null,\n height: null,\n icon: {}\n }\n },\n prefix: prefix,\n iconName: iconName,\n transform: _objectSpread({}, meaninglessTransform, transform),\n symbol: symbol,\n title: title,\n maskId: maskId,\n titleId: titleId,\n extra: {\n attributes: attributes,\n styles: styles,\n classes: classes\n }\n });\n });\n});\nvar text = function text(content) {\n var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var _params$transform2 = params.transform,\n transform = _params$transform2 === void 0 ? meaninglessTransform : _params$transform2,\n _params$title2 = params.title,\n title = _params$title2 === void 0 ? null : _params$title2,\n _params$classes2 = params.classes,\n classes = _params$classes2 === void 0 ? [] : _params$classes2,\n _params$attributes2 = params.attributes,\n attributes = _params$attributes2 === void 0 ? {} : _params$attributes2,\n _params$styles2 = params.styles,\n styles = _params$styles2 === void 0 ? {} : _params$styles2;\n return apiObject({\n type: 'text',\n content: content\n }, function () {\n ensureCss();\n return makeLayersTextAbstract({\n content: content,\n transform: _objectSpread({}, meaninglessTransform, transform),\n title: title,\n extra: {\n attributes: attributes,\n styles: styles,\n classes: [\"\".concat(config.familyPrefix, \"-layers-text\")].concat(_toConsumableArray(classes))\n }\n });\n });\n};\nvar counter = function counter(content) {\n var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var _params$title3 = params.title,\n title = _params$title3 === void 0 ? null : _params$title3,\n _params$classes3 = params.classes,\n classes = _params$classes3 === void 0 ? [] : _params$classes3,\n _params$attributes3 = params.attributes,\n attributes = _params$attributes3 === void 0 ? {} : _params$attributes3,\n _params$styles3 = params.styles,\n styles = _params$styles3 === void 0 ? {} : _params$styles3;\n return apiObject({\n type: 'counter',\n content: content\n }, function () {\n ensureCss();\n return makeLayersCounterAbstract({\n content: content.toString(),\n title: title,\n extra: {\n attributes: attributes,\n styles: styles,\n classes: [\"\".concat(config.familyPrefix, \"-layers-counter\")].concat(_toConsumableArray(classes))\n }\n });\n });\n};\nvar layer = function layer(assembler) {\n var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n var _params$classes4 = params.classes,\n classes = _params$classes4 === void 0 ? [] : _params$classes4;\n return apiObject({\n type: 'layer'\n }, function () {\n ensureCss();\n var children = [];\n assembler(function (args) {\n Array.isArray(args) ? args.map(function (a) {\n children = children.concat(a.abstract);\n }) : children = children.concat(args.abstract);\n });\n return [{\n tag: 'span',\n attributes: {\n class: [\"\".concat(config.familyPrefix, \"-layers\")].concat(_toConsumableArray(classes)).join(' ')\n },\n children: children\n }];\n });\n};\nvar api = {\n noAuto: noAuto,\n config: config,\n dom: dom,\n library: library,\n parse: parse,\n findIconDefinition: findIconDefinition,\n icon: icon,\n text: text,\n counter: counter,\n layer: layer,\n toHtml: toHtml\n};\n\nvar autoReplace = function autoReplace() {\n var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n var _params$autoReplaceSv = params.autoReplaceSvgRoot,\n autoReplaceSvgRoot = _params$autoReplaceSv === void 0 ? DOCUMENT : _params$autoReplaceSv;\n if ((Object.keys(namespace.styles).length > 0 || config.autoFetchSvg) && IS_DOM && config.autoReplaceSvg) api.dom.i2svg({\n node: autoReplaceSvgRoot\n });\n};\n\nexport { icon, noAuto, config, toHtml, layer, text, counter, library, dom, parse, findIconDefinition };\n","'use strict';\nObject.defineProperty(exports, '__esModule', { value: true });\nvar prefix = 'fas';\nvar iconName = 'chevron-left';\nvar width = 320;\nvar height = 512;\nvar ligatures = [];\nvar unicode = 'f053';\nvar svgPathData = 'M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z';\n\nexports.definition = {\n prefix: prefix,\n iconName: iconName,\n icon: [\n width,\n height,\n ligatures,\n unicode,\n svgPathData\n ]};\n\nexports.faChevronLeft = exports.definition;\nexports.prefix = prefix;\nexports.iconName = iconName;\nexports.width = width;\nexports.height = height;\nexports.ligatures = ligatures;\nexports.unicode = unicode;\nexports.svgPathData = svgPathData;","'use strict';\nObject.defineProperty(exports, '__esModule', { value: true });\nvar prefix = 'fas';\nvar iconName = 'envelope';\nvar width = 512;\nvar height = 512;\nvar ligatures = [];\nvar unicode = 'f0e0';\nvar svgPathData = 'M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z';\n\nexports.definition = {\n prefix: prefix,\n iconName: iconName,\n icon: [\n width,\n height,\n ligatures,\n unicode,\n svgPathData\n ]};\n\nexports.faEnvelope = exports.definition;\nexports.prefix = prefix;\nexports.iconName = iconName;\nexports.width = width;\nexports.height = height;\nexports.ligatures = ligatures;\nexports.unicode = unicode;\nexports.svgPathData = svgPathData;","'use strict';\nObject.defineProperty(exports, '__esModule', { value: true });\nvar prefix = 'fas';\nvar iconName = 'fax';\nvar width = 512;\nvar height = 512;\nvar ligatures = [];\nvar unicode = 'f1ac';\nvar svgPathData = 'M480 160V77.25a32 32 0 0 0-9.38-22.63L425.37 9.37A32 32 0 0 0 402.75 0H160a32 32 0 0 0-32 32v448a32 32 0 0 0 32 32h320a32 32 0 0 0 32-32V192a32 32 0 0 0-32-32zM288 432a16 16 0 0 1-16 16h-32a16 16 0 0 1-16-16v-32a16 16 0 0 1 16-16h32a16 16 0 0 1 16 16zm0-128a16 16 0 0 1-16 16h-32a16 16 0 0 1-16-16v-32a16 16 0 0 1 16-16h32a16 16 0 0 1 16 16zm128 128a16 16 0 0 1-16 16h-32a16 16 0 0 1-16-16v-32a16 16 0 0 1 16-16h32a16 16 0 0 1 16 16zm0-128a16 16 0 0 1-16 16h-32a16 16 0 0 1-16-16v-32a16 16 0 0 1 16-16h32a16 16 0 0 1 16 16zm0-112H192V64h160v48a16 16 0 0 0 16 16h48zM64 128H32a32 32 0 0 0-32 32v320a32 32 0 0 0 32 32h32a32 32 0 0 0 32-32V160a32 32 0 0 0-32-32z';\n\nexports.definition = {\n prefix: prefix,\n iconName: iconName,\n icon: [\n width,\n height,\n ligatures,\n unicode,\n svgPathData\n ]};\n\nexports.faFax = exports.definition;\nexports.prefix = prefix;\nexports.iconName = iconName;\nexports.width = width;\nexports.height = height;\nexports.ligatures = ligatures;\nexports.unicode = unicode;\nexports.svgPathData = svgPathData;","'use strict';\nObject.defineProperty(exports, '__esModule', { value: true });\nvar prefix = 'fas';\nvar iconName = 'info-circle';\nvar width = 512;\nvar height = 512;\nvar ligatures = [];\nvar unicode = 'f05a';\nvar svgPathData = 'M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z';\n\nexports.definition = {\n prefix: prefix,\n iconName: iconName,\n icon: [\n width,\n height,\n ligatures,\n unicode,\n svgPathData\n ]};\n\nexports.faInfoCircle = exports.definition;\nexports.prefix = prefix;\nexports.iconName = iconName;\nexports.width = width;\nexports.height = height;\nexports.ligatures = ligatures;\nexports.unicode = unicode;\nexports.svgPathData = svgPathData;","'use strict';\nObject.defineProperty(exports, '__esModule', { value: true });\nvar prefix = 'fas';\nvar iconName = 'map-marker-alt';\nvar width = 384;\nvar height = 512;\nvar ligatures = [];\nvar unicode = 'f3c5';\nvar svgPathData = 'M172.268 501.67C26.97 291.031 0 269.413 0 192 0 85.961 85.961 0 192 0s192 85.961 192 192c0 77.413-26.97 99.031-172.268 309.67-9.535 13.774-29.93 13.773-39.464 0zM192 272c44.183 0 80-35.817 80-80s-35.817-80-80-80-80 35.817-80 80 35.817 80 80 80z';\n\nexports.definition = {\n prefix: prefix,\n iconName: iconName,\n icon: [\n width,\n height,\n ligatures,\n unicode,\n svgPathData\n ]};\n\nexports.faMapMarkerAlt = exports.definition;\nexports.prefix = prefix;\nexports.iconName = iconName;\nexports.width = width;\nexports.height = height;\nexports.ligatures = ligatures;\nexports.unicode = unicode;\nexports.svgPathData = svgPathData;","'use strict';\nObject.defineProperty(exports, '__esModule', { value: true });\nvar prefix = 'fas';\nvar iconName = 'minus';\nvar width = 448;\nvar height = 512;\nvar ligatures = [];\nvar unicode = 'f068';\nvar svgPathData = 'M416 208H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h384c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z';\n\nexports.definition = {\n prefix: prefix,\n iconName: iconName,\n icon: [\n width,\n height,\n ligatures,\n unicode,\n svgPathData\n ]};\n\nexports.faMinus = exports.definition;\nexports.prefix = prefix;\nexports.iconName = iconName;\nexports.width = width;\nexports.height = height;\nexports.ligatures = ligatures;\nexports.unicode = unicode;\nexports.svgPathData = svgPathData;","'use strict';\nObject.defineProperty(exports, '__esModule', { value: true });\nvar prefix = 'fas';\nvar iconName = 'phone';\nvar width = 512;\nvar height = 512;\nvar ligatures = [];\nvar unicode = 'f095';\nvar svgPathData = 'M493.4 24.6l-104-24c-11.3-2.6-22.9 3.3-27.5 13.9l-48 112c-4.2 9.8-1.4 21.3 6.9 28l60.6 49.6c-36 76.7-98.9 140.5-177.2 177.2l-49.6-60.6c-6.8-8.3-18.2-11.1-28-6.9l-112 48C3.9 366.5-2 378.1.6 389.4l24 104C27.1 504.2 36.7 512 48 512c256.1 0 464-207.5 464-464 0-11.2-7.7-20.9-18.6-23.4z';\n\nexports.definition = {\n prefix: prefix,\n iconName: iconName,\n icon: [\n width,\n height,\n ligatures,\n unicode,\n svgPathData\n ]};\n\nexports.faPhone = exports.definition;\nexports.prefix = prefix;\nexports.iconName = iconName;\nexports.width = width;\nexports.height = height;\nexports.ligatures = ligatures;\nexports.unicode = unicode;\nexports.svgPathData = svgPathData;","'use strict';\nObject.defineProperty(exports, '__esModule', { value: true });\nvar prefix = 'fas';\nvar iconName = 'plus';\nvar width = 448;\nvar height = 512;\nvar ligatures = [];\nvar unicode = 'f067';\nvar svgPathData = 'M416 208H272V64c0-17.67-14.33-32-32-32h-32c-17.67 0-32 14.33-32 32v144H32c-17.67 0-32 14.33-32 32v32c0 17.67 14.33 32 32 32h144v144c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32V304h144c17.67 0 32-14.33 32-32v-32c0-17.67-14.33-32-32-32z';\n\nexports.definition = {\n prefix: prefix,\n iconName: iconName,\n icon: [\n width,\n height,\n ligatures,\n unicode,\n svgPathData\n ]};\n\nexports.faPlus = exports.definition;\nexports.prefix = prefix;\nexports.iconName = iconName;\nexports.width = width;\nexports.height = height;\nexports.ligatures = ligatures;\nexports.unicode = unicode;\nexports.svgPathData = svgPathData;","'use strict';\nObject.defineProperty(exports, '__esModule', { value: true });\nvar prefix = 'fas';\nvar iconName = 'search';\nvar width = 512;\nvar height = 512;\nvar ligatures = [];\nvar unicode = 'f002';\nvar svgPathData = 'M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z';\n\nexports.definition = {\n prefix: prefix,\n iconName: iconName,\n icon: [\n width,\n height,\n ligatures,\n unicode,\n svgPathData\n ]};\n\nexports.faSearch = exports.definition;\nexports.prefix = prefix;\nexports.iconName = iconName;\nexports.width = width;\nexports.height = height;\nexports.ligatures = ligatures;\nexports.unicode = unicode;\nexports.svgPathData = svgPathData;","'use strict';\nObject.defineProperty(exports, '__esModule', { value: true });\nvar prefix = 'fas';\nvar iconName = 'user';\nvar width = 448;\nvar height = 512;\nvar ligatures = [];\nvar unicode = 'f007';\nvar svgPathData = 'M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z';\n\nexports.definition = {\n prefix: prefix,\n iconName: iconName,\n icon: [\n width,\n height,\n ligatures,\n unicode,\n svgPathData\n ]};\n\nexports.faUser = exports.definition;\nexports.prefix = prefix;\nexports.iconName = iconName;\nexports.width = width;\nexports.height = height;\nexports.ligatures = ligatures;\nexports.unicode = unicode;\nexports.svgPathData = svgPathData;","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t__webpack_require__(1);\n\tmodule.exports = __webpack_require__(1);\n\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){\r\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\r\n\t})(function(){\r\n\r\n\t(function ($, undefined) {\r\n\t var kendo = window.kendo,\r\n\t ui = kendo.ui;\r\n\r\n\t if (ui && ui.ComboBox) {\r\n\t ui.ComboBox.requestData = function (selector) {\r\n\t var combobox = $(selector).data(\"kendoComboBox\");\r\n\r\n\t if (!combobox) {\r\n\t return;\r\n\t }\r\n\r\n\t var filter = combobox.dataSource.filter();\r\n\t var value = combobox.input.val();\r\n\r\n\t if (!filter || !filter.filters.length) {\r\n\t value = \"\";\r\n\t }\r\n\r\n\t return { text: value };\r\n\t };\r\n\t }\r\n\r\n\t})(window.kendo.jQuery);\r\n\r\n\t}, __webpack_require__(3));\r\n\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"./kendo.data.aspnetmvc\");\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ })\n/******/ ]);","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t__webpack_require__(4);\n\tmodule.exports = __webpack_require__(4);\n\n\n/***/ }),\n/* 1 */,\n/* 2 */,\n/* 3 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n/* 4 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(5), __webpack_require__(6), __webpack_require__(7), __webpack_require__(8) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t})(function(){\n\n\t(function ($, undefined) {\n\t var kendo = window.kendo,\n\t escapeQuoteRegExp = /'/ig,\n\t extend = $.extend,\n\t isArray = $.isArray,\n\t isPlainObject = $.isPlainObject,\n\t POINT = \".\";\n\n\t function parameterMap(options, operation, serializationOptions) {\n\t var result = {};\n\n\t if (options.sort) {\n\t result[this.options.prefix + \"sort\"] = $.map(options.sort, function(sort) {\n\t return sort.field + \"-\" + sort.dir;\n\t }).join(\"~\");\n\n\t delete options.sort;\n\t } else {\n\t result[this.options.prefix + \"sort\"] = \"\";\n\t }\n\n\t if (options.page) {\n\t result[this.options.prefix + \"page\"] = options.page;\n\n\t delete options.page;\n\t }\n\n\t if (options.pageSize) {\n\t result[this.options.prefix + \"pageSize\"] = options.pageSize;\n\n\t delete options.pageSize;\n\t }\n\n\t if (options.group) {\n\t result[this.options.prefix + \"group\"] = $.map(options.group, function(group) {\n\t return group.field + \"-\" + group.dir;\n\t }).join(\"~\");\n\n\t delete options.group;\n\t } else {\n\t result[this.options.prefix + \"group\"] = \"\";\n\t }\n\n\t if (options.aggregate) {\n\t result[this.options.prefix + \"aggregate\"] = $.map(options.aggregate, function(aggregate) {\n\t return aggregate.field + \"-\" + aggregate.aggregate;\n\t }).join(\"~\");\n\n\t delete options.aggregate;\n\t }\n\n\t if (options.filter) {\n\t result[this.options.prefix + \"filter\"] = serializeFilter(options.filter, serializationOptions.encode);\n\n\t delete options.filter;\n\t } else {\n\t result[this.options.prefix + \"filter\"] = \"\";\n\t delete options.filter;\n\t }\n\n\t if (!options.groupPaging) {\n\t delete options.take;\n\t delete options.skip;\n\t }\n\n\t var serializer = new Serializer(serializationOptions);\n\t serializer.serialize(result, options, \"\");\n\n\t return result;\n\t }\n\n\t var Serializer = function(options) {\n\t options = options || {};\n\t this.culture = options.culture || kendo.culture();\n\t this.stringifyDates = options.stringifyDates;\n\t this.decimalSeparator = this.culture.numberFormat[POINT];\n\t };\n\n\t Serializer.prototype = Serializer.fn = {\n\t serialize: function(result, data, prefix) {\n\t var valuePrefix;\n\t for (var key in data) {\n\t valuePrefix = prefix ? prefix + \".\" + key : key;\n\t this.serializeField(result, data[key], data, key, valuePrefix);\n\t }\n\t },\n\n\t serializeField: function (result, value, data, key, prefix) {\n\t if (isArray(value)) {\n\t this.serializeArray(result, value, prefix);\n\t } else if (isPlainObject(value)) {\n\t this.serialize(result, value, prefix);\n\t } else {\n\t if (result[prefix] === undefined) {\n\t result[prefix] = data[key] = this.serializeValue(value);\n\t }\n\t }\n\t },\n\n\t serializeArray: function (result, data, prefix) {\n\t var value, key, valuePrefix;\n\t for (var sourceIndex = 0, destinationIndex = 0; sourceIndex < data.length; sourceIndex++) {\n\t value = data[sourceIndex];\n\t key = \"[\" + destinationIndex + \"]\";\n\t valuePrefix = prefix + key;\n\n\t this.serializeField(result, value, data, key, valuePrefix);\n\n\t destinationIndex++;\n\t }\n\t },\n\n\t serializeValue: function (value) {\n\t if (value instanceof Date) {\n\t if (this.stringifyDates) {\n\t value = kendo.stringify(value).replace(/\"/g, \"\");\n\t } else {\n\t value = kendo.toString(value, \"G\", this.culture.name);\n\t }\n\t } else if (typeof value === \"number\") {\n\t value = value.toString().replace(POINT, this.decimalSeparator);\n\t }\n\t return value;\n\t }\n\t };\n\n\t function serializeFilter(filter, encode) {\n\t if (filter.filters) {\n\t return $.map(filter.filters, function(f) {\n\t var hasChildren = f.filters && f.filters.length > 1,\n\t result = serializeFilter(f, encode);\n\n\t if (result && hasChildren) {\n\t result = \"(\" + result + \")\";\n\t }\n\n\t return result;\n\t }).join(\"~\" + filter.logic + \"~\");\n\t }\n\n\t if (filter.field) {\n\t return filter.field + \"~\" + filter.operator + \"~\" + encodeFilterValue(filter.value, encode);\n\t } else {\n\t return undefined;\n\t }\n\t }\n\n\t function encodeFilterValue(value, encode) {\n\t if (typeof value === \"string\") {\n\t if (value.indexOf('Date(') > -1) {\n\t value = new Date(parseInt(value.replace(/^\\/Date\\((.*?)\\)\\/$/, '$1'), 10));\n\t } else {\n\t value = value.replace(escapeQuoteRegExp, \"''\");\n\n\t if (encode) {\n\t value = encodeURIComponent(value);\n\t }\n\n\t return \"'\" + value + \"'\";\n\t }\n\t }\n\n\t if (value && value.getTime) {\n\t return \"datetime'\" + kendo.format(\"{0:yyyy-MM-ddTHH-mm-ss}\", value) + \"'\";\n\t }\n\t return value;\n\t }\n\n\t function valueOrDefault(value, defaultValue) {\n\t return typeof value !== \"undefined\" ? value : defaultValue;\n\t }\n\n\t function translateGroup(group) {\n\t var hasSubgroups = group.HasSubgroups || group.hasSubgroups || false;\n\t var items = group.Items || group.items;\n\t var itemCount = group.ItemCount || group.itemCount;\n\t var subgroupCount = group.SubgroupCount || group.subgroupCount;\n\n\t return {\n\t value: valueOrDefault(group.Key, valueOrDefault(group.key, group.value)),\n\t field: group.Member || group.member || group.field,\n\t hasSubgroups: hasSubgroups,\n\t aggregates: translateAggregate(group.Aggregates || group.aggregates),\n\t items: hasSubgroups ? $.map(items, translateGroup) : items,\n\t itemCount: itemCount,\n\t subgroupCount: subgroupCount,\n\t uid: kendo.guid()\n\t };\n\t }\n\n\t function translateAggregateResults(aggregate) {\n\t var obj = {};\n\t obj[aggregate.AggregateMethodName.toLowerCase()] = aggregate.Value;\n\n\t return obj;\n\t }\n\n\t function translateAggregate(aggregates) {\n\t var functionResult = {},\n\t key,\n\t functionName,\n\t aggregate;\n\n\t for (key in aggregates) {\n\t functionResult = {};\n\t aggregate = aggregates[key];\n\n\t for (functionName in aggregate) {\n\t functionResult[functionName.toLowerCase()] = aggregate[functionName];\n\t }\n\n\t aggregates[key] = functionResult;\n\t }\n\n\t return aggregates;\n\t }\n\n\t function convertAggregates(aggregates) {\n\t var idx, length, aggregate;\n\t var result = {};\n\n\t for (idx = 0, length = aggregates.length; idx < length; idx++) {\n\t aggregate = aggregates[idx];\n\t result[aggregate.Member] = extend(true, result[aggregate.Member], translateAggregateResults(aggregate));\n\t }\n\n\t return result;\n\t }\n\n\t extend(true, kendo.data, {\n\t schemas: {\n\t \"aspnetmvc-ajax\": {\n\t groups: function(data) {\n\t return $.map(this._dataAccessFunction(data), translateGroup);\n\t },\n\t aggregates: function(data) {\n\t data = data.d || data;\n\t var aggregates = data.AggregateResults || [];\n\n\t if (!$.isArray(aggregates)) {\n\t for (var key in aggregates) {\n\t aggregates[key] = convertAggregates(aggregates[key]);\n\t }\n\n\t return aggregates;\n\t }\n\n\t return convertAggregates(aggregates);\n\t }\n\t }\n\t }\n\t });\n\n\t extend(true, kendo.data, {\n\t transports: {\n\t \"aspnetmvc-ajax\": kendo.data.RemoteTransport.extend({\n\t init: function(options) {\n\t var that = this,\n\t stringifyDates = (options || {}).stringifyDates;\n\n\t kendo.data.RemoteTransport.fn.init.call(this,\n\t extend(true, {}, this.options, options, {\n\t parameterMap: function(options, operation) {\n\t return parameterMap.call(that, options, operation, {\n\t encode: false,\n\t stringifyDates: stringifyDates\n\t });\n\t }\n\t })\n\t );\n\t },\n\t read: function(options) {\n\t var data = this.options.data,\n\t url = this.options.read.url;\n\n\t if (isPlainObject(data)) {\n\t if (url) {\n\t this.options.data = null;\n\t }\n\n\t if (!data.Data.length && url) {\n\t kendo.data.RemoteTransport.fn.read.call(this, options);\n\t } else {\n\t options.success(data);\n\t }\n\t } else {\n\t kendo.data.RemoteTransport.fn.read.call(this, options);\n\t }\n\t },\n\t options: {\n\t read: {\n\t type: \"POST\"\n\t },\n\t update: {\n\t type: \"POST\"\n\t },\n\t create: {\n\t type: \"POST\"\n\t },\n\t destroy: {\n\t type: \"POST\"\n\t },\n\t parameterMap: parameterMap,\n\t prefix: \"\"\n\t }\n\t })\n\t }\n\t });\n\n\t extend(true, kendo.data, {\n\t schemas: {\n\t \"webapi\": kendo.data.schemas[\"aspnetmvc-ajax\"]\n\t }\n\t });\n\n\t extend(true, kendo.data, {\n\t transports: {\n\t \"webapi\": kendo.data.RemoteTransport.extend({\n\t init: function(options) {\n\t var that = this;\n\t var stringifyDates = (options || {}).stringifyDates;\n\t var culture = kendo.cultures[options.culture] || kendo.cultures[\"en-US\"];\n\n\t if (options.update) {\n\t var updateUrl = typeof options.update === \"string\" ? options.update : options.update.url;\n\n\t options.update = extend(options.update, {url: function (data) {\n\t return kendo.format(updateUrl, data[options.idField]);\n\t }});\n\t }\n\n\t if (options.destroy) {\n\t var destroyUrl = typeof options.destroy === \"string\" ? options.destroy : options.destroy.url;\n\n\t options.destroy = extend(options.destroy, {url: function (data) {\n\t return kendo.format(destroyUrl, data[options.idField]);\n\t }});\n\t }\n\n\t if(options.create && typeof options.create === \"string\") {\n\t options.create = {\n\t url: options.create\n\t };\n\t }\n\n\t kendo.data.RemoteTransport.fn.init.call(this,\n\t extend(true, {}, this.options, options, {\n\t parameterMap: function(options, operation) {\n\t return parameterMap.call(that, options, operation, {\n\t encode: false,\n\t stringifyDates: stringifyDates,\n\t culture: culture\n\t });\n\t }\n\t })\n\t );\n\t },\n\t read: function(options) {\n\t var data = this.options.data,\n\t url = this.options.read.url;\n\n\t if (isPlainObject(data)) {\n\t if (url) {\n\t this.options.data = null;\n\t }\n\n\t if (!data.Data.length && url) {\n\t kendo.data.RemoteTransport.fn.read.call(this, options);\n\t } else {\n\t options.success(data);\n\t }\n\t } else {\n\t kendo.data.RemoteTransport.fn.read.call(this, options);\n\t }\n\t },\n\t options: {\n\t read: {\n\t type: \"GET\"\n\t },\n\t update: {\n\t type: \"PUT\"\n\t },\n\t create: {\n\t type: \"POST\"\n\t },\n\t destroy: {\n\t type: \"DELETE\"\n\t },\n\t parameterMap: parameterMap,\n\t prefix: \"\"\n\t }\n\t })\n\t }\n\t });\n\n\t extend(true, kendo.data, {\n\t transports: {\n\t \"aspnetmvc-server\": kendo.data.RemoteTransport.extend({\n\t init: function(options) {\n\t var that = this;\n\n\t kendo.data.RemoteTransport.fn.init.call(this,\n\t extend(options, {\n\t parameterMap: function(options, operation) {\n\t return parameterMap.call(that, options, operation, {\n\t encode: true\n\t });\n\t }\n\t }\n\t ));\n\t },\n\t read: function(options) {\n\t var url,\n\t prefix = this.options.prefix,\n\t params = [prefix + \"sort\",\n\t prefix + \"page\",\n\t prefix + \"pageSize\",\n\t prefix + \"group\",\n\t prefix + \"aggregate\",\n\t prefix + \"filter\"],\n\t regExp = new RegExp(\"(\" + params.join('|') + \")=[^&]*&?\", \"g\"),\n\t query;\n\n\t query = location.search.replace(regExp, \"\").replace(\"?\", \"\");\n\n\t if (query.length && !(/&$/.test(query))) {\n\t query += \"&\";\n\t }\n\n\t options = this.setup(options, \"read\");\n\n\t url = options.url;\n\n\t if (url.indexOf(\"?\") >= 0) {\n\t query = query.replace(/(.*?=.*?)&/g, function(match){\n\t if(url.indexOf(match.substr(0, match.indexOf(\"=\"))) >= 0){\n\t return \"\";\n\t }\n\t return match;\n\t });\n\t url += \"&\" + query;\n\t } else {\n\t url += \"?\" + query;\n\t }\n\n\t url += $.map(options.data, function(value, key) {\n\t return key + \"=\" + value;\n\t }).join(\"&\");\n\n\t location.href = url;\n\t }\n\t })\n\t }\n\t });\n\t})(window.kendo.jQuery);\n\n\t}, __webpack_require__(3));\n\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../kendo.data\");\n\n/***/ }),\n/* 6 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../kendo.combobox\");\n\n/***/ }),\n/* 7 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../kendo.multiselect\");\n\n/***/ }),\n/* 8 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../kendo.validator\");\n\n/***/ })\n/******/ ]);","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t__webpack_require__(9);\n\tmodule.exports = __webpack_require__(9);\n\n\n/***/ }),\n/* 1 */,\n/* 2 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"./kendo.data.aspnetmvc\");\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n/* 4 */,\n/* 5 */,\n/* 6 */,\n/* 7 */,\n/* 8 */,\n/* 9 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){\r\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\r\n\t})(function(){\r\n\r\n\t(function ($, undefined) {\r\n\t var kendo = window.kendo,\r\n\t ui = kendo.ui;\r\n\r\n\t if (ui && ui.DropDownList) {\r\n\t ui.DropDownList.requestData = function (selector) {\r\n\t var dropdownlist = $(selector).data(\"kendoDropDownList\");\r\n\r\n\t if (!dropdownlist) {\r\n\t return;\r\n\t }\r\n\r\n\t var filter = dropdownlist.dataSource.filter();\r\n\t var filterInput = dropdownlist.filterInput;\r\n\t var value = filterInput ? filterInput.val() : \"\";\r\n\r\n\t if (!filter || !filter.filters.length) {\r\n\t value = \"\";\r\n\t }\r\n\r\n\t return { text: value };\r\n\t };\r\n\t }\r\n\r\n\t})(window.kendo.jQuery);\r\n\r\n\t}, __webpack_require__(3));\r\n\n\n/***/ })\n/******/ ]);","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t__webpack_require__(10);\n\tmodule.exports = __webpack_require__(10);\n\n\n/***/ }),\n/* 1 */,\n/* 2 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"./kendo.data.aspnetmvc\");\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n/* 4 */,\n/* 5 */,\n/* 6 */,\n/* 7 */,\n/* 8 */,\n/* 9 */,\n/* 10 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t})(function(){\n\n\t(function ($, undefined) {\n\t var kendo = window.kendo,\n\t ui = kendo.ui;\n\n\t if (ui && ui.DropDownTree) {\n\t ui.DropDownTree.requestData = function (selector) {\n\t var dropdowntree = $(selector).data(\"kendoDropDownTree\");\n\n\t if (!dropdowntree) {\n\t return;\n\t }\n\n\t var filter = dropdowntree.dataSource.filter();\n\t var filterInput = dropdowntree.filterInput;\n\t var value = filterInput ? filterInput.val() : \"\";\n\n\t if (!filter || !filter.filters.length) {\n\t value = \"\";\n\t }\n\n\t return { text: value };\n\t };\n\t }\n\n\t})(window.kendo.jQuery);\n\n\t}, __webpack_require__(3));\n\n\n/***/ })\n/******/ ]);","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t__webpack_require__(11);\n\tmodule.exports = __webpack_require__(11);\n\n\n/***/ }),\n/* 1 */,\n/* 2 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"./kendo.data.aspnetmvc\");\n\n/***/ }),\n/* 3 */\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n/* 4 */,\n/* 5 */,\n/* 6 */,\n/* 7 */,\n/* 8 */,\n/* 9 */,\n/* 10 */,\n/* 11 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t})(function(){\n\n\t(function ($, undefined) {\n\t var kendo = window.kendo,\n\t extend = $.extend;\n\n\t extend(true, kendo.data, {\n\t schemas: {\n\t \"filemanager\": {\n\t data: function(data) {\n\t return data || [];\n\t },\n\t model: {\n\t id: \"path\",\n\t hasChildren: \"hasDirectories\",\n\t fields: {\n\t name: {field: \"Name\", editable: true, type: \"String\", defaultValue: \"New Folder\" },\n\t size: {field: \"Size\", editable: false, type: \"Number\"},\n\t path: {field: \"Path\", editable: false, type: \"String\"},\n\t extension: {field: \"Extension\", editable: false, type: \"String\"},\n\t isDirectory: {field: \"IsDirectory\", editable: false, defaultValue: true, type: \"Boolean\"},\n\t hasDirectories: {field: \"HasDirectories\", editable: false, defaultValue: false, type: \"Boolean\"},\n\t created: {field: \"Created\", type: \"Date\", editable: false},\n\t createdUtc: {field: \"CreatedUtc\", type: \"Date\", editable: false },\n\t modified: {field: \"Modified\", type: \"Date\", editable: false},\n\t modifiedUtc: {field: \"ModifiedUtc\", type: \"Date\", editable: false }\n\t }\n\t }\n\t }\n\t }\n\t });\n\t})(window.kendo.jQuery);\n\n\t}, __webpack_require__(3));\n\n\n/***/ })\n/******/ ]);","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ 0:\n/***/ (function(module, exports, __webpack_require__) {\n\n\t__webpack_require__(12);\n\tmodule.exports = __webpack_require__(12);\n\n\n/***/ }),\n\n/***/ 3:\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n\n/***/ 12:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){\r\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(13) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\r\n\t})(function(){\r\n\r\n\t(function ($, undefined) {\r\n\t var kendo = window.kendo,\r\n\t extend = $.extend,\r\n\t isFunction = $.isFunction;\r\n\r\n\t extend(true, kendo.data, {\r\n\t schemas: {\r\n\t \"imagebrowser-aspnetmvc\": {\r\n\t data: function(data) {\r\n\t return data || [];\r\n\t },\r\n\t model: {\r\n\t id: \"name\",\r\n\t fields: {\r\n\t name: { field: \"Name\" },\r\n\t size: { field: \"Size\" },\r\n\t type: { field: \"EntryType\", parse: function(value) { return value == 0 ? \"f\" : \"d\"; } } // jshint ignore:line, afraid to break something with strict equality\r\n\t }\r\n\t }\r\n\t }\r\n\t }\r\n\t });\r\n\r\n\t extend(true, kendo.data, {\r\n\t schemas: {\r\n\t \"filebrowser-aspnetmvc\": kendo.data.schemas[\"imagebrowser-aspnetmvc\"]\r\n\t }\r\n\t });\r\n\r\n\t extend(true, kendo.data, {\r\n\t transports: {\r\n\t \"imagebrowser-aspnetmvc\": kendo.data.RemoteTransport.extend({\r\n\t init: function(options) {\r\n\t kendo.data.RemoteTransport.fn.init.call(this, $.extend(true, {}, this.options, options));\r\n\t },\r\n\t _call: function(type, options) {\r\n\t options.data = $.extend({}, options.data, { path: this.options.path() });\r\n\r\n\t if (isFunction(this.options[type])) {\r\n\t this.options[type].call(this, options);\r\n\t } else {\r\n\t kendo.data.RemoteTransport.fn[type].call(this, options);\r\n\t }\r\n\t },\r\n\t read: function(options) {\r\n\t this._call(\"read\", options);\r\n\t },\r\n\t create: function(options) {\r\n\t this._call(\"create\", options);\r\n\t },\r\n\t destroy: function(options) {\r\n\t this._call(\"destroy\", options);\r\n\t },\r\n\t update: function() {\r\n\t //updates are handled by the upload\r\n\t },\r\n\t options: {\r\n\t read: {\r\n\t type: \"POST\"\r\n\t },\r\n\t update: {\r\n\t type: \"POST\"\r\n\t },\r\n\t create: {\r\n\t type: \"POST\"\r\n\t },\r\n\t destroy: {\r\n\t type: \"POST\"\r\n\t },\r\n\t parameterMap: function(options, type) {\r\n\t if (type != \"read\") {\r\n\t options.EntryType = options.EntryType === \"f\" ? 0 : 1;\r\n\t }\r\n\t return options;\r\n\t }\r\n\t }\r\n\t })\r\n\t }\r\n\t });\r\n\r\n\t extend(true, kendo.data, {\r\n\t transports: {\r\n\t \"filebrowser-aspnetmvc\": kendo.data.transports[\"imagebrowser-aspnetmvc\"]\r\n\t }\r\n\t });\r\n\r\n\t})(window.kendo.jQuery);\r\n\r\n\t}, __webpack_require__(3));\r\n\n\n/***/ }),\n\n/***/ 13:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"./kendo.multiselect.aspnetmvc\");\n\n/***/ })\n\n/******/ });","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ 0:\n/***/ (function(module, exports, __webpack_require__) {\n\n\t__webpack_require__(14);\n\tmodule.exports = __webpack_require__(14);\n\n\n/***/ }),\n\n/***/ 2:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"./kendo.data.aspnetmvc\");\n\n/***/ }),\n\n/***/ 3:\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n\n/***/ 14:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(2) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t})(function(){\n\n\t(function ($, undefined) {\n\t var kendo = window.kendo,\n\t ui = kendo.ui;\n\n\t if (ui && ui.MultiColumnComboBox) {\n\t ui.MultiColumnComboBox.requestData = function (selector) {\n\n\t var multicolumncombobox = $(selector).data(\"kendoMultiColumnComboBox\");\n\n\t if (!multicolumncombobox) {\n\t return;\n\t }\n\n\t var filter = multicolumncombobox.dataSource.filter();\n\t var value = multicolumncombobox.input.val();\n\n\t if (!filter || !filter.filters.length) {\n\t value = \"\";\n\t }\n\n\t return { text: value };\n\t };\n\t }\n\n\t})(window.kendo.jQuery);\n\n\t}, __webpack_require__(3));\n\n\n/***/ })\n\n/******/ });","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ 0:\n/***/ (function(module, exports, __webpack_require__) {\n\n\t__webpack_require__(15);\n\tmodule.exports = __webpack_require__(15);\n\n\n/***/ }),\n\n/***/ 3:\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n\n/***/ 15:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){\r\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(16) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\r\n\t})(function(){\r\n\r\n\t(function ($, undefined) {\r\n\t var kendo = window.kendo,\r\n\t ui = kendo.ui;\r\n\r\n\t if (ui && ui.MultiSelect) {\r\n\t ui.MultiSelect.requestData = function (selector) {\r\n\t var multiselect = $(selector).data(\"kendoMultiSelect\");\r\n\r\n\t if (!multiselect) {\r\n\t return;\r\n\t }\r\n\r\n\t var text = multiselect.input.val();\r\n\r\n\t return { text: text !== multiselect.options.placeholder ? text : \"\" };\r\n\t };\r\n\t }\r\n\r\n\t})(window.kendo.jQuery);\r\n\r\n\t}, __webpack_require__(3));\r\n\n\n/***/ }),\n\n/***/ 16:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"./kendo.combobox.aspnetmvc\");\n\n/***/ })\n\n/******/ });","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ 0:\n/***/ (function(module, exports, __webpack_require__) {\n\n\t__webpack_require__(17);\n\tmodule.exports = __webpack_require__(17);\n\n\n/***/ }),\n\n/***/ 3:\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n\n/***/ 17:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(18) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t})(function(){\n\n\t(function ($, undefined) {\n\t var nameSpecialCharRegExp = /(\"|\\%|'|\\[|\\]|\\$|\\.|\\,|\\:|\\;|\\+|\\*|\\&|\\!|\\#|\\(|\\)|<|>|\\=|\\?|\\@|\\^|\\{|\\}|\\~|\\/|\\||`)/g;\n\t var SWITCHSELECTOR = \".k-switch\";\n\n\t function generateMessages() {\n\t var name,\n\t messages = {};\n\n\t for (name in validationRules) {\n\t messages[\"mvc\" + name] = createMessage(name);\n\t }\n\t return messages;\n\t }\n\n\t function generateRules() {\n\t var name,\n\t rules = {};\n\n\t for (name in validationRules) {\n\t rules[\"mvc\" + name] = createRule(name);\n\t }\n\t return rules;\n\t }\n\n\t function extractParams(input, ruleName) {\n\t var params = {},\n\t index,\n\t data = input.data(),\n\t length = ruleName.length,\n\t rule,\n\t key,\n\t start;\n\n\t for (key in data) {\n\t rule = key.toLowerCase();\n\t index = rule.indexOf(ruleName);\n\t if (index > -1) {\n\t start = rule === \"valserver\" ? index : index + length;\n\t rule = rule.substring(start, key.length);\n\n\t if (rule) {\n\t params[rule] = data[key];\n\t }\n\t }\n\t }\n\t return params;\n\t }\n\n\t function rulesFromData(metadata) {\n\t var idx,\n\t length,\n\t fields = metadata.Fields || [],\n\t rules = {};\n\n\t for (idx = 0, length = fields.length; idx < length; idx++) {\n\t $.extend(true, rules, rulesForField(fields[idx]));\n\t }\n\t return rules;\n\t }\n\n\t function rulesForField(field) {\n\t var rules = {},\n\t messages = {},\n\t fieldName = field.FieldName,\n\t fieldRules = field.ValidationRules,\n\t validationType,\n\t validationParams,\n\t idx,\n\t length;\n\n\t for (idx = 0, length = fieldRules.length; idx < length; idx++) {\n\t validationType = fieldRules[idx].ValidationType;\n\t validationParams = fieldRules[idx].ValidationParameters;\n\n\t rules[fieldName + validationType] = createMetaRule(fieldName, validationType, validationParams);\n\n\t messages[fieldName + validationType] = createMetaMessage(fieldRules[idx].ErrorMessage);\n\t }\n\t return { rules: rules, messages: messages };\n\t }\n\n\t function createMessage(rule) {\n\t return function (input) {\n\t return input.attr(\"data-val-\" + rule);\n\t };\n\t }\n\n\t function createRule(ruleName) {\n\t return function (input) {\n\t if (input.filter(\"[data-val-\" + ruleName + \"]\").length) {\n\t return validationRules[ruleName](input, extractParams(input, ruleName));\n\t }\n\t return true;\n\t };\n\t }\n\n\t function createMetaMessage(message) {\n\t return function() { return message; };\n\t }\n\n\t function createMetaRule(fieldName, type, params) {\n\t return function (input) {\n\t if (input.filter(\"[name=\" + fieldName + \"]\").length) {\n\t return validationRules[type](input, params);\n\t }\n\t return true;\n\t };\n\t }\n\n\t function patternMatcher(value, pattern) {\n\t if (typeof pattern === \"string\") {\n\t pattern = new RegExp('^(?:' + pattern + ')$');\n\t }\n\t return pattern.test(value);\n\t }\n\n\t var validationRules = {\n\t required: function (input) {\n\t var value = input.val(),\n\t checkbox = input.filter(\"[type=checkbox]\"),\n\t name;\n\n\t if (checkbox.length) {\n\t name = checkbox[0].name.replace(nameSpecialCharRegExp, \"\\\\$1\");\n\t var hiddenSelector = \"input:hidden[name='\" + name + \"']\";\n\n\t if (checkbox.closest(SWITCHSELECTOR).length) {\n\t checkbox = checkbox.closest(SWITCHSELECTOR);\n\t }\n\n\t var hidden = checkbox.next(hiddenSelector);\n\n\t if (!hidden.length) {\n\t hidden = checkbox.next(\"label.k-checkbox-label\").next(hiddenSelector);\n\t }\n\n\t if (hidden.length) {\n\t value = hidden.val();\n\t } else {\n\t value = input.prop(\"checked\") === true;\n\t }\n\t }\n\n\t return !(value === \"\" || !value || value.length === 0);\n\t },\n\t number: function (input) {\n\t /* jshint eqnull:true */\n\t return input.val() === \"\" || input.val() == null || kendo.parseFloat(input.val()) !== null;\n\t },\n\t regex: function (input, params) {\n\t if (input.val() !== \"\") {\n\t return patternMatcher(input.val(), params.pattern);\n\t }\n\t return true;\n\t },\n\t range: function(input, params) {\n\t if (input.val() !== \"\") {\n\t return this.min(input, params) && this.max(input, params);\n\t }\n\t return true;\n\t },\n\t min: function(input, params) {\n\t var min = parseFloat(params.min) || 0,\n\t val = kendo.parseFloat(input.val());\n\n\t return min <= val;\n\t },\n\t max: function(input, params) {\n\t var max = parseFloat(params.max) || 0,\n\t val = kendo.parseFloat(input.val());\n\n\t return val <= max;\n\t },\n\t date: function(input) {\n\t return input.val() === \"\" || kendo.parseDate(input.val()) !== null;\n\t },\n\t length: function(input, params) {\n\t if (input.val() !== \"\") {\n\t var len = kendo.trim(input.val()).length;\n\t return (!params.min || len >= (params.min || 0)) && (!params.max || len <= (params.max || 0));\n\t }\n\t return true;\n\t },\n\t server: function(input, params) {\n\t if (params.server) {\n\t return false;\n\t }\n\n\t return true;\n\t }\n\t };\n\n\t $.extend(true, kendo.ui.validator, {\n\t rules: generateRules(),\n\t messages: generateMessages(),\n\t messageLocators: {\n\t mvcLocator: {\n\t locate: function (element, fieldName) {\n\t fieldName = fieldName.replace(nameSpecialCharRegExp, \"\\\\$1\");\n\t return element.find(\".field-validation-valid[data-valmsg-for='\" + fieldName + \"'], .field-validation-error[data-valmsg-for='\" + fieldName + \"']\");\n\t },\n\t decorate: function (message, fieldName) {\n\t message.addClass(\"field-validation-error\").attr(\"data-valmsg-for\", fieldName || \"\");\n\t }\n\t },\n\t mvcMetadataLocator: {\n\t locate: function (element, fieldName) {\n\t fieldName = fieldName.replace(nameSpecialCharRegExp, \"\\\\$1\");\n\t return element.find(\"#\" + fieldName + \"_validationMessage.field-validation-valid\");\n\t },\n\t decorate: function (message, fieldName) {\n\t message.addClass(\"field-validation-error\").attr(\"id\", fieldName + \"_validationMessage\");\n\t }\n\t }\n\t },\n\t ruleResolvers: {\n\t mvcMetaDataResolver: {\n\t resolve: function (element) {\n\t var metadata = window.mvcClientValidationMetadata || [];\n\n\t if (metadata.length) {\n\t element = $(element);\n\t for (var idx = 0; idx < metadata.length; idx++) {\n\t if (metadata[idx].FormId == element.attr(\"id\")) {\n\t return rulesFromData(metadata[idx]);\n\t }\n\t }\n\t }\n\t return {};\n\t }\n\t }\n\t },\n\t validateOnInit: function(element) {\n\t return !!element.find(\"input[data-val-server]\").length;\n\t },\n\t allowSubmit: function(element, errors) {\n\t return !!errors && errors.length === element.find(\"input[data-val-server]\").length;\n\t }\n\t });\n\t})(window.kendo.jQuery);\n\n\t}, __webpack_require__(3));\n\n\n/***/ }),\n\n/***/ 18:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"./kendo.imagebrowser.aspnetmvc\");\n\n/***/ })\n\n/******/ });","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ 0:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tmodule.exports = __webpack_require__(855);\n\n\n/***/ }),\n\n/***/ 3:\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n\n/***/ 855:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n\t __webpack_require__(856),\n\t __webpack_require__(857),\n\t __webpack_require__(858),\n\t __webpack_require__(859),\n\t __webpack_require__(860),\n\t __webpack_require__(861)\n\t ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t})(function(){\n\n\t(function ($, undefined) {\n\n\t var NS = \".kendoChart\";\n\t var kendo = window.kendo;\n\t var Class = kendo.Class;\n\t var outerWidth = kendo._outerWidth;\n\t var outerHeight = kendo._outerHeight;\n\t var dataviz = kendo.dataviz;\n\t var constants = dataviz.constants;\n\t var KendoChart = dataviz.Chart;\n\t var SeriesBinder = dataviz.SeriesBinder;\n\t var Widget = kendo.ui.Widget;\n\t var DataSource = kendo.data.DataSource;\n\t var deepExtend = kendo.deepExtend;\n\t var defined = dataviz.defined;\n\t var getField = dataviz.getField;\n\t var InstanceObserver = dataviz.InstanceObserver;\n\t var inArray = dataviz.inArray;\n\t var services = dataviz.services;\n\t var proxy = $.proxy;\n\t var isArray = $.isArray;\n\t var extend = $.extend;\n\t var template = kendo.template;\n\n\t var MOUSELEAVE_NS = \"mouseleave\" + NS;\n\t var AXIS_LABEL_CLICK = constants.AXIS_LABEL_CLICK;\n\t var LEGEND_ITEM_CLICK = constants.LEGEND_ITEM_CLICK;\n\t var LEGEND_ITEM_HOVER = constants.LEGEND_ITEM_HOVER;\n\t var LEGEND_ITEM_LEAVE = constants.LEGEND_ITEM_LEAVE;\n\t var SERIES_CLICK = constants.SERIES_CLICK;\n\t var SERIES_HOVER = constants.SERIES_HOVER;\n\t var SERIES_OVER = constants.SERIES_OVER;\n\t var SERIES_LEAVE = constants.SERIES_LEAVE;\n\t var PANE_RENDER = constants.PANE_RENDER;\n\t var PLOT_AREA_CLICK = constants.PLOT_AREA_CLICK;\n\t var PLOT_AREA_HOVER = constants.PLOT_AREA_HOVER;\n\t var PLOT_AREA_LEAVE = constants.PLOT_AREA_LEAVE;\n\t var DRAG = constants.DRAG;\n\t var DRAG_END = constants.DRAG_END;\n\t var DRAG_START = constants.DRAG_START;\n\t var ZOOM_START = constants.ZOOM_START;\n\t var ZOOM = constants.ZOOM;\n\t var ZOOM_END = constants.ZOOM_END;\n\t var SELECT_START = constants.SELECT_START;\n\t var SELECT = constants.SELECT;\n\t var SELECT_END = constants.SELECT_END;\n\t var RENDER = constants.RENDER;\n\t var NOTE_CLICK = constants.NOTE_CLICK;\n\t var NOTE_HOVER = constants.NOTE_HOVER;\n\t var NOTE_LEAVE = constants.NOTE_LEAVE;\n\n\t var CHANGE = \"change\";\n\t var DATABOUND = \"dataBound\";\n\t var LEAVE = \"leave\";\n\n\t var VALUE = constants.VALUE;\n\t var PIE = constants.PIE;\n\t var DONUT = constants.DONUT;\n\t var FUNNEL = constants.FUNNEL;\n\n\t var Observable = kendo.Observable;\n\t var TOOLTIP_ANIMATION_DURATION = 150;\n\t var TOOLTIP_SHOW_DELAY = 100;\n\t var TOOLTIP_INVERSE = \"k-chart-tooltip-inverse\";\n\t var SHARED_TOOLTIP_CLASS = \"k-chart-shared-tooltip\";\n\t var RTL = \"rtl\";\n\n\t services.DomEventsBuilder.register({\n\t create: function(element, events) {\n\t return new kendo.UserEvents(element, deepExtend({\n\t global: true,\n\t multiTouch: true,\n\t fastTap: true\n\t }, events));\n\t }\n\t });\n\n\t var ChartInstanceObserver = InstanceObserver.extend({\n\t handlerMap: {\n\t showTooltip: '_showTooltip',\n\t hideTooltip: '_hideTooltip',\n\t legendItemClick: '_onLegendItemClick',\n\t render: '_onRender',\n\t init: '_onInit'\n\t }\n\t });\n\n\t var Chart = Widget.extend({\n\t init: function(element, userOptions) {\n\t var dataSource;\n\n\t kendo.destroy(element);\n\n\t Widget.fn.init.call(this, element);\n\n\t if (userOptions) {\n\t dataSource = userOptions.dataSource;\n\t delete userOptions.dataSource;\n\t }\n\n\t this.options = deepExtend({}, this.options, userOptions);\n\n\t this.wrapper = this.element;\n\t this._attachEvents();\n\n\t if (userOptions) {\n\t userOptions.dataSource = dataSource;\n\t }\n\n\t this._seriesVisibility = new SeriesVisibilityState();\n\n\t this.bind(this.events, this.options);\n\t this._initDataSource(userOptions);\n\n\t kendo.notify(this, dataviz.ui);\n\t },\n\n\t events:[\n\t DATABOUND,\n\t SERIES_CLICK,\n\t SERIES_HOVER,\n\t SERIES_OVER,\n\t SERIES_LEAVE,\n\t AXIS_LABEL_CLICK,\n\t LEGEND_ITEM_CLICK,\n\t LEGEND_ITEM_HOVER,\n\t LEGEND_ITEM_LEAVE,\n\t PANE_RENDER,\n\t PLOT_AREA_CLICK,\n\t PLOT_AREA_HOVER,\n\t PLOT_AREA_LEAVE,\n\t DRAG_START,\n\t DRAG,\n\t DRAG_END,\n\t ZOOM_START,\n\t ZOOM,\n\t ZOOM_END,\n\t SELECT_START,\n\t SELECT,\n\t SELECT_END,\n\t NOTE_CLICK,\n\t NOTE_HOVER,\n\t NOTE_LEAVE,\n\t RENDER\n\t ],\n\n\t options: {\n\t name: \"Chart\",\n\t renderAs: \"\",\n\t theme: \"default\",\n\t axisDefaults: {},\n\t chartArea: {},\n\t legend: {},\n\t categoryAxis: {},\n\t autoBind: true,\n\t seriesDefaults: {},\n\t series: [],\n\t seriesColors: null,\n\t tooltip: {},\n\t transitions: true,\n\t valueAxis: {},\n\t plotArea: {},\n\t title: {},\n\t xAxis: {},\n\t yAxis: {},\n\t panes: [{}],\n\t pannable: false,\n\t zoomable: false\n\t },\n\n\t items: function() {\n\t return $();\n\t },\n\n\t refresh: function() {\n\t var chart = this;\n\t var instance = chart._instance;\n\t instance.applyDefaults(chart.options);\n\t instance.applySeriesColors();\n\n\t chart._bindSeries();\n\t chart._bindCategories();\n\n\t chart.trigger(DATABOUND);\n\t chart._redraw();\n\t },\n\n\t getSize: function() {\n\t return kendo.dimensions(this.element);\n\t },\n\n\t redraw: function(paneName) {\n\t this._size = null;\n\t this._instance.redraw(paneName);\n\t },\n\n\t setOptions: function(options) {\n\t var chart = this,\n\t dataSource = options.dataSource;\n\n\t delete options.dataSource;\n\n\t Widget.fn._setEvents.call(chart, options);\n\n\t this._instance.applyOptions(options, this._getThemeOptions(options));\n\t this.options = this._instance.options;\n\t this._tooltip.setOptions(this.options.tooltip);\n\t this._seriesVisibility.setOptions(this.options);\n\t this._sourceSeries = null;\n\n\t if (dataSource) {\n\t chart.setDataSource(dataSource);\n\t }\n\n\t if (chart._hasDataSource) {\n\t chart._onDataChanged();\n\t } else {\n\t chart._bindCategories();\n\t chart.redraw();\n\t }\n\n\t chart._instance.updateMouseMoveHandler();\n\n\t },\n\n\t setDataSource: function(dataSource) {\n\t var chart = this;\n\n\t chart.dataSource.unbind(CHANGE, chart._dataChangeHandler);\n\t chart.dataSource = dataSource = DataSource.create(dataSource);\n\t chart._hasDataSource = true;\n\t chart._hasData = false;\n\n\t dataSource.bind(CHANGE, chart._dataChangeHandler);\n\n\t if (chart.options.autoBind) {\n\t dataSource.fetch();\n\t }\n\t },\n\n\t destroy: function() {\n\t var chart = this,\n\t dataSource = chart.dataSource;\n\n\t chart.element.off(NS);\n\n\t if (dataSource) {\n\t dataSource.unbind(CHANGE, chart._dataChangeHandler);\n\t }\n\n\t if (chart._instance) {\n\t chart._instance.destroy();\n\t delete this._instance;\n\t }\n\n\t if (this._tooltip) {\n\t this._tooltip.destroy();\n\t delete this._tooltip;\n\t }\n\n\t this._destroyCrosshairTooltips();\n\n\t Widget.fn.destroy.call(chart);\n\t },\n\n\t findPaneByName: function(name) {\n\t var panes = this._plotArea.panes;\n\n\t for (var idx = 0; idx < panes.length; idx++) {\n\t if (panes[idx].options.name === name) {\n\t return new ChartPane(this, panes[idx]);\n\t }\n\t }\n\t },\n\n\t findPaneByIndex: function(idx) {\n\t var panes = this._plotArea.panes;\n\t if (panes[idx]) {\n\t return new ChartPane(this, panes[idx]);\n\t }\n\t },\n\n\t findSeries: function(callback) {\n\t var plotArea = this._plotArea;\n\t var series = plotArea.srcSeries || plotArea.series;\n\t for (var idx = 0; idx < series.length; idx++) {\n\t if (callback(series[idx])) {\n\t return new ChartSeries(this, series[idx]);\n\t }\n\t }\n\t },\n\n\t findSeriesByName: function(name) {\n\t return this._createSeries({ name: name });\n\t },\n\n\t findSeriesByIndex: function(index) {\n\t return this._createSeries({ index: index });\n\t },\n\n\t exportVisual: function(options) {\n\t var instance = this._instance;\n\t if (!instance) {\n\t return;\n\t }\n\n\t var visual;\n\n\t //TO DO: support for setting any options. already available in kendo-charts\n\t if (options && (options.width || options.height)) {\n\t var chartArea = instance.options.chartArea;\n\t var originalChartArea = instance._originalOptions.chartArea;\n\n\t deepExtend(chartArea, options);\n\n\t var model = instance._getModel();\n\n\t chartArea.width = originalChartArea.width;\n\t chartArea.height = originalChartArea.height;\n\n\t model.renderVisual();\n\n\t triggerPaneRender(model._plotArea.panes);\n\n\t visual = model.visual;\n\t } else {\n\t visual = instance.exportVisual();\n\t }\n\n\t return visual;\n\t },\n\n\t _createSeries: function(options) {\n\t var seriesOptions = this._seriesOptions(options);\n\t if (seriesOptions) {\n\t return new ChartSeries(this, seriesOptions);\n\t }\n\t },\n\n\t _seriesOptions: function(options) {\n\t var plotArea = this._plotArea;\n\t var series = plotArea.srcSeries || plotArea.series;\n\t var seriesOptions;\n\n\t if (defined(options.index)) {\n\t seriesOptions = series[options.index];\n\t } else if (defined(options.name)) {\n\t for (var idx = 0; idx < series.length; idx++) {\n\t if (series[idx].name === options.name) {\n\t seriesOptions = series[idx];\n\t break;\n\t }\n\t }\n\t }\n\n\t return seriesOptions;\n\t },\n\n\t _attachEvents: function() {\n\t this.element.on(MOUSELEAVE_NS, proxy(this._mouseleave, this));\n\t },\n\n\t _mouseleave: function(e) {\n\t var instance = this._instance;\n\t var tooltip = this._tooltip;\n\t var target = e.relatedTarget;\n\n\t if (!(target && $(target).closest(tooltip.element).length) && instance && !instance.handlingTap) {\n\t instance.hideElements();\n\t }\n\t },\n\n\t _getThemeOptions: function(userOptions) {\n\t var themeName = (userOptions || {}).theme;\n\n\t if (themeName && dataviz.SASS_THEMES.indexOf(themeName.toLowerCase()) !== -1) {\n\t return dataviz.autoTheme().chart;\n\t }\n\n\t if (defined(themeName)) {\n\t var themes = dataviz.ui.themes || {};\n\t var theme = themes[themeName] || themes[themeName.toLowerCase()] || {};\n\t return theme.chart || {};\n\t }\n\t },\n\n\t _initChart: function() {\n\t this._createChart(this.options, this._getThemeOptions(this.options));\n\t this.options = this._instance.options;\n\t this._seriesVisibility.setOptions(this.options);\n\t },\n\n\t _createChart: function(options, themeOptions) {\n\t this._instance = new KendoChart(this.element[0], options, themeOptions, {\n\t observer: new ChartInstanceObserver(this),\n\t sender: this,\n\t rtl: this._isRtl()\n\t });\n\t },\n\n\t _onInit: function(e) {\n\t this._instance = e.sender;\n\t },\n\n\t _initDataSource: function(userOptions) {\n\t var chart = this,\n\t dataSource = (userOptions || {}).dataSource;\n\n\t chart._dataChangeHandler = proxy(chart._onDataChanged, chart);\n\n\t chart.dataSource = DataSource\n\t .create(dataSource)\n\t .bind(\"change\", chart._dataChangeHandler);\n\n\t chart._bindCategories();\n\n\t if (dataSource) {\n\t chart._hasDataSource = true;\n\t }\n\n\t this._initChart();\n\t this._initTooltip();\n\n\t if (dataSource) {\n\t if (chart.options.autoBind) {\n\t chart.dataSource.fetch();\n\t }\n\t }\n\t },\n\n\t _destroyCrosshairTooltips: function() {\n\t var tooltips = this._crosshairTooltips;\n\t if (tooltips) {\n\t for (var key in tooltips) {\n\t tooltips[key].destroy();\n\t }\n\t }\n\t this._crosshairTooltips = {};\n\t },\n\n\t _getCrosshairTooltip: function(name, index) {\n\t var tooltips = this._crosshairTooltips = this._crosshairTooltips || {};\n\t var key = name + index;\n\t var tooltip = tooltips[key];\n\t if (!tooltip) {\n\t tooltip = tooltips[key] = new CrosshairTooltip(this.element);\n\t }\n\t return tooltip;\n\t },\n\n\t _showTooltip: function(e) {\n\t if (e.crosshair) {\n\t var tooltip = this._getCrosshairTooltip(e.axisName, e.axisIndex);\n\t tooltip.show(e);\n\t } else if (this._tooltip) {\n\t this._tooltip.show(e);\n\t }\n\t },\n\n\t _hideTooltip: function(e) {\n\t if (e.crosshair) {\n\t var tooltip = this._getCrosshairTooltip(e.axisName, e.axisIndex);\n\t tooltip.hide();\n\t } else if (this._tooltip) {\n\t this._tooltip.hide(e);\n\t }\n\t },\n\n\t _onRender: function(e) {\n\t this._destroyCrosshairTooltips();\n\t this._copyMembers(e.sender);\n\t if (!this._hasDataSource || this._hasData || !this.options.autoBind) {\n\t this.trigger(RENDER);\n\t }\n\t },\n\n\t _copyMembers: function(instance) {\n\t this.options = instance.options;\n\t this._originalOptions = instance._originalOptions;\n\t this.surface = instance.surface;\n\t this._plotArea = instance._plotArea;\n\t this._model = instance._model;\n\t this._highlight = instance._highlight;\n\t this._selections = instance._selections;\n\t this._pannable = instance._pannable;\n\t this._zoomSelection = instance._zoomSelection;\n\t this._mousewheelZoom = instance._mousewheelZoom;\n\t },\n\n\t requiresHandlers: function(names) {\n\t var events = this._events;\n\t for (var idx = 0; idx < names.length; idx++) {\n\t if (defined(events[names[idx]])) {\n\t return true;\n\t }\n\t }\n\t },\n\n\t _initTooltip: function() {\n\t this._tooltip = this._createTooltip();\n\n\t this._tooltip.bind(LEAVE, proxy(this._tooltipleave, this));\n\t },\n\n\t _onLegendItemClick: function(e) {\n\t if (!this.trigger(LEGEND_ITEM_CLICK, e)) {\n\t this._legendItemClick(e.seriesIndex, e.pointIndex);\n\t }\n\t },\n\n\t _legendItemClick: function(seriesIndex, pointIndex) {\n\t var chart = this._instance,\n\t plotArea = chart._plotArea,\n\t currentSeries = (plotArea.srcSeries || plotArea.series)[seriesIndex];\n\n\t if ($.inArray(currentSeries.type, [PIE, DONUT, FUNNEL]) >= 0) {\n\t var point = currentSeries.data[pointIndex];\n\t if (point && defined(point.visible)) {\n\t point.visible = !point.visible;\n\t } else {\n\t var pointVisibility = currentSeries.pointVisibility = currentSeries.pointVisibility || {};\n\t var visible = pointVisibility[pointIndex];\n\t pointVisibility[pointIndex] = defined(visible) ? !visible : false;\n\t }\n\t } else {\n\t currentSeries.visible = !currentSeries.visible;\n\t this._seriesVisibility.save(currentSeries);\n\t }\n\n\t chart._noTransitionsRedraw();\n\t },\n\n\t _createTooltip: function() {\n\t return new Tooltip(this.element, extend({}, this.options.tooltip, {\n\t rtl: this._isRtl()\n\t }));\n\t },\n\n\t _tooltipleave: function() {\n\t if (this._instance) {\n\t this._instance.hideElements();\n\t }\n\t },\n\n\t _bindData: function(e) {\n\t var chart = this,\n\t options = chart.options,\n\t series = chart._sourceSeries || options.series,\n\t seriesIx,\n\t seriesLength = series.length,\n\t data = chart.dataSource.view(),\n\t grouped = (chart.dataSource.group() || []).length > 0,\n\t processedSeries = [],\n\t seriesVisibility = this._seriesVisibility,\n\t currentSeries,\n\t groupedSeries;\n\n\t seriesVisibility.read();\n\n\t for (seriesIx = 0; seriesIx < seriesLength; seriesIx++) {\n\t currentSeries = series[seriesIx];\n\n\t if (chart._isBindable(currentSeries) && grouped) {\n\t groupedSeries = groupSeries(currentSeries, data);\n\t processedSeries = processedSeries.concat(groupedSeries);\n\n\t seriesVisibility.applyByGroup(groupedSeries, e);\n\t } else {\n\t currentSeries = extend({}, currentSeries);\n\t processedSeries.push(currentSeries);\n\n\t seriesVisibility.applyByIndex(currentSeries, e);\n\t }\n\t }\n\n\t chart._sourceSeries = series;\n\t options.series = processedSeries;\n\t this._instance.applySeriesColors();\n\n\t chart._bindSeries();\n\t chart._bindCategories();\n\n\t this._hasData = true;\n\t },\n\n\t _onDataChanged: function(e) {\n\t this._bindData(e);\n\n\t this.trigger(DATABOUND);\n\t if (this._instance && this._instance.fontLoaded) {\n\t this._redraw();\n\t }\n\t },\n\n\t _bindSeries: function() {\n\t var chart = this,\n\t data = chart.dataSource.view(),\n\t series = chart.options.series,\n\t seriesIx,\n\t seriesLength = series.length,\n\t currentSeries,\n\t groupIx,\n\t seriesData;\n\n\t for (seriesIx = 0; seriesIx < seriesLength; seriesIx++) {\n\t currentSeries = series[seriesIx];\n\n\t if (chart._isBindable(currentSeries)) {\n\t groupIx = currentSeries._groupIx;\n\t seriesData = defined(groupIx) ? (data[groupIx] || {}).items : data;\n\n\t if (currentSeries.autoBind !== false) {\n\t currentSeries.data = seriesData;\n\t }\n\t }\n\t }\n\t },\n\n\t _bindCategories: function() {\n\t var chart = this,\n\t data = chart.dataSource.view() || [],\n\t grouped = (chart.dataSource.group() || []).length > 0,\n\t categoriesData = data,\n\t options = chart.options,\n\t definitions = [].concat(options.categoryAxis),\n\t axisIx,\n\t axis;\n\n\t if (grouped) {\n\t if (data.length) {\n\t categoriesData = data[0].items;\n\t }\n\t }\n\n\t for (axisIx = 0; axisIx < definitions.length; axisIx++) {\n\t axis = definitions[axisIx];\n\t if (axis.autoBind !== false) {\n\t chart._bindCategoryAxis(axis, categoriesData, axisIx);\n\t }\n\t }\n\t },\n\n\t _bindCategoryAxis: function(axis, data, axisIx) {\n\t var count = (data || []).length,\n\t categoryIx,\n\t category,\n\t row;\n\n\t if (axis.field) {\n\t axis.categories = [];\n\t for (categoryIx = 0; categoryIx < count; categoryIx++) {\n\t row = data[categoryIx];\n\n\t category = getField(axis.field, row);\n\t if (categoryIx === 0) {\n\t axis.categories = [category];\n\t axis.dataItems = [row];\n\t } else {\n\t axis.categories.push(category);\n\t axis.dataItems.push(row);\n\t }\n\t }\n\t } else if (this._instance) {\n\t this._instance.bindCategoryAxisFromSeries(axis, axisIx);\n\t }\n\t },\n\n\t _isBindable: function(series) {\n\t var valueFields = SeriesBinder.current.valueFields(series),\n\t result = true,\n\t field, i;\n\n\t for (i = 0; i < valueFields.length; i++) {\n\t field = valueFields[i];\n\t if (field === VALUE) {\n\t field = \"field\";\n\t } else {\n\t field = field + \"Field\";\n\t }\n\n\t if (!defined(series[field])) {\n\t result = false;\n\t break;\n\t }\n\t }\n\n\t return result;\n\t },\n\n\t _isRtl: function() {\n\t return kendo.support.isRtl(this.element) && this.element.css(\"direction\") === RTL;\n\t }\n\t });\n\n\t var proxyMembers = [\"getAxis\", \"findAxisByName\", \"plotArea\", \"toggleHighlight\", \"showTooltip\",\n\t \"hideTooltip\", \"_resize\", \"_redraw\", \"_noTransitionsRedraw\", \"_legendItemHover\", \"_eventCoordinates\"];\n\n\t function createProxyMember(name) {\n\t Chart.fn[name] = function() {\n\t var instance = this._instance;\n\t if (instance) {\n\t return instance[name].apply(instance, arguments);\n\t }\n\t };\n\t }\n\n\t for (var idx = 0; idx < proxyMembers.length; idx++) {\n\t createProxyMember(proxyMembers[idx]);\n\t }\n\n\t function groupSeries(series, data) {\n\t var result = [],\n\t nameTemplate,\n\t legacyTemplate = series.groupNameTemplate,\n\t groupIx,\n\t dataLength = data.length,\n\t seriesClone;\n\n\t if (dataLength === 0) {\n\t seriesClone = deepExtend({}, series);\n\t seriesClone.visibleInLegend = false;\n\t return [seriesClone];\n\t }\n\n\t if (defined(legacyTemplate)) {\n\t kendo.logToConsole(\n\t \"'groupNameTemplate' is obsolete and will be removed in future versions. \" +\n\t \"Specify the group name template as 'series.name'\"\n\t );\n\n\t if (legacyTemplate) {\n\t nameTemplate = template(legacyTemplate);\n\t }\n\t } else {\n\t nameTemplate = template(series.name || \"\");\n\t if (nameTemplate._slotCount === 0) {\n\t nameTemplate = template(defined(series.name) ?\n\t \"#= group.value #: #= series.name #\" :\n\t \"#= group.value #\"\n\t );\n\t }\n\t }\n\n\t for (groupIx = 0; groupIx < dataLength; groupIx++) {\n\t seriesClone = deepExtend({}, series);\n\n\t if (!kendo.isFunction(seriesClone.color)) {\n\t seriesClone.color = undefined;\n\t }\n\n\t seriesClone._groupIx = groupIx;\n\t seriesClone._groupValue = data[groupIx].value;\n\t result.push(seriesClone);\n\n\t if (nameTemplate) {\n\t seriesClone.name = nameTemplate({\n\t series: seriesClone, group: data[groupIx]\n\t });\n\t }\n\t }\n\n\t return result;\n\t }\n\n\t dataviz.ExportMixin.extend(Chart.fn);\n\n\t if (kendo.PDFMixin) {\n\t kendo.PDFMixin.extend(Chart.fn);\n\t }\n\n\t dataviz.ui.plugin(Chart);\n\n\t var SeriesVisibilityState = Class.extend({\n\t init: function() {\n\t this.groups = {};\n\t this.index = {};\n\t this.options = {};\n\t },\n\n\t applyByGroup: function(series, e) {\n\t if ((e && e.action) || this.options.persistSeriesVisibility) {\n\t for (var idx = 0; idx < series.length; idx++) {\n\t if (this.groups[series[idx]._groupValue] === false) {\n\t series[idx].visible = false;\n\t }\n\t }\n\t } else {\n\t this.groups = {};\n\t }\n\t },\n\n\t applyByIndex: function(series, e) {\n\t if ((e && e.action) || this.options.persistSeriesVisibility) {\n\t if (this.index[series.index] === false) {\n\t series.visible = false;\n\t }\n\t } else {\n\t this.index = {};\n\t }\n\t },\n\n\t save: function(series) {\n\t if (!series) {\n\t return;\n\t }\n\n\t if (this.options.persistSeriesVisibility) {\n\t this.options.series[series.index].visible = series.visible;\n\t } else {\n\t this.saveState(series);\n\t }\n\t },\n\n\t setOptions: function(options) {\n\t this.options = options;\n\t this.groups = {};\n\t this.index = {};\n\t },\n\n\t read: function() {\n\t var options = this.options;\n\t if (options.persistSeriesVisibility) {\n\t var series = options.series;\n\t for (var idx = 0; idx < series.length; idx++) {\n\t this.saveState(series[idx]);\n\t }\n\t }\n\t },\n\n\t saveState: function(series) {\n\t if (defined(series._groupValue)) {\n\t this.groups[series._groupValue] = series.visible;\n\t } else {\n\t this.index[series.index] = series.visible;\n\t }\n\t }\n\t });\n\n\t var geom = kendo.geometry;\n\n\t function normalizeStyle(style) {\n\t for (var field in style) {\n\t if (style[field] === undefined) {\n\t style[field] = '';\n\t }\n\t }\n\n\t return style;\n\t }\n\n\t var Tooltip = Observable.extend({\n\t init: function(chartElement, options) {\n\t var tooltip = this;\n\n\t Observable.fn.init.call(tooltip);\n\n\t this.setOptions(options);\n\n\t tooltip.chartElement = chartElement;\n\n\t tooltip.template = Tooltip.template;\n\t if (!tooltip.template) {\n\t tooltip.template = Tooltip.template = kendo.template(\n\t \"
\" +\n\t \"
\", { useWithBlock: false, paramName: \"d\" });\n\t }\n\n\t tooltip.element = $(tooltip.template(tooltip.options));\n\n\t tooltip.move = proxy(tooltip.move, tooltip);\n\t tooltip._mouseleave = proxy(tooltip._mouseleave, tooltip);\n\n\t var mobileScrollerSelector = kendo.format(\"[{0}='content'],[{0}='scroller']\", kendo.attr(\"role\"));\n\t tooltip._mobileScroller = chartElement.closest(mobileScrollerSelector).data(\"kendoMobileScroller\");\n\t },\n\n\t destroy: function() {\n\t this._clearShowTimeout();\n\n\t if (this.element) {\n\t this.element.off(MOUSELEAVE_NS).remove();\n\t this.element = null;\n\t }\n\t },\n\n\t setOptions: function(options) {\n\t this.options = deepExtend({}, this.options, options);\n\t },\n\n\t options: {\n\t opacity: 1,\n\t animation: {\n\t duration: TOOLTIP_ANIMATION_DURATION\n\t },\n\t sharedTemplate:\n\t \"\" +\n\t \"#= categoryText # | \" +\n\t \"# for(var i = 0; i < points.length; i++) { #\" +\n\t \"# var point = points[i]; #\" +\n\t \"\" +\n\t \"# if(colorMarker) { # \" +\n\t \" | \" +\n\t \"# } #\" +\n\t \"# if(nameColumn) { # \" +\n\t \" #if (point.series.name) {# #: point.series.name #: #} else {# #}# | \" +\n\t \"# } #\" +\n\t \"#= content(point) # | \" +\n\t \"
\" +\n\t \"# } #\" +\n\t \"
\",\n\t categoryFormat: \"{0:d}\"\n\t },\n\n\t move: function() {\n\t var tooltip = this,\n\t options = tooltip.options,\n\t element = tooltip.element,\n\t offset;\n\n\t if (!tooltip.anchor || !tooltip.element) {\n\t return;\n\t }\n\n\t offset = tooltip._offset();\n\t if (!tooltip.visible) {\n\t element.css({ top: offset.top, left: offset.left });\n\t }\n\n\t tooltip.visible = true;\n\t tooltip._ensureElement(document.body);\n\t element\n\t .stop(true, true)\n\t .show()\n\t .animate({\n\t left: offset.left,\n\t top: offset.top\n\t }, options.animation.duration);\n\t },\n\n\t _clearShowTimeout: function() {\n\t if (this.showTimeout) {\n\t clearTimeout(this.showTimeout);\n\t this.showTimeout = null;\n\t }\n\t },\n\n\t getAnchor: function(size) {\n\t var anchor = this.anchor;\n\t var point = anchor.point;\n\t var align = anchor.align;\n\t var x = point.left;\n\t var y = point.top;\n\t if (align.horizontal === \"center\") {\n\t x -= size.width / 2;\n\t } else if (align.horizontal === \"right\") {\n\t x -= size.width;\n\t }\n\n\t if (align.vertical === \"center\") {\n\t y -= size.height / 2;\n\t } else if (align.vertical === \"bottom\") {\n\t y -= size.height;\n\t }\n\n\t return {\n\t x: x,\n\t y: y\n\t };\n\t },\n\n\t _offset: function() {\n\t var tooltip = this,\n\t size = tooltip._measure(),\n\t anchor = tooltip.getAnchor(size),\n\t top = anchor.y,\n\t left = anchor.x,\n\t zoomLevel = kendo.support.zoomLevel(),\n\t viewport = $(window),\n\t scrollTop = window.pageYOffset || document.documentElement.scrollTop || 0,\n\t scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || 0,\n\t movable = (this._mobileScroller || {}).movable;\n\n\t if (!movable || movable.scale === 1) {\n\t top += tooltip._fit(top - scrollTop, size.height, outerHeight(viewport) / zoomLevel);\n\t left += tooltip._fit(left - scrollLeft, size.width, outerWidth(viewport) / zoomLevel);\n\t } else {\n\t var transform = geom.transform().scale(movable.scale, movable.scale, [movable.x, movable.y]);\n\t var point = new geom.Point(left, top).transform(transform);\n\t left = point.x;\n\t top = point.y;\n\t }\n\n\t return {\n\t top: top,\n\t left: left\n\t };\n\t },\n\n\t show: function(e) {\n\t this.anchor = e.anchor;\n\t this.element.css(normalizeStyle(e.style));\n\t this.element.toggleClass(TOOLTIP_INVERSE, !!e.className);\n\t this.element.toggleClass(SHARED_TOOLTIP_CLASS, !!e.shared);\n\n\t var content = e.shared ? this._sharedContent(e) : this._pointContent(e.point);\n\t this.element.html(content);\n\n\t this._clearShowTimeout();\n\t this.showTimeout = setTimeout(this.move, TOOLTIP_SHOW_DELAY);\n\t },\n\n\t hide: function() {\n\t var tooltip = this;\n\n\t clearTimeout(tooltip.showTimeout);\n\t tooltip._hideElement();\n\n\t if (tooltip.visible) {\n\t tooltip.point = null;\n\t tooltip.visible = false;\n\t tooltip.index = null;\n\t }\n\t },\n\n\t _sharedContent: function(e) {\n\t var points = e.points;\n\t var nameColumn = dataviz.grep(points, function(point) {\n\t return defined(point.series.name);\n\t }).length;\n\n\t var colorMarker = e.series.length > 1;\n\t var colspan = 1;\n\t if (nameColumn) {\n\t colspan++;\n\t }\n\t if (colorMarker) {\n\t colspan++;\n\t }\n\n\t var template = kendo.template(this.options.sharedTemplate);\n\t var content = template({\n\t points: points,\n\t category: e.category,\n\t categoryText: e.categoryText,\n\t content: this._pointContent,\n\t colorMarker: colorMarker,\n\t nameColumn: nameColumn,\n\t colspan: colspan\n\t });\n\n\t return content;\n\t },\n\n\t _measure: function() {\n\t this._ensureElement();\n\n\t var size = {\n\t width: outerWidth(this.element),\n\t height: outerHeight(this.element)\n\t };\n\n\t return size;\n\t },\n\n\t _ensureElement: function() {\n\t if (this.element) {\n\t this.element\n\t .appendTo(document.body)\n\t .on(MOUSELEAVE_NS, this._mouseleave);\n\t }\n\t },\n\n\t _mouseleave: function(e) {\n\t var target = e.relatedTarget;\n\t var chart = this.chartElement[0];\n\t if (target && target !== chart && !$.contains(chart, target)) {\n\t this.trigger(LEAVE);\n\t }\n\t },\n\n\t _hideElement: function() {\n\t var tooltip = this;\n\t var element = this.element;\n\t if (element) {\n\t element.fadeOut({\n\t always: function(){\n\t if (!tooltip.visible) {\n\t element.off(MOUSELEAVE_NS).remove();\n\t }\n\t }\n\t });\n\t }\n\t },\n\n\t _pointContent: function(point) {\n\t var tooltip = this,\n\t options = deepExtend({}, tooltip.options, point.options.tooltip),\n\t content, tooltipTemplate;\n\n\t if (defined(point.value)) {\n\t content = point.value.toString();\n\t }\n\n\t if (options.template) {\n\t tooltipTemplate = template(options.template);\n\t content = tooltipTemplate({\n\t value: point.value,\n\t category: point.category,\n\t series: point.series,\n\t dataItem: point.dataItem,\n\t percentage: point.percentage,\n\t runningTotal: point.runningTotal,\n\t total: point.total,\n\t low: point.low,\n\t high: point.high,\n\t xLow: point.xLow,\n\t xHigh: point.xHigh,\n\t yLow: point.yLow,\n\t yHigh: point.yHigh\n\t });\n\t } else if (options.format) {\n\t content = point.formatValue(options.format);\n\t }\n\n\t return content;\n\t },\n\n\t _fit: function(offset, size, viewPortSize) {\n\t var output = 0;\n\n\t if (offset + size > viewPortSize) {\n\t output = viewPortSize - (offset + size);\n\t }\n\n\t if (offset < 0) {\n\t output = -offset;\n\t }\n\n\t return output;\n\t }\n\t });\n\n\t var CrosshairTooltip = Tooltip.extend({\n\t init: function(chartElement, options) {\n\t Tooltip.fn.init.call(this, chartElement, options);\n\t this.element.addClass(\"k-chart-crosshair-tooltip\");\n\t },\n\n\t show: function(e) {\n\t var element = this.element;\n\n\t if (element) {\n\t this.anchor = e.anchor;\n\t this.element.css(e.style);\n\t this.element.html(this.content(e));\n\n\t this.move();\n\t }\n\t },\n\n\t move: function() {\n\t var tooltip = this,\n\t element = tooltip.element,\n\t offset = tooltip._offset();\n\n\t tooltip._ensureElement();\n\t element.css({ top: offset.top, left: offset.left }).show();\n\t },\n\n\t content: function(e) {\n\t var content = e.value,\n\t options = e.crosshair.options.tooltip;\n\n\t if (options.template) {\n\t content = template(options.template)({\n\t value: content\n\t });\n\t }\n\n\t return content;\n\t },\n\n\t hide: function() {\n\t this.element.hide();\n\t }\n\t });\n\n\t var ChartPane = Class.extend({\n\t init: function(chart, pane) {\n\t this._chart = chart;\n\t this._pane = pane;\n\t this.visual = pane.visual;\n\t this.chartsVisual = pane.chartContainer.visual;\n\t this.name = pane.options.name;\n\t },\n\n\t series: function() {\n\t var chart = this._chart;\n\t var seriesByPane = chart._plotArea.groupSeriesByPane();\n\t var series = seriesByPane[this.name || \"default\"];\n\n\t var result = [];\n\t if (series) {\n\t for (var idx = 0; idx < series.length; idx++) {\n\t result.push(new ChartSeries(chart, series[idx]));\n\t }\n\t }\n\n\t return result;\n\t }\n\t });\n\n\t var ChartSeries = Class.extend({\n\t init: function(chart, options) {\n\t this._chart = chart;\n\t this._options = options;\n\t },\n\n\t points: function(filter) {\n\t var points = this._points;\n\t if (!points) {\n\t var series = this._seriesOptions();\n\t var plotArea = this._chart._plotArea;\n\t this._points = points = plotArea.pointsBySeriesIndex(series.index);\n\t }\n\t if (kendo.isFunction(filter)) {\n\t points = this._filterPoints(points, filter);\n\t }\n\n\n\t return points;\n\t },\n\n\t data: function(data) {\n\t var series = this._seriesOptions();\n\t if (data) {\n\t var chart = this._chart;\n\t var plotArea = chart._plotArea;\n\n\t series.data = data;\n\n\t if (series.categoryField) {\n\t var axis = plotArea.seriesCategoryAxis(series);\n\t var options = [].concat(chart.options.categoryAxis);\n\n\t chart._instance.bindCategoryAxisFromSeries(options[axis.axisIndex], axis.axisIndex);\n\t }\n\n\t chart._noTransitionsRedraw();\n\t this._clearFields();\n\t }\n\n\t return series.data;\n\t },\n\n\t findPoint: function(filter) {\n\t var points = this.points();\n\t for (var idx = 0; idx < points.length; idx++) {\n\t if (filter(points[idx])) {\n\t return points[idx];\n\t }\n\t }\n\t },\n\n\t toggleHighlight: function(show, elements) {\n\t if (!elements) {\n\t elements = this.points();\n\t } else if (kendo.isFunction(elements)) {\n\t elements = this.points(elements);\n\t } else {\n\t elements = isArray(elements) ? elements : [elements];\n\t }\n\n\t this._chart._instance.togglePointsHighlight(show, elements);\n\t },\n\n\t toggleVisibility: function(visible, filter) {\n\t var chart = this._chart;\n\t var seriesOptions = this._seriesOptions();\n\t var hasFilter = kendo.isFunction(filter);\n\t if (!hasFilter) {\n\t seriesOptions.visible = visible;\n\t chart._seriesVisibility.save(seriesOptions);\n\t } else {\n\t if (inArray(seriesOptions.type, [PIE, DONUT, FUNNEL])) {\n\t var data = this._filterData(filter);\n\t for (var idx = 0; idx < data.length; idx++) {\n\t data[idx].visible = visible;\n\t }\n\t } else {\n\t seriesOptions.visible = function(data) {\n\t return filter(data.dataItem) ? visible : true;\n\t };\n\t }\n\t }\n\n\t chart._noTransitionsRedraw();\n\n\t this._clearFields();\n\t },\n\n\t _filterData: function(filter) {\n\t var data = this._seriesOptions().data;\n\t var length = data.length;\n\t var result = [];\n\n\t for (var idx = 0; idx < length; idx++) {\n\t if (filter(data[idx])) {\n\t result.push(data[idx]);\n\t }\n\t }\n\t return result;\n\t },\n\n\t _filterPoints: function(points, filter) {\n\t var result = [];\n\t var length = points.length;\n\t for (var idx = 0; idx < length; idx++) {\n\t if (filter(points[idx])) {\n\t result.push(points[idx]);\n\t }\n\t }\n\t return result;\n\t },\n\n\t _seriesOptions: function() {\n\t var series = this._series;\n\t if (!series) {\n\t series = this._series = this._chart._seriesOptions(this._options);\n\t }\n\t return series;\n\t },\n\n\t _clearFields: function() {\n\t delete this._points;\n\t delete this._series;\n\t }\n\t });\n\n\t function triggerPaneRender(panes) {\n\t for (var idx = 0; idx < panes.length; idx++) {\n\t panes[idx].notifyRender();\n\t }\n\t }\n\n\t dataviz.Tooltip = Tooltip;\n\t dataviz.CrosshairTooltip = CrosshairTooltip;\n\t dataviz.ChartInstanceObserver = ChartInstanceObserver;\n\t dataviz.ChartPane = ChartPane;\n\t dataviz.ChartSeries = ChartSeries;\n\n\t})(window.kendo.jQuery);\n\n\treturn window.kendo;\n\n\t}, __webpack_require__(3));\n\n\n/***/ }),\n\n/***/ 856:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"./kendo-chart\");\n\n/***/ }),\n\n/***/ 857:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.data\");\n\n/***/ }),\n\n/***/ 858:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.dataviz.core\");\n\n/***/ }),\n\n/***/ 859:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.dataviz.themes\");\n\n/***/ }),\n\n/***/ 860:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.drawing\");\n\n/***/ }),\n\n/***/ 861:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.userevents\");\n\n/***/ })\n\n/******/ });","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ 0:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tmodule.exports = __webpack_require__(862);\n\n\n/***/ }),\n\n/***/ 3:\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n\n/***/ 858:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.dataviz.core\");\n\n/***/ }),\n\n/***/ 860:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.drawing\");\n\n/***/ }),\n\n/***/ 862:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/***********************************************************************\n\t * WARNING: this file is auto-generated. If you change it directly,\n\t * your modifications will eventually be lost. The source code is in\n\t * `kendo-charts` repository, you should make your changes there and\n\t * run `src-modules/sync.sh` in this repository.\n\t */\n\t(function(f, define){\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n\t __webpack_require__(863),\n\t __webpack_require__(864),\n\t __webpack_require__(860),\n\t __webpack_require__(858)\n\t ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t})(function(){\n\n\t(function ($) {\n\n\twindow.kendo.dataviz = window.kendo.dataviz || {};\n\tvar dataviz = kendo.dataviz;\n\tvar Class = dataviz.Class;\n\tvar isNumber = dataviz.isNumber;\n\tvar datavizConstants = dataviz.constants;\n\tvar MAX_VALUE = datavizConstants.MAX_VALUE;\n\tvar MIN_VALUE = datavizConstants.MIN_VALUE;\n\tvar VALUE = datavizConstants.VALUE;\n\tvar CENTER = datavizConstants.CENTER;\n\tvar TOP = datavizConstants.TOP;\n\tvar BOTTOM = datavizConstants.BOTTOM;\n\tvar LEFT = datavizConstants.LEFT;\n\tvar WHITE = datavizConstants.WHITE;\n\tvar CIRCLE = datavizConstants.CIRCLE;\n\tvar X = datavizConstants.X;\n\tvar Y = datavizConstants.Y;\n\tvar RIGHT = datavizConstants.RIGHT;\n\tvar BLACK = datavizConstants.BLACK;\n\tvar DATE = datavizConstants.DATE;\n\tvar DEFAULT_PRECISION = datavizConstants.DEFAULT_PRECISION;\n\tvar ARC = datavizConstants.ARC;\n\tvar defined = dataviz.defined;\n\tvar getter = dataviz.getter;\n\tvar isArray = dataviz.isArray;\n\tvar ChartElement = dataviz.ChartElement;\n\tvar Point = dataviz.Point;\n\tvar Box = dataviz.Box;\n\tvar alignPathToPixel = dataviz.alignPathToPixel;\n\tvar setDefaultOptions = dataviz.setDefaultOptions;\n\tvar inArray = dataviz.inArray;\n\tvar isFunction = dataviz.isFunction;\n\tvar valueOrDefault = dataviz.valueOrDefault;\n\tvar isObject = dataviz.isObject;\n\tvar deepExtend = dataviz.deepExtend;\n\tvar last = dataviz.last;\n\tvar eventElement = dataviz.eventElement;\n\tvar getTemplate = dataviz.getTemplate;\n\tvar TextBox = dataviz.TextBox;\n\tvar ShapeElement = dataviz.ShapeElement;\n\tvar getSpacing = dataviz.getSpacing;\n\tvar CurveProcessor = dataviz.CurveProcessor;\n\tvar append = dataviz.append;\n\tvar isString = dataviz.isString;\n\tvar parseDate = dataviz.parseDate;\n\tvar styleValue = dataviz.styleValue;\n\tvar CategoryAxis = dataviz.CategoryAxis;\n\tvar BoxElement = dataviz.BoxElement;\n\tvar round = dataviz.round;\n\tvar limitValue = dataviz.limitValue;\n\tvar grep = dataviz.grep;\n\tvar elementStyles = dataviz.elementStyles;\n\tvar hasClasses = dataviz.hasClasses;\n\tvar bindEvents = dataviz.bindEvents;\n\tvar services = dataviz.services;\n\tvar unbindEvents = dataviz.unbindEvents;\n\tvar support = kendo.support;\n\tvar drawing = kendo.drawing;\n\tvar Path = drawing.Path;\n\tvar Animation = drawing.Animation;\n\tvar AnimationFactory = drawing.AnimationFactory;\n\tvar Group = drawing.Group;\n\tvar Color = kendo.Color;\n\tvar geometry = kendo.geometry;\n\tvar GeometryPoint = geometry.Point;\n\tvar transform = geometry.transform;\n\n\tvar ChartAxis = Class.extend({\n\t init: function(axis) {\n\n\t this._axis = axis;\n\t this.options = axis.options;\n\t },\n\n\t value: function(point) {\n\t var axis = this._axis;\n\t var value = axis.getCategory ? axis.getCategory(point) : axis.getValue(point);\n\n\t return value;\n\t },\n\n\t slot: function(from, to, limit) {\n\t if (limit === void 0) { limit = true; }\n\n\t return this._axis.slot(from, to, limit);\n\t },\n\n\t range: function() {\n\t return this._axis.range();\n\t },\n\n\t valueRange: function() {\n\t return this._axis.valueRange();\n\t }\n\t});\n\n\tfunction findAxisByName(name, axes) {\n\t for (var idx = 0; idx < axes.length; idx++) {\n\t if (axes[idx].options.name === name) {\n\t axes[idx].prepareUserOptions();\n\t return new ChartAxis(axes[idx]);\n\t }\n\t }\n\t}\n\n\tvar ChartPane = kendo.Class.extend({\n\t init: function(pane) {\n\t this.visual = pane.visual;\n\t this.chartsVisual = pane.chartContainer.visual;\n\t this._pane = pane;\n\t },\n\n\t findAxisByName: function(name) {\n\t return findAxisByName(name, this._pane.axes);\n\t }\n\t});\n\n\tvar ChartPlotArea = Class.extend({\n\t init: function(plotArea) {\n\n\t this._plotArea = plotArea;\n\t this.visual = plotArea.visual;\n\t this.backgroundVisual = plotArea._bgVisual;\n\t }\n\t});\n\n\tfunction countNumbers(values) {\n\t var length = values.length;\n\t var count = 0;\n\n\t for (var i = 0; i < length; i++) {\n\t var num = values[i];\n\t if (isNumber(num)) {\n\t count++;\n\t }\n\t }\n\n\t return count;\n\t}\n\n\tvar Aggregates = {\n\t min: function(values) {\n\t var length = values.length;\n\t var min = MAX_VALUE;\n\n\t for (var i = 0; i < length; i++) {\n\t var value = values[i];\n\t if (isNumber(value)) {\n\t min = Math.min(min, value);\n\t }\n\t }\n\n\t return min === MAX_VALUE ? values[0] : min;\n\t },\n\n\t max: function(values) {\n\t var length = values.length;\n\t var max = MIN_VALUE;\n\n\t for (var i = 0; i < length; i++) {\n\t var value = values[i];\n\t if (isNumber(value)) {\n\t max = Math.max(max, value);\n\t }\n\t }\n\n\t return max === MIN_VALUE ? values[0] : max;\n\t },\n\n\t sum: function(values) {\n\t var length = values.length;\n\t var sum = 0;\n\n\t for (var i = 0; i < length; i++) {\n\t var value = values[i];\n\t if (isNumber(value)) {\n\t sum += value;\n\t }\n\t }\n\n\t return sum;\n\t },\n\n\t sumOrNull: function(values) {\n\t var result = null;\n\n\t if (countNumbers(values)) {\n\t result = Aggregates.sum(values);\n\t }\n\n\t return result;\n\t },\n\n\t count: function(values) {\n\t var length = values.length;\n\t var count = 0;\n\n\t for (var i = 0; i < length; i++) {\n\t var value = values[i];\n\t if (value !== null && defined(value)) {\n\t count++;\n\t }\n\t }\n\n\t return count;\n\t },\n\n\t avg: function(values) {\n\t var count = countNumbers(values);\n\t var result = values[0];\n\n\t if (count > 0) {\n\t result = Aggregates.sum(values) / count;\n\t }\n\n\t return result;\n\t },\n\n\t first: function(values) {\n\t var length = values.length;\n\n\t for (var i = 0; i < length; i++) {\n\t var value = values[i];\n\t if (value !== null && defined(value)) {\n\t return value;\n\t }\n\t }\n\n\t return values[0];\n\t }\n\t};\n\n\tfunction getField(field, row) {\n\t if (row === null) {\n\t return row;\n\t }\n\n\t var get = getter(field, true);\n\t return get(row);\n\t}\n\n\tvar SeriesBinder = Class.extend({\n\t init: function() {\n\n\t this._valueFields = {};\n\t this._otherFields = {};\n\t this._nullValue = {};\n\t this._undefinedValue = {};\n\t },\n\n\t register: function(seriesTypes, valueFields, otherFields) {\n\t var this$1 = this;\n\t if (valueFields === void 0) { valueFields = [ VALUE ]; }\n\t if (otherFields === void 0) { otherFields = {}; }\n\n\t for (var i = 0; i < seriesTypes.length; i++) {\n\t var type = seriesTypes[i];\n\n\t this$1._valueFields[type] = valueFields;\n\t this$1._otherFields[type] = otherFields;\n\t this$1._nullValue[type] = this$1._makeValue(valueFields, null);\n\t this$1._undefinedValue[type] = this$1._makeValue(valueFields, undefined);\n\t }\n\t },\n\n\t canonicalFields: function(series) {\n\t return this.valueFields(series).concat(this.otherFields(series));\n\t },\n\n\t valueFields: function(series) {\n\t return this._valueFields[series.type] || [ VALUE ];\n\t },\n\n\t otherFields: function(series) {\n\t return this._otherFields[series.type] || [ VALUE ];\n\t },\n\n\t bindPoint: function(series, pointIx, item) {\n\t var data = series.data;\n\t var pointData = defined(item) ? item : data[pointIx];\n\t var result = { valueFields: { value: pointData } };\n\t var valueFields = this.valueFields(series);\n\t var otherFields = this._otherFields[series.type];\n\t var fields, value;\n\n\t if (pointData === null) {\n\t value = this._nullValue[series.type];\n\t } else if (!defined(pointData)) {\n\t value = this._undefinedValue[series.type];\n\t } else if (Array.isArray(pointData)) {\n\t var fieldData = pointData.slice(valueFields.length);\n\t value = this._bindFromArray(pointData, valueFields);\n\t fields = this._bindFromArray(fieldData, otherFields);\n\t } else if (typeof pointData === \"object\") {\n\t var srcValueFields = this.sourceFields(series, valueFields);\n\t var srcPointFields = this.sourceFields(series, otherFields);\n\n\t value = this._bindFromObject(pointData, valueFields, srcValueFields);\n\t fields = this._bindFromObject(pointData, otherFields, srcPointFields);\n\t }\n\n\t if (defined(value)) {\n\t if (valueFields.length === 1) {\n\t result.valueFields.value = value[valueFields[0]];\n\t } else {\n\t result.valueFields = value;\n\t }\n\t }\n\n\t result.fields = fields || {};\n\n\t return result;\n\t },\n\n\t _makeValue: function(fields, initialValue) {\n\t var value = {};\n\t var length = fields.length;\n\n\t for (var i = 0; i < length; i++) {\n\t var fieldName = fields[i];\n\t value[fieldName] = initialValue;\n\t }\n\n\t return value;\n\t },\n\n\t _bindFromArray: function(array, fields) {\n\t var value = {};\n\n\t if (fields) {\n\t var length = Math.min(fields.length, array.length);\n\n\t for (var i = 0; i < length; i++) {\n\t value[fields[i]] = array[i];\n\t }\n\t }\n\n\t return value;\n\t },\n\n\t _bindFromObject: function(object, fields, srcFields) {\n\t if (srcFields === void 0) { srcFields = fields; }\n\n\t var value = {};\n\n\t if (fields) {\n\t var length = fields.length;\n\n\t for (var i = 0; i < length; i++) {\n\t var fieldName = fields[i];\n\t var srcFieldName = srcFields[i];\n\t if (srcFieldName !== null) {\n\t value[fieldName] = getField(srcFieldName, object);\n\t }\n\t }\n\t }\n\n\t return value;\n\t },\n\n\t sourceFields: function(series, canonicalFields) {\n\t var sourceFields = [];\n\n\t if (canonicalFields) {\n\t var length = canonicalFields.length;\n\n\t for (var i = 0; i < length; i++) {\n\t var fieldName = canonicalFields[i];\n\t var sourceFieldName = fieldName === VALUE ? \"field\" : fieldName + \"Field\";\n\n\t sourceFields.push(series[sourceFieldName] !== null ? (series[sourceFieldName] || fieldName) : null);\n\t }\n\t }\n\n\t return sourceFields;\n\t }\n\t});\n\n\tSeriesBinder.current = new SeriesBinder();\n\n\tvar STD_ERR = \"stderr\";\n\tvar STD_DEV = \"stddev\";\n\tvar percentRegex = /percent(?:\\w*)\\((\\d+)\\)/;\n\tvar standardDeviationRegex = new RegExp(\"^\" + STD_DEV + \"(?:\\\\((\\\\d+(?:\\\\.\\\\d+)?)\\\\))?$\");\n\n\tvar ErrorRangeCalculator = Class.extend({\n\t init: function(errorValue, series, field) {\n\n\t this.initGlobalRanges(errorValue, series, field);\n\t },\n\n\t initGlobalRanges: function(errorValue, series, field) {\n\t var data = series.data;\n\t var deviationMatch = standardDeviationRegex.exec(errorValue);\n\n\t if (deviationMatch) {\n\t this.valueGetter = this.createValueGetter(series, field);\n\n\t var average = this.getAverage(data);\n\t var deviation = this.getStandardDeviation(data, average, false);\n\t var multiple = deviationMatch[1] ? parseFloat(deviationMatch[1]) : 1;\n\t var errorRange = { low: average.value - deviation * multiple, high: average.value + deviation * multiple };\n\n\t this.globalRange = function() {\n\t return errorRange;\n\t };\n\t } else if (errorValue.indexOf && errorValue.indexOf(STD_ERR) >= 0) {\n\t this.valueGetter = this.createValueGetter(series, field);\n\t var standardError = this.getStandardError(data, this.getAverage(data));\n\n\t this.globalRange = function(value) {\n\t return { low: value - standardError, high: value + standardError };\n\t };\n\t }\n\t },\n\n\t createValueGetter: function(series, field) {\n\t var data = series.data;\n\t var binder = SeriesBinder.current;\n\t var valueFields = binder.valueFields(series);\n\t var item = defined(data[0]) ? data[0] : {};\n\t var valueGetter;\n\n\t if (isArray(item)) {\n\t var index = field ? valueFields.indexOf(field) : 0;\n\t valueGetter = getter(\"[\" + index + \"]\");\n\t } else if (isNumber(item)) {\n\t valueGetter = getter();\n\t } else if (typeof item === datavizConstants.OBJECT) {\n\t var srcValueFields = binder.sourceFields(series, valueFields);\n\t valueGetter = getter(srcValueFields[valueFields.indexOf(field)]);\n\t }\n\n\t return valueGetter;\n\t },\n\n\t getErrorRange: function(pointValue, errorValue) {\n\t var low, high, value;\n\n\t if (!defined(errorValue)) {\n\t return null;\n\t }\n\n\t if (this.globalRange) {\n\t return this.globalRange(pointValue);\n\t }\n\n\t if (isArray(errorValue)) {\n\t low = pointValue - errorValue[0];\n\t high = pointValue + errorValue[1];\n\t } else if (isNumber(value = parseFloat(errorValue))) {\n\t low = pointValue - value;\n\t high = pointValue + value;\n\t } else if ((value = percentRegex.exec(errorValue))) {\n\t var percentValue = pointValue * (parseFloat(value[1]) / 100);\n\t low = pointValue - Math.abs(percentValue);\n\t high = pointValue + Math.abs(percentValue);\n\t } else {\n\t throw new Error(\"Invalid ErrorBar value: \" + errorValue);\n\t }\n\n\t return { low: low, high: high };\n\t },\n\n\t getStandardError: function(data, average) {\n\t return this.getStandardDeviation(data, average, true) / Math.sqrt(average.count);\n\t },\n\n\t getStandardDeviation: function(data, average, isSample) {\n\t var this$1 = this;\n\n\t var length = data.length;\n\t var total = isSample ? average.count - 1 : average.count;\n\t var squareDifferenceSum = 0;\n\n\t for (var idx = 0; idx < length; idx++) {\n\t var value = this$1.valueGetter(data[idx]);\n\t if (isNumber(value)) {\n\t squareDifferenceSum += Math.pow(value - average.value, 2);\n\t }\n\t }\n\n\t return Math.sqrt(squareDifferenceSum / total);\n\t },\n\n\t getAverage: function(data) {\n\t var this$1 = this;\n\n\t var length = data.length;\n\t var sum = 0;\n\t var count = 0;\n\n\t for (var idx = 0; idx < length; idx++) {\n\t var value = this$1.valueGetter(data[idx]);\n\t if (isNumber(value)) {\n\t sum += value;\n\t count++;\n\t }\n\t }\n\n\t return {\n\t value: sum / count,\n\t count: count\n\t };\n\t }\n\t});\n\n\tvar browser = support.browser || {};\n\n\tvar INITIAL_ANIMATION_DURATION = 600;\n\tvar FADEIN = \"fadeIn\";\n\n\tvar GLASS = \"glass\";\n\tvar BORDER_BRIGHTNESS = 0.8;\n\tvar TOOLTIP_OFFSET = 5;\n\tvar START_SCALE = browser.msie ? 0.001 : 0;\n\tvar ERROR_LOW_FIELD = \"errorLow\";\n\tvar ERROR_HIGH_FIELD = \"errorHigh\";\n\tvar X_ERROR_LOW_FIELD = \"xErrorLow\";\n\tvar X_ERROR_HIGH_FIELD = \"xErrorHigh\";\n\tvar Y_ERROR_LOW_FIELD = \"yErrorLow\";\n\tvar Y_ERROR_HIGH_FIELD = \"yErrorHigh\";\n\tvar LINE_MARKER_SIZE = 8;\n\tvar ZERO = \"zero\";\n\tvar INTERPOLATE = \"interpolate\";\n\tvar GAP = \"gap\";\n\tvar ABOVE = \"above\";\n\tvar BELOW = \"below\";\n\n\tvar SMOOTH = \"smooth\";\n\tvar STEP = \"step\";\n\n\tvar AREA = \"area\";\n\tvar BAR = \"bar\";\n\tvar BOX_PLOT = \"boxPlot\";\n\tvar BUBBLE = \"bubble\";\n\tvar BULLET = \"bullet\";\n\tvar CANDLESTICK = \"candlestick\";\n\tvar COLUMN = \"column\";\n\tvar DONUT = \"donut\";\n\tvar FUNNEL = \"funnel\";\n\tvar HORIZONTAL_WATERFALL = \"horizontalWaterfall\";\n\tvar LINE = \"line\";\n\tvar OHLC = \"ohlc\";\n\tvar PIE = \"pie\";\n\tvar POLAR_AREA = \"polarArea\";\n\tvar POLAR_LINE = \"polarLine\";\n\tvar POLAR_SCATTER = \"polarScatter\";\n\tvar RADAR_AREA = \"radarArea\";\n\tvar RADAR_COLUMN = \"radarColumn\";\n\tvar RADAR_LINE = \"radarLine\";\n\tvar RANGE_AREA = \"rangeArea\";\n\tvar RANGE_BAR = \"rangeBar\";\n\tvar RANGE_COLUMN = \"rangeColumn\";\n\tvar SCATTER = \"scatter\";\n\tvar SCATTER_LINE = \"scatterLine\";\n\tvar VERTICAL_AREA = \"verticalArea\";\n\tvar VERTICAL_BOX_PLOT = \"verticalBoxPlot\";\n\tvar VERTICAL_BULLET = \"verticalBullet\";\n\tvar VERTICAL_LINE = \"verticalLine\";\n\tvar VERTICAL_RANGE_AREA = \"verticalRangeArea\";\n\tvar WATERFALL = \"waterfall\";\n\tvar EQUALLY_SPACED_SERIES = [\n\t BAR, COLUMN, OHLC, CANDLESTICK, BOX_PLOT, VERTICAL_BOX_PLOT,\n\t BULLET, RANGE_COLUMN, RANGE_BAR, WATERFALL, HORIZONTAL_WATERFALL\n\t];\n\n\tvar LEGEND_ITEM_CLICK = \"legendItemClick\";\n\tvar LEGEND_ITEM_HOVER = \"legendItemHover\";\n\tvar LEGEND_ITEM_LEAVE = \"legendItemLeave\";\n\tvar SERIES_CLICK = \"seriesClick\";\n\tvar SERIES_HOVER = \"seriesHover\";\n\tvar SERIES_OVER = \"seriesOver\";\n\tvar SERIES_LEAVE = \"seriesLeave\";\n\tvar PLOT_AREA_CLICK = \"plotAreaClick\";\n\tvar PLOT_AREA_HOVER = \"plotAreaHover\";\n\tvar PLOT_AREA_LEAVE = \"plotAreaLeave\";\n\tvar DRAG = \"drag\";\n\tvar DRAG_END = \"dragEnd\";\n\tvar DRAG_START = \"dragStart\";\n\tvar ZOOM_START = \"zoomStart\";\n\tvar ZOOM = \"zoom\";\n\tvar ZOOM_END = \"zoomEnd\";\n\tvar SELECT_START = \"selectStart\";\n\tvar SELECT = \"select\";\n\tvar SELECT_END = \"selectEnd\";\n\tvar RENDER = \"render\";\n\tvar SHOW_TOOLTIP = \"showTooltip\";\n\tvar HIDE_TOOLTIP = \"hideTooltip\";\n\tvar PANE_RENDER = \"paneRender\";\n\n\tvar LOGARITHMIC = \"log\";\n\tvar CATEGORY = \"category\";\n\n\tvar INSIDE_END = \"insideEnd\";\n\tvar INSIDE_BASE = \"insideBase\";\n\tvar OUTSIDE_END = \"outsideEnd\";\n\n\tvar MOUSEWHEEL = \"DOMMouseScroll mousewheel\";\n\tvar MOUSEWHEEL_DELAY = 150;\n\n\tvar constants = {\n\t\tINITIAL_ANIMATION_DURATION: INITIAL_ANIMATION_DURATION,\n\t\tFADEIN: FADEIN,\n\t\tLEGEND_ITEM_CLICK: LEGEND_ITEM_CLICK,\n\t\tLEGEND_ITEM_HOVER: LEGEND_ITEM_HOVER,\n\t\tLEGEND_ITEM_LEAVE: LEGEND_ITEM_LEAVE,\n\t\tSERIES_CLICK: SERIES_CLICK,\n\t\tSERIES_HOVER: SERIES_HOVER,\n\t\tSERIES_OVER: SERIES_OVER,\n\t\tSERIES_LEAVE: SERIES_LEAVE,\n\t\tGLASS: GLASS,\n\t\tBORDER_BRIGHTNESS: BORDER_BRIGHTNESS,\n\t\tTOOLTIP_OFFSET: TOOLTIP_OFFSET,\n\t\tSTART_SCALE: START_SCALE,\n\t\tERROR_LOW_FIELD: ERROR_LOW_FIELD,\n\t\tERROR_HIGH_FIELD: ERROR_HIGH_FIELD,\n\t\tX_ERROR_LOW_FIELD: X_ERROR_LOW_FIELD,\n\t\tX_ERROR_HIGH_FIELD: X_ERROR_HIGH_FIELD,\n\t\tY_ERROR_LOW_FIELD: Y_ERROR_LOW_FIELD,\n\t\tY_ERROR_HIGH_FIELD: Y_ERROR_HIGH_FIELD,\n\t\tLINE_MARKER_SIZE: LINE_MARKER_SIZE,\n\t\tINTERPOLATE: INTERPOLATE,\n\t\tZERO: ZERO,\n\t\tSMOOTH: SMOOTH,\n\t\tSTEP: STEP,\n\t\tCATEGORY: CATEGORY,\n\t\tFUNNEL: FUNNEL,\n\t\tBAR: BAR,\n\t\tCANDLESTICK: CANDLESTICK,\n\t\tPIE: PIE,\n\t\tCOLUMN: COLUMN,\n\t\tAREA: AREA,\n\t\tVERTICAL_BULLET: VERTICAL_BULLET,\n\t\tBOX_PLOT: BOX_PLOT,\n\t\tOHLC: OHLC,\n\t\tWATERFALL: WATERFALL,\n\t\tLINE: LINE,\n\t\tBULLET: BULLET,\n\t\tVERTICAL_LINE: VERTICAL_LINE,\n\t\tVERTICAL_AREA: VERTICAL_AREA,\n\t\tRANGE_AREA: RANGE_AREA,\n\t\tVERTICAL_RANGE_AREA: VERTICAL_RANGE_AREA,\n\t\tRANGE_COLUMN: RANGE_COLUMN,\n\t\tVERTICAL_BOX_PLOT: VERTICAL_BOX_PLOT,\n\t\tRANGE_BAR: RANGE_BAR,\n\t\tHORIZONTAL_WATERFALL: HORIZONTAL_WATERFALL,\n\t\tSCATTER: SCATTER,\n\t\tSCATTER_LINE: SCATTER_LINE,\n\t\tBUBBLE: BUBBLE,\n\t\tRADAR_AREA: RADAR_AREA,\n\t\tRADAR_LINE: RADAR_LINE,\n\t\tRADAR_COLUMN: RADAR_COLUMN,\n\t\tPOLAR_LINE: POLAR_LINE,\n\t\tPOLAR_AREA: POLAR_AREA,\n\t\tPOLAR_SCATTER: POLAR_SCATTER,\n\t\tRENDER: RENDER,\n\t\tPLOT_AREA_CLICK: PLOT_AREA_CLICK,\n\t\tPLOT_AREA_HOVER: PLOT_AREA_HOVER,\n\t\tPLOT_AREA_LEAVE: PLOT_AREA_LEAVE,\n\t\tLOGARITHMIC: LOGARITHMIC,\n\t\tDRAG: DRAG,\n\t\tDRAG_START: DRAG_START,\n\t\tDRAG_END: DRAG_END,\n\t\tZOOM_START: ZOOM_START,\n\t\tZOOM: ZOOM,\n\t\tZOOM_END: ZOOM_END,\n\t\tSELECT_START: SELECT_START,\n\t\tSELECT: SELECT,\n\t\tSELECT_END: SELECT_END,\n\t\tPANE_RENDER: PANE_RENDER,\n\t\tGAP: GAP,\n\t\tDONUT: DONUT,\n\t\tINSIDE_END: INSIDE_END,\n\t\tINSIDE_BASE: INSIDE_BASE,\n\t\tOUTSIDE_END: OUTSIDE_END,\n\t\tMOUSEWHEEL: MOUSEWHEEL,\n\t\tMOUSEWHEEL_DELAY: MOUSEWHEEL_DELAY,\n\t\tSHOW_TOOLTIP: SHOW_TOOLTIP,\n\t\tHIDE_TOOLTIP: HIDE_TOOLTIP,\n\t\tEQUALLY_SPACED_SERIES: EQUALLY_SPACED_SERIES,\n\t\tABOVE: ABOVE,\n\t\tBELOW: BELOW\n\t};\n\n\tvar DEFAULT_ERROR_BAR_WIDTH = 4;\n\n\tvar ErrorBarBase = ChartElement.extend({\n\t init: function(low, high, isVertical, chart, series, options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.low = low;\n\t this.high = high;\n\t this.isVertical = isVertical;\n\t this.chart = chart;\n\t this.series = series;\n\t },\n\n\t reflow: function(targetBox) {\n\t var endCaps = this.options.endCaps;\n\t var isVertical = this.isVertical;\n\t var axis = this.getAxis();\n\t var valueBox = axis.getSlot(this.low, this.high);\n\t var centerBox = targetBox.center();\n\t var capsWidth = this.getCapsWidth(targetBox, isVertical);\n\t var capValue = isVertical ? centerBox.x : centerBox.y;\n\t var capStart = capValue - capsWidth;\n\t var capEnd = capValue + capsWidth;\n\t var linePoints;\n\n\t if (isVertical) {\n\t linePoints = [\n\t new Point(centerBox.x, valueBox.y1),\n\t new Point(centerBox.x, valueBox.y2)\n\t ];\n\t if (endCaps) {\n\t linePoints.push(new Point(capStart, valueBox.y1),\n\t new Point(capEnd, valueBox.y1),\n\t new Point(capStart, valueBox.y2),\n\t new Point(capEnd, valueBox.y2));\n\t }\n\t this.box = new Box(capStart, valueBox.y1, capEnd, valueBox.y2);\n\t } else {\n\t linePoints = [\n\t new Point(valueBox.x1, centerBox.y),\n\t new Point(valueBox.x2, centerBox.y)\n\t ];\n\t if (endCaps) {\n\t linePoints.push(new Point(valueBox.x1, capStart),\n\t new Point(valueBox.x1, capEnd),\n\t new Point(valueBox.x2, capStart),\n\t new Point(valueBox.x2, capEnd));\n\t }\n\t this.box = new Box(valueBox.x1, capStart, valueBox.x2, capEnd);\n\t }\n\n\t this.linePoints = linePoints;\n\t },\n\n\t getCapsWidth: function(box, isVertical) {\n\t var boxSize = isVertical ? box.width() : box.height();\n\t var capsWidth = Math.min(Math.floor(boxSize / 2), DEFAULT_ERROR_BAR_WIDTH) || DEFAULT_ERROR_BAR_WIDTH;\n\n\t return capsWidth;\n\t },\n\n\t createVisual: function() {\n\t var this$1 = this;\n\n\t var options = this.options;\n\t var visual = options.visual;\n\n\t if (visual) {\n\t this.visual = visual({\n\t low: this.low,\n\t high: this.high,\n\t rect: this.box.toRect(),\n\t sender: this.getSender(),\n\t options: {\n\t endCaps: options.endCaps,\n\t color: options.color,\n\t line: options.line\n\t },\n\t createVisual: function () {\n\t this$1.createDefaultVisual();\n\t var defaultVisual = this$1.visual;\n\t delete this$1.visual;\n\t return defaultVisual;\n\t }\n\t });\n\t } else {\n\t this.createDefaultVisual();\n\t }\n\t },\n\n\t createDefaultVisual: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var options = ref.options;\n\t var linePoints = ref.linePoints;\n\t var lineOptions = {\n\t stroke: {\n\t color: options.color,\n\t width: options.line.width,\n\t dashType: options.line.dashType\n\t }\n\t };\n\n\t ChartElement.fn.createVisual.call(this);\n\n\t for (var idx = 0; idx < linePoints.length; idx += 2) {\n\t var line = new Path(lineOptions)\n\t .moveTo(linePoints[idx].x, linePoints[idx].y)\n\t .lineTo(linePoints[idx + 1].x, linePoints[idx + 1].y);\n\n\t alignPathToPixel(line);\n\t this$1.visual.append(line);\n\t }\n\t }\n\t});\n\n\tsetDefaultOptions(ErrorBarBase, {\n\t animation: {\n\t type: FADEIN,\n\t delay: INITIAL_ANIMATION_DURATION\n\t },\n\t endCaps: true,\n\t line: {\n\t width: 2\n\t },\n\t zIndex: 1\n\t});\n\n\tvar CategoricalErrorBar = ErrorBarBase.extend({\n\t getAxis: function() {\n\t var axis = this.chart.seriesValueAxis(this.series);\n\n\t return axis;\n\t }\n\t});\n\n\tvar MAX_EXPAND_DEPTH = 5;\n\n\tfunction evalOptions(options, context, state, dryRun) {\n\t if (state === void 0) { state = {}; }\n\t if (dryRun === void 0) { dryRun = false; }\n\n\t var defaults = state.defaults = state.defaults || {};\n\t var depth = state.depth = state.depth || 0;\n\t var needsEval = false;\n\n\t state.excluded = state.excluded || [];\n\n\t if (depth > MAX_EXPAND_DEPTH) {\n\t return null;\n\t }\n\n\t for (var property in options) {\n\t if (!inArray(property, state.excluded) && options.hasOwnProperty(property)) {\n\t var propValue = options[property];\n\t if (isFunction(propValue)) {\n\t needsEval = true;\n\t if (!dryRun) {\n\t options[property] = valueOrDefault(propValue(context), defaults[property]);\n\t }\n\t } else if (isObject(propValue)) {\n\t if (!dryRun) {\n\t state.defaults = defaults[property];\n\t }\n\t state.depth++;\n\t needsEval = evalOptions(propValue, context, state, dryRun) || needsEval;\n\t state.depth--;\n\t }\n\t }\n\t }\n\n\t return needsEval;\n\t}\n\n\tfunction categoriesCount(series) {\n\t var seriesCount = series.length;\n\t var categories = 0;\n\n\t for (var i = 0; i < seriesCount; i++) {\n\t categories = Math.max(categories, series[i].data.length);\n\t }\n\n\t return categories;\n\t}\n\n\tvar CategoricalChart = ChartElement.extend({\n\t init: function(plotArea, options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.plotArea = plotArea;\n\t this.chartService = plotArea.chartService;\n\t this.categoryAxis = plotArea.seriesCategoryAxis(options.series[0]);\n\n\t // Value axis ranges grouped by axis name, e.g.:\n\t // primary: { min: 0, max: 1 }\n\t this.valueAxisRanges = {};\n\n\t this.points = [];\n\t this.categoryPoints = [];\n\t this.seriesPoints = [];\n\t this.seriesOptions = [];\n\t this._evalSeries = [];\n\n\t this.render();\n\t },\n\n\t render: function() {\n\t this.traverseDataPoints(this.addValue.bind(this));\n\t },\n\n\t pointOptions: function(series, seriesIx) {\n\t var options = this.seriesOptions[seriesIx];\n\t if (!options) {\n\t var defaults = this.pointType().prototype.defaults;\n\t this.seriesOptions[seriesIx] = options = deepExtend({ }, defaults, {\n\t vertical: !this.options.invertAxes\n\t }, series);\n\t }\n\n\t return options;\n\t },\n\n\t plotValue: function(point) {\n\t if (!point) {\n\t return 0;\n\t }\n\n\t if (this.options.isStacked100 && isNumber(point.value)) {\n\t var categoryIx = point.categoryIx;\n\t var categoryPoints = this.categoryPoints[categoryIx];\n\t var otherValues = [];\n\t var categorySum = 0;\n\n\t for (var i = 0; i < categoryPoints.length; i++) {\n\t var other = categoryPoints[i];\n\t if (other) {\n\t var stack = point.series.stack;\n\t var otherStack = other.series.stack;\n\n\t if ((stack && otherStack) && stack.group !== otherStack.group) {\n\t continue;\n\t }\n\n\t if (isNumber(other.value)) {\n\t categorySum += Math.abs(other.value);\n\t otherValues.push(Math.abs(other.value));\n\t }\n\t }\n\t }\n\n\t if (categorySum > 0) {\n\t return point.value / categorySum;\n\t }\n\t }\n\n\t return point.value;\n\t },\n\n\t plotRange: function(point, startValue) {\n\t var this$1 = this;\n\t if (startValue === void 0) { startValue = 0; }\n\n\t var categoryPoints = this.categoryPoints[point.categoryIx];\n\n\t if (this.options.isStacked) {\n\t var plotValue = this.plotValue(point);\n\t var positive = plotValue >= 0;\n\t var prevValue = startValue;\n\t var isStackedBar = false;\n\n\t for (var i = 0; i < categoryPoints.length; i++) {\n\t var other = categoryPoints[i];\n\n\t if (point === other) {\n\t break;\n\t }\n\n\t var stack = point.series.stack;\n\t var otherStack = other.series.stack;\n\t if (stack && otherStack) {\n\t if (typeof stack === datavizConstants.STRING && stack !== otherStack) {\n\t continue;\n\t }\n\n\t if (stack.group && stack.group !== otherStack.group) {\n\t continue;\n\t }\n\t }\n\n\t var otherValue = this$1.plotValue(other);\n\t if ((otherValue >= 0 && positive) ||\n\t (otherValue < 0 && !positive)) {\n\t prevValue += otherValue;\n\t plotValue += otherValue;\n\t isStackedBar = true;\n\n\t if (this$1.options.isStacked100) {\n\t plotValue = Math.min(plotValue, 1);\n\t }\n\t }\n\t }\n\n\t if (isStackedBar) {\n\t prevValue -= startValue;\n\t }\n\n\t return [ prevValue, plotValue ];\n\t }\n\n\t var series = point.series;\n\t var valueAxis = this.seriesValueAxis(series);\n\t var axisCrossingValue = this.categoryAxisCrossingValue(valueAxis);\n\n\t return [ axisCrossingValue, dataviz.convertableToNumber(point.value) ? point.value : axisCrossingValue ];\n\t },\n\n\t stackLimits: function(axisName, stackName) {\n\t var this$1 = this;\n\n\t var min = MAX_VALUE;\n\t var max = MIN_VALUE;\n\n\t for (var i = 0; i < this.categoryPoints.length; i++) {\n\t var categoryPoints = this$1.categoryPoints[i];\n\t if (!categoryPoints) {\n\t continue;\n\t }\n\n\t for (var pIx = 0; pIx < categoryPoints.length; pIx++) {\n\t var point = categoryPoints[pIx];\n\t if (point) {\n\t if (point.series.stack === stackName || point.series.axis === axisName) {\n\t var to = this$1.plotRange(point, 0)[1];\n\t if (defined(to) && isFinite(to)) {\n\t max = Math.max(max, to);\n\t min = Math.min(min, to);\n\t }\n\t }\n\t }\n\t }\n\t }\n\n\t return { min: min, max: max };\n\t },\n\n\t updateStackRange: function() {\n\t var this$1 = this;\n\n\t var ref = this.options;\n\t var isStacked = ref.isStacked;\n\t var chartSeries = ref.series;\n\t var limitsCache = {};\n\n\t if (isStacked) {\n\t for (var i = 0; i < chartSeries.length; i++) {\n\t var series = chartSeries[i];\n\t var axisName = series.axis;\n\t var key = axisName + series.stack;\n\n\t var limits = limitsCache[key];\n\t if (!limits) {\n\t limits = this$1.stackLimits(axisName, series.stack);\n\n\t var errorTotals = this$1.errorTotals;\n\t if (errorTotals) {\n\t if (errorTotals.negative.length) {\n\t limits.min = Math.min(limits.min, dataviz.sparseArrayLimits(errorTotals.negative).min);\n\t }\n\t if (errorTotals.positive.length) {\n\t limits.max = Math.max(limits.max, dataviz.sparseArrayLimits(errorTotals.positive).max);\n\t }\n\t }\n\n\t if (limits.min !== MAX_VALUE || limits.max !== MIN_VALUE) {\n\t limitsCache[key] = limits;\n\t } else {\n\t limits = null;\n\t }\n\t }\n\n\t if (limits) {\n\t this$1.valueAxisRanges[axisName] = limits;\n\t }\n\t }\n\t }\n\t },\n\n\t addErrorBar: function(point, data, categoryIx) {\n\t var value = point.value;\n\t var series = point.series;\n\t var seriesIx = point.seriesIx;\n\t var errorBars = point.options.errorBars;\n\t var lowValue = data.fields[ERROR_LOW_FIELD];\n\t var highValue = data.fields[ERROR_HIGH_FIELD];\n\t var errorRange;\n\n\t if (isNumber(lowValue) && isNumber(highValue)) {\n\t errorRange = { low: lowValue, high: highValue };\n\t } else if (errorBars && defined(errorBars.value)) {\n\t this.seriesErrorRanges = this.seriesErrorRanges || [];\n\t this.seriesErrorRanges[seriesIx] = this.seriesErrorRanges[seriesIx] ||\n\t new ErrorRangeCalculator(errorBars.value, series, VALUE);\n\n\t errorRange = this.seriesErrorRanges[seriesIx].getErrorRange(value, errorBars.value);\n\t }\n\n\t if (errorRange) {\n\t point.low = errorRange.low;\n\t point.high = errorRange.high;\n\t this.addPointErrorBar(point, categoryIx);\n\t }\n\t },\n\n\t addPointErrorBar: function(point, categoryIx) {\n\t var isVertical = !this.options.invertAxes;\n\t var options = point.options.errorBars;\n\t var series = point.series;\n\t var low = point.low;\n\t var high = point.high;\n\n\t if (this.options.isStacked) {\n\t var stackedErrorRange = this.stackedErrorRange(point, categoryIx);\n\t low = stackedErrorRange.low;\n\t high = stackedErrorRange.high;\n\t } else {\n\t var fields = { categoryIx: categoryIx, series: series };\n\t this.updateRange({ value: low }, fields);\n\t this.updateRange({ value: high }, fields);\n\t }\n\n\t var errorBar = new CategoricalErrorBar(low, high, isVertical, this, series, options);\n\t point.errorBars = [ errorBar ];\n\t point.append(errorBar);\n\t },\n\n\t stackedErrorRange: function(point, categoryIx) {\n\t var plotValue = this.plotRange(point, 0)[1] - point.value;\n\t var low = point.low + plotValue;\n\t var high = point.high + plotValue;\n\n\t this.errorTotals = this.errorTotals || { positive: [], negative: [] };\n\n\t if (low < 0) {\n\t this.errorTotals.negative[categoryIx] = Math.min(this.errorTotals.negative[categoryIx] || 0, low);\n\t }\n\n\t if (high > 0) {\n\t this.errorTotals.positive[categoryIx] = Math.max(this.errorTotals.positive[categoryIx] || 0, high);\n\t }\n\n\t return { low: low, high: high };\n\t },\n\n\t addValue: function(data, fields) {\n\t var categoryIx = fields.categoryIx;\n\t var series = fields.series;\n\t var seriesIx = fields.seriesIx;\n\n\t var categoryPoints = this.categoryPoints[categoryIx];\n\t if (!categoryPoints) {\n\t this.categoryPoints[categoryIx] = categoryPoints = [];\n\t }\n\n\t var seriesPoints = this.seriesPoints[seriesIx];\n\t if (!seriesPoints) {\n\t this.seriesPoints[seriesIx] = seriesPoints = [];\n\t }\n\n\t var point = this.createPoint(data, fields);\n\t if (point) {\n\t $.extend(point, fields);\n\n\t point.owner = this;\n\t point.noteText = data.fields.noteText;\n\t if (!defined(point.dataItem)) {\n\t point.dataItem = series.data[categoryIx];\n\t }\n\t this.addErrorBar(point, data, categoryIx);\n\t }\n\n\t this.points.push(point);\n\t seriesPoints.push(point);\n\t categoryPoints.push(point);\n\n\t this.updateRange(data.valueFields, fields);\n\t },\n\n\t evalPointOptions: function(options, value, category, categoryIx, series, seriesIx) {\n\t var state = { defaults: series._defaults, excluded: [ \"data\", \"aggregate\", \"_events\", \"tooltip\", \"content\", \"template\", \"visual\", \"toggle\", \"_outOfRangeMinPoint\", \"_outOfRangeMaxPoint\" ] };\n\n\t var doEval = this._evalSeries[seriesIx];\n\t if (!defined(doEval)) {\n\t this._evalSeries[seriesIx] = doEval = evalOptions(options, {}, state, true);\n\t }\n\n\t var pointOptions = options;\n\t if (doEval) {\n\t pointOptions = deepExtend({}, pointOptions);\n\t evalOptions(pointOptions, {\n\t value: value,\n\t category: category,\n\t index: categoryIx,\n\t series: series,\n\t dataItem: series.data[categoryIx]\n\t }, state);\n\t }\n\n\t return pointOptions;\n\t },\n\n\t updateRange: function(data, fields) {\n\t var axisName = fields.series.axis;\n\t var value = data.value;\n\t var axisRange = this.valueAxisRanges[axisName];\n\n\t if (isFinite(value) && value !== null) {\n\t axisRange = this.valueAxisRanges[axisName] =\n\t axisRange || { min: MAX_VALUE, max: MIN_VALUE };\n\n\t axisRange.min = Math.min(axisRange.min, value);\n\t axisRange.max = Math.max(axisRange.max, value);\n\t }\n\t },\n\n\t seriesValueAxis: function(series) {\n\t var plotArea = this.plotArea;\n\t var axisName = series.axis;\n\t var axis = axisName ? plotArea.namedValueAxes[axisName] : plotArea.valueAxis;\n\n\t if (!axis) {\n\t throw new Error(\"Unable to locate value axis with name \" + axisName);\n\t }\n\n\t return axis;\n\t },\n\n\t reflow: function(targetBox) {\n\t var this$1 = this;\n\n\t var categorySlots = this.categorySlots = [];\n\t var chartPoints = this.points;\n\t var categoryAxis = this.categoryAxis;\n\t var pointIx = 0;\n\n\t this.traverseDataPoints(function (data, fields) {\n\t var categoryIx = fields.categoryIx;\n\t var currentSeries = fields.series;\n\n\t var valueAxis = this$1.seriesValueAxis(currentSeries);\n\t var point = chartPoints[pointIx++];\n\n\t var categorySlot = categorySlots[categoryIx];\n\t if (!categorySlot) {\n\t categorySlots[categoryIx] = categorySlot =\n\t this$1.categorySlot(categoryAxis, categoryIx, valueAxis);\n\t }\n\n\t if (point) {\n\t var plotRange = this$1.plotRange(point, valueAxis.startValue());\n\t var valueSlot = this$1.valueSlot(valueAxis, plotRange);\n\t if (valueSlot) {\n\t var pointSlot = this$1.pointSlot(categorySlot, valueSlot);\n\n\t point.aboveAxis = this$1.aboveAxis(point, valueAxis);\n\t point.stackValue = plotRange[1];\n\n\t if (this$1.options.isStacked100) {\n\t point.percentage = this$1.plotValue(point);\n\t }\n\n\t this$1.reflowPoint(point, pointSlot);\n\t } else {\n\t point.visible = false;\n\t }\n\t }\n\t });\n\n\t this.reflowCategories(categorySlots);\n\t if (!this.options.clip && this.options.limitPoints && this.points.length) {\n\t this.limitPoints();\n\t }\n\n\t this.box = targetBox;\n\t },\n\n\t valueSlot: function(valueAxis, plotRange) {\n\t return valueAxis.getSlot(plotRange[0], plotRange[1], !this.options.clip);\n\t },\n\n\t limitPoints: function() {\n\t var this$1 = this;\n\n\t var categoryPoints = this.categoryPoints;\n\t var points = categoryPoints[0].concat(last(categoryPoints));\n\t for (var idx = 0; idx < points.length; idx++) {\n\t if (points[idx]) {\n\t this$1.limitPoint(points[idx]);\n\t }\n\t }\n\t },\n\n\t limitPoint: function(point) {\n\t var limittedSlot = this.categoryAxis.limitSlot(point.box);\n\t if (!limittedSlot.equals(point.box)) {\n\t point.reflow(limittedSlot);\n\t }\n\t },\n\n\t aboveAxis: function(point, valueAxis) {\n\t var axisCrossingValue = this.categoryAxisCrossingValue(valueAxis);\n\t var value = point.value;\n\n\t return valueAxis.options.reverse ?\n\t value < axisCrossingValue : value >= axisCrossingValue;\n\t },\n\n\t categoryAxisCrossingValue: function(valueAxis) {\n\t var categoryAxis = this.categoryAxis;\n\t var options = valueAxis.options;\n\t var crossingValues = [].concat(\n\t options.axisCrossingValues || options.axisCrossingValue\n\t );\n\n\t return crossingValues[categoryAxis.axisIndex || 0] || 0;\n\t },\n\n\t reflowPoint: function(point, pointSlot) {\n\t point.reflow(pointSlot);\n\t },\n\n\t reflowCategories: function() { },\n\n\t pointSlot: function(categorySlot, valueSlot) {\n\t var options = this.options;\n\t var invertAxes = options.invertAxes;\n\t var slotX = invertAxes ? valueSlot : categorySlot;\n\t var slotY = invertAxes ? categorySlot : valueSlot;\n\n\t return new Box(slotX.x1, slotY.y1, slotX.x2, slotY.y2);\n\t },\n\n\t categorySlot: function(categoryAxis, categoryIx) {\n\t return categoryAxis.getSlot(categoryIx);\n\t },\n\n\t traverseDataPoints: function(callback) {\n\t var this$1 = this;\n\n\t var series = this.options.series;\n\t var count = categoriesCount(series);\n\t var seriesCount = series.length;\n\n\t for (var seriesIx = 0; seriesIx < seriesCount; seriesIx++) {\n\t this$1._outOfRangeCallback(series[seriesIx], \"_outOfRangeMinPoint\", seriesIx, callback);\n\t }\n\n\t for (var categoryIx = 0; categoryIx < count; categoryIx++) {\n\t for (var seriesIx$1 = 0; seriesIx$1 < seriesCount; seriesIx$1++) {\n\t var currentSeries = series[seriesIx$1];\n\t var currentCategory = this$1.categoryAxis.categoryAt(categoryIx);\n\t var pointData = this$1._bindPoint(currentSeries, seriesIx$1, categoryIx);\n\n\t callback(pointData, {\n\t category: currentCategory,\n\t categoryIx: categoryIx,\n\t categoriesCount: count,\n\t series: currentSeries,\n\t seriesIx: seriesIx$1\n\t });\n\t }\n\t }\n\n\t for (var seriesIx$2 = 0; seriesIx$2 < seriesCount; seriesIx$2++) {\n\t this$1._outOfRangeCallback(series[seriesIx$2], \"_outOfRangeMaxPoint\", seriesIx$2, callback);\n\t }\n\t },\n\n\t _outOfRangeCallback: function(series, field, seriesIx, callback) {\n\t var outOfRangePoint = series[field];\n\t if (outOfRangePoint) {\n\t var categoryIx = outOfRangePoint.categoryIx;\n\t var pointData = this._bindPoint(series, seriesIx, categoryIx, outOfRangePoint.item);\n\n\t callback(pointData, {\n\t category: outOfRangePoint.category,\n\t categoryIx: categoryIx,\n\t series: series,\n\t seriesIx: seriesIx,\n\t dataItem: outOfRangePoint.item\n\t });\n\t }\n\t },\n\n\t _bindPoint: function(series, seriesIx, categoryIx, item) {\n\t if (!this._bindCache) {\n\t this._bindCache = [];\n\t }\n\n\t var bindCache = this._bindCache[seriesIx];\n\t if (!bindCache) {\n\t bindCache = this._bindCache[seriesIx] = [];\n\t }\n\n\t var data = bindCache[categoryIx];\n\t if (!data) {\n\t data = bindCache[categoryIx] = SeriesBinder.current.bindPoint(series, categoryIx, item);\n\t }\n\n\t return data;\n\t },\n\n\t formatPointValue: function(point, format) {\n\t if (point.value === null) {\n\t return \"\";\n\t }\n\n\t return this.chartService.format.auto(format, point.value);\n\t },\n\n\t pointValue: function(data) {\n\t return data.valueFields.value;\n\t }\n\t});\n\n\tsetDefaultOptions(CategoricalChart, {\n\t series: [],\n\t invertAxes: false,\n\t isStacked: false,\n\t clip: true,\n\t limitPoints: true\n\t});\n\n\tvar PointEventsMixin = {\n\t click: function(chart, e) {\n\t return chart.trigger(\n\t SERIES_CLICK,\n\t this.eventArgs(e)\n\t );\n\t },\n\n\t hover: function(chart, e) {\n\t return chart.trigger(\n\t SERIES_HOVER,\n\t this.eventArgs(e)\n\t );\n\t },\n\n\t over: function(chart, e) {\n\t return chart.trigger(\n\t SERIES_OVER,\n\t this.eventArgs(e)\n\t );\n\t },\n\n\t out: function(chart, e) {\n\t return chart.trigger(\n\t SERIES_LEAVE,\n\t this.eventArgs(e)\n\t );\n\t },\n\n\t eventArgs: function(e) {\n\t return {\n\t value: this.value,\n\t percentage: this.percentage,\n\t stackValue: this.stackValue,\n\t category: this.category,\n\t series: this.series,\n\t dataItem: this.dataItem,\n\t runningTotal: this.runningTotal,\n\t total: this.total,\n\t element: eventElement(e),\n\t originalEvent: e,\n\t point: this\n\t };\n\t }\n\t};\n\n\tvar NoteMixin = {\n\t createNote: function() {\n\t var options = this.options.notes;\n\t var text = this.noteText || options.label.text;\n\n\t if (options.visible !== false && defined(text) && text !== null) {\n\t this.note = new dataviz.Note({\n\t value: this.value,\n\t text: text,\n\t dataItem: this.dataItem,\n\t category: this.category,\n\t series: this.series\n\t }, this.options.notes, this.owner.chartService);\n\n\t this.append(this.note);\n\t }\n\t }\n\t};\n\n\tvar LinePoint = ChartElement.extend({\n\t init: function(value, options) {\n\t ChartElement.fn.init.call(this);\n\n\t this.value = value;\n\t this.options = options;\n\t this.aboveAxis = valueOrDefault(this.options.aboveAxis, true);\n\t this.tooltipTracking = true;\n\t },\n\n\t render: function() {\n\t var ref = this.options;\n\t var markers = ref.markers;\n\t var labels = ref.labels;\n\n\t if (this._rendered) {\n\t return;\n\t }\n\n\t this._rendered = true;\n\n\t if (markers.visible && markers.size) {\n\t this.marker = this.createMarker();\n\t this.append(this.marker);\n\t }\n\n\t if (labels.visible) {\n\t var labelTemplate = getTemplate(labels);\n\t var pointData = this.pointData();\n\t var labelText = this.value;\n\t if (labelTemplate) {\n\t labelText = labelTemplate(pointData);\n\t } else if (labels.format) {\n\t labelText = this.formatValue(labels.format);\n\t }\n\t this.label = new TextBox(labelText,\n\t deepExtend({\n\t align: CENTER,\n\t vAlign: CENTER,\n\t margin: {\n\t left: 5,\n\t right: 5\n\t },\n\t zIndex: valueOrDefault(labels.zIndex, this.series.zIndex)\n\t }, labels),\n\t pointData\n\t );\n\t this.append(this.label);\n\t }\n\n\t this.createNote();\n\n\t if (this.errorBar) {\n\t this.append(this.errorBar);\n\t }\n\t },\n\n\t markerBorder: function() {\n\t var options = this.options.markers;\n\t var background = options.background;\n\t var border = deepExtend({ color: this.color }, options.border);\n\n\t if (!defined(border.color)) {\n\t border.color = new Color(background).brightness(BORDER_BRIGHTNESS).toHex();\n\t }\n\n\t return border;\n\t },\n\n\t createVisual: function() {},\n\n\t createMarker: function() {\n\t var options = this.options.markers;\n\t var marker = new ShapeElement({\n\t type: options.type,\n\t width: options.size,\n\t height: options.size,\n\t rotation: options.rotation,\n\t background: options.background,\n\t border: this.markerBorder(),\n\t opacity: options.opacity,\n\t zIndex: valueOrDefault(options.zIndex, this.series.zIndex),\n\t animation: options.animation,\n\t visual: options.visual\n\t }, {\n\t dataItem: this.dataItem,\n\t value: this.value,\n\t series: this.series,\n\t category: this.category\n\t });\n\n\t return marker;\n\t },\n\n\t markerBox: function() {\n\t if (!this.marker) {\n\t this.marker = this.createMarker();\n\t this.marker.reflow(this._childBox);\n\t }\n\n\t return this.marker.box;\n\t },\n\n\t reflow: function(targetBox) {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var options = ref.options;\n\t var aboveAxis = ref.aboveAxis;\n\t var vertical = options.vertical;\n\n\t this.render();\n\n\t this.box = targetBox;\n\t var childBox = targetBox.clone();\n\n\t if (vertical) {\n\t if (aboveAxis) {\n\t childBox.y1 -= childBox.height();\n\t } else {\n\t childBox.y2 += childBox.height();\n\t }\n\t } else {\n\t if (aboveAxis) {\n\t childBox.x1 += childBox.width();\n\t } else {\n\t childBox.x2 -= childBox.width();\n\t }\n\t }\n\n\t this._childBox = childBox;\n\t if (this.marker) {\n\t this.marker.reflow(childBox);\n\t }\n\n\t this.reflowLabel(childBox);\n\n\t if (this.errorBars) {\n\t for (var i = 0; i < this.errorBars.length; i++) {\n\t this$1.errorBars[i].reflow(childBox);\n\t }\n\t }\n\n\t if (this.note) {\n\t var noteTargetBox = this.markerBox();\n\n\t if (!(options.markers.visible && options.markers.size)) {\n\t var center = noteTargetBox.center();\n\t noteTargetBox = new Box(center.x, center.y, center.x, center.y);\n\t }\n\n\t this.note.reflow(noteTargetBox);\n\t }\n\t },\n\n\t reflowLabel: function(box) {\n\t var ref = this;\n\t var options = ref.options;\n\t var label = ref.label;\n\t var anchor = options.labels.position;\n\n\t if (label) {\n\t anchor = anchor === ABOVE ? TOP : anchor;\n\t anchor = anchor === BELOW ? BOTTOM : anchor;\n\n\t label.reflow(box);\n\t label.box.alignTo(this.markerBox(), anchor);\n\t label.reflow(label.box);\n\t }\n\t },\n\n\t createHighlight: function() {\n\t var markers = this.options.highlight.markers;\n\t var defaultColor = this.markerBorder().color;\n\t var options = this.options.markers;\n\t var size = options.size + (options.border.width || 0) + (markers.border.width || 0);\n\n\t var shadow = new ShapeElement({\n\t type: options.type,\n\t width: size,\n\t height: size,\n\t rotation: options.rotation,\n\t background: markers.color || defaultColor,\n\t border: {\n\t color: markers.border.color,\n\t width: markers.border.width,\n\t opacity: valueOrDefault(markers.border.opacity, 1)\n\t },\n\t opacity: valueOrDefault(markers.opacity, 1)\n\t });\n\t shadow.reflow(this._childBox);\n\n\t return shadow.getElement();\n\t },\n\n\t highlightVisual: function() {\n\t return (this.marker || {}).visual;\n\t },\n\n\t highlightVisualArgs: function() {\n\t var marker = this.marker;\n\t var visual, rect;\n\n\t if (marker) {\n\t rect = marker.paddingBox.toRect();\n\t visual = marker.visual;\n\t } else {\n\t var size = this.options.markers.size;\n\t var halfSize = size / 2;\n\t var center = this.box.center();\n\t rect = new geometry.Rect([ center.x - halfSize, center.y - halfSize ], [ size, size ]);\n\t }\n\n\t return {\n\t options: this.options,\n\t rect: rect,\n\t visual: visual\n\t };\n\t },\n\n\t tooltipAnchor: function() {\n\t var markerBox = this.markerBox();\n\t var clipBox = this.owner.pane.clipBox();\n\t var showTooltip = !clipBox || clipBox.overlaps(markerBox);\n\n\t if (showTooltip) {\n\t var x = markerBox.x2 + TOOLTIP_OFFSET;\n\t var horizontalAlign = LEFT;\n\t var y, verticalAlign;\n\n\t if (this.aboveAxis) {\n\t y = markerBox.y1;\n\t verticalAlign = BOTTOM;\n\t } else {\n\t y = markerBox.y2;\n\t verticalAlign = TOP;\n\t }\n\n\t return {\n\t point: new Point(x, y),\n\t align: {\n\t horizontal: horizontalAlign,\n\t vertical: verticalAlign\n\t }\n\t };\n\t }\n\t },\n\n\t formatValue: function(format) {\n\t return this.owner.formatPointValue(this, format);\n\t },\n\n\t overlapsBox: function(box) {\n\t var markerBox = this.markerBox();\n\t return markerBox.overlaps(box);\n\t },\n\n\t unclipElements: function() {\n\t if (this.label) {\n\t this.label.options.noclip = true;\n\t }\n\n\t if (this.note) {\n\t this.note.options.noclip = true;\n\t }\n\t },\n\n\t pointData: function() {\n\t return {\n\t dataItem: this.dataItem,\n\t category: this.category,\n\t value: this.value,\n\t percentage: this.percentage,\n\t stackValue: this.stackValue,\n\t series: this.series\n\t };\n\t }\n\t});\n\n\tLinePoint.prototype.defaults = {\n\t vertical: true,\n\t markers: {\n\t visible: true,\n\t background: WHITE,\n\t size: LINE_MARKER_SIZE,\n\t type: CIRCLE,\n\t border: {\n\t width: 2\n\t },\n\t opacity: 1\n\t },\n\t labels: {\n\t visible: false,\n\t position: ABOVE,\n\t margin: getSpacing(3),\n\t padding: getSpacing(4),\n\t animation: {\n\t type: FADEIN,\n\t delay: INITIAL_ANIMATION_DURATION\n\t }\n\t },\n\t notes: {\n\t label: {}\n\t },\n\t highlight: {\n\t markers: {\n\t border: {\n\t color: \"#fff\",\n\t width: 2\n\t }\n\t },\n\t zIndex: datavizConstants.HIGHLIGHT_ZINDEX\n\t },\n\t errorBars: {\n\t line: {\n\t width: 1\n\t }\n\t }\n\t};\n\n\tdeepExtend(LinePoint.prototype, PointEventsMixin);\n\tdeepExtend(LinePoint.prototype, NoteMixin);\n\n\tvar LineSegment = ChartElement.extend({\n\t init: function(linePoints, series, seriesIx) {\n\t ChartElement.fn.init.call(this);\n\n\t this.linePoints = linePoints;\n\t this.series = series;\n\t this.seriesIx = seriesIx;\n\t },\n\n\t points: function() {\n\t return this.toGeometryPoints(this.linePoints);\n\t },\n\n\t toGeometryPoints: function(points) {\n\t var result = [];\n\t for (var i = 0, length = points.length; i < length; i++) {\n\t if (points[i] && points[i].visible !== false) {\n\t result.push(points[i]._childBox.toRect().center());\n\t }\n\t }\n\n\t return result;\n\t },\n\n\t createVisual: function() {\n\t var this$1 = this;\n\n\t var customVisual = this.series.visual;\n\t if (customVisual) {\n\t this.visual = customVisual({\n\t points: this.toGeometryPoints(this.linePoints),\n\t series: this.series,\n\t sender: this.getSender(),\n\t createVisual: function () {\n\t this$1.segmentVisual();\n\n\t return this$1.visual;\n\t }\n\t });\n\t if (this.visual && !defined(this.visual.options.zIndex)) {\n\t this.visual.options.zIndex = this.series.zIndex;\n\t }\n\t } else {\n\t this.segmentVisual();\n\t }\n\t },\n\n\t segmentVisual: function() {\n\t var ref = this;\n\t var options = ref.options;\n\t var series = ref.series;\n\t var color = series.color;\n\t var defaults = series._defaults;\n\n\t if (isFunction(color) && defaults) {\n\t color = defaults.color;\n\t }\n\n\t var line = Path.fromPoints(this.points(), {\n\t stroke: {\n\t color: color,\n\t width: series.width,\n\t opacity: series.opacity,\n\t dashType: series.dashType\n\t },\n\t zIndex: series.zIndex\n\t });\n\n\t if (options.closed) {\n\t line.close();\n\t }\n\n\t this.visual = line;\n\t },\n\n\t aliasFor: function(e, coords) {\n\t return this.parent.getNearestPoint(coords.x, coords.y, this.seriesIx);\n\t }\n\t});\n\n\tsetDefaultOptions(LineSegment, {\n\t closed: false\n\t});\n\n\tvar StepLineMixin = {\n\t calculateStepPoints: function(points) {\n\t var categoryAxis = this.parent.plotArea.seriesCategoryAxis(this.series);\n\t var ref = categoryAxis.options;\n\t var justified = ref.justified;\n\t var vertical = ref.vertical;\n\t var reverse = ref.reverse;\n\n\t var stepAxis = vertical ? X : Y;\n\t var axis = vertical ? Y : X;\n\t var stepDir = reverse ? 2 : 1;\n\t var dir = stepDir;\n\n\t var previousPoint = toGeometryPoint(points[0], stepAxis, stepDir, axis, dir);\n\t var result = [ previousPoint ];\n\n\t for (var idx = 1; idx < points.length; idx++) {\n\t var point = toGeometryPoint(points[idx], stepAxis, stepDir, axis, dir);\n\n\t if (previousPoint[stepAxis] !== point[stepAxis]) {\n\t var stepPoint = new GeometryPoint();\n\t stepPoint[stepAxis] = previousPoint[stepAxis];\n\t stepPoint[axis] = point[axis];\n\n\t result.push(stepPoint, point);\n\t }\n\n\t previousPoint = point;\n\t }\n\n\t if (!justified) {\n\t result.push(toGeometryPoint(last(points), stepAxis, stepDir, axis, reverse ? 1 : 2));\n\t } else if (previousPoint !== last(result)) {\n\t result.push(previousPoint);\n\t }\n\n\t return result;\n\n\t }\n\t};\n\n\tfunction toGeometryPoint(lintPoint, stepAxis, stepDir, axis, dir) {\n\t var box = lintPoint.box;\n\t var result = new GeometryPoint();\n\n\t result[stepAxis] = box[stepAxis + stepDir];\n\t result[axis] = box[axis + dir];\n\n\t return result;\n\t}\n\n\tvar StepLineSegment = LineSegment.extend({\n\t points: function() {\n\t return this.calculateStepPoints(this.linePoints);\n\t }\n\t});\n\n\tdeepExtend(StepLineSegment.prototype, StepLineMixin);\n\n\tvar SplineSegment = LineSegment.extend({\n\t segmentVisual: function() {\n\t var series = this.series;\n\t var defaults = series._defaults;\n\t var color = series.color;\n\n\t if (isFunction(color) && defaults) {\n\t color = defaults.color;\n\t }\n\n\t var curveProcessor = new CurveProcessor(this.options.closed);\n\t var segments = curveProcessor.process(this.points());\n\t var curve = new Path({\n\t stroke: {\n\t color: color,\n\t width: series.width,\n\t opacity: series.opacity,\n\t dashType: series.dashType\n\t },\n\t zIndex: series.zIndex\n\t });\n\n\t curve.segments.push.apply(curve.segments, segments);\n\n\t this.visual = curve;\n\t }\n\t});\n\n\tvar LineChartMixin = {\n\t renderSegments: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var options = ref.options;\n\t var seriesPoints = ref.seriesPoints;\n\t var series = options.series;\n\t var seriesCount = seriesPoints.length;\n\t var lastSegment;\n\n\t this._segments = [];\n\n\t for (var seriesIx = 0; seriesIx < seriesCount; seriesIx++) {\n\t var currentSeries = series[seriesIx];\n\t var sortedPoints = this$1.sortPoints(seriesPoints[seriesIx]);\n\t var pointCount = sortedPoints.length;\n\t var linePoints = [];\n\n\t for (var pointIx = 0; pointIx < pointCount; pointIx++) {\n\t var point = sortedPoints[pointIx];\n\t if (point) {\n\t linePoints.push(point);\n\t } else if (this$1.seriesMissingValues(currentSeries) !== INTERPOLATE) {\n\t if (linePoints.length > 1) {\n\t lastSegment = this$1.createSegment(\n\t linePoints, currentSeries, seriesIx, lastSegment\n\t );\n\t this$1._addSegment(lastSegment);\n\t }\n\t linePoints = [];\n\t }\n\t }\n\n\t if (linePoints.length > 1) {\n\t lastSegment = this$1.createSegment(\n\t linePoints, currentSeries, seriesIx, lastSegment\n\t );\n\t this$1._addSegment(lastSegment);\n\t }\n\t }\n\n\t this.children.unshift.apply(this.children, this._segments);\n\t },\n\n\t _addSegment: function(segment) {\n\t this._segments.push(segment);\n\t segment.parent = this;\n\t },\n\n\t sortPoints: function(points) {\n\t return points;\n\t },\n\n\t seriesMissingValues: function(series) {\n\t var missingValues = series.missingValues;\n\t var assumeZero = !missingValues && this.options.isStacked;\n\n\t return assumeZero ? ZERO : missingValues || INTERPOLATE;\n\t },\n\n\t getNearestPoint: function(x, y, seriesIx) {\n\t var target = new Point(x, y);\n\t var allPoints = this.seriesPoints[seriesIx];\n\t var nearestPointDistance = MAX_VALUE;\n\t var nearestPoint;\n\n\t for (var i = 0; i < allPoints.length; i++) {\n\t var point = allPoints[i];\n\n\t if (point && defined(point.value) && point.value !== null && point.visible !== false) {\n\t var pointBox = point.box;\n\t var pointDistance = pointBox.center().distanceTo(target);\n\n\t if (pointDistance < nearestPointDistance) {\n\t nearestPoint = point;\n\t nearestPointDistance = pointDistance;\n\t }\n\t }\n\t }\n\n\t return nearestPoint;\n\t }\n\t};\n\n\tvar ClipAnimation = Animation.extend({\n\t setup: function() {\n\t this._setEnd(this.options.box.x1);\n\t },\n\n\t step: function(pos) {\n\t var box = this.options.box;\n\t this._setEnd(dataviz.interpolateValue(box.x1, box.x2, pos));\n\t },\n\n\t _setEnd: function(x) {\n\t var element = this.element;\n\t var segments = element.segments;\n\t var topRight = segments[1].anchor();\n\t var bottomRight = segments[2].anchor();\n\n\t element.suspend();\n\t topRight.setX(x);\n\t element.resume();\n\t bottomRight.setX(x);\n\t }\n\t});\n\n\tsetDefaultOptions(ClipAnimation, {\n\t duration: INITIAL_ANIMATION_DURATION\n\t});\n\n\tAnimationFactory.current.register(\"clip\", ClipAnimation);\n\n\tfunction anyHasZIndex(elements) {\n\t for (var idx = 0; idx < elements.length; idx++) {\n\t if (defined(elements[idx].zIndex)) {\n\t return true;\n\t }\n\t }\n\t}\n\n\tvar ClipAnimationMixin = {\n\t createAnimation: function() {\n\t var root = this.getRoot();\n\t if (root && (root.options || {}).transitions !== false) {\n\t var box = root.size();\n\t var clipPath = Path.fromRect(box.toRect());\n\t this.visual.clip(clipPath);\n\t this.animation = new ClipAnimation(clipPath, {\n\t box: box\n\t });\n\t if (anyHasZIndex(this.options.series)) {\n\t this._setChildrenAnimation(clipPath);\n\t }\n\t }\n\t },\n\n\t _setChildrenAnimation: function(clipPath) {\n\t var points = this.animationPoints();\n\n\t for (var idx = 0; idx < points.length; idx++) {\n\t var point = points[idx];\n\t if (point && point.visual && defined(point.visual.options.zIndex)) {\n\t point.visual.clip(clipPath);\n\t }\n\t }\n\t }\n\t};\n\n\tvar LineChart = CategoricalChart.extend({\n\t render: function() {\n\n\t CategoricalChart.fn.render.call(this);\n\n\t this.updateStackRange();\n\t this.renderSegments();\n\t },\n\n\t pointType: function() {\n\t return LinePoint;\n\t },\n\n\t createPoint: function(data, fields) {\n\t var categoryIx = fields.categoryIx;\n\t var category = fields.category;\n\t var series = fields.series;\n\t var seriesIx = fields.seriesIx;\n\t var missingValues = this.seriesMissingValues(series);\n\t var value = data.valueFields.value;\n\n\t if (!defined(value) || value === null) {\n\t if (missingValues === ZERO) {\n\t value = 0;\n\t } else {\n\t return null;\n\t }\n\t }\n\n\t var pointOptions = this.pointOptions(series, seriesIx);\n\t pointOptions = this.evalPointOptions(\n\t pointOptions, value, category, categoryIx, series, seriesIx\n\t );\n\n\t var color = data.fields.color || series.color;\n\t if (isFunction(series.color)) {\n\t color = pointOptions.color;\n\t }\n\n\t var point = new LinePoint(value, pointOptions);\n\t point.color = color;\n\n\t this.append(point);\n\n\t return point;\n\t },\n\n\t plotRange: function(point) {\n\t var this$1 = this;\n\n\t var plotValue = this.plotValue(point);\n\n\t if (this.options.isStacked) {\n\t var categoryIx = point.categoryIx;\n\t var categoryPoints = this.categoryPoints[categoryIx];\n\n\t for (var i = 0; i < categoryPoints.length; i++) {\n\t var other = categoryPoints[i];\n\n\t if (point === other) {\n\t break;\n\t }\n\n\t plotValue += this$1.plotValue(other);\n\n\t if (this$1.options.isStacked100) {\n\t plotValue = Math.min(plotValue, 1);\n\t }\n\t }\n\n\t }\n\n\t return [ plotValue, plotValue ];\n\t },\n\n\t createSegment: function(linePoints, currentSeries, seriesIx) {\n\t var style = currentSeries.style;\n\t var pointType;\n\n\t if (style === STEP) {\n\t pointType = StepLineSegment;\n\t } else if (style === SMOOTH) {\n\t pointType = SplineSegment;\n\t } else {\n\t pointType = LineSegment;\n\t }\n\n\t return new pointType(linePoints, currentSeries, seriesIx);\n\t },\n\n\t animationPoints: function() {\n\t var points = this.points;\n\t var result = [];\n\t for (var idx = 0; idx < points.length; idx++) {\n\t result.push((points[idx] || {}).marker);\n\t }\n\t return result.concat(this._segments);\n\t }\n\t});\n\n\tdeepExtend(LineChart.prototype, LineChartMixin, ClipAnimationMixin);\n\n\tvar AreaSegment = LineSegment.extend({\n\t init: function(linePoints, currentSeries, seriesIx, prevSegment, stackPoints) {\n\t LineSegment.fn.init.call(this, linePoints, currentSeries, seriesIx);\n\n\t this.prevSegment = prevSegment;\n\t this.stackPoints = stackPoints;\n\t },\n\n\t createVisual: function() {\n\t var series = this.series;\n\t var defaults = series._defaults;\n\t var lineOptions = series.line || {};\n\t var color = series.color;\n\n\t if (isFunction(color) && defaults) {\n\t color = defaults.color;\n\t }\n\n\t this.visual = new Group({\n\t zIndex: series.zIndex\n\t });\n\n\t this.createFill({\n\t fill: {\n\t color: color,\n\t opacity: series.opacity\n\t },\n\t stroke: null\n\t });\n\n\t if (lineOptions.width > 0 && lineOptions.visible !== false) {\n\t this.createStroke({\n\t stroke: deepExtend({\n\t color: color,\n\t opacity: series.opacity,\n\t lineCap: \"butt\"\n\t }, lineOptions)\n\t });\n\t }\n\t },\n\n\t strokeSegments: function() {\n\t var segments = this._strokeSegments;\n\n\t if (!segments) {\n\t segments = this._strokeSegments = this.createStrokeSegments();\n\t }\n\n\t return segments;\n\t },\n\n\t createStrokeSegments: function() {\n\t return this.segmentsFromPoints(this.points());\n\t },\n\n\t stackSegments: function() {\n\t if (this.prevSegment) {\n\t return this.prevSegment.createStackSegments(this.stackPoints);\n\t }\n\n\t return this.createStackSegments(this.stackPoints);\n\t },\n\n\t createStackSegments: function(stackPoints) {\n\t return this.segmentsFromPoints(this.toGeometryPoints(stackPoints)).reverse();\n\t },\n\n\t segmentsFromPoints: function(points) {\n\t return points.map(function (point) { return new geometry.Segment(point); });\n\t },\n\n\t createStroke: function(style) {\n\t var stroke = new Path(style);\n\t stroke.segments.push.apply(stroke.segments, this.strokeSegments());\n\n\t this.visual.append(stroke);\n\t },\n\n\t hasStackSegment: function() {\n\t return this.prevSegment || (this.stackPoints && this.stackPoints.length);\n\t },\n\n\t createFill: function(style) {\n\t var strokeSegments = this.strokeSegments();\n\t var fillSegments = strokeSegments.slice(0);\n\t var hasStackSegments = this.hasStackSegment();\n\n\t if (hasStackSegments) {\n\t var stackSegments = this.stackSegments();\n\n\t append(fillSegments, stackSegments);\n\t }\n\n\t var fill = new Path(style);\n\t fill.segments.push.apply(fill.segments, fillSegments);\n\n\t if (!hasStackSegments && strokeSegments.length > 1) {\n\t this.fillToAxes(fill);\n\t }\n\n\t this.visual.append(fill);\n\t },\n\n\t fillToAxes: function(fillPath) {\n\t var chart = this.parent;\n\t var invertAxes = chart.options.invertAxes;\n\t var valueAxis = chart.seriesValueAxis(this.series);\n\t var crossingValue = chart.categoryAxisCrossingValue(valueAxis);\n\t var endSlot = valueAxis.getSlot(crossingValue, crossingValue, true);\n\t var segments = this.strokeSegments();\n\t var firstPoint = segments[0].anchor();\n\t var lastPoint = last(segments).anchor();\n\t var end = invertAxes ? endSlot.x1 : endSlot.y1;\n\n\t if (invertAxes) {\n\t fillPath.lineTo(end, lastPoint.y)\n\t .lineTo(end, firstPoint.y);\n\t } else {\n\t fillPath.lineTo(lastPoint.x, end)\n\t .lineTo(firstPoint.x, end);\n\t }\n\t }\n\t});\n\n\tvar StepAreaSegment = AreaSegment.extend({\n\t createStrokeSegments: function() {\n\t return this.segmentsFromPoints(this.calculateStepPoints(this.linePoints));\n\t },\n\n\t createStackSegments: function(stackPoints) {\n\t return this.segmentsFromPoints(this.calculateStepPoints(stackPoints)).reverse();\n\t }\n\t});\n\n\tdeepExtend(StepAreaSegment.prototype, StepLineMixin);\n\n\tvar SplineAreaSegment = AreaSegment.extend({\n\t createStrokeSegments: function() {\n\t var curveProcessor = new CurveProcessor(this.options.closed);\n\t var linePoints = this.points();\n\n\t return curveProcessor.process(linePoints);\n\t },\n\n\t createStackSegments: function() {\n\t var strokeSegments = this.strokeSegments();\n\t var stackSegments = [];\n\t for (var idx = strokeSegments.length - 1; idx >= 0; idx--) {\n\t var segment = strokeSegments[idx];\n\t stackSegments.push(new geometry.Segment(\n\t segment.anchor(),\n\t segment.controlOut(),\n\t segment.controlIn()\n\t ));\n\t }\n\n\t return stackSegments;\n\t }\n\t});\n\n\tvar AreaChart = LineChart.extend({\n\t createSegment: function(linePoints, currentSeries, seriesIx, prevSegment) {\n\t var isStacked = this.options.isStacked;\n\t var style = (currentSeries.line || {}).style;\n\t var previousSegment;\n\n\t var stackPoints;\n\t if (isStacked && seriesIx > 0 && prevSegment) {\n\t var missingValues = this.seriesMissingValues(currentSeries);\n\t if (missingValues !== \"gap\") {\n\t stackPoints = prevSegment.linePoints;\n\t previousSegment = prevSegment;\n\t } else {\n\t stackPoints = this._gapStackPoints(linePoints, seriesIx, style);\n\t }\n\t }\n\n\t var pointType;\n\t if (style === STEP) {\n\t pointType = StepAreaSegment;\n\t } else if (style === SMOOTH) {\n\t pointType = SplineAreaSegment;\n\t } else {\n\t pointType = AreaSegment;\n\t }\n\n\t return new pointType(linePoints, currentSeries, seriesIx, previousSegment, stackPoints);\n\t },\n\n\t reflow: function(targetBox) {\n\t var this$1 = this;\n\n\t LineChart.fn.reflow.call(this, targetBox);\n\n\t var stackPoints = this._stackPoints;\n\t if (stackPoints) {\n\t for (var idx = 0; idx < stackPoints.length; idx++) {\n\t var stackPoint = stackPoints[idx];\n\t var pointSlot = this$1.categoryAxis.getSlot(stackPoint.categoryIx);\n\t stackPoint.reflow(pointSlot);\n\t }\n\t }\n\t },\n\n\t _gapStackPoints: function(linePoints, seriesIx, style) {\n\t var this$1 = this;\n\n\t var seriesPoints = this.seriesPoints;\n\t var startIdx = linePoints[0].categoryIx;\n\t var length = linePoints.length;\n\t if (startIdx < 0) {\n\t startIdx = 0;\n\t length--;\n\t }\n\n\t var endIdx = startIdx + length;\n\t var pointOffset = this.seriesOptions[0]._outOfRangeMinPoint ? 1 : 0;\n\t var stackPoints = [];\n\n\t this._stackPoints = this._stackPoints || [];\n\t for (var categoryIx = startIdx; categoryIx < endIdx; categoryIx++) {\n\t var pointIx = categoryIx + pointOffset;\n\t var currentSeriesIx = seriesIx;\n\t var point = (void 0);\n\n\t do {\n\t currentSeriesIx--;\n\t point = seriesPoints[currentSeriesIx][pointIx];\n\t } while (currentSeriesIx > 0 && !point);\n\n\t if (point) {\n\t if (style !== STEP && categoryIx > startIdx && !seriesPoints[currentSeriesIx][pointIx - 1]) {\n\t stackPoints.push(this$1._previousSegmentPoint(categoryIx, pointIx, pointIx - 1, currentSeriesIx));\n\t }\n\n\t stackPoints.push(point);\n\n\t if (style !== STEP && categoryIx + 1 < endIdx && !seriesPoints[currentSeriesIx][pointIx + 1]) {\n\t stackPoints.push(this$1._previousSegmentPoint(categoryIx, pointIx, pointIx + 1, currentSeriesIx));\n\t }\n\t } else {\n\t var gapStackPoint = this$1._createGapStackPoint(categoryIx);\n\t this$1._stackPoints.push(gapStackPoint);\n\t stackPoints.push(gapStackPoint);\n\t }\n\t }\n\n\t return stackPoints;\n\t },\n\n\t _previousSegmentPoint: function(categoryIx, pointIx, segmentIx, seriesIdx) {\n\t var seriesPoints = this.seriesPoints;\n\t var index = seriesIdx;\n\t var point;\n\n\t while (index > 0 && !point) {\n\t index--;\n\t point = seriesPoints[index][segmentIx];\n\t }\n\n\t if (!point) {\n\t point = this._createGapStackPoint(categoryIx);\n\t this._stackPoints.push(point);\n\t } else {\n\t point = seriesPoints[index][pointIx];\n\t }\n\n\t return point;\n\t },\n\n\t _createGapStackPoint: function(categoryIx) {\n\t var options = this.pointOptions({}, 0);\n\t var point = new LinePoint(0, options);\n\t point.categoryIx = categoryIx;\n\t point.series = {};\n\n\t return point;\n\t },\n\n\t seriesMissingValues: function(series) {\n\t return series.missingValues || ZERO;\n\t }\n\t});\n\n\tvar AxisGroupRangeTracker = Class.extend({\n\t init: function() {\n\n\t this.axisRanges = {};\n\t },\n\n\t update: function(chartAxisRanges) {\n\t var axisRanges = this.axisRanges;\n\n\t for (var axisName in chartAxisRanges) {\n\t var chartRange = chartAxisRanges[axisName];\n\t var range = axisRanges[axisName];\n\t axisRanges[axisName] = range = range || { min: MAX_VALUE, max: MIN_VALUE };\n\n\t range.min = Math.min(range.min, chartRange.min);\n\t range.max = Math.max(range.max, chartRange.max);\n\t }\n\t },\n\n\t reset: function(axisName) {\n\t this.axisRanges[axisName] = undefined;\n\t },\n\n\t query: function(axisName) {\n\t return this.axisRanges[axisName];\n\t }\n\t});\n\n\tvar BarLabel = ChartElement.extend({\n\t init: function(content, options, pointData) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.textBox = new TextBox(content, this.options, pointData);\n\t this.append(this.textBox);\n\t },\n\n\t createVisual: function() {\n\t this.textBox.options.noclip = this.options.noclip;\n\t },\n\n\t reflow: function(targetBox) {\n\t var options = this.options;\n\t var vertical = options.vertical;\n\t var aboveAxis = options.aboveAxis;\n\t var text = this.children[0];\n\t var textOptions = text.options;\n\t var box = text.box;\n\t var padding = text.options.padding;\n\t var labelBox = targetBox;\n\n\t textOptions.align = vertical ? CENTER : LEFT;\n\t textOptions.vAlign = vertical ? TOP : CENTER;\n\n\t if (options.position === INSIDE_END) {\n\t if (vertical) {\n\t textOptions.vAlign = TOP;\n\n\t if (!aboveAxis && box.height() < targetBox.height()) {\n\t textOptions.vAlign = BOTTOM;\n\t }\n\t } else {\n\t textOptions.align = aboveAxis ? RIGHT : LEFT;\n\t }\n\t } else if (options.position === CENTER) {\n\t textOptions.vAlign = CENTER;\n\t textOptions.align = CENTER;\n\t } else if (options.position === INSIDE_BASE) {\n\t if (vertical) {\n\t textOptions.vAlign = aboveAxis ? BOTTOM : TOP;\n\t } else {\n\t textOptions.align = aboveAxis ? LEFT : RIGHT;\n\t }\n\t } else if (options.position === OUTSIDE_END) {\n\t if (vertical) {\n\t if (aboveAxis) {\n\t labelBox = new Box(\n\t targetBox.x1, targetBox.y1 - box.height(),\n\t targetBox.x2, targetBox.y1\n\t );\n\t } else {\n\t labelBox = new Box(\n\t targetBox.x1, targetBox.y2,\n\t targetBox.x2, targetBox.y2 + box.height()\n\t );\n\t }\n\t } else {\n\t textOptions.align = CENTER;\n\t if (aboveAxis) {\n\t labelBox = new Box(\n\t targetBox.x2, targetBox.y1,\n\t targetBox.x2 + box.width(), targetBox.y2\n\t );\n\t } else {\n\t labelBox = new Box(\n\t targetBox.x1 - box.width(), targetBox.y1,\n\t targetBox.x1, targetBox.y2\n\t );\n\t }\n\t }\n\t }\n\n\t if (!options.rotation) {\n\t if (vertical) {\n\t padding.left = padding.right =\n\t (labelBox.width() - text.contentBox.width()) / 2;\n\t } else {\n\t padding.top = padding.bottom =\n\t (labelBox.height() - text.contentBox.height()) / 2;\n\t }\n\t }\n\n\t text.reflow(labelBox);\n\t },\n\n\t alignToClipBox: function(clipBox) {\n\t var vertical = this.options.vertical;\n\t var field = vertical ? Y : X;\n\t var start = field + \"1\";\n\t var end = field + \"2\";\n\t var text = this.children[0];\n\t var parentBox = this.parent.box;\n\n\t if (parentBox[start] < clipBox[start] || clipBox[end] < parentBox[end]) {\n\t var targetBox = text.paddingBox.clone();\n\t targetBox[start] = Math.max(parentBox[start], clipBox[start]);\n\t targetBox[end] = Math.min(parentBox[end], clipBox[end]);\n\n\t this.reflow(targetBox);\n\t }\n\t }\n\t});\n\n\tsetDefaultOptions(BarLabel, {\n\t position: OUTSIDE_END,\n\t margin: getSpacing(3),\n\t padding: getSpacing(4),\n\t color: BLACK,\n\t background: \"\",\n\t border: {\n\t width: 1,\n\t color: \"\"\n\t },\n\t aboveAxis: true,\n\t vertical: false,\n\t animation: {\n\t type: FADEIN,\n\t delay: INITIAL_ANIMATION_DURATION\n\t },\n\t zIndex: 2\n\t});\n\n\tfunction hasGradientOverlay(options) {\n\t var overlay = options.overlay;\n\n\t return overlay && overlay.gradient && overlay.gradient !== \"none\";\n\t}\n\n\tvar BAR_ALIGN_MIN_WIDTH = 6;\n\n\tvar Bar = ChartElement.extend({\n\t init: function(value, options) {\n\t ChartElement.fn.init.call(this);\n\n\t this.options = options;\n\t this.color = options.color || WHITE;\n\t this.aboveAxis = valueOrDefault(this.options.aboveAxis, true);\n\t this.value = value;\n\t },\n\n\t render: function() {\n\t if (this._rendered) {\n\t return;\n\t }\n\n\t this._rendered = true;\n\n\t this.createLabel();\n\t this.createNote();\n\n\t if (this.errorBar) {\n\t this.append(this.errorBar);\n\t }\n\t },\n\n\t createLabel: function() {\n\t var options = this.options;\n\t var labels = options.labels;\n\n\t if (labels.visible) {\n\t var pointData = this.pointData();\n\t var labelTemplate = getTemplate(labels);\n\t var labelText;\n\n\t if (labelTemplate) {\n\t labelText = labelTemplate(pointData);\n\t } else {\n\t labelText = this.formatValue(labels.format);\n\t }\n\n\t this.label = new BarLabel(labelText,\n\t deepExtend({\n\t vertical: options.vertical\n\t },\n\t labels\n\t ), pointData);\n\t this.append(this.label);\n\t }\n\t },\n\n\t formatValue: function(format) {\n\t return this.owner.formatPointValue(this, format);\n\t },\n\n\t reflow: function(targetBox) {\n\t var this$1 = this;\n\n\t this.render();\n\n\t var label = this.label;\n\n\t this.box = targetBox;\n\n\t if (label) {\n\t label.options.aboveAxis = this.aboveAxis;\n\t label.reflow(targetBox);\n\t }\n\n\t if (this.note) {\n\t this.note.reflow(targetBox);\n\t }\n\n\t if (this.errorBars) {\n\t for (var i = 0; i < this.errorBars.length; i++) {\n\t this$1.errorBars[i].reflow(targetBox);\n\t }\n\t }\n\t },\n\n\t createVisual: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var box = ref.box;\n\t var options = ref.options;\n\t var customVisual = options.visual;\n\n\t if (this.visible !== false) {\n\t ChartElement.fn.createVisual.call(this);\n\n\t if (customVisual) {\n\t var visual = this.rectVisual = customVisual({\n\t category: this.category,\n\t dataItem: this.dataItem,\n\t value: this.value,\n\t sender: this.getSender(),\n\t series: this.series,\n\t percentage: this.percentage,\n\t stackValue: this.stackValue,\n\t runningTotal: this.runningTotal,\n\t total: this.total,\n\t rect: box.toRect(),\n\t createVisual: function () {\n\t var group = new Group();\n\t this$1.createRect(group);\n\t return group;\n\t },\n\t options: options\n\t });\n\n\t if (visual) {\n\t this.visual.append(visual);\n\t }\n\t } else if (box.width() > 0 && box.height() > 0) {\n\t this.createRect(this.visual);\n\t }\n\t }\n\t },\n\n\t createRect: function(visual) {\n\t var options = this.options;\n\t var border = options.border;\n\t var strokeOpacity = defined(border.opacity) ? border.opacity : options.opacity;\n\t var rect = this.box.toRect();\n\n\t rect.size.width = Math.round(rect.size.width);\n\n\t var path = this.rectVisual = Path.fromRect(rect, {\n\t fill: {\n\t color: this.color,\n\t opacity: options.opacity\n\t },\n\t stroke: {\n\t color: this.getBorderColor(),\n\t width: border.width,\n\t opacity: strokeOpacity,\n\t dashType: border.dashType\n\t }\n\t });\n\n\t var width = this.box.width();\n\t var height = this.box.height();\n\n\t var size = options.vertical ? width : height;\n\n\t if (size > BAR_ALIGN_MIN_WIDTH) {\n\t alignPathToPixel(path);\n\n\t // Fixes lineJoin issue in firefox when the joined lines are parallel\n\t if (width < 1 || height < 1) {\n\t path.options.stroke.lineJoin = \"round\";\n\t }\n\t }\n\n\t visual.append(path);\n\n\t if (hasGradientOverlay(options)) {\n\t var overlay = this.createGradientOverlay(path, { baseColor: this.color }, deepExtend({\n\t end: !options.vertical ? [ 0, 1 ] : undefined\n\t }, options.overlay));\n\n\t visual.append(overlay);\n\t }\n\t },\n\n\t createHighlight: function(style) {\n\t var highlight = Path.fromRect(this.box.toRect(), style);\n\n\t return alignPathToPixel(highlight);\n\t },\n\n\t highlightVisual: function() {\n\t return this.rectVisual;\n\t },\n\n\t highlightVisualArgs: function() {\n\t return {\n\t options: this.options,\n\t rect: this.box.toRect(),\n\t visual: this.rectVisual\n\t };\n\t },\n\n\t getBorderColor: function() {\n\t var color = this.color;\n\t var border = this.options.border;\n\t var brightness = border._brightness || BORDER_BRIGHTNESS;\n\t var borderColor = border.color;\n\n\t if (!defined(borderColor)) {\n\t borderColor = new Color(color).brightness(brightness).toHex();\n\t }\n\n\t return borderColor;\n\t },\n\n\t tooltipAnchor: function() {\n\t var ref = this;\n\t var options = ref.options;\n\t var box = ref.box;\n\t var aboveAxis = ref.aboveAxis;\n\t var clipBox = this.owner.pane.clipBox() || box;\n\t var horizontalAlign = LEFT;\n\t var verticalAlign = TOP;\n\t var x, y;\n\n\t if (options.vertical) {\n\t x = Math.min(box.x2, clipBox.x2) + TOOLTIP_OFFSET;\n\t if (aboveAxis) {\n\t y = Math.max(box.y1, clipBox.y1);\n\t } else {\n\t y = Math.min(box.y2, clipBox.y2);\n\t verticalAlign = BOTTOM;\n\t }\n\t } else {\n\t var x1 = Math.max(box.x1, clipBox.x1);\n\t var x2 = Math.min(box.x2, clipBox.x2);\n\n\t if (options.isStacked) {\n\t verticalAlign = BOTTOM;\n\t if (aboveAxis) {\n\t horizontalAlign = RIGHT;\n\t x = x2;\n\t } else {\n\t x = x1;\n\t }\n\t y = Math.max(box.y1, clipBox.y1) - TOOLTIP_OFFSET;\n\t } else {\n\t if (aboveAxis) {\n\t x = x2 + TOOLTIP_OFFSET;\n\t } else {\n\t x = x1 - TOOLTIP_OFFSET;\n\t horizontalAlign = RIGHT;\n\t }\n\t y = Math.max(box.y1, clipBox.y1);\n\t }\n\t }\n\n\t return {\n\t point: new Point(x, y),\n\t align: {\n\t horizontal: horizontalAlign,\n\t vertical: verticalAlign\n\t }\n\t };\n\t },\n\n\t overlapsBox: function(box) {\n\t return this.box.overlaps(box);\n\t },\n\n\t pointData: function() {\n\t return {\n\t dataItem: this.dataItem,\n\t category: this.category,\n\t value: this.value,\n\t percentage: this.percentage,\n\t stackValue: this.stackValue,\n\t runningTotal: this.runningTotal,\n\t total: this.total,\n\t series: this.series\n\t };\n\t }\n\t});\n\n\tdeepExtend(Bar.prototype, PointEventsMixin);\n\tdeepExtend(Bar.prototype, NoteMixin);\n\n\tBar.prototype.defaults = {\n\t border: {\n\t width: 1\n\t },\n\t vertical: true,\n\t overlay: {\n\t gradient: \"glass\"\n\t },\n\t labels: {\n\t visible: false,\n\t format: \"{0}\"\n\t },\n\t opacity: 1,\n\t notes: {\n\t label: {}\n\t }\n\t};\n\n\tfunction forEach(elements, callback) {\n\t elements.forEach(callback);\n\t}\n\n\tfunction forEachReverse(elements, callback) {\n\t var length = elements.length;\n\n\t for (var idx = length - 1; idx >= 0; idx--) {\n\t callback(elements[idx], idx - length - 1);\n\t }\n\t}\n\n\tvar ClusterLayout = ChartElement.extend({\n\t init: function(options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.forEach = options.rtl ? forEachReverse : forEach;\n\t },\n\n\t reflow: function(box) {\n\t var ref = this.options;\n\t var vertical = ref.vertical;\n\t var gap = ref.gap;\n\t var spacing = ref.spacing;\n\t var children = this.children;\n\t var count = children.length;\n\t var axis = vertical ? Y : X;\n\t var slots = count + gap + (spacing * (count - 1));\n\t var slotSize = (vertical ? box.height() : box.width()) / slots;\n\t var position = box[axis + 1] + slotSize * (gap / 2);\n\n\t this.forEach(children, function (child, idx) {\n\t var childBox = (child.box || box).clone();\n\n\t childBox[axis + 1] = position;\n\t childBox[axis + 2] = position + slotSize;\n\n\t child.reflow(childBox);\n\t if (idx < count - 1) {\n\t position += (slotSize * spacing);\n\t }\n\n\t position += slotSize;\n\t });\n\t }\n\t});\n\n\tsetDefaultOptions(ClusterLayout, {\n\t vertical: false,\n\t gap: 0,\n\t spacing: 0\n\t});\n\n\tvar StackWrap = ChartElement.extend({\n\t reflow: function(targetBox) {\n\t var this$1 = this;\n\n\t var positionAxis = this.options.vertical ? X : Y;\n\t var children = this.children;\n\t var childrenCount = children.length;\n\t var box = this.box = new Box();\n\n\t for (var i = 0; i < childrenCount; i++) {\n\t var currentChild = children[i];\n\n\t if (currentChild.visible !== false) {\n\t var childBox = currentChild.box.clone();\n\t childBox.snapTo(targetBox, positionAxis);\n\n\t if (i === 0) {\n\t box = this$1.box = childBox.clone();\n\t }\n\n\t currentChild.reflow(childBox);\n\t box.wrap(childBox);\n\t }\n\t }\n\t }\n\t});\n\n\tsetDefaultOptions(StackWrap, {\n\t vertical: true\n\t});\n\n\tvar BarChart = CategoricalChart.extend({\n\t render: function() {\n\t CategoricalChart.fn.render.call(this);\n\t this.updateStackRange();\n\t },\n\n\t pointType: function() {\n\t return Bar;\n\t },\n\n\t clusterType: function() {\n\t return ClusterLayout;\n\t },\n\n\t stackType: function() {\n\t return StackWrap;\n\t },\n\n\t stackLimits: function(axisName, stackName) {\n\t var limits = CategoricalChart.fn.stackLimits.call(this, axisName, stackName);\n\n\t return limits;\n\t },\n\n\t createPoint: function(data, fields) {\n\t var categoryIx = fields.categoryIx;\n\t var category = fields.category;\n\t var series = fields.series;\n\t var seriesIx = fields.seriesIx;\n\t var ref = this;\n\t var options = ref.options;\n\t var children = ref.children;\n\t var isStacked = options.isStacked;\n\t var value = this.pointValue(data);\n\t var pointOptions = this.pointOptions(series, seriesIx);\n\n\t var labelOptions = pointOptions.labels;\n\t if (isStacked) {\n\t if (labelOptions.position === OUTSIDE_END) {\n\t labelOptions.position = INSIDE_END;\n\t }\n\t }\n\n\t pointOptions.isStacked = isStacked;\n\n\t var color = data.fields.color || series.color;\n\t if (value < 0 && pointOptions.negativeColor) {\n\t color = pointOptions.negativeColor;\n\t }\n\n\t pointOptions = this.evalPointOptions(\n\t pointOptions, value, category, categoryIx, series, seriesIx\n\t );\n\n\t if (isFunction(series.color)) {\n\t color = pointOptions.color;\n\t }\n\n\t var pointType = this.pointType();\n\t var point = new pointType(value, pointOptions);\n\t point.color = color;\n\n\t var cluster = children[categoryIx];\n\t if (!cluster) {\n\t var clusterType = this.clusterType();\n\t cluster = new clusterType({\n\t vertical: options.invertAxes,\n\t gap: options.gap,\n\t spacing: options.spacing,\n\t rtl: !options.invertAxes && (this.chartService || {}).rtl\n\t });\n\t this.append(cluster);\n\t }\n\n\t if (isStacked) {\n\t var stackWrap = this.getStackWrap(series, cluster);\n\t stackWrap.append(point);\n\t } else {\n\t cluster.append(point);\n\t }\n\n\t return point;\n\t },\n\n\t getStackWrap: function(series, cluster) {\n\t var stack = series.stack;\n\t var stackGroup = stack ? stack.group || stack : stack;\n\t var wraps = cluster.children;\n\t var stackWrap;\n\n\t if (typeof stackGroup === datavizConstants.STRING) {\n\t for (var i = 0; i < wraps.length; i++) {\n\t if (wraps[i]._stackGroup === stackGroup) {\n\t stackWrap = wraps[i];\n\t break;\n\t }\n\t }\n\t } else {\n\t stackWrap = wraps[0];\n\t }\n\n\t if (!stackWrap) {\n\t var stackType = this.stackType();\n\t stackWrap = new stackType({\n\t vertical: !this.options.invertAxes\n\t });\n\t stackWrap._stackGroup = stackGroup;\n\t cluster.append(stackWrap);\n\t }\n\n\t return stackWrap;\n\t },\n\n\t categorySlot: function(categoryAxis, categoryIx, valueAxis) {\n\t var options = this.options;\n\t var categorySlot = categoryAxis.getSlot(categoryIx);\n\t var startValue = valueAxis.startValue();\n\n\t if (options.isStacked) {\n\t var zeroSlot = valueAxis.getSlot(startValue, startValue, true);\n\t var stackAxis = options.invertAxes ? X : Y;\n\t categorySlot[stackAxis + 1] = categorySlot[stackAxis + 2] = zeroSlot[stackAxis + 1];\n\t }\n\n\t return categorySlot;\n\t },\n\n\t reflowCategories: function(categorySlots) {\n\t var children = this.children;\n\t var childrenLength = children.length;\n\n\t for (var i = 0; i < childrenLength; i++) {\n\t children[i].reflow(categorySlots[i]);\n\t }\n\t },\n\n\t createAnimation: function() {\n\t this._setAnimationOptions();\n\t CategoricalChart.fn.createAnimation.call(this);\n\n\t if (anyHasZIndex(this.options.series)) {\n\t this._setChildrenAnimation();\n\t }\n\t },\n\n\t _setChildrenAnimation: function() {\n\t var this$1 = this;\n\n\t var points = this.points;\n\n\t for (var idx = 0; idx < points.length; idx++) {\n\t var point = points[idx];\n\t var pointVisual = point.visual;\n\t if (pointVisual && defined(pointVisual.options.zIndex)) {\n\t point.options.animation = this$1.options.animation;\n\t point.createAnimation();\n\t }\n\t }\n\t },\n\n\t _setAnimationOptions: function() {\n\t var options = this.options;\n\t var animation = options.animation || {};\n\t var origin;\n\n\t if (options.isStacked) {\n\t var valueAxis = this.seriesValueAxis(options.series[0]);\n\t origin = valueAxis.getSlot(valueAxis.startValue());\n\t } else {\n\t origin = this.categoryAxis.getSlot(0);\n\t }\n\n\t animation.origin = new GeometryPoint(origin.x1, origin.y1);\n\t animation.vertical = !options.invertAxes;\n\t }\n\t});\n\n\tsetDefaultOptions(BarChart, {\n\t animation: {\n\t type: BAR\n\t }\n\t});\n\n\tvar Candlestick = ChartElement.extend({\n\t init: function(value, options) {\n\t ChartElement.fn.init.call(this, options);\n\t this.value = value;\n\t },\n\n\t reflow: function(box) {\n\t var ref = this;\n\t var options = ref.options;\n\t var value = ref.value;\n\t var chart = ref.owner;\n\t var valueAxis = chart.seriesValueAxis(options);\n\t var ocSlot = valueAxis.getSlot(value.open, value.close);\n\t var lhSlot = valueAxis.getSlot(value.low, value.high);\n\n\t ocSlot.x1 = lhSlot.x1 = box.x1;\n\t ocSlot.x2 = lhSlot.x2 = box.x2;\n\n\t this.realBody = ocSlot;\n\n\t var mid = lhSlot.center().x;\n\t var points = [];\n\n\t points.push([ [ mid, lhSlot.y1 ], [ mid, ocSlot.y1 ] ]);\n\t points.push([ [ mid, ocSlot.y2 ], [ mid, lhSlot.y2 ] ]);\n\n\t this.lines = points;\n\n\t this.box = lhSlot.clone().wrap(ocSlot);\n\n\t if (!this._rendered) {\n\t this._rendered = true;\n\t this.createNote();\n\t }\n\n\t this.reflowNote();\n\t },\n\n\t reflowNote: function() {\n\t if (this.note) {\n\t this.note.reflow(this.box);\n\t }\n\t },\n\n\t createVisual: function() {\n\t ChartElement.fn.createVisual.call(this);\n\t this._mainVisual = this.mainVisual(this.options);\n\t this.visual.append(\n\t this._mainVisual\n\t );\n\n\t this.createOverlay();\n\t },\n\n\t mainVisual: function(options) {\n\t var group = new Group();\n\n\t this.createBody(group, options);\n\t this.createLines(group, options);\n\n\t return group;\n\t },\n\n\t createBody: function(container, options) {\n\t var body = Path.fromRect(this.realBody.toRect(), {\n\t fill: {\n\t color: this.color,\n\t opacity: options.opacity\n\t },\n\t stroke: null\n\t });\n\n\t if (options.border.width > 0) {\n\t body.options.set(\"stroke\", {\n\t color: this.getBorderColor(),\n\t width: options.border.width,\n\t dashType: options.border.dashType,\n\t opacity: valueOrDefault(options.border.opacity, options.opacity)\n\t });\n\t }\n\n\t alignPathToPixel(body);\n\t container.append(body);\n\n\t if (hasGradientOverlay(options)) {\n\t container.append(this.createGradientOverlay(body, { baseColor: this.color }, deepExtend({\n\t end: !options.vertical ? [ 0, 1 ] : undefined\n\t }, options.overlay)));\n\t }\n\t },\n\n\t createLines: function(container, options) {\n\t this.drawLines(container, options, this.lines, options.line);\n\t },\n\n\t drawLines: function(container, options, lines, lineOptions) {\n\t if (!lines) {\n\t return;\n\t }\n\n\t var lineStyle = {\n\t stroke: {\n\t color: lineOptions.color || this.color,\n\t opacity: valueOrDefault(lineOptions.opacity, options.opacity),\n\t width: lineOptions.width,\n\t dashType: lineOptions.dashType,\n\t lineCap: \"butt\"\n\t }\n\t };\n\n\t for (var i = 0; i < lines.length; i++) {\n\t var line = Path.fromPoints(lines[i], lineStyle);\n\t alignPathToPixel(line);\n\t container.append(line);\n\t }\n\t },\n\n\t getBorderColor: function() {\n\t var border = this.options.border;\n\t var borderColor = border.color;\n\n\t if (!defined(borderColor)) {\n\t borderColor = new Color(this.color).brightness(border._brightness).toHex();\n\t }\n\n\t return borderColor;\n\t },\n\n\t createOverlay: function() {\n\t var overlay = Path.fromRect(this.box.toRect(), {\n\t fill: {\n\t color: WHITE,\n\t opacity: 0\n\t },\n\t stroke: null\n\t });\n\n\t this.visual.append(overlay);\n\t },\n\n\t createHighlight: function() {\n\t var highlight = this.options.highlight;\n\t var normalColor = this.color;\n\n\t this.color = highlight.color || this.color;\n\t var overlay = this.mainVisual(\n\t deepExtend({}, this.options, {\n\t line: {\n\t color: this.getBorderColor()\n\t }\n\t }, highlight)\n\t );\n\t this.color = normalColor;\n\n\t return overlay;\n\t },\n\n\t highlightVisual: function() {\n\t return this._mainVisual;\n\t },\n\n\t highlightVisualArgs: function() {\n\t return {\n\t options: this.options,\n\t rect: this.box.toRect(),\n\t visual: this._mainVisual\n\t };\n\t },\n\n\t tooltipAnchor: function() {\n\t var box = this.box;\n\t var clipBox = this.owner.pane.clipBox() || box;\n\n\t return {\n\t point: new Point(box.x2 + TOOLTIP_OFFSET, Math.max(box.y1, clipBox.y1) + TOOLTIP_OFFSET),\n\t align: {\n\t horizontal: LEFT,\n\t vertical: TOP\n\t }\n\t };\n\t },\n\n\t formatValue: function(format) {\n\t return this.owner.formatPointValue(this, format);\n\t },\n\n\t overlapsBox: function(box) {\n\t return this.box.overlaps(box);\n\t }\n\t});\n\n\tsetDefaultOptions(Candlestick, {\n\t vertical: true,\n\t border: {\n\t _brightness: 0.8\n\t },\n\t line: {\n\t width: 2\n\t },\n\t overlay: {\n\t gradient: \"glass\"\n\t },\n\t tooltip: {\n\t format: \"\" +\n\t \"{4:d} |
\" +\n\t \"Open: | {0:C} |
\" +\n\t \"High: | {1:C} |
\" +\n\t \"Low: | {2:C} |
\" +\n\t \"Close: | {3:C} |
\" +\n\t \"
\"\n\t },\n\t highlight: {\n\t opacity: 1,\n\t border: {\n\t width: 1,\n\t opacity: 1\n\t },\n\t line: {\n\t width: 1,\n\t opacity: 1\n\t }\n\t },\n\t notes: {\n\t visible: true,\n\t label: {}\n\t }\n\t});\n\n\tdeepExtend(Candlestick.prototype, PointEventsMixin);\n\tdeepExtend(Candlestick.prototype, NoteMixin);\n\n\tfunction areNumbers(values) {\n\t return countNumbers(values) === values.length;\n\t}\n\n\tvar CandlestickChart = CategoricalChart.extend({\n\t reflowCategories: function(categorySlots) {\n\t var children = this.children;\n\t var childrenLength = children.length;\n\n\t for (var i = 0; i < childrenLength; i++) {\n\t children[i].reflow(categorySlots[i]);\n\t }\n\t },\n\n\t addValue: function(data, fields) {\n\t var categoryIx = fields.categoryIx;\n\t var category = fields.category;\n\t var series = fields.series;\n\t var seriesIx = fields.seriesIx;\n\t var ref = this;\n\t var children = ref.children;\n\t var options = ref.options;\n\t var value = data.valueFields;\n\t var valueParts = this.splitValue(value);\n\t var hasValue = areNumbers(valueParts);\n\t var dataItem = series.data[categoryIx];\n\t var categoryPoints = this.categoryPoints[categoryIx];\n\t var point;\n\n\t if (!categoryPoints) {\n\t this.categoryPoints[categoryIx] = categoryPoints = [];\n\t }\n\n\t if (hasValue) {\n\t point = this.createPoint(data, fields);\n\t }\n\n\t var cluster = children[categoryIx];\n\t if (!cluster) {\n\t cluster = new ClusterLayout({\n\t vertical: options.invertAxes,\n\t gap: options.gap,\n\t spacing: options.spacing,\n\t rtl: !options.invertAxes && (this.chartService || {}).rtl\n\t });\n\t this.append(cluster);\n\t }\n\n\t if (point) {\n\t this.updateRange(value, fields);\n\n\t cluster.append(point);\n\n\t point.categoryIx = categoryIx;\n\t point.category = category;\n\t point.series = series;\n\t point.seriesIx = seriesIx;\n\t point.owner = this;\n\t point.dataItem = dataItem;\n\t point.noteText = data.fields.noteText;\n\t }\n\n\t this.points.push(point);\n\t categoryPoints.push(point);\n\t },\n\n\t pointType: function() {\n\t return Candlestick;\n\t },\n\n\t createPoint: function(data, fields) {\n\t var categoryIx = fields.categoryIx;\n\t var category = fields.category;\n\t var series = fields.series;\n\t var seriesIx = fields.seriesIx;\n\t var pointType = this.pointType();\n\t var value = data.valueFields;\n\t var pointOptions = deepExtend({}, series);\n\t var color = data.fields.color || series.color;\n\n\t pointOptions = this.evalPointOptions(\n\t pointOptions, value, category, categoryIx, series, seriesIx\n\t );\n\n\t if (series.type === CANDLESTICK) {\n\t if (value.open > value.close) {\n\t color = data.fields.downColor || series.downColor || series.color;\n\t }\n\t }\n\n\t if (isFunction(series.color)) {\n\t color = pointOptions.color;\n\t }\n\n\t pointOptions.vertical = !this.options.invertAxes;\n\n\t var point = new pointType(value, pointOptions);\n\t point.color = color;\n\n\t return point;\n\t },\n\n\t splitValue: function(value) {\n\t return [ value.low, value.open, value.close, value.high ];\n\t },\n\n\t updateRange: function(value, fields) {\n\t var axisName = fields.series.axis;\n\t var parts = this.splitValue(value);\n\t var axisRange = this.valueAxisRanges[axisName];\n\n\t axisRange = this.valueAxisRanges[axisName] =\n\t axisRange || { min: MAX_VALUE, max: MIN_VALUE };\n\n\t axisRange = this.valueAxisRanges[axisName] = {\n\t min: Math.min.apply(Math, parts.concat([ axisRange.min ])),\n\t max: Math.max.apply(Math, parts.concat([ axisRange.max ]))\n\t };\n\t },\n\n\t formatPointValue: function(point, format) {\n\t var value = point.value;\n\n\t return this.chartService.format.auto(format,\n\t value.open, value.high,\n\t value.low, value.close, point.category\n\t );\n\t },\n\n\t animationPoints: function() {\n\t return this.points;\n\t }\n\t});\n\n\tdeepExtend(CandlestickChart.prototype, ClipAnimationMixin);\n\n\tvar BoxPlot = Candlestick.extend({\n\t init: function(value, options) {\n\t Candlestick.fn.init.call(this, value, options);\n\n\t this.createNote();\n\t },\n\n\t reflow: function(box) {\n\t var ref = this;\n\t var options = ref.options;\n\t var value = ref.value;\n\t var chart = ref.owner;\n\t var valueAxis = chart.seriesValueAxis(options);\n\t var whiskerSlot, boxSlot;\n\n\t this.boxSlot = boxSlot = valueAxis.getSlot(value.q1, value.q3);\n\t this.realBody = boxSlot;\n\t this.reflowBoxSlot(box);\n\n\t this.whiskerSlot = whiskerSlot = valueAxis.getSlot(value.lower, value.upper);\n\t this.reflowWhiskerSlot(box);\n\n\t var medianSlot = valueAxis.getSlot(value.median);\n\n\t if (value.mean) {\n\t var meanSlot = valueAxis.getSlot(value.mean);\n\t this.meanPoints = this.calcMeanPoints(box, meanSlot);\n\t }\n\n\t this.whiskerPoints = this.calcWhiskerPoints(boxSlot, whiskerSlot);\n\t this.medianPoints = this.calcMedianPoints(box, medianSlot);\n\n\t this.box = whiskerSlot.clone().wrap(boxSlot);\n\t this.reflowNote();\n\t },\n\n\t reflowBoxSlot: function(box) {\n\t this.boxSlot.x1 = box.x1;\n\t this.boxSlot.x2 = box.x2;\n\t },\n\n\t reflowWhiskerSlot: function(box) {\n\t this.whiskerSlot.x1 = box.x1;\n\t this.whiskerSlot.x2 = box.x2;\n\t },\n\n\t calcMeanPoints: function(box, meanSlot) {\n\t return [\n\t [ [ box.x1, meanSlot.y1 ], [ box.x2, meanSlot.y1 ] ]\n\t ];\n\t },\n\n\t calcWhiskerPoints: function(boxSlot, whiskerSlot) {\n\t var mid = whiskerSlot.center().x;\n\t return [ [\n\t [ mid - 5, whiskerSlot.y1 ], [ mid + 5, whiskerSlot.y1 ],\n\t [ mid, whiskerSlot.y1 ], [ mid, boxSlot.y1 ]\n\t ], [\n\t [ mid - 5, whiskerSlot.y2 ], [ mid + 5, whiskerSlot.y2 ],\n\t [ mid, whiskerSlot.y2 ], [ mid, boxSlot.y2 ]\n\t ] ];\n\t },\n\n\t calcMedianPoints: function(box, medianSlot) {\n\t return [\n\t [ [ box.x1, medianSlot.y1 ], [ box.x2, medianSlot.y1 ] ]\n\t ];\n\t },\n\n\t renderOutliers: function(options) {\n\t var this$1 = this;\n\n\t var value = this.value;\n\t var outliers = value.outliers || [];\n\t var outerFence = Math.abs(value.q3 - value.q1) * 3;\n\t var elements = [];\n\t var markers = options.markers || {};\n\n\t for (var i = 0; i < outliers.length; i++) {\n\t var outlierValue = outliers[i];\n\t if (outlierValue < value.q3 + outerFence && outlierValue > value.q1 - outerFence) {\n\t markers = options.outliers;\n\t } else {\n\t markers = options.extremes;\n\t }\n\t var markersBorder = deepExtend({}, markers.border);\n\n\t if (!defined(markersBorder.color)) {\n\t if (defined(this$1.color)) {\n\t markersBorder.color = this$1.color;\n\t } else {\n\t markersBorder.color =\n\t new Color(markers.background).brightness(BORDER_BRIGHTNESS).toHex();\n\t }\n\t }\n\n\t var shape = new ShapeElement({\n\t type: markers.type,\n\t width: markers.size,\n\t height: markers.size,\n\t rotation: markers.rotation,\n\t background: markers.background,\n\t border: markersBorder,\n\t opacity: markers.opacity\n\t });\n\n\t shape.value = outlierValue;\n\n\t elements.push(shape);\n\t }\n\n\t this.reflowOutliers(elements);\n\t return elements;\n\t },\n\n\t reflowOutliers: function(outliers) {\n\t var this$1 = this;\n\n\t var valueAxis = this.owner.seriesValueAxis(this.options);\n\t var center = this.box.center();\n\n\t for (var i = 0; i < outliers.length; i++) {\n\t var outlierValue = outliers[i].value;\n\t var markerBox = valueAxis.getSlot(outlierValue);\n\n\t if (this$1.options.vertical) {\n\t markerBox.move(center.x);\n\t } else {\n\t markerBox.move(undefined, center.y);\n\t }\n\n\t this$1.box = this$1.box.wrap(markerBox);\n\t outliers[i].reflow(markerBox);\n\t }\n\t },\n\n\t mainVisual: function(options) {\n\t var group = Candlestick.fn.mainVisual.call(this, options);\n\t var outliers = this.renderOutliers(options);\n\n\t for (var i = 0; i < outliers.length; i++) {\n\t var element = outliers[i].getElement();\n\t if (element) {\n\t group.append(element);\n\t }\n\t }\n\n\t return group;\n\t },\n\n\t createLines: function(container, options) {\n\t this.drawLines(container, options, this.whiskerPoints, options.whiskers);\n\t this.drawLines(container, options, this.medianPoints, options.median);\n\t this.drawLines(container, options, this.meanPoints, options.mean);\n\t },\n\n\t getBorderColor: function() {\n\t if ((this.options.border || {}).color) {\n\t return this.options.border.color;\n\t }\n\n\t if (this.color) {\n\t return this.color;\n\t }\n\n\t return Candlestick.fn.getBorderColor.call(this);\n\t }\n\t});\n\n\tsetDefaultOptions(BoxPlot, {\n\t border: {\n\t _brightness: 0.8\n\t },\n\t line: {\n\t width: 2\n\t },\n\t median: {\n\t color: \"#f6f6f6\"\n\t },\n\t mean: {\n\t width: 2,\n\t dashType: \"dash\",\n\t color: \"#f6f6f6\"\n\t },\n\t overlay: {\n\t gradient: \"glass\"\n\t },\n\t tooltip: {\n\t format: \"\" +\n\t \"{6:d} |
\" +\n\t \"Lower: | {0:C} |
\" +\n\t \"Q1: | {1:C} |
\" +\n\t \"Median: | {2:C} |
\" +\n\t \"Mean: | {5:C} |
\" +\n\t \"Q3: | {3:C} |
\" +\n\t \"Upper: | {4:C} |
\" +\n\t \"
\"\n\t },\n\t highlight: {\n\t opacity: 1,\n\t border: {\n\t width: 1,\n\t opacity: 1\n\t },\n\t line: {\n\t width: 1,\n\t opacity: 1\n\t }\n\t },\n\t notes: {\n\t visible: true,\n\t label: {}\n\t },\n\t outliers: {\n\t visible: true,\n\t size: LINE_MARKER_SIZE,\n\t type: datavizConstants.CROSS,\n\t background: WHITE,\n\t border: {\n\t width: 2,\n\t opacity: 1\n\t },\n\t opacity: 0\n\t },\n\t extremes: {\n\t visible: true,\n\t size: LINE_MARKER_SIZE,\n\t type: CIRCLE,\n\t background: WHITE,\n\t border: {\n\t width: 2,\n\t opacity: 1\n\t },\n\t opacity: 0\n\t }\n\t});\n\n\tdeepExtend(BoxPlot.prototype, PointEventsMixin);\n\n\tvar VerticalBoxPlot = BoxPlot.extend({\n\t reflowBoxSlot: function(box) {\n\t this.boxSlot.y1 = box.y1;\n\t this.boxSlot.y2 = box.y2;\n\t },\n\n\t reflowWhiskerSlot: function(box) {\n\t this.whiskerSlot.y1 = box.y1;\n\t this.whiskerSlot.y2 = box.y2;\n\t },\n\n\t calcMeanPoints: function(box, meanSlot) {\n\t return [\n\t [ [ meanSlot.x1, box.y1 ], [ meanSlot.x1, box.y2 ] ]\n\t ];\n\t },\n\n\t calcWhiskerPoints: function(boxSlot, whiskerSlot) {\n\t var mid = whiskerSlot.center().y;\n\t return [ [\n\t [ whiskerSlot.x1, mid - 5 ], [ whiskerSlot.x1, mid + 5 ],\n\t [ whiskerSlot.x1, mid ], [ boxSlot.x1, mid ]\n\t ], [\n\t [ whiskerSlot.x2, mid - 5 ], [ whiskerSlot.x2, mid + 5 ],\n\t [ whiskerSlot.x2, mid ], [ boxSlot.x2, mid ]\n\t ] ];\n\t },\n\n\t calcMedianPoints: function(box, medianSlot) {\n\t return [\n\t [ [ medianSlot.x1, box.y1 ], [ medianSlot.x1, box.y2 ] ]\n\t ];\n\t }\n\t});\n\n\tvar BoxPlotChart = CandlestickChart.extend({\n\t addValue: function(data, fields) {\n\t var categoryIx = fields.categoryIx;\n\t var category = fields.category;\n\t var series = fields.series;\n\t var seriesIx = fields.seriesIx;\n\t var ref = this;\n\t var children = ref.children;\n\t var options = ref.options;\n\t var value = data.valueFields;\n\t var valueParts = this.splitValue(value);\n\t var hasValue = areNumbers(valueParts);\n\t var dataItem = series.data[categoryIx];\n\t var categoryPoints = this.categoryPoints[categoryIx];\n\t var point;\n\n\t if (!categoryPoints) {\n\t this.categoryPoints[categoryIx] = categoryPoints = [];\n\t }\n\n\t if (hasValue) {\n\t point = this.createPoint(data, fields);\n\t }\n\n\t var cluster = children[categoryIx];\n\t if (!cluster) {\n\t cluster = new ClusterLayout({\n\t vertical: options.invertAxes,\n\t gap: options.gap,\n\t spacing: options.spacing,\n\t rtl: !options.invertAxes && (this.chartService || {}).rtl\n\t });\n\t this.append(cluster);\n\t }\n\n\t if (point) {\n\t this.updateRange(value, fields);\n\n\t cluster.append(point);\n\n\t point.categoryIx = categoryIx;\n\t point.category = category;\n\t point.series = series;\n\t point.seriesIx = seriesIx;\n\t point.owner = this;\n\t point.dataItem = dataItem;\n\t }\n\n\t this.points.push(point);\n\t categoryPoints.push(point);\n\t },\n\n\t pointType: function() {\n\t if (this.options.invertAxes) {\n\t return VerticalBoxPlot;\n\t }\n\n\t return BoxPlot;\n\t },\n\n\t splitValue: function(value) {\n\t return [\n\t value.lower, value.q1, value.median,\n\t value.q3, value.upper\n\t ];\n\t },\n\n\t updateRange: function(value, fields) {\n\t var axisName = fields.series.axis;\n\t var axisRange = this.valueAxisRanges[axisName];\n\t var parts = this.splitValue(value).concat(this.filterOutliers(value.outliers));\n\n\t if (defined(value.mean)) {\n\t parts = parts.concat(value.mean);\n\t }\n\n\t axisRange = this.valueAxisRanges[axisName] =\n\t axisRange || { min: MAX_VALUE, max: MIN_VALUE };\n\n\t axisRange = this.valueAxisRanges[axisName] = {\n\t min: Math.min.apply(Math, parts.concat([ axisRange.min ])),\n\t max: Math.max.apply(Math, parts.concat([ axisRange.max ]))\n\t };\n\t },\n\n\t formatPointValue: function(point, format) {\n\t var value = point.value;\n\n\t return this.chartService.format.auto(format,\n\t value.lower, value.q1, value.median,\n\t value.q3, value.upper, value.mean, point.category\n\t );\n\t },\n\n\t filterOutliers: function(items) {\n\t var length = (items || []).length;\n\t var result = [];\n\n\t for (var i = 0; i < length; i++) {\n\t var item = items[i];\n\t if (defined(item) && item !== null) {\n\t result.push(item);\n\t }\n\t }\n\n\t return result;\n\t }\n\t});\n\n\tvar ScatterErrorBar = ErrorBarBase.extend({\n\t getAxis: function() {\n\t var axes = this.chart.seriesAxes(this.series);\n\t var axis = this.isVertical ? axes.y : axes.x;\n\n\t return axis;\n\t }\n\t});\n\n\tfunction hasValue(value) {\n\t return defined(value) && value !== null;\n\t}\n\n\tvar ScatterChart = ChartElement.extend({\n\t init: function(plotArea, options) {\n\n\t ChartElement.fn.init.call(this, options);\n\n\t this.plotArea = plotArea;\n\t this.chartService = plotArea.chartService;\n\t this._initFields();\n\n\t this.render();\n\t },\n\n\t _initFields: function() {\n\t // X and Y axis ranges grouped by name, e.g.:\n\t // primary: { min: 0, max: 1 }\n\t this.xAxisRanges = {};\n\t this.yAxisRanges = {};\n\n\t this.points = [];\n\t this.seriesPoints = [];\n\t this.seriesOptions = [];\n\t this._evalSeries = [];\n\t },\n\n\t render: function() {\n\t this.traverseDataPoints(this.addValue.bind(this));\n\t },\n\n\t addErrorBar: function(point, field, fields) {\n\t var value = point.value[field];\n\t var valueErrorField = field + \"Value\";\n\t var lowField = field + \"ErrorLow\";\n\t var highField = field + \"ErrorHigh\";\n\t var seriesIx = fields.seriesIx;\n\t var series = fields.series;\n\t var errorBars = point.options.errorBars;\n\t var lowValue = fields[lowField];\n\t var highValue = fields[highField];\n\n\t if (isNumber(value)) {\n\t var errorRange;\n\t if (isNumber(lowValue) && isNumber(highValue)) {\n\t errorRange = { low: lowValue, high: highValue };\n\t }\n\n\t if (errorBars && defined(errorBars[valueErrorField])) {\n\t this.seriesErrorRanges = this.seriesErrorRanges || { x: [], y: [] };\n\t this.seriesErrorRanges[field][seriesIx] = this.seriesErrorRanges[field][seriesIx] ||\n\t new ErrorRangeCalculator(errorBars[valueErrorField], series, field);\n\n\t errorRange = this.seriesErrorRanges[field][seriesIx].getErrorRange(value, errorBars[valueErrorField]);\n\t }\n\n\t if (errorRange) {\n\t this.addPointErrorBar(errorRange, point, field);\n\t }\n\t }\n\t },\n\n\t addPointErrorBar: function(errorRange, point, field) {\n\t var low = errorRange.low;\n\t var high = errorRange.high;\n\t var series = point.series;\n\t var options = point.options.errorBars;\n\t var isVertical = field === Y;\n\t var item = {};\n\n\t point[field + \"Low\"] = low;\n\t point[field + \"High\"] = high;\n\n\t point.errorBars = point.errorBars || [];\n\t var errorBar = new ScatterErrorBar(low, high, isVertical, this, series, options);\n\t point.errorBars.push(errorBar);\n\t point.append(errorBar);\n\n\t item[field] = low;\n\t this.updateRange(item, series);\n\t item[field] = high;\n\t this.updateRange(item, series);\n\t },\n\n\t addValue: function(value, fields) {\n\t var x = value.x;\n\t var y = value.y;\n\t var seriesIx = fields.seriesIx;\n\t var series = this.options.series[seriesIx];\n\t var missingValues = this.seriesMissingValues(series);\n\t var seriesPoints = this.seriesPoints[seriesIx];\n\n\t var pointValue = value;\n\t if (!(hasValue(x) && hasValue(y))) {\n\t pointValue = this.createMissingValue(pointValue, missingValues);\n\t }\n\n\t var point;\n\t if (pointValue) {\n\t point = this.createPoint(pointValue, fields);\n\t if (point) {\n\t $.extend(point, fields);\n\t this.addErrorBar(point, X, fields);\n\t this.addErrorBar(point, Y, fields);\n\t }\n\t this.updateRange(pointValue, fields.series);\n\t }\n\n\t this.points.push(point);\n\t seriesPoints.push(point);\n\t },\n\n\t seriesMissingValues: function(series) {\n\t return series.missingValues;\n\t },\n\n\t createMissingValue: function() {},\n\n\t updateRange: function(value, series) {\n\t var intlService = this.chartService.intl;\n\t var xAxisName = series.xAxis;\n\t var yAxisName = series.yAxis;\n\t var x = value.x;\n\t var y = value.y;\n\t var xAxisRange = this.xAxisRanges[xAxisName];\n\t var yAxisRange = this.yAxisRanges[yAxisName];\n\n\t if (hasValue(x)) {\n\t xAxisRange = this.xAxisRanges[xAxisName] =\n\t xAxisRange || { min: MAX_VALUE, max: MIN_VALUE };\n\n\t if (isString(x)) {\n\t x = parseDate(intlService, x);\n\t }\n\n\t xAxisRange.min = Math.min(xAxisRange.min, x);\n\t xAxisRange.max = Math.max(xAxisRange.max, x);\n\t }\n\n\t if (hasValue(y)) {\n\t yAxisRange = this.yAxisRanges[yAxisName] =\n\t yAxisRange || { min: MAX_VALUE, max: MIN_VALUE };\n\n\t if (isString(y)) {\n\t y = parseDate(intlService, y);\n\t }\n\n\t yAxisRange.min = Math.min(yAxisRange.min, y);\n\t yAxisRange.max = Math.max(yAxisRange.max, y);\n\t }\n\t },\n\n\t evalPointOptions: function(options, value, fields) {\n\t var series = fields.series;\n\t var seriesIx = fields.seriesIx;\n\t var state = { defaults: series._defaults, excluded: [ \"data\", \"tooltip\", \"content\", \"template\", \"visual\", \"toggle\", \"_outOfRangeMinPoint\", \"_outOfRangeMaxPoint\" ] };\n\n\t var doEval = this._evalSeries[seriesIx];\n\t if (!defined(doEval)) {\n\t this._evalSeries[seriesIx] = doEval = evalOptions(options, {}, state, true);\n\t }\n\n\t var pointOptions = options;\n\t if (doEval) {\n\t pointOptions = deepExtend({}, options);\n\t evalOptions(pointOptions, {\n\t value: value,\n\t series: series,\n\t dataItem: fields.dataItem\n\t }, state);\n\t }\n\n\t return pointOptions;\n\t },\n\n\t pointType: function() {\n\t return LinePoint;\n\t },\n\n\t pointOptions: function(series, seriesIx) {\n\t var options = this.seriesOptions[seriesIx];\n\t if (!options) {\n\t var defaults = this.pointType().prototype.defaults;\n\t this.seriesOptions[seriesIx] = options = deepExtend({}, defaults, {\n\t markers: {\n\t opacity: series.opacity\n\t },\n\t tooltip: {\n\t format: this.options.tooltip.format\n\t },\n\t labels: {\n\t format: this.options.labels.format\n\t }\n\t }, series);\n\t }\n\n\t return options;\n\t },\n\n\t createPoint: function(value, fields) {\n\t var series = fields.series;\n\t var pointOptions = this.pointOptions(series, fields.seriesIx);\n\t var color = fields.color || series.color;\n\n\t pointOptions = this.evalPointOptions(pointOptions, value, fields);\n\n\t if (isFunction(series.color)) {\n\t color = pointOptions.color;\n\t }\n\n\t var point = new LinePoint(value, pointOptions);\n\t point.color = color;\n\n\t this.append(point);\n\n\t return point;\n\t },\n\n\t seriesAxes: function(series) {\n\t var xAxisName = series.xAxis;\n\t var yAxisName = series.yAxis;\n\t var plotArea = this.plotArea;\n\t var xAxis = xAxisName ? plotArea.namedXAxes[xAxisName] : plotArea.axisX;\n\t var yAxis = yAxisName ? plotArea.namedYAxes[yAxisName] : plotArea.axisY;\n\n\t if (!xAxis) {\n\t throw new Error(\"Unable to locate X axis with name \" + xAxisName);\n\t }\n\n\t if (!yAxis) {\n\t throw new Error(\"Unable to locate Y axis with name \" + yAxisName);\n\t }\n\n\t return {\n\t x: xAxis,\n\t y: yAxis\n\t };\n\t },\n\n\t reflow: function(targetBox) {\n\t var this$1 = this;\n\n\t var chartPoints = this.points;\n\t var limit = !this.options.clip;\n\t var pointIx = 0;\n\n\t this.traverseDataPoints(function (value, fields) {\n\t var point = chartPoints[pointIx++];\n\t var seriesAxes = this$1.seriesAxes(fields.series);\n\t var slotX = seriesAxes.x.getSlot(value.x, value.x, limit);\n\t var slotY = seriesAxes.y.getSlot(value.y, value.y, limit);\n\n\t if (point) {\n\t if (slotX && slotY) {\n\t var pointSlot = this$1.pointSlot(slotX, slotY);\n\t point.reflow(pointSlot);\n\t } else {\n\t point.visible = false;\n\t }\n\t }\n\t });\n\n\t this.box = targetBox;\n\t },\n\n\t pointSlot: function(slotX, slotY) {\n\t return new Box(slotX.x1, slotY.y1, slotX.x2, slotY.y2);\n\t },\n\n\t traverseDataPoints: function(callback) {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var series = ref.options.series;\n\t var seriesPoints = ref.seriesPoints;\n\n\t for (var seriesIx = 0; seriesIx < series.length; seriesIx++) {\n\t var currentSeries = series[seriesIx];\n\t var currentSeriesPoints = seriesPoints[seriesIx];\n\t if (!currentSeriesPoints) {\n\t seriesPoints[seriesIx] = [];\n\t }\n\n\t for (var pointIx = 0; pointIx < currentSeries.data.length; pointIx++) {\n\t var ref$1 = this$1._bindPoint(currentSeries, seriesIx, pointIx);\n\t var value = ref$1.valueFields;\n\t var fields = ref$1.fields;\n\n\t callback(value, deepExtend({\n\t pointIx: pointIx,\n\t series: currentSeries,\n\t seriesIx: seriesIx,\n\t dataItem: currentSeries.data[pointIx],\n\t owner: this$1\n\t }, fields));\n\t }\n\t }\n\t },\n\n\t formatPointValue: function(point, format) {\n\t var value = point.value;\n\t return this.chartService.format.auto(format, value.x, value.y);\n\t },\n\n\t animationPoints: function() {\n\t var points = this.points;\n\t var result = [];\n\t for (var idx = 0; idx < points.length; idx++) {\n\t result.push((points[idx] || {}).marker);\n\t }\n\t return result;\n\t }\n\t});\n\tsetDefaultOptions(ScatterChart, {\n\t series: [],\n\t tooltip: {\n\t format: \"{0}, {1}\"\n\t },\n\t labels: {\n\t format: \"{0}, {1}\"\n\t },\n\t clip: true\n\t});\n\tdeepExtend(ScatterChart.prototype, ClipAnimationMixin, {\n\t _bindPoint: CategoricalChart.prototype._bindPoint\n\t});\n\n\tvar Bubble = LinePoint.extend({\n\t init: function(value, options) {\n\t LinePoint.fn.init.call(this, value, options);\n\n\t this.category = value.category;\n\t },\n\n\t createHighlight: function() {\n\t var highlight = this.options.highlight;\n\t var border = highlight.border;\n\t var markers = this.options.markers;\n\t var center = this.box.center();\n\t var radius = (markers.size + markers.border.width + border.width) / 2;\n\t var highlightGroup = new Group();\n\t var shadow = new drawing.Circle(new geometry.Circle([ center.x, center.y + radius / 5 + border.width / 2 ], radius + border.width / 2), {\n\t stroke: {\n\t color: 'none'\n\t },\n\t fill: this.createGradient({\n\t gradient: 'bubbleShadow',\n\t color: markers.background,\n\t stops: [ {\n\t offset: 0,\n\t color: markers.background,\n\t opacity: 0.3\n\t }, {\n\t offset: 1,\n\t color: markers.background,\n\t opacity: 0\n\t } ]\n\t })\n\t });\n\t var overlay = new drawing.Circle(new geometry.Circle([ center.x, center.y ], radius), {\n\t stroke: {\n\t color: border.color ||\n\t new Color(markers.background).brightness(BORDER_BRIGHTNESS).toHex(),\n\t width: border.width,\n\t opacity: border.opacity\n\t },\n\t fill: {\n\t color: markers.background,\n\t opacity: highlight.opacity\n\t }\n\t });\n\n\t highlightGroup.append(shadow, overlay);\n\n\t return highlightGroup;\n\t }\n\t});\n\n\tBubble.prototype.defaults = deepExtend({}, Bubble.prototype.defaults, {\n\t labels: {\n\t position: CENTER\n\t },\n\t highlight: {\n\t opacity: 1,\n\t border: {\n\t color: \"#fff\",\n\t width: 2,\n\t opacity: 1\n\t }\n\t }\n\t});\n\n\tBubble.prototype.defaults.highlight.zIndex = undefined;\n\n\tvar BubbleChart = ScatterChart.extend({\n\t _initFields: function() {\n\t this._maxSize = MIN_VALUE;\n\t ScatterChart.fn._initFields.call(this);\n\t },\n\n\t addValue: function(value, fields) {\n\t if (value.size !== null && (value.size > 0 || (value.size < 0 && fields.series.negativeValues.visible))) {\n\t this._maxSize = Math.max(this._maxSize, Math.abs(value.size));\n\t ScatterChart.fn.addValue.call(this, value, fields);\n\t } else {\n\t this.points.push(null);\n\t this.seriesPoints[fields.seriesIx].push(null);\n\t }\n\t },\n\n\t reflow: function(box) {\n\t this.updateBubblesSize(box);\n\t ScatterChart.fn.reflow.call(this, box);\n\t },\n\n\t pointType: function() {\n\t return Bubble;\n\t },\n\n\t createPoint: function(value, fields) {\n\t var series = fields.series;\n\t var pointsCount = series.data.length;\n\t var delay = fields.pointIx * (INITIAL_ANIMATION_DURATION / pointsCount);\n\t var animationOptions = {\n\t delay: delay,\n\t duration: INITIAL_ANIMATION_DURATION - delay,\n\t type: BUBBLE\n\t };\n\n\t var color = fields.color || series.color;\n\t if (value.size < 0 && series.negativeValues.visible) {\n\t color = valueOrDefault(\n\t series.negativeValues.color, color\n\t );\n\t }\n\n\t var pointOptions = deepExtend({\n\t labels: {\n\t animation: {\n\t delay: delay,\n\t duration: INITIAL_ANIMATION_DURATION - delay\n\t }\n\t }\n\t }, this.pointOptions(series, fields.seriesIx), {\n\t markers: {\n\t type: CIRCLE,\n\t border: series.border,\n\t opacity: series.opacity,\n\t animation: animationOptions\n\t }\n\t });\n\n\t pointOptions = this.evalPointOptions(pointOptions, value, fields);\n\t if (isFunction(series.color)) {\n\t color = pointOptions.color;\n\t }\n\n\t pointOptions.markers.background = color;\n\n\t var point = new Bubble(value, pointOptions);\n\t point.color = color;\n\n\t this.append(point);\n\n\t return point;\n\t },\n\n\t updateBubblesSize: function(box) {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var series = ref.options.series;\n\t var boxSize = Math.min(box.width(), box.height());\n\n\t for (var seriesIx = 0; seriesIx < series.length; seriesIx++) {\n\t var currentSeries = series[seriesIx];\n\t var seriesPoints = this$1.seriesPoints[seriesIx];\n\t var minSize = currentSeries.minSize || Math.max(boxSize * 0.02, 10);\n\t var maxSize = currentSeries.maxSize || boxSize * 0.2;\n\t var minR = minSize / 2;\n\t var maxR = maxSize / 2;\n\t var minArea = Math.PI * minR * minR;\n\t var maxArea = Math.PI * maxR * maxR;\n\t var areaRange = maxArea - minArea;\n\t var areaRatio = areaRange / this$1._maxSize;\n\n\t for (var pointIx = 0; pointIx < seriesPoints.length; pointIx++) {\n\t var point = seriesPoints[pointIx];\n\t if (point) {\n\t var area = Math.abs(point.value.size) * areaRatio;\n\t var radius = Math.sqrt((minArea + area) / Math.PI);\n\t var baseZIndex = valueOrDefault(point.options.zIndex, 0);\n\t var zIndex = baseZIndex + (1 - radius / maxR);\n\n\t deepExtend(point.options, {\n\t zIndex: zIndex,\n\t markers: {\n\t size: radius * 2,\n\t zIndex: zIndex\n\t },\n\t labels: {\n\t zIndex: zIndex + 1\n\t }\n\t });\n\t }\n\t }\n\t }\n\t },\n\n\t formatPointValue: function(point, format) {\n\t var value = point.value;\n\t return this.chartService.format.auto(format, value.x, value.y, value.size, point.category);\n\t },\n\n\t createAnimation: function() {},\n\n\t createVisual: function() {}\n\t});\n\n\tsetDefaultOptions(BubbleChart, {\n\t tooltip: {\n\t format: \"{3}\"\n\t },\n\t labels: {\n\t format: \"{3}\"\n\t }\n\t});\n\n\tvar Target = ShapeElement.extend({\n\n\t});\n\n\tdeepExtend(Target.prototype, PointEventsMixin);\n\n\tvar Bullet = ChartElement.extend({\n\t init: function(value, options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.aboveAxis = this.options.aboveAxis;\n\t this.color = options.color || WHITE;\n\t this.value = value;\n\t },\n\n\t render: function() {\n\t var options = this.options;\n\n\t if (!this._rendered) {\n\t this._rendered = true;\n\n\t if (defined(this.value.target)) {\n\t this.target = new Target({\n\t type: options.target.shape,\n\t background: options.target.color || this.color,\n\t opacity: options.opacity,\n\t zIndex: options.zIndex,\n\t border: options.target.border,\n\t vAlign: TOP,\n\t align: RIGHT\n\t });\n\n\t this.target.value = this.value;\n\t this.target.dataItem = this.dataItem;\n\t this.target.series = this.series;\n\n\t this.append(this.target);\n\t }\n\n\t this.createNote();\n\t }\n\t },\n\n\t reflow: function(box) {\n\t this.render();\n\n\t var ref = this;\n\t var options = ref.options;\n\t var target = ref.target;\n\t var chart = ref.owner;\n\t var invertAxes = options.invertAxes;\n\t var valueAxis = chart.seriesValueAxis(this.options);\n\t var categorySlot = chart.categorySlot(chart.categoryAxis, options.categoryIx, valueAxis);\n\t var targetValueSlot = valueAxis.getSlot(this.value.target);\n\t var targetSlotX = invertAxes ? targetValueSlot : categorySlot;\n\t var targetSlotY = invertAxes ? categorySlot : targetValueSlot;\n\n\t if (target) {\n\t var targetSlot = new Box(\n\t targetSlotX.x1, targetSlotY.y1,\n\t targetSlotX.x2, targetSlotY.y2\n\t );\n\t target.options.height = invertAxes ? targetSlot.height() : options.target.line.width;\n\t target.options.width = invertAxes ? options.target.line.width : targetSlot.width();\n\t target.reflow(targetSlot);\n\t }\n\n\t if (this.note) {\n\t this.note.reflow(box);\n\t }\n\n\t this.box = box;\n\t },\n\n\t createVisual: function() {\n\t ChartElement.fn.createVisual.call(this);\n\n\t var options = this.options;\n\t var body = Path.fromRect(this.box.toRect(), {\n\t fill: {\n\t color: this.color,\n\t opacity: options.opacity\n\t },\n\t stroke: null\n\t });\n\n\t if (options.border.width > 0) {\n\t body.options.set(\"stroke\", {\n\t color: options.border.color || this.color,\n\t width: options.border.width,\n\t dashType: options.border.dashType,\n\t opacity: valueOrDefault(options.border.opacity, options.opacity)\n\t });\n\t }\n\n\t this.bodyVisual = body;\n\n\t alignPathToPixel(body);\n\t this.visual.append(body);\n\t },\n\n\t createAnimation: function() {\n\t if (this.bodyVisual) {\n\t this.animation = Animation.create(\n\t this.bodyVisual, this.options.animation\n\t );\n\t }\n\t },\n\n\t createHighlight: function(style) {\n\t return Path.fromRect(this.box.toRect(), style);\n\t },\n\n\t highlightVisual: function() {\n\t return this.bodyVisual;\n\t },\n\n\t highlightVisualArgs: function() {\n\t return {\n\t rect: this.box.toRect(),\n\t visual: this.bodyVisual,\n\t options: this.options\n\t };\n\t },\n\n\t formatValue: function(format) {\n\t return this.owner.formatPointValue(this, format);\n\t }\n\t});\n\n\tBullet.prototype.tooltipAnchor = Bar.prototype.tooltipAnchor;\n\n\tsetDefaultOptions(Bullet, {\n\t border: {\n\t width: 1\n\t },\n\t vertical: false,\n\t opacity: 1,\n\t target: {\n\t shape: \"\",\n\t border: {\n\t width: 0,\n\t color: \"green\"\n\t },\n\t line: {\n\t width: 2\n\t }\n\t },\n\t tooltip: {\n\t format: \"Current: {0}
Target: {1}\"\n\t }\n\t});\n\n\tdeepExtend(Bullet.prototype, PointEventsMixin);\n\tdeepExtend(Bullet.prototype, NoteMixin);\n\n\tvar BulletChart = CategoricalChart.extend({\n\t init: function(plotArea, options) {\n\n\t wrapData(options);\n\n\t CategoricalChart.fn.init.call(this, plotArea, options);\n\t },\n\n\t reflowCategories: function(categorySlots) {\n\t var children = this.children;\n\t var childrenLength = children.length;\n\n\t for (var i = 0; i < childrenLength; i++) {\n\t children[i].reflow(categorySlots[i]);\n\t }\n\t },\n\n\t plotRange: function(point) {\n\t var series = point.series;\n\t var valueAxis = this.seriesValueAxis(series);\n\t var axisCrossingValue = this.categoryAxisCrossingValue(valueAxis);\n\n\t return [ axisCrossingValue, point.value.current || axisCrossingValue ];\n\t },\n\n\t createPoint: function(data, fields) {\n\t var categoryIx = fields.categoryIx;\n\t var category = fields.category;\n\t var series = fields.series;\n\t var seriesIx = fields.seriesIx;\n\t var ref = this;\n\t var options = ref.options;\n\t var children = ref.children;\n\t var value = data.valueFields;\n\n\t var bulletOptions = deepExtend({\n\t vertical: !options.invertAxes,\n\t overlay: series.overlay,\n\t categoryIx: categoryIx,\n\t invertAxes: options.invertAxes\n\t }, series);\n\n\t var color = data.fields.color || series.color;\n\t bulletOptions = this.evalPointOptions(\n\t bulletOptions, value, category, categoryIx, series, seriesIx\n\t );\n\n\t if (isFunction(series.color)) {\n\t color = bulletOptions.color;\n\t }\n\n\t var bullet = new Bullet(value, bulletOptions);\n\t bullet.color = color;\n\n\t var cluster = children[categoryIx];\n\t if (!cluster) {\n\t cluster = new ClusterLayout({\n\t vertical: options.invertAxes,\n\t gap: options.gap,\n\t spacing: options.spacing,\n\t rtl: !options.invertAxes && (this.chartService || {}).rtl\n\t });\n\t this.append(cluster);\n\t }\n\n\t cluster.append(bullet);\n\n\t return bullet;\n\t },\n\n\t updateRange: function(value, fields) {\n\t var current = value.current;\n\t var target = value.target;\n\t var axisName = fields.series.axis;\n\t var axisRange = this.valueAxisRanges[axisName];\n\n\t if (defined(current) && !isNaN(current) && defined(target && !isNaN(target))) {\n\t axisRange = this.valueAxisRanges[axisName] =\n\t axisRange || { min: MAX_VALUE, max: MIN_VALUE };\n\n\t axisRange.min = Math.min(axisRange.min, current, target);\n\t axisRange.max = Math.max(axisRange.max, current, target);\n\t }\n\t },\n\n\t formatPointValue: function(point, format) {\n\t return this.chartService.format.auto(format, point.value.current, point.value.target);\n\t },\n\n\t pointValue: function(data) {\n\t return data.valueFields.current;\n\t },\n\n\t aboveAxis: function(point) {\n\t var value = point.value.current;\n\n\t return value > 0;\n\t },\n\n\t createAnimation: function() {\n\t var this$1 = this;\n\n\t var points = this.points;\n\n\t this._setAnimationOptions();\n\n\t for (var idx = 0; idx < points.length; idx++) {\n\t var point = points[idx];\n\t point.options.animation = this$1.options.animation;\n\t point.createAnimation();\n\t }\n\t }\n\t});\n\n\tBulletChart.prototype._setAnimationOptions = BarChart.prototype._setAnimationOptions;\n\n\tsetDefaultOptions(BulletChart, {\n\t animation: {\n\t type: BAR\n\t }\n\t});\n\n\tfunction wrapData(options) {\n\t var series = options.series;\n\n\t for (var i = 0; i < series.length; i++) {\n\t var seriesItem = series[i];\n\t var data = seriesItem.data;\n\t if (data && !isArray(data[0]) && !isObject(data[0])) {\n\t seriesItem.data = [ data ];\n\t }\n\t }\n\t}\n\n\tvar BaseTooltip = Class.extend({\n\t init: function(chartService, options) {\n\n\t this.chartService = chartService;\n\t this.options = deepExtend({}, this.options, options);\n\t },\n\n\t getStyle: function(options, point) {\n\t var background = options.background;\n\t var border = options.border.color;\n\n\t if (point) {\n\t var pointColor = point.color || point.options.color;\n\t background = valueOrDefault(background, pointColor);\n\t border = valueOrDefault(border, pointColor);\n\t }\n\n\t var padding = getSpacing(options.padding || {}, \"auto\");\n\n\t return {\n\t backgroundColor: background,\n\t borderColor: border,\n\t font: options.font,\n\t color: options.color,\n\t opacity: options.opacity,\n\t borderWidth: styleValue(options.border.width),\n\t paddingTop: styleValue(padding.top),\n\t paddingBottom: styleValue(padding.bottom),\n\t paddingLeft: styleValue(padding.left),\n\t paddingRight: styleValue(padding.right)\n\t };\n\t },\n\n\t show: function(options, tooltipOptions, point) {\n\t options.format = tooltipOptions.format;\n\n\t var style = this.getStyle(tooltipOptions, point);\n\t options.style = style;\n\n\t if (!defined(tooltipOptions.color) && new Color(style.backgroundColor).percBrightness() > 180) {\n\t options.className = \"k-chart-tooltip-inverse\";\n\t }\n\n\t this.chartService.notify(SHOW_TOOLTIP, options);\n\n\t this.visible = true;\n\t },\n\n\t hide: function() {\n\t if (this.chartService) {\n\t this.chartService.notify(HIDE_TOOLTIP);\n\t }\n\n\t this.visible = false;\n\t },\n\n\t destroy: function() {\n\t delete this.chartService;\n\t }\n\t});\n\n\tsetDefaultOptions(BaseTooltip, {\n\t border: {\n\t width: 1\n\t },\n\t opacity: 1\n\t});\n\n\tvar CrosshairTooltip = BaseTooltip.extend({\n\t init: function(chartService, crosshair, options) {\n\t BaseTooltip.fn.init.call(this, chartService, options);\n\n\t this.crosshair = crosshair;\n\t this.formatService = chartService.format;\n\t this.initAxisName();\n\t },\n\n\t initAxisName: function() {\n\t var axis = this.crosshair.axis;\n\t var plotArea = axis.plotArea;\n\t var name;\n\t if (plotArea.categoryAxis) {\n\t name = axis.getCategory ? \"categoryAxis\" : \"valueAxis\";\n\t } else {\n\t name = axis.options.vertical ? \"yAxis\" : \"xAxis\";\n\t }\n\t this.axisName = name;\n\t },\n\n\t showAt: function(point) {\n\t var ref = this;\n\t var axis = ref.crosshair.axis;\n\t var options = ref.options;\n\t var value = axis[options.stickyMode ? \"getCategory\" : \"getValue\"](point);\n\t var formattedValue = value;\n\n\t if (options.format) {\n\t formattedValue = this.formatService.auto(options.format, value);\n\t } else if (axis.options.type === DATE) {\n\t formattedValue = this.formatService.auto(axis.options.labels.dateFormats[axis.options.baseUnit], value);\n\t }\n\n\t this.show({\n\t point: point,\n\t anchor: this.getAnchor(),\n\t crosshair: this.crosshair,\n\t value: formattedValue,\n\t axisName: this.axisName,\n\t axisIndex: this.crosshair.axis.axisIndex\n\t }, this.options);\n\t },\n\n\t hide: function() {\n\t this.chartService.notify(HIDE_TOOLTIP, {\n\t crosshair: this.crosshair,\n\t axisName: this.axisName,\n\t axisIndex: this.crosshair.axis.axisIndex\n\t });\n\t },\n\n\t getAnchor: function() {\n\t var ref = this;\n\t var crosshair = ref.crosshair;\n\t var ref_options = ref.options;\n\t var position = ref_options.position;\n\t var padding = ref_options.padding;\n\t var vertical = !crosshair.axis.options.vertical;\n\t var lineBox = crosshair.line.bbox();\n\t var horizontalAlign, verticalAlign, point;\n\n\t if (vertical) {\n\t horizontalAlign = CENTER;\n\t if (position === BOTTOM) {\n\t verticalAlign = TOP;\n\t point = lineBox.bottomLeft().translate(0, padding);\n\t } else {\n\t verticalAlign = BOTTOM;\n\t point = lineBox.topLeft().translate(0, -padding);\n\t }\n\t } else {\n\t verticalAlign = CENTER;\n\t if (position === LEFT) {\n\t horizontalAlign = RIGHT;\n\t point = lineBox.topLeft().translate(-padding, 0);\n\t } else {\n\t horizontalAlign = LEFT;\n\t point = lineBox.topRight().translate(padding, 0);\n\t }\n\t }\n\n\t return {\n\t point: point,\n\t align: {\n\t horizontal: horizontalAlign,\n\t vertical: verticalAlign\n\t }\n\t };\n\t }\n\t});\n\n\tsetDefaultOptions(CrosshairTooltip, {\n\t padding: 10\n\t});\n\n\tvar Crosshair = ChartElement.extend({\n\t init: function(chartService, axis, options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.axis = axis;\n\t this.stickyMode = axis instanceof CategoryAxis;\n\n\t var tooltipOptions = this.options.tooltip;\n\n\t if (tooltipOptions.visible) {\n\t this.tooltip = new CrosshairTooltip(chartService, this,\n\t deepExtend({}, tooltipOptions, { stickyMode: this.stickyMode })\n\t );\n\t }\n\t },\n\n\t showAt: function(point) {\n\t this.point = point;\n\t this.moveLine();\n\t this.line.visible(true);\n\n\t if (this.tooltip) {\n\t this.tooltip.showAt(point);\n\t }\n\t },\n\n\t hide: function() {\n\t this.line.visible(false);\n\n\t if (this.tooltip) {\n\t this.tooltip.hide();\n\t }\n\t },\n\n\t moveLine: function() {\n\t var ref = this;\n\t var axis = ref.axis;\n\t var point = ref.point;\n\t var vertical = axis.options.vertical;\n\t var box = this.getBox();\n\t var dim = vertical ? Y : X;\n\t var lineStart = new GeometryPoint(box.x1, box.y1);\n\t var lineEnd;\n\n\t if (vertical) {\n\t lineEnd = new GeometryPoint(box.x2, box.y1);\n\t } else {\n\t lineEnd = new GeometryPoint(box.x1, box.y2);\n\t }\n\n\t if (point) {\n\t if (this.stickyMode) {\n\t var slot = axis.getSlot(axis.pointCategoryIndex(point));\n\t lineStart[dim] = lineEnd[dim] = slot.center()[dim];\n\t } else {\n\t lineStart[dim] = lineEnd[dim] = point[dim];\n\t }\n\t }\n\n\t this.box = box;\n\n\t this.line.moveTo(lineStart).lineTo(lineEnd);\n\t },\n\n\t getBox: function() {\n\t var axis = this.axis;\n\t var axes = axis.pane.axes;\n\t var length = axes.length;\n\t var vertical = axis.options.vertical;\n\t var box = axis.lineBox().clone();\n\t var dim = vertical ? X : Y;\n\t var axisLineBox;\n\n\t for (var i = 0; i < length; i++) {\n\t var currentAxis = axes[i];\n\t if (currentAxis.options.vertical !== vertical) {\n\t if (!axisLineBox) {\n\t axisLineBox = currentAxis.lineBox().clone();\n\t } else {\n\t axisLineBox.wrap(currentAxis.lineBox());\n\t }\n\t }\n\t }\n\n\t box[dim + 1] = axisLineBox[dim + 1];\n\t box[dim + 2] = axisLineBox[dim + 2];\n\n\t return box;\n\t },\n\n\t createVisual: function() {\n\t ChartElement.fn.createVisual.call(this);\n\n\t var options = this.options;\n\t this.line = new Path({\n\t stroke: {\n\t color: options.color,\n\t width: options.width,\n\t opacity: options.opacity,\n\t dashType: options.dashType\n\t },\n\t visible: false\n\t });\n\n\t this.moveLine();\n\t this.visual.append(this.line);\n\t },\n\n\t destroy: function() {\n\t if (this.tooltip) {\n\t this.tooltip.destroy();\n\t }\n\n\t ChartElement.fn.destroy.call(this);\n\t }\n\t});\n\n\tsetDefaultOptions(Crosshair, {\n\t color: BLACK,\n\t width: 2,\n\t zIndex: -1,\n\t tooltip: {\n\t visible: false\n\t }\n\t});\n\n\tvar ChartContainer = ChartElement.extend({\n\t init: function(options, pane) {\n\t ChartElement.fn.init.call(this, options);\n\t this.pane = pane;\n\t },\n\n\t shouldClip: function() {\n\t var children = this.children;\n\t var length = children.length;\n\n\t for (var i = 0; i < length; i++) {\n\t if (children[i].options.clip === true) {\n\t return true;\n\t }\n\t }\n\t return false;\n\t },\n\n\t _clipBox: function() {\n\t return this.pane.chartsBox();\n\t },\n\n\t createVisual: function() {\n\t this.visual = new Group({\n\t zIndex: 0\n\t });\n\n\t if (this.shouldClip()) {\n\t var clipBox = this.clipBox = this._clipBox();\n\t var clipRect = clipBox.toRect();\n\t var clipPath = Path.fromRect(clipRect);\n\t alignPathToPixel(clipPath);\n\n\t this.visual.clip(clipPath);\n\t this.unclipLabels();\n\t }\n\t },\n\n\t stackRoot: function() {\n\t return this;\n\t },\n\n\t unclipLabels: function() {\n\t var ref = this;\n\t var charts = ref.children;\n\t var clipBox = ref.clipBox;\n\n\t for (var i = 0; i < charts.length; i++) {\n\t var points = charts[i].points || {};\n\t var length = points.length;\n\n\t for (var j = 0; j < length; j++) {\n\t var point = points[j];\n\t if (point && point.visible !== false && point.overlapsBox && point.overlapsBox(clipBox)) {\n\t if (point.unclipElements) {\n\t point.unclipElements();\n\t } else {\n\t var label = point.label;\n\t var note = point.note;\n\n\t if (label && label.options.visible) {\n\t if (label.alignToClipBox) {\n\t label.alignToClipBox(clipBox);\n\t }\n\t label.options.noclip = true;\n\t }\n\n\t if (note && note.options.visible) {\n\t note.options.noclip = true;\n\t }\n\t }\n\t }\n\t }\n\t }\n\t },\n\n\t destroy: function() {\n\t ChartElement.fn.destroy.call(this);\n\n\t delete this.parent;\n\t }\n\t});\n\n\tChartContainer.prototype.isStackRoot = true;\n\n\tvar Pane = BoxElement.extend({\n\t init: function(options) {\n\t BoxElement.fn.init.call(this, options);\n\n\t this.id = paneID();\n\n\t this.createTitle();\n\n\t this.content = new ChartElement();\n\n\t this.chartContainer = new ChartContainer({}, this);\n\t this.append(this.content);\n\n\t this.axes = [];\n\t this.charts = [];\n\t },\n\n\t createTitle: function() {\n\t var titleOptions = this.options.title;\n\t if (isObject(titleOptions)) {\n\t titleOptions = deepExtend({}, titleOptions, {\n\t align: titleOptions.position,\n\t position: TOP\n\t });\n\t }\n\n\t this.title = dataviz.Title.buildTitle(titleOptions, this, Pane.prototype.options.title);\n\t },\n\n\t appendAxis: function(axis) {\n\t this.content.append(axis);\n\t this.axes.push(axis);\n\t axis.pane = this;\n\t },\n\n\t appendAxisAt: function(axis, pos) {\n\t this.content.append(axis);\n\t this.axes.splice(pos, 0, axis);\n\t axis.pane = this;\n\t },\n\n\t appendChart: function(chart) {\n\t if (this.chartContainer.parent !== this.content) {\n\t this.content.append(this.chartContainer);\n\t }\n\n\t this.charts.push(chart);\n\t this.chartContainer.append(chart);\n\t chart.pane = this;\n\t },\n\n\t empty: function() {\n\t var this$1 = this;\n\n\t var plotArea = this.parent;\n\n\t if (plotArea) {\n\t for (var i = 0; i < this.axes.length; i++) {\n\t plotArea.removeAxis(this$1.axes[i]);\n\t }\n\n\t for (var i$1 = 0; i$1 < this.charts.length; i$1++) {\n\t plotArea.removeChart(this$1.charts[i$1]);\n\t }\n\t }\n\n\t this.axes = [];\n\t this.charts = [];\n\n\t this.content.destroy();\n\t this.content.children = [];\n\t this.chartContainer.children = [];\n\t },\n\n\t reflow: function(targetBox) {\n\t // Content (such as charts) is rendered, but excluded from reflows\n\t var content;\n\t if (last(this.children) === this.content) {\n\t content = this.children.pop();\n\t }\n\n\t BoxElement.fn.reflow.call(this, targetBox);\n\n\t if (content) {\n\t this.children.push(content);\n\t }\n\n\t if (this.title) {\n\t this.contentBox.y1 += this.title.box.height();\n\t }\n\t },\n\n\t visualStyle: function() {\n\t var style = BoxElement.fn.visualStyle.call(this);\n\t style.zIndex = -10;\n\n\t return style;\n\t },\n\n\t renderComplete: function() {\n\t if (this.options.visible) {\n\t this.createGridLines();\n\t }\n\t },\n\n\t stackRoot: function() {\n\t return this;\n\t },\n\n\t clipRoot: function() {\n\t return this;\n\t },\n\n\t createGridLines: function() {\n\t var axes = this.axes;\n\t var allAxes = axes.concat(this.parent.axes);\n\t var vGridLines = [];\n\t var hGridLines = [];\n\n\t // TODO\n\t // Is full combination really necessary?\n\t for (var i = 0; i < axes.length; i++) {\n\t var axis = axes[i];\n\t var vertical = axis.options.vertical;\n\t var gridLines = vertical ? vGridLines : hGridLines;\n\t for (var j = 0; j < allAxes.length; j++) {\n\t if (gridLines.length === 0) {\n\t var altAxis = allAxes[j];\n\t if (vertical !== altAxis.options.vertical) {\n\t append(gridLines, axis.createGridLines(altAxis));\n\t }\n\t }\n\t }\n\t }\n\t },\n\n\t refresh: function() {\n\t this.visual.clear();\n\n\t this.content.parent = null;\n\t this.content.createGradient = this.createGradient.bind(this);\n\t this.content.renderVisual();\n\t this.content.parent = this;\n\n\t if (this.title) {\n\t this.visual.append(this.title.visual);\n\t }\n\n\t this.visual.append(this.content.visual);\n\n\t this.renderComplete();\n\t this.notifyRender();\n\t },\n\n\t chartsBox: function() {\n\t var axes = this.axes;\n\t var length = axes.length;\n\t var chartsBox = new Box();\n\n\t for (var idx = 0; idx < length; idx++) {\n\t var axis = axes[idx];\n\t var axisValueField = axis.options.vertical ? Y : X;\n\t var lineBox = axis.lineBox();\n\t chartsBox[axisValueField + 1] = lineBox[axisValueField + 1];\n\t chartsBox[axisValueField + 2] = lineBox[axisValueField + 2];\n\t }\n\n\t if (chartsBox.x2 === 0) {\n\t var allAxes = this.parent.axes;\n\t var length$1 = allAxes.length;\n\n\t for (var idx$1 = 0; idx$1 < length$1; idx$1++) {\n\t var axis$1 = allAxes[idx$1];\n\t if (!axis$1.options.vertical) {\n\t var lineBox$1 = axis$1.lineBox();\n\t chartsBox.x1 = lineBox$1.x1;\n\t chartsBox.x2 = lineBox$1.x2;\n\t }\n\t }\n\t }\n\t return chartsBox;\n\t },\n\n\t clipBox: function() {\n\t return this.chartContainer.clipBox;\n\t },\n\n\t notifyRender: function() {\n\t var service = this.getService();\n\t if (service) {\n\t service.notify(PANE_RENDER, {\n\t pane: new ChartPane(this),\n\t index: this.paneIndex,\n\t name: this.options.name\n\t });\n\t }\n\t }\n\t});\n\n\tvar ID = 1;\n\n\tfunction paneID() {\n\t return \"pane\" + ID++;\n\t}\n\n\tPane.prototype.isStackRoot = true;\n\n\tsetDefaultOptions(Pane, {\n\t zIndex: -1,\n\t shrinkToFit: true,\n\t title: {\n\t align: LEFT\n\t },\n\t visible: true\n\t});\n\n\tfunction appendIfNotNull(array, element) {\n\t if (element !== null) {\n\t array.push(element);\n\t }\n\t}\n\n\tfunction segmentVisible(series, fields, index) {\n\t var visible = fields.visible;\n\t if (defined(visible)) {\n\t return visible;\n\t }\n\n\t var pointVisibility = series.pointVisibility;\n\t if (pointVisibility) {\n\t return pointVisibility[index];\n\t }\n\t}\n\n\tfunction bindSegments(series) {\n\t var data = series.data;\n\t var points = [];\n\t var sum = 0;\n\t var count = 0;\n\n\t for (var idx = 0; idx < data.length; idx++) {\n\t var pointData = SeriesBinder.current.bindPoint(series, idx);\n\t var value = pointData.valueFields.value;\n\n\t if (isString(value)) {\n\t value = parseFloat(value);\n\t }\n\n\t if (isNumber(value)) {\n\t pointData.visible = segmentVisible(series, pointData.fields, idx) !== false;\n\n\t pointData.value = Math.abs(value);\n\t points.push(pointData);\n\n\t if (pointData.visible) {\n\t sum += pointData.value;\n\t }\n\n\t if (value !== 0) {\n\t count++;\n\t }\n\t } else {\n\t points.push(null);\n\t }\n\t }\n\n\t return {\n\t total: sum,\n\t points: points,\n\t count: count\n\t };\n\t}\n\n\tfunction equalsIgnoreCase(a, b) {\n\t if (a && b) {\n\t return a.toLowerCase() === b.toLowerCase();\n\t }\n\n\t return a === b;\n\t}\n\n\tfunction filterSeriesByType(series, types) {\n\t var result = [];\n\n\t var seriesTypes = [].concat(types);\n\t for (var idx = 0; idx < series.length; idx++) {\n\t var currentSeries = series[idx];\n\t if (inArray(currentSeries.type, seriesTypes)) {\n\t result.push(currentSeries);\n\t }\n\t }\n\n\t return result;\n\t}\n\n\tfunction getDateField(field, row, intlService) {\n\t if (row === null) {\n\t return row;\n\t }\n\n\t var key = \"_date_\" + field;\n\t var value = row[key];\n\n\t if (!value) {\n\t value = parseDate(intlService, getter(field, true)(row));\n\t row[key] = value;\n\t }\n\n\t return value;\n\t}\n\n\tfunction isDateAxis(axisOptions, sampleCategory) {\n\t var type = axisOptions.type;\n\t var dateCategory = sampleCategory instanceof Date;\n\n\t return (!type && dateCategory) || equalsIgnoreCase(type, DATE);\n\t}\n\n\tfunction singleItemOrArray(array) {\n\t return array.length === 1 ? array[0] : array;\n\t}\n\n\tvar AREA_REGEX = /area/i;\n\n\tfunction seriesMissingValues(series) {\n\t if (series.missingValues) {\n\t return series.missingValues;\n\t }\n\n\t return AREA_REGEX.test(series.type) || series.stack ? ZERO : INTERPOLATE;\n\t}\n\n\tfunction hasValue$1(series, item) {\n\t var fields = SeriesBinder.current.bindPoint(series, null, item);\n\t var valueFields = fields.valueFields;\n\n\t for (var field in valueFields) {\n\t if (dataviz.convertableToNumber(valueFields[field])) {\n\t return true;\n\t }\n\t }\n\t}\n\n\tfunction findNext(ref) {\n\t var start = ref.start;\n\t var dir = ref.dir;\n\t var min = ref.min;\n\t var max = ref.max;\n\t var getter$$1 = ref.getter;\n\t var hasItem = ref.hasItem;\n\t var series = ref.series;\n\n\t var pointHasValue, outPoint;\n\t var idx = start;\n\t do {\n\t idx += dir;\n\t //aggregating and binding the item takes too much time for large number of categories\n\t //will assume that if the aggregation does not create value for a missing item for one it will not create for others\n\t if (hasItem(idx)) {\n\t outPoint = getter$$1(idx);\n\t pointHasValue = hasValue$1(series, outPoint.item);\n\t }\n\t } while (min <= idx && idx <= max && !pointHasValue);\n\n\t if (pointHasValue) {\n\t return outPoint;\n\t }\n\t}\n\n\tfunction createOutOfRangePoints(series, range, count, getter$$1, hasItem) {\n\t var min = range.min;\n\t var max = range.max;\n\t var hasMinPoint = min > 0 && min < count;\n\t var hasMaxPoint = max + 1 < count;\n\n\t if (hasMinPoint || hasMaxPoint) {\n\t var missingValues = seriesMissingValues(series);\n\t var minPoint, maxPoint;\n\t if (missingValues !== INTERPOLATE) {\n\t if (hasMinPoint) {\n\t minPoint = getter$$1(min - 1);\n\t }\n\n\t if (hasMaxPoint) {\n\t maxPoint = getter$$1(max + 1);\n\t }\n\t } else {\n\t var outPoint, pointHasValue;\n\t if (hasMinPoint) {\n\t outPoint = getter$$1(min - 1);\n\t pointHasValue = hasValue$1(series, outPoint.item);\n\t if (!pointHasValue) {\n\t minPoint = findNext({\n\t start: min,\n\t dir: -1,\n\t min: 0,\n\t max: count - 1,\n\t getter: getter$$1,\n\t hasItem: hasItem,\n\t series: series\n\t });\n\t } else {\n\t minPoint = outPoint;\n\t }\n\t }\n\n\t if (hasMaxPoint) {\n\t outPoint = getter$$1(max + 1);\n\t pointHasValue = hasValue$1(series, outPoint.item);\n\t if (!pointHasValue) {\n\t maxPoint = findNext({\n\t start: max,\n\t dir: 1,\n\t min: 0,\n\t max: count - 1,\n\t getter: getter$$1,\n\t hasItem: hasItem,\n\t series: series\n\t });\n\t } else {\n\t maxPoint = outPoint;\n\t }\n\t }\n\t }\n\n\t if (minPoint) {\n\t series._outOfRangeMinPoint = minPoint;\n\t }\n\n\t if (maxPoint) {\n\t series._outOfRangeMaxPoint = maxPoint;\n\t }\n\t }\n\t}\n\n\tvar PlotAreaBase = ChartElement.extend({\n\t init: function(series, options, chartService) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.initFields(series, options);\n\t this.series = series;\n\t this.initSeries();\n\t this.charts = [];\n\t this.options.legend = this.options.legend || {};\n\t this.options.legend.items = [];\n\t this.axes = [];\n\t this.crosshairs = [];\n\t this.chartService = chartService;\n\t this.originalOptions = options;\n\n\t this.createPanes();\n\t this.render();\n\t this.createCrosshairs();\n\t },\n\n\t initFields: function() { },\n\n\t initSeries: function() {\n\t var series = this.series;\n\n\t for (var i = 0; i < series.length; i++) {\n\t series[i].index = i;\n\t }\n\t },\n\n\t createPanes: function() {\n\t var this$1 = this;\n\n\t var defaults = { title: { color: (this.options.title || {}).color } };\n\t var panes = [];\n\t var paneOptions = this.options.panes || [];\n\t var panesLength = Math.max(paneOptions.length, 1);\n\n\t function setTitle(options, defaults) {\n\t if (isString(options.title)) {\n\t options.title = {\n\t text: options.title\n\t };\n\t }\n\n\t options.title = deepExtend({}, defaults.title, options.title);\n\t }\n\n\t for (var i = 0; i < panesLength; i++) {\n\t var options = paneOptions[i] || {};\n\t setTitle(options, defaults);\n\n\t var currentPane = new Pane(options);\n\t currentPane.paneIndex = i;\n\n\t panes.push(currentPane);\n\t this$1.append(currentPane);\n\t }\n\n\t this.panes = panes;\n\t },\n\n\t createCrosshairs: function(panes) {\n\t var this$1 = this;\n\t if (panes === void 0) { panes = this.panes; }\n\n\t for (var i = 0; i < panes.length; i++) {\n\t var pane = panes[i];\n\t for (var j = 0; j < pane.axes.length; j++) {\n\t var axis = pane.axes[j];\n\t if (axis.options.crosshair && axis.options.crosshair.visible) {\n\t var currentCrosshair = new Crosshair(this$1.chartService, axis, axis.options.crosshair);\n\n\t this$1.crosshairs.push(currentCrosshair);\n\t pane.content.append(currentCrosshair);\n\t }\n\t }\n\t }\n\t },\n\n\t removeCrosshairs: function(pane) {\n\t var crosshairs = this.crosshairs;\n\t var axes = pane.axes;\n\n\t for (var i = crosshairs.length - 1; i >= 0; i--) {\n\t for (var j = 0; j < axes.length; j++) {\n\t if (crosshairs[i].axis === axes[j]) {\n\t crosshairs.splice(i, 1);\n\t break;\n\t }\n\t }\n\t }\n\t },\n\n\t hideCrosshairs: function() {\n\t var crosshairs = this.crosshairs;\n\t for (var idx = 0; idx < crosshairs.length; idx++) {\n\t crosshairs[idx].hide();\n\t }\n\t },\n\n\t findPane: function(name) {\n\t var panes = this.panes;\n\t var matchingPane;\n\n\t for (var i = 0; i < panes.length; i++) {\n\t if (panes[i].options.name === name) {\n\t matchingPane = panes[i];\n\t break;\n\t }\n\t }\n\n\t return matchingPane || panes[0];\n\t },\n\n\t findPointPane: function(point) {\n\t var panes = this.panes;\n\t var matchingPane;\n\n\t for (var i = 0; i < panes.length; i++) {\n\t if (panes[i].box.containsPoint(point)) {\n\t matchingPane = panes[i];\n\t break;\n\t }\n\t }\n\n\t return matchingPane;\n\t },\n\n\t appendAxis: function(axis) {\n\t var pane = this.findPane(axis.options.pane);\n\n\t pane.appendAxis(axis);\n\t this.axes.push(axis);\n\t axis.plotArea = this;\n\t },\n\n\t removeAxis: function(axisToRemove) {\n\t var this$1 = this;\n\n\t var filteredAxes = [];\n\n\t for (var i = 0; i < this.axes.length; i++) {\n\t var axis = this$1.axes[i];\n\t if (axisToRemove !== axis) {\n\t filteredAxes.push(axis);\n\t } else {\n\t axis.destroy();\n\t }\n\t }\n\n\t this.axes = filteredAxes;\n\t },\n\n\t appendChart: function(chart, pane) {\n\t this.charts.push(chart);\n\t if (pane) {\n\t pane.appendChart(chart);\n\t } else {\n\t this.append(chart);\n\t }\n\t },\n\n\t removeChart: function(chartToRemove) {\n\t var this$1 = this;\n\n\t var filteredCharts = [];\n\n\t for (var i = 0; i < this.charts.length; i++) {\n\t var chart = this$1.charts[i];\n\t if (chart !== chartToRemove) {\n\t filteredCharts.push(chart);\n\t } else {\n\t chart.destroy();\n\t }\n\t }\n\n\t this.charts = filteredCharts;\n\t },\n\n\t addToLegend: function(series) {\n\t var count = series.length;\n\t var legend = this.options.legend;\n\t var labels = legend.labels || {};\n\t var inactiveItems = legend.inactiveItems || {};\n\t var inactiveItemsLabels = inactiveItems.labels || {};\n\t var data = [];\n\n\t for (var i = 0; i < count; i++) {\n\t var currentSeries = series[i];\n\t var seriesVisible = currentSeries.visible !== false;\n\t if (currentSeries.visibleInLegend === false) {\n\t continue;\n\t }\n\n\t var text = currentSeries.name;\n\t var labelTemplate = seriesVisible ? getTemplate(labels) : getTemplate(inactiveItemsLabels) || getTemplate(labels);\n\t if (labelTemplate) {\n\t text = labelTemplate({\n\t text: hasValue(text) ? text : \"\",\n\t series: currentSeries\n\t });\n\t }\n\n\t var defaults = currentSeries._defaults;\n\t var color = currentSeries.color;\n\t if (isFunction(color) && defaults) {\n\t color = defaults.color;\n\t }\n\n\t var itemLabelOptions = (void 0), markerColor = (void 0);\n\t if (seriesVisible) {\n\t itemLabelOptions = {};\n\t markerColor = color;\n\t } else {\n\t itemLabelOptions = {\n\t color: inactiveItemsLabels.color,\n\t font: inactiveItemsLabels.font\n\t };\n\t markerColor = inactiveItems.markers.color;\n\t }\n\n\t if (hasValue(text) && text !== \"\") {\n\t data.push({\n\t text: text,\n\t labels: itemLabelOptions,\n\t markerColor: markerColor,\n\t series: currentSeries,\n\t active: seriesVisible\n\t });\n\t }\n\t }\n\n\t append(legend.items, data);\n\t },\n\n\t groupAxes: function(panes) {\n\t var xAxes = [];\n\t var yAxes = [];\n\n\t for (var paneIx = 0; paneIx < panes.length; paneIx++) {\n\t var paneAxes = panes[paneIx].axes;\n\t for (var axisIx = 0; axisIx < paneAxes.length; axisIx++) {\n\t var axis = paneAxes[axisIx];\n\t if (axis.options.vertical) {\n\t yAxes.push(axis);\n\t } else {\n\t xAxes.push(axis);\n\t }\n\t }\n\t }\n\n\t return { x: xAxes, y: yAxes, any: xAxes.concat(yAxes) };\n\t },\n\n\t groupSeriesByPane: function() {\n\t var this$1 = this;\n\n\t var series = this.series;\n\t var seriesByPane = {};\n\n\t for (var i = 0; i < series.length; i++) {\n\t var currentSeries = series[i];\n\t var pane = this$1.seriesPaneName(currentSeries);\n\n\t if (seriesByPane[pane]) {\n\t seriesByPane[pane].push(currentSeries);\n\t } else {\n\t seriesByPane[pane] = [ currentSeries ];\n\t }\n\t }\n\n\t return seriesByPane;\n\t },\n\n\t filterVisibleSeries: function(series) {\n\t var result = [];\n\n\t for (var i = 0; i < series.length; i++) {\n\t var currentSeries = series[i];\n\t if (currentSeries.visible !== false) {\n\t result.push(currentSeries);\n\t }\n\t }\n\n\t return result;\n\t },\n\n\t reflow: function(targetBox) {\n\t var options = this.options.plotArea;\n\t var panes = this.panes;\n\t var margin = getSpacing(options.margin);\n\n\t this.box = targetBox.clone().unpad(margin);\n\t this.reflowPanes();\n\n\t this.detachLabels();\n\t this.reflowAxes(panes);\n\t this.reflowCharts(panes);\n\t },\n\n\t redraw: function(panes) {\n\t var this$1 = this;\n\n\t var panesArray = [].concat(panes);\n\t this.initSeries();\n\n\t //prevents leak during partial redraws. the cached gradients observers retain reference to the destroyed elements.\n\t var root = this.getRoot();\n\t if (root) {\n\t root.cleanGradients();\n\t }\n\n\t for (var i = 0; i < panesArray.length; i++) {\n\t this$1.removeCrosshairs(panesArray[i]);\n\t panesArray[i].empty();\n\t }\n\n\t this.render(panesArray);\n\t this.detachLabels();\n\t this.reflowAxes(this.panes);\n\t this.reflowCharts(panesArray);\n\n\t this.createCrosshairs(panesArray);\n\n\t for (var i$1 = 0; i$1 < panesArray.length; i$1++) {\n\t panesArray[i$1].refresh();\n\t }\n\t },\n\n\t axisCrossingValues: function(axis, crossingAxes) {\n\t var options = axis.options;\n\t var crossingValues = [].concat(\n\t options.axisCrossingValues || options.axisCrossingValue\n\t );\n\t var valuesToAdd = crossingAxes.length - crossingValues.length;\n\t var defaultValue = crossingValues[0] || 0;\n\n\t for (var i = 0; i < valuesToAdd; i++) {\n\t crossingValues.push(defaultValue);\n\t }\n\n\t return crossingValues;\n\t },\n\n\t alignAxisTo: function(axis, targetAxis, crossingValue, targetCrossingValue) {\n\t var slot = axis.getSlot(crossingValue, crossingValue, true);\n\t var slotEdge = axis.options.reverse ? 2 : 1;\n\t var targetSlot = targetAxis.getSlot(targetCrossingValue, targetCrossingValue, true);\n\t var targetEdge = targetAxis.options.reverse ? 2 : 1;\n\t var axisBox = axis.box.translate(\n\t targetSlot[X + targetEdge] - slot[X + slotEdge],\n\t targetSlot[Y + targetEdge] - slot[Y + slotEdge]\n\t );\n\n\t if (axis.pane !== targetAxis.pane) {\n\t axisBox.translate(0, axis.pane.box.y1 - targetAxis.pane.box.y1);\n\t }\n\n\t axis.reflow(axisBox);\n\t },\n\n\t alignAxes: function(xAxes, yAxes) {\n\t var this$1 = this;\n\n\t var xAnchor = xAxes[0];\n\t var yAnchor = yAxes[0];\n\t var xAnchorCrossings = this.axisCrossingValues(xAnchor, yAxes);\n\t var yAnchorCrossings = this.axisCrossingValues(yAnchor, xAxes);\n\t var leftAnchors = {};\n\t var rightAnchors = {};\n\t var topAnchors = {};\n\t var bottomAnchors = {};\n\n\t for (var i = 0; i < yAxes.length; i++) {\n\t var axis = yAxes[i];\n\t var pane = axis.pane;\n\t var paneId = pane.id;\n\t var visible = axis.options.visible !== false;\n\n\t // Locate pane anchor, if any, and use its axisCrossingValues\n\t var anchor = paneAnchor(xAxes, pane) || xAnchor;\n\t var anchorCrossings = xAnchorCrossings;\n\n\t if (anchor !== xAnchor) {\n\t anchorCrossings = this$1.axisCrossingValues(anchor, yAxes);\n\t }\n\n\t this$1.alignAxisTo(axis, anchor, yAnchorCrossings[i], anchorCrossings[i]);\n\n\t if (axis.options._overlap) {\n\t continue;\n\t }\n\n\t if (round(axis.lineBox().x1) === round(anchor.lineBox().x1)) {\n\t // Push the axis to the left the previous y-axis so they don't overlap\n\t if (leftAnchors[paneId]) {\n\t axis.reflow(axis.box\n\t .alignTo(leftAnchors[paneId].box, LEFT)\n\t .translate(-axis.options.margin, 0)\n\t );\n\t }\n\n\t if (visible) {\n\t leftAnchors[paneId] = axis;\n\t }\n\t }\n\n\t if (round(axis.lineBox().x2) === round(anchor.lineBox().x2)) {\n\t // Flip the labels on the right if we're at the right end of the pane\n\t if (!axis._mirrored) {\n\t axis.options.labels.mirror = !axis.options.labels.mirror;\n\t axis._mirrored = true;\n\t }\n\n\t this$1.alignAxisTo(axis, anchor, yAnchorCrossings[i], anchorCrossings[i]);\n\n\t // Push the axis to the right the previous y-axis so they don't overlap\n\t if (rightAnchors[paneId]) {\n\t axis.reflow(axis.box\n\t .alignTo(rightAnchors[paneId].box, RIGHT)\n\t .translate(axis.options.margin, 0)\n\t );\n\t }\n\n\t if (visible) {\n\t rightAnchors[paneId] = axis;\n\t }\n\t }\n\n\t if (i !== 0 && yAnchor.pane === axis.pane) {\n\t axis.alignTo(yAnchor);\n\t axis.reflow(axis.box);\n\t }\n\t }\n\n\t for (var i$1 = 0; i$1 < xAxes.length; i$1++) {\n\t var axis$1 = xAxes[i$1];\n\t var pane$1 = axis$1.pane;\n\t var paneId$1 = pane$1.id;\n\t var visible$1 = axis$1.options.visible !== false;\n\n\t // Locate pane anchor and use its axisCrossingValues\n\t var anchor$1 = paneAnchor(yAxes, pane$1) || yAnchor;\n\t var anchorCrossings$1 = yAnchorCrossings;\n\t if (anchor$1 !== yAnchor) {\n\t anchorCrossings$1 = this$1.axisCrossingValues(anchor$1, xAxes);\n\t }\n\n\t this$1.alignAxisTo(axis$1, anchor$1, xAnchorCrossings[i$1], anchorCrossings$1[i$1]);\n\n\t if (axis$1.options._overlap) {\n\t continue;\n\t }\n\n\t if (round(axis$1.lineBox().y1) === round(anchor$1.lineBox().y1)) {\n\t // Flip the labels on top if we're at the top of the pane\n\t if (!axis$1._mirrored) {\n\t axis$1.options.labels.mirror = !axis$1.options.labels.mirror;\n\t axis$1._mirrored = true;\n\t }\n\t this$1.alignAxisTo(axis$1, anchor$1, xAnchorCrossings[i$1], anchorCrossings$1[i$1]);\n\n\t // Push the axis above the previous x-axis so they don't overlap\n\t if (topAnchors[paneId$1]) {\n\t axis$1.reflow(axis$1.box\n\t .alignTo(topAnchors[paneId$1].box, TOP)\n\t .translate(0, -axis$1.options.margin)\n\t );\n\t }\n\n\t if (visible$1) {\n\t topAnchors[paneId$1] = axis$1;\n\t }\n\t }\n\n\t if (round(axis$1.lineBox().y2, datavizConstants.COORD_PRECISION) === round(anchor$1.lineBox().y2, datavizConstants.COORD_PRECISION)) {\n\t // Push the axis below the previous x-axis so they don't overlap\n\t if (bottomAnchors[paneId$1]) {\n\t axis$1.reflow(axis$1.box\n\t .alignTo(bottomAnchors[paneId$1].box, BOTTOM)\n\t .translate(0, axis$1.options.margin)\n\t );\n\t }\n\n\t if (visible$1) {\n\t bottomAnchors[paneId$1] = axis$1;\n\t }\n\t }\n\n\t if (i$1 !== 0) {\n\t axis$1.alignTo(xAnchor);\n\t axis$1.reflow(axis$1.box);\n\t }\n\t }\n\t },\n\n\t shrinkAxisWidth: function(panes) {\n\t var axes = this.groupAxes(panes).any;\n\t var axisBox = axisGroupBox(axes);\n\t var overflowX = 0;\n\n\t for (var i = 0; i < panes.length; i++) {\n\t var currentPane = panes[i];\n\n\t if (currentPane.axes.length > 0) {\n\t overflowX = Math.max(\n\t overflowX,\n\t axisBox.width() - currentPane.contentBox.width()\n\t );\n\t }\n\t }\n\n\t if (overflowX !== 0) {\n\t for (var i$1 = 0; i$1 < axes.length; i$1++) {\n\t var currentAxis = axes[i$1];\n\n\t if (!currentAxis.options.vertical) {\n\t currentAxis.reflow(currentAxis.box.shrink(overflowX, 0));\n\t }\n\t }\n\t }\n\t },\n\n\t shrinkAxisHeight: function(panes) {\n\t var shrinked;\n\n\t for (var i = 0; i < panes.length; i++) {\n\t var currentPane = panes[i];\n\t var axes = currentPane.axes;\n\t var overflowY = Math.max(0, axisGroupBox(axes).height() - currentPane.contentBox.height());\n\n\t if (overflowY !== 0) {\n\t for (var j = 0; j < axes.length; j++) {\n\t var currentAxis = axes[j];\n\n\t if (currentAxis.options.vertical) {\n\t currentAxis.reflow(\n\t currentAxis.box.shrink(0, overflowY)\n\t );\n\t }\n\t }\n\t shrinked = true;\n\t }\n\t }\n\n\t return shrinked;\n\t },\n\n\t fitAxes: function(panes) {\n\t var axes = this.groupAxes(panes).any;\n\t var offsetX = 0;\n\n\t for (var i = 0; i < panes.length; i++) {\n\t var currentPane = panes[i];\n\t var paneAxes = currentPane.axes;\n\t var paneBox = currentPane.contentBox;\n\n\t if (paneAxes.length > 0) {\n\t var axisBox = axisGroupBox(paneAxes);\n\t // OffsetY is calculated and applied per pane\n\t var offsetY = Math.max(paneBox.y1 - axisBox.y1, paneBox.y2 - axisBox.y2);\n\n\t // OffsetX is calculated and applied globally\n\t offsetX = Math.max(offsetX, paneBox.x1 - axisBox.x1);\n\n\t for (var j = 0; j < paneAxes.length; j++) {\n\t var currentAxis = paneAxes[j];\n\n\t currentAxis.reflow(\n\t currentAxis.box.translate(0, offsetY)\n\t );\n\t }\n\t }\n\t }\n\n\t for (var i$1 = 0; i$1 < axes.length; i$1++) {\n\t var currentAxis$1 = axes[i$1];\n\n\t currentAxis$1.reflow(\n\t currentAxis$1.box.translate(offsetX, 0)\n\t );\n\t }\n\t },\n\n\t reflowAxes: function(panes) {\n\t var this$1 = this;\n\n\t var axes = this.groupAxes(panes);\n\n\t for (var i = 0; i < panes.length; i++) {\n\t this$1.reflowPaneAxes(panes[i]);\n\t }\n\n\t if (axes.x.length > 0 && axes.y.length > 0) {\n\t this.alignAxes(axes.x, axes.y);\n\t this.shrinkAxisWidth(panes);\n\n\t this.autoRotateAxisLabels(axes);\n\n\t this.alignAxes(axes.x, axes.y);\n\t if (this.shrinkAxisWidth(panes)) {\n\t this.alignAxes(axes.x, axes.y);\n\t }\n\n\t this.shrinkAxisHeight(panes);\n\t this.alignAxes(axes.x, axes.y);\n\n\t if (this.shrinkAxisHeight(panes)) {\n\t this.alignAxes(axes.x, axes.y);\n\t }\n\n\t this.fitAxes(panes);\n\t }\n\t },\n\n\t autoRotateAxisLabels: function(groupedAxes) {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var panes = ref.panes;\n\t var axes = allPaneAxes(panes);\n\t var rotated;\n\n\t for (var idx = 0; idx < axes.length; idx++) {\n\t var axis = axes[idx];\n\t if (axis.autoRotateLabels()) {\n\t rotated = true;\n\t }\n\t }\n\n\t if (rotated) {\n\t for (var idx$1 = 0; idx$1 < panes.length; idx$1++) {\n\t this$1.reflowPaneAxes(panes[idx$1]);\n\t }\n\n\t if (groupedAxes.x.length > 0 && groupedAxes.y.length > 0) {\n\t this.alignAxes(groupedAxes.x, groupedAxes.y);\n\t this.shrinkAxisWidth(panes);\n\t }\n\t }\n\t },\n\n\t reflowPaneAxes: function(pane) {\n\t var axes = pane.axes;\n\t var length = axes.length;\n\n\t if (length > 0) {\n\t for (var i = 0; i < length; i++) {\n\t axes[i].reflow(pane.contentBox);\n\t }\n\t }\n\t },\n\n\t reflowCharts: function(panes) {\n\t var charts = this.charts;\n\t var count = charts.length;\n\t var box = this.box;\n\n\t for (var i = 0; i < count; i++) {\n\t var chartPane = charts[i].pane;\n\t if (!chartPane || inArray(chartPane, panes)) {\n\t charts[i].reflow(box);\n\t }\n\t }\n\t },\n\n\t reflowPanes: function() {\n\t var ref = this;\n\t var box = ref.box;\n\t var panes = ref.panes;\n\t var panesLength = panes.length;\n\t var remainingHeight = box.height();\n\t var remainingPanes = panesLength;\n\t var autoHeightPanes = 0;\n\t var top = box.y1;\n\n\t for (var i = 0; i < panesLength; i++) {\n\t var currentPane = panes[i];\n\t var height = currentPane.options.height;\n\n\t currentPane.options.width = box.width();\n\n\t if (!currentPane.options.height) {\n\t autoHeightPanes++;\n\t } else {\n\t if (height.indexOf && height.indexOf(\"%\")) {\n\t var percents = parseInt(height, 10) / 100;\n\t currentPane.options.height = percents * box.height();\n\t }\n\n\t currentPane.reflow(box.clone());\n\n\t remainingHeight -= currentPane.options.height;\n\t }\n\t }\n\n\t for (var i$1 = 0; i$1 < panesLength; i$1++) {\n\t var currentPane$1 = panes[i$1];\n\n\t if (!currentPane$1.options.height) {\n\t currentPane$1.options.height = remainingHeight / autoHeightPanes;\n\t }\n\t }\n\n\t for (var i$2 = 0; i$2 < panesLength; i$2++) {\n\t var currentPane$2 = panes[i$2];\n\t var paneBox = box\n\t .clone()\n\t .move(box.x1, top);\n\n\t currentPane$2.reflow(paneBox);\n\n\t remainingPanes--;\n\t top += currentPane$2.options.height;\n\t }\n\t },\n\n\t backgroundBox: function() {\n\t var axes = this.axes;\n\t var axesCount = axes.length;\n\t var box;\n\n\t for (var i = 0; i < axesCount; i++) {\n\t var axisA = axes[i];\n\n\t for (var j = 0; j < axesCount; j++) {\n\t var axisB = axes[j];\n\n\t if (axisA.options.vertical !== axisB.options.vertical) {\n\t var lineBox = axisA.lineBox().clone().wrap(axisB.lineBox());\n\n\t if (!box) {\n\t box = lineBox;\n\t } else {\n\t box = box.wrap(lineBox);\n\t }\n\t }\n\t }\n\t }\n\n\t return box || this.box;\n\t },\n\n\t chartsBoxes: function() {\n\t var panes = this.panes;\n\t var boxes = [];\n\n\t for (var idx = 0; idx < panes.length; idx++) {\n\t boxes.push(panes[idx].chartsBox());\n\t }\n\n\t return boxes;\n\t },\n\n\t addBackgroundPaths: function(multipath) {\n\t var boxes = this.chartsBoxes();\n\t for (var idx = 0; idx < boxes.length; idx++) {\n\t multipath.paths.push(Path.fromRect(boxes[idx].toRect()));\n\t }\n\t },\n\n\t backgroundContainsPoint: function(point) {\n\t var boxes = this.chartsBoxes();\n\t for (var idx = 0; idx < boxes.length; idx++) {\n\t if (boxes[idx].containsPoint(point)) {\n\t return true;\n\t }\n\t }\n\t },\n\n\t createVisual: function() {\n\t ChartElement.fn.createVisual.call(this);\n\n\t var options = this.options.plotArea;\n\t var opacity = options.opacity;\n\t var background = options.background;\n\t var border = options.border; if (border === void 0) { border = {}; }\n\t if (isTransparent(background)) {\n\t background = WHITE;\n\t opacity = 0;\n\t }\n\n\t var bg = this._bgVisual = new drawing.MultiPath({\n\t fill: {\n\t color: background,\n\t opacity: opacity\n\t },\n\t stroke: {\n\t color: border.width ? border.color : \"\",\n\t width: border.width,\n\t dashType: border.dashType\n\t },\n\t zIndex: -1\n\t });\n\n\t this.addBackgroundPaths(bg);\n\n\t this.appendVisual(bg);\n\t },\n\n\t pointsByCategoryIndex: function(categoryIndex) {\n\t var charts = this.charts;\n\t var result = [];\n\n\t if (categoryIndex !== null) {\n\t for (var i = 0; i < charts.length; i++) {\n\t var chart = charts[i];\n\t if (chart.pane.options.name === \"_navigator\") {\n\t continue;\n\t }\n\n\t var points = charts[i].categoryPoints[categoryIndex];\n\t if (points && points.length) {\n\t for (var j = 0; j < points.length; j++) {\n\t var point = points[j];\n\t if (point && defined(point.value) && point.value !== null) {\n\t result.push(point);\n\t }\n\t }\n\t }\n\t }\n\t }\n\n\t return result;\n\t },\n\n\t pointsBySeriesIndex: function(seriesIndex) {\n\t return this.filterPoints(function(point) {\n\t return point.series.index === seriesIndex;\n\t });\n\t },\n\n\t pointsBySeriesName: function(name) {\n\t return this.filterPoints(function(point) {\n\t return point.series.name === name;\n\t });\n\t },\n\n\t filterPoints: function(callback) {\n\t var charts = this.charts;\n\t var result = [];\n\n\t for (var i = 0; i < charts.length; i++) {\n\t var chart = charts[i];\n\t var points = chart.points;\n\t for (var j = 0; j < points.length; j++) {\n\t var point = points[j];\n\t if (point && point.visible !== false && callback(point)) {\n\t result.push(point);\n\t }\n\t }\n\t }\n\n\t return result;\n\t },\n\n\t findPoint: function(callback) {\n\t var charts = this.charts;\n\n\t for (var i = 0; i < charts.length; i++) {\n\t var chart = charts[i];\n\t var points = chart.points;\n\t for (var j = 0; j < points.length; j++) {\n\t var point = points[j];\n\t if (point && point.visible !== false && callback(point)) {\n\t return point;\n\t }\n\t }\n\t }\n\t },\n\n\t paneByPoint: function(point) {\n\t var panes = this.panes;\n\n\t for (var i = 0; i < panes.length; i++) {\n\t var pane = panes[i];\n\t if (pane.box.containsPoint(point)) {\n\t return pane;\n\t }\n\t }\n\t },\n\n\t detachLabels: function() {\n\t var axes = this.groupAxes(this.panes);\n\t var xAxes = axes.x;\n\t var yAxes = axes.y;\n\n\t this.detachAxisGroupLabels(yAxes, xAxes);\n\t this.detachAxisGroupLabels(xAxes, yAxes);\n\t },\n\n\t detachAxisGroupLabels: function(axes, crossingAxes) {\n\t var this$1 = this;\n\n\t var labelAxisCount = 0;\n\n\t for (var i = 0; i < axes.length; i++) {\n\t var axis = axes[i];\n\t var pane = axis.pane;\n\t var anchor = paneAnchor(crossingAxes, pane) || crossingAxes[0];\n\t var axisIndex = i + labelAxisCount;\n\t var labelAxis = this$1.createLabelAxis(axis, axisIndex, anchor);\n\n\t if (labelAxis) {\n\t labelAxisCount++;\n\n\t var pos = pane.axes.indexOf(axis) + labelAxisCount;\n\t pane.appendAxisAt(labelAxis, pos);\n\t }\n\t }\n\t },\n\n\t createLabelAxis: function(axis, axisIndex, anchor) {\n\t var labelOptions = axis.options.labels;\n\t var position = labelOptions.position;\n\t var onAxis = position !== datavizConstants.END && position !== datavizConstants.START;\n\t var visible = labelOptions.visible;\n\n\t if (onAxis || visible === false) {\n\t return null;\n\t }\n\n\t var allAxes = this.groupAxes(this.panes);\n\t var crossingAxes = anchor.options.vertical ? allAxes.x : allAxes.y;\n\t var anchorCrossings = this.axisCrossingValues(anchor, crossingAxes);\n\t var end = position === datavizConstants.END;\n\t var range = anchor.range();\n\t var edge = end ? range.max : range.min;\n\t var crossingValue = limitValue(anchorCrossings[axisIndex], range.min, range.max);\n\n\t if (crossingValue - edge === 0) {\n\t return null;\n\t }\n\n\t anchorCrossings.splice(axisIndex + 1, 0, edge);\n\t anchor.options.axisCrossingValues = anchorCrossings;\n\n\t var labelAxis = axis.clone();\n\t axis.clear();\n\n\t labelAxis.options.name = undefined;\n\t labelAxis.options.line.visible = false;\n\n\t labelAxis.options.crosshair = undefined;\n\t labelAxis.options.notes = undefined;\n\t labelAxis.options.plotBands = undefined;\n\n\t return labelAxis;\n\t }\n\t});\n\n\tfunction isSingleAxis(axis) {\n\t return !axis.pane.axes.some(function (a) { return a.options.vertical === axis.options.vertical && a !== axis && a.options.visible !== false; }\n\t );\n\t}\n\n\tfunction axisGroupBox(axes) {\n\t var length = axes.length;\n\t var box;\n\n\t for (var i = 0; i < length; i++) {\n\t var axis = axes[i];\n\t var visible = axis.options.visible !== false;\n\t if (visible || isSingleAxis(axis)) {\n\t var axisBox = visible ? axis.contentBox() : axis.lineBox();\n\n\t if (!box) {\n\t box = axisBox.clone();\n\t } else {\n\t box.wrap(axisBox);\n\t }\n\t }\n\t }\n\n\t return box || new Box();\n\t}\n\n\tfunction paneAnchor(axes, pane) {\n\t for (var i = 0; i < axes.length; i++) {\n\t var anchor = axes[i];\n\t if (anchor && anchor.pane === pane) {\n\t return anchor;\n\t }\n\t }\n\t}\n\n\tfunction isTransparent(color) {\n\t return color === \"\" || color === null || color === \"none\" || color === \"transparent\" || !defined(color);\n\t}\n\n\tvar allPaneAxes = function (panes) { return panes.reduce(function (acc, pane) { return acc.concat(pane.axes); }, []); };\n\n\tsetDefaultOptions(PlotAreaBase, {\n\t series: [],\n\t plotArea: {\n\t margin: {}\n\t },\n\t background: \"\",\n\t border: {\n\t color: BLACK,\n\t width: 0\n\t },\n\t legend: {\n\t inactiveItems: {\n\t labels: {\n\t color: \"#919191\"\n\t },\n\t markers: {\n\t color: \"#919191\"\n\t }\n\t }\n\t }\n\t});\n\n\tvar PlotAreaEventsMixin = {\n\t hover: function(chart, e) {\n\t this._dispatchEvent(chart, e, PLOT_AREA_HOVER);\n\t },\n\n\t click: function(chart, e) {\n\t this._dispatchEvent(chart, e, PLOT_AREA_CLICK);\n\t }\n\t};\n\n\tvar SeriesAggregator = Class.extend({\n\t init: function(series, binder, defaultAggregates) {\n\n\t var canonicalFields = binder.canonicalFields(series);\n\t var valueFields = binder.valueFields(series);\n\t var sourceFields = binder.sourceFields(series, canonicalFields);\n\t var seriesFields = this._seriesFields = [];\n\t var defaults = defaultAggregates.query(series.type);\n\t var rootAggregate = series.aggregate || defaults;\n\n\t this._series = series;\n\t this._binder = binder;\n\n\t for (var i = 0; i < canonicalFields.length; i++) {\n\t var field = canonicalFields[i];\n\t var fieldAggregate = (void 0);\n\n\t if (isObject(rootAggregate)) {\n\t fieldAggregate = rootAggregate[field];\n\t } else if (i === 0 || inArray(field, valueFields)) {\n\t fieldAggregate = rootAggregate;\n\t } else {\n\t break;\n\t }\n\n\t if (fieldAggregate) {\n\t seriesFields.push({\n\t canonicalName: field,\n\t name: sourceFields[i],\n\t transform: isFunction(fieldAggregate) ? fieldAggregate : Aggregates[fieldAggregate]\n\t });\n\t }\n\t }\n\t },\n\n\t aggregatePoints: function(srcPoints, group) {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var series = ref._series;\n\t var seriesFields = ref._seriesFields;\n\t var data = this._bindPoints(srcPoints || []);\n\t var firstDataItem = data.dataItems[0];\n\t var result = {};\n\n\t if (firstDataItem && !isNumber(firstDataItem) && !isArray(firstDataItem)) {\n\t var fn = function() {};\n\t fn.prototype = firstDataItem;\n\t result = new fn();\n\t }\n\n\t for (var i = 0; i < seriesFields.length; i++) {\n\t var field = seriesFields[i];\n\t var srcValues = this$1._bindField(data.values, field.canonicalName);\n\t var value = field.transform(srcValues, series, data.dataItems, group);\n\n\t if (value !== null && isObject(value) && !defined(value.length) && !(value instanceof Date)) {\n\t result = value;\n\t break;\n\t } else {\n\t if (defined(value)) {\n\t setValue(field.name, result, value);\n\t }\n\t }\n\t }\n\n\t return result;\n\t },\n\n\t _bindPoints: function(points) {\n\t var ref = this;\n\t var binder = ref._binder;\n\t var series = ref._series;\n\t var values = [];\n\t var dataItems = [];\n\n\t for (var i = 0; i < points.length; i++) {\n\t var pointIx = points[i];\n\n\t values.push(binder.bindPoint(series, pointIx));\n\t dataItems.push(series.data[pointIx]);\n\t }\n\n\t return {\n\t values: values,\n\t dataItems: dataItems\n\t };\n\t },\n\n\t _bindField: function(data, field) {\n\t var values = [];\n\t var count = data.length;\n\n\t for (var i = 0; i < count; i++) {\n\t var item = data[i];\n\t var valueFields = item.valueFields;\n\t var value = (void 0);\n\n\t if (defined(valueFields[field])) {\n\t value = valueFields[field];\n\t } else {\n\t value = item.fields[field];\n\t }\n\n\t values.push(value);\n\t }\n\n\t return values;\n\t }\n\t});\n\n\tfunction setValue(fieldName, target, value) {\n\t var parentObj = target;\n\t var field = fieldName;\n\n\t if (fieldName.indexOf(\".\") > -1) {\n\t var parts = fieldName.split(\".\");\n\n\t while (parts.length > 1) {\n\t field = parts.shift();\n\t if (!defined(parentObj[field])) {\n\t parentObj[field] = {};\n\t }\n\t parentObj = parentObj[field];\n\t }\n\t field = parts.shift();\n\t }\n\n\t parentObj[field] = value;\n\t}\n\n\tvar DefaultAggregates = Class.extend({\n\t init: function() {\n\n\t this._defaults = {};\n\t },\n\n\t register: function(seriesTypes, aggregates) {\n\t var this$1 = this;\n\n\t for (var i = 0; i < seriesTypes.length; i++) {\n\t this$1._defaults[seriesTypes[i]] = aggregates;\n\t }\n\t },\n\n\t query: function(seriesType) {\n\t return this._defaults[seriesType];\n\t }\n\t});\n\n\tDefaultAggregates.current = new DefaultAggregates();\n\n\tvar RangeBar = Bar.extend({\n\t createLabel: function() {\n\t var labels = this.options.labels;\n\t var fromOptions = deepExtend({}, labels, labels.from);\n\t var toOptions = deepExtend({}, labels, labels.to);\n\n\t if (fromOptions.visible) {\n\t this.labelFrom = this._createLabel(fromOptions);\n\t this.append(this.labelFrom);\n\t }\n\n\t if (toOptions.visible) {\n\t this.labelTo = this._createLabel(toOptions);\n\t this.append(this.labelTo);\n\t }\n\t },\n\n\t _createLabel: function(options) {\n\t var labelTemplate = getTemplate(options);\n\t var pointData = this.pointData();\n\n\t var labelText;\n\n\t if (labelTemplate) {\n\t labelText = labelTemplate(pointData);\n\t } else {\n\t labelText = this.formatValue(options.format);\n\t }\n\n\t return new BarLabel(labelText,\n\t deepExtend({\n\t vertical: this.options.vertical\n\t },\n\t options\n\t ), pointData);\n\t },\n\n\t reflow: function(targetBox) {\n\t this.render();\n\n\t var ref = this;\n\t var labelFrom = ref.labelFrom;\n\t var labelTo = ref.labelTo;\n\t var value = ref.value;\n\n\t this.box = targetBox;\n\n\t if (labelFrom) {\n\t labelFrom.options.aboveAxis = value.from > value.to;\n\t labelFrom.reflow(targetBox);\n\t }\n\n\t if (labelTo) {\n\t labelTo.options.aboveAxis = value.to > value.from;\n\t labelTo.reflow(targetBox);\n\t }\n\n\t if (this.note) {\n\t this.note.reflow(targetBox);\n\t }\n\t }\n\t});\n\n\tRangeBar.prototype.defaults = deepExtend({}, RangeBar.prototype.defaults, {\n\t labels: {\n\t format: \"{0} - {1}\"\n\t },\n\t tooltip: {\n\t format: \"{1}\"\n\t }\n\t});\n\n\tvar RangeBarChart = BarChart.extend({\n\t pointType: function() {\n\t return RangeBar;\n\t },\n\n\t pointValue: function(data) {\n\t return data.valueFields;\n\t },\n\n\t formatPointValue: function(point, format) {\n\t if (point.value.from === null && point.value.to === null) {\n\t return \"\";\n\t }\n\n\t return this.chartService.format.auto(format, point.value.from, point.value.to);\n\t },\n\n\t plotRange: function(point) {\n\t if (!point) {\n\t return 0;\n\t }\n\n\t return [ point.value.from, point.value.to ];\n\t },\n\n\t updateRange: function(value, fields) {\n\t var axisName = fields.series.axis;\n\t var from = value.from;\n\t var to = value.to;\n\t var axisRange = this.valueAxisRanges[axisName];\n\n\t if (value !== null && isNumber(from) && isNumber(to)) {\n\t axisRange = this.valueAxisRanges[axisName] = axisRange || { min: MAX_VALUE, max: MIN_VALUE };\n\n\t axisRange.min = Math.min(axisRange.min, from);\n\t axisRange.max = Math.max(axisRange.max, from);\n\n\t axisRange.min = Math.min(axisRange.min, to);\n\t axisRange.max = Math.max(axisRange.max, to);\n\t }\n\t },\n\n\t aboveAxis: function(point) {\n\t var value = point.value;\n\t return value.from < value.to;\n\t }\n\t});\n\n\tRangeBarChart.prototype.plotLimits = CategoricalChart.prototype.plotLimits;\n\n\tvar RangeLinePoint = LinePoint.extend({\n\t aliasFor: function() {\n\t return this.parent;\n\t }\n\t});\n\n\tvar AUTO = 'auto';\n\tvar DEFAULT_FROM_FORMAT = '{0}';\n\tvar DEFAULT_TO_FORMAT = '{1}';\n\n\tvar RangeAreaPoint = ChartElement.extend({\n\t init: function(value, options) {\n\t ChartElement.fn.init.call(this);\n\n\t this.value = value;\n\t this.options = options;\n\t this.aboveAxis = valueOrDefault(this.options.aboveAxis, true);\n\t this.tooltipTracking = true;\n\t this.initLabelsFormat();\n\t },\n\n\t render: function() {\n\t if (this._rendered) {\n\t return;\n\t }\n\n\t this._rendered = true;\n\n\t var ref = this.options;\n\t var markers = ref.markers;\n\t var labels = ref.labels;\n\t var value = this.value;\n\n\t var fromPoint = this.fromPoint = new RangeLinePoint(value, deepExtend({}, this.options, {\n\t labels: labels.from,\n\t markers: markers.from\n\t }));\n\n\t var toPoint = this.toPoint = new RangeLinePoint(value, deepExtend({}, this.options, {\n\t labels: labels.to,\n\t markers: markers.to\n\t }));\n\n\t this.copyFields(fromPoint);\n\t this.copyFields(toPoint);\n\n\t this.append(fromPoint);\n\t this.append(toPoint);\n\t },\n\n\t reflow: function(targetBox) {\n\t this.render();\n\n\t var fromBox = targetBox.from;\n\t var toBox = targetBox.to;\n\n\t this.positionLabels(fromBox, toBox);\n\n\t this.fromPoint.reflow(fromBox);\n\t this.toPoint.reflow(toBox);\n\n\t this.box = this.fromPoint.markerBox().clone().wrap(this.toPoint.markerBox());\n\t },\n\n\t createHighlight: function() {\n\t var group = new Group();\n\t group.append(this.fromPoint.createHighlight());\n\t group.append(this.toPoint.createHighlight());\n\n\t return group;\n\t },\n\n\t highlightVisual: function() {\n\t return this.visual;\n\t },\n\n\t highlightVisualArgs: function() {\n\t return {\n\t options: this.options,\n\t from: this.fromPoint.highlightVisualArgs(),\n\t to: this.toPoint.highlightVisualArgs()\n\t };\n\t },\n\n\t tooltipAnchor: function() {\n\t var clipBox = this.owner.pane.clipBox();\n\t var showTooltip = !clipBox || clipBox.overlaps(this.box);\n\n\t if (showTooltip) {\n\t var box = this.box;\n\t var center = box.center();\n\t var horizontalAlign = LEFT;\n\t var x, y, verticalAlign;\n\n\t if (this.options.vertical) {\n\t x = center.x;\n\t y = box.y1 - TOOLTIP_OFFSET;\n\t verticalAlign = BOTTOM;\n\t } else {\n\t x = box.x2 + TOOLTIP_OFFSET;\n\t y = center.y;\n\t verticalAlign = CENTER;\n\t }\n\n\t return {\n\t point: new Point(x, y),\n\t align: {\n\t horizontal: horizontalAlign,\n\t vertical: verticalAlign\n\t }\n\t };\n\t }\n\t },\n\n\t formatValue: function(format) {\n\t return this.owner.formatPointValue(this, format);\n\t },\n\n\t overlapsBox: function(box) {\n\t return this.box.overlaps(box);\n\t },\n\n\t unclipElements: function() {\n\t this.fromPoint.unclipElements();\n\t this.toPoint.unclipElements();\n\t },\n\n\t initLabelsFormat: function() {\n\t var labels = this.options.labels;\n\t if (!labels.format) {\n\t if (!labels.from || !labels.from.format) {\n\t labels.from = $.extend({}, labels.from, {\n\t format: DEFAULT_FROM_FORMAT\n\t });\n\t }\n\n\t if (!labels.to || !labels.to.format) {\n\t labels.to = $.extend({}, labels.to, {\n\t format: DEFAULT_TO_FORMAT\n\t });\n\t }\n\t }\n\t },\n\n\t positionLabels: function(fromBox, toBox) {\n\t var ref = this.options;\n\t var labels = ref.labels;\n\t var vertical = ref.vertical;\n\n\t if (labels.position === AUTO) {\n\t var fromLabelPosition, toLabelPosition;\n\t if (vertical) {\n\t if (toBox.y1 <= fromBox.y1) {\n\t toLabelPosition = ABOVE;\n\t fromLabelPosition = BELOW;\n\t } else {\n\t toLabelPosition = BELOW;\n\t fromLabelPosition = ABOVE;\n\t }\n\t } else {\n\t if (toBox.x1 <= fromBox.x1) {\n\t toLabelPosition = LEFT;\n\t fromLabelPosition = RIGHT;\n\t } else {\n\t toLabelPosition = RIGHT;\n\t fromLabelPosition = LEFT;\n\t }\n\t }\n\n\t if (!labels.from || !labels.from.position) {\n\t this.fromPoint.options.labels.position = fromLabelPosition;\n\t }\n\n\t if (!labels.to || !labels.to.position) {\n\t this.toPoint.options.labels.position = toLabelPosition;\n\t }\n\t }\n\t },\n\n\t copyFields: function(point) {\n\t point.dataItem = this.dataItem;\n\t point.category = this.category;\n\t point.series = this.series;\n\t point.color = this.color;\n\t point.owner = this.owner;\n\t }\n\t});\n\n\tdeepExtend(RangeAreaPoint.prototype, PointEventsMixin);\n\tdeepExtend(RangeAreaPoint.prototype, NoteMixin);\n\n\tRangeAreaPoint.prototype.defaults = {\n\t markers: {\n\t visible: false,\n\t background: WHITE,\n\t size: LINE_MARKER_SIZE,\n\t type: CIRCLE,\n\t border: {\n\t width: 2\n\t },\n\t opacity: 1\n\t },\n\t labels: {\n\t visible: false,\n\t margin: getSpacing(3),\n\t padding: getSpacing(4),\n\t animation: {\n\t type: FADEIN,\n\t delay: INITIAL_ANIMATION_DURATION\n\t },\n\t position: AUTO\n\t },\n\t notes: {\n\t label: {}\n\t },\n\t highlight: {\n\t markers: {\n\t border: {\n\t color: WHITE,\n\t width: 2\n\t }\n\t },\n\t zIndex: datavizConstants.HIGHLIGHT_ZINDEX\n\t },\n\t tooltip: {\n\t format: '{0} - {1}'\n\t }\n\t};\n\n\tvar RangeAreaSegment = AreaSegment.extend({\n\t createStrokeSegments: function() {\n\t return this.segmentsFromPoints(this.toGeometryPoints(this.toPoints()));\n\t },\n\n\t stackSegments: function() {\n\t var fromSegments = this.fromSegments;\n\t if (!this.fromSegments) {\n\t fromSegments = this.fromSegments = this.segmentsFromPoints(this.toGeometryPoints(this.fromPoints().reverse()));\n\t }\n\n\t return fromSegments;\n\t },\n\n\t createStroke: function(style) {\n\t var toPath = new Path(style);\n\t var fromPath = new Path(style);\n\n\t toPath.segments.push.apply(toPath.segments, this.strokeSegments());\n\t fromPath.segments.push.apply(fromPath.segments, this.stackSegments());\n\n\t this.visual.append(toPath);\n\t this.visual.append(fromPath);\n\t },\n\n\t hasStackSegment: function() {\n\t return true;\n\t },\n\n\t fromPoints: function() {\n\t return this.linePoints.map(function (point) { return point.fromPoint; });\n\t },\n\n\t toPoints: function() {\n\t return this.linePoints.map(function (point) { return point.toPoint; });\n\t }\n\t});\n\n\tvar SplineRangeAreaSegment = RangeAreaSegment.extend({\n\t createStrokeSegments: function() {\n\t return this.createCurveSegments(this.toPoints());\n\t },\n\n\t stackSegments: function() {\n\t var fromSegments = this.fromSegments;\n\t if (!this.fromSegments) {\n\t fromSegments = this.fromSegments = this.createCurveSegments(this.fromPoints().reverse());\n\t }\n\n\t return fromSegments;\n\t },\n\n\t createCurveSegments: function(points) {\n\t var curveProcessor = new CurveProcessor();\n\n\t return curveProcessor.process(this.toGeometryPoints(points));\n\t }\n\t});\n\n\tvar StepRangeAreaSegment = RangeAreaSegment.extend({\n\t createStrokeSegments: function() {\n\t return this.segmentsFromPoints(this.calculateStepPoints(this.toPoints()));\n\t },\n\n\t stackSegments: function() {\n\t var fromSegments = this.fromSegments;\n\t if (!this.fromSegments) {\n\t fromSegments = this.fromSegments = this.segmentsFromPoints(this.calculateStepPoints(this.fromPoints()));\n\t fromSegments.reverse();\n\t }\n\n\t return fromSegments;\n\t }\n\t});\n\n\tdeepExtend(StepRangeAreaSegment.prototype, StepLineMixin);\n\n\tvar RangeAreaChart = CategoricalChart.extend({\n\t render: function() {\n\t CategoricalChart.fn.render.call(this);\n\n\t this.renderSegments();\n\t },\n\n\t pointType: function() {\n\t return RangeAreaPoint;\n\t },\n\n\t createPoint: function(data, fields) {\n\t var categoryIx = fields.categoryIx;\n\t var category = fields.category;\n\t var series = fields.series;\n\t var seriesIx = fields.seriesIx;\n\t var value = data.valueFields;\n\n\t if (!hasValue(value.from) && !hasValue(value.to)) {\n\t if (this.seriesMissingValues(series) === ZERO) {\n\t value = {\n\t from: 0,\n\t to: 0\n\t };\n\t } else {\n\t return null;\n\t }\n\t }\n\n\t var pointOptions = this.pointOptions(series, seriesIx);\n\t pointOptions = this.evalPointOptions(\n\t pointOptions, value, category, categoryIx, series, seriesIx\n\t );\n\n\t var color = data.fields.color || series.color;\n\t if (isFunction(series.color)) {\n\t color = pointOptions.color;\n\t }\n\n\t var point = new RangeAreaPoint(value, pointOptions);\n\t point.color = color;\n\n\t this.append(point);\n\n\t return point;\n\t },\n\n\t createSegment: function(linePoints, currentSeries, seriesIx) {\n\t var style = (currentSeries.line || {}).style;\n\t var segmentType;\n\t if (style === \"smooth\") {\n\t segmentType = SplineRangeAreaSegment;\n\t } else if (style === \"step\") {\n\t segmentType = StepRangeAreaSegment;\n\t } else {\n\t segmentType = RangeAreaSegment;\n\t }\n\n\t return new segmentType(linePoints, currentSeries, seriesIx);\n\t },\n\n\t plotRange: function(point, startValue) {\n\t if (!point) {\n\t return [ startValue, startValue ];\n\t }\n\n\t return [ point.value.from, point.value.to ];\n\t },\n\n\t valueSlot: function(valueAxis, plotRange) {\n\t var fromSlot = valueAxis.getSlot(plotRange[0], plotRange[0], !this.options.clip);\n\t var toSlot = valueAxis.getSlot(plotRange[1], plotRange[1], !this.options.clip);\n\t if (fromSlot && toSlot) {\n\t return {\n\t from: fromSlot,\n\t to: toSlot\n\t };\n\t }\n\t },\n\n\t pointSlot: function(categorySlot, valueSlot) {\n\t var from = valueSlot.from;\n\t var to = valueSlot.to;\n\t var fromSlot, toSlot;\n\n\t if (this.options.invertAxes) {\n\t fromSlot = new Box(from.x1, categorySlot.y1, from.x2, categorySlot.y2);\n\t toSlot = new Box(to.x1, categorySlot.y1, to.x2, categorySlot.y2);\n\t } else {\n\t fromSlot = new Box(categorySlot.x1, from.y1, categorySlot.x2, from.y2);\n\t toSlot = new Box(categorySlot.x1, to.y1, categorySlot.x2, to.y2);\n\t }\n\n\t return {\n\t from: fromSlot,\n\t to: toSlot\n\t };\n\t },\n\n\t addValue: function(data, fields) {\n\t var valueFields = data.valueFields;\n\t if (!isNumber(valueFields.from)) {\n\t valueFields.from = valueFields.to;\n\t }\n\n\t if (!isNumber(valueFields.to)) {\n\t valueFields.to = valueFields.from;\n\t }\n\n\t CategoricalChart.fn.addValue.call(this, data, fields);\n\t },\n\n\t updateRange: function(value, fields) {\n\t if (value !== null && isNumber(value.from) && isNumber(value.to)) {\n\t var axisName = fields.series.axis;\n\t var axisRange = this.valueAxisRanges[axisName] = this.valueAxisRanges[axisName] || { min: MAX_VALUE, max: MIN_VALUE };\n\t var from = value.from;\n\t var to = value.to;\n\n\t axisRange.min = Math.min(axisRange.min, from, to);\n\t axisRange.max = Math.max(axisRange.max, from, to);\n\t }\n\t },\n\n\t formatPointValue: function(point, format) {\n\t var value = point.value;\n\n\t return this.chartService.format.auto(format, value.from, value.to);\n\t },\n\n\t animationPoints: function() {\n\t var points = this.points;\n\t var result = [];\n\t for (var idx = 0; idx < points.length; idx++) {\n\t var point = points[idx];\n\t if (point) {\n\t result.push((point.fromPoint || {}).marker);\n\t result.push((point.toPoint || {}).marker);\n\t }\n\t }\n\n\t return result.concat(this._segments);\n\t }\n\t});\n\n\tdeepExtend(RangeAreaChart.prototype, LineChartMixin, ClipAnimationMixin);\n\n\tvar OHLCPoint = Candlestick.extend({\n\t reflow: function(box) {\n\t var ref = this;\n\t var options = ref.options;\n\t var value = ref.value;\n\t var chart = ref.owner;\n\t var valueAxis = chart.seriesValueAxis(options);\n\t var oPoints = [];\n\t var cPoints = [];\n\t var lhPoints = [];\n\n\t var lhSlot = valueAxis.getSlot(value.low, value.high);\n\t var oSlot = valueAxis.getSlot(value.open, value.open);\n\t var cSlot = valueAxis.getSlot(value.close, value.close);\n\n\t oSlot.x1 = cSlot.x1 = lhSlot.x1 = box.x1;\n\t oSlot.x2 = cSlot.x2 = lhSlot.x2 = box.x2;\n\n\t var mid = lhSlot.center().x;\n\n\t oPoints.push([ oSlot.x1, oSlot.y1 ]);\n\t oPoints.push([ mid, oSlot.y1 ]);\n\t cPoints.push([ mid, cSlot.y1 ]);\n\t cPoints.push([ cSlot.x2, cSlot.y1 ]);\n\t lhPoints.push([ mid, lhSlot.y1 ]);\n\t lhPoints.push([ mid, lhSlot.y2 ]);\n\n\t this.lines = [\n\t oPoints, cPoints, lhPoints\n\t ];\n\n\t this.box = lhSlot.clone().wrap(oSlot.clone().wrap(cSlot));\n\n\t this.reflowNote();\n\t },\n\n\t createBody: function() {}\n\t});\n\n\tvar OHLCChart = CandlestickChart.extend({\n\t pointType: function() {\n\t return OHLCPoint;\n\t }\n\t});\n\n\tvar WaterfallSegment = ChartElement.extend({\n\t init: function(from, to, series) {\n\t ChartElement.fn.init.call(this);\n\n\t this.from = from;\n\t this.to = to;\n\t this.series = series;\n\t },\n\n\t linePoints: function() {\n\t var from = this.from;\n\t var ref = this;\n\t var fromBox = ref.from.box;\n\t var toBox = ref.to.box;\n\t var points = [];\n\n\t if (from.isVertical) {\n\t var y = from.aboveAxis ? fromBox.y1 : fromBox.y2;\n\t points.push(\n\t [ fromBox.x1, y ],\n\t [ toBox.x2, y ]\n\t );\n\t } else {\n\t var x = from.aboveAxis ? fromBox.x2 : fromBox.x1;\n\t points.push(\n\t [ x, fromBox.y1 ],\n\t [ x, toBox.y2 ]\n\t );\n\t }\n\n\t return points;\n\t },\n\n\t createVisual: function() {\n\t ChartElement.fn.createVisual.call(this);\n\n\t var line = this.series.line || {};\n\n\t var path = Path.fromPoints(this.linePoints(), {\n\t stroke: {\n\t color: line.color,\n\t width: line.width,\n\t opacity: line.opacity,\n\t dashType: line.dashType\n\t }\n\t });\n\n\t alignPathToPixel(path);\n\t this.visual.append(path);\n\t }\n\t});\n\n\tsetDefaultOptions(WaterfallSegment, {\n\t animation: {\n\t type: FADEIN,\n\t delay: INITIAL_ANIMATION_DURATION\n\t }\n\t});\n\n\tvar WaterfallChart = BarChart.extend({\n\t render: function() {\n\t BarChart.fn.render.call(this);\n\t this.createSegments();\n\t },\n\n\t traverseDataPoints: function(callback) {\n\t var this$1 = this;\n\n\t var series = this.options.series;\n\t var totalCategories = categoriesCount(series);\n\t var isVertical = !this.options.invertAxes;\n\n\t for (var seriesIx = 0; seriesIx < series.length; seriesIx++) {\n\t var currentSeries = series[seriesIx];\n\t var total = 0;\n\t var runningTotal = 0;\n\n\t for (var categoryIx = 0; categoryIx < totalCategories; categoryIx++) {\n\t var data = SeriesBinder.current.bindPoint(currentSeries, categoryIx);\n\t var value = data.valueFields.value;\n\t var summary = data.fields.summary;\n\t var from = total;\n\t var to = (void 0);\n\n\t if (summary) {\n\t if (summary.toLowerCase() === \"total\") {\n\t data.valueFields.value = total;\n\t from = 0;\n\t to = total;\n\t } else {\n\t data.valueFields.value = runningTotal;\n\t to = from - runningTotal;\n\t runningTotal = 0;\n\t }\n\t } else if (isNumber(value)) {\n\t runningTotal += value;\n\t total += value;\n\t to = total;\n\t }\n\n\t callback(data, {\n\t category: this$1.categoryAxis.categoryAt(categoryIx),\n\t categoryIx: categoryIx,\n\t series: currentSeries,\n\t seriesIx: seriesIx,\n\t total: total,\n\t runningTotal: runningTotal,\n\t from: from,\n\t to: to,\n\t isVertical: isVertical\n\t });\n\t }\n\t }\n\t },\n\n\t updateRange: function(value, fields) {\n\t BarChart.fn.updateRange.call(this, { value: fields.to }, fields);\n\t },\n\n\t aboveAxis: function(point) {\n\t return point.value >= 0;\n\t },\n\n\t plotRange: function(point) {\n\t return [ point.from, point.to ];\n\t },\n\n\t createSegments: function() {\n\t var this$1 = this;\n\n\t var series = this.options.series;\n\t var seriesPoints = this.seriesPoints;\n\t var segments = this.segments = [];\n\n\t for (var seriesIx = 0; seriesIx < series.length; seriesIx++) {\n\t var currentSeries = series[seriesIx];\n\t var points = seriesPoints[seriesIx];\n\n\t if (points) {\n\t var prevPoint = (void 0);\n\t for (var pointIx = 0; pointIx < points.length; pointIx++) {\n\t var point = points[pointIx];\n\n\t if (point && prevPoint) {\n\t var segment = new WaterfallSegment(prevPoint, point, currentSeries);\n\t segments.push(segment);\n\t this$1.append(segment);\n\t }\n\n\t prevPoint = point;\n\t }\n\t }\n\t }\n\t }\n\t});\n\n\tvar AREA_SERIES = [ AREA, VERTICAL_AREA, RANGE_AREA, VERTICAL_RANGE_AREA ];\n\tvar OUT_OF_RANGE_SERIES = [ LINE, VERTICAL_LINE ].concat(AREA_SERIES);\n\n\tvar CategoricalPlotArea = PlotAreaBase.extend({\n\t initFields: function(series) {\n\t var this$1 = this;\n\n\t this.namedCategoryAxes = {};\n\t this.namedValueAxes = {};\n\t this.valueAxisRangeTracker = new AxisGroupRangeTracker();\n\n\t if (series.length > 0) {\n\t this.invertAxes = inArray(\n\t series[0].type, [ BAR, BULLET, VERTICAL_LINE, VERTICAL_AREA, VERTICAL_RANGE_AREA,\n\t RANGE_BAR, HORIZONTAL_WATERFALL, VERTICAL_BOX_PLOT ]\n\t );\n\n\t for (var i = 0; i < series.length; i++) {\n\t var stack = series[i].stack;\n\t if (stack && stack.type === \"100%\") {\n\t this$1.stack100 = true;\n\t break;\n\t }\n\t }\n\t }\n\n\t },\n\n\t render: function(panes) {\n\t if (panes === void 0) { panes = this.panes; }\n\n\t this.createCategoryAxes(panes);\n\t this.aggregateCategories(panes);\n\t this.createCategoryAxesLabels(panes);\n\t this.createCharts(panes);\n\t this.createValueAxes(panes);\n\t },\n\n\t removeAxis: function(axis) {\n\t var axisName = axis.options.name;\n\n\t PlotAreaBase.fn.removeAxis.call(this, axis);\n\n\t if (axis instanceof CategoryAxis) {\n\t delete this.namedCategoryAxes[axisName];\n\t } else {\n\t this.valueAxisRangeTracker.reset(axisName);\n\t delete this.namedValueAxes[axisName];\n\t }\n\n\t if (axis === this.categoryAxis) {\n\t delete this.categoryAxis;\n\t }\n\n\t if (axis === this.valueAxis) {\n\t delete this.valueAxis;\n\t }\n\t },\n\n\t createCharts: function(panes) {\n\t var this$1 = this;\n\n\t var seriesByPane = this.groupSeriesByPane();\n\n\t for (var i = 0; i < panes.length; i++) {\n\t var pane = panes[i];\n\t var paneSeries = seriesByPane[pane.options.name || \"default\"] || [];\n\t this$1.addToLegend(paneSeries);\n\n\t var visibleSeries = this$1.filterVisibleSeries(paneSeries);\n\t if (!visibleSeries) {\n\t continue;\n\t }\n\n\t var groups = this$1.groupSeriesByCategoryAxis(visibleSeries);\n\t for (var groupIx = 0; groupIx < groups.length; groupIx++) {\n\t this$1.createChartGroup(groups[groupIx], pane);\n\t }\n\t }\n\t },\n\n\t createChartGroup: function(series, pane) {\n\t this.createAreaChart(\n\t filterSeriesByType(series, [ AREA, VERTICAL_AREA ]), pane\n\t );\n\n\t this.createRangeAreaChart(\n\t filterSeriesByType(series, [ RANGE_AREA, VERTICAL_RANGE_AREA ]), pane\n\t );\n\n\t this.createBarChart(\n\t filterSeriesByType(series, [ COLUMN, BAR ]), pane\n\t );\n\n\t this.createRangeBarChart(\n\t filterSeriesByType(series, [ RANGE_COLUMN, RANGE_BAR ]), pane\n\t );\n\n\t this.createBulletChart(\n\t filterSeriesByType(series, [ BULLET, VERTICAL_BULLET ]), pane\n\t );\n\n\t this.createCandlestickChart(\n\t filterSeriesByType(series, CANDLESTICK), pane\n\t );\n\n\t this.createBoxPlotChart(\n\t filterSeriesByType(series, [ BOX_PLOT, VERTICAL_BOX_PLOT ]), pane\n\t );\n\n\t this.createOHLCChart(\n\t filterSeriesByType(series, OHLC), pane\n\t );\n\n\t this.createWaterfallChart(\n\t filterSeriesByType(series, [ WATERFALL, HORIZONTAL_WATERFALL ]), pane\n\t );\n\n\t this.createLineChart(\n\t filterSeriesByType(series, [ LINE, VERTICAL_LINE ]), pane\n\t );\n\t },\n\n\t aggregateCategories: function(panes) {\n\t var this$1 = this;\n\n\t var series = this.srcSeries || this.series;\n\t var processedSeries = [];\n\t this._currentPointsCache = {};\n\t this._seriesPointsCache = this._seriesPointsCache || {};\n\n\t for (var i = 0; i < series.length; i++) {\n\t var currentSeries = series[i];\n\t var categoryAxis = this$1.seriesCategoryAxis(currentSeries);\n\t var axisPane = this$1.findPane(categoryAxis.options.pane);\n\t var dateAxis = equalsIgnoreCase(categoryAxis.options.type, DATE);\n\n\t if ((dateAxis || currentSeries.categoryField) && inArray(axisPane, panes)) {\n\t currentSeries = this$1.aggregateSeries(currentSeries, categoryAxis);\n\t } else {\n\t currentSeries = this$1.filterSeries(currentSeries, categoryAxis);\n\t }\n\n\t processedSeries.push(currentSeries);\n\t }\n\n\t this._seriesPointsCache = this._currentPointsCache;\n\t this._currentPointsCache = null;\n\n\t this.srcSeries = series;\n\t this.series = processedSeries;\n\t },\n\n\t filterSeries: function(series, categoryAxis) {\n\t var dataLength = (series.data || {}).length;\n\t categoryAxis._seriesMax = Math.max(categoryAxis._seriesMax || 0, dataLength);\n\n\t if (!(isNumber(categoryAxis.options.min) || isNumber(categoryAxis.options.max))) {\n\t return series;\n\t }\n\n\t var range = categoryAxis.currentRangeIndices();\n\t var outOfRangePoints = inArray(series.type, OUT_OF_RANGE_SERIES);\n\t var currentSeries = deepExtend({}, series);\n\n\t currentSeries.data = (currentSeries.data || []).slice(range.min, range.max + 1);\n\n\t if (outOfRangePoints) {\n\t createOutOfRangePoints(currentSeries, range, dataLength, function (idx) { return ({\n\t item: series.data[idx],\n\t category: categoryAxis.categoryAt(idx, true),\n\t categoryIx: idx - range.min\n\t }); }, function (idx) { return defined(series.data[idx]); });\n\t }\n\n\t return currentSeries;\n\t },\n\n\t clearSeriesPointsCache: function() {\n\t this._seriesPointsCache = {};\n\t },\n\n\t seriesSourcePoints: function(series, categoryAxis) {\n\t var this$1 = this;\n\n\t var key = (series.index) + \";\" + (categoryAxis.categoriesHash());\n\t if (this._seriesPointsCache[key]) {\n\t this._currentPointsCache[key] = this._seriesPointsCache[key];\n\t return this._seriesPointsCache[key];\n\t }\n\n\t var axisOptions = categoryAxis.options;\n\t var srcCategories = axisOptions.srcCategories;\n\t var dateAxis = equalsIgnoreCase(axisOptions.type, DATE);\n\t var srcData = series.data;\n\t var getFn = dateAxis ? getDateField : getField;\n\t var result = [];\n\t if (!dateAxis) {\n\t categoryAxis.mapCategories();//fixes major performance issue caused by searching for the index for large data\n\t }\n\n\t for (var idx = 0; idx < srcData.length; idx++) {\n\t var category = (void 0);\n\t if (series.categoryField) {\n\t category = getFn(series.categoryField, srcData[idx], this$1.chartService.intl);\n\t } else {\n\t category = srcCategories[idx];\n\t }\n\n\t if (defined(category) && category !== null) {\n\t var categoryIx = categoryAxis.totalIndex(category);\n\t result[categoryIx] = result[categoryIx] || { items: [], category: category };\n\t result[categoryIx].items.push(idx);\n\t }\n\t }\n\n\t this._currentPointsCache[key] = result;\n\n\t return result;\n\t },\n\n\t aggregateSeries: function(series, categoryAxis) {\n\t var srcData = series.data;\n\t if (!srcData.length) {\n\t return series;\n\t }\n\n\t var srcPoints = this.seriesSourcePoints(series, categoryAxis);\n\t var result = deepExtend({}, series);\n\t var aggregator = new SeriesAggregator(deepExtend({}, series), SeriesBinder.current, DefaultAggregates.current);\n\t var data = result.data = [];\n\t var dataItems = categoryAxis.options.dataItems || [];\n\n\t var range = categoryAxis.currentRangeIndices();\n\t var categoryItem = function (idx) {\n\t var categoryIdx = idx - range.min;\n\t var point = srcPoints[idx];\n\t if (!point) {\n\t point = srcPoints[idx] = {};\n\t }\n\n\t point.categoryIx = categoryIdx;\n\n\t if (!point.item) {\n\t var category = categoryAxis.categoryAt(idx, true);\n\t point.category = category;\n\t point.item = aggregator.aggregatePoints(point.items, category);\n\t }\n\n\t return point;\n\t };\n\n\t for (var idx = range.min; idx <= range.max; idx++) {\n\t var point = categoryItem(idx);\n\t data[point.categoryIx] = point.item;\n\n\t if (point.items && point.items.length) {\n\t dataItems[point.categoryIx] = point.item;\n\t }\n\t }\n\n\t if (inArray(result.type, OUT_OF_RANGE_SERIES)) {\n\t createOutOfRangePoints(result, range, categoryAxis.totalCount(), categoryItem, function (idx) { return srcPoints[idx]; });\n\t }\n\n\t categoryAxis.options.dataItems = dataItems;\n\n\t return result;\n\t },\n\n\t appendChart: function(chart, pane) {\n\t var series = chart.options.series;\n\t var categoryAxis = this.seriesCategoryAxis(series[0]);\n\t var categories = categoryAxis.options.categories;\n\t var categoriesToAdd = Math.max(0, categoriesCount(series) - categories.length);\n\n\t if (categoriesToAdd > 0) {//consider setting an option to axis instead of adding fake categories\n\t categories = categoryAxis.options.categories = categoryAxis.options.categories.slice(0);\n\t while (categoriesToAdd--) {\n\t categories.push(\"\");\n\t }\n\t }\n\n\t this.valueAxisRangeTracker.update(chart.valueAxisRanges);\n\n\t PlotAreaBase.fn.appendChart.call(this, chart, pane);\n\t },\n\n\t seriesPaneName: function(series) {\n\t var options = this.options;\n\t var axisName = series.axis;\n\t var axisOptions = [].concat(options.valueAxis);\n\t var axis = grep(axisOptions, function(a) { return a.name === axisName; })[0];\n\t var panes = options.panes || [ {} ];\n\t var defaultPaneName = (panes[0] || {}).name || \"default\";\n\t var paneName = (axis || {}).pane || defaultPaneName;\n\n\t return paneName;\n\t },\n\n\t seriesCategoryAxis: function(series) {\n\t var axisName = series.categoryAxis;\n\t var axis = axisName ? this.namedCategoryAxes[axisName] : this.categoryAxis;\n\n\t if (!axis) {\n\t throw new Error(\"Unable to locate category axis with name \" + axisName);\n\t }\n\n\t return axis;\n\t },\n\n\t stackableChartOptions: function(firstSeries, pane) {\n\t var stack = firstSeries.stack;\n\t var isStacked100 = stack && stack.type === \"100%\";\n\t var clip = pane.options.clip;\n\n\t return {\n\t isStacked: stack,\n\t isStacked100: isStacked100,\n\t clip: clip\n\t };\n\t },\n\n\t groupSeriesByCategoryAxis: function(series) {\n\t var categoryAxes = [];\n\t var unique = {};\n\t for (var idx = 0; idx < series.length; idx++) {\n\t var name = series[idx].categoryAxis || \"$$default$$\";\n\t if (!unique.hasOwnProperty(name)) {\n\t unique[name] = true;\n\t categoryAxes.push(name);\n\t }\n\t }\n\n\t var groups = [];\n\t for (var axisIx = 0; axisIx < categoryAxes.length; axisIx++) {\n\t var axis = categoryAxes[axisIx];\n\t var axisSeries = groupSeries(series, axis, axisIx);\n\t if (axisSeries.length === 0) {\n\t continue;\n\t }\n\n\t groups.push(axisSeries);\n\t }\n\n\t return groups;\n\t },\n\n\t createBarChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var firstSeries = series[0];\n\t var barChart = new BarChart(this, $.extend({\n\t series: series,\n\t invertAxes: this.invertAxes,\n\t gap: firstSeries.gap,\n\t spacing: firstSeries.spacing\n\t }, this.stackableChartOptions(firstSeries, pane)));\n\n\t this.appendChart(barChart, pane);\n\t },\n\n\t createRangeBarChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var firstSeries = series[0];\n\t var rangeColumnChart = new RangeBarChart(this, {\n\t series: series,\n\t invertAxes: this.invertAxes,\n\t gap: firstSeries.gap,\n\t spacing: firstSeries.spacing\n\t });\n\n\t this.appendChart(rangeColumnChart, pane);\n\t },\n\n\t createBulletChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var firstSeries = series[0];\n\t var bulletChart = new BulletChart(this, {\n\t series: series,\n\t invertAxes: this.invertAxes,\n\t gap: firstSeries.gap,\n\t spacing: firstSeries.spacing,\n\t clip: pane.options.clip\n\t });\n\n\t this.appendChart(bulletChart, pane);\n\t },\n\n\t createLineChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var firstSeries = series[0];\n\t var lineChart = new LineChart(this, $.extend({\n\t invertAxes: this.invertAxes,\n\t series: series\n\t }, this.stackableChartOptions(firstSeries, pane)));\n\n\t this.appendChart(lineChart, pane);\n\t },\n\n\t createAreaChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var firstSeries = series[0];\n\t var areaChart = new AreaChart(this, $.extend({\n\t invertAxes: this.invertAxes,\n\t series: series\n\t }, this.stackableChartOptions(firstSeries, pane)));\n\n\t this.appendChart(areaChart, pane);\n\t },\n\n\t createRangeAreaChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var rangeAreaChart = new RangeAreaChart(this, {\n\t invertAxes: this.invertAxes,\n\t series: series,\n\t clip: pane.options.clip\n\t });\n\n\t this.appendChart(rangeAreaChart, pane);\n\t },\n\n\t createOHLCChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var firstSeries = series[0];\n\t var chart = new OHLCChart(this, {\n\t invertAxes: this.invertAxes,\n\t gap: firstSeries.gap,\n\t series: series,\n\t spacing: firstSeries.spacing,\n\t clip: pane.options.clip\n\t });\n\n\t this.appendChart(chart, pane);\n\t },\n\n\t createCandlestickChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var firstSeries = series[0];\n\t var chart = new CandlestickChart(this, {\n\t invertAxes: this.invertAxes,\n\t gap: firstSeries.gap,\n\t series: series,\n\t spacing: firstSeries.spacing,\n\t clip: pane.options.clip\n\t });\n\n\t this.appendChart(chart, pane);\n\t },\n\n\t createBoxPlotChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var firstSeries = series[0];\n\t var chart = new BoxPlotChart(this, {\n\t invertAxes: this.invertAxes,\n\t gap: firstSeries.gap,\n\t series: series,\n\t spacing: firstSeries.spacing,\n\t clip: pane.options.clip\n\t });\n\n\t this.appendChart(chart, pane);\n\t },\n\n\t createWaterfallChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var firstSeries = series[0];\n\t var waterfallChart = new WaterfallChart(this, {\n\t series: series,\n\t invertAxes: this.invertAxes,\n\t gap: firstSeries.gap,\n\t spacing: firstSeries.spacing\n\t });\n\n\t this.appendChart(waterfallChart, pane);\n\t },\n\n\t axisRequiresRounding: function(categoryAxisName, categoryAxisIndex) {\n\t var this$1 = this;\n\n\t var centeredSeries = filterSeriesByType(this.series, EQUALLY_SPACED_SERIES);\n\n\t for (var seriesIx = 0; seriesIx < this.series.length; seriesIx++) {\n\t var currentSeries = this$1.series[seriesIx];\n\t if (inArray(currentSeries.type, AREA_SERIES)) {\n\t var line = currentSeries.line;\n\t if (line && line.style === STEP) {\n\t centeredSeries.push(currentSeries);\n\t }\n\t }\n\t }\n\n\t for (var seriesIx$1 = 0; seriesIx$1 < centeredSeries.length; seriesIx$1++) {\n\t var seriesAxis = centeredSeries[seriesIx$1].categoryAxis || \"\";\n\t if (seriesAxis === categoryAxisName || (!seriesAxis && categoryAxisIndex === 0)) {\n\t return true;\n\t }\n\t }\n\t },\n\n\t aggregatedAxis: function(categoryAxisName, categoryAxisIndex) {\n\t var series = this.series;\n\n\t for (var seriesIx = 0; seriesIx < series.length; seriesIx++) {\n\t var seriesAxis = series[seriesIx].categoryAxis || \"\";\n\t if ((seriesAxis === categoryAxisName || (!seriesAxis && categoryAxisIndex === 0)) && series[seriesIx].categoryField) {\n\t return true;\n\t }\n\t }\n\t },\n\n\t createCategoryAxesLabels: function() {\n\t var axes = this.axes;\n\t for (var i = 0; i < axes.length; i++) {\n\t if (axes[i] instanceof CategoryAxis) {\n\t axes[i].createLabels();\n\t }\n\t }\n\t },\n\n\t createCategoryAxes: function(panes) {\n\t var this$1 = this;\n\n\t var invertAxes = this.invertAxes;\n\t var definitions = [].concat(this.options.categoryAxis);\n\t var axes = [];\n\n\t for (var i = 0; i < definitions.length; i++) {\n\t var axisOptions = definitions[i];\n\t var axisPane = this$1.findPane(axisOptions.pane);\n\n\t if (inArray(axisPane, panes)) {\n\t var name = axisOptions.name;\n\t var categories = axisOptions.categories; if (categories === void 0) { categories = []; }\n\t axisOptions = deepExtend({\n\t vertical: invertAxes,\n\t reverse: !invertAxes && this$1.chartService.rtl,\n\t axisCrossingValue: invertAxes ? MAX_VALUE : 0\n\t }, axisOptions);\n\n\t if (!defined(axisOptions.justified)) {\n\t axisOptions.justified = this$1.isJustified();\n\t }\n\n\t if (this$1.axisRequiresRounding(name, i)) {\n\t axisOptions.justified = false;\n\t }\n\n\t var categoryAxis = (void 0);\n\n\t if (isDateAxis(axisOptions, categories[0])) {\n\t categoryAxis = new dataviz.DateCategoryAxis(axisOptions, this$1.chartService);\n\t } else {\n\t categoryAxis = new CategoryAxis(axisOptions, this$1.chartService);\n\t }\n\n\t definitions[i].categories = categoryAxis.options.srcCategories;\n\n\t if (name) {\n\t if (this$1.namedCategoryAxes[name]) {\n\t throw new Error((\"Category axis with name \" + name + \" is already defined\"));\n\t }\n\t this$1.namedCategoryAxes[name] = categoryAxis;\n\t }\n\n\t categoryAxis.axisIndex = i;\n\t axes.push(categoryAxis);\n\t this$1.appendAxis(categoryAxis);\n\t }\n\t }\n\n\t var primaryAxis = this.categoryAxis || axes[0];\n\t this.categoryAxis = primaryAxis;\n\n\t if (invertAxes) {\n\t this.axisY = primaryAxis;\n\t } else {\n\t this.axisX = primaryAxis;\n\t }\n\t },\n\n\t isJustified: function() {\n\t var series = this.series;\n\n\t for (var i = 0; i < series.length; i++) {\n\t var currentSeries = series[i];\n\t if (!inArray(currentSeries.type, AREA_SERIES)) {\n\t return false;\n\t }\n\t }\n\n\t return true;\n\t },\n\n\t createValueAxes: function(panes) {\n\t var this$1 = this;\n\n\t var tracker = this.valueAxisRangeTracker;\n\t var defaultRange = tracker.query();\n\t var definitions = [].concat(this.options.valueAxis);\n\t var invertAxes = this.invertAxes;\n\t var baseOptions = { vertical: !invertAxes, reverse: invertAxes && this.chartService.rtl };\n\t var axes = [];\n\n\t if (this.stack100) {\n\t baseOptions.roundToMajorUnit = false;\n\t baseOptions.labels = { format: \"P0\" };\n\t }\n\n\t for (var i = 0; i < definitions.length; i++) {\n\t var axisOptions = definitions[i];\n\t var axisPane = this$1.findPane(axisOptions.pane);\n\n\t if (inArray(axisPane, panes)) {\n\t var name = axisOptions.name;\n\t var defaultAxisRange = equalsIgnoreCase(axisOptions.type, LOGARITHMIC) ? { min: 0.1, max: 1 } : { min: 0, max: 1 };\n\t var range = tracker.query(name) || defaultRange || defaultAxisRange;\n\n\t if (i === 0 && range && defaultRange) {\n\t range.min = Math.min(range.min, defaultRange.min);\n\t range.max = Math.max(range.max, defaultRange.max);\n\t }\n\n\t var axisType = (void 0);\n\t if (equalsIgnoreCase(axisOptions.type, LOGARITHMIC)) {\n\t axisType = dataviz.LogarithmicAxis;\n\t } else {\n\t axisType = dataviz.NumericAxis;\n\t }\n\n\t var valueAxis = new axisType(range.min, range.max,\n\t deepExtend({}, baseOptions, axisOptions),\n\t this$1.chartService\n\t );\n\n\t if (name) {\n\t if (this$1.namedValueAxes[name]) {\n\t throw new Error((\"Value axis with name \" + name + \" is already defined\"));\n\t }\n\t this$1.namedValueAxes[name] = valueAxis;\n\t }\n\t valueAxis.axisIndex = i;\n\n\t axes.push(valueAxis);\n\t this$1.appendAxis(valueAxis);\n\t }\n\t }\n\n\t var primaryAxis = this.valueAxis || axes[0];\n\t this.valueAxis = primaryAxis;\n\n\t if (invertAxes) {\n\t this.axisX = primaryAxis;\n\t } else {\n\t this.axisY = primaryAxis;\n\t }\n\t },\n\n\t _dispatchEvent: function(chart, e, eventType) {\n\t var coords = chart._eventCoordinates(e);\n\t var point = new Point(coords.x, coords.y);\n\t var pane = this.pointPane(point);\n\t var categories = [];\n\t var values = [];\n\n\t if (!pane) {\n\t return;\n\t }\n\n\t var allAxes = pane.axes;\n\t for (var i = 0; i < allAxes.length; i++) {\n\t var axis = allAxes[i];\n\t if (axis.getValue) {\n\t appendIfNotNull(values, axis.getValue(point));\n\t } else {\n\t appendIfNotNull(categories, axis.getCategory(point));\n\t }\n\t }\n\n\t if (categories.length === 0) {\n\t appendIfNotNull(categories, this.categoryAxis.getCategory(point));\n\t }\n\n\t if (categories.length > 0 && values.length > 0) {\n\t chart.trigger(eventType, {\n\t element: eventElement(e),\n\t originalEvent: e,\n\t category: singleItemOrArray(categories),\n\t value: singleItemOrArray(values)\n\t });\n\t }\n\t },\n\n\t pointPane: function(point) {\n\t var panes = this.panes;\n\n\t for (var i = 0; i < panes.length; i++) {\n\t var currentPane = panes[i];\n\t if (currentPane.contentBox.containsPoint(point)) {\n\t return currentPane;\n\t }\n\t }\n\t },\n\n\t updateAxisOptions: function(axis, options) {\n\t updateAxisOptions(this.options, axis, options);\n\t updateAxisOptions(this.originalOptions, axis, options);\n\t }\n\t});\n\n\tfunction updateAxisOptions(targetOptions, axis, options) {\n\t var axesOptions = axis instanceof CategoryAxis ? [].concat(targetOptions.categoryAxis) : [].concat(targetOptions.valueAxis);\n\t deepExtend(axesOptions[axis.axisIndex], options);\n\t}\n\n\tfunction groupSeries(series, axis, axisIx) {\n\t return grep(series, function(s) {\n\t return (axisIx === 0 && !s.categoryAxis) || (s.categoryAxis === axis);\n\t });\n\t}\n\n\tsetDefaultOptions(CategoricalPlotArea, {\n\t categoryAxis: {},\n\t valueAxis: {}\n\t});\n\n\tdeepExtend(CategoricalPlotArea.prototype, PlotAreaEventsMixin);\n\n\tvar Highlight = Class.extend({\n\t init: function() {\n\n\t this._points = [];\n\t },\n\n\t destroy: function() {\n\t this._points = [];\n\t },\n\n\t show: function(points) {\n\t var this$1 = this;\n\n\t var arrayPoints = [].concat(points);\n\t this.hide();\n\n\t for (var i = 0; i < arrayPoints.length; i++) {\n\t var point = arrayPoints[i];\n\t if (point && point.toggleHighlight && point.hasHighlight()) {\n\t this$1.togglePointHighlight(point, true);\n\t this$1._points.push(point);\n\t }\n\t }\n\t },\n\n\t togglePointHighlight: function(point, show) {\n\t var toggleHandler = (point.options.highlight || {}).toggle;\n\t if (toggleHandler) {\n\t var eventArgs = {\n\t category: point.category,\n\t series: point.series,\n\t dataItem: point.dataItem,\n\t value: point.value,\n\t stackValue: point.stackValue,\n\t preventDefault: preventDefault,\n\t visual: point.highlightVisual(),\n\t show: show\n\t };\n\t toggleHandler(eventArgs);\n\t if (!eventArgs._defaultPrevented) {\n\t point.toggleHighlight(show);\n\t }\n\t } else {\n\t point.toggleHighlight(show);\n\t }\n\t },\n\n\t hide: function() {\n\t var this$1 = this;\n\n\t var points = this._points;\n\t while (points.length) {\n\t this$1.togglePointHighlight(points.pop(), false);\n\t }\n\t },\n\n\t isHighlighted: function(element) {\n\t var points = this._points;\n\n\t for (var i = 0; i < points.length; i++) {\n\t var point = points[i];\n\t if (element === point) {\n\t return true;\n\t }\n\t }\n\n\t return false;\n\t }\n\t});\n\n\tfunction preventDefault() {\n\t this._defaultPrevented = true;\n\t}\n\n\tfunction acceptKey(e, mouseKey) {\n\t var key = (mouseKey || \"\").toLowerCase();\n\t var event = e.event;\n\t var accept = (key === \"none\" && !(event.ctrlKey || event.shiftKey || event.altKey)) || event[key + \"Key\"];\n\n\t return accept;\n\t}\n\n\tfunction toChartAxisRanges(axisRanges) {\n\t var ranges = {};\n\t for (var idx = 0; idx < axisRanges.length; idx++) {\n\t var axisRange = axisRanges[idx];\n\t if (axisRange.axis.options.name) {\n\t ranges[axisRange.axis.options.name] = {\n\t min: axisRange.range.min,\n\t max: axisRange.range.max\n\t };\n\t }\n\t }\n\t return ranges;\n\t}\n\n\tvar Pannable = Class.extend({\n\t init: function(plotArea, options) {\n\n\t this.plotArea = plotArea;\n\t this.options = deepExtend({}, this.options, options);\n\t },\n\n\t start: function(e) {\n\t this._active = acceptKey(e, this.options.key);\n\t return this._active;\n\t },\n\n\t move: function(e) {\n\t if (this._active) {\n\t var axisRanges = this.axisRanges = this._panAxes(e, X).concat(this._panAxes(e, Y));\n\t if (axisRanges.length) {\n\t this.axisRanges = axisRanges;\n\t return toChartAxisRanges(axisRanges);\n\t }\n\t }\n\t },\n\n\t end: function() {\n\t var active = this._active;\n\t this._active = false;\n\n\t return active;\n\t },\n\n\t pan: function() {\n\t var ref = this;\n\t var plotArea = ref.plotArea;\n\t var axisRanges = ref.axisRanges;\n\t if (axisRanges.length) {\n\t for (var idx = 0; idx < axisRanges.length; idx++) {\n\t var range = axisRanges[idx];\n\t plotArea.updateAxisOptions(range.axis, range.range);\n\t }\n\t plotArea.redraw(plotArea.panes);\n\t }\n\t },\n\n\t destroy: function() {\n\t delete this.plotArea;\n\t },\n\n\t _panAxes: function(e, position) {\n\t var plotArea = this.plotArea;\n\t var delta = -e[position].delta;\n\t var lock = (this.options.lock || \"\").toLowerCase();\n\t var updatedAxes = [];\n\n\t if (delta !== 0 && (lock || \"\").toLowerCase() !== position) {\n\t var axes = plotArea.axes;\n\t for (var idx = 0; idx < axes.length; idx++) {\n\t var axis = axes[idx];\n\n\t if (position === X && !axis.options.vertical || position === Y && axis.options.vertical) {\n\t var range = axis.pan(delta);\n\n\t if (range) {\n\t range.limitRange = true;\n\t updatedAxes.push({\n\t axis: axis,\n\t range: range\n\t });\n\t }\n\t }\n\t }\n\t }\n\n\t return updatedAxes;\n\t }\n\t});\n\n\tPannable.prototype.options = {\n\t key: \"none\",\n\t lock: \"none\"\n\t};\n\n\tvar ZoomSelection = Class.extend({\n\t init: function(chart, options) {\n\n\t this.chart = chart;\n\t this.options = deepExtend({}, this.options, options);\n\t this.createElement();\n\t },\n\n\t createElement: function() {\n\t var marquee = this._marquee = document.createElement(\"div\");\n\t marquee.className = \"k-marquee\";\n\t var marqueeColor = document.createElement(\"div\");\n\t marqueeColor.className = \"k-marquee-color\";\n\t marquee.appendChild(marqueeColor);\n\t },\n\n\t removeElement: function() {\n\t if (this._marquee.parentNode) {\n\t this._marquee.parentNode.removeChild(this._marquee);\n\t }\n\t },\n\n\t setStyles: function(styles) {\n\t elementStyles(this._marquee, styles);\n\t },\n\n\t start: function(e) {\n\t if (acceptKey(e, this.options.key)) {\n\t var chart = this.chart;\n\t var point = chart._eventCoordinates(e);\n\t var zoomPane = this._zoomPane = chart._plotArea.paneByPoint(point);\n\t var clipBox = zoomPane ? zoomPane.chartsBox().clone() : null;\n\n\t if (zoomPane && clipBox) {\n\t var offset = this._elementOffset();\n\n\t clipBox.translate(offset.left, offset.top);\n\t this._zoomPaneClipBox = clipBox;\n\n\t document.body.appendChild(this._marquee);\n\t this.setStyles({\n\t left: e.pageX + 1,\n\t top: e.pageY + 1,\n\t width: 0,\n\t height: 0\n\t });\n\n\t return true;\n\t }\n\t }\n\t return false;\n\t },\n\n\t _elementOffset: function() {\n\t var chartElement = this.chart.element;\n\t var ref = elementStyles(chartElement, [ \"paddingLeft\", \"paddingTop\" ]);\n\t var paddingLeft = ref.paddingLeft;\n\t var paddingTop = ref.paddingTop;\n\t var offset = dataviz.elementOffset(chartElement);\n\n\t return {\n\t left: paddingLeft + offset.left,\n\t top: paddingTop + offset.top\n\t };\n\t },\n\n\t move: function(e) {\n\t var zoomPane = this._zoomPane;\n\t if (zoomPane) {\n\t this.setStyles(this._selectionPosition(e));\n\t }\n\t },\n\n\t end: function(e) {\n\t var zoomPane = this._zoomPane;\n\t if (zoomPane) {\n\t var elementOffset$$1 = this._elementOffset();\n\t var selectionPosition = this._selectionPosition(e);\n\t selectionPosition.left -= elementOffset$$1.left;\n\t selectionPosition.top -= elementOffset$$1.top;\n\n\t var start = { x: selectionPosition.left, y: selectionPosition.top };\n\t var end = { x: selectionPosition.left + selectionPosition.width, y: selectionPosition.top + selectionPosition.height };\n\t this._updateAxisRanges(start, end);\n\n\t this.removeElement();\n\t delete this._zoomPane;\n\n\t return toChartAxisRanges(this.axisRanges);\n\t }\n\t },\n\n\t zoom: function() {\n\t var axisRanges = this.axisRanges;\n\t if (axisRanges && axisRanges.length) {\n\t var plotArea = this.chart._plotArea;\n\t for (var idx = 0; idx < axisRanges.length; idx++) {\n\t var axisRange = axisRanges[idx];\n\t plotArea.updateAxisOptions(axisRange.axis, axisRange.range);\n\t }\n\t plotArea.redraw(plotArea.panes);\n\t }\n\t },\n\n\t destroy: function() {\n\t this.removeElement();\n\t delete this._marquee;\n\t delete this.chart;\n\t },\n\n\t _updateAxisRanges: function(start, end) {\n\t var lock = (this.options.lock || \"\").toLowerCase();\n\t var axisRanges = [];\n\n\t var axes = this._zoomPane.axes;\n\t for (var idx = 0; idx < axes.length; idx++) {\n\t var axis = axes[idx];\n\t var vertical = axis.options.vertical;\n\t if (!(lock === X && !vertical) && !(lock === Y && vertical) && defined(axis.axisIndex)) {\n\t var range = axis.pointsRange(start, end);\n\t if (range) {\n\t axisRanges.push({\n\t axis: axis,\n\t range: range\n\t });\n\t }\n\t }\n\t }\n\n\t this.axisRanges = axisRanges;\n\t },\n\n\t _selectionPosition: function(e) {\n\t var clipBox = this._zoomPaneClipBox;\n\t var startLocation = {\n\t x: e.x.startLocation,\n\t y: e.y.startLocation\n\t };\n\t var pageX = e.x.location;\n\t var pageY = e.y.location;\n\t var lock = (this.options.lock || \"\").toLowerCase();\n\t var left = Math.min(startLocation.x, pageX);\n\t var top = Math.min(startLocation.y, pageY);\n\t var width = Math.abs(startLocation.x - pageX);\n\t var height = Math.abs(startLocation.y - pageY);\n\n\t if (lock === X) {\n\t left = clipBox.x1;\n\t width = clipBox.width();\n\t }\n\t if (lock === Y) {\n\t top = clipBox.y1;\n\t height = clipBox.height();\n\t }\n\n\t if (pageX > clipBox.x2) {\n\t width = clipBox.x2 - startLocation.x;\n\t }\n\n\t if (pageX < clipBox.x1) {\n\t width = startLocation.x - clipBox.x1;\n\t }\n\n\t if (pageY > clipBox.y2) {\n\t height = clipBox.y2 - startLocation.y;\n\t }\n\n\t if (pageY < clipBox.y1) {\n\t height = startLocation.y - clipBox.y1;\n\t }\n\n\t return {\n\t left: Math.max(left, clipBox.x1),\n\t top: Math.max(top, clipBox.y1),\n\t width: width,\n\t height: height\n\t };\n\t }\n\t});\n\n\tZoomSelection.prototype.options = {\n\t key: \"shift\",\n\t lock: \"none\"\n\t};\n\n\tvar MousewheelZoom = Class.extend({\n\t init: function(chart, options) {\n\n\t this.chart = chart;\n\t this.options = deepExtend({}, this.options, options);\n\t },\n\n\t updateRanges: function(delta) {\n\t var lock = (this.options.lock || \"\").toLowerCase();\n\t var axisRanges = [];\n\t var axes = this.chart._plotArea.axes;\n\n\t for (var idx = 0; idx < axes.length; idx++) {\n\t var axis = axes[idx];\n\t var vertical = axis.options.vertical;\n\n\t if (!(lock === X && !vertical) && !(lock === Y && vertical) && axis.zoomRange) {\n\t var range = axis.zoomRange(-delta);\n\n\t if (range) {\n\t axisRanges.push({\n\t axis: axis,\n\t range: range\n\t });\n\t }\n\t }\n\t }\n\n\t this.axisRanges = axisRanges;\n\t return toChartAxisRanges(axisRanges);\n\t },\n\n\t zoom: function() {\n\t var axisRanges = this.axisRanges;\n\t var plotArea = this.chart._plotArea;\n\n\t if (axisRanges && axisRanges.length && plotArea.updateAxisOptions) {\n\t for (var idx = 0; idx < axisRanges.length; idx++) {\n\t var axisRange = axisRanges[idx];\n\t plotArea.updateAxisOptions(axisRange.axis, axisRange.range);\n\t }\n\t plotArea.redraw(plotArea.panes);\n\t }\n\t },\n\n\t destroy: function() {\n\t delete this.chart;\n\t }\n\t});\n\n\tvar LegendLayout = ChartElement.extend({\n\t init: function(options, chartService) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.chartService = chartService;\n\t },\n\n\t render: function() {\n\t var ref = this;\n\t var children = ref.children;\n\t var options = ref.options;\n\t var vertical = options.vertical;\n\n\t this.visual = new drawing.Layout(null, {\n\t spacing: vertical ? 0 : options.spacing,\n\t lineSpacing: vertical ? options.spacing : 0,\n\t orientation: vertical ? \"vertical\" : \"horizontal\",\n\t reverse: options.rtl,\n\t alignItems: vertical ? \"start\" : \"center\"\n\t });\n\n\t for (var idx = 0; idx < children.length; idx++) {\n\t var legendItem = children[idx];\n\t legendItem.reflow(new Box());\n\t legendItem.renderVisual();\n\t }\n\t },\n\n\t reflow: function(box) {\n\t this.visual.rect(box.toRect());\n\t this.visual.reflow();\n\t var bbox = this.visual.clippedBBox();\n\n\t if (bbox) {\n\t this.box = dataviz.rectToBox(bbox);\n\t } else {\n\t this.box = new Box();\n\t }\n\t },\n\n\t renderVisual: function() {\n\t this.addVisual();\n\t },\n\n\t createVisual: function() {}\n\t});\n\n\tvar LegendItem = BoxElement.extend({\n\t init: function(options) {\n\t BoxElement.fn.init.call(this, options);\n\n\t this.createContainer();\n\t if (!options.rtl) {\n\t this.createMarker();\n\t this.createLabel();\n\t } else {\n\t this.createLabel();\n\t this.createMarker();\n\t }\n\t },\n\n\t createContainer: function() {\n\t this.container = new dataviz.FloatElement({ vertical: false, wrap: false, align: CENTER, spacing: this.options.spacing });\n\t this.append(this.container);\n\t },\n\n\t createMarker: function() {\n\t this.container.append(new ShapeElement(this.markerOptions()));\n\t },\n\n\t markerOptions: function() {\n\t var options = this.options;\n\t var markerColor = options.markerColor;\n\t return deepExtend({}, options.markers, {\n\t background: markerColor,\n\t border: {\n\t color: markerColor\n\t }\n\t });\n\t },\n\n\t createLabel: function() {\n\t var options = this.options;\n\t var labelOptions = deepExtend({}, options.labels);\n\n\t this.container.append(new TextBox(options.text, labelOptions));\n\t },\n\n\t renderComplete: function() {\n\t BoxElement.fn.renderComplete.call(this);\n\n\t var cursor = this.options.cursor || {};\n\t var eventSink = this._itemOverlay = Path.fromRect(this.container.box.toRect(), {\n\t fill: {\n\t color: WHITE,\n\t opacity: 0\n\t },\n\t stroke: null,\n\t cursor: cursor.style || cursor\n\t });\n\n\t this.appendVisual(eventSink);\n\t },\n\n\t click: function(widget, e) {\n\t var args = this.eventArgs(e);\n\n\t if (!widget.trigger(LEGEND_ITEM_CLICK, args) && e && e.type === 'contextmenu') {\n\t e.preventDefault();\n\t }\n\t },\n\n\t over: function(widget, e) {\n\t var args = this.eventArgs(e);\n\n\t if (!widget.trigger(LEGEND_ITEM_HOVER, args)) {\n\t widget._legendItemHover(args.seriesIndex, args.pointIndex);\n\t }\n\n\t // Don't trigger point hover for legend items\n\t return true;\n\t },\n\n\t out: function(widget, e) {\n\t widget._unsetActivePoint();\n\n\t widget.trigger(LEGEND_ITEM_LEAVE, this.eventArgs(e));\n\t },\n\n\t eventArgs: function(e) {\n\t var options = this.options;\n\n\t return {\n\t element: eventElement(e),\n\t text: options.text,\n\t series: options.series,\n\t seriesIndex: options.series.index,\n\t pointIndex: options.pointIndex\n\t };\n\t },\n\n\t renderVisual: function() {\n\t var this$1 = this;\n\n\t var options = this.options;\n\t var customVisual = options.visual;\n\n\t if (customVisual) {\n\t this.visual = customVisual({\n\t active: options.active,\n\t series: options.series,\n\t sender: this.getSender(),\n\t pointIndex: options.pointIndex,\n\t options: {\n\t markers: this.markerOptions(),\n\t labels: options.labels\n\t },\n\t createVisual: function () {\n\t this$1.createVisual();\n\t this$1.renderChildren();\n\t this$1.renderComplete();\n\n\t var defaultVisual = this$1.visual;\n\n\t delete this$1.visual;\n\n\t return defaultVisual;\n\t }\n\t });\n\t this.addVisual();\n\t } else {\n\t BoxElement.fn.renderVisual.call(this);\n\t }\n\t }\n\t});\n\n\tvar HORIZONTAL = \"horizontal\";\n\tvar POINTER = \"pointer\";\n\tvar CUSTOM = \"custom\";\n\n\tvar Legend = ChartElement.extend({\n\t init: function(options, chartService) {\n\t if (chartService === void 0) { chartService = {}; }\n\n\t ChartElement.fn.init.call(this, options);\n\n\t this.chartService = chartService;\n\n\t if (!inArray(this.options.position, [ TOP, RIGHT, BOTTOM, LEFT, CUSTOM ])) {\n\t this.options.position = RIGHT;\n\t }\n\n\t this.createContainer();\n\n\t this.createItems();\n\t },\n\n\t createContainer: function() {\n\t var options = this.options;\n\t var position = options.position;\n\t var userAlign = options.align;\n\t var align = position;\n\t var vAlign = CENTER;\n\n\t if (position === CUSTOM) {\n\t align = LEFT;\n\t } else if (inArray(position, [ TOP, BOTTOM ])) {\n\t if (userAlign === \"start\") {\n\t align = LEFT;\n\t } else if (userAlign === \"end\") {\n\t align = RIGHT;\n\t } else {\n\t align = CENTER;\n\t }\n\t vAlign = position;\n\t } else if (userAlign) {\n\t if (userAlign === \"start\") {\n\t vAlign = TOP;\n\t } else if (userAlign === \"end\") {\n\t vAlign = BOTTOM;\n\t }\n\t }\n\n\t this.container = new BoxElement({\n\t margin: options.margin,\n\t padding: options.padding,\n\t background: options.background,\n\t border: options.border,\n\t vAlign: vAlign,\n\t align: align,\n\t zIndex: options.zIndex,\n\t shrinkToFit: true\n\t });\n\n\t this.append(this.container);\n\t },\n\n\t createItems: function() {\n\t var chartService = this.getService();\n\t var options = this.options;\n\t var vertical = this.isVertical();\n\t var innerElement = new LegendLayout({\n\t vertical: vertical,\n\t spacing: options.spacing,\n\t rtl: chartService.rtl\n\t }, chartService);\n\t var items = options.items;\n\n\t if (options.reverse) {\n\t items = items.slice(0).reverse();\n\t }\n\n\t var count = items.length;\n\n\t for (var i = 0; i < count; i++) {\n\t var item = items[i];\n\n\t innerElement.append(new LegendItem(deepExtend({}, {\n\t markers: options.markers,\n\t labels: options.labels,\n\t rtl: chartService.rtl\n\t }, options.item, item)));\n\t }\n\n\t innerElement.render();\n\n\t this.container.append(innerElement);\n\t },\n\n\t isVertical: function() {\n\t var ref = this.options;\n\t var orientation = ref.orientation;\n\t var position = ref.position;\n\t var vertical = (position === CUSTOM && orientation !== HORIZONTAL) ||\n\t (defined(orientation) ? orientation !== HORIZONTAL : inArray(position, [ LEFT, RIGHT ]));\n\n\t return vertical;\n\t },\n\n\t hasItems: function() {\n\t return this.container.children[0].children.length > 0;\n\t },\n\n\t reflow: function(targetBox) {\n\t var options = this.options;\n\t var legendBox = targetBox.clone();\n\n\t if (!this.hasItems()) {\n\t this.box = legendBox;\n\t return;\n\t }\n\n\t if (options.position === CUSTOM) {\n\t this.containerCustomReflow(legendBox);\n\t this.box = legendBox;\n\t } else {\n\t this.containerReflow(legendBox);\n\t }\n\t },\n\n\t containerReflow: function(targetBox) {\n\t var ref = this;\n\t var options = ref.options;\n\t var container = ref.container;\n\t var position = options.position;\n\t var width = options.width;\n\t var height = options.height;\n\t var pos = position === TOP || position === BOTTOM ? X : Y;\n\t var vertical = this.isVertical();\n\t var alignTarget = targetBox.clone();\n\t var containerBox = targetBox.clone();\n\n\t if (position === LEFT || position === RIGHT) {\n\t containerBox.y1 = alignTarget.y1 = 0;\n\t }\n\n\t if (vertical && height) {\n\t containerBox.y2 = containerBox.y1 + height;\n\t containerBox.align(alignTarget, Y, container.options.vAlign);\n\t } else if (!vertical && width) {\n\t containerBox.x2 = containerBox.x1 + width;\n\t containerBox.align(alignTarget, X, container.options.align);\n\t }\n\n\t container.reflow(containerBox);\n\t containerBox = container.box;\n\n\t var box = containerBox.clone();\n\n\t if (options.offsetX || options.offsetY) {\n\t containerBox.translate(options.offsetX, options.offsetY);\n\t this.container.reflow(containerBox);\n\t }\n\n\t box[pos + 1] = targetBox[pos + 1];\n\t box[pos + 2] = targetBox[pos + 2];\n\n\t this.box = box;\n\t },\n\n\t containerCustomReflow: function(targetBox) {\n\t var ref = this;\n\t var options = ref.options;\n\t var container = ref.container;\n\t var offsetX = options.offsetX;\n\t var offsetY = options.offsetY;\n\t var width = options.width;\n\t var height = options.height;\n\t var vertical = this.isVertical();\n\t var containerBox = targetBox.clone();\n\n\t if (vertical && height) {\n\t containerBox.y2 = containerBox.y1 + height;\n\t } else if (!vertical && width) {\n\t containerBox.x2 = containerBox.x1 + width;\n\t }\n\t container.reflow(containerBox);\n\t containerBox = container.box;\n\n\t container.reflow(new Box(\n\t offsetX, offsetY,\n\t offsetX + containerBox.width(), offsetY + containerBox.height()\n\t ));\n\t },\n\n\t renderVisual: function() {\n\t if (this.hasItems()) {\n\t ChartElement.fn.renderVisual.call(this);\n\t }\n\t }\n\t});\n\n\tsetDefaultOptions(Legend, {\n\t position: RIGHT,\n\t items: [],\n\t offsetX: 0,\n\t offsetY: 0,\n\t margin: getSpacing(5),\n\t padding: getSpacing(5),\n\t border: {\n\t color: BLACK,\n\t width: 0\n\t },\n\t item: {\n\t cursor: POINTER,\n\t spacing: 6\n\t },\n\t spacing: 6,\n\t background: \"\",\n\t zIndex: 1,\n\t markers: {\n\t border: {\n\t width: 0\n\t },\n\t width: 15,\n\t height: 3,\n\t type: \"rect\",\n\t align: LEFT,\n\t vAlign: CENTER\n\t }\n\t});\n\n\tvar PlotAreaFactory = Class.extend({\n\t init: function() {\n\n\t this._registry = [];\n\t },\n\n\t register: function(type, seriesTypes) {\n\t this._registry.push({\n\t type: type,\n\t seriesTypes: seriesTypes\n\t });\n\t },\n\n\t create: function(srcSeries, options, chartService) {\n\t var registry = this._registry;\n\t var match = registry[0];\n\t var series;\n\n\t for (var idx = 0; idx < registry.length; idx++) {\n\t var entry = registry[idx];\n\t series = filterSeriesByType(srcSeries, entry.seriesTypes);\n\n\t if (series.length > 0) {\n\t match = entry;\n\t break;\n\t }\n\t }\n\n\t return new match.type(series, options, chartService);\n\t }\n\t});\n\n\tPlotAreaFactory.current = new PlotAreaFactory();\n\n\tvar ZOOM_ACCELERATION = 3;\n\tvar SELECTOR_HEIGHT_ADJUST = 0.1;\n\n\tfunction createDiv(className) {\n\t var element = document.createElement(\"div\");\n\t if (className) {\n\t element.className = className;\n\t }\n\n\t return element;\n\t}\n\n\tfunction closestHandle(element) {\n\t var current = element;\n\t while (current && !hasClasses(current, \"k-handle\")) {\n\t current = current.parentNode;\n\t }\n\n\t return current;\n\t}\n\n\tvar Selection = Class.extend({\n\t init: function(chart, categoryAxis, options, observer) {\n\n\t var chartElement = chart.element;\n\n\t this.options = deepExtend({}, this.options, options);\n\t this.chart = chart;\n\t this.observer = observer;\n\t this.chartElement = chartElement;\n\t this.categoryAxis = categoryAxis;\n\t this._dateAxis = this.categoryAxis instanceof dataviz.DateCategoryAxis;\n\n\t this.initOptions();\n\n\t this.visible = this.options.visible && chartElement.offsetHeight;\n\n\t if (this.visible) {\n\t this.createElements();\n\n\t this.set(this._index(this.options.from), this._index(this.options.to));\n\n\t this.bindEvents();\n\t }\n\t },\n\n\t onPane: function(pane) {\n\t return this.categoryAxis.pane === pane;\n\t },\n\n\t createElements: function() {\n\t var options = this.options;\n\t var wrapper = this.wrapper = createDiv(\"k-selector\");\n\t elementStyles(wrapper, {\n\t top: options.offset.top,\n\t left: options.offset.left,\n\t width: options.width,\n\t height: options.height,\n\t direction: 'ltr'\n\t });\n\t var selection = this.selection = createDiv(\"k-selection\");\n\t this.leftMask = createDiv(\"k-mask\");\n\t this.rightMask = createDiv(\"k-mask\");\n\n\t wrapper.appendChild(this.leftMask);\n\t wrapper.appendChild(this.rightMask);\n\t wrapper.appendChild(selection);\n\n\t selection.appendChild(createDiv(\"k-selection-bg\"));\n\n\t var leftHandle = this.leftHandle = createDiv(\"k-handle k-left-handle\");\n\t var rightHandle = this.rightHandle = createDiv(\"k-handle k-right-handle\");\n\t leftHandle.appendChild(createDiv());\n\t rightHandle.appendChild(createDiv());\n\n\t selection.appendChild(leftHandle);\n\t selection.appendChild(rightHandle);\n\n\t this.chartElement.appendChild(wrapper);\n\t var selectionStyles = elementStyles(selection, [ \"borderLeftWidth\", \"borderRightWidth\", \"height\" ]);\n\t var leftHandleHeight = elementStyles(leftHandle, \"height\").height;\n\t var rightHandleHeight = elementStyles(rightHandle, \"height\").height;\n\n\t options.selection = {\n\t border: {\n\t left: selectionStyles.borderLeftWidth,\n\t right: selectionStyles.borderRightWidth\n\t }\n\t };\n\n\t elementStyles(leftHandle, {\n\t top: (selectionStyles.height - leftHandleHeight) / 2\n\t });\n\n\t elementStyles(rightHandle, {\n\t top: (selectionStyles.height - rightHandleHeight) / 2\n\t });\n\n\t wrapper.style.cssText = wrapper.style.cssText;\n\t },\n\n\t bindEvents: function() {\n\t if (this.options.mousewheel !== false) {\n\t this._mousewheelHandler = this._mousewheel.bind(this);\n\t var obj;\n\t bindEvents(this.wrapper, ( obj = {}, obj[ MOUSEWHEEL ] = this._mousewheelHandler, obj ));\n\t }\n\n\t this._domEvents = services.DomEventsBuilder.create(this.wrapper, {\n\t stopPropagation: true, // applicable for the jQuery UserEvents\n\t start: this._start.bind(this),\n\t move: this._move.bind(this),\n\t end: this._end.bind(this),\n\t tap: this._tap.bind(this),\n\t press: this._press.bind(this),\n\t gesturestart: this._gesturestart.bind(this),\n\t gesturechange: this._gesturechange.bind(this),\n\t gestureend: this._gestureend.bind(this)\n\t });\n\t },\n\n\t initOptions: function() {\n\t var ref = this;\n\t var options = ref.options;\n\t var categoryAxis = ref.categoryAxis;\n\t var box = categoryAxis.pane.chartsBox();\n\t var intlService = this.chart.chartService.intl;\n\n\t if (this._dateAxis) {\n\t deepExtend(options, {\n\t min: parseDate(intlService, options.min),\n\t max: parseDate(intlService, options.max),\n\t from: parseDate(intlService, options.from),\n\t to: parseDate(intlService, options.to)\n\t });\n\t }\n\n\t var ref$1 = elementStyles(this.chartElement, [ \"paddingLeft\", \"paddingTop\" ]);\n\t var paddingLeft = ref$1.paddingLeft;\n\t var paddingTop = ref$1.paddingTop;\n\n\t this.options = deepExtend({}, {\n\t width: box.width(),\n\t height: box.height() + SELECTOR_HEIGHT_ADJUST, //workaround for sub-pixel hover on the paths in chrome\n\t padding: {\n\t left: paddingLeft,\n\t top: paddingTop\n\t },\n\t offset: {\n\t left: box.x1 + paddingLeft,\n\t top: box.y1 + paddingTop\n\t },\n\t from: options.min,\n\t to: options.max\n\t }, options);\n\t },\n\n\t destroy: function() {\n\t if (this._domEvents) {\n\t this._domEvents.destroy();\n\t delete this._domEvents;\n\t }\n\n\t clearTimeout(this._mwTimeout);\n\t this._state = null;\n\n\t if (this.wrapper) {\n\t if (this._mousewheelHandler) {\n\t var obj;\n\t unbindEvents(this.wrapper, ( obj = {}, obj[ MOUSEWHEEL ] = this._mousewheelHandler, obj ));\n\t this._mousewheelHandler = null;\n\t }\n\t this.chartElement.removeChild(this.wrapper);\n\t this.wrapper = null;\n\t }\n\t },\n\n\t _rangeEventArgs: function(range) {\n\n\t return {\n\t axis: this.categoryAxis.options,\n\t from: this._value(range.from),\n\t to: this._value(range.to)\n\t };\n\t },\n\n\t _start: function(e) {\n\t var options = this.options;\n\t var target = eventElement(e);\n\n\t if (this._state || !target) {\n\t return;\n\t }\n\n\t this.chart._unsetActivePoint();\n\t this._state = {\n\t moveTarget: closestHandle(target) || target,\n\t startLocation: e.x ? e.x.location : 0,\n\t range: {\n\t from: this._index(options.from),\n\t to: this._index(options.to)\n\t }\n\t };\n\n\t var args = this._rangeEventArgs({\n\t from: this._index(options.from),\n\t to: this._index(options.to)\n\t });\n\n\t if (this.trigger(SELECT_START, args)) {\n\t this._state = null;\n\t }\n\t },\n\n\t _press: function(e) {\n\t var handle;\n\t if (this._state) {\n\t handle = this._state.moveTarget;\n\t } else {\n\t handle = closestHandle(eventElement(e));\n\t }\n\t if (handle) {\n\t dataviz.addClass(handle, \"k-handle-active\");\n\t }\n\t },\n\n\t _move: function(e) {\n\t if (!this._state) {\n\t return;\n\t }\n\n\t var ref = this;\n\t var state = ref._state;\n\t var options = ref.options;\n\t var categoryAxis = ref.categoryAxis;\n\t var range = state.range;\n\t var target = state.moveTarget;\n\t var reverse = categoryAxis.options.reverse;\n\t var from = this._index(options.from);\n\t var to = this._index(options.to);\n\t var min = this._index(options.min);\n\t var max = this._index(options.max);\n\t var delta = state.startLocation - e.x.location;\n\t var oldRange = { from: range.from, to: range.to };\n\t var span = range.to - range.from;\n\t var scale = elementStyles(this.wrapper, \"width\").width / (categoryAxis.categoriesCount() - 1);\n\t var offset = Math.round(delta / scale) * (reverse ? -1 : 1);\n\n\t if (!target) {\n\t return;\n\t }\n\n\t var leftHandle = hasClasses(target, \"k-left-handle\");\n\t var rightHandle = hasClasses(target, \"k-right-handle\");\n\n\t if (hasClasses(target, \"k-selection k-selection-bg\")) {\n\t range.from = Math.min(\n\t Math.max(min, from - offset),\n\t max - span\n\t );\n\t range.to = Math.min(\n\t range.from + span,\n\t max\n\t );\n\t } else if ((leftHandle && !reverse) || (rightHandle && reverse)) {\n\t range.from = Math.min(\n\t Math.max(min, from - offset),\n\t max - 1\n\t );\n\t range.to = Math.max(range.from + 1, range.to);\n\t } else if ((leftHandle && reverse) || (rightHandle && !reverse)) {\n\t range.to = Math.min(\n\t Math.max(min + 1, to - offset),\n\t max\n\t );\n\t range.from = Math.min(range.to - 1, range.from);\n\t }\n\n\t if (range.from !== oldRange.from || range.to !== oldRange.to) {\n\t this.move(range.from, range.to);\n\t this.trigger(SELECT, this._rangeEventArgs(range));\n\t }\n\t },\n\n\t _end: function() {\n\t if (this._state) {\n\t var moveTarget = this._state.moveTarget;\n\t if (moveTarget) {\n\t dataviz.removeClass(moveTarget, \"k-handle-active\");\n\t }\n\n\t var range = this._state.range;\n\t this.set(range.from, range.to);\n\t this.trigger(SELECT_END, this._rangeEventArgs(range));\n\n\t delete this._state;\n\t }\n\t },\n\n\t _tap: function(e) {\n\t var ref = this;\n\t var options = ref.options;\n\t var categoryAxis = ref.categoryAxis;\n\t var coords = this.chart._eventCoordinates(e);\n\t var categoryIx = categoryAxis.pointCategoryIndex(new Point(coords.x, categoryAxis.box.y1));\n\t var from = this._index(options.from);\n\t var to = this._index(options.to);\n\t var min = this._index(options.min);\n\t var max = this._index(options.max);\n\t var span = to - from;\n\t var mid = from + span / 2;\n\t var range = {};\n\t var rightClick = e.event.which === 3;\n\t var offset = Math.round(mid - categoryIx);\n\n\t if (this._state || rightClick) {\n\t return;\n\t }\n\n\t this.chart._unsetActivePoint();\n\n\t if (!categoryAxis.options.justified) {\n\t offset--;\n\t }\n\n\t range.from = Math.min(\n\t Math.max(min, from - offset),\n\t max - span\n\t );\n\n\t range.to = Math.min(range.from + span, max);\n\n\t this._start(e);\n\t if (this._state) {\n\t this._state.range = range;\n\t this.trigger(SELECT, this._rangeEventArgs(range));\n\t this._end();\n\t }\n\t },\n\n\t _mousewheel: function(e) {\n\t var this$1 = this;\n\n\t var delta = dataviz.mousewheelDelta(e);\n\n\t this._start({ target: this.selection });\n\n\t if (this._state) {\n\t var range = this._state.range;\n\n\t e.preventDefault();\n\t e.stopPropagation();\n\n\t if (Math.abs(delta) > 1) {\n\t delta *= ZOOM_ACCELERATION;\n\t }\n\n\t if (this.options.mousewheel.reverse) {\n\t delta *= -1;\n\t }\n\n\t if (this.expand(delta)) {\n\t this.trigger(SELECT, {\n\t axis: this.categoryAxis.options,\n\t delta: delta,\n\t originalEvent: e,\n\t from: this._value(range.from),\n\t to: this._value(range.to)\n\t });\n\t }\n\n\t if (this._mwTimeout) {\n\t clearTimeout(this._mwTimeout);\n\t }\n\n\t this._mwTimeout = setTimeout(function () {\n\t this$1._end();\n\t }, MOUSEWHEEL_DELAY);\n\t }\n\t },\n\n\t _gesturestart: function(e) {\n\t var options = this.options;\n\n\t this._state = {\n\t range: {\n\t from: this._index(options.from),\n\t to: this._index(options.to)\n\t }\n\t };\n\t var args = this._rangeEventArgs(this._state.range);\n\n\t if (this.trigger(SELECT_START, args)) {\n\t this._state = null;\n\t } else {\n\t e.preventDefault();\n\t }\n\t },\n\n\t _gestureend: function() {\n\t if (this._state) {\n\t this.trigger(SELECT_END, this._rangeEventArgs(this._state.range));\n\t delete this._state;\n\t }\n\t },\n\n\t _gesturechange: function(e) {\n\t var ref = this;\n\t var chart = ref.chart;\n\t var state = ref._state;\n\t var options = ref.options;\n\t var categoryAxis = ref.categoryAxis;\n\t var range = state.range;\n\t var p0 = chart._toModelCoordinates(e.touches[0].x.location).x;\n\t var p1 = chart._toModelCoordinates(e.touches[1].x.location).x;\n\t var left = Math.min(p0, p1);\n\t var right = Math.max(p0, p1);\n\n\t e.preventDefault();\n\n\t range.from = categoryAxis.pointCategoryIndex(new Point(left)) || options.min;\n\n\t range.to = categoryAxis.pointCategoryIndex(new Point(right)) || options.max;\n\n\t this.move(range.from, range.to);\n\n\t this.trigger(SELECT, this._rangeEventArgs(range));\n\t },\n\n\t _index: function(value) {\n\t var index = value;\n\n\t if (value instanceof Date) {\n\t index = this.categoryAxis.categoryIndex(value);\n\t }\n\n\t return index;\n\t },\n\n\t _value: function(index) {\n\t var value = index;\n\t if (this._dateAxis) {\n\t value = this.categoryAxis.categoryAt(index);\n\t if (value > this.options.max) {\n\t value = this.options.max;\n\t }\n\t }\n\n\t return value;\n\t },\n\n\t _slot: function(value) {\n\t var categoryAxis = this.categoryAxis;\n\t var index = this._index(value);\n\n\t return categoryAxis.getSlot(index, index, true);\n\t },\n\n\t move: function(from, to) {\n\t var options = this.options;\n\t var reverse = this.categoryAxis.options.reverse;\n\t var offset = options.offset;\n\t var padding = options.padding;\n\t var border = options.selection.border;\n\t var left = reverse ? to : from;\n\t var right = reverse ? from : to;\n\t var edge = 'x' + (reverse ? 2 : 1);\n\n\t var box = this._slot(left);\n\t var leftMaskWidth = round(box[edge] - offset.left + padding.left);\n\n\t elementStyles(this.leftMask, {\n\t width: leftMaskWidth\n\t });\n\t elementStyles(this.selection, {\n\t left: leftMaskWidth\n\t });\n\n\t box = this._slot(right);\n\n\t var rightMaskWidth = round(options.width - (box[edge] - offset.left + padding.left));\n\t elementStyles(this.rightMask, {\n\t width: rightMaskWidth\n\t });\n\n\t var distance = options.width - rightMaskWidth;\n\t if (distance !== options.width) {\n\t distance += border.right;\n\t }\n\n\t elementStyles(this.rightMask, {\n\t left: distance\n\t });\n\t elementStyles(this.selection, {\n\t width: Math.max(options.width - (leftMaskWidth + rightMaskWidth) - border.right, 0)\n\t });\n\t },\n\n\t set: function(from, to) {\n\t var options = this.options;\n\t var min = this._index(options.min);\n\t var max = this._index(options.max);\n\t var fromValue = limitValue(this._index(from), min, max);\n\t var toValue = limitValue(this._index(to), fromValue + 1, max);\n\n\t if (options.visible) {\n\t this.move(fromValue, toValue);\n\t }\n\n\t options.from = this._value(fromValue);\n\t options.to = this._value(toValue);\n\t },\n\n\t expand: function(delta) {\n\t var options = this.options;\n\t var min = this._index(options.min);\n\t var max = this._index(options.max);\n\t var zDir = options.mousewheel.zoom;\n\t var from = this._index(options.from);\n\t var to = this._index(options.to);\n\t var range = { from: from, to: to };\n\t var oldRange = deepExtend({}, range);\n\n\t if (this._state) {\n\t range = this._state.range;\n\t }\n\n\t if (zDir !== RIGHT) {\n\t range.from = limitValue(\n\t limitValue(from - delta, 0, to - 1),\n\t min, max\n\t );\n\t }\n\n\t if (zDir !== LEFT) {\n\t range.to = limitValue(\n\t limitValue(to + delta, range.from + 1, max),\n\t min,\n\t max\n\t );\n\t }\n\n\t if (range.from !== oldRange.from || range.to !== oldRange.to) {\n\t this.set(range.from, range.to);\n\t return true;\n\t }\n\t },\n\n\t trigger: function(name, args) {\n\t return (this.observer || this.chart).trigger(name, args);\n\t }\n\t});\n\n\tsetDefaultOptions(Selection, {\n\t visible: true,\n\t mousewheel: {\n\t zoom: \"both\"\n\t },\n\t min: MIN_VALUE,\n\t max: MAX_VALUE\n\t});\n\n\tvar Tooltip = BaseTooltip.extend({\n\t show: function(point) {\n\t if (!point || !point.tooltipAnchor || (this._current && this._current === point)) {\n\t return;\n\t }\n\n\t var options = deepExtend({}, this.options, point.options.tooltip);\n\t var anchor = point.tooltipAnchor();\n\n\t if (anchor) {\n\t this._current = point;\n\t BaseTooltip.fn.show.call(this, {\n\t point: point,\n\t anchor: anchor\n\t }, options, point);\n\t } else {\n\t this.hide();\n\t }\n\t },\n\n\t hide: function() {\n\t delete this._current;\n\t BaseTooltip.fn.hide.call(this);\n\t }\n\t});\n\n\tvar SharedTooltip = BaseTooltip.extend({\n\t init: function(plotArea, options) {\n\t BaseTooltip.fn.init.call(this, plotArea.chartService, options);\n\n\t this.plotArea = plotArea;\n\t this.formatService = plotArea.chartService.format;\n\t },\n\n\t showAt: function(points, coords) {\n\t var tooltipPoints = grep(points, function(point) {\n\t var tooltip = point.series.tooltip;\n\t var excluded = tooltip && tooltip.visible === false;\n\n\t return !excluded;\n\t });\n\n\t if (tooltipPoints.length > 0) {\n\t var point = tooltipPoints[0];\n\t var slot = this.plotArea.categoryAxis.getSlot(point.categoryIx);\n\n\t var anchor = coords ? this._slotAnchor(coords, slot) : this._defaultAnchor(point, slot);\n\n\t this.show({\n\t anchor: anchor,\n\t shared: true,\n\t points: points,\n\t category: point.category,\n\t categoryText: this.formatService.auto(this.options.categoryFormat, point.category),\n\t series: this.plotArea.series\n\t }, this.options);\n\t }\n\t },\n\n\t _slotAnchor: function(point, slot) {\n\t var axis = this.plotArea.categoryAxis;\n\t var align = {\n\t horizontal: \"left\",\n\t vertical: \"center\"\n\t };\n\n\t if (!axis.options.vertical) {\n\t point.x = slot.center().x;\n\t }\n\n\t return {\n\t point: point,\n\t align: align\n\t };\n\t },\n\n\t _defaultAnchor: function(point, slot) {\n\t var box = point.owner.pane.chartsBox();\n\t var vertical = this.plotArea.categoryAxis.options.vertical;\n\t var center = box.center();\n\t var slotCenter = slot.center();\n\t var align = {\n\t horizontal: \"center\",\n\t vertical: \"center\"\n\t };\n\n\t var centerPoint;\n\t if (vertical) {\n\t centerPoint = new Point(center.x, slotCenter.y);\n\t } else {\n\t centerPoint = new Point(slotCenter.x, center.y);\n\t }\n\n\t return {\n\t point: centerPoint,\n\t align: align\n\t };\n\t }\n\t});\n\n\tsetDefaultOptions(SharedTooltip, {\n\t categoryFormat: '{0:d}'\n\t});\n\n\tvar BarChartAnimation = Animation.extend({\n\t setup: function() {\n\t var ref = this;\n\t var element = ref.element;\n\t var options = ref.options;\n\t var bbox = element.bbox();\n\n\t if (bbox) {\n\t this.origin = options.origin;\n\t var axis = options.vertical ? Y : X;\n\n\t var fromScale = this.fromScale = new GeometryPoint(1, 1);\n\t fromScale[axis] = START_SCALE;\n\n\t element.transform(transform()\n\t .scale(fromScale.x, fromScale.y)\n\t );\n\t } else {\n\t this.abort();\n\t }\n\t },\n\n\t step: function(pos) {\n\t var scaleX = dataviz.interpolateValue(this.fromScale.x, 1, pos);\n\t var scaleY = dataviz.interpolateValue(this.fromScale.y, 1, pos);\n\n\t this.element.transform(transform()\n\t .scale(scaleX, scaleY, this.origin)\n\t );\n\t },\n\n\t abort: function() {\n\t Animation.fn.abort.call(this);\n\t this.element.transform(null);\n\t }\n\t});\n\n\tsetDefaultOptions(BarChartAnimation, {\n\t duration: INITIAL_ANIMATION_DURATION\n\t});\n\n\tAnimationFactory.current.register(BAR, BarChartAnimation);\n\n\tvar BubbleAnimation = Animation.extend({\n\t setup: function() {\n\t var center = this.center = this.element.bbox().center();\n\t this.element.transform(transform()\n\t .scale(START_SCALE, START_SCALE, center)\n\t );\n\t },\n\n\t step: function(pos) {\n\t this.element.transform(transform()\n\t .scale(pos, pos, this.center)\n\t );\n\t }\n\t});\n\n\tsetDefaultOptions(BubbleAnimation, {\n\t easing: \"easeOutElastic\"\n\t});\n\n\tAnimationFactory.current.register(BUBBLE, BubbleAnimation);\n\n\tvar FadeInAnimation = Animation.extend({\n\t setup: function() {\n\t this.fadeTo = this.element.opacity();\n\t this.element.opacity(0);\n\t },\n\n\t step: function(pos) {\n\t this.element.opacity(pos * this.fadeTo);\n\t }\n\t});\n\n\tsetDefaultOptions(FadeInAnimation, {\n\t duration: 200,\n\t easing: \"linear\"\n\t});\n\n\tAnimationFactory.current.register(FADEIN, FadeInAnimation);\n\n\tvar PieAnimation = Animation.extend({\n\t setup: function() {\n\t this.element.transform(transform()\n\t .scale(START_SCALE, START_SCALE, this.options.center)\n\t );\n\t },\n\n\t step: function(pos) {\n\t this.element.transform(transform()\n\t .scale(pos, pos, this.options.center)\n\t );\n\t }\n\t});\n\n\tsetDefaultOptions(PieAnimation, {\n\t easing: \"easeOutElastic\",\n\t duration: INITIAL_ANIMATION_DURATION\n\t});\n\n\tAnimationFactory.current.register(PIE, PieAnimation);\n\n\tvar ScatterLineChart = ScatterChart.extend({\n\t render: function() {\n\t ScatterChart.fn.render.call(this);\n\n\t this.renderSegments();\n\t },\n\n\t createSegment: function(linePoints, currentSeries, seriesIx) {\n\t var style = currentSeries.style;\n\t var pointType;\n\n\t if (style === SMOOTH) {\n\t pointType = SplineSegment;\n\t } else {\n\t pointType = LineSegment;\n\t }\n\n\t return new pointType(linePoints, currentSeries, seriesIx);\n\t },\n\n\t animationPoints: function() {\n\t var points = ScatterChart.fn.animationPoints.call(this);\n\t return points.concat(this._segments);\n\t },\n\n\t createMissingValue: function(value, missingValues) {\n\t if (missingValues === ZERO) {\n\t var missingValue = {\n\t x: value.x,\n\t y: value.y\n\t };\n\t if (!hasValue(missingValue.x)) {\n\t missingValue.x = 0;\n\t }\n\t if (!hasValue(missingValue.y)) {\n\t missingValue.y = 0;\n\t }\n\t return missingValue;\n\t }\n\t }\n\t});\n\n\tdeepExtend(ScatterLineChart.prototype, LineChartMixin);\n\n\tvar XYPlotArea = PlotAreaBase.extend({\n\t initFields: function() {\n\t this.namedXAxes = {};\n\t this.namedYAxes = {};\n\n\t this.xAxisRangeTracker = new AxisGroupRangeTracker();\n\t this.yAxisRangeTracker = new AxisGroupRangeTracker();\n\t },\n\n\t render: function(panes) {\n\t var this$1 = this;\n\t if (panes === void 0) { panes = this.panes; }\n\n\t var seriesByPane = this.groupSeriesByPane();\n\n\t for (var i = 0; i < panes.length; i++) {\n\t var pane = panes[i];\n\t var paneSeries = seriesByPane[pane.options.name || \"default\"] || [];\n\t this$1.addToLegend(paneSeries);\n\t var filteredSeries = this$1.filterVisibleSeries(paneSeries);\n\n\t if (!filteredSeries) {\n\t continue;\n\t }\n\n\t this$1.createScatterChart(\n\t filterSeriesByType(filteredSeries, SCATTER),\n\t pane\n\t );\n\n\t this$1.createScatterLineChart(\n\t filterSeriesByType(filteredSeries, SCATTER_LINE),\n\t pane\n\t );\n\n\t this$1.createBubbleChart(\n\t filterSeriesByType(filteredSeries, BUBBLE),\n\t pane\n\t );\n\t }\n\n\t this.createAxes(panes);\n\t },\n\n\t appendChart: function(chart, pane) {\n\t this.xAxisRangeTracker.update(chart.xAxisRanges);\n\t this.yAxisRangeTracker.update(chart.yAxisRanges);\n\n\t PlotAreaBase.fn.appendChart.call(this, chart, pane);\n\t },\n\n\t removeAxis: function(axis) {\n\t var axisName = axis.options.name;\n\n\t PlotAreaBase.fn.removeAxis.call(this, axis);\n\n\t if (axis.options.vertical) {\n\t this.yAxisRangeTracker.reset(axisName);\n\t delete this.namedYAxes[axisName];\n\t } else {\n\t this.xAxisRangeTracker.reset(axisName);\n\t delete this.namedXAxes[axisName];\n\t }\n\n\t if (axis === this.axisX) {\n\t delete this.axisX;\n\t }\n\n\t if (axis === this.axisY) {\n\t delete this.axisY;\n\t }\n\t },\n\n\t seriesPaneName: function(series) {\n\t var options = this.options;\n\t var xAxisName = series.xAxis;\n\t var xAxisOptions = [].concat(options.xAxis);\n\t var xAxis = grep(xAxisOptions, function(a) { return a.name === xAxisName; })[0];\n\t var yAxisName = series.yAxis;\n\t var yAxisOptions = [].concat(options.yAxis);\n\t var yAxis = grep(yAxisOptions, function(a) { return a.name === yAxisName; })[0];\n\t var panes = options.panes || [ {} ];\n\t var defaultPaneName = panes[0].name || \"default\";\n\t var paneName = (xAxis || {}).pane || (yAxis || {}).pane || defaultPaneName;\n\n\t return paneName;\n\t },\n\n\t createScatterChart: function(series, pane) {\n\t if (series.length > 0) {\n\t this.appendChart(\n\t new ScatterChart(this, { series: series, clip: pane.options.clip }),\n\t pane\n\t );\n\t }\n\t },\n\n\t createScatterLineChart: function(series, pane) {\n\t if (series.length > 0) {\n\t this.appendChart(\n\t new ScatterLineChart(this, { series: series, clip: pane.options.clip }),\n\t pane\n\t );\n\t }\n\t },\n\n\t createBubbleChart: function(series, pane) {\n\t if (series.length > 0) {\n\t this.appendChart(\n\t new BubbleChart(this, { series: series, clip: pane.options.clip }),\n\t pane\n\t );\n\t }\n\t },\n\n\t createXYAxis: function(options, vertical, axisIndex) {\n\t var axisName = options.name;\n\t var namedAxes = vertical ? this.namedYAxes : this.namedXAxes;\n\t var tracker = vertical ? this.yAxisRangeTracker : this.xAxisRangeTracker;\n\t var axisOptions = deepExtend({ reverse: !vertical && this.chartService.rtl }, options, { vertical: vertical });\n\t var isLog = equalsIgnoreCase(axisOptions.type, LOGARITHMIC);\n\t var defaultRange = tracker.query();\n\t var defaultAxisRange = isLog ? { min: 0.1, max: 1 } : { min: 0, max: 1 };\n\t var range = tracker.query(axisName) || defaultRange || defaultAxisRange;\n\t var typeSamples = [ axisOptions.min, axisOptions.max ];\n\t var series = this.series;\n\n\t for (var seriesIx = 0; seriesIx < series.length; seriesIx++) {\n\t var currentSeries = series[seriesIx];\n\t var seriesAxisName = currentSeries[vertical ? \"yAxis\" : \"xAxis\"];\n\t if ((seriesAxisName === axisOptions.name) || (axisIndex === 0 && !seriesAxisName)) {\n\t var firstPointValue = SeriesBinder.current.bindPoint(currentSeries, 0).valueFields;\n\t typeSamples.push(firstPointValue[vertical ? \"y\" : \"x\"]);\n\n\t break;\n\t }\n\t }\n\n\t if (axisIndex === 0 && defaultRange) {\n\t range.min = Math.min(range.min, defaultRange.min);\n\t range.max = Math.max(range.max, defaultRange.max);\n\t }\n\n\t var inferredDate;\n\n\t for (var i = 0; i < typeSamples.length; i++) {\n\t if (typeSamples[i] instanceof Date) {\n\t inferredDate = true;\n\t break;\n\t }\n\t }\n\n\t var axisType;\n\t if (equalsIgnoreCase(axisOptions.type, DATE) || (!axisOptions.type && inferredDate)) {\n\t axisType = dataviz.DateValueAxis;\n\t } else if (isLog) {\n\t axisType = dataviz.LogarithmicAxis;\n\t } else {\n\t axisType = dataviz.NumericAxis;\n\t }\n\n\t var axis = new axisType(range.min, range.max, axisOptions, this.chartService);\n\t axis.axisIndex = axisIndex;\n\n\t if (axisName) {\n\t if (namedAxes[axisName]) {\n\t throw new Error(((vertical ? \"Y\" : \"X\") + \" axis with name \" + axisName + \" is already defined\"));\n\t }\n\t namedAxes[axisName] = axis;\n\t }\n\n\t this.appendAxis(axis);\n\n\t return axis;\n\t },\n\n\t createAxes: function(panes) {\n\t var this$1 = this;\n\n\t var options = this.options;\n\t var xAxesOptions = [].concat(options.xAxis);\n\t var xAxes = [];\n\t var yAxesOptions = [].concat(options.yAxis);\n\t var yAxes = [];\n\n\t for (var idx = 0; idx < xAxesOptions.length; idx++) {\n\t var axisPane = this$1.findPane(xAxesOptions[idx].pane);\n\t if (inArray(axisPane, panes)) {\n\t xAxes.push(this$1.createXYAxis(xAxesOptions[idx], false, idx));\n\t }\n\t }\n\n\t for (var idx$1 = 0; idx$1 < yAxesOptions.length; idx$1++) {\n\t var axisPane$1 = this$1.findPane(yAxesOptions[idx$1].pane);\n\t if (inArray(axisPane$1, panes)) {\n\t yAxes.push(this$1.createXYAxis(yAxesOptions[idx$1], true, idx$1));\n\t }\n\t }\n\n\t this.axisX = this.axisX || xAxes[0];\n\t this.axisY = this.axisY || yAxes[0];\n\t },\n\n\t _dispatchEvent: function(chart, e, eventType) {\n\t var coords = chart._eventCoordinates(e);\n\t var point = new Point(coords.x, coords.y);\n\t var allAxes = this.axes;\n\t var length = allAxes.length;\n\t var xValues = [];\n\t var yValues = [];\n\n\t for (var i = 0; i < length; i++) {\n\t var axis = allAxes[i];\n\t var values = axis.options.vertical ? yValues : xValues;\n\t var currentValue = axis.getValue(point);\n\t if (currentValue !== null) {\n\t values.push(currentValue);\n\t }\n\t }\n\n\t if (xValues.length > 0 && yValues.length > 0) {\n\t chart.trigger(eventType, {\n\t element: eventElement(e),\n\t originalEvent: e,\n\t x: singleItemOrArray(xValues),\n\t y: singleItemOrArray(yValues)\n\t });\n\t }\n\t },\n\n\t updateAxisOptions: function(axis, options) {\n\t var vertical = axis.options.vertical;\n\t var axes = this.groupAxes(this.panes);\n\t var index = (vertical ? axes.y : axes.x).indexOf(axis);\n\n\t updateAxisOptions$1(this.options, index, vertical, options);\n\t updateAxisOptions$1(this.originalOptions, index, vertical, options);\n\t }\n\t});\n\n\tfunction updateAxisOptions$1(targetOptions, axisIndex, vertical, options) {\n\t var axisOptions = ([].concat(vertical ? targetOptions.yAxis : targetOptions.xAxis))[axisIndex];\n\t deepExtend(axisOptions, options);\n\t}\n\n\tsetDefaultOptions(XYPlotArea, {\n\t xAxis: {},\n\t yAxis: {}\n\t});\n\n\tdeepExtend(XYPlotArea.prototype, PlotAreaEventsMixin);\n\n\tvar PieSegment = ChartElement.extend({\n\t init: function(value, sector, options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.value = value;\n\t this.sector = sector;\n\t },\n\n\t render: function() {\n\t var labels = this.options.labels;\n\t var chartService = this.owner.chartService;\n\t var labelText = this.value;\n\n\t if (this._rendered || this.visible === false) {\n\t return;\n\t }\n\t this._rendered = true;\n\n\t var labelTemplate = getTemplate(labels);\n\t var pointData = this.pointData();\n\n\t if (labelTemplate) {\n\t labelText = labelTemplate(pointData);\n\t } else if (labels.format) {\n\t labelText = chartService.format.auto(labels.format, labelText);\n\t }\n\n\t if (labels.visible && (labelText || labelText === 0)) {\n\t if (labels.position === CENTER || labels.position === INSIDE_END) {\n\t if (!labels.color) {\n\t var brightnessValue = new Color(this.options.color).percBrightness();\n\t if (brightnessValue > 180) {\n\t labels.color = BLACK;\n\t } else {\n\t labels.color = WHITE;\n\t }\n\t }\n\t if (!labels.background) {\n\t labels.background = this.options.color;\n\t }\n\t } else {\n\t var themeLabels = chartService.theme.seriesDefaults.labels;\n\t labels.color = labels.color || themeLabels.color;\n\t labels.background = labels.background || themeLabels.background;\n\t }\n\n\t this.label = new TextBox(labelText, deepExtend({}, labels, {\n\t align: CENTER,\n\t vAlign: \"\",\n\t animation: {\n\t type: FADEIN,\n\t delay: this.animationDelay\n\t }\n\t }), pointData);\n\n\t this.append(this.label);\n\t }\n\t },\n\n\t reflow: function(targetBox) {\n\t this.render();\n\t this.box = targetBox;\n\t this.reflowLabel();\n\t },\n\n\t reflowLabel: function() {\n\t var ref = this;\n\t var labelsOptions = ref.options.labels;\n\t var label = ref.label;\n\t var sector = this.sector.clone();\n\t var labelsDistance = labelsOptions.distance;\n\t var angle = sector.middle();\n\n\t if (label) {\n\t var labelHeight = label.box.height();\n\t var labelWidth = label.box.width();\n\t var lp;\n\n\t if (labelsOptions.position === CENTER) {\n\t sector.radius = Math.abs((sector.radius - labelHeight) / 2) + labelHeight;\n\t lp = sector.point(angle);\n\t label.reflow(new Box(lp.x, lp.y - labelHeight / 2, lp.x, lp.y));\n\t } else if (labelsOptions.position === INSIDE_END) {\n\t sector.radius = sector.radius - labelHeight / 2;\n\t lp = sector.point(angle);\n\t label.reflow(new Box(lp.x, lp.y - labelHeight / 2, lp.x, lp.y));\n\t } else {\n\t var x1;\n\t lp = sector.clone().expand(labelsDistance).point(angle);\n\t if (lp.x >= sector.center.x) {\n\t x1 = lp.x + labelWidth;\n\t label.orientation = RIGHT;\n\t } else {\n\t x1 = lp.x - labelWidth;\n\t label.orientation = LEFT;\n\t }\n\t label.reflow(new Box(x1, lp.y - labelHeight, lp.x, lp.y));\n\t }\n\t }\n\t },\n\n\t createVisual: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var sector = ref.sector;\n\t var options = ref.options;\n\n\t ChartElement.fn.createVisual.call(this);\n\n\t if (this.value) {\n\t if (options.visual) {\n\t var startAngle = (sector.startAngle + 180) % 360;\n\t var visual = options.visual({\n\t category: this.category,\n\t dataItem: this.dataItem,\n\t value: this.value,\n\t series: this.series,\n\t percentage: this.percentage,\n\t center: new GeometryPoint(sector.center.x, sector.center.y),\n\t radius: sector.radius,\n\t innerRadius: sector.innerRadius,\n\t startAngle: startAngle,\n\t endAngle: startAngle + sector.angle,\n\t options: options,\n\t sender: this.getSender(),\n\t createVisual: function () {\n\t var group = new Group();\n\t this$1.createSegmentVisual(group);\n\n\t return group;\n\t }\n\t });\n\n\t if (visual) {\n\t this.visual.append(visual);\n\t }\n\t } else {\n\t this.createSegmentVisual(this.visual);\n\t }\n\t }\n\t },\n\n\t createSegmentVisual: function(group) {\n\t var ref = this;\n\t var sector = ref.sector;\n\t var options = ref.options;\n\t var borderOptions = options.border || {};\n\t var border = borderOptions.width > 0 ? {\n\t stroke: {\n\t color: borderOptions.color,\n\t width: borderOptions.width,\n\t opacity: borderOptions.opacity,\n\t dashType: borderOptions.dashType\n\t }\n\t } : {};\n\t var color = options.color;\n\t var fill = {\n\t color: color,\n\t opacity: options.opacity\n\t };\n\t var visual = this.createSegment(sector, deepExtend({\n\t fill: fill,\n\t stroke: {\n\t opacity: options.opacity\n\t },\n\t zIndex: options.zIndex\n\t }, border));\n\n\t group.append(visual);\n\n\t if (hasGradientOverlay(options)) {\n\t group.append(this.createGradientOverlay(visual, {\n\t baseColor: color,\n\t fallbackFill: fill\n\t }, deepExtend({\n\t center: [ sector.center.x, sector.center.y ],\n\t innerRadius: sector.innerRadius,\n\t radius: sector.radius,\n\t userSpace: true\n\t }, options.overlay)));\n\t }\n\t },\n\n\t createSegment: function(sector, options) {\n\t if (options.singleSegment) {\n\t return new drawing.Circle(new geometry.Circle(new GeometryPoint(sector.center.x, sector.center.y), sector.radius), options);\n\t }\n\n\t return dataviz.ShapeBuilder.current.createRing(sector, options);\n\t },\n\n\t createAnimation: function() {\n\t var ref = this;\n\t var options = ref.options;\n\t var center = ref.sector.center;\n\n\t deepExtend(options, {\n\t animation: {\n\t center: [ center.x, center.y ],\n\t delay: this.animationDelay\n\t }\n\t });\n\n\t ChartElement.fn.createAnimation.call(this);\n\t },\n\n\t createHighlight: function(options) {\n\t var highlight = this.options.highlight || {};\n\t var border = highlight.border || {};\n\n\t return this.createSegment(this.sector, deepExtend({}, options, {\n\t fill: {\n\t color: highlight.color,\n\t opacity: highlight.opacity\n\t },\n\t stroke: {\n\t opacity: border.opacity,\n\t width: border.width,\n\t color: border.color\n\t }\n\t }));\n\t },\n\n\t highlightVisual: function() {\n\t return this.visual.children[0];\n\t },\n\n\t highlightVisualArgs: function() {\n\t var sector = this.sector;\n\n\t return {\n\t options: this.options,\n\t radius: sector.radius,\n\t innerRadius: sector.innerRadius,\n\t center: new GeometryPoint(sector.center.x, sector.center.y),\n\t startAngle: sector.startAngle,\n\t endAngle: sector.angle + sector.startAngle,\n\t visual: this.visual\n\t };\n\t },\n\n\t tooltipAnchor: function() {\n\t var sector = this.sector.clone().expand(TOOLTIP_OFFSET);\n\t var midAndle = sector.middle();\n\t var midPoint = sector.point(midAndle);\n\n\t return {\n\t point: midPoint,\n\t align: tooltipAlignment(midAndle + 180)\n\t };\n\t },\n\n\t formatValue: function(format) {\n\t return this.owner.formatPointValue(this, format);\n\t },\n\n\t pointData: function() {\n\t return {\n\t dataItem: this.dataItem,\n\t category: this.category,\n\t value: this.value,\n\t series: this.series,\n\t percentage: this.percentage\n\t };\n\t }\n\t});\n\n\tvar RAD_30 = round(dataviz.rad(30), DEFAULT_PRECISION);\n\tvar RAD_60 = round(dataviz.rad(60), DEFAULT_PRECISION);\n\n\tfunction tooltipAlignment(angle) {\n\t var radians = dataviz.rad(angle);\n\t var sine = round(Math.sin(radians), DEFAULT_PRECISION);\n\t var cosine = round(Math.cos(radians), DEFAULT_PRECISION);\n\n\t var horizontal;\n\t if (Math.abs(sine) > RAD_60) {\n\t horizontal = CENTER;\n\t } else if (cosine < 0) {\n\t horizontal = RIGHT;\n\t } else {\n\t horizontal = LEFT;\n\t }\n\n\t var vertical;\n\t if (Math.abs(sine) < RAD_30) {\n\t vertical = CENTER;\n\t } else if (sine < 0) {\n\t vertical = BOTTOM;\n\t } else {\n\t vertical = TOP;\n\t }\n\n\t return {\n\t horizontal: horizontal,\n\t vertical: vertical\n\t };\n\t}\n\n\tsetDefaultOptions(PieSegment, {\n\t color: WHITE,\n\t overlay: {\n\t gradient: \"roundedBevel\"\n\t },\n\t border: {\n\t width: 0.5\n\t },\n\t labels: {\n\t visible: false,\n\t distance: 35,\n\t font: datavizConstants.DEFAULT_FONT,\n\t margin: getSpacing(0.5),\n\t align: CIRCLE,\n\t zIndex: 1,\n\t position: OUTSIDE_END\n\t },\n\t animation: {\n\t type: PIE\n\t },\n\t highlight: {\n\t visible: true,\n\t border: {\n\t width: 1\n\t }\n\t },\n\t visible: true\n\t});\n\n\tdeepExtend(PieSegment.prototype, PointEventsMixin);\n\n\tvar PieChartMixin = {\n\t createLegendItem: function(value, point, options) {\n\t var legendOptions = this.options.legend || {};\n\t var labelsOptions = legendOptions.labels || {};\n\t var inactiveItems = legendOptions.inactiveItems || {};\n\t var inactiveItemsLabels = inactiveItems.labels || {};\n\n\t if (options && options.visibleInLegend !== false) {\n\t var pointVisible = options.visible !== false;\n\t var labelTemplate = pointVisible ? getTemplate(labelsOptions) :\n\t getTemplate(inactiveItemsLabels) || getTemplate(labelsOptions);\n\t var text = options.category;\n\n\t if (labelTemplate) {\n\t text = labelTemplate({\n\t text: text,\n\t series: options.series,\n\t dataItem: options.dataItem,\n\t percentage: options.percentage,\n\t value: value\n\t });\n\t }\n\n\t var itemLabelOptions, markerColor;\n\t if (pointVisible) {\n\t itemLabelOptions = {};\n\t markerColor = point.color;\n\t } else {\n\t itemLabelOptions = {\n\t color: inactiveItemsLabels.color,\n\t font: inactiveItemsLabels.font\n\t };\n\t markerColor = (inactiveItems.markers || {}).color;\n\t }\n\n\t if (hasValue(text) && text !== \"\") {\n\t this.legendItems.push({\n\t active: pointVisible,\n\t pointIndex: options.index,\n\t text: text,\n\t series: options.series,\n\t markerColor: markerColor,\n\t labels: itemLabelOptions\n\t });\n\t }\n\t }\n\t }\n\t};\n\n\tvar PIE_SECTOR_ANIM_DELAY = 70;\n\n\tvar PieChart = ChartElement.extend({\n\t init: function(plotArea, options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.plotArea = plotArea;\n\t this.chartService = plotArea.chartService;\n\t this.points = [];\n\t this.legendItems = [];\n\t this.render();\n\t },\n\n\t render: function() {\n\t this.traverseDataPoints(this.addValue.bind(this));\n\t },\n\n\t traverseDataPoints: function(callback) {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var options = ref.options;\n\t var seriesColors = ref.plotArea.options.seriesColors; if (seriesColors === void 0) { seriesColors = []; }\n\t var colorsCount = seriesColors.length;\n\t var series = options.series;\n\t var seriesCount = series.length;\n\n\t for (var seriesIx = 0; seriesIx < seriesCount; seriesIx++) {\n\t var currentSeries = series[seriesIx];\n\t var data = currentSeries.data;\n\t var ref$1 = bindSegments(currentSeries);\n\t var total = ref$1.total;\n\t var points = ref$1.points;\n\t var count = ref$1.count;\n\t var anglePerValue = 360 / total;\n\t var constantAngle = (void 0);\n\t if (!isFinite(anglePerValue)) {\n\t constantAngle = 360 / count;\n\t }\n\t var currentAngle = (void 0);\n\n\t if (defined(currentSeries.startAngle)) {\n\t currentAngle = currentSeries.startAngle;\n\t } else {\n\t currentAngle = options.startAngle;\n\t }\n\n\t if (seriesIx !== seriesCount - 1) {\n\t if (currentSeries.labels.position === OUTSIDE_END) {\n\t currentSeries.labels.position = CENTER;\n\t }\n\t }\n\n\t for (var i = 0; i < points.length; i++) {\n\t var pointData = points[i];\n\t if (!pointData) {\n\t continue;\n\t }\n\n\t var fields = pointData.fields;\n\t var value = pointData.value;\n\t var visible = pointData.visible;\n\t var angle = value !== 0 ? (constantAngle || (value * anglePerValue)) : 0;\n\t var explode = data.length !== 1 && Boolean(fields.explode);\n\n\t if (!isFunction(currentSeries.color)) {\n\t currentSeries.color = fields.color || seriesColors[i % colorsCount];\n\t }\n\n\t callback(pointData.valueFields.value, new dataviz.Ring(null, 0, 0, currentAngle, angle), {\n\t owner: this$1,\n\t category: defined(fields.category) ? fields.category : \"\",\n\t index: i,\n\t series: currentSeries,\n\t seriesIx: seriesIx,\n\t dataItem: data[i],\n\t percentage: total !== 0 ? value / total : 0,\n\t explode: explode,\n\t visibleInLegend: fields.visibleInLegend,\n\t visible: visible,\n\t zIndex: seriesCount - seriesIx,\n\t animationDelay: this$1.animationDelay(i, seriesIx, seriesCount)\n\t });\n\n\t if (visible !== false) {\n\t currentAngle += angle;\n\t }\n\t }\n\t }\n\t },\n\n\t evalSegmentOptions: function(options, value, fields) {\n\t var series = fields.series;\n\n\t evalOptions(options, {\n\t value: value,\n\t series: series,\n\t dataItem: fields.dataItem,\n\t category: fields.category,\n\t percentage: fields.percentage\n\t }, { defaults: series._defaults, excluded: [ \"data\", \"content\", \"template\", \"visual\", \"toggle\" ] });\n\t },\n\n\t addValue: function(value, sector, fields) {\n\t var segmentOptions = deepExtend({}, fields.series, { index: fields.index });\n\t this.evalSegmentOptions(segmentOptions, value, fields);\n\n\t this.createLegendItem(value, segmentOptions, fields);\n\n\t if (fields.visible === false) {\n\t return;\n\t }\n\n\t var segment = new PieSegment(value, sector, segmentOptions);\n\t $.extend(segment, fields);\n\t this.append(segment);\n\t this.points.push(segment);\n\t },\n\n\t reflow: function(targetBox) {\n\t var ref = this;\n\t var options = ref.options;\n\t var points = ref.points;\n\t var seriesConfigs = ref.seriesConfigs; if (seriesConfigs === void 0) { seriesConfigs = []; }\n\t var count = points.length;\n\t var box = targetBox.clone();\n\t var space = 5;\n\t var minWidth = Math.min(box.width(), box.height());\n\t var halfMinWidth = minWidth / 2;\n\t var defaultPadding = minWidth - minWidth * 0.85;\n\t var newBox = new Box(box.x1, box.y1, box.x1 + minWidth, box.y1 + minWidth);\n\t var newBoxCenter = newBox.center();\n\t var boxCenter = box.center();\n\t var seriesCount = options.series.length;\n\t var leftSideLabels = [];\n\t var rightSideLabels = [];\n\t var padding = valueOrDefault(options.padding, defaultPadding);\n\n\t this.targetBox = targetBox;\n\n\t padding = padding > halfMinWidth - space ? halfMinWidth - space : padding;\n\t newBox.translate(boxCenter.x - newBoxCenter.x, boxCenter.y - newBoxCenter.y);\n\n\t var radius = halfMinWidth - padding;\n\t var center = new Point(\n\t radius + newBox.x1 + padding,\n\t radius + newBox.y1 + padding\n\t );\n\n\t for (var i = 0; i < count; i++) {\n\t var segment = points[i];\n\t var sector = segment.sector;\n\t var seriesIndex = segment.seriesIx;\n\t sector.radius = radius;\n\t sector.center = center;\n\n\t if (seriesConfigs.length) {\n\t var seriesConfig = seriesConfigs[seriesIndex];\n\t sector.innerRadius = seriesConfig.innerRadius;\n\t sector.radius = seriesConfig.radius;\n\t }\n\n\t if (seriesIndex === seriesCount - 1 && segment.explode) {\n\t sector.center = sector.clone().setRadius(sector.radius * 0.15).point(sector.middle());\n\t }\n\n\t segment.reflow(newBox);\n\n\t var label = segment.label;\n\t if (label) {\n\t if (label.options.position === OUTSIDE_END) {\n\t if (seriesIndex === seriesCount - 1) {\n\t if (label.orientation === RIGHT) {\n\t rightSideLabels.push(label);\n\t } else {\n\t leftSideLabels.push(label);\n\t }\n\t }\n\t }\n\t }\n\t }\n\n\t if (leftSideLabels.length > 0) {\n\t leftSideLabels.sort(this.labelComparator(true));\n\t this.leftLabelsReflow(leftSideLabels);\n\t }\n\n\t if (rightSideLabels.length > 0) {\n\t rightSideLabels.sort(this.labelComparator(false));\n\t this.rightLabelsReflow(rightSideLabels);\n\t }\n\n\t this.box = newBox;\n\t },\n\n\t leftLabelsReflow: function(labels) {\n\t var distances = this.distanceBetweenLabels(labels);\n\n\t this.distributeLabels(distances, labels);\n\t },\n\n\t rightLabelsReflow: function(labels) {\n\t var distances = this.distanceBetweenLabels(labels);\n\n\t this.distributeLabels(distances, labels);\n\t },\n\n\t distanceBetweenLabels: function(labels) {\n\t var segment = last(this.points);\n\t var sector = segment.sector;\n\t var count = labels.length - 1;\n\t var lr = sector.radius + segment.options.labels.distance;\n\t var distances = [];\n\t var firstBox = labels[0].box;\n\t var distance = round(firstBox.y1 - (sector.center.y - lr - firstBox.height() - firstBox.height() / 2));\n\n\t distances.push(distance);\n\n\t for (var i = 0; i < count; i++) {\n\t var secondBox = labels[i + 1].box;\n\n\t firstBox = labels[i].box;\n\t distance = round(secondBox.y1 - firstBox.y2);\n\t distances.push(distance);\n\t }\n\t distance = round(sector.center.y + lr - labels[count].box.y2 - labels[count].box.height() / 2);\n\t distances.push(distance);\n\n\t return distances;\n\t },\n\n\t distributeLabels: function(distances, labels) {\n\t var this$1 = this;\n\n\t var count = distances.length;\n\t var left, right, remaining;\n\n\t for (var i = 0; i < count; i++) {\n\t remaining = -distances[i];\n\t left = right = i;\n\n\t while (remaining > 0 && (left >= 0 || right < count)) {\n\t remaining = this$1._takeDistance(distances, i, --left, remaining);\n\t remaining = this$1._takeDistance(distances, i, ++right, remaining);\n\t }\n\t }\n\n\t this.reflowLabels(distances, labels);\n\t },\n\n\t _takeDistance: function(distances, anchor, position, amount) {\n\t var result = amount;\n\t if (distances[position] > 0) {\n\t var available = Math.min(distances[position], result);\n\t result -= available;\n\t distances[position] -= available;\n\t distances[anchor] += available;\n\t }\n\n\t return result;\n\t },\n\n\t reflowLabels: function(distances, labels) {\n\t var this$1 = this;\n\n\t var segment = last(this.points);\n\t var sector = segment.sector;\n\t var labelOptions = segment.options.labels;\n\t var labelsCount = labels.length;\n\t var labelDistance = labelOptions.distance;\n\t var boxY = sector.center.y - (sector.radius + labelDistance) - labels[0].box.height();\n\t var boxX;\n\n\t distances[0] += 2;\n\t for (var i = 0; i < labelsCount; i++) {\n\t var label = labels[i];\n\t var box = label.box;\n\n\t boxY += distances[i];\n\t boxX = this$1.hAlignLabel(\n\t box.x2,\n\t sector.clone().expand(labelDistance),\n\t boxY,\n\t boxY + box.height(),\n\t label.orientation === RIGHT);\n\n\t if (label.orientation === RIGHT) {\n\t if (labelOptions.align !== CIRCLE) {\n\t boxX = sector.radius + sector.center.x + labelDistance;\n\t }\n\t label.reflow(new Box(boxX + box.width(), boxY, boxX, boxY));\n\t } else {\n\t if (labelOptions.align !== CIRCLE) {\n\t boxX = sector.center.x - sector.radius - labelDistance;\n\t }\n\t label.reflow(new Box(boxX - box.width(), boxY, boxX, boxY));\n\t }\n\n\t boxY += box.height();\n\t }\n\t },\n\n\t createVisual: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var connectors = ref.options.connectors;\n\t var points = ref.points;\n\t var count = points.length;\n\t var space = 4;\n\n\t ChartElement.fn.createVisual.call(this);\n\n\t this._connectorLines = [];\n\n\t for (var i = 0; i < count; i++) {\n\t var segment = points[i];\n\t var sector = segment.sector;\n\t var label = segment.label;\n\t var angle = sector.middle();\n\t var connectorsColor = (segment.options.connectors || {}).color || connectors.color;\n\n\t if (label) {\n\t var connectorLine = new Path({\n\t stroke: {\n\t color: connectorsColor,\n\t width: connectors.width\n\t },\n\t animation: {\n\t type: FADEIN,\n\t delay: segment.animationDelay\n\t }\n\t });\n\n\t if (label.options.position === OUTSIDE_END) {\n\t var box = label.box;\n\t var centerPoint = sector.center;\n\t var start = sector.point(angle);\n\t var middle = new Point(box.x1, box.center().y);\n\t var sr = (void 0), end = (void 0), crossing = (void 0);\n\n\t start = sector.clone().expand(connectors.padding).point(angle);\n\t connectorLine.moveTo(start.x, start.y);\n\t // TODO: Extract into a method to remove duplication\n\t if (label.orientation === RIGHT) {\n\t end = new Point(box.x1 - connectors.padding, box.center().y);\n\t crossing = intersection(centerPoint, start, middle, end);\n\t middle = new Point(end.x - space, end.y);\n\t crossing = crossing || middle;\n\t crossing.x = Math.min(crossing.x, middle.x);\n\n\t if (this$1.pointInCircle(crossing, sector.center, sector.radius + space) ||\n\t crossing.x < sector.center.x) {\n\t sr = sector.center.x + sector.radius + space;\n\t if (segment.options.labels.align !== COLUMN) {\n\t if (sr < middle.x) {\n\t connectorLine.lineTo(sr, start.y);\n\t } else {\n\t connectorLine.lineTo(start.x + space * 2, start.y);\n\t }\n\t } else {\n\t connectorLine.lineTo(sr, start.y);\n\t }\n\t connectorLine.lineTo(middle.x, end.y);\n\t } else {\n\t crossing.y = end.y;\n\t connectorLine.lineTo(crossing.x, crossing.y);\n\t }\n\t } else {\n\t end = new Point(box.x2 + connectors.padding, box.center().y);\n\t crossing = intersection(centerPoint, start, middle, end);\n\t middle = new Point(end.x + space, end.y);\n\t crossing = crossing || middle;\n\t crossing.x = Math.max(crossing.x, middle.x);\n\n\t if (this$1.pointInCircle(crossing, sector.center, sector.radius + space) ||\n\t crossing.x > sector.center.x) {\n\t sr = sector.center.x - sector.radius - space;\n\t if (segment.options.labels.align !== COLUMN) {\n\t if (sr > middle.x) {\n\t connectorLine.lineTo(sr, start.y);\n\t } else {\n\t connectorLine.lineTo(start.x - space * 2, start.y);\n\t }\n\t } else {\n\t connectorLine.lineTo(sr, start.y);\n\t }\n\t connectorLine.lineTo(middle.x, end.y);\n\t } else {\n\t crossing.y = end.y;\n\t connectorLine.lineTo(crossing.x, crossing.y);\n\t }\n\t }\n\n\t connectorLine.lineTo(end.x, end.y);\n\n\t this$1._connectorLines.push(connectorLine);\n\t this$1.visual.append(connectorLine);\n\t }\n\t }\n\t }\n\t },\n\n\t renderVisual: function() {\n\t ChartElement.fn.renderVisual.call(this);\n\n\t if (dataviz.find(this.options.series, function (options) { return options.autoFit; })) {\n\t var targetBox = this.targetBox;\n\t var pieCenter = this.box.center();\n\t var bbox = this.visual.bbox();\n\t if (!bbox) {\n\t return;\n\t }\n\n\t var bboxBottom = bbox.bottomRight();\n\n\t var scale = Math.min(\n\t (pieCenter.y - targetBox.y1) / (pieCenter.y - bbox.origin.y),\n\t (targetBox.y2 - pieCenter.y) / (bboxBottom.y - pieCenter.y),\n\t (pieCenter.x - targetBox.x1) / (pieCenter.x - bbox.origin.x),\n\t (targetBox.x2 - pieCenter.x) / (bboxBottom.x - pieCenter.x)\n\t );\n\n\t if (scale < 1) {\n\t this.visual.transform(transform().scale(scale, scale, [ pieCenter.x, pieCenter.y ]));\n\t }\n\t }\n\t },\n\n\t labelComparator: function(reverse) {\n\t var reverseValue = reverse ? -1 : 1;\n\n\t return function(a, b) {\n\t var first = (a.parent.sector.middle() + 270) % 360;\n\t var second = (b.parent.sector.middle() + 270) % 360;\n\t return (first - second) * reverseValue;\n\t };\n\t },\n\n\t hAlignLabel: function(originalX, sector, y1, y2, direction) {\n\t var radius = sector.radius;\n\t var sector_center = sector.center;\n\t var cx = sector_center.x;\n\t var cy = sector_center.y;\n\t var t = Math.min(Math.abs(cy - y1), Math.abs(cy - y2));\n\n\t if (t > radius) {\n\t return originalX;\n\t }\n\n\t return cx + Math.sqrt((radius * radius) - (t * t)) * (direction ? 1 : -1);\n\t },\n\n\t pointInCircle: function(point, center, radius) {\n\t return Math.pow(center.x - point.x, 2) + Math.pow(center.y - point.y, 2) < Math.pow(radius, 2);\n\t },\n\n\t formatPointValue: function(point, format) {\n\t return this.chartService.format.auto(format, point.value);\n\t },\n\n\t animationDelay: function(categoryIndex) {\n\t return categoryIndex * PIE_SECTOR_ANIM_DELAY;\n\t },\n\n\t stackRoot: function() {\n\t return this;\n\t }\n\t});\n\n\tfunction intersection(a1, a2, b1, b2) {\n\t var uat = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x);\n\t var ub = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);\n\n\t var result;\n\t if (ub !== 0) {\n\t var ua = (uat / ub);\n\n\t result = new Point(\n\t a1.x + ua * (a2.x - a1.x),\n\t a1.y + ua * (a2.y - a1.y)\n\t );\n\t }\n\n\t return result;\n\t}\n\n\tsetDefaultOptions(PieChart, {\n\t startAngle: 90,\n\t connectors: {\n\t width: 2,\n\t color: \"#939393\",\n\t padding: 8\n\t },\n\t inactiveItems: {\n\t markers: {},\n\t labels: {}\n\t }\n\t});\n\n\tdeepExtend(PieChart.prototype, PieChartMixin);\n\n\tPieChart.prototype.isStackRoot = true;\n\n\tvar PiePlotArea = PlotAreaBase.extend({\n\t render: function() {\n\t this.createPieChart(this.series);\n\t },\n\n\t createPieChart: function(series) {\n\t var firstSeries = series[0];\n\t var pieChart = new PieChart(this, {\n\t series: series,\n\t padding: firstSeries.padding,\n\t startAngle: firstSeries.startAngle,\n\t connectors: firstSeries.connectors,\n\t legend: this.options.legend\n\t });\n\n\t this.appendChart(pieChart);\n\t },\n\n\t appendChart: function(chart, pane) {\n\t PlotAreaBase.fn.appendChart.call(this, chart, pane);\n\t append(this.options.legend.items, chart.legendItems);\n\t }\n\t});\n\n\tvar DonutSegment = PieSegment.extend({\n\t reflowLabel: function() {\n\t var ref = this;\n\t var labelsOptions = ref.options.labels;\n\t var label = ref.label;\n\t var sector = this.sector.clone();\n\t var angle = sector.middle();\n\n\t if (label) {\n\t var labelHeight = label.box.height();\n\t if (labelsOptions.position === CENTER) {\n\t sector.radius -= (sector.radius - sector.innerRadius) / 2;\n\n\t var lp = sector.point(angle);\n\n\t label.reflow(new Box(lp.x, lp.y - labelHeight / 2, lp.x, lp.y));\n\t } else {\n\t PieSegment.fn.reflowLabel.call(this);\n\t }\n\t }\n\t },\n\n\t createSegment: function(sector, options) {\n\t return dataviz.ShapeBuilder.current.createRing(sector, options);\n\t }\n\t});\n\n\tsetDefaultOptions(DonutSegment, {\n\t overlay: {\n\t gradient: \"roundedGlass\"\n\t },\n\t labels: {\n\t position: CENTER\n\t },\n\t animation: {\n\t type: PIE\n\t }\n\t});\n\n\tdeepExtend(DonutSegment.prototype, PointEventsMixin);\n\n\tvar DONUT_SECTOR_ANIM_DELAY = 50;\n\n\tvar DonutChart = PieChart.extend({\n\t addValue: function(value, sector, fields) {\n\t var segmentOptions = deepExtend({}, fields.series, { index: fields.index });\n\t this.evalSegmentOptions(segmentOptions, value, fields);\n\n\t this.createLegendItem(value, segmentOptions, fields);\n\n\t if (!value || fields.visible === false) {\n\t return;\n\t }\n\n\t var segment = new DonutSegment(value, sector, segmentOptions);\n\n\t $.extend(segment, fields);\n\t this.append(segment);\n\t this.points.push(segment);\n\t },\n\n\t reflow: function(targetBox) {\n\t var this$1 = this;\n\n\t var options = this.options;\n\t var box = targetBox.clone();\n\t var space = 5;\n\t var minWidth = Math.min(box.width(), box.height());\n\t var halfMinWidth = minWidth / 2;\n\t var defaultPadding = minWidth - minWidth * 0.85;\n\t var series = options.series;\n\t var seriesCount = series.length;\n\n\t var padding = valueOrDefault(options.padding, defaultPadding);\n\t padding = padding > halfMinWidth - space ? halfMinWidth - space : padding;\n\n\t var totalSize = halfMinWidth - padding;\n\t var seriesWithoutSize = 0;\n\t var holeSize;\n\n\t for (var i = 0; i < seriesCount; i++) {\n\t var currentSeries = series[i];\n\t if (i === 0) {\n\t if (defined(currentSeries.holeSize)) {\n\t holeSize = currentSeries.holeSize;\n\t totalSize -= currentSeries.holeSize;\n\t }\n\t }\n\n\t if (defined(currentSeries.size)) {\n\t totalSize -= currentSeries.size;\n\t } else {\n\t seriesWithoutSize++;\n\t }\n\n\t if (defined(currentSeries.margin) && i !== seriesCount - 1) {\n\t totalSize -= currentSeries.margin;\n\t }\n\t }\n\n\t if (!defined(holeSize)) {\n\t var currentSize = (halfMinWidth - padding) / (seriesCount + 0.75);\n\t holeSize = currentSize * 0.75;\n\t totalSize -= holeSize;\n\t }\n\n\t var innerRadius = holeSize;\n\t var margin = 0;\n\t var size, radius;\n\n\t this.seriesConfigs = [];\n\n\t for (var i$1 = 0; i$1 < seriesCount; i$1++) {\n\t var currentSeries$1 = series[i$1];\n\t size = valueOrDefault(currentSeries$1.size, totalSize / seriesWithoutSize);\n\t innerRadius += margin;\n\t radius = innerRadius + size;\n\t this$1.seriesConfigs.push({ innerRadius: innerRadius, radius: radius });\n\t margin = currentSeries$1.margin || 0;\n\t innerRadius = radius;\n\t }\n\n\t PieChart.fn.reflow.call(this, targetBox);\n\t },\n\n\t animationDelay: function(categoryIndex, seriesIndex, seriesCount) {\n\t return categoryIndex * DONUT_SECTOR_ANIM_DELAY +\n\t (INITIAL_ANIMATION_DURATION * (seriesIndex + 1) / (seriesCount + 1));\n\t }\n\t});\n\n\tsetDefaultOptions(DonutChart, {\n\t startAngle: 90,\n\t connectors: {\n\t width: 2,\n\t color: \"#939393\",\n\t padding: 8\n\t }\n\t});\n\n\tvar DonutPlotArea = PiePlotArea.extend({\n\t render: function() {\n\t this.createDonutChart(this.series);\n\t },\n\n\t createDonutChart: function(series) {\n\t var firstSeries = series[0];\n\t var donutChart = new DonutChart(this, {\n\t series: series,\n\t padding: firstSeries.padding,\n\t connectors: firstSeries.connectors,\n\t legend: this.options.legend\n\t });\n\n\t this.appendChart(donutChart);\n\t }\n\t});\n\n\tvar DEFAULT_PADDING = 0.15;\n\n\tvar PolarPlotAreaBase = PlotAreaBase.extend({\n\t initFields: function() {\n\t this.valueAxisRangeTracker = new AxisGroupRangeTracker();\n\t },\n\n\t render: function() {\n\t this.addToLegend(this.series);\n\t this.createPolarAxis();\n\t this.createCharts();\n\t this.createValueAxis();\n\t },\n\n\t alignAxes: function() {\n\t var axis = this.valueAxis;\n\t var range = axis.range();\n\t var crossingValue = axis.options.reverse ? range.max : range.min;\n\t var slot = axis.getSlot(crossingValue);\n\t var center = this.polarAxis.getSlot(0).center;\n\t var axisBox = axis.box.translate(\n\t center.x - slot.x1,\n\t center.y - slot.y1\n\t );\n\n\t axis.reflow(axisBox);\n\t },\n\n\t createValueAxis: function() {\n\t var tracker = this.valueAxisRangeTracker;\n\t var defaultRange = tracker.query();\n\t var axisOptions = this.valueAxisOptions({\n\t roundToMajorUnit: false,\n\t zIndex: -1\n\t });\n\t var axisType, axisDefaultRange;\n\n\t if (axisOptions.type === LOGARITHMIC) {\n\t axisType = dataviz.RadarLogarithmicAxis;\n\t axisDefaultRange = { min: 0.1, max: 1 };\n\t } else {\n\t axisType = dataviz.RadarNumericAxis;\n\t axisDefaultRange = { min: 0, max: 1 };\n\t }\n\n\t var range = tracker.query(name) || defaultRange || axisDefaultRange;\n\n\t if (range && defaultRange) {\n\t range.min = Math.min(range.min, defaultRange.min);\n\t range.max = Math.max(range.max, defaultRange.max);\n\t }\n\n\t var valueAxis = new axisType(\n\t range.min, range.max,\n\t axisOptions,\n\t this.chartService\n\t );\n\n\t this.valueAxis = valueAxis;\n\t this.appendAxis(valueAxis);\n\t },\n\n\t reflowAxes: function() {\n\t var ref = this;\n\t var options = ref.options.plotArea;\n\t var valueAxis = ref.valueAxis;\n\t var polarAxis = ref.polarAxis;\n\t var box = ref.box;\n\t var defaultPadding = Math.min(box.width(), box.height()) * DEFAULT_PADDING;\n\t var padding = getSpacing(options.padding || {}, defaultPadding);\n\t var paddingBox = box.clone().unpad(padding);\n\t var axisBox = paddingBox.clone();\n\n\t axisBox.y2 = axisBox.y1 + Math.min(axisBox.width(), axisBox.height());\n\t axisBox.align(paddingBox, Y, CENTER);\n\n\t var valueAxisBox = axisBox.clone().shrink(0, axisBox.height() / 2);\n\n\t polarAxis.reflow(axisBox);\n\t valueAxis.reflow(valueAxisBox);\n\t var heightDiff = valueAxis.lineBox().height() - valueAxis.box.height();\n\t valueAxis.reflow(valueAxis.box.unpad({ top: heightDiff }));\n\n\t this.axisBox = axisBox;\n\t this.alignAxes(axisBox);\n\t },\n\n\t backgroundBox: function() {\n\t return this.box;\n\t },\n\n\t detachLabels: function() {}\n\t});\n\n\tvar PolarScatterChart = ScatterChart.extend({\n\t pointSlot: function(slotX, slotY) {\n\t var valueRadius = slotX.center.y - slotY.y1;\n\t var slot = Point.onCircle(slotX.center, slotX.startAngle, valueRadius);\n\n\t return new Box(slot.x, slot.y, slot.x, slot.y);\n\t }\n\t});\n\n\tsetDefaultOptions(PolarScatterChart, {\n\t clip: false\n\t});\n\n\tvar PolarLineChart = ScatterLineChart.extend({\n\n\t});\n\n\tPolarLineChart.prototype.pointSlot = PolarScatterChart.prototype.pointSlot;\n\n\tsetDefaultOptions(PolarLineChart, {\n\t clip: false\n\t});\n\n\tvar SplinePolarAreaSegment = SplineAreaSegment.extend({\n\t fillToAxes: function(fillPath) {\n\t var center = this._polarAxisCenter();\n\t fillPath.lineTo(center.x, center.y);\n\t },\n\n\t _polarAxisCenter: function() {\n\t var polarAxis = this.parent.plotArea.polarAxis;\n\t var center = polarAxis.box.center();\n\t return center;\n\t },\n\n\t strokeSegments: function() {\n\t var segments = this._strokeSegments;\n\n\t if (!segments) {\n\t var center = this._polarAxisCenter();\n\t var curveProcessor = new CurveProcessor(false);\n\t var linePoints = this.points();\n\n\t linePoints.push(center);\n\t segments = this._strokeSegments = curveProcessor.process(linePoints);\n\t segments.pop();\n\t }\n\n\t return segments;\n\t }\n\t});\n\n\tvar PolarAreaSegment = AreaSegment.extend({\n\t fillToAxes: function(fillPath) {\n\t var polarAxis = this.parent.plotArea.polarAxis;\n\t var center = polarAxis.box.center();\n\t var centerSegment = new geometry.Segment([ center.x, center.y ]);\n\n\t fillPath.segments.unshift(centerSegment);\n\t fillPath.segments.push(centerSegment);\n\t }\n\t});\n\n\tvar PolarAreaChart = PolarLineChart.extend({\n\t createSegment: function(linePoints, currentSeries, seriesIx) {\n\t var style = (currentSeries.line || {}).style;\n\t var segment;\n\n\t if (style === SMOOTH) {\n\t segment = new SplinePolarAreaSegment(linePoints, currentSeries, seriesIx);\n\t } else {\n\t segment = new PolarAreaSegment(linePoints, currentSeries, seriesIx);\n\t }\n\t return segment;\n\t },\n\n\t createMissingValue: function(value, missingValues) {\n\t var missingValue;\n\n\t if (hasValue(value.x) && missingValues !== INTERPOLATE) {\n\t missingValue = {\n\t x: value.x,\n\t y: value.y\n\t };\n\t if (missingValues === ZERO) {\n\t missingValue.y = 0;\n\t }\n\t }\n\n\t return missingValue;\n\t },\n\n\t seriesMissingValues: function(series) {\n\t return series.missingValues || ZERO;\n\t },\n\n\t _hasMissingValuesGap: function() {\n\t var this$1 = this;\n\n\t var series = this.options.series;\n\n\t for (var idx = 0; idx < series.length; idx++) {\n\t if (this$1.seriesMissingValues(series[idx]) === GAP) {\n\t return true;\n\t }\n\t }\n\t },\n\n\t sortPoints: function(points) {\n\t var this$1 = this;\n\n\t points.sort(xComparer);\n\n\t if (this._hasMissingValuesGap()) {\n\t for (var idx = 0; idx < points.length; idx++) {\n\t var point = points[idx];\n\t if (point) {\n\t var value = point.value;\n\t if (!hasValue(value.y) && this$1.seriesMissingValues(point.series) === GAP) {\n\t delete points[idx];\n\t }\n\t }\n\t }\n\t }\n\n\t return points;\n\t }\n\t});\n\n\tfunction xComparer(a, b) {\n\t return a.value.x - b.value.x;\n\t}\n\n\tvar PolarPlotArea = PolarPlotAreaBase.extend({\n\t createPolarAxis: function() {\n\t var polarAxis = new dataviz.PolarAxis(this.options.xAxis, this.chartService);\n\n\t this.polarAxis = polarAxis;\n\t this.axisX = polarAxis;\n\t this.appendAxis(polarAxis);\n\t },\n\n\t valueAxisOptions: function(defaults) {\n\t return deepExtend(defaults, {\n\t majorGridLines: { type: ARC },\n\t minorGridLines: { type: ARC }\n\t }, this.options.yAxis);\n\t },\n\n\t createValueAxis: function() {\n\t PolarPlotAreaBase.fn.createValueAxis.call(this);\n\t this.axisY = this.valueAxis;\n\t },\n\n\t appendChart: function(chart, pane) {\n\t this.valueAxisRangeTracker.update(chart.yAxisRanges);\n\n\t PlotAreaBase.prototype.appendChart.call(this, chart, pane);\n\t },\n\n\t createCharts: function() {\n\t var series = this.filterVisibleSeries(this.series);\n\t var pane = this.panes[0];\n\n\t this.createLineChart(\n\t filterSeriesByType(series, [ POLAR_LINE ]),\n\t pane\n\t );\n\n\t this.createScatterChart(\n\t filterSeriesByType(series, [ POLAR_SCATTER ]),\n\t pane\n\t );\n\n\t this.createAreaChart(\n\t filterSeriesByType(series, [ POLAR_AREA ]),\n\t pane\n\t );\n\t },\n\n\t createLineChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var lineChart = new PolarLineChart(this, { series: series });\n\n\t this.appendChart(lineChart, pane);\n\t },\n\n\t createScatterChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var scatterChart = new PolarScatterChart(this, { series: series });\n\n\t this.appendChart(scatterChart, pane);\n\t },\n\n\t createAreaChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var areaChart = new PolarAreaChart(this, { series: series });\n\n\t this.appendChart(areaChart, pane);\n\t },\n\n\t _dispatchEvent: function(chart, e, eventType) {\n\t var coords = chart._eventCoordinates(e);\n\t var point = new Point(coords.x, coords.y);\n\t var xValue = this.axisX.getValue(point);\n\t var yValue = this.axisY.getValue(point);\n\n\t if (xValue !== null && yValue !== null) {\n\t chart.trigger(eventType, {\n\t element: eventElement(e),\n\t x: xValue,\n\t y: yValue\n\t });\n\t }\n\t },\n\n\t createCrosshairs: function() {}\n\t});\n\n\tsetDefaultOptions(PolarPlotArea, {\n\t xAxis: {},\n\t yAxis: {}\n\t});\n\n\tdeepExtend(PolarPlotArea.prototype, PlotAreaEventsMixin);\n\n\tfunction groupBySeriesIx(segments) {\n\t var seriesSegments = [];\n\t for (var idx = 0; idx < segments.length; idx++) {\n\t var segment = segments[idx];\n\t seriesSegments[segment.seriesIx] = seriesSegments[segment.seriesIx] || [];\n\t seriesSegments[segment.seriesIx].push(segment);\n\t }\n\n\t return seriesSegments;\n\t}\n\n\tvar RadarLineChart = LineChart.extend({\n\t pointSlot: function(categorySlot, valueSlot) {\n\t var valueRadius = categorySlot.center.y - valueSlot.y1;\n\t var slot = Point.onCircle(categorySlot.center, categorySlot.middle(), valueRadius);\n\n\t return new Box(slot.x, slot.y, slot.x, slot.y);\n\t },\n\n\t renderSegments: function() {\n\t LineChart.fn.renderSegments.call(this);\n\n\t if (this._segments && this._segments.length > 1) {\n\t var seriesSegments = groupBySeriesIx(this._segments);\n\n\t for (var idx = 0; idx < seriesSegments.length; idx++) {\n\t var segments = seriesSegments[idx];\n\t if (segments && segments.length > 1) {\n\t var firstPoint = segments[0].linePoints[0];\n\t var lastSegment = last(segments);\n\t var lastPoint = last(lastSegment.linePoints);\n\t var isFirstDataPoint = firstPoint.categoryIx === 0;\n\t var isLastDataPoint = lastPoint.categoryIx === lastPoint.categoriesCount - 1;\n\t if (isFirstDataPoint && isLastDataPoint) {\n\t last(segments).linePoints.push(firstPoint);\n\t }\n\t }\n\t }\n\t }\n\t },\n\n\t createSegment: function(linePoints, currentSeries, seriesIx) {\n\t var style = currentSeries.style;\n\t var pointType;\n\n\t if (style === SMOOTH) {\n\t pointType = SplineSegment;\n\t } else {\n\t pointType = LineSegment;\n\t }\n\n\t var segment = new pointType(linePoints, currentSeries, seriesIx);\n\n\t if (linePoints.length === currentSeries.data.length) {\n\t segment.options.closed = true;\n\t }\n\n\t return segment;\n\t }\n\t});\n\n\tsetDefaultOptions(RadarLineChart, {\n\t clip: false,\n\t limitPoints: false\n\t});\n\n\tvar SplineRadarAreaSegment = SplineAreaSegment.extend({\n\t fillToAxes: function() {}\n\t});\n\n\tvar RadarAreaSegment = AreaSegment.extend({\n\t fillToAxes: function() {}\n\t});\n\n\tvar RadarAreaChart = RadarLineChart.extend({\n\t createSegment: function(linePoints, currentSeries, seriesIx, prevSegment) {\n\t var isStacked = this.options.isStacked;\n\t var style = (currentSeries.line || {}).style;\n\t var previousSegment;\n\t var stackPoints;\n\t var segment;\n\n\t if (isStacked && seriesIx > 0 && prevSegment) {\n\t stackPoints = prevSegment.linePoints.slice(0);\n\t previousSegment = prevSegment;\n\t }\n\n\t if (style === SMOOTH) {\n\t segment = new SplineRadarAreaSegment(linePoints, currentSeries, seriesIx, previousSegment, stackPoints);\n\t segment.options.closed = true;\n\t } else {\n\t linePoints.push(linePoints[0]);\n\t segment = new RadarAreaSegment(linePoints, currentSeries, seriesIx, previousSegment, stackPoints);\n\t }\n\n\t return segment;\n\t },\n\n\t seriesMissingValues: function(series) {\n\t return series.missingValues || ZERO;\n\t }\n\t});\n\n\tvar RadarSegment = DonutSegment.extend({\n\t init: function(value, options) {\n\t DonutSegment.fn.init.call(this, value, null, options);\n\t }\n\t});\n\n\tsetDefaultOptions(RadarSegment, {\n\t overlay: {\n\t gradient: \"none\"\n\t },\n\t labels: {\n\t distance: 10\n\t }\n\t});\n\n\tvar RadarClusterLayout = ChartElement.extend({\n\t init: function(options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.forEach = options.rtl ? forEachReverse : forEach;\n\t },\n\n\t reflow: function(sector) {\n\t var ref = this;\n\t var options = ref.options;\n\t var children = ref.children;\n\t var gap = options.gap;\n\t var spacing = options.spacing;\n\t var count = children.length;\n\t var slots = count + gap + (spacing * (count - 1));\n\t var slotAngle = sector.angle / slots;\n\t var angle = sector.startAngle + slotAngle * (gap / 2);\n\n\t this.forEach(children, function (child) {\n\t var slotSector = sector.clone();\n\t slotSector.startAngle = angle;\n\t slotSector.angle = slotAngle;\n\n\t if (child.sector) {\n\t slotSector.radius = child.sector.radius;\n\t }\n\n\t child.reflow(slotSector);\n\t child.sector = slotSector;\n\n\t angle += slotAngle + (slotAngle * spacing);\n\t });\n\t }\n\t});\n\n\tsetDefaultOptions(RadarClusterLayout, {\n\t gap: 1,\n\t spacing: 0\n\t});\n\n\tvar RadarStackLayout = ChartElement.extend({\n\t reflow: function(sector) {\n\t var ref = this;\n\t var reverse = ref.options.reverse;\n\t var children = ref.children;\n\t var childrenCount = children.length;\n\t var first = reverse ? childrenCount - 1 : 0;\n\t var step = reverse ? -1 : 1;\n\n\t this.box = new Box();\n\n\t for (var i = first; i >= 0 && i < childrenCount; i += step) {\n\t var childSector = children[i].sector;\n\t childSector.startAngle = sector.startAngle;\n\t childSector.angle = sector.angle;\n\t }\n\t }\n\t});\n\n\tvar RadarBarChart = BarChart.extend({\n\t pointType: function() {\n\t return RadarSegment;\n\t },\n\n\t clusterType: function() {\n\t return RadarClusterLayout;\n\t },\n\n\t stackType: function() {\n\t return RadarStackLayout;\n\t },\n\n\t categorySlot: function(categoryAxis, categoryIx) {\n\t return categoryAxis.getSlot(categoryIx);\n\t },\n\n\t pointSlot: function(categorySlot, valueSlot) {\n\t var slot = categorySlot.clone();\n\t var y = categorySlot.center.y;\n\n\t slot.radius = y - valueSlot.y1;\n\t slot.innerRadius = y - valueSlot.y2;\n\n\t return slot;\n\t },\n\n\t reflowPoint: function(point, pointSlot) {\n\t point.sector = pointSlot;\n\t point.reflow();\n\t },\n\n\t createAnimation: function() {\n\t this.options.animation.center = this.box.toRect().center();\n\t BarChart.fn.createAnimation.call(this);\n\t }\n\t});\n\n\tRadarBarChart.prototype.reflow = CategoricalChart.prototype.reflow;\n\n\tsetDefaultOptions(RadarBarChart, {\n\t clip: false,\n\t limitPoints: false,\n\t animation: {\n\t type: \"pie\"\n\t }\n\t});\n\n\tvar RadarPlotArea = PolarPlotAreaBase.extend({\n\t createPolarAxis: function() {\n\t var categoryAxis = new dataviz.RadarCategoryAxis(this.options.categoryAxis, this.chartService);\n\n\t this.polarAxis = categoryAxis;\n\t this.categoryAxis = categoryAxis;\n\t this.appendAxis(categoryAxis);\n\t this.aggregateCategories();\n\t this.createCategoryAxesLabels();\n\t },\n\n\t valueAxisOptions: function(defaults) {\n\t if (this._hasBarCharts) {\n\t deepExtend(defaults, {\n\t majorGridLines: { type: ARC },\n\t minorGridLines: { type: ARC }\n\t });\n\t }\n\n\t if (this._isStacked100) {\n\t deepExtend(defaults, {\n\t roundToMajorUnit: false,\n\t labels: { format: \"P0\" }\n\t });\n\t }\n\n\t return deepExtend(defaults, this.options.valueAxis);\n\t },\n\n\t aggregateCategories: function() {\n\t // No separate panes in radar charts\n\t CategoricalPlotArea.prototype.aggregateCategories.call(this, this.panes);\n\t },\n\n\t createCategoryAxesLabels: function() {\n\t CategoricalPlotArea.prototype.createCategoryAxesLabels.call(this, this.panes);\n\t },\n\n\t filterSeries: function(currentSeries) {\n\t // Not supported for radar charts\n\t return currentSeries;\n\t },\n\n\t createCharts: function() {\n\t var series = this.filterVisibleSeries(this.series);\n\t var pane = this.panes[0];\n\n\t this.createAreaChart(\n\t filterSeriesByType(series, [ RADAR_AREA ]),\n\t pane\n\t );\n\n\t this.createLineChart(\n\t filterSeriesByType(series, [ RADAR_LINE ]),\n\t pane\n\t );\n\n\t this.createBarChart(\n\t filterSeriesByType(series, [ RADAR_COLUMN ]),\n\t pane\n\t );\n\t },\n\n\t chartOptions: function(series) {\n\t var options = { series: series };\n\t var firstSeries = series[0];\n\t if (firstSeries) {\n\t var filteredSeries = this.filterVisibleSeries(series);\n\t var stack = firstSeries.stack;\n\t options.isStacked = stack && filteredSeries.length > 1;\n\t options.isStacked100 = stack && stack.type === \"100%\" && filteredSeries.length > 1;\n\n\t if (options.isStacked100) {\n\t this._isStacked100 = true;\n\t }\n\t }\n\n\t return options;\n\t },\n\n\t createAreaChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var areaChart = new RadarAreaChart(this, this.chartOptions(series));\n\t this.appendChart(areaChart, pane);\n\t },\n\n\t createLineChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var lineChart = new RadarLineChart(this, this.chartOptions(series));\n\t this.appendChart(lineChart, pane);\n\t },\n\n\t createBarChart: function(series, pane) {\n\t if (series.length === 0) {\n\t return;\n\t }\n\n\t var firstSeries = series[0];\n\t var options = this.chartOptions(series);\n\t options.gap = firstSeries.gap;\n\t options.spacing = firstSeries.spacing;\n\n\t var barChart = new RadarBarChart(this, options);\n\t this.appendChart(barChart, pane);\n\n\t this._hasBarCharts = true;\n\t },\n\n\t seriesCategoryAxis: function() {\n\t return this.categoryAxis;\n\t },\n\n\t _dispatchEvent: function(chart, e, eventType) {\n\t var coords = chart._eventCoordinates(e);\n\t var point = new Point(coords.x, coords.y);\n\t var category = this.categoryAxis.getCategory(point);\n\t var value = this.valueAxis.getValue(point);\n\n\t if (category !== null && value !== null) {\n\t chart.trigger(eventType, {\n\t element: eventElement(e),\n\t category: category,\n\t value: value\n\t });\n\t }\n\t },\n\n\t createCrosshairs: function() {}\n\t});\n\n\tdeepExtend(RadarPlotArea.prototype, PlotAreaEventsMixin, {\n\t appendChart: CategoricalPlotArea.prototype.appendChart,\n\t aggregateSeries: CategoricalPlotArea.prototype.aggregateSeries,\n\t seriesSourcePoints: CategoricalPlotArea.prototype.seriesSourcePoints\n\t});\n\n\tsetDefaultOptions(RadarPlotArea, {\n\t categoryAxis: {\n\t categories: []\n\t },\n\t valueAxis: {}\n\t});\n\n\tvar FunnelSegment = ChartElement.extend({\n\t init: function(value, options, segmentOptions) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.value = value;\n\t this.options.index = segmentOptions.index;\n\t },\n\n\t reflow: function(chartBox) {\n\t var points = this.points;\n\t var label = this.children[0];\n\n\t this.box = new Box(points[0].x, points[0].y, points[1].x, points[2].y);\n\n\t if (label) {\n\t label.reflow(new Box(chartBox.x1, points[0].y, chartBox.x2, points[2].y));\n\t }\n\t },\n\n\t createVisual: function() {\n\t var this$1 = this;\n\n\t var options = this.options;\n\t var visual;\n\n\t ChartElement.fn.createVisual.call(this);\n\n\t if (options.visual) {\n\t visual = options.visual({\n\t category: this.category,\n\t dataItem: this.dataItem,\n\t value: this.value,\n\t series: this.series,\n\t percentage: this.percentage,\n\t points: this.points,\n\t options: options,\n\t sender: this.getSender(),\n\t createVisual: function () { return this$1.createPath(); }\n\t });\n\t } else {\n\t visual = this.createPath();\n\t }\n\n\t if (visual) {\n\t this.visual.append(visual);\n\t }\n\t },\n\n\t createPath: function() {\n\t var options = this.options;\n\t var border = options.border;\n\t var path = Path.fromPoints(this.points, {\n\t fill: {\n\t color: options.color,\n\t opacity: options.opacity\n\t },\n\t stroke: {\n\t color: border.color,\n\t opacity: border.opacity,\n\t width: border.width\n\t }\n\t }).close();\n\n\t return path;\n\t },\n\n\t createHighlight: function(style) {\n\t return Path.fromPoints(this.points, style);\n\t },\n\n\t highlightVisual: function() {\n\t return this.visual.children[0];\n\t },\n\n\t highlightVisualArgs: function() {\n\t var path = Path.fromPoints(this.points).close();\n\n\t return {\n\t options: this.options,\n\t path: path\n\t };\n\t },\n\n\t tooltipAnchor: function() {\n\t var box = this.box;\n\t return {\n\t point: new Point(box.center().x, box.y1),\n\t align: {\n\t horizontal: \"center\",\n\t vertical: \"top\"\n\t }\n\t };\n\t },\n\n\t formatValue: function(format) {\n\t var point = this;\n\t return point.owner.formatPointValue(point, format);\n\t }\n\t});\n\n\tsetDefaultOptions(FunnelSegment, {\n\t color: WHITE,\n\t border: {\n\t width: 1\n\t }\n\t});\n\n\tdeepExtend(FunnelSegment.prototype, PointEventsMixin);\n\n\tvar FunnelChart = ChartElement.extend({\n\t init: function(plotArea, options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.plotArea = plotArea;\n\t this.points = [];\n\t this.labels = [];\n\t this.legendItems = [];\n\t this.render();\n\t },\n\n\t formatPointValue: function(point, format) {\n\t return this.chartService.format.auto(format,point.value);\n\t },\n\n\t render: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var options = ref.options;\n\t var seriesColors = ref.plotArea.options.seriesColors; if (seriesColors === void 0) { seriesColors = []; }\n\t var series = options.series[0];\n\t var data = series.data;\n\n\t if (!data) {\n\t return;\n\t }\n\n\t var ref$1 = bindSegments(series);\n\t var total = ref$1.total;\n\t var points = ref$1.points;\n\n\t for (var i = 0; i < points.length; i++) {\n\t var pointData = points[i];\n\n\t if (!pointData) {\n\t continue;\n\t }\n\n\t var fields = pointData.fields;\n\n\t if (!isFunction(series.color)) {\n\t series.color = fields.color || seriesColors[i % seriesColors.length];\n\t }\n\n\t fields = deepExtend({\n\t index: i,\n\t owner: this$1,\n\t series: series,\n\t dataItem: data[i],\n\t percentage: pointData.value / total\n\t }, fields, { visible: pointData.visible });\n\n\t var value = pointData.valueFields.value;\n\t var segment = this$1.createSegment(value, fields);\n\t var label = this$1.createLabel(value, fields);\n\n\t if (segment && label) {\n\t segment.append(label);\n\t }\n\t }\n\t },\n\n\t evalSegmentOptions: function(options, value, fields) {\n\t var series = fields.series;\n\n\t evalOptions(options, {\n\t value: value,\n\t series: series,\n\t dataItem: fields.dataItem,\n\t index: fields.index\n\t }, { defaults: series._defaults, excluded: [ \"data\", \"content\", \"template\", \"toggle\", \"visual\" ] });\n\t },\n\n\t createSegment: function(value, fields) {\n\t var seriesOptions = deepExtend({}, fields.series);\n\t this.evalSegmentOptions(seriesOptions, value, fields);\n\n\t this.createLegendItem(value, seriesOptions, fields);\n\n\t if (fields.visible !== false) {\n\n\t var segment = new FunnelSegment(value, seriesOptions, fields);\n\t $.extend(segment, fields);\n\n\t this.append(segment);\n\t this.points.push(segment);\n\n\t return segment;\n\t }\n\t },\n\n\t createLabel: function(value, fields) {\n\t var series = fields.series;\n\t var dataItem = fields.dataItem;\n\t var labels = deepExtend({}, this.options.labels, series.labels);\n\t var text = value;\n\n\t if (labels.visible) {\n\t var labelTemplate = getTemplate(labels);\n\t var data = {\n\t dataItem: dataItem,\n\t value: value,\n\t percentage: fields.percentage,\n\t category: fields.category,\n\t series: series\n\t };\n\t if (labelTemplate) {\n\t text = labelTemplate(data);\n\t } else if (labels.format) {\n\t text = this.plotArea.chartService.format.auto(labels.format, text);\n\t }\n\n\t if (!labels.color) {\n\t var brightnessValue = new Color(series.color).percBrightness();\n\t if (brightnessValue > 180) {\n\t labels.color = BLACK;\n\t } else {\n\t labels.color = WHITE;\n\t }\n\t if (!labels.background) {\n\t labels.background = series.color;\n\t }\n\t }\n\n\t this.evalSegmentOptions(labels, value, fields);\n\t var textBox = new TextBox(text, deepExtend({\n\t vAlign: labels.position\n\t }, labels), data);\n\n\t this.labels.push(textBox);\n\n\t return textBox;\n\t }\n\t },\n\n\t labelPadding: function() {\n\t var labels = this.labels;\n\t var padding = { left: 0, right: 0 };\n\n\t for (var i = 0; i < labels.length; i++) {\n\t var label = labels[i];\n\t var align = label.options.align;\n\t if (align !== CENTER) {\n\t var width = labels[i].box.width();\n\n\t if (align === LEFT) {\n\t padding.left = Math.max(padding.left, width);\n\t } else {\n\t padding.right = Math.max(padding.right, width);\n\t }\n\t }\n\t }\n\n\t return padding;\n\t },\n\n\t dynamicSlopeReflow: function(box, width, totalHeight) {\n\t var ref = this;\n\t var options = ref.options;\n\t var segments = ref.points;\n\t var count = segments.length;\n\t var firstSegment = segments[0];\n\t var maxSegment = firstSegment;\n\n\t for (var idx = 0; idx < segments.length; idx++) {\n\t if (segments[idx].percentage > maxSegment.percentage) {\n\t maxSegment = segments[idx];\n\t }\n\t }\n\n\t var lastUpperSide = (firstSegment.percentage / maxSegment.percentage) * width;\n\t var previousOffset = (width - lastUpperSide) / 2;\n\t var previousHeight = 0;\n\n\t for (var idx$1 = 0; idx$1 < count; idx$1++) {\n\t var percentage = segments[idx$1].percentage;\n\t var nextSegment = segments[idx$1 + 1];\n\t var nextPercentage = (nextSegment ? nextSegment.percentage : percentage);\n\t var points = segments[idx$1].points = [];\n\t var height = (options.dynamicHeight) ? (totalHeight * percentage) : (totalHeight / count);\n\t var offset = (void 0);\n\n\t if (!percentage) {\n\t offset = nextPercentage ? 0 : width / 2;\n\t } else {\n\t offset = (width - lastUpperSide * (nextPercentage / percentage)) / 2;\n\t }\n\n\t offset = limitValue(offset, 0, width);\n\n\t points.push(new GeometryPoint(box.x1 + previousOffset, box.y1 + previousHeight));\n\t points.push(new GeometryPoint(box.x1 + width - previousOffset, box.y1 + previousHeight));\n\t points.push(new GeometryPoint(box.x1 + width - offset, box.y1 + height + previousHeight));\n\t points.push(new GeometryPoint(box.x1 + offset, box.y1 + height + previousHeight));\n\n\t previousOffset = offset;\n\t previousHeight += height + options.segmentSpacing;\n\t lastUpperSide = limitValue(width - 2 * offset, 0, width);\n\t }\n\t },\n\n\t constantSlopeReflow: function(box, width, totalHeight) {\n\t var ref = this;\n\t var options = ref.options;\n\t var segments = ref.points;\n\t var count = segments.length;\n\t var decreasingWidth = options.neckRatio <= 1;\n\t var neckRatio = decreasingWidth ? options.neckRatio * width : width;\n\t var previousOffset = decreasingWidth ? 0 : (width - width / options.neckRatio) / 2;\n\t var topMostWidth = decreasingWidth ? width : width - previousOffset * 2;\n\t var finalNarrow = (topMostWidth - neckRatio) / 2;\n\t var previousHeight = 0;\n\n\t for (var idx = 0; idx < count; idx++) {\n\t var points = segments[idx].points = [];\n\t var percentage = segments[idx].percentage;\n\t var offset = (options.dynamicHeight) ? (finalNarrow * percentage) : (finalNarrow / count);\n\t var height = (options.dynamicHeight) ? (totalHeight * percentage) : (totalHeight / count);\n\n\t points.push(new GeometryPoint(box.x1 + previousOffset, box.y1 + previousHeight));\n\t points.push(new GeometryPoint(box.x1 + width - previousOffset, box.y1 + previousHeight));\n\t points.push(new GeometryPoint(box.x1 + width - previousOffset - offset, box.y1 + height + previousHeight));\n\t points.push(new GeometryPoint(box.x1 + previousOffset + offset,box.y1 + height + previousHeight));\n\t previousOffset += offset;\n\t previousHeight += height + options.segmentSpacing;\n\t }\n\t },\n\n\t reflow: function(chartBox) {\n\t var points = this.points;\n\t var count = points.length;\n\n\t if (!count) {\n\t return;\n\t }\n\n\t var options = this.options;\n\t var box = chartBox.clone().unpad(this.labelPadding());\n\t var totalHeight = box.height() - options.segmentSpacing * (count - 1);\n\t var width = box.width();\n\n\t if (options.dynamicSlope) {\n\t this.dynamicSlopeReflow(box, width, totalHeight);\n\t } else {\n\t this.constantSlopeReflow(box, width, totalHeight);\n\t }\n\n\t for (var idx = 0; idx < count; idx++) {\n\t points[idx].reflow(chartBox);\n\t }\n\t }\n\t});\n\n\tsetDefaultOptions(FunnelChart, {\n\t neckRatio: 0.3,\n\t width: 300,\n\t dynamicSlope: false,\n\t dynamicHeight: true,\n\t segmentSpacing: 0,\n\t labels: {\n\t visible: false,\n\t align: CENTER,\n\t position: CENTER,\n\t zIndex: 1\n\t }\n\t});\n\n\tdeepExtend(FunnelChart.prototype, PieChartMixin);\n\n\tvar FunnelPlotArea = PlotAreaBase.extend({\n\t render: function() {\n\t this.createFunnelChart(this.series);\n\t },\n\n\t createFunnelChart: function(series) {\n\t var firstSeries = series[0];\n\t var funnelChart = new FunnelChart(this, {\n\t series: series,\n\t legend: this.options.legend,\n\t neckRatio: firstSeries.neckRatio,\n\t dynamicHeight: firstSeries.dynamicHeight,\n\t dynamicSlope: firstSeries.dynamicSlope,\n\t segmentSpacing: firstSeries.segmentSpacing,\n\t highlight: firstSeries.highlight\n\t });\n\n\t this.appendChart(funnelChart);\n\t },\n\n\t appendChart: function(chart, pane) {\n\t PlotAreaBase.fn.appendChart.call(this, chart, pane);\n\t append(this.options.legend.items, chart.legendItems);\n\t }\n\t});\n\n\tvar COLOR = \"color\";\n\tvar FIRST = \"first\";\n\tvar FROM = \"from\";\n\tvar MAX = \"max\";\n\tvar MIN = \"min\";\n\tvar NOTE_TEXT = \"noteText\";\n\tvar SUMMARY_FIELD = \"summary\";\n\tvar TO = \"to\";\n\n\tPlotAreaFactory.current.register(CategoricalPlotArea, [\n\t BAR, COLUMN, LINE, VERTICAL_LINE, AREA, VERTICAL_AREA,\n\t CANDLESTICK, OHLC, BULLET, VERTICAL_BULLET, BOX_PLOT, VERTICAL_BOX_PLOT,\n\t RANGE_COLUMN, RANGE_BAR, WATERFALL, HORIZONTAL_WATERFALL, RANGE_AREA, VERTICAL_RANGE_AREA\n\t]);\n\n\tPlotAreaFactory.current.register(XYPlotArea, [\n\t SCATTER, SCATTER_LINE, BUBBLE\n\t]);\n\n\tPlotAreaFactory.current.register(PiePlotArea, [ PIE ]);\n\tPlotAreaFactory.current.register(DonutPlotArea, [ DONUT ]);\n\tPlotAreaFactory.current.register(FunnelPlotArea, [ FUNNEL ]);\n\n\tPlotAreaFactory.current.register(PolarPlotArea, [ POLAR_AREA, POLAR_LINE, POLAR_SCATTER ]);\n\tPlotAreaFactory.current.register(RadarPlotArea, [ RADAR_AREA, RADAR_COLUMN, RADAR_LINE ]);\n\n\tSeriesBinder.current.register(\n\t [ BAR, COLUMN, LINE, VERTICAL_LINE, AREA, VERTICAL_AREA ],\n\t [ VALUE ], [ CATEGORY, COLOR, NOTE_TEXT, ERROR_LOW_FIELD, ERROR_HIGH_FIELD ]\n\t);\n\n\tSeriesBinder.current.register(\n\t [ RANGE_COLUMN, RANGE_BAR, RANGE_AREA, VERTICAL_RANGE_AREA ],\n\t [ FROM, TO ], [ CATEGORY, COLOR, NOTE_TEXT ]\n\t);\n\n\tSeriesBinder.current.register(\n\t [ WATERFALL, HORIZONTAL_WATERFALL ],\n\t [ VALUE ], [ CATEGORY, COLOR, NOTE_TEXT, SUMMARY_FIELD ]\n\t);\n\n\tSeriesBinder.current.register([ POLAR_AREA, POLAR_LINE, POLAR_SCATTER ], [ X, Y ], [ COLOR ]);\n\tSeriesBinder.current.register([ RADAR_AREA, RADAR_COLUMN, RADAR_LINE ], [ VALUE ], [ COLOR ]);\n\n\tSeriesBinder.current.register(\n\t [ FUNNEL ],\n\t [ VALUE ], [ CATEGORY, COLOR, \"visibleInLegend\", \"visible\" ]\n\t);\n\n\tDefaultAggregates.current.register(\n\t [ BAR, COLUMN, LINE, VERTICAL_LINE, AREA, VERTICAL_AREA, WATERFALL, HORIZONTAL_WATERFALL ],\n\t { value: MAX, color: FIRST, noteText: FIRST, errorLow: MIN, errorHigh: MAX }\n\t);\n\n\tDefaultAggregates.current.register(\n\t [ RANGE_COLUMN, RANGE_BAR, RANGE_AREA, VERTICAL_RANGE_AREA ],\n\t { from: MIN, to: MAX, color: FIRST, noteText: FIRST }\n\t);\n\n\tDefaultAggregates.current.register(\n\t [ RADAR_AREA, RADAR_COLUMN, RADAR_LINE ],\n\t { value: MAX, color: FIRST }\n\t);\n\n\tSeriesBinder.current.register(\n\t [ SCATTER, SCATTER_LINE, BUBBLE ],\n\t [ X, Y ], [ COLOR, NOTE_TEXT, X_ERROR_LOW_FIELD, X_ERROR_HIGH_FIELD, Y_ERROR_LOW_FIELD, Y_ERROR_HIGH_FIELD ]\n\t);\n\n\tSeriesBinder.current.register(\n\t [ BUBBLE ], [ X, Y, \"size\" ], [ COLOR, CATEGORY, NOTE_TEXT ]\n\t);\n\n\tSeriesBinder.current.register(\n\t [ CANDLESTICK, OHLC ],\n\t [ \"open\", \"high\", \"low\", \"close\" ], [ CATEGORY, COLOR, \"downColor\", NOTE_TEXT ]\n\t);\n\n\tDefaultAggregates.current.register(\n\t [ CANDLESTICK, OHLC ],\n\t { open: MAX, high: MAX, low: MIN, close: MAX,\n\t color: FIRST, downColor: FIRST, noteText: FIRST }\n\t);\n\n\tSeriesBinder.current.register(\n\t [ BOX_PLOT, VERTICAL_BOX_PLOT ],\n\t [ \"lower\", \"q1\", \"median\", \"q3\", \"upper\", \"mean\", \"outliers\" ], [ CATEGORY, COLOR, NOTE_TEXT ]\n\t);\n\n\tDefaultAggregates.current.register(\n\t [ BOX_PLOT, VERTICAL_BOX_PLOT ],\n\t { lower: MAX, q1: MAX, median: MAX, q3: MAX, upper: MAX, mean: MAX, outliers: FIRST,\n\t color: FIRST, noteText: FIRST }\n\t);\n\n\tSeriesBinder.current.register(\n\t [ BULLET, VERTICAL_BULLET ],\n\t [ \"current\", \"target\" ], [ CATEGORY, COLOR, \"visibleInLegend\", NOTE_TEXT ]\n\t);\n\n\tDefaultAggregates.current.register(\n\t [ BULLET, VERTICAL_BULLET ],\n\t { current: MAX, target: MAX, color: FIRST, noteText: FIRST }\n\t);\n\n\tSeriesBinder.current.register(\n\t [ PIE, DONUT ],\n\t [ VALUE ], [ CATEGORY, COLOR, \"explode\", \"visibleInLegend\", \"visible\" ]\n\t);\n\n\tvar AXIS_NAMES = [ CATEGORY, VALUE, X, Y ];\n\n\tvar MOUSEMOVE = \"mousemove\";\n\tvar CONTEXTMENU = \"contextmenu\";\n\tvar MOUSELEAVE = \"mouseleave\";\n\tvar MOUSEMOVE_DELAY = 20;\n\n\tvar Chart = Class.extend({\n\t init: function(element, userOptions, themeOptions, context) {\n\t var this$1 = this;\n\t if (context === void 0) { context = {}; }\n\n\t this.observers = [];\n\t this.addObserver(context.observer);\n\t this.chartService = new services.ChartService(this, context);\n\t this.chartService.theme = themeOptions;\n\n\t this._initElement(element);\n\n\t var options = deepExtend({}, this.options, userOptions);\n\t this._originalOptions = deepExtend({}, options);\n\t this._theme = themeOptions;\n\t this._initTheme(options, themeOptions);\n\n\t this._initHandlers();\n\t this._initSurface();\n\n\t this.bindCategories();\n\t dataviz.FontLoader.preloadFonts(userOptions, function () {\n\t this$1.fontLoaded = true;\n\t if (!this$1._destroyed) {\n\t this$1.trigger('init');\n\t this$1._redraw();\n\t this$1._attachEvents();\n\t }\n\t });\n\t },\n\n\t _initElement: function(element) {\n\t this._setElementClass(element);\n\t element.style.position = \"relative\";\n\t while (element.firstChild) {\n\t element.removeChild(element.firstChild);\n\t }\n\t this.element = element;\n\t },\n\n\t _setElementClass: function(element) {\n\t dataviz.addClass(element, \"k-chart\");\n\t },\n\n\t _initTheme: function(options, themeOptions) {\n\t var seriesCopies = [];\n\t var series = options.series || [];\n\n\t for (var i = 0; i < series.length; i++) {\n\t seriesCopies.push($.extend({}, series[i]));\n\t }\n\t options.series = seriesCopies;\n\n\t resolveAxisAliases(options);\n\t this.applyDefaults(options, themeOptions);\n\n\t // Clean up default if not overriden by data attributes\n\t if (options.seriesColors === null) {\n\t delete options.seriesColors;\n\t }\n\n\t this.options = deepExtend({}, themeOptions, options);\n\t this.applySeriesColors();\n\t },\n\n\t getSize: function() {\n\t var chartArea = this.options.chartArea || {};\n\t var width = chartArea.width ? parseInt(chartArea.width, 10) : Math.floor(this.element.offsetWidth);\n\t var height = chartArea.height ? parseInt(chartArea.height, 10) : Math.floor(this.element.offsetHeight);\n\n\t return {\n\t width: width,\n\t height: height\n\t };\n\t },\n\n\t resize: function(force) {\n\t var size = this.getSize();\n\t var currentSize = this._size;\n\t var hasSize = size.width > 0 || size.height > 0;\n\n\t if (force || hasSize && (!currentSize || size.width !== currentSize.width || size.height !== currentSize.height)) {\n\t this._size = size;\n\t this._resize(size, force);\n\t this.trigger(\"resize\", size);\n\t } else if (hasSize && this._selections && dataviz.find(this._selections, function (s) { return !s.visible; })) {\n\t this._destroySelections();\n\t this._setupSelection();\n\t }\n\t },\n\n\t _resize: function() {\n\t this._noTransitionsRedraw();\n\t },\n\n\t redraw: function(paneName) {\n\t this.applyDefaults(this.options);\n\t this.applySeriesColors();\n\n\t if (paneName) {\n\t var plotArea = this._model._plotArea;\n\t var pane = plotArea.findPane(paneName);\n\t plotArea.redraw(pane);\n\t } else {\n\t this._redraw();\n\t }\n\t },\n\n\t getAxis: function(name) {\n\t return findAxisByName(name, this._plotArea.axes);\n\t },\n\n\t findAxisByName: function(name) {\n\t return this.getAxis(name);\n\t },\n\n\t findPaneByName: function(name) {\n\t var panes = this._plotArea.panes;\n\n\t for (var idx = 0; idx < panes.length; idx++) {\n\t if (panes[idx].options.name === name) {\n\t return new ChartPane(panes[idx]);\n\t }\n\t }\n\t },\n\n\t findPaneByIndex: function(idx) {\n\t var panes = this._plotArea.panes;\n\t if (panes[idx]) {\n\t return new ChartPane(panes[idx]);\n\t }\n\t },\n\n\t plotArea: function() {\n\t return new ChartPlotArea(this._plotArea);\n\t },\n\n\t toggleHighlight: function(show, filter) {\n\t var plotArea = this._plotArea;\n\t var firstSeries = (plotArea.srcSeries || plotArea.series || [])[0];\n\t var points;\n\n\t if (isFunction(filter)) {\n\t points = plotArea.filterPoints(filter);\n\t } else {\n\t var seriesName, categoryName;\n\t if (isObject(filter)) {\n\t seriesName = filter.series;\n\t categoryName = filter.category;\n\t } else {\n\t seriesName = categoryName = filter;\n\t }\n\n\t if (firstSeries.type === DONUT) {\n\t points = pointByCategoryName(plotArea.pointsBySeriesName(seriesName), categoryName);\n\t } else if (firstSeries.type === PIE || firstSeries.type === FUNNEL) {\n\t points = pointByCategoryName((plotArea.charts[0] || {}).points, categoryName);\n\t } else {\n\t points = plotArea.pointsBySeriesName(seriesName);\n\t }\n\t }\n\n\t if (points) {\n\t this.togglePointsHighlight(show, points);\n\t }\n\t },\n\n\t togglePointsHighlight: function(show, points) {\n\t var highlight = this._highlight;\n\t for (var idx = 0; idx < points.length; idx++) {\n\t highlight.togglePointHighlight(points[idx], show);\n\t }\n\t },\n\n\t showTooltip: function(filter) {\n\t var shared = this._sharedTooltip();\n\t var ref = this;\n\t var tooltip = ref._tooltip;\n\t var plotArea = ref._plotArea;\n\t var point, categoryIndex;\n\n\t if (isFunction(filter)) {\n\t point = plotArea.findPoint(filter);\n\t if (point && shared) {\n\t categoryIndex = point.categoryIx;\n\t }\n\t } else if (shared && defined(filter)) {\n\t categoryIndex = plotArea.categoryAxis.categoryIndex(filter);\n\t }\n\n\t if (shared) {\n\t if (categoryIndex >= 0) {\n\t var points = this._plotArea.pointsByCategoryIndex(categoryIndex);\n\t tooltip.showAt(points);\n\t }\n\t } else if (point) {\n\t tooltip.show(point);\n\t }\n\t },\n\n\t hideTooltip: function() {\n\t this._tooltip.hide();\n\t },\n\n\t _initSurface: function() {\n\t var surface = this.surface;\n\t var wrap = this._surfaceWrap();\n\n\t var chartArea = this.options.chartArea || {};\n\t if (chartArea.width) {\n\t dataviz.elementSize(wrap, { width: chartArea.width });\n\t }\n\t if (chartArea.height) {\n\t dataviz.elementSize(wrap, { height: chartArea.height });\n\t }\n\n\t if (!surface || surface.options.type !== this.options.renderAs) {\n\t this._destroySurface();\n\n\t this.surface = drawing.Surface.create(wrap, {\n\t type: this.options.renderAs\n\t });\n\n\t this.surface.bind(\"mouseenter\", this._surfaceMouseenterHandler);\n\t this.surface.bind(\"mouseleave\", this._surfaceMouseleaveHandler);\n\n\t } else {\n\t this.surface.clear();\n\t this.surface.resize();\n\t }\n\t },\n\n\t _surfaceWrap: function() {\n\t return this.element;\n\t },\n\n\t _redraw: function() {\n\t var model = this._getModel();\n\t this._size = {\n\t width: model.options.width,\n\t height: model.options.height\n\t };\n\n\t this._destroyView();\n\n\t this._model = model;\n\t this._plotArea = model._plotArea;\n\n\t model.renderVisual();\n\n\t if (this.options.transitions !== false) {\n\t model.traverse(function(element) {\n\t if (element.animation) {\n\t element.animation.setup();\n\t }\n\t });\n\t }\n\n\t this._initSurface();\n\t this.surface.draw(model.visual);\n\n\t if (this.options.transitions !== false) {\n\t model.traverse(function(element) {\n\t if (element.animation) {\n\t element.animation.play();\n\t }\n\t });\n\t }\n\n\t this._tooltip = this._createTooltip();\n\t this._highlight = new Highlight();\n\t this._setupSelection();\n\t this._createPannable();\n\t this._createZoomSelection();\n\t this._createMousewheelZoom();\n\n\t this.trigger(RENDER);\n\t triggerPaneRender(this._plotArea.panes);\n\n\t if (!this._navState) {\n\t this._cancelDomEvents();\n\t }\n\t },\n\n\t exportVisual: function(exportOptions) {\n\t var visual;\n\t if (exportOptions && (exportOptions.width || exportOptions.height || exportOptions.options)) {\n\t var currentOptions = this.options;\n\t var options = deepExtend({}, exportOptions.options, {\n\t chartArea: {\n\t width: exportOptions.width,\n\t height: exportOptions.height\n\t }\n\t });\n\n\t clearMissingValues(this._originalOptions, options);\n\t this.options = deepExtend({}, this._originalOptions, options);\n\t this._initTheme(this.options, this._theme);\n\t this.bindCategories();\n\n\t var model = this._getModel();\n\n\t model.renderVisual();\n\t triggerPaneRender(model._plotArea.panes);\n\n\t visual = model.visual;\n\n\t this.options = currentOptions;\n\t } else {\n\t visual = this.surface.exportVisual();\n\t }\n\n\t return visual;\n\t },\n\n\t _sharedTooltip: function() {\n\t return this._plotArea instanceof CategoricalPlotArea && this.options.tooltip && this.options.tooltip.shared;\n\t },\n\n\t _createPannable: function() {\n\t var options = this.options;\n\t if (options.pannable !== false) {\n\t this._pannable = new Pannable(this._plotArea, options.pannable);\n\t }\n\t },\n\n\t _createZoomSelection: function() {\n\t var zoomable = this.options.zoomable;\n\t var selection = (zoomable || {}).selection;\n\t if (zoomable !== false && selection !== false) {\n\t this._zoomSelection = new ZoomSelection(this, selection);\n\t }\n\t },\n\n\t _createMousewheelZoom: function() {\n\t var zoomable = this.options.zoomable;\n\t var mousewheel = (zoomable || {}).mousewheel;\n\t if (zoomable !== false && mousewheel !== false) {\n\t this._mousewheelZoom = new MousewheelZoom(this, mousewheel);\n\t }\n\t },\n\n\t _toggleDragZoomEvents: function() {\n\t var pannable = this.options.pannable;\n\t var zoomable = this.options.zoomable;\n\t var selection = (zoomable || {}).selection;\n\t var mousewheel = (zoomable || {}).mousewheel;\n\t var allowDrag = !pannable && (zoomable === false || selection === false) && !this.requiresHandlers([ DRAG_START, DRAG, DRAG_END ]);\n\t var allowZoom = (zoomable === false || mousewheel === false) && !this.requiresHandlers([ ZOOM_START, ZOOM, ZOOM_END ]);\n\t var element = this.element;\n\n\t if (this._dragZoomEnabled && allowDrag && allowZoom) {\n\t element.style.touchAction = this._touchAction || '';\n\t this._dragZoomEnabled = false;\n\t } else if (!this._dragZoomEnabled && !(allowDrag && allowZoom)) {\n\t element.style.touchAction = \"none\";\n\n\t this._dragZoomEnabled = true;\n\t }\n\n\t this._toggleDomEvents(!allowDrag, !allowZoom);\n\t },\n\n\t _toggleDomEvents: function(drag, zoom) {\n\t var domEvents = this.domEvents;\n\t if (!domEvents) {\n\t return;\n\t }\n\n\t if (domEvents.toggleDrag) {\n\t domEvents.toggleDrag(drag);\n\t }\n\n\t if (domEvents.toggleZoom) {\n\t domEvents.toggleZoom(zoom);\n\t }\n\t },\n\n\t _createTooltip: function() {\n\t var ref = this;\n\t var tooltipOptions = ref.options.tooltip;\n\t var tooltip;\n\n\t if (this._sharedTooltip()) {\n\t tooltip = this._createSharedTooltip(tooltipOptions);\n\t } else {\n\t tooltip = new Tooltip(this.chartService, tooltipOptions);\n\t }\n\n\t return tooltip;\n\t },\n\n\t _createSharedTooltip: function(options) {\n\t return new SharedTooltip(this._plotArea, options);\n\t },\n\n\t applyDefaults: function(options, themeOptions) {\n\t applyAxisDefaults(options, themeOptions);\n\t applySeriesDefaults(options, themeOptions);\n\t },\n\n\t applySeriesColors: function() {\n\t var options = this.options;\n\t var series = options.series;\n\t var colors = options.seriesColors || [];\n\n\t for (var i = 0; i < series.length; i++) {\n\t var currentSeries = series[i];\n\t var seriesColor = colors[i % colors.length];\n\t var defaults = currentSeries._defaults;\n\n\t currentSeries.color = currentSeries.color || seriesColor;\n\t if (defaults) {\n\t defaults.color = defaults.color || seriesColor;\n\t }\n\t }\n\t },\n\n\t _getModel: function() {\n\t var options = this.options;\n\t var plotArea = this._createPlotArea();\n\t var model = new dataviz.RootElement(this._modelOptions());\n\t model.chart = this;\n\t model._plotArea = plotArea;\n\n\t dataviz.Title.buildTitle(options.title, model);\n\n\t if (options.legend && options.legend.visible) {\n\t model.append(new Legend(plotArea.options.legend, this.chartService));\n\t }\n\t model.append(plotArea);\n\t model.reflow();\n\n\t return model;\n\t },\n\n\t _modelOptions: function() {\n\t var options = this.options;\n\t var size = this.getSize();\n\n\t return deepExtend({\n\t transitions: options.transitions,\n\t width: size.width || datavizConstants.DEFAULT_WIDTH,\n\t height: size.height || datavizConstants.DEFAULT_HEIGHT\n\t }, options.chartArea);\n\t },\n\n\t _createPlotArea: function(skipSeries) {\n\t var options = this.options;\n\n\t var plotArea = PlotAreaFactory.current.create(skipSeries ? [] : options.series, options, this.chartService);\n\n\t return plotArea;\n\t },\n\n\t _setupSelection: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var axes = ref._plotArea.axes;\n\t var selections = this._selections = [];\n\n\t for (var i = 0; i < axes.length; i++) {\n\t var axis = axes[i];\n\t var options = axis.options;\n\t if (axis instanceof CategoryAxis && options.select && !options.vertical) {\n\t var range = axis.range();\n\n\t var selection = new Selection(this$1, axis,\n\t deepExtend({ min: range.min, max: range.max }, options.select)\n\t );\n\n\t selections.push(selection);\n\t }\n\t }\n\t },\n\n\t _selectStart: function(e) {\n\t return this.trigger(SELECT_START, e);\n\t },\n\n\t _select: function(e) {\n\t return this.trigger(SELECT, e);\n\t },\n\n\t _selectEnd: function(e) {\n\t return this.trigger(SELECT_END, e);\n\t },\n\n\t _initHandlers: function() {\n\t this._clickHandler = this._click.bind(this);\n\t this._mousewheelHandler = this._mousewheel.bind(this);\n\t this._mouseleaveHandler = this._mouseleave.bind(this);\n\t this._surfaceMouseenterHandler = this._mouseover.bind(this);\n\t this._surfaceMouseleaveHandler = this._mouseout.bind(this);\n\n\t this._mousemove = kendo.throttle(\n\t this._mousemove.bind(this),\n\t MOUSEMOVE_DELAY\n\t );\n\t },\n\n\t addObserver: function(observer) {\n\t if (observer) {\n\t this.observers.push(observer);\n\t }\n\t },\n\n\t removeObserver: function(observer) {\n\t var index = this.observers.indexOf(observer);\n\t if (index >= 0) {\n\t this.observers.splice(index, 1);\n\t }\n\t },\n\n\t requiresHandlers: function(eventNames) {\n\t var observers = this.observers;\n\t for (var idx = 0; idx < observers.length; idx++) {\n\t if (observers[idx].requiresHandlers(eventNames)) {\n\t return true;\n\t }\n\t }\n\t },\n\n\t trigger: function(name, args) {\n\t if (args === void 0) { args = {}; }\n\n\t if (name === SHOW_TOOLTIP) {\n\t args.anchor.point = this._toDocumentCoordinates(args.anchor.point);\n\t }\n\t args.sender = this;\n\n\t var observers = this.observers;\n\t var isDefaultPrevented = false;\n\t for (var idx = 0; idx < observers.length; idx++) {\n\t if (observers[idx].trigger(name, args)) {\n\t isDefaultPrevented = true;\n\t }\n\t }\n\n\t return isDefaultPrevented;\n\t },\n\n\t _attachEvents: function() {\n\t var element = this.element;\n\n\t this._touchAction = element.style.touchAction;\n\n\t var obj;\n\t bindEvents(element, ( obj = {}, obj[ CONTEXTMENU ] = this._clickHandler, obj[ MOUSEWHEEL ] = this._mousewheelHandler, obj[ MOUSELEAVE ] = this._mouseleaveHandler, obj ));\n\n\t if (this._shouldAttachMouseMove()) {\n\t var obj$1;\n\t bindEvents(element, ( obj$1 = {}, obj$1[ MOUSEMOVE ] = this._mousemove, obj$1 ));\n\t }\n\n\t this.domEvents = services.DomEventsBuilder.create(this.element, {\n\t start: this._start.bind(this),\n\t move: this._move.bind(this),\n\t end: this._end.bind(this),\n\t tap: this._tap.bind(this),\n\t gesturestart: this._gesturestart.bind(this),\n\t gesturechange: this._gesturechange.bind(this),\n\t gestureend: this._gestureend.bind(this)\n\t });\n\n\t this._toggleDragZoomEvents();\n\t },\n\n\t _mouseleave: function(e) {\n\t if (this._hoveredPoint) {\n\t this._hoveredPoint.out(this, e);\n\t this._hoveredPoint = null;\n\t }\n\n\t if (this._plotArea.hovered) {\n\t this.trigger(PLOT_AREA_LEAVE);\n\t this._plotArea.hovered = false;\n\t }\n\t },\n\n\t _cancelDomEvents: function() {\n\t if (this.domEvents && this.domEvents.cancel) {\n\t this.domEvents.cancel();\n\t }\n\t },\n\n\t _gesturestart: function(e) {\n\t if (this._mousewheelZoom && !this._stopChartHandlers(e)) {\n\t this._gestureDistance = e.distance;\n\t this._unsetActivePoint();\n\t this.surface.suspendTracking();\n\t }\n\t },\n\n\t _gestureend: function(e) {\n\t if (this._zooming && !this._stopChartHandlers(e)) {\n\t if (this.surface) {\n\t this.surface.resumeTracking();\n\t }\n\t this._zooming = false;\n\t this.trigger(ZOOM_END, {});\n\t }\n\t },\n\n\t _gesturechange: function(e) {\n\t var mousewheelZoom = this._mousewheelZoom;\n\n\t if (mousewheelZoom && !this._stopChartHandlers(e)) {\n\t e.preventDefault();\n\t var previousGestureDistance = this._gestureDistance;\n\t var scaleDelta = -e.distance / previousGestureDistance + 1;\n\n\t if (Math.abs(scaleDelta) >= 0.1) {\n\t scaleDelta = Math.round(scaleDelta * 10);\n\n\t this._gestureDistance = e.distance;\n\t var args = { delta: scaleDelta, axisRanges: axisRanges(this._plotArea.axes), originalEvent: e };\n\t if (this._zooming || !this.trigger(ZOOM_START, args)) {\n\n\t if (!this._zooming) {\n\t this._zooming = true;\n\t }\n\n\t var ranges = args.axisRanges = mousewheelZoom.updateRanges(scaleDelta);\n\t if (ranges && !this.trigger(ZOOM, args)) {\n\t mousewheelZoom.zoom();\n\t }\n\t }\n\t }\n\t }\n\t },\n\n\t _mouseout: function(e) {\n\t if (e.element) {\n\t var element = this._drawingChartElement(e.element, e);\n\n\t if (element && element.leave) {\n\t element.leave(this, e.originalEvent);\n\t }\n\t }\n\t },\n\n\t _start: function(e) {\n\t var coords = this._eventCoordinates(e);\n\n\t if (this._stopChartHandlers(e) || !this._plotArea.backgroundContainsPoint(coords)) {\n\t return;\n\t }\n\n\t if (this.requiresHandlers([ DRAG_START, DRAG, DRAG_END ])) {\n\t this._startNavigation(e, coords, DRAG_START);\n\t }\n\n\t if (this._pannable && this._pannable.start(e)) {\n\t this.surface.suspendTracking();\n\t this._unsetActivePoint();\n\t this._suppressHover = true;\n\t this.chartService.panning = true;\n\t }\n\n\t if (this._zoomSelection) {\n\t if (this._zoomSelection.start(e)) {\n\t this.trigger(ZOOM_START, { axisRanges: axisRanges(this._plotArea.axes), originalEvent: e });\n\t }\n\t }\n\t },\n\n\t _move: function(e) {\n\t var ref = this;\n\t var state = ref._navState;\n\t var pannable = ref._pannable;\n\n\t if (this._stopChartHandlers(e)) {\n\t return;\n\t }\n\n\t if (pannable) {\n\t var ranges = pannable.move(e);\n\n\t if (ranges && !this.trigger(DRAG, { axisRanges: ranges, originalEvent: e })) {\n\t pannable.pan();\n\t }\n\t } else if (state) {\n\t var ranges$1 = {};\n\t var axes = state.axes;\n\n\t for (var i = 0; i < axes.length; i++) {\n\t var currentAxis = axes[i];\n\t var axisName = currentAxis.options.name;\n\t if (axisName) {\n\t var axis = currentAxis.options.vertical ? e.y : e.x;\n\t var delta = axis.startLocation - axis.location;\n\n\t if (delta !== 0) {\n\t ranges$1[currentAxis.options.name] = currentAxis.translateRange(delta);\n\t }\n\t }\n\t }\n\n\t state.axisRanges = ranges$1;\n\t this.trigger(DRAG, {\n\t axisRanges: ranges$1,\n\t originalEvent: e\n\t });\n\t }\n\n\t if (this._zoomSelection) {\n\t this._zoomSelection.move(e);\n\t }\n\t },\n\n\t _end: function(e) {\n\t if (this._stopChartHandlers(e)) {\n\t return;\n\t }\n\n\t var pannable = this._pannable;\n\t if (pannable && pannable.end(e)) {\n\t this.surface.resumeTracking();\n\t this.trigger(DRAG_END, {\n\t axisRanges: axisRanges(this._plotArea.axes),\n\t originalEvent: e\n\t });\n\t this._suppressHover = false;\n\t this.chartService.panning = false;\n\t } else {\n\t this._endNavigation(e, DRAG_END);\n\t }\n\n\t if (this._zoomSelection) {\n\t var ranges = this._zoomSelection.end(e);\n\t if (ranges && !this.trigger(ZOOM, { axisRanges: ranges, originalEvent: e })) {\n\t this._zoomSelection.zoom();\n\t this.trigger(ZOOM_END, { axisRanges: ranges, originalEvent: e });\n\t }\n\t }\n\t },\n\n\t _stopChartHandlers: function(e) {\n\t var selections = this._selections || [];\n\t if (!selections.length) {\n\t return false;\n\t }\n\n\t var coords = this._eventCoordinates(e);\n\t var pane = this._plotArea.paneByPoint(coords);\n\t if (pane) {\n\t for (var idx = 0; idx < selections.length; idx++) {\n\t if (selections[idx].onPane(pane)) {\n\t return true;\n\t }\n\t }\n\t }\n\t },\n\n\t _mousewheel: function(e) {\n\t var this$1 = this;\n\n\t var delta = dataviz.mousewheelDelta(e);\n\t var mousewheelZoom = this._mousewheelZoom;\n\t var coords = this._eventCoordinates(e);\n\n\t if (this._stopChartHandlers(e) || !this._plotArea.backgroundContainsPoint(coords)) {\n\t return;\n\t }\n\n\t if (mousewheelZoom) {\n\t var args = { delta: delta, axisRanges: axisRanges(this._plotArea.axes), originalEvent: e };\n\t if (this._zooming || !this.trigger(ZOOM_START, args)) {\n\t e.preventDefault();\n\n\t if (!this._zooming) {\n\t this._unsetActivePoint();\n\t this.surface.suspendTracking();\n\t this._zooming = true;\n\t }\n\n\t if (this._mwTimeout) {\n\t clearTimeout(this._mwTimeout);\n\t }\n\n\t args.axisRanges = mousewheelZoom.updateRanges(delta);\n\t if (args.axisRanges && !this.trigger(ZOOM, args)) {\n\t mousewheelZoom.zoom();\n\t }\n\n\t this._mwTimeout = setTimeout(function () {\n\t this$1.trigger(ZOOM_END, args);\n\t this$1._zooming = false;\n\t if (this$1.surface) {\n\t this$1.surface.resumeTracking();\n\t }\n\t }, MOUSEWHEEL_DELAY);\n\t }\n\t } else {\n\t var state = this._navState;\n\t if (!state) {\n\t var prevented = this._startNavigation(e, coords, ZOOM_START);\n\t if (!prevented) {\n\t state = this._navState;\n\t }\n\t }\n\n\t if (state) {\n\t var totalDelta = state.totalDelta || delta;\n\t state.totalDelta = totalDelta + delta;\n\n\t var axes = this._navState.axes;\n\t var ranges = {};\n\n\t for (var i = 0; i < axes.length; i++) {\n\t var currentAxis = axes[i];\n\t var axisName = currentAxis.options.name;\n\t if (axisName) {\n\t ranges[axisName] = currentAxis.scaleRange(-totalDelta);\n\t }\n\t }\n\n\t this.trigger(ZOOM, {\n\t delta: delta,\n\t axisRanges: ranges,\n\t originalEvent: e\n\t });\n\n\t if (this._mwTimeout) {\n\t clearTimeout(this._mwTimeout);\n\t }\n\n\t this._mwTimeout = setTimeout(function () {\n\t this$1._endNavigation(e, ZOOM_END);\n\t }, MOUSEWHEEL_DELAY);\n\t }\n\t }\n\t },\n\n\t _startNavigation: function(e, coords, chartEvent) {\n\t var plotArea = this._model._plotArea;\n\t var pane = plotArea.findPointPane(coords);\n\t var axes = plotArea.axes.slice(0);\n\n\t if (!pane) {\n\t return;\n\t }\n\n\t var ranges = axisRanges(axes);\n\n\t var prevented = this.trigger(chartEvent, {\n\t axisRanges: ranges,\n\t originalEvent: e\n\t });\n\n\t if (prevented) {\n\t this._cancelDomEvents();\n\t } else {\n\t this._suppressHover = true;\n\t this._unsetActivePoint();\n\t this._navState = {\n\t axisRanges: ranges,\n\t pane: pane,\n\t axes: axes\n\t };\n\t }\n\t },\n\n\t _endNavigation: function(e, chartEvent) {\n\t if (this._navState) {\n\t this.trigger(chartEvent, {\n\t axisRanges: this._navState.axisRanges,\n\t originalEvent: e\n\t });\n\t this._suppressHover = false;\n\t this._navState = null;\n\t }\n\t },\n\n\t _getChartElement: function(e, match) {\n\t var element = this.surface.eventTarget(e);\n\t if (element) {\n\t return this._drawingChartElement(element, e, match);\n\t }\n\t },\n\n\t _drawingChartElement: function(element, e, match) {\n\t var current = element;\n\t var chartElement;\n\t while (current && !chartElement) {\n\t chartElement = current.chartElement;\n\t current = current.parent;\n\t }\n\n\t if (chartElement) {\n\t if (chartElement.aliasFor) {\n\t chartElement = chartElement.aliasFor(e, this._eventCoordinates(e));\n\t }\n\n\t if (match) {\n\t chartElement = chartElement.closest(match);\n\t if (chartElement && chartElement.aliasFor) {\n\t chartElement = chartElement.aliasFor();\n\t }\n\t }\n\n\t return chartElement;\n\t }\n\t },\n\n\t _eventCoordinates: function(e) {\n\t var coordinates = dataviz.eventCoordinates(e);\n\t return this._toModelCoordinates(coordinates.x, coordinates.y);\n\t },\n\n\t _elementPadding: function() {\n\t if (!this._padding) {\n\t var ref = elementStyles(this.element, [ \"paddingLeft\", \"paddingTop\" ]);\n\t var paddingLeft = ref.paddingLeft;\n\t var paddingTop = ref.paddingTop;\n\t this._padding = {\n\t top: paddingTop,\n\t left: paddingLeft\n\t };\n\t }\n\n\t return this._padding;\n\t },\n\n\t _toDocumentCoordinates: function(point) {\n\t var padding = this._elementPadding();\n\t var offset = dataviz.elementOffset(this.element);\n\n\t return {\n\t left: round(point.x + padding.left + offset.left),\n\t top: round(point.y + padding.top + offset.top)\n\t };\n\t },\n\n\t _toModelCoordinates: function(clientX, clientY) {\n\t var element = this.element;\n\t var offset = dataviz.elementOffset(element);\n\t var padding = this._elementPadding();\n\n\t return new Point(\n\t clientX - offset.left - padding.left,\n\t clientY - offset.top - padding.top\n\t );\n\t },\n\n\t _tap: function(e) {\n\t var this$1 = this;\n\n\t var drawingElement = this.surface.eventTarget(e);\n\t var element = this._drawingChartElement(drawingElement, e);\n\t var sharedTooltip = this._sharedTooltip();\n\n\t if (!this._startHover(drawingElement, e) && !sharedTooltip) {\n\t this._unsetActivePoint();\n\t }\n\n\t if (sharedTooltip) {\n\t this._trackSharedTooltip(this._eventCoordinates(e), e, true);\n\t }\n\n\t this._propagateClick(element, e);\n\n\t //part of fix for hover issue on windows touch\n\t this.handlingTap = true;\n\t setTimeout(function () {\n\t this$1.handlingTap = false;\n\t }, 0);\n\t },\n\n\t _click: function(e) {\n\t var element = this._getChartElement(e);\n\t this._propagateClick(element, e);\n\t },\n\n\t _propagateClick: function(element, e) {\n\t var this$1 = this;\n\n\t var current = element;\n\t while (current) {\n\t if (current.click) {\n\t current.click(this$1, e);\n\t }\n\n\t current = current.parent;\n\t }\n\t },\n\n\t _startHover: function(element, e) {\n\t if (this._suppressHover) {\n\t return false;\n\t }\n\n\t var point = this._drawingChartElement(element, e, function(element) {\n\t return (element.hover || element.over) && !(element instanceof PlotAreaBase);\n\t });\n\n\t var activePoint = this._activePoint;\n\t var hoveredPoint = this._hoveredPoint;\n\n\t if (hoveredPoint && hoveredPoint !== point) {\n\t hoveredPoint.out(this, e);\n\t this._hoveredPoint = null;\n\t }\n\n\t if (point && hoveredPoint !== point && point.over) {\n\t this._hoveredPoint = point;\n\t point.over(this, e);\n\t }\n\n\t if (point && activePoint !== point && point.hover) {\n\t this._activePoint = point;\n\n\t if (!this._sharedTooltip() && !point.hover(this, e)) {\n\t var tooltipOptions = deepExtend({}, this.options.tooltip, point.options.tooltip);\n\t if (tooltipOptions.visible) {\n\t this._tooltip.show(point);\n\t }\n\n\t this._highlight.show(point);\n\t }\n\t }\n\n\t return point;\n\t },\n\n\t _mouseover: function(e) {\n\t var point = this._startHover(e.element, e.originalEvent);\n\n\t if (point && point.tooltipTracking && !this._mouseMoveTrackHandler && !this._sharedTooltip()) {\n\t this._mouseMoveTrackHandler = this._mouseMoveTracking.bind(this);\n\t var obj;\n\t bindEvents(document, ( obj = {}, obj[ MOUSEMOVE ] = this._mouseMoveTrackHandler, obj ));\n\t }\n\t },\n\n\t _mouseMoveTracking: function(e) {\n\t var ref = this;\n\t var options = ref.options;\n\t var tooltip = ref._tooltip;\n\t var highlight = ref._highlight;\n\t var point = ref._activePoint;\n\t var coords = this._eventCoordinates(e);\n\n\t if (this._plotArea.box.containsPoint(coords)) {\n\t if (point && point.tooltipTracking && point.series && point.parent.getNearestPoint) {\n\t var seriesPoint = point.parent.getNearestPoint(coords.x, coords.y, point.seriesIx);\n\t if (seriesPoint && seriesPoint !== point) {\n\t this._activePoint = seriesPoint;\n\n\t if (!seriesPoint.hover(this, e)) {\n\t var tooltipOptions = deepExtend({}, options.tooltip, seriesPoint.options.tooltip);\n\t if (tooltipOptions.visible) {\n\t tooltip.show(seriesPoint);\n\t }\n\n\t highlight.show(seriesPoint);\n\t }\n\t }\n\t }\n\t } else {\n\t var obj;\n\t unbindEvents(document, ( obj = {}, obj[ MOUSEMOVE ] = this._mouseMoveTrackHandler, obj ));\n\t this._unsetActivePoint();\n\t this._mouseMoveTrackHandler = null;\n\t }\n\t },\n\n\t _mousemove: function(e) {\n\t var coords = this._eventCoordinates(e);\n\t var plotArea = this._plotArea;\n\n\t this._trackCrosshairs(coords);\n\n\t if (plotArea.hover) {\n\t var overPlotArea = plotArea.backgroundContainsPoint(coords);\n\t if (overPlotArea) {\n\t plotArea.hovered = true;\n\t this._plotArea.hover(this, e);\n\t } else if (plotArea.hovered && !overPlotArea) {\n\t this.trigger(PLOT_AREA_LEAVE);\n\t plotArea.hovered = false;\n\t }\n\t }\n\n\t if (this._sharedTooltip()) {\n\t this._trackSharedTooltip(coords, e);\n\t }\n\t },\n\n\t _trackCrosshairs: function(coords) {\n\t var crosshairs = this._plotArea.crosshairs;\n\n\t for (var i = 0; i < crosshairs.length; i++) {\n\t var current = crosshairs[i];\n\n\t if (current.box.containsPoint(coords)) {\n\t current.showAt(coords);\n\t } else {\n\t current.hide();\n\t }\n\t }\n\t },\n\n\t _trackSharedTooltip: function(coords, e, toggle) {\n\t if (this._suppressHover) {\n\t return;\n\t }\n\n\t var ref = this;\n\t var tooltipOptions = ref.options.tooltip;\n\t var plotArea = ref._plotArea;\n\t var categoryAxis = ref._plotArea.categoryAxis;\n\t var tooltip = ref._tooltip;\n\t var highlight = ref._highlight;\n\n\t if (plotArea.backgroundContainsPoint(coords)) {\n\t var index = categoryAxis.pointCategoryIndex(coords);\n\t if (index !== this._tooltipCategoryIx || (!this._sharedHighlight && toggle)) {\n\t var points = plotArea.pointsByCategoryIndex(index);\n\t var pointArgs = points.map(function(point) {\n\t return point.eventArgs(e);\n\t });\n\t var hoverArgs = pointArgs[0] || {};\n\t hoverArgs.categoryPoints = pointArgs;\n\n\t if (points.length > 0 && !this.trigger(SERIES_HOVER, hoverArgs)) {\n\t if (tooltipOptions.visible) {\n\t tooltip.showAt(points, coords);\n\t }\n\n\t highlight.show(points);\n\n\t this._sharedHighlight = true;\n\t } else {\n\t tooltip.hide();\n\t }\n\n\t this._tooltipCategoryIx = index;\n\t } else if (toggle && this._sharedHighlight) {\n\t highlight.hide();\n\t tooltip.hide();\n\t this._sharedHighlight = false;\n\t }\n\t } else if (this._sharedHighlight) {\n\t highlight.hide();\n\t tooltip.hide();\n\t this._tooltipCategoryIx = null;\n\t this._sharedHighlight = false;\n\t }\n\t },\n\n\t hideElements: function() {\n\t var plotArea = this._plotArea;\n\t this._mousemove.cancel();\n\n\t plotArea.hideCrosshairs();\n\n\t this._unsetActivePoint();\n\t },\n\n\t _unsetActivePoint: function() {\n\t var ref = this;\n\t var tooltip = ref._tooltip;\n\t var highlight = ref._highlight;\n\n\t this._activePoint = null;\n\t this._hoveredPoint = null;\n\n\t if (tooltip) {\n\t tooltip.hide();\n\t }\n\n\t this._tooltipCategoryIx = null;\n\t this._sharedHighlight = false;\n\n\t if (highlight) {\n\t highlight.hide();\n\t }\n\t },\n\n\t _deferRedraw: function() {\n\t this._redraw();\n\t },\n\n\t _clearRedrawTimeout: function() {\n\t if (this._redrawTimeout) {\n\t clearInterval(this._redrawTimeout);\n\t this._redrawTimeout = null;\n\t }\n\t },\n\n\t bindCategories: function() {\n\t var this$1 = this;\n\n\t var options = this.options;\n\t var definitions = [].concat(options.categoryAxis);\n\n\t for (var axisIx = 0; axisIx < definitions.length; axisIx++) {\n\t var axis = definitions[axisIx];\n\t if (axis.autoBind !== false) {\n\t this$1.bindCategoryAxisFromSeries(axis, axisIx);\n\t }\n\t }\n\t },\n\n\t bindCategoryAxisFromSeries: function(axis, axisIx) {\n\t var this$1 = this;\n\n\t var series = this.options.series;\n\t var seriesLength = series.length;\n\t var uniqueCategories = new dataviz.HashMap();//perf improvement in case type category with dates\n\t var items = [];\n\t var bindable = false;\n\t var dateAxis;\n\n\t for (var seriesIx = 0; seriesIx < seriesLength; seriesIx++) {\n\t var s = series[seriesIx];\n\t var onAxis = s.categoryAxis === axis.name || (!s.categoryAxis && axisIx === 0);\n\t var data = s.data;\n\t var dataLength = data.length;\n\t var bind = s.categoryField && onAxis;\n\t bindable = bind || bindable;\n\n\t if (bind && dataLength > 0) {\n\t dateAxis = isDateAxis(axis, getField(s.categoryField, data[0]));\n\n\t var getFn = dateAxis ? getDateField : getField;\n\n\t for (var dataIx = 0; dataIx < dataLength; dataIx++) {\n\t var dataRow = data[dataIx];\n\t var category = getFn(s.categoryField, dataRow, this$1.chartService.intl);\n\n\t if (dateAxis || !uniqueCategories.get(category)) {\n\t items.push([ category, dataRow ]);\n\n\t if (!dateAxis) {\n\t uniqueCategories.set(category, true);\n\t }\n\t }\n\t }\n\t }\n\t }\n\n\t if (items.length > 0) {\n\t if (dateAxis) {\n\t items = uniqueDates(items, function(a, b) {\n\t return dataviz.dateComparer(a[0], b[0]);\n\t });\n\t }\n\n\t var result = transpose(items);\n\t axis.categories = result[0];\n\t } else if (bindable) {\n\t axis.categories = [];\n\t }\n\t },\n\n\t _isBindable: function(series) {\n\t var valueFields = SeriesBinder.current.valueFields(series);\n\t var result = true;\n\n\t for (var i = 0; i < valueFields.length; i++) {\n\t var field = valueFields[i];\n\t if (field === VALUE) {\n\t field = \"field\";\n\t } else {\n\t field = field + \"Field\";\n\t }\n\n\t if (!defined(series[field])) {\n\t result = false;\n\t break;\n\t }\n\t }\n\n\t return result;\n\t },\n\n\t _noTransitionsRedraw: function() {\n\t var options = this.options;\n\t var transitionsState;\n\n\t if (options.transitions !== false) {\n\t options.transitions = false;\n\t transitionsState = true;\n\t }\n\n\t this._redraw();\n\n\t if (transitionsState) {\n\t options.transitions = true;\n\t }\n\t },\n\n\t _legendItemHover: function(seriesIndex, pointIndex) {\n\t var ref = this;\n\t var plotArea = ref._plotArea;\n\t var highlight = ref._highlight;\n\t var currentSeries = (plotArea.srcSeries || plotArea.series)[seriesIndex];\n\t var items;\n\n\t if (inArray(currentSeries.type, [ PIE, DONUT, FUNNEL ])) {\n\t items = plotArea.findPoint(function(point) {\n\t return point.series.index === seriesIndex && point.index === pointIndex;\n\t });\n\t } else {\n\t items = plotArea.pointsBySeriesIndex(seriesIndex);\n\t }\n\n\t highlight.show(items);\n\t },\n\n\t _shouldAttachMouseMove: function() {\n\t return this._plotArea.crosshairs.length || (this._tooltip && this._sharedTooltip()) || this.requiresHandlers([ PLOT_AREA_HOVER, PLOT_AREA_LEAVE ]);\n\t },\n\n\t updateMouseMoveHandler: function() {\n\t var obj;\n\t unbindEvents(this.element, ( obj = {}, obj[ MOUSEMOVE ] = this._mousemove, obj ));\n\n\t if (this._shouldAttachMouseMove()) {\n\t var obj$1;\n\t bindEvents(this.element, ( obj$1 = {}, obj$1[ MOUSEMOVE ] = this._mousemove, obj$1 ));\n\t }\n\t },\n\n\t applyOptions: function(options, theme) {\n\t clearMissingValues(this._originalOptions, options);\n\t this._originalOptions = deepExtend(this._originalOptions, options);\n\t this.options = deepExtend({}, this._originalOptions);\n\n\t if (theme) {\n\t this._theme = theme;\n\t this.chartService.theme = theme;\n\t }\n\t this._initTheme(this.options, this._theme);\n\n\t this._toggleDragZoomEvents();\n\t },\n\n\t setOptions: function(options, theme) {\n\t this.applyOptions(options, theme);\n\t this.bindCategories();\n\t this.redraw();\n\t this.updateMouseMoveHandler();\n\t },\n\n\t setDirection: function(rtl) {\n\t this.chartService.rtl = Boolean(rtl);\n\t if (this.surface && this.surface.type === 'svg') {\n\t this._destroySurface();\n\t }\n\t },\n\n\t setIntlService: function(intl) {\n\t this.chartService.intl = intl;\n\t },\n\n\t noTransitionsRedraw: function() {\n\t this._noTransitionsRedraw();\n\t },\n\n\t destroy: function() {\n\t this._destroyed = true;\n\n\t var obj;\n\t unbindEvents(this.element, ( obj = {}, obj[ CONTEXTMENU ] = this._clickHandler, obj[ MOUSEWHEEL ] = this._mousewheelHandler, obj[ MOUSEMOVE ] = this._mousemove, obj[ MOUSELEAVE ] = this._mouseleaveHandler, obj ));\n\n\t if (this.domEvents) {\n\t this.domEvents.destroy();\n\t delete this.domEvents;\n\t }\n\n\t if (this._mouseMoveTrackHandler) {\n\t var obj$1;\n\t unbindEvents(document, ( obj$1 = {}, obj$1[ MOUSEMOVE ] = this._mouseMoveTrackHandler, obj$1 ));\n\t }\n\n\t this._destroyView();\n\n\t this._destroySurface();\n\n\t this._clearRedrawTimeout();\n\t },\n\n\t _destroySurface: function() {\n\t var surface = this.surface;\n\t if (surface) {\n\t surface.unbind(\"mouseenter\", this._surfaceMouseenterHandler);\n\t surface.unbind(\"mouseleave\", this._surfaceMouseleaveHandler);\n\t surface.destroy();\n\n\t this.surface = null;\n\t }\n\t },\n\n\t _destroySelections: function() {\n\t var selections = this._selections;\n\n\t if (selections) {\n\t while (selections.length > 0) {\n\t selections.shift().destroy();\n\t }\n\t }\n\t },\n\n\t _destroyView: function() {\n\t var model = this._model;\n\n\t if (model) {\n\t model.destroy();\n\t this._model = null;\n\t }\n\n\t this._unsetActivePoint();\n\n\t this._destroySelections();\n\n\t if (this._tooltip) {\n\t this._tooltip.destroy();\n\t }\n\n\t if (this._highlight) {\n\t this._highlight.destroy();\n\t }\n\n\t if (this._zoomSelection) {\n\t this._zoomSelection.destroy();\n\t delete this._zoomSelection;\n\t }\n\n\t if (this._pannable) {\n\t this._pannable.destroy();\n\t delete this._pannable;\n\t }\n\n\t if (this._mousewheelZoom) {\n\t this._mousewheelZoom.destroy();\n\t delete this._mousewheelZoom;\n\t }\n\t }\n\t});\n\n\tfunction resolveAxisAliases(options) {\n\t var aliases = AXIS_NAMES;\n\n\t for (var idx = 0; idx < aliases.length; idx++) {\n\t var alias = aliases[idx] + \"Axes\";\n\t if (options[alias]) {\n\t options[aliases[idx] + \"Axis\"] = options[alias];\n\t delete options[alias];\n\t }\n\t }\n\t}\n\n\tfunction pointByCategoryName(points, name) {\n\t if (points) {\n\t for (var idx = 0; idx < points.length; idx++) {\n\t if (points[idx].category === name) {\n\t return [ points[idx] ];\n\t }\n\t }\n\t }\n\t}\n\n\tfunction applyAxisDefaults(options, themeOptions) {\n\t var themeAxisDefaults = ((themeOptions || {}).axisDefaults) || {};\n\t var axisName, axisDefaults, axes;\n\n\t function mapAxisOptions(axisOptions) {\n\t var axisColor = (axisOptions || {}).color || axisDefaults.color;\n\t var result = deepExtend({},\n\t themeAxisDefaults,\n\t themeAxisDefaults[axisName],\n\t axisDefaults,\n\t axisDefaults[axisName], {\n\t line: { color: axisColor },\n\t labels: { color: axisColor },\n\t title: { color: axisColor }\n\t },\n\t axisOptions\n\t );\n\n\t delete result[axisName];\n\n\t return result;\n\t }\n\n\t for (var idx = 0; idx < AXIS_NAMES.length; idx++) {\n\t axisName = AXIS_NAMES[idx] + \"Axis\";\n\t axisDefaults = options.axisDefaults || {};\n\t axes = [].concat(options[axisName]);\n\n\t axes = axes.map(mapAxisOptions);\n\n\t options[axisName] = axes.length > 1 ? axes : axes[0];\n\t }\n\t}\n\n\tfunction applySeriesDefaults(options, themeOptions) {\n\t var series = options.series;\n\t var seriesLength = series.length;\n\t var seriesDefaults = options.seriesDefaults;\n\t var commonDefaults = deepExtend({}, options.seriesDefaults);\n\t var themeSeriesDefaults = themeOptions ? deepExtend({}, themeOptions.seriesDefaults) : {};\n\t var commonThemeDefaults = deepExtend({}, themeSeriesDefaults);\n\n\t cleanupNestedSeriesDefaults(commonDefaults);\n\t cleanupNestedSeriesDefaults(commonThemeDefaults);\n\n\t for (var i = 0; i < seriesLength; i++) {\n\t var seriesType = series[i].type || options.seriesDefaults.type;\n\n\t var baseOptions = deepExtend(\n\t { data: [] },\n\t commonThemeDefaults,\n\t themeSeriesDefaults[seriesType],\n\t { tooltip: options.tooltip },\n\t commonDefaults,\n\t seriesDefaults[seriesType]\n\t );\n\n\t series[i]._defaults = baseOptions;\n\t series[i] = deepExtend({}, baseOptions, series[i]);\n\t series[i].data = series[i].data || [];\n\t }\n\t}\n\n\tfunction cleanupNestedSeriesDefaults(seriesDefaults) {\n\t delete seriesDefaults.bar;\n\t delete seriesDefaults.column;\n\t delete seriesDefaults.rangeColumn;\n\t delete seriesDefaults.line;\n\t delete seriesDefaults.verticalLine;\n\t delete seriesDefaults.pie;\n\t delete seriesDefaults.donut;\n\t delete seriesDefaults.area;\n\t delete seriesDefaults.verticalArea;\n\t delete seriesDefaults.scatter;\n\t delete seriesDefaults.scatterLine;\n\t delete seriesDefaults.bubble;\n\t delete seriesDefaults.candlestick;\n\t delete seriesDefaults.ohlc;\n\t delete seriesDefaults.boxPlot;\n\t delete seriesDefaults.bullet;\n\t delete seriesDefaults.verticalBullet;\n\t delete seriesDefaults.polarArea;\n\t delete seriesDefaults.polarLine;\n\t delete seriesDefaults.radarArea;\n\t delete seriesDefaults.radarLine;\n\t delete seriesDefaults.waterfall;\n\t}\n\n\tfunction axisRanges(axes) {\n\t var ranges = {};\n\n\t for (var i = 0; i < axes.length; i++) {\n\t var axis = axes[i];\n\t var axisName = axis.options.name;\n\t if (axisName) {\n\t ranges[axisName] = axis.range();\n\t }\n\t }\n\n\t return ranges;\n\t}\n\n\tfunction sortDates(dates, comparer) {\n\t if (comparer === void 0) { comparer = dataviz.dateComparer; }\n\n\t for (var i = 1, length = dates.length; i < length; i++) {\n\t if (comparer(dates[i], dates[i - 1]) < 0) {\n\t dates.sort(comparer);\n\t break;\n\t }\n\t }\n\n\t return dates;\n\t}\n\n\tfunction uniqueDates(srcDates, comparer) {\n\t if (comparer === void 0) { comparer = dataviz.dateComparer; }\n\n\t var dates = sortDates(srcDates, comparer);\n\t var length = dates.length;\n\t var result = length > 0 ? [ dates[0] ] : [];\n\n\t for (var i = 1; i < length; i++) {\n\t if (comparer(dates[i], last(result)) !== 0) {\n\t result.push(dates[i]);\n\t }\n\t }\n\n\t return result;\n\t}\n\n\tfunction transpose(rows) {\n\t var rowCount = rows.length;\n\t var result = [];\n\n\t for (var rowIx = 0; rowIx < rowCount; rowIx++) {\n\t var row = rows[rowIx];\n\t var colCount = row.length;\n\n\t for (var colIx = 0; colIx < colCount; colIx++) {\n\t result[colIx] = result[colIx] || [];\n\t result[colIx].push(row[colIx]);\n\t }\n\t }\n\n\t return result;\n\t}\n\n\tvar DATA_FIELDS = [ 'data', 'categories' ];\n\n\tfunction clearMissingValues(originalOptions, options) {\n\t for (var field in options) {\n\t if (!inArray(field, DATA_FIELDS) && options.hasOwnProperty(field)) {\n\t var fieldValue = options[field];\n\t var originalValue = originalOptions[field];\n\t if (defined(originalValue)) {\n\t var nullValue = fieldValue === null;\n\t if ((nullValue || !defined(fieldValue))) {\n\t delete originalOptions[field];\n\t if (nullValue) {\n\t delete options[field];\n\t }\n\t } else if (originalValue && isObject(fieldValue)) {\n\t if (isObject(originalValue)) {\n\t clearMissingValues(originalValue, fieldValue);\n\t }\n\t }\n\t }\n\t }\n\t }\n\t}\n\n\tfunction triggerPaneRender(panes) {\n\t for (var idx = 0; idx < panes.length; idx++) {\n\t panes[idx].notifyRender();\n\t }\n\t}\n\n\tsetDefaultOptions(Chart, {\n\t renderAs: \"\",\n\t chartArea: {},\n\t legend: {\n\t visible: true,\n\t labels: {}\n\t },\n\t categoryAxis: {},\n\t seriesDefaults: {\n\t type: COLUMN,\n\t data: [],\n\t highlight: {\n\t visible: true\n\t },\n\t labels: {},\n\t negativeValues: {\n\t visible: false\n\t }\n\t },\n\t series: [],\n\t seriesColors: null,\n\t tooltip: {\n\t visible: false\n\t },\n\t transitions: true,\n\t valueAxis: {},\n\t plotArea: {},\n\t title: {},\n\t xAxis: {},\n\t yAxis: {},\n\t panes: [ {} ],\n\t pannable: false,\n\t zoomable: false\n\t});\n\n\tkendo.deepExtend(kendo.dataviz, {\n\t constants: constants,\n\t Aggregates: Aggregates,\n\t AreaChart: AreaChart,\n\t AreaSegment: AreaSegment,\n\t AxisGroupRangeTracker: AxisGroupRangeTracker,\n\t Bar: Bar,\n\t BarChart: BarChart,\n\t BarLabel: BarLabel,\n\t BoxPlotChart: BoxPlotChart,\n\t BoxPlot: BoxPlot,\n\t BubbleChart: BubbleChart,\n\t Bullet: Bullet,\n\t BulletChart: BulletChart,\n\t CandlestickChart: CandlestickChart,\n\t Candlestick: Candlestick,\n\t CategoricalChart: CategoricalChart,\n\t CategoricalErrorBar: CategoricalErrorBar,\n\t CategoricalPlotArea: CategoricalPlotArea,\n\t Chart: Chart,\n\t ChartContainer: ChartContainer,\n\t ClipAnimation: ClipAnimation,\n\t ClusterLayout: ClusterLayout,\n\t Crosshair: Crosshair,\n\t CrosshairTooltip: CrosshairTooltip,\n\t DefaultAggregates: DefaultAggregates,\n\t DonutChart: DonutChart,\n\t DonutPlotArea: DonutPlotArea,\n\t DonutSegment: DonutSegment,\n\t ErrorBarBase: ErrorBarBase,\n\t ErrorRangeCalculator: ErrorRangeCalculator,\n\t Highlight: Highlight,\n\t SharedTooltip: SharedTooltip,\n\t Legend: Legend,\n\t LegendItem: LegendItem,\n\t LegendLayout: LegendLayout,\n\t LineChart: LineChart,\n\t LinePoint: LinePoint,\n\t LineSegment: LineSegment,\n\t Pane: Pane,\n\t PieAnimation: PieAnimation,\n\t PieChart: PieChart,\n\t PieChartMixin: PieChartMixin,\n\t PiePlotArea: PiePlotArea,\n\t PieSegment: PieSegment,\n\t PlotAreaBase: PlotAreaBase,\n\t PlotAreaEventsMixin: PlotAreaEventsMixin,\n\t PlotAreaFactory: PlotAreaFactory,\n\t PointEventsMixin: PointEventsMixin,\n\t RangeBar: RangeBar,\n\t RangeBarChart: RangeBarChart,\n\t RangeAreaPoint: RangeAreaPoint,\n\t RangeAreaChart: RangeAreaChart,\n\t ScatterChart: ScatterChart,\n\t ScatterErrorBar: ScatterErrorBar,\n\t ScatterLineChart: ScatterLineChart,\n\t Selection: Selection,\n\t SeriesAggregator: SeriesAggregator,\n\t SeriesBinder: SeriesBinder,\n\t SplineSegment: SplineSegment,\n\t SplineAreaSegment: SplineAreaSegment,\n\t StackWrap: StackWrap,\n\t Tooltip: Tooltip,\n\t OHLCChart: OHLCChart,\n\t OHLCPoint: OHLCPoint,\n\t WaterfallChart: WaterfallChart,\n\t WaterfallSegment: WaterfallSegment,\n\t XYPlotArea: XYPlotArea,\n\t MousewheelZoom: MousewheelZoom,\n\t ZoomSelection: ZoomSelection,\n\t Pannable: Pannable,\n\t ChartAxis: ChartAxis,\n\t ChartPane: ChartPane,\n\t ChartPlotArea: ChartPlotArea,\n\t findAxisByName: findAxisByName,\n\t anyHasZIndex: anyHasZIndex,\n\t appendIfNotNull: appendIfNotNull,\n\t areNumbers: areNumbers,\n\t bindSegments: bindSegments,\n\t categoriesCount: categoriesCount,\n\t countNumbers: countNumbers,\n\t equalsIgnoreCase: equalsIgnoreCase,\n\t evalOptions: evalOptions,\n\t filterSeriesByType: filterSeriesByType,\n\t getDateField: getDateField,\n\t getField: getField,\n\t hasGradientOverlay: hasGradientOverlay,\n\t hasValue: hasValue,\n\t isDateAxis: isDateAxis,\n\t segmentVisible: segmentVisible,\n\t singleItemOrArray: singleItemOrArray,\n\t createOutOfRangePoints: createOutOfRangePoints\n\t});\n\n\t})(window.kendo.jQuery);\n\n\t}, __webpack_require__(3));\n\n/***/ }),\n\n/***/ 863:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.core\");\n\n/***/ }),\n\n/***/ 864:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.color\");\n\n/***/ })\n\n/******/ });","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ 0:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tmodule.exports = __webpack_require__(865);\n\n\n/***/ }),\n\n/***/ 3:\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n\n/***/ 865:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(f, define){\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n\t __webpack_require__(866)\n\t ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t})(function(){\n\n\t(function ($) {\n\n\t var dataviz = kendo.dataviz;\n\t var services = dataviz.services;\n\t var draw = kendo.drawing;\n\n\t dataviz.SASS_THEMES = [\"sass\", \"default-v2\", \"bootstrap-v4\", \"material-v2\"];\n\n\t dataviz.ExportMixin = {\n\t extend: function(proto, skipLegacy) {\n\t if (!proto.exportVisual) {\n\t throw new Error(\"Mixin target has no exportVisual method defined.\");\n\t }\n\n\t proto.exportSVG = this.exportSVG;\n\t proto.exportImage = this.exportImage;\n\t proto.exportPDF = this.exportPDF;\n\n\t if (!skipLegacy) {\n\t proto.svg = this.svg;\n\t proto.imageDataURL = this.imageDataURL;\n\t }\n\t },\n\n\t exportSVG: function(options) {\n\t return draw.exportSVG(this.exportVisual(), options);\n\t },\n\n\t exportImage: function(options) {\n\t return draw.exportImage(this.exportVisual(options), options);\n\t },\n\n\t exportPDF: function(options) {\n\t return draw.exportPDF(this.exportVisual(), options);\n\t },\n\n\t svg: function() {\n\t if (draw.svg.Surface) {\n\t return draw.svg.exportGroup(this.exportVisual());\n\t } else {\n\t throw new Error(\"SVG Export failed. Unable to export instantiate kendo.drawing.svg.Surface\");\n\t }\n\t },\n\n\t imageDataURL: function() {\n\t if (!kendo.support.canvas) {\n\t return null;\n\t }\n\n\t if (draw.canvas.Surface) {\n\t var container = $(\"\").css({\n\t display: \"none\",\n\t width: this.element.width(),\n\t height: this.element.height()\n\t }).appendTo(document.body);\n\n\t var surface = new draw.canvas.Surface(container[0]);\n\t surface.draw(this.exportVisual());\n\t var image = surface._rootElement.toDataURL();\n\n\t surface.destroy();\n\t container.remove();\n\n\t return image;\n\t } else {\n\t throw new Error(\"Image Export failed. Unable to export instantiate kendo.drawing.canvas.Surface\");\n\t }\n\t }\n\t };\n\n\t services.IntlService.register({\n\t format: function(format) {\n\t return kendo.format.apply(null, [format].concat(Array.prototype.slice.call(arguments, 1)));\n\t },\n\t toString: kendo.toString,\n\t parseDate: kendo.parseDate\n\t });\n\n\t services.TemplateService.register({\n\t compile: kendo.template\n\t });\n\n\t dataviz.Point2D = dataviz.Point;\n\t dataviz.Box2D = dataviz.Box;\n\t dataviz.mwDelta = function(e) {\n\t return dataviz.mousewheelDelta(e.originalEvent);\n\t };\n\n\t})(window.kendo.jQuery);\n\n\t}, __webpack_require__(3));\n\n/***/ }),\n\n/***/ 866:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"./kendo-core\");\n\n/***/ })\n\n/******/ });","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ 0:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tmodule.exports = __webpack_require__(867);\n\n\n/***/ }),\n\n/***/ 3:\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n\n/***/ 860:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.drawing\");\n\n/***/ }),\n\n/***/ 863:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.core\");\n\n/***/ }),\n\n/***/ 867:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/***********************************************************************\n\t * WARNING: this file is auto-generated. If you change it directly,\n\t * your modifications will eventually be lost. The source code is in\n\t * `kendo-charts` repository, you should make your changes there and\n\t * run `src-modules/sync.sh` in this repository.\n\t */\n\t(function(f, define){\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [\n\t __webpack_require__(863),\n\t __webpack_require__(860)\n\t ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t})(function(){\n\n\t(function ($) {\n\t/* jshint curly:false */\n\n\twindow.kendo.dataviz = window.kendo.dataviz || {};\n\tvar drawing = kendo.drawing;\n\tvar util = drawing.util;\n\tvar Path = drawing.Path;\n\tvar Group = drawing.Group;\n\tvar Class = kendo.Class;\n\tvar geometry = kendo.geometry;\n\tvar Rect = geometry.Rect;\n\tvar Circle = geometry.Circle;\n\tvar geometryTransform = geometry.transform;\n\tvar Segment = geometry.Segment;\n\tvar dataviz = kendo.dataviz;\n\n\tvar deepExtend = kendo.deepExtend;\n\tvar isFunction = kendo.isFunction;\n\tvar __common_getter_js = kendo.getter;\n\n\tvar ARC = \"arc\";\n\tvar AXIS_LABEL_CLICK = \"axisLabelClick\";\n\tvar BLACK = \"#000\";\n\tvar BOTTOM = \"bottom\";\n\tvar CENTER = \"center\";\n\tvar CIRCLE = \"circle\";\n\tvar COORD_PRECISION = 3;\n\tvar CROSS = \"cross\";\n\tvar DATE = \"date\";\n\tvar DEFAULT_FONT = \"12px sans-serif\";\n\tvar DEFAULT_HEIGHT = 400;\n\tvar DEFAULT_PRECISION = 10;\n\tvar DEFAULT_WIDTH = 600;\n\tvar END = \"end\";\n\tvar FORMAT_REGEX = /\\{\\d+:?/;\n\tvar HEIGHT = \"height\";\n\tvar HIGHLIGHT_ZINDEX = 100;\n\tvar INSIDE = \"inside\";\n\tvar LEFT = \"left\";\n\tvar MAX_VALUE = Number.MAX_VALUE;\n\tvar MIN_VALUE = -Number.MAX_VALUE;\n\tvar NONE = \"none\";\n\tvar NOTE_CLICK = \"noteClick\";\n\tvar NOTE_HOVER = \"noteHover\";\n\tvar NOTE_LEAVE = \"noteLeave\";\n\tvar OBJECT = \"object\";\n\tvar OUTSIDE = \"outside\";\n\tvar RIGHT = \"right\";\n\tvar START = \"start\";\n\tvar STRING = \"string\";\n\tvar TOP = \"top\";\n\tvar TRIANGLE = \"triangle\";\n\tvar VALUE = \"value\";\n\tvar WHITE = \"#fff\";\n\tvar WIDTH = \"width\";\n\tvar X = \"x\";\n\tvar Y = \"y\";\n\n\tvar constants = {\n\t\tARC: ARC,\n\t\tAXIS_LABEL_CLICK: AXIS_LABEL_CLICK,\n\t\tBLACK: BLACK,\n\t\tBOTTOM: BOTTOM,\n\t\tCENTER: CENTER,\n\t\tCIRCLE: CIRCLE,\n\t\tCOORD_PRECISION: COORD_PRECISION,\n\t\tCROSS: CROSS,\n\t\tDATE: DATE,\n\t\tDEFAULT_FONT: DEFAULT_FONT,\n\t\tDEFAULT_HEIGHT: DEFAULT_HEIGHT,\n\t\tDEFAULT_PRECISION: DEFAULT_PRECISION,\n\t\tDEFAULT_WIDTH: DEFAULT_WIDTH,\n\t\tEND: END,\n\t\tFORMAT_REGEX: FORMAT_REGEX,\n\t\tHEIGHT: HEIGHT,\n\t\tHIGHLIGHT_ZINDEX: HIGHLIGHT_ZINDEX,\n\t\tINSIDE: INSIDE,\n\t\tLEFT: LEFT,\n\t\tMAX_VALUE: MAX_VALUE,\n\t\tMIN_VALUE: MIN_VALUE,\n\t\tNONE: NONE,\n\t\tNOTE_CLICK: NOTE_CLICK,\n\t\tNOTE_HOVER: NOTE_HOVER,\n\t\tNOTE_LEAVE: NOTE_LEAVE,\n\t\tOBJECT: OBJECT,\n\t\tOUTSIDE: OUTSIDE,\n\t\tRIGHT: RIGHT,\n\t\tSTART: START,\n\t\tSTRING: STRING,\n\t\tTOP: TOP,\n\t\tTRIANGLE: TRIANGLE,\n\t\tVALUE: VALUE,\n\t\tWHITE: WHITE,\n\t\tWIDTH: WIDTH,\n\t\tX: X,\n\t\tY: Y\n\t};\n\n\tfunction isArray(value) {\n\t return Array.isArray(value);\n\t}\n\n\tfunction addClass(element, classes) {\n\t var classArray = isArray(classes) ? classes : [ classes ];\n\n\t for (var idx = 0; idx < classArray.length; idx++) {\n\t var className = classArray[idx];\n\t if (element.className.indexOf(className) === -1) {\n\t element.className += \" \" + className;\n\t }\n\t }\n\t}\n\n\tvar SPACE_REGEX = /\\s+/g;\n\n\tfunction removeClass(element, className) {\n\t if (element && element.className) {\n\t element.className = element.className.replace(className, \"\").replace(SPACE_REGEX, \" \");\n\t }\n\t}\n\n\tfunction alignPathToPixel(path) {\n\t var offset = 0.5;\n\t if (path.options.stroke && kendo.drawing.util.defined(path.options.stroke.width)) {\n\t if (path.options.stroke.width % 2 === 0) {\n\t offset = 0;\n\t }\n\t }\n\n\t for (var i = 0; i < path.segments.length; i++) {\n\t path.segments[i].anchor().round(0).translate(offset, offset);\n\t }\n\n\t return path;\n\t}\n\n\tfunction clockwise(angle1, angle2) {\n\t // True if angle2 is clockwise of angle1\n\t // assuming angles grow in clock-wise direction\n\t // (as in the pie and radar charts)\n\t return -angle1.x * angle2.y + angle1.y * angle2.x < 0;\n\t}\n\n\tfunction isNumber(value) {\n\t return typeof value === \"number\" && !isNaN(value);\n\t}\n\n\tfunction isString(value) {\n\t return typeof value === STRING;\n\t}\n\n\tfunction convertableToNumber(value) {\n\t return isNumber(value) || (isString(value) && isFinite(value));\n\t}\n\n\tfunction isObject(value) {\n\t return typeof value === \"object\";\n\t}\n\n\tfunction styleValue(value) {\n\t if (isNumber(value)) {\n\t return value + \"px\";\n\t }\n\t return value;\n\t}\n\n\tvar SIZE_STYLES_REGEX = /width|height|top|left|bottom|right/i;\n\n\tfunction isSizeField(field) {\n\t return SIZE_STYLES_REGEX.test(field);\n\t}\n\n\tfunction elementStyles(element, styles) {\n\t var stylesArray = isString(styles) ? [ styles ] : styles;\n\n\t if (isArray(stylesArray)) {\n\t var result = {};\n\t var style = window.getComputedStyle(element);\n\n\t for (var idx = 0; idx < stylesArray.length; idx++) {\n\t var field = stylesArray[idx];\n\t result[field] = isSizeField(field) ? parseFloat(style[field]) : style[field];\n\t }\n\n\t return result;\n\t } else if (isObject(styles)) {\n\t for (var field$1 in styles) {\n\t element.style[field$1] = styleValue(styles[field$1]);\n\t }\n\t }\n\t}\n\n\tfunction getSpacing(value, defaultSpacing) {\n\t if (defaultSpacing === void 0) { defaultSpacing = 0; }\n\n\t var spacing = { top: 0, right: 0, bottom: 0, left: 0 };\n\n\t if (typeof(value) === \"number\") {\n\t spacing[TOP] = spacing[RIGHT] = spacing[BOTTOM] = spacing[LEFT] = value;\n\t } else {\n\t spacing[TOP] = value[TOP] || defaultSpacing;\n\t spacing[RIGHT] = value[RIGHT] || defaultSpacing;\n\t spacing[BOTTOM] = value[BOTTOM] || defaultSpacing;\n\t spacing[LEFT] = value[LEFT] || defaultSpacing;\n\t }\n\n\t return spacing;\n\t}\n\n\tvar defaultImplementation = {\n\t format: function (format, value) { return value; },\n\n\t toString: function (value) { return value; },\n\n\t parseDate: function (value) { return new Date(value); }\n\t};\n\n\tvar current = defaultImplementation;\n\n\tvar IntlService = Class.extend({\n\n\t});\n\n\tIntlService.register = function(userImplementation) {\n\t current = userImplementation;\n\t};\n\n\tif (Object.defineProperties) {\n\t Object.defineProperties(IntlService, {\n\t implementation: {\n\t get: function() {\n\t return current;\n\t }\n\t }\n\t });\n\t}\n\n\tvar FORMAT_REPLACE_REGEX = /\\{(\\d+)(:[^\\}]+)?\\}/g;\n\n\tvar FormatService = Class.extend({\n\t init: function(intlService) {\n\t this._intlService = intlService;\n\t },\n\n\t auto: function(formatString) {\n\t var values = [], len = arguments.length - 1;\n\t while ( len-- > 0 ) values[ len ] = arguments[ len + 1 ];\n\n\t var intl = this.intl;\n\n\t if (isString(formatString) && formatString.match(FORMAT_REGEX)) {\n\t return intl.format.apply(intl, [ formatString ].concat( values ));\n\t }\n\n\t return intl.toString(values[0], formatString);\n\t },\n\n\t localeAuto: function(formatString, values, locale) {\n\t var intl = this.intl;\n\t var result;\n\n\t if (isString(formatString) && formatString.match(FORMAT_REGEX)) {\n\t result = formatString.replace(FORMAT_REPLACE_REGEX, function(match, index, placeholderFormat) {\n\t var value = values[parseInt(index, 10)];\n\n\t return intl.toString(value, placeholderFormat ? placeholderFormat.substring(1) : \"\", locale);\n\t });\n\t } else {\n\t result = intl.toString(values[0], formatString, locale);\n\t }\n\n\t return result;\n\t }\n\t});\n\n\tif (Object.defineProperties) {\n\t Object.defineProperties(FormatService.fn, {\n\t intl: {\n\t get: function() {\n\t return this._intlService || IntlService.implementation;\n\t },\n\t set: function(value) {\n\t this._intlService = value;\n\t }\n\t }\n\t });\n\t}\n\n\tvar ChartService = Class.extend({\n\t init: function(chart, context) {\n\t if (context === void 0) { context = {}; }\n\n\t this._intlService = context.intlService;\n\t this.sender = context.sender || chart;\n\t this.format = new FormatService(context.intlService);\n\t this.chart = chart;\n\t this.rtl = Boolean(context.rtl);\n\t },\n\n\t notify: function(name, args) {\n\t if (this.chart) {\n\t this.chart.trigger(name, args);\n\t }\n\t },\n\n\t isPannable: function(axis) {\n\t var pannable = ((this.chart || {}).options || {}).pannable;\n\t return pannable && pannable.lock !== axis;\n\t }\n\t});\n\n\tif (Object.defineProperties) {\n\t Object.defineProperties(ChartService.fn, {\n\t intl: {\n\t get: function() {\n\t return this._intlService || IntlService.implementation;\n\t },\n\t set: function(value) {\n\t this._intlService = value;\n\t this.format.intl = value;\n\t }\n\t }\n\t });\n\t}\n\n\tvar current$1;\n\n\tvar DomEventsBuilder = Class.extend({\n\n\t});\n\n\tDomEventsBuilder.register = function(userImplementation) {\n\t current$1 = userImplementation;\n\t};\n\n\tDomEventsBuilder.create = function(element, events) {\n\t if (current$1) {\n\t return current$1.create(element, events);\n\t }\n\t};\n\n\tvar current$2 = {\n\t compile: function(template) {\n\t return template;\n\t }\n\t};\n\n\tvar TemplateService = Class.extend({\n\n\t});\n\n\tTemplateService.register = function(userImplementation) {\n\t current$2 = userImplementation;\n\t};\n\n\tTemplateService.compile = function(template) {\n\t return current$2.compile(template);\n\t};\n\n\tvar services = {\n\t\tChartService: ChartService,\n\t\tDomEventsBuilder: DomEventsBuilder,\n\t\tFormatService: FormatService,\n\t\tIntlService: IntlService,\n\t\tTemplateService: TemplateService\n\t};\n\n\tfunction getTemplate(options) {\n\t if (options === void 0) { options = {}; }\n\n\t var template;\n\t if (options.template) {\n\t options.template = template = TemplateService.compile(options.template);\n\t } else if (isFunction(options.content)) {\n\t template = options.content;\n\t }\n\n\t return template;\n\t}\n\n\tfunction grep(array, callback) {\n\t var length = array.length;\n\t var result = [];\n\t for (var idx = 0; idx < length; idx++) {\n\t if (callback(array[idx])) {\n\t result .push(array[idx]);\n\t }\n\t }\n\n\t return result;\n\t}\n\n\tfunction hasClasses(element, classNames) {\n\t if (element.className) {\n\t var names = classNames.split(\" \");\n\t for (var idx = 0; idx < names.length; idx++) {\n\t if (element.className.indexOf(names[idx]) !== -1) {\n\t return true;\n\t }\n\t }\n\t }\n\t}\n\n\tvar HashMap = function HashMap() {\n\t this._map = {};\n\t};\n\n\tHashMap.prototype.get = function get (name) {\n\t return this._map[this._key(name)];\n\t};\n\n\tHashMap.prototype.set = function set (name, value) {\n\t this._map[this._key(name)] = value;\n\t};\n\n\tHashMap.prototype._key = function _key (name) {\n\t return name instanceof Date ? name.getTime() : name;\n\t};\n\n\tfunction inArray(value, array) {\n\t if (array) {\n\t return array.indexOf(value) !== -1;\n\t }\n\t}\n\n\tfunction interpolateValue(start, end, progress) {\n\t return kendo.drawing.util.round(start + (end - start) * progress, COORD_PRECISION);\n\t}\n\n\tvar TRIGGER = 'trigger';\n\n\tvar InstanceObserver = Class.extend({\n\t init: function(observer, handlers) {\n\t this.observer = observer;\n\t this.handlerMap = deepExtend({}, this.handlerMap, handlers);\n\t },\n\n\t trigger: function(name, args) {\n\t var ref = this;\n\t var observer = ref.observer;\n\t var handlerMap = ref.handlerMap;\n\t var isDefaultPrevented;\n\t if (handlerMap[name]) {\n\t isDefaultPrevented = this.callObserver(handlerMap[name], args);\n\t } else if (observer[TRIGGER]) {\n\t isDefaultPrevented = this.callObserver(TRIGGER, name, args);\n\t }\n\n\t return isDefaultPrevented;\n\t },\n\n\t callObserver: function(fnName) {\n\t var args = [], len = arguments.length - 1;\n\t while ( len-- > 0 ) args[ len ] = arguments[ len + 1 ];\n\n\t return this.observer[fnName].apply(this.observer, args);\n\t },\n\n\t requiresHandlers: function(names) {\n\t var this$1 = this;\n\n\t if (this.observer.requiresHandlers) {\n\t return this.observer.requiresHandlers(names);\n\t }\n\n\t for (var idx = 0; idx < names.length; idx++) {\n\t if (this$1.handlerMap[names[idx]]) {\n\t return true;\n\t }\n\t }\n\t }\n\t});\n\n\tfunction map(array, callback) {\n\t var length = array.length;\n\t var result = [];\n\t for (var idx = 0; idx < length; idx++) {\n\t var value = callback(array[idx]);\n\t if (kendo.drawing.util.defined(value)) {\n\t result.push(value);\n\t }\n\t }\n\t return result;\n\t}\n\n\tfunction mousewheelDelta(e) {\n\t var delta = 0;\n\n\t if (e.wheelDelta) {\n\t delta = -e.wheelDelta / 120;\n\t delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta);\n\t }\n\n\t if (e.detail) {\n\t delta = kendo.drawing.util.round(e.detail / 3);\n\t }\n\n\t return delta;\n\t}\n\n\tvar ref = kendo.drawing.util;\n\tvar append = ref.append;\n\tvar bindEvents = ref.bindEvents;\n\tvar defined = ref.defined;\n\tvar deg = ref.deg;\n\tvar elementOffset = ref.elementOffset;\n\tvar elementSize = ref.elementSize;\n\tvar eventElement = ref.eventElement;\n\tvar eventCoordinates = ref.eventCoordinates;\n\tvar last = ref.last;\n\tvar limitValue = ref.limitValue;\n\tvar objectKey = ref.objectKey;\n\tvar rad = ref.rad;\n\tvar round = ref.round;\n\tvar unbindEvents = ref.unbindEvents;\n\tvar valueOrDefault = ref.valueOrDefault;\n\n\tvar FontLoader = Class.extend({\n\n\t});\n\n\tFontLoader.fetchFonts = function(options, fonts, state) {\n\t if (state === void 0) { state = { depth: 0 }; }\n\n\t var MAX_DEPTH = 5;\n\n\t if (!options || state.depth > MAX_DEPTH || !document.fonts) {\n\t return;\n\t }\n\n\t Object.keys(options).forEach(function(key) {\n\t var value = options[key];\n\t if (key === \"dataSource\" || key[0] === \"$\" || !value) {\n\t return;\n\t }\n\n\t if (key === \"font\") {\n\t fonts.push(value);\n\t } else if (typeof value === \"object\") {\n\t state.depth++;\n\t FontLoader.fetchFonts(value, fonts, state);\n\t state.depth--;\n\t }\n\t });\n\t};\n\n\tFontLoader.loadFonts = function(fonts, callback) {\n\t var promises = [];\n\n\t if (fonts.length > 0 && document.fonts) {\n\t try {\n\t promises = fonts.map(function(font) {\n\t return document.fonts.load(font);\n\t });\n\t } catch (e) {\n\t // Silence font-loading errors\n\t kendo.logToConsole(e);\n\t }\n\n\t Promise.all(promises).then(callback, callback);\n\t } else {\n\t callback();\n\t }\n\t};\n\n\tFontLoader.preloadFonts = function(options, callback) {\n\t var fonts = [];\n\t FontLoader.fetchFonts(options, fonts);\n\n\t FontLoader.loadFonts(fonts, callback);\n\t};\n\n\tfunction setDefaultOptions(type, options) {\n\t var proto = type.prototype;\n\t if (proto.options) {\n\t proto.options = deepExtend({}, proto.options, options);\n\t } else {\n\t proto.options = options;\n\t }\n\t}\n\n\tfunction sparseArrayLimits(arr) {\n\t var min = MAX_VALUE;\n\t var max = MIN_VALUE;\n\n\t for (var idx = 0, length = arr.length; idx < length; idx++) {\n\t var value = arr[idx];\n\t if (value !== null && isFinite(value)) {\n\t min = Math.min(min, value);\n\t max = Math.max(max, value);\n\t }\n\t }\n\n\t return {\n\t min: min === MAX_VALUE ? undefined : min,\n\t max: max === MIN_VALUE ? undefined : max\n\t };\n\t}\n\n\tfunction find(array, predicate) {\n\t for (var i = 0; i < array.length; i++) {\n\t var item = array[i];\n\t if (predicate(item, i, array)) {\n\t return item;\n\t }\n\t }\n\t}\n\n\tfunction autoMajorUnit(min, max) {\n\t var diff = round(max - min, DEFAULT_PRECISION - 1);\n\n\t if (diff === 0) {\n\t if (max === 0) {\n\t return 0.1;\n\t }\n\n\t diff = Math.abs(max);\n\t }\n\n\t var scale = Math.pow(10, Math.floor(Math.log(diff) / Math.log(10)));\n\t var relativeValue = round((diff / scale), DEFAULT_PRECISION);\n\t var scaleMultiplier = 1;\n\n\t if (relativeValue < 1.904762) {\n\t scaleMultiplier = 0.2;\n\t } else if (relativeValue < 4.761904) {\n\t scaleMultiplier = 0.5;\n\t } else if (relativeValue < 9.523809) {\n\t scaleMultiplier = 1;\n\t } else {\n\t scaleMultiplier = 2;\n\t }\n\n\t return round(scale * scaleMultiplier, DEFAULT_PRECISION);\n\t}\n\n\tvar Point = Class.extend({\n\t init: function(x, y) {\n\n\t this.x = x || 0;\n\t this.y = y || 0;\n\t },\n\n\t clone: function() {\n\t return new Point(this.x, this.y);\n\t },\n\n\t equals: function(point) {\n\t return point && this.x === point.x && this.y === point.y;\n\t },\n\n\t rotate: function(center, degrees) {\n\t var theta = rad(degrees);\n\t var cosT = Math.cos(theta);\n\t var sinT = Math.sin(theta);\n\t var cx = center.x;\n\t var cy = center.y;\n\t var ref = this;\n\t var x = ref.x;\n\t var y = ref.y;\n\n\t this.x = round(\n\t cx + (x - cx) * cosT + (y - cy) * sinT,\n\t COORD_PRECISION\n\t );\n\n\t this.y = round(\n\t cy + (y - cy) * cosT - (x - cx) * sinT,\n\t COORD_PRECISION\n\t );\n\n\t return this;\n\t },\n\n\t multiply: function(a) {\n\n\t this.x *= a;\n\t this.y *= a;\n\n\t return this;\n\t },\n\n\t distanceTo: function(point) {\n\t var dx = this.x - point.x;\n\t var dy = this.y - point.y;\n\n\t return Math.sqrt(dx * dx + dy * dy);\n\t }\n\t});\n\n\tPoint.onCircle = function(center, angle, radius) {\n\t var radians = rad(angle);\n\n\t return new Point(\n\t center.x - radius * Math.cos(radians),\n\t center.y - radius * Math.sin(radians)\n\t );\n\t};\n\n\tvar Box = Class.extend({\n\t init: function(x1, y1, x2, y2) {\n\n\t this.x1 = x1 || 0;\n\t this.y1 = y1 || 0;\n\t this.x2 = x2 || 0;\n\t this.y2 = y2 || 0;\n\t },\n\n\t equals: function(box) {\n\t return this.x1 === box.x1 && this.x2 === box.x2 &&\n\t this.y1 === box.y1 && this.y2 === box.y2;\n\t },\n\n\t width: function() {\n\t return this.x2 - this.x1;\n\t },\n\n\t height: function() {\n\t return this.y2 - this.y1;\n\t },\n\n\t translate: function(dx, dy) {\n\t this.x1 += dx;\n\t this.x2 += dx;\n\t this.y1 += dy;\n\t this.y2 += dy;\n\n\t return this;\n\t },\n\n\t move: function(x, y) {\n\t var height = this.height();\n\t var width = this.width();\n\n\t if (defined(x)) {\n\t this.x1 = x;\n\t this.x2 = this.x1 + width;\n\t }\n\n\t if (defined(y)) {\n\t this.y1 = y;\n\t this.y2 = this.y1 + height;\n\t }\n\n\t return this;\n\t },\n\n\t wrap: function(targetBox) {\n\t this.x1 = Math.min(this.x1, targetBox.x1);\n\t this.y1 = Math.min(this.y1, targetBox.y1);\n\t this.x2 = Math.max(this.x2, targetBox.x2);\n\t this.y2 = Math.max(this.y2, targetBox.y2);\n\n\t return this;\n\t },\n\n\t wrapPoint: function(point) {\n\t var arrayPoint = isArray(point);\n\t var x = arrayPoint ? point[0] : point.x;\n\t var y = arrayPoint ? point[1] : point.y;\n\t this.wrap(new Box(x, y, x, y));\n\n\t return this;\n\t },\n\n\t snapTo: function(targetBox, axis) {\n\n\t if (axis === X || !axis) {\n\t this.x1 = targetBox.x1;\n\t this.x2 = targetBox.x2;\n\t }\n\n\t if (axis === Y || !axis) {\n\t this.y1 = targetBox.y1;\n\t this.y2 = targetBox.y2;\n\t }\n\n\t return this;\n\t },\n\n\t alignTo: function(targetBox, anchor) {\n\t var height = this.height();\n\t var width = this.width();\n\t var axis = anchor === TOP || anchor === BOTTOM ? Y : X;\n\t var offset = axis === Y ? height : width;\n\n\t if (anchor === CENTER) {\n\t var targetCenter = targetBox.center();\n\t var center = this.center();\n\n\t this.x1 += targetCenter.x - center.x;\n\t this.y1 += targetCenter.y - center.y;\n\t } else if (anchor === TOP || anchor === LEFT) {\n\t this[axis + 1] = targetBox[axis + 1] - offset;\n\t } else {\n\t this[axis + 1] = targetBox[axis + 2];\n\t }\n\n\t this.x2 = this.x1 + width;\n\t this.y2 = this.y1 + height;\n\n\t return this;\n\t },\n\n\t shrink: function(dw, dh) {\n\n\t this.x2 -= dw;\n\t this.y2 -= dh;\n\n\t return this;\n\t },\n\n\t expand: function(dw, dh) {\n\t this.shrink(-dw, -dh);\n\t return this;\n\t },\n\n\t pad: function(padding) {\n\t var spacing = getSpacing(padding);\n\n\t this.x1 -= spacing.left;\n\t this.x2 += spacing.right;\n\t this.y1 -= spacing.top;\n\t this.y2 += spacing.bottom;\n\n\t return this;\n\t },\n\n\t unpad: function(padding) {\n\t var spacing = getSpacing(padding);\n\n\t spacing.left = -spacing.left;\n\t spacing.top = -spacing.top;\n\t spacing.right = -spacing.right;\n\t spacing.bottom = -spacing.bottom;\n\n\t return this.pad(spacing);\n\t },\n\n\t clone: function() {\n\t return new Box(this.x1, this.y1, this.x2, this.y2);\n\t },\n\n\t center: function() {\n\t return new Point(\n\t this.x1 + this.width() / 2,\n\t this.y1 + this.height() / 2\n\t );\n\t },\n\n\t containsPoint: function(point) {\n\n\t return point.x >= this.x1 && point.x <= this.x2 &&\n\t point.y >= this.y1 && point.y <= this.y2;\n\t },\n\n\t points: function() {\n\t return [\n\t new Point(this.x1, this.y1),\n\t new Point(this.x2, this.y1),\n\t new Point(this.x2, this.y2),\n\t new Point(this.x1, this.y2)\n\t ];\n\t },\n\n\t getHash: function() {\n\t return [ this.x1, this.y1, this.x2, this.y2 ].join(\",\");\n\t },\n\n\t overlaps: function(box) {\n\t return !(box.y2 < this.y1 || this.y2 < box.y1 || box.x2 < this.x1 || this.x2 < box.x1);\n\t },\n\n\t rotate: function(rotation) {\n\t var width = this.width();\n\t var height = this.height();\n\t var ref = this.center();\n\t var cx = ref.x;\n\t var cy = ref.y;\n\n\t var r1 = rotatePoint(0, 0, cx, cy, rotation);\n\t var r2 = rotatePoint(width, 0, cx, cy, rotation);\n\t var r3 = rotatePoint(width, height, cx, cy, rotation);\n\t var r4 = rotatePoint(0, height, cx, cy, rotation);\n\n\t width = Math.max(r1.x, r2.x, r3.x, r4.x) - Math.min(r1.x, r2.x, r3.x, r4.x);\n\t height = Math.max(r1.y, r2.y, r3.y, r4.y) - Math.min(r1.y, r2.y, r3.y, r4.y);\n\n\t this.x2 = this.x1 + width;\n\t this.y2 = this.y1 + height;\n\n\t return this;\n\t },\n\n\t toRect: function() {\n\t return new Rect([ this.x1, this.y1 ], [ this.width(), this.height() ]);\n\t },\n\n\t hasSize: function() {\n\t return this.width() !== 0 && this.height() !== 0;\n\t },\n\n\t align: function(targetBox, axis, alignment) {\n\t var c1 = axis + 1;\n\t var c2 = axis + 2;\n\t var sizeFunc = axis === X ? WIDTH : HEIGHT;\n\t var size = this[sizeFunc]();\n\n\t if (inArray(alignment, [ LEFT, TOP ])) {\n\t this[c1] = targetBox[c1];\n\t this[c2] = this[c1] + size;\n\t } else if (inArray(alignment, [ RIGHT, BOTTOM ])) {\n\t this[c2] = targetBox[c2];\n\t this[c1] = this[c2] - size;\n\t } else if (alignment === CENTER) {\n\t this[c1] = targetBox[c1] + (targetBox[sizeFunc]() - size) / 2;\n\t this[c2] = this[c1] + size;\n\t }\n\t }\n\t});\n\n\tfunction rotatePoint(x, y, cx, cy, angle) {\n\t var theta = rad(angle);\n\n\t return new Point(\n\t cx + (x - cx) * Math.cos(theta) + (y - cy) * Math.sin(theta),\n\t cy - (x - cx) * Math.sin(theta) + (y - cy) * Math.cos(theta)\n\t );\n\t}\n\n\tvar Ring = Class.extend({\n\t init: function(center, innerRadius, radius, startAngle, angle) {\n\n\t this.center = center;\n\t this.innerRadius = innerRadius;\n\t this.radius = radius;\n\t this.startAngle = startAngle;\n\t this.angle = angle;\n\t },\n\n\t clone: function() {\n\t return new Ring(this.center, this.innerRadius, this.radius, this.startAngle, this.angle);\n\t },\n\n\t middle: function() {\n\t return this.startAngle + this.angle / 2;\n\t },\n\n\t setRadius: function(newRadius, innerRadius) {\n\t if (innerRadius) {\n\t this.innerRadius = newRadius;\n\t } else {\n\t this.radius = newRadius;\n\t }\n\n\t return this;\n\t },\n\n\t point: function(angle, innerRadius) {\n\t var radianAngle = rad(angle);\n\t var ax = Math.cos(radianAngle);\n\t var ay = Math.sin(radianAngle);\n\t var radius = innerRadius ? this.innerRadius : this.radius;\n\t var x = round(this.center.x - (ax * radius), COORD_PRECISION);\n\t var y = round(this.center.y - (ay * radius), COORD_PRECISION);\n\n\t return new Point(x, y);\n\t },\n\n\t adjacentBox: function(distance, width, height) {\n\t var sector = this.clone().expand(distance);\n\t var midAndle = sector.middle();\n\t var midPoint = sector.point(midAndle);\n\t var hw = width / 2;\n\t var hh = height / 2;\n\t var sa = Math.sin(rad(midAndle));\n\t var ca = Math.cos(rad(midAndle));\n\t var x = midPoint.x - hw;\n\t var y = midPoint.y - hh;\n\n\t if (Math.abs(sa) < 0.9) {\n\t x += hw * -ca / Math.abs(ca);\n\t }\n\n\t if (Math.abs(ca) < 0.9) {\n\t y += hh * -sa / Math.abs(sa);\n\t }\n\n\t return new Box(x, y, x + width, y + height);\n\t },\n\n\t containsPoint: function(p) {\n\t var center = this.center;\n\t var innerRadius = this.innerRadius;\n\t var radius = this.radius;\n\t var startAngle = this.startAngle;\n\t var endAngle = this.startAngle + this.angle;\n\t var dx = p.x - center.x;\n\t var dy = p.y - center.y;\n\t var vector = new Point(dx, dy);\n\t var startPoint = this.point(startAngle);\n\t var startVector = new Point(startPoint.x - center.x, startPoint.y - center.y);\n\t var endPoint = this.point(endAngle);\n\t var endVector = new Point(endPoint.x - center.x, endPoint.y - center.y);\n\t var dist = round(dx * dx + dy * dy, COORD_PRECISION);\n\n\t return (startVector.equals(vector) || clockwise(startVector, vector)) &&\n\t !clockwise(endVector, vector) &&\n\t dist >= innerRadius * innerRadius && dist <= radius * radius;\n\t },\n\n\t getBBox: function() {\n\t var this$1 = this;\n\n\t var box = new Box(MAX_VALUE, MAX_VALUE, MIN_VALUE, MIN_VALUE);\n\t var startAngle = round(this.startAngle % 360);\n\t var endAngle = round((startAngle + this.angle) % 360);\n\t var innerRadius = this.innerRadius;\n\t var allAngles = [ 0, 90, 180, 270, startAngle, endAngle ].sort(numericComparer);\n\t var startAngleIndex = allAngles.indexOf(startAngle);\n\t var endAngleIndex = allAngles.indexOf(endAngle);\n\t var angles;\n\n\t if (startAngle === endAngle) {\n\t angles = allAngles;\n\t } else {\n\t if (startAngleIndex < endAngleIndex) {\n\t angles = allAngles.slice(startAngleIndex, endAngleIndex + 1);\n\t } else {\n\t angles = [].concat(\n\t allAngles.slice(0, endAngleIndex + 1),\n\t allAngles.slice(startAngleIndex, allAngles.length)\n\t );\n\t }\n\t }\n\n\t for (var i = 0; i < angles.length; i++) {\n\t var point = this$1.point(angles[i]);\n\t box.wrapPoint(point);\n\t box.wrapPoint(point, innerRadius);\n\t }\n\n\t if (!innerRadius) {\n\t box.wrapPoint(this.center);\n\t }\n\n\t return box;\n\t },\n\n\t expand: function(value) {\n\t this.radius += value;\n\t return this;\n\t }\n\t});\n\n\tfunction numericComparer(a, b) {\n\t return a - b;\n\t}\n\n\tvar Sector = Ring.extend({\n\t init: function(center, radius, startAngle, angle) {\n\t Ring.fn.init.call(this, center, 0, radius, startAngle, angle);\n\t },\n\n\t expand: function(value) {\n\t return Ring.fn.expand.call(this, value);\n\t },\n\n\t clone: function() {\n\t return new Sector(this.center, this.radius, this.startAngle, this.angle);\n\t },\n\n\t setRadius: function(newRadius) {\n\t this.radius = newRadius;\n\n\t return this;\n\t }\n\t});\n\n\tvar DIRECTION_ANGLE = 0.001; //any value that will make the endAngle bigger than the start angle will work here.\n\n\tvar ShapeBuilder = Class.extend({\n\t createRing: function(sector, options) {\n\t var startAngle = sector.startAngle + 180;\n\t var endAngle = sector.angle + startAngle;\n\n\t //required in order to avoid reversing the arc direction in cases like 0.000000000000001 + 100 === 100\n\t if (sector.angle > 0 && startAngle === endAngle) {\n\t endAngle += DIRECTION_ANGLE;\n\t }\n\n\t var center = new geometry.Point(sector.center.x, sector.center.y);\n\t var radius = Math.max(sector.radius, 0);\n\t var innerRadius = Math.max(sector.innerRadius, 0);\n\t var arc = new geometry.Arc(center, {\n\t startAngle: startAngle,\n\t endAngle: endAngle,\n\t radiusX: radius,\n\t radiusY: radius\n\t });\n\t var path = Path.fromArc(arc, options).close();\n\n\t if (innerRadius) {\n\t arc.radiusX = arc.radiusY = innerRadius;\n\t var innerEnd = arc.pointAt(endAngle);\n\t path.lineTo(innerEnd.x, innerEnd.y);\n\t path.arc(endAngle, startAngle, innerRadius, innerRadius, true);\n\t } else {\n\t path.lineTo(center.x, center.y);\n\t }\n\n\t return path;\n\t }\n\t});\n\n\tShapeBuilder.current = new ShapeBuilder();\n\n\tvar ChartElement = Class.extend({\n\t init: function(options) {\n\n\t this.children = [];\n\n\t this.options = deepExtend({}, this.options, this.initUserOptions(options));\n\t },\n\n\t initUserOptions: function(options) {\n\t return options;\n\t },\n\n\t reflow: function(targetBox) {\n\t var children = this.children;\n\t var box;\n\n\t for (var i = 0; i < children.length; i++) {\n\t var currentChild = children[i];\n\t currentChild.reflow(targetBox);\n\n\t box = box ? box.wrap(currentChild.box) : currentChild.box.clone();\n\t }\n\n\t this.box = box || targetBox;\n\t },\n\n\t destroy: function() {\n\t var children = this.children;\n\n\t if (this.animation) {\n\t this.animation.destroy();\n\t }\n\n\t for (var i = 0; i < children.length; i++) {\n\t children[i].destroy();\n\t }\n\t },\n\n\t getRoot: function() {\n\t var parent = this.parent;\n\n\t return parent ? parent.getRoot() : null;\n\t },\n\n\t getSender: function() {\n\t var service = this.getService();\n\t if (service) {\n\t return service.sender;\n\t }\n\t },\n\n\t getService: function() {\n\t var element = this;\n\t while (element) {\n\t if (element.chartService) {\n\t return element.chartService;\n\t }\n\t element = element.parent;\n\t }\n\t },\n\n\t translateChildren: function(dx, dy) {\n\t var children = this.children;\n\t var childrenCount = children.length;\n\n\t for (var i = 0; i < childrenCount; i++) {\n\t children[i].box.translate(dx, dy);\n\t }\n\t },\n\n\t append: function() {\n\t var arguments$1 = arguments;\n\t var this$1 = this;\n\n\t for (var i = 0; i < arguments.length; i++) {\n\t var item = arguments$1[i];\n\t this$1.children.push(item);\n\t item.parent = this$1;\n\t }\n\t },\n\n\t renderVisual: function() {\n\t if (this.options.visible === false) {\n\t return;\n\t }\n\n\t this.createVisual();\n\n\t this.addVisual();\n\n\t this.renderChildren();\n\n\t this.createAnimation();\n\t this.renderComplete();\n\t },\n\n\t addVisual: function() {\n\t if (this.visual) {\n\t this.visual.chartElement = this;\n\n\t if (this.parent) {\n\t this.parent.appendVisual(this.visual);\n\t }\n\t }\n\t },\n\n\t renderChildren: function() {\n\t var children = this.children;\n\t var length = children.length;\n\t for (var i = 0; i < length; i++) {\n\t children[i].renderVisual();\n\t }\n\t },\n\n\t createVisual: function() {\n\t this.visual = new Group({\n\t zIndex: this.options.zIndex,\n\t visible: valueOrDefault(this.options.visible, true)\n\t });\n\t },\n\n\t createAnimation: function() {\n\t if (this.visual && this.options.animation) {\n\t this.animation = drawing.Animation.create(\n\t this.visual, this.options.animation\n\t );\n\t }\n\t },\n\n\t appendVisual: function(childVisual) {\n\t if (!childVisual.chartElement) {\n\t childVisual.chartElement = this;\n\t }\n\n\t if (childVisual.options.noclip) {\n\t this.clipRoot().visual.append(childVisual);\n\t } else if (defined(childVisual.options.zIndex)) {\n\t this.stackRoot().stackVisual(childVisual);\n\t } else if (this.isStackRoot) {\n\t this.stackVisual(childVisual);\n\t } else if (this.visual) {\n\t this.visual.append(childVisual);\n\t } else {\n\t // Allow chart elements without visuals to\n\t // pass through child visuals\n\t this.parent.appendVisual(childVisual);\n\t }\n\t },\n\n\t clipRoot: function() {\n\t if (this.parent) {\n\t return this.parent.clipRoot();\n\t }\n\n\t return this;\n\t },\n\n\t stackRoot: function() {\n\t if (this.parent) {\n\t return this.parent.stackRoot();\n\t }\n\n\t return this;\n\t },\n\n\t stackVisual: function(childVisual) {\n\t var zIndex = childVisual.options.zIndex || 0;\n\t var visuals = this.visual.children;\n\t var length = visuals.length;\n\t var pos;\n\n\t for (pos = 0; pos < length; pos++) {\n\t var sibling = visuals[pos];\n\t var here = valueOrDefault(sibling.options.zIndex, 0);\n\t if (here > zIndex) {\n\t break;\n\t }\n\t }\n\n\t this.visual.insert(pos, childVisual);\n\t },\n\n\t traverse: function(callback) {\n\t var children = this.children;\n\t var length = children.length;\n\n\t for (var i = 0; i < length; i++) {\n\t var child = children[i];\n\n\t callback(child);\n\t if (child.traverse) {\n\t child.traverse(callback);\n\t }\n\t }\n\t },\n\n\t closest: function(match) {\n\t var element = this;\n\t var matched = false;\n\n\t while (element && !matched) {\n\t matched = match(element);\n\n\t if (!matched) {\n\t element = element.parent;\n\t }\n\t }\n\n\t if (matched) {\n\t return element;\n\t }\n\t },\n\n\t renderComplete: function() {},\n\n\t hasHighlight: function() {\n\t var options = (this.options || {}).highlight;\n\t return !(!this.createHighlight || (options && options.visible === false));\n\t },\n\n\t toggleHighlight: function(show) {\n\t var this$1 = this;\n\n\t var options = (this.options || {}).highlight || {};\n\t var customVisual = options.visual;\n\t var highlight = this._highlight;\n\n\t if (!highlight) {\n\t var highlightOptions = {\n\t fill: {\n\t color: WHITE,\n\t opacity: 0.2\n\t },\n\t stroke: {\n\t color: WHITE,\n\t width: 1,\n\t opacity: 0.2\n\t }\n\t };\n\n\t if (customVisual) {\n\t highlight = this._highlight = customVisual(\n\t $.extend(this.highlightVisualArgs(), {\n\t createVisual: function () { return this$1.createHighlight(highlightOptions); },\n\t sender: this.getSender(),\n\t series: this.series,\n\t dataItem: this.dataItem,\n\t category: this.category,\n\t value: this.value,\n\t percentage: this.percentage,\n\t runningTotal: this.runningTotal,\n\t total: this.total\n\t }\n\t ));\n\n\t if (!highlight) {\n\t return;\n\t }\n\t } else {\n\t highlight = this._highlight = this.createHighlight(highlightOptions);\n\t }\n\n\t if (!defined(highlight.options.zIndex)) {\n\t highlight.options.zIndex = valueOrDefault(options.zIndex, this.options.zIndex);\n\t }\n\n\t this.appendVisual(highlight);\n\t }\n\n\t highlight.visible(show);\n\t },\n\n\t createGradientOverlay: function(element, options, gradientOptions) {\n\t var overlay = new Path($.extend({\n\t stroke: {\n\t color: \"none\"\n\t },\n\t fill: this.createGradient(gradientOptions),\n\t closed: element.options.closed\n\t }, options));\n\n\t overlay.segments.elements(element.segments.elements());\n\n\t return overlay;\n\t },\n\n\t createGradient: function(options) {\n\t if (this.parent) {\n\t return this.parent.createGradient(options);\n\t }\n\t }\n\t});\n\n\tChartElement.prototype.options = { };\n\n\tvar BoxElement = ChartElement.extend({\n\t init: function(options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.options.margin = getSpacing(this.options.margin);\n\t this.options.padding = getSpacing(this.options.padding);\n\t },\n\n\t reflow: function(targetBox) {\n\t var this$1 = this;\n\n\t var options = this.options;\n\t var width = options.width;\n\t var height = options.height;\n\t var shrinkToFit = options.shrinkToFit;\n\t var hasSetSize = width && height;\n\t var margin = options.margin;\n\t var padding = options.padding;\n\t var borderWidth = options.border.width;\n\t var box;\n\n\t var reflowPaddingBox = function () {\n\t this$1.align(targetBox, X, options.align);\n\t this$1.align(targetBox, Y, options.vAlign);\n\t this$1.paddingBox = box.clone().unpad(margin).unpad(borderWidth);\n\t };\n\n\t var contentBox = targetBox.clone();\n\t if (hasSetSize) {\n\t contentBox.x2 = contentBox.x1 + width;\n\t contentBox.y2 = contentBox.y1 + height;\n\t }\n\n\t if (shrinkToFit) {\n\t contentBox.unpad(margin).unpad(borderWidth).unpad(padding);\n\t }\n\n\t ChartElement.fn.reflow.call(this, contentBox);\n\n\t if (hasSetSize) {\n\t box = this.box = new Box(0, 0, width, height);\n\t } else {\n\t box = this.box;\n\t }\n\n\t if (shrinkToFit && hasSetSize) {\n\t reflowPaddingBox();\n\t contentBox = this.contentBox = this.paddingBox.clone().unpad(padding);\n\t } else {\n\t contentBox = this.contentBox = box.clone();\n\t box.pad(padding).pad(borderWidth).pad(margin);\n\t reflowPaddingBox();\n\t }\n\n\t this.translateChildren(\n\t box.x1 - contentBox.x1 + margin.left + borderWidth + padding.left,\n\t box.y1 - contentBox.y1 + margin.top + borderWidth + padding.top\n\t );\n\n\t var children = this.children;\n\t for (var i = 0; i < children.length; i++) {\n\t var item = children[i];\n\t item.reflow(item.box);\n\t }\n\t },\n\n\t align: function(targetBox, axis, alignment) {\n\t this.box.align(targetBox, axis, alignment);\n\t },\n\n\t hasBox: function() {\n\t var options = this.options;\n\t return options.border.width || options.background;\n\t },\n\n\t createVisual: function() {\n\t ChartElement.fn.createVisual.call(this);\n\n\t var options = this.options;\n\t if (options.visible && this.hasBox()) {\n\t this.visual.append(Path.fromRect(\n\t this.paddingBox.toRect(),\n\t this.visualStyle()\n\t ));\n\t }\n\t },\n\n\t visualStyle: function() {\n\t var options = this.options;\n\t var border = options.border || {};\n\n\t return {\n\t stroke: {\n\t width: border.width,\n\t color: border.color,\n\t opacity: valueOrDefault(border.opacity, options.opacity),\n\t dashType: border.dashType\n\t },\n\t fill: {\n\t color: options.background,\n\t opacity: options.opacity\n\t },\n\t cursor: options.cursor\n\t };\n\t }\n\t});\n\n\tsetDefaultOptions(BoxElement, {\n\t align: LEFT,\n\t vAlign: TOP,\n\t margin: {},\n\t padding: {},\n\t border: {\n\t color: BLACK,\n\t width: 0\n\t },\n\t background: \"\",\n\t shrinkToFit: false,\n\t width: 0,\n\t height: 0,\n\t visible: true\n\t});\n\n\tvar ShapeElement = BoxElement.extend({\n\t init: function(options, pointData) {\n\t BoxElement.fn.init.call(this, options);\n\n\t this.pointData = pointData;\n\t },\n\n\t getElement: function() {\n\t var ref = this;\n\t var options = ref.options;\n\t var box = ref.paddingBox;\n\t var type = options.type;\n\t var rotation = options.rotation;\n\t var center = box.center();\n\t var halfWidth = box.width() / 2;\n\n\t if (!options.visible || !this.hasBox()) {\n\t return null;\n\t }\n\n\t var style = this.visualStyle();\n\t var element;\n\n\t if (type === CIRCLE) {\n\t element = new drawing.Circle(\n\t new Circle([\n\t round(box.x1 + halfWidth, COORD_PRECISION),\n\t round(box.y1 + box.height() / 2, COORD_PRECISION)\n\t ], halfWidth),\n\t style\n\t );\n\t } else if (type === TRIANGLE) {\n\t element = Path.fromPoints([\n\t [ box.x1 + halfWidth, box.y1 ],\n\t [ box.x1, box.y2 ],\n\t [ box.x2, box.y2 ]\n\t ], style).close();\n\t } else if (type === CROSS) {\n\t element = new drawing.MultiPath(style);\n\n\t element.moveTo(box.x1, box.y1).lineTo(box.x2, box.y2);\n\t element.moveTo(box.x1, box.y2).lineTo(box.x2, box.y1);\n\t } else {\n\t element = Path.fromRect(box.toRect(), style);\n\t }\n\n\t if (rotation) {\n\t element.transform(geometryTransform()\n\t .rotate(-rotation, [ center.x, center.y ])\n\t );\n\t }\n\n\t element.options.zIndex = options.zIndex;\n\t return element;\n\t },\n\n\t createElement: function() {\n\t var this$1 = this;\n\n\t var customVisual = this.options.visual;\n\t var pointData = this.pointData || {};\n\t var visual;\n\n\t if (customVisual) {\n\t visual = customVisual({\n\t value: pointData.value,\n\t dataItem: pointData.dataItem,\n\t sender: this.getSender(),\n\t series: pointData.series,\n\t category: pointData.category,\n\t rect: this.paddingBox.toRect(),\n\t options: this.visualOptions(),\n\t createVisual: function () { return this$1.getElement(); }\n\t });\n\t } else {\n\t visual = this.getElement();\n\t }\n\n\t return visual;\n\t },\n\n\t visualOptions: function() {\n\t var options = this.options;\n\t return {\n\t background: options.background,\n\t border: options.border,\n\t margin: options.margin,\n\t padding: options.padding,\n\t type: options.type,\n\t size: options.width,\n\t visible: options.visible\n\t };\n\t },\n\n\t createVisual: function() {\n\t this.visual = this.createElement();\n\t }\n\t});\n\n\tsetDefaultOptions(ShapeElement, {\n\t type: CIRCLE,\n\t align: CENTER,\n\t vAlign: CENTER\n\t});\n\n\tvar LINEAR = \"linear\";\n\tvar RADIAL = \"radial\";\n\n\tvar GRADIENTS = {\n\t glass: {\n\t type: LINEAR,\n\t rotation: 0,\n\t stops: [ {\n\t offset: 0,\n\t color: WHITE,\n\t opacity: 0\n\t }, {\n\t offset: 0.25,\n\t color: WHITE,\n\t opacity: 0.3\n\t }, {\n\t offset: 1,\n\t color: WHITE,\n\t opacity: 0\n\t } ]\n\t },\n\t sharpBevel: {\n\t type: RADIAL,\n\t stops: [ {\n\t offset: 0,\n\t color: WHITE,\n\t opacity: 0.55\n\t }, {\n\t offset: 0.65,\n\t color: WHITE,\n\t opacity: 0\n\t }, {\n\t offset: 0.95,\n\t color: WHITE,\n\t opacity: 0.25\n\t } ]\n\t },\n\t roundedBevel: {\n\t type: RADIAL,\n\t stops: [ {\n\t offset: 0.33,\n\t color: WHITE,\n\t opacity: 0.06\n\t }, {\n\t offset: 0.83,\n\t color: WHITE,\n\t opacity: 0.2\n\t }, {\n\t offset: 0.95,\n\t color: WHITE,\n\t opacity: 0\n\t } ]\n\t },\n\t roundedGlass: {\n\t type: RADIAL,\n\t supportVML: false,\n\t stops: [ {\n\t offset: 0,\n\t color: WHITE,\n\t opacity: 0\n\t }, {\n\t offset: 0.5,\n\t color: WHITE,\n\t opacity: 0.3\n\t }, {\n\t offset: 0.99,\n\t color: WHITE,\n\t opacity: 0\n\t } ]\n\t },\n\t sharpGlass: {\n\t type: RADIAL,\n\t supportVML: false,\n\t stops: [ {\n\t offset: 0,\n\t color: WHITE,\n\t opacity: 0.2\n\t }, {\n\t offset: 0.15,\n\t color: WHITE,\n\t opacity: 0.15\n\t }, {\n\t offset: 0.17,\n\t color: WHITE,\n\t opacity: 0.35\n\t }, {\n\t offset: 0.85,\n\t color: WHITE,\n\t opacity: 0.05\n\t }, {\n\t offset: 0.87,\n\t color: WHITE,\n\t opacity: 0.15\n\t }, {\n\t offset: 0.99,\n\t color: WHITE,\n\t opacity: 0\n\t } ]\n\t },\n\t bubbleShadow: {\n\t type: RADIAL,\n\t center: [ 0.5, 0.5 ],\n\t radius: 0.5\n\t }\n\t};\n\n\tfunction boxDiff(r, s) {\n\t if (r.x1 === s.x1 && r.y1 === s.y1 && r.x2 === s.x2 && r.y2 === s.y2) {\n\t return s;\n\t }\n\n\t var a = Math.min(r.x1, s.x1);\n\t var b = Math.max(r.x1, s.x1);\n\t var c = Math.min(r.x2, s.x2);\n\t var d = Math.max(r.x2, s.x2);\n\t var e = Math.min(r.y1, s.y1);\n\t var f = Math.max(r.y1, s.y1);\n\t var g = Math.min(r.y2, s.y2);\n\t var h = Math.max(r.y2, s.y2);\n\t var boxes = [];\n\n\t // X = intersection, 0-7 = possible difference areas\n\t // h +-+-+-+\n\t // . |5|6|7|\n\t // g +-+-+-+\n\t // . |3|X|4|\n\t // f +-+-+-+\n\t // . |0|1|2|\n\t // e +-+-+-+\n\t // . a b c d\n\n\t // we'll always have rectangles 1, 3, 4 and 6\n\t boxes[0] = new Box(b, e, c, f);\n\t boxes[1] = new Box(a, f, b, g);\n\t boxes[2] = new Box(c, f, d, g);\n\t boxes[3] = new Box(b, g, c, h);\n\n\t // decide which corners\n\t if (r.x1 === a && r.y1 === e || s.x1 === a && s.y1 === e) { // corners 0 and 7\n\t boxes[4] = new Box(a, e, b, f);\n\t boxes[5] = new Box(c, g, d, h);\n\t } else { // corners 2 and 5\n\t boxes[4] = new Box(c, e, d, f);\n\t boxes[5] = new Box(a, g, b, h);\n\t }\n\n\t return grep(boxes, function(box) {\n\t return box.height() > 0 && box.width() > 0;\n\t })[0];\n\t}\n\n\tvar RootElement = ChartElement.extend({\n\t init: function(options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t var rootOptions = this.options;\n\t rootOptions.width = parseInt(rootOptions.width, 10);\n\t rootOptions.height = parseInt(rootOptions.height, 10);\n\n\t this.gradients = {};\n\t },\n\n\t reflow: function() {\n\t var ref = this;\n\t var options = ref.options;\n\t var children = ref.children;\n\t var currentBox = new Box(0, 0, options.width, options.height);\n\n\t this.box = currentBox.unpad(options.margin);\n\n\t for (var i = 0; i < children.length; i++) {\n\t children[i].reflow(currentBox);\n\t currentBox = boxDiff(currentBox, children[i].box) || new Box();\n\t }\n\t },\n\n\t createVisual: function() {\n\t this.visual = new Group();\n\t this.createBackground();\n\t },\n\n\t createBackground: function() {\n\t var options = this.options;\n\t var border = options.border || {};\n\t var box = this.box.clone().pad(options.margin).unpad(border.width);\n\n\t var background = Path.fromRect(box.toRect(), {\n\t stroke: {\n\t color: border.width ? border.color : \"\",\n\t width: border.width,\n\t dashType: border.dashType\n\t },\n\t fill: {\n\t color: options.background,\n\t opacity: options.opacity\n\t },\n\t zIndex: -10\n\t });\n\n\t this.visual.append(background);\n\t },\n\n\t getRoot: function() {\n\t return this;\n\t },\n\n\t createGradient: function(options) {\n\t var gradients = this.gradients;\n\t var hashCode = objectKey(options);\n\t var gradient = GRADIENTS[options.gradient];\n\t var drawingGradient;\n\n\t if (gradients[hashCode]) {\n\t drawingGradient = gradients[hashCode];\n\t } else {\n\t var gradientOptions = $.extend({}, gradient, options);\n\t if (gradient.type === \"linear\") {\n\t drawingGradient = new drawing.LinearGradient(gradientOptions);\n\t } else {\n\t if (options.innerRadius) {\n\t gradientOptions.stops = innerRadialStops(gradientOptions);\n\t }\n\t drawingGradient = new drawing.RadialGradient(gradientOptions);\n\t drawingGradient.supportVML = gradient.supportVML !== false;\n\t }\n\t gradients[hashCode] = drawingGradient;\n\t }\n\n\t return drawingGradient;\n\t },\n\n\t cleanGradients: function() {\n\t var gradients = this.gradients;\n\t for (var hashCode in gradients) {\n\t gradients[hashCode]._observers = [];//add clear observers method in drawing ObserversMixin\n\t }\n\t },\n\n\t size: function() {\n\t var options = this.options;\n\t return new Box(0, 0, options.width, options.height);\n\t }\n\t});\n\n\tsetDefaultOptions(RootElement, {\n\t width: DEFAULT_WIDTH,\n\t height: DEFAULT_HEIGHT,\n\t background: WHITE,\n\t border: {\n\t color: BLACK,\n\t width: 0\n\t },\n\t margin: getSpacing(5),\n\t zIndex: -2\n\t});\n\n\tfunction innerRadialStops(options) {\n\t var stops = options.stops;\n\t var usedSpace = ((options.innerRadius / options.radius) * 100);\n\t var length = stops.length;\n\t var currentStops = [];\n\n\t for (var i = 0; i < length; i++) {\n\t var currentStop = $.extend({}, stops[i]);\n\t currentStop.offset = (currentStop.offset * (100 - usedSpace) + usedSpace) / 100;\n\t currentStops.push(currentStop);\n\t }\n\n\t return currentStops;\n\t}\n\n\tvar FloatElement = ChartElement.extend({\n\t init: function(options) {\n\t ChartElement.fn.init.call(this, options);\n\t this._initDirection();\n\t },\n\n\t _initDirection: function() {\n\t var options = this.options;\n\t if (options.vertical) {\n\t this.groupAxis = X;\n\t this.elementAxis = Y;\n\t this.groupSizeField = WIDTH;\n\t this.elementSizeField = HEIGHT;\n\t this.groupSpacing = options.spacing;\n\t this.elementSpacing = options.vSpacing;\n\t } else {\n\t this.groupAxis = Y;\n\t this.elementAxis = X;\n\t this.groupSizeField = HEIGHT;\n\t this.elementSizeField = WIDTH;\n\t this.groupSpacing = options.vSpacing;\n\t this.elementSpacing = options.spacing;\n\t }\n\t },\n\n\t reflow: function(targetBox) {\n\t this.box = targetBox.clone();\n\t this.reflowChildren();\n\t },\n\n\t reflowChildren: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var box = ref.box;\n\t var elementAxis = ref.elementAxis;\n\t var groupAxis = ref.groupAxis;\n\t var elementSizeField = ref.elementSizeField;\n\t var groupSizeField = ref.groupSizeField;\n\t var ref$1 = this.groupOptions();\n\t var groups = ref$1.groups;\n\t var groupsSize = ref$1.groupsSize;\n\t var maxGroupElementsSize = ref$1.maxGroupElementsSize;\n\t var groupsCount = groups.length;\n\t var groupsStart = box[groupAxis + 1] + this.alignStart(groupsSize, box[groupSizeField]());\n\n\t if (groupsCount) {\n\t var groupStart = groupsStart;\n\n\t for (var groupIdx = 0; groupIdx < groupsCount; groupIdx++) {\n\t var group = groups[groupIdx];\n\t var groupElements = group.groupElements;\n\t var elementStart = box[elementAxis + 1];\n\t var groupElementsCount = groupElements.length;\n\n\t for (var idx = 0; idx < groupElementsCount; idx++) {\n\t var element = groupElements[idx];\n\t var elementSize$$1 = this$1.elementSize(element);\n\t var groupElementStart = groupStart + this$1.alignStart(elementSize$$1[groupSizeField], group.groupSize);\n\n\t var elementBox = new Box();\n\t elementBox[groupAxis + 1] = groupElementStart;\n\t elementBox[groupAxis + 2] = groupElementStart + elementSize$$1[groupSizeField];\n\t elementBox[elementAxis + 1] = elementStart;\n\t elementBox[elementAxis + 2] = elementStart + elementSize$$1[elementSizeField];\n\n\t element.reflow(elementBox);\n\n\t elementStart += elementSize$$1[elementSizeField] + this$1.elementSpacing;\n\t }\n\t groupStart += group.groupSize + this$1.groupSpacing;\n\t }\n\t box[groupAxis + 1] = groupsStart;\n\t box[groupAxis + 2] = groupsStart + groupsSize;\n\t box[elementAxis + 2] = box[elementAxis + 1] + maxGroupElementsSize;\n\t }\n\t },\n\n\t alignStart: function(size, maxSize) {\n\t var start = 0;\n\t var align = this.options.align;\n\t if (align === RIGHT || align === BOTTOM) {\n\t start = maxSize - size;\n\t } else if (align === CENTER) {\n\t start = (maxSize - size) / 2;\n\t }\n\t return start;\n\t },\n\n\t groupOptions: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var box = ref.box;\n\t var children = ref.children;\n\t var elementSizeField = ref.elementSizeField;\n\t var groupSizeField = ref.groupSizeField;\n\t var elementSpacing = ref.elementSpacing;\n\t var groupSpacing = ref.groupSpacing;\n\t var maxSize = round(box[elementSizeField]());\n\t var childrenCount = children.length;\n\t var groups = [];\n\n\t var groupSize = 0;\n\t var groupElementsSize = 0;\n\t var groupsSize = 0;\n\t var maxGroupElementsSize = 0;\n\t var groupElements = [];\n\n\t for (var idx = 0; idx < childrenCount; idx++) {\n\t var element = children[idx];\n\t if (!element.box) {\n\t element.reflow(box);\n\t }\n\n\t var elementSize$$1 = this$1.elementSize(element);\n\t if (this$1.options.wrap && round(groupElementsSize + elementSpacing + elementSize$$1[elementSizeField]) > maxSize) {\n\t groups.push({\n\t groupElements: groupElements,\n\t groupSize: groupSize,\n\t groupElementsSize: groupElementsSize\n\t });\n\t maxGroupElementsSize = Math.max(maxGroupElementsSize, groupElementsSize);\n\t groupsSize += groupSpacing + groupSize;\n\t groupSize = 0;\n\t groupElementsSize = 0;\n\t groupElements = [];\n\t }\n\t groupSize = Math.max(groupSize, elementSize$$1[groupSizeField]);\n\t if (groupElementsSize > 0) {\n\t groupElementsSize += elementSpacing;\n\t }\n\t groupElementsSize += elementSize$$1[elementSizeField];\n\t groupElements.push(element);\n\t }\n\n\t groups.push({\n\t groupElements: groupElements,\n\t groupSize: groupSize,\n\t groupElementsSize: groupElementsSize\n\t });\n\t maxGroupElementsSize = Math.max(maxGroupElementsSize, groupElementsSize);\n\t groupsSize += groupSize;\n\n\t return {\n\t groups: groups,\n\t groupsSize: groupsSize,\n\t maxGroupElementsSize: maxGroupElementsSize\n\t };\n\t },\n\n\t elementSize: function(element) {\n\t return {\n\t width: element.box.width(),\n\t height: element.box.height()\n\t };\n\t },\n\n\t createVisual: function() {}\n\t});\n\n\tsetDefaultOptions(FloatElement, {\n\t vertical: true,\n\t wrap: true,\n\t vSpacing: 0,\n\t spacing: 0\n\t});\n\n\tvar DrawingText = drawing.Text;\n\n\tvar Text = ChartElement.extend({\n\t init: function(content, options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.content = content;\n\n\t // Calculate size\n\t this.reflow(new Box());\n\t },\n\n\t reflow: function(targetBox) {\n\t var options = this.options;\n\t var size = options.size = util.measureText(this.content, { font: options.font });\n\n\t this.baseline = size.baseline;\n\n\t this.box = new Box(targetBox.x1, targetBox.y1,\n\t targetBox.x1 + size.width, targetBox.y1 + size.height);\n\t },\n\n\t createVisual: function() {\n\t var ref = this.options;\n\t var font = ref.font;\n\t var color = ref.color;\n\t var opacity = ref.opacity;\n\t var cursor = ref.cursor;\n\n\t this.visual = new DrawingText(this.content, this.box.toRect().topLeft(), {\n\t font: font,\n\t fill: { color: color, opacity: opacity },\n\t cursor: cursor\n\t });\n\t }\n\t});\n\n\tsetDefaultOptions(Text, {\n\t font: DEFAULT_FONT,\n\t color: BLACK\n\t});\n\n\tfunction rectToBox(rect) {\n\t var origin = rect.origin;\n\t var bottomRight = rect.bottomRight();\n\n\t return new Box(origin.x, origin.y, bottomRight.x, bottomRight.y);\n\t}\n\n\tvar ROWS_SPLIT_REGEX = /\\n/m;\n\n\tvar TextBox = BoxElement.extend({\n\t init: function(content, options, data) {\n\t BoxElement.fn.init.call(this, options);\n\t this.content = content;\n\t this.data = data;\n\n\t this._initContainer();\n\t if (this.options._autoReflow !== false) {\n\t this.reflow(new Box());\n\t }\n\t },\n\n\t _initContainer: function() {\n\t var options = this.options;\n\t var rows = String(this.content).split(ROWS_SPLIT_REGEX);\n\t var floatElement = new FloatElement({ vertical: true, align: options.align, wrap: false });\n\t var textOptions = deepExtend({ }, options, { opacity: 1, animation: null });\n\n\t this.container = floatElement;\n\t this.append(floatElement);\n\n\t for (var rowIdx = 0; rowIdx < rows.length; rowIdx++) {\n\t var text = new Text(rows[rowIdx].trim(), textOptions);\n\t floatElement.append(text);\n\t }\n\t },\n\n\t reflow: function(targetBox) {\n\t var options = this.options;\n\t var visualFn = options.visual;\n\t this.container.options.align = options.align;\n\n\t if (visualFn && !this._boxReflow) {\n\t var visualBox = targetBox;\n\t if (!visualBox.hasSize()) {\n\t this._boxReflow = true;\n\t this.reflow(visualBox);\n\t this._boxReflow = false;\n\t visualBox = this.box;\n\t }\n\t var visual = this.visual = visualFn(this.visualContext(visualBox));\n\n\t if (visual) {\n\t visualBox = rectToBox(visual.clippedBBox() || new Rect());\n\n\t visual.options.zIndex = options.zIndex;\n\t }\n\n\t this.box = this.contentBox = this.paddingBox = visualBox;\n\t } else {\n\t BoxElement.fn.reflow.call(this, targetBox);\n\n\t if (options.rotation) {\n\t var margin = getSpacing(options.margin);\n\t var box = this.box.unpad(margin);\n\n\t this.targetBox = targetBox;\n\t this.normalBox = box.clone();\n\n\t box = this.rotate();\n\t box.translate(margin.left - margin.right, margin.top - margin.bottom);\n\n\t this.rotatedBox = box.clone();\n\n\t box.pad(margin);\n\t }\n\t }\n\t },\n\n\t createVisual: function() {\n\t var options = this.options;\n\n\t this.visual = new Group({\n\t transform: this.rotationTransform(),\n\t zIndex: options.zIndex,\n\t noclip: options.noclip\n\t });\n\n\t if (this.hasBox()) {\n\t var box = Path.fromRect(this.paddingBox.toRect(), this.visualStyle());\n\t this.visual.append(box);\n\t }\n\t },\n\n\t renderVisual: function() {\n\t if (!this.options.visible) {\n\t return;\n\t }\n\n\t if (this.options.visual) {\n\t var visual = this.visual;\n\t if (visual && !defined(visual.options.noclip)) {\n\t visual.options.noclip = this.options.noclip;\n\t }\n\t this.addVisual();\n\t this.createAnimation();\n\t } else {\n\t BoxElement.fn.renderVisual.call(this);\n\t }\n\t },\n\n\t visualContext: function(targetBox) {\n\t var this$1 = this;\n\n\t var context = {\n\t text: this.content,\n\t rect: targetBox.toRect(),\n\t sender: this.getSender(),\n\t options: this.options,\n\t createVisual: function () {\n\t this$1._boxReflow = true;\n\t this$1.reflow(targetBox);\n\t this$1._boxReflow = false;\n\t return this$1.getDefaultVisual();\n\t }\n\t };\n\t if (this.data) {\n\t $.extend(context, this.data);\n\t }\n\n\t return context;\n\t },\n\n\t getDefaultVisual: function() {\n\t this.createVisual();\n\t this.renderChildren();\n\t var visual = this.visual;\n\t delete this.visual;\n\t return visual;\n\t },\n\n\t rotate: function() {\n\t var options = this.options;\n\t this.box.rotate(options.rotation);\n\t this.align(this.targetBox, X, options.align);\n\t this.align(this.targetBox, Y, options.vAlign);\n\t return this.box;\n\t },\n\n\t rotationTransform: function() {\n\t var rotation = this.options.rotation;\n\t if (!rotation) {\n\t return null;\n\t }\n\n\t var ref = this.normalBox.center();\n\t var cx = ref.x;\n\t var cy = ref.y;\n\t var boxCenter = this.rotatedBox.center();\n\n\t return geometryTransform()\n\t .translate(boxCenter.x - cx, boxCenter.y - cy)\n\t .rotate(rotation, [ cx, cy ]);\n\t }\n\t});\n\n\tvar Title = ChartElement.extend({\n\t init: function(options) {\n\t ChartElement.fn.init.call(this, options);\n\n\t this.append(\n\t new TextBox(this.options.text, $.extend({}, this.options, {\n\t vAlign: this.options.position\n\t }))\n\t );\n\t },\n\n\t reflow: function(targetBox) {\n\t ChartElement.fn.reflow.call(this, targetBox);\n\t this.box.snapTo(targetBox, X);\n\t }\n\t});\n\n\tTitle.buildTitle = function(options, parent, defaultOptions) {\n\t var titleOptions = options;\n\n\t if (typeof options === \"string\") {\n\t titleOptions = { text: options };\n\t }\n\n\t titleOptions = $.extend({ visible: true }, defaultOptions, titleOptions);\n\n\t var title;\n\t if (titleOptions && titleOptions.visible && titleOptions.text) {\n\t title = new Title(titleOptions);\n\t parent.append(title);\n\t }\n\n\t return title;\n\t};\n\n\tsetDefaultOptions(Title, {\n\t color: BLACK,\n\t position: TOP,\n\t align: CENTER,\n\t margin: getSpacing(5),\n\t padding: getSpacing(5)\n\t});\n\n\tvar AxisLabel = TextBox.extend({\n\t init: function(value, text, index, dataItem, options) {\n\t TextBox.fn.init.call(this, text, options);\n\n\t this.text = text;\n\t this.value = value;\n\t this.index = index;\n\t this.dataItem = dataItem;\n\t this.reflow(new Box());\n\t },\n\n\t visualContext: function(targetBox) {\n\t var context = TextBox.fn.visualContext.call(this, targetBox);\n\n\t context.value = this.value;\n\t context.dataItem = this.dataItem;\n\t context.format = this.options.format;\n\t context.culture = this.options.culture;\n\n\t return context;\n\t },\n\n\t click: function(widget, e) {\n\n\t widget.trigger(AXIS_LABEL_CLICK, {\n\t element: eventElement(e),\n\t value: this.value,\n\t text: this.text,\n\t index: this.index,\n\t dataItem: this.dataItem,\n\t axis: this.parent.options\n\t });\n\t },\n\n\t rotate: function() {\n\t if (this.options.alignRotation !== CENTER) {\n\t var box = this.normalBox.toRect();\n\t var transform = this.rotationTransform();\n\n\t this.box = rectToBox(box.bbox(transform.matrix()));\n\t } else {\n\t TextBox.fn.rotate.call(this);\n\t }\n\n\t return this.box;\n\t },\n\n\t rotationTransform: function() {\n\t var options = this.options;\n\t var rotation = options.rotation;\n\t if (!rotation) {\n\t return null;\n\t }\n\n\t if (options.alignRotation === CENTER) {\n\t return TextBox.fn.rotationTransform.call(this);\n\t }\n\n\t var rotationMatrix = geometryTransform().rotate(rotation).matrix();\n\t var box = this.normalBox.toRect();\n\t var rect = this.targetBox.toRect();\n\n\t var rotationOrigin = options.rotationOrigin || TOP;\n\t var alignAxis = rotationOrigin === TOP || rotationOrigin === BOTTOM ? X : Y;\n\t var distanceAxis = rotationOrigin === TOP || rotationOrigin === BOTTOM ? Y : X;\n\t var axisAnchor = rotationOrigin === TOP || rotationOrigin === LEFT ? rect.origin : rect.bottomRight();\n\n\t var topLeft = box.topLeft().transformCopy(rotationMatrix);\n\t var topRight = box.topRight().transformCopy(rotationMatrix);\n\t var bottomRight = box.bottomRight().transformCopy(rotationMatrix);\n\t var bottomLeft = box.bottomLeft().transformCopy(rotationMatrix);\n\t var rotatedBox = Rect.fromPoints(topLeft, topRight, bottomRight, bottomLeft);\n\n\t var translate = {};\n\t translate[distanceAxis] = rect.origin[distanceAxis] - rotatedBox.origin[distanceAxis];\n\n\t var distanceLeft = Math.abs(topLeft[distanceAxis] + translate[distanceAxis] - axisAnchor[distanceAxis]);\n\t var distanceRight = Math.abs(topRight[distanceAxis] + translate[distanceAxis] - axisAnchor[distanceAxis]);\n\n\t var alignStart, alignEnd;\n\n\t if (round(distanceLeft, DEFAULT_PRECISION) === round(distanceRight, DEFAULT_PRECISION)) {\n\t alignStart = topLeft;\n\t alignEnd = topRight;\n\t } else if (distanceRight < distanceLeft) {\n\t alignStart = topRight;\n\t alignEnd = bottomRight;\n\t } else {\n\t alignStart = topLeft;\n\t alignEnd = bottomLeft;\n\t }\n\n\t var alignCenter = alignStart[alignAxis] + (alignEnd[alignAxis] - alignStart[alignAxis]) / 2;\n\t translate[alignAxis] = rect.center()[alignAxis] - alignCenter;\n\n\t return geometryTransform()\n\t .translate(translate.x, translate.y)\n\t .rotate(rotation);\n\t }\n\t});\n\n\tsetDefaultOptions(AxisLabel, {\n\t _autoReflow: false\n\t});\n\n\tvar DEFAULT_ICON_SIZE = 7;\n\tvar DEFAULT_LABEL_COLOR = \"#fff\";\n\n\tvar Note = BoxElement.extend({\n\t init: function(fields, options, chartService) {\n\t BoxElement.fn.init.call(this, options);\n\n\t this.fields = fields;\n\t this.chartService = chartService;\n\n\t this.render();\n\t },\n\n\t hide: function() {\n\t this.options.visible = false;\n\t },\n\n\t show: function() {\n\t this.options.visible = true;\n\t },\n\n\t render: function() {\n\t var this$1 = this;\n\n\t var options = this.options;\n\n\t if (options.visible) {\n\t var label = options.label;\n\t var icon = options.icon;\n\t var box = new Box();\n\t var childAlias = function () { return this$1; };\n\t var size = icon.size;\n\t var text = this.fields.text;\n\t var width, height;\n\n\t if (defined(label) && label.visible) {\n\t var noteTemplate = getTemplate(label);\n\t if (noteTemplate) {\n\t text = noteTemplate(this.fields);\n\t } else if (label.format) {\n\t text = this.chartService.format.auto(label.format, text);\n\t }\n\n\t if (!label.color) {\n\t label.color = label.position === INSIDE ? DEFAULT_LABEL_COLOR : icon.background;\n\t }\n\n\t this.label = new TextBox(text, deepExtend({}, label));\n\t this.label.aliasFor = childAlias;\n\n\t if (label.position === INSIDE && !defined(size)) {\n\t if (icon.type === CIRCLE) {\n\t size = Math.max(this.label.box.width(), this.label.box.height());\n\t } else {\n\t width = this.label.box.width();\n\t height = this.label.box.height();\n\t }\n\t box.wrap(this.label.box);\n\t }\n\t }\n\n\t icon.width = width || size || DEFAULT_ICON_SIZE;\n\t icon.height = height || size || DEFAULT_ICON_SIZE;\n\n\t var marker = new ShapeElement(deepExtend({}, icon));\n\t marker.aliasFor = childAlias;\n\n\t this.marker = marker;\n\t this.append(marker);\n\n\t if (this.label) {\n\t this.append(this.label);\n\t }\n\n\t marker.reflow(new Box());\n\t this.wrapperBox = box.wrap(marker.box);\n\t }\n\t },\n\n\t reflow: function(targetBox) {\n\t var ref = this;\n\t var options = ref.options;\n\t var label = ref.label;\n\t var marker = ref.marker;\n\t var wrapperBox = ref.wrapperBox;\n\t var center = targetBox.center();\n\t var length = options.line.length;\n\t var position = options.position;\n\n\t // TODO: Review\n\t if (options.visible) {\n\t var lineStart, box, contentBox;\n\n\t if (inArray(position, [ LEFT, RIGHT ])) {\n\t if (position === LEFT) {\n\t contentBox = wrapperBox.alignTo(targetBox, position).translate(-length, targetBox.center().y - wrapperBox.center().y);\n\n\t if (options.line.visible) {\n\t lineStart = [ targetBox.x1, center.y ];\n\t this.linePoints = [\n\t lineStart,\n\t [ contentBox.x2, center.y ]\n\t ];\n\t box = contentBox.clone().wrapPoint(lineStart);\n\t }\n\t } else {\n\t contentBox = wrapperBox.alignTo(targetBox, position).translate(length, targetBox.center().y - wrapperBox.center().y);\n\n\t if (options.line.visible) {\n\t lineStart = [ targetBox.x2, center.y ];\n\t this.linePoints = [\n\t lineStart,\n\t [ contentBox.x1, center.y ]\n\t ];\n\t box = contentBox.clone().wrapPoint(lineStart);\n\t }\n\t }\n\t } else {\n\t if (position === BOTTOM) {\n\t contentBox = wrapperBox.alignTo(targetBox, position).translate(targetBox.center().x - wrapperBox.center().x, length);\n\n\t if (options.line.visible) {\n\t lineStart = [ center.x, targetBox.y2 ];\n\t this.linePoints = [\n\t lineStart,\n\t [ center.x, contentBox.y1 ]\n\t ];\n\t box = contentBox.clone().wrapPoint(lineStart);\n\t }\n\t } else {\n\t contentBox = wrapperBox.alignTo(targetBox, position).translate(targetBox.center().x - wrapperBox.center().x, -length);\n\n\t if (options.line.visible) {\n\t lineStart = [ center.x, targetBox.y1 ];\n\t this.linePoints = [\n\t lineStart,\n\t [ center.x, contentBox.y2 ]\n\t ];\n\t box = contentBox.clone().wrapPoint(lineStart);\n\t }\n\t }\n\t }\n\n\t if (marker) {\n\t marker.reflow(contentBox);\n\t }\n\n\t if (label) {\n\t label.reflow(contentBox);\n\t if (marker) {\n\t if (options.label.position === OUTSIDE) {\n\t label.box.alignTo(marker.box, position);\n\t }\n\t label.reflow(label.box);\n\t }\n\t }\n\n\t this.contentBox = contentBox;\n\t this.targetBox = targetBox;\n\t this.box = box || contentBox;\n\t }\n\t },\n\n\t createVisual: function() {\n\t BoxElement.fn.createVisual.call(this);\n\t this.visual.options.noclip = this.options.noclip;\n\n\t if (this.options.visible) {\n\t this.createLine();\n\t }\n\t },\n\n\t renderVisual: function() {\n\t var this$1 = this;\n\n\t var options = this.options;\n\t var customVisual = options.visual;\n\t if (options.visible && customVisual) {\n\t this.visual = customVisual($.extend(this.fields, {\n\t sender: this.getSender(),\n\t rect: this.targetBox.toRect(),\n\t options: {\n\t background: options.background,\n\t border: options.background,\n\t icon: options.icon,\n\t label: options.label,\n\t line: options.line,\n\t position: options.position,\n\t visible: options.visible\n\t },\n\t createVisual: function () {\n\t this$1.createVisual();\n\t this$1.renderChildren();\n\t var defaultVisual = this$1.visual;\n\t delete this$1.visual;\n\t return defaultVisual;\n\t }\n\t }));\n\t this.addVisual();\n\t } else {\n\t BoxElement.fn.renderVisual.call(this);\n\t }\n\t },\n\n\t createLine: function() {\n\t var options = this.options.line;\n\n\t if (this.linePoints) {\n\t var path = Path.fromPoints(this.linePoints, {\n\t stroke: {\n\t color: options.color,\n\t width: options.width,\n\t dashType: options.dashType\n\t }\n\t });\n\n\t alignPathToPixel(path);\n\t this.visual.append(path);\n\t }\n\t },\n\n\t click: function(widget, e) {\n\t var args = this.eventArgs(e);\n\n\t if (!widget.trigger(NOTE_CLICK, args)) {\n\t e.preventDefault();\n\t }\n\t },\n\n\t over: function(widget, e) {\n\t var args = this.eventArgs(e);\n\n\t if (!widget.trigger(NOTE_HOVER, args)) {\n\t e.preventDefault();\n\t }\n\t },\n\n\t out: function(widget, e) {\n\t var args = this.eventArgs(e);\n\n\t widget.trigger(NOTE_LEAVE, args);\n\t },\n\n\t eventArgs: function(e) {\n\t var options = this.options;\n\n\t return $.extend(this.fields, {\n\t element: eventElement(e),\n\t text: defined(options.label) ? options.label.text : \"\",\n\t visual: this.visual\n\t });\n\t }\n\t});\n\n\tsetDefaultOptions(Note, {\n\t icon: {\n\t visible: true,\n\t type: CIRCLE\n\t },\n\t label: {\n\t position: INSIDE,\n\t visible: true,\n\t align: CENTER,\n\t vAlign: CENTER\n\t },\n\t line: {\n\t visible: true\n\t },\n\t visible: true,\n\t position: TOP,\n\t zIndex: 2\n\t});\n\n\tfunction createAxisTick(options, tickOptions) {\n\t var tickX = options.tickX;\n\t var tickY = options.tickY;\n\t var position = options.position;\n\n\t var tick = new Path({\n\t stroke: {\n\t width: tickOptions.width,\n\t color: tickOptions.color\n\t }\n\t });\n\n\t if (options.vertical) {\n\t tick.moveTo(tickX, position)\n\t .lineTo(tickX + tickOptions.size, position);\n\t } else {\n\t tick.moveTo(position, tickY)\n\t .lineTo(position, tickY + tickOptions.size);\n\t }\n\n\t alignPathToPixel(tick);\n\n\t return tick;\n\t}\n\n\tfunction createAxisGridLine(options, gridLine) {\n\t var lineStart = options.lineStart;\n\t var lineEnd = options.lineEnd;\n\t var position = options.position;\n\n\t var line = new Path({\n\t stroke: {\n\t width: gridLine.width,\n\t color: gridLine.color,\n\t dashType: gridLine.dashType\n\t }\n\t });\n\n\t if (options.vertical) {\n\t line.moveTo(lineStart, position)\n\t .lineTo(lineEnd, position);\n\t } else {\n\t line.moveTo(position, lineStart)\n\t .lineTo(position, lineEnd);\n\t }\n\n\t alignPathToPixel(line);\n\n\t return line;\n\t}\n\n\tvar Axis = ChartElement.extend({\n\t init: function(options, chartService) {\n\t if (chartService === void 0) { chartService = new ChartService(); }\n\n\t ChartElement.fn.init.call(this, options);\n\n\t this.chartService = chartService;\n\n\t if (!this.options.visible) {\n\t this.options = deepExtend({}, this.options, {\n\t labels: {\n\t visible: false\n\t },\n\t line: {\n\t visible: false\n\t },\n\t margin: 0,\n\t majorTickSize: 0,\n\t minorTickSize: 0\n\t });\n\t }\n\n\t this.options.minorTicks = deepExtend({}, {\n\t color: this.options.line.color,\n\t width: this.options.line.width,\n\t visible: this.options.minorTickType !== NONE\n\t }, this.options.minorTicks, {\n\t size: this.options.minorTickSize,\n\t align: this.options.minorTickType\n\t });\n\n\t this.options.majorTicks = deepExtend({}, {\n\t color: this.options.line.color,\n\t width: this.options.line.width,\n\t visible: this.options.majorTickType !== NONE\n\t }, this.options.majorTicks, {\n\t size: this.options.majorTickSize,\n\t align: this.options.majorTickType\n\t });\n\n\t this.initFields();\n\n\t if (!this.options._deferLabels) {\n\t this.createLabels();\n\t }\n\n\t this.createTitle();\n\t this.createNotes();\n\t },\n\n\t initFields: function() {\n\t },\n\n\t labelsRange: function() {\n\t return {\n\t min: this.options.labels.skip,\n\t max: this.labelsCount()\n\t };\n\t },\n\n\t createLabels: function() {\n\t var this$1 = this;\n\n\t var options = this.options;\n\t var align = options.vertical ? RIGHT : CENTER;\n\t var labelOptions = deepExtend({ }, options.labels, {\n\t align: align,\n\t zIndex: options.zIndex\n\t });\n\t var step = Math.max(1, labelOptions.step);\n\n\t this.clearLabels();\n\n\t if (labelOptions.visible) {\n\t var range = this.labelsRange();\n\t var rotation = labelOptions.rotation;\n\n\t if (isObject(rotation)) {\n\t labelOptions.alignRotation = rotation.align;\n\t labelOptions.rotation = rotation.angle;\n\t }\n\n\t if (labelOptions.rotation === \"auto\") {\n\t labelOptions.rotation = 0;\n\t options.autoRotateLabels = true;\n\t }\n\n\t for (var idx = range.min; idx < range.max; idx += step) {\n\t var label = this$1.createAxisLabel(idx, labelOptions);\n\t if (label) {\n\t this$1.append(label);\n\t this$1.labels.push(label);\n\t }\n\t }\n\t }\n\t },\n\n\t clearLabels: function() {\n\t this.children = grep(this.children, function (child) { return !(child instanceof AxisLabel); });\n\t this.labels = [];\n\t },\n\n\t clearTitle: function() {\n\t var this$1 = this;\n\n\t if (this.title) {\n\t this.children = grep(this.children, function (child) { return child !== this$1.title; });\n\t this.title = undefined;\n\t }\n\t },\n\n\t clear: function() {\n\t this.clearLabels();\n\t this.clearTitle();\n\t },\n\n\t lineBox: function() {\n\t var ref = this;\n\t var options = ref.options;\n\t var box = ref.box;\n\t var vertical = options.vertical;\n\t var mirror = options.labels.mirror;\n\t var axisX = mirror ? box.x1 : box.x2;\n\t var axisY = mirror ? box.y2 : box.y1;\n\t var lineWidth = options.line.width || 0;\n\n\t return vertical ?\n\t new Box(axisX, box.y1, axisX, box.y2 - lineWidth) :\n\t new Box(box.x1, axisY, box.x2 - lineWidth, axisY);\n\t },\n\n\t createTitle: function() {\n\t var options = this.options;\n\t var titleOptions = deepExtend({\n\t rotation: options.vertical ? -90 : 0,\n\t text: \"\",\n\t zIndex: 1,\n\t visualSize: true\n\t }, options.title);\n\n\t if (titleOptions.visible && titleOptions.text) {\n\t var title = new TextBox(titleOptions.text, titleOptions);\n\t this.append(title);\n\t this.title = title;\n\t }\n\t },\n\n\t createNotes: function() {\n\t var this$1 = this;\n\n\t var options = this.options;\n\t var notes = options.notes;\n\t var items = notes.data || [];\n\n\t this.notes = [];\n\n\t for (var i = 0; i < items.length; i++) {\n\t var item = deepExtend({}, notes, items[i]);\n\t item.value = this$1.parseNoteValue(item.value);\n\n\t var note = new Note({\n\t value: item.value,\n\t text: item.label.text,\n\t dataItem: item\n\t }, item, this$1.chartService);\n\n\t if (note.options.visible) {\n\t if (defined(note.options.position)) {\n\t if (options.vertical && !inArray(note.options.position, [ LEFT, RIGHT ])) {\n\t note.options.position = options.reverse ? LEFT : RIGHT;\n\t } else if (!options.vertical && !inArray(note.options.position, [ TOP, BOTTOM ])) {\n\t note.options.position = options.reverse ? BOTTOM : TOP;\n\t }\n\t } else {\n\t if (options.vertical) {\n\t note.options.position = options.reverse ? LEFT : RIGHT;\n\t } else {\n\t note.options.position = options.reverse ? BOTTOM : TOP;\n\t }\n\t }\n\t this$1.append(note);\n\t this$1.notes.push(note);\n\t }\n\t }\n\t },\n\n\t parseNoteValue: function(value) {\n\t return value;\n\t },\n\n\t renderVisual: function() {\n\t ChartElement.fn.renderVisual.call(this);\n\n\t this.createPlotBands();\n\t },\n\n\t createVisual: function() {\n\t ChartElement.fn.createVisual.call(this);\n\n\t this.createBackground();\n\t this.createLine();\n\t },\n\n\t gridLinesVisual: function() {\n\t var gridLines = this._gridLines;\n\t if (!gridLines) {\n\t gridLines = this._gridLines = new Group({\n\t zIndex: -2\n\t });\n\t this.appendVisual(this._gridLines);\n\t }\n\n\t return gridLines;\n\t },\n\n\t createTicks: function(lineGroup) {\n\t var options = this.options;\n\t var lineBox = this.lineBox();\n\t var mirror = options.labels.mirror;\n\t var majorUnit = options.majorTicks.visible ? options.majorUnit : 0;\n\t var tickLineOptions = {\n\t // TODO\n\t // _alignLines: options._alignLines,\n\t vertical: options.vertical\n\t };\n\n\t function render(tickPositions, tickOptions, skipUnit) {\n\t var count = tickPositions.length;\n\t var step = Math.max(1, tickOptions.step);\n\n\t if (tickOptions.visible) {\n\t for (var i = tickOptions.skip; i < count; i += step) {\n\t if (defined(skipUnit) && (i % skipUnit === 0)) {\n\t continue;\n\t }\n\n\t tickLineOptions.tickX = mirror ? lineBox.x2 : lineBox.x2 - tickOptions.size;\n\t tickLineOptions.tickY = mirror ? lineBox.y1 - tickOptions.size : lineBox.y1;\n\t tickLineOptions.position = tickPositions[i];\n\n\t lineGroup.append(createAxisTick(tickLineOptions, tickOptions));\n\t }\n\t }\n\t }\n\n\t render(this.getMajorTickPositions(), options.majorTicks);\n\t render(this.getMinorTickPositions(), options.minorTicks, majorUnit / options.minorUnit);\n\t },\n\n\t createLine: function() {\n\t var options = this.options;\n\t var line = options.line;\n\t var lineBox = this.lineBox();\n\n\t if (line.width > 0 && line.visible) {\n\t var path = new Path({\n\t stroke: {\n\t width: line.width,\n\t color: line.color,\n\t dashType: line.dashType\n\t }\n\n\t /* TODO\n\t zIndex: line.zIndex,\n\t */\n\t });\n\n\t path.moveTo(lineBox.x1, lineBox.y1)\n\t .lineTo(lineBox.x2, lineBox.y2);\n\n\t if (options._alignLines) {\n\t alignPathToPixel(path);\n\t }\n\n\t var group = this._lineGroup = new Group();\n\t group.append(path);\n\n\t this.visual.append(group);\n\t this.createTicks(group);\n\t }\n\t },\n\n\t getActualTickSize: function() {\n\t var options = this.options;\n\t var tickSize = 0;\n\n\t if (options.majorTicks.visible && options.minorTicks.visible) {\n\t tickSize = Math.max(options.majorTicks.size, options.minorTicks.size);\n\t } else if (options.majorTicks.visible) {\n\t tickSize = options.majorTicks.size;\n\t } else if (options.minorTicks.visible) {\n\t tickSize = options.minorTicks.size;\n\t }\n\n\t return tickSize;\n\t },\n\n\t createBackground: function() {\n\t var ref = this;\n\t var options = ref.options;\n\t var box = ref.box;\n\t var background = options.background;\n\n\t if (background) {\n\t this._backgroundPath = Path.fromRect(box.toRect(), {\n\t fill: {\n\t color: background\n\t },\n\t stroke: null\n\t });\n\n\t this.visual.append(this._backgroundPath);\n\t }\n\t },\n\n\t createPlotBands: function() {\n\t var this$1 = this;\n\n\t var options = this.options;\n\t var plotBands = options.plotBands || [];\n\t var vertical = options.vertical;\n\t var plotArea = this.plotArea;\n\n\t if (plotBands.length === 0) {\n\t return;\n\t }\n\n\t var group = this._plotbandGroup = new Group({\n\t zIndex: -1\n\t });\n\n\t var altAxis = grep(this.pane.axes, function (axis) { return axis.options.vertical !== this$1.options.vertical; })[0];\n\n\t for (var idx = 0; idx < plotBands.length; idx++) {\n\t var item = plotBands[idx];\n\t var slotX = (void 0), slotY = (void 0);\n\n\t if (vertical) {\n\t slotX = (altAxis || plotArea.axisX).lineBox();\n\t slotY = this$1.getSlot(item.from, item.to, true);\n\t } else {\n\t slotX = this$1.getSlot(item.from, item.to, true);\n\t slotY = (altAxis || plotArea.axisY).lineBox();\n\t }\n\n\t if (slotX.width() !== 0 && slotY.height() !== 0) {\n\t var bandRect = new Rect(\n\t [ slotX.x1, slotY.y1 ],\n\t [ slotX.width(), slotY.height() ]\n\t );\n\n\t var path = Path.fromRect(bandRect, {\n\t fill: {\n\t color: item.color,\n\t opacity: item.opacity\n\t },\n\t stroke: null\n\t });\n\n\t group.append(path);\n\t }\n\t }\n\n\t this.appendVisual(group);\n\t },\n\n\t createGridLines: function(altAxis) {\n\t var options = this.options;\n\t var minorGridLines = options.minorGridLines;\n\t var majorGridLines = options.majorGridLines;\n\t var minorUnit = options.minorUnit;\n\t var vertical = options.vertical;\n\t var axisLineVisible = altAxis.options.line.visible;\n\t var majorUnit = majorGridLines.visible ? options.majorUnit : 0;\n\t var lineBox = altAxis.lineBox();\n\t var linePos = lineBox[vertical ? \"y1\" : \"x1\"];\n\t var lineOptions = {\n\t lineStart: lineBox[vertical ? \"x1\" : \"y1\"],\n\t lineEnd: lineBox[vertical ? \"x2\" : \"y2\"],\n\t vertical: vertical\n\t };\n\t var majorTicks = [];\n\n\t var container = this.gridLinesVisual();\n\n\t function render(tickPositions, gridLine, skipUnit) {\n\t var count = tickPositions.length;\n\t var step = Math.max(1, gridLine.step);\n\n\t if (gridLine.visible) {\n\t for (var i = gridLine.skip; i < count; i += step) {\n\t var pos = round(tickPositions[i]);\n\t if (!inArray(pos, majorTicks)) {\n\t if (i % skipUnit !== 0 && (!axisLineVisible || linePos !== pos)) {\n\t lineOptions.position = pos;\n\t container.append(createAxisGridLine(lineOptions, gridLine));\n\n\t majorTicks.push(pos);\n\t }\n\t }\n\t }\n\t }\n\t }\n\n\t render(this.getMajorTickPositions(), majorGridLines);\n\t render(this.getMinorTickPositions(), minorGridLines, majorUnit / minorUnit);\n\n\t return container.children;\n\t },\n\n\t reflow: function(box) {\n\t var ref = this;\n\t var options = ref.options;\n\t var labels = ref.labels;\n\t var title = ref.title;\n\t var vertical = options.vertical;\n\t var count = labels.length;\n\t var sizeFn = vertical ? WIDTH : HEIGHT;\n\t var titleSize = title ? title.box[sizeFn]() : 0;\n\t var space = this.getActualTickSize() + options.margin + titleSize;\n\t var rootBox = (this.getRoot() || {}).box || box;\n\t var boxSize = rootBox[sizeFn]();\n\t var maxLabelSize = 0;\n\n\t for (var i = 0; i < count; i++) {\n\t var labelSize = labels[i].box[sizeFn]();\n\t if (labelSize + space <= boxSize) {\n\t maxLabelSize = Math.max(maxLabelSize, labelSize);\n\t }\n\t }\n\n\t if (vertical) {\n\t this.box = new Box(\n\t box.x1, box.y1,\n\t box.x1 + maxLabelSize + space, box.y2\n\t );\n\t } else {\n\t this.box = new Box(\n\t box.x1, box.y1,\n\t box.x2, box.y1 + maxLabelSize + space\n\t );\n\t }\n\n\t this.arrangeTitle();\n\t this.arrangeLabels();\n\t this.arrangeNotes();\n\t },\n\n\t getLabelsTickPositions: function() {\n\t return this.getMajorTickPositions();\n\t },\n\n\t labelTickIndex: function(label) {\n\t return label.index;\n\t },\n\n\t arrangeLabels: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var options = ref.options;\n\t var labels = ref.labels;\n\t var labelsBetweenTicks = this.labelsBetweenTicks();\n\t var vertical = options.vertical;\n\t var lineBox = this.lineBox();\n\t var mirror = options.labels.mirror;\n\t var tickPositions = this.getLabelsTickPositions();\n\t var labelOffset = this.getActualTickSize() + options.margin;\n\n\t for (var idx = 0; idx < labels.length; idx++) {\n\t var label = labels[idx];\n\t var tickIx = this$1.labelTickIndex(label);\n\t var labelSize = vertical ? label.box.height() : label.box.width();\n\t var labelPos = tickPositions[tickIx] - (labelSize / 2);\n\t var labelBox = (void 0), firstTickPosition = (void 0), nextTickPosition = (void 0);\n\n\t if (vertical) {\n\t if (labelsBetweenTicks) {\n\t firstTickPosition = tickPositions[tickIx];\n\t nextTickPosition = tickPositions[tickIx + 1];\n\n\t var middle = firstTickPosition + (nextTickPosition - firstTickPosition) / 2;\n\t labelPos = middle - (labelSize / 2);\n\t }\n\n\t var labelX = lineBox.x2;\n\n\t if (mirror) {\n\t labelX += labelOffset;\n\t label.options.rotationOrigin = LEFT;\n\t } else {\n\t labelX -= labelOffset + label.box.width();\n\t label.options.rotationOrigin = RIGHT;\n\t }\n\n\t labelBox = label.box.move(labelX, labelPos);\n\t } else {\n\t if (labelsBetweenTicks) {\n\t firstTickPosition = tickPositions[tickIx];\n\t nextTickPosition = tickPositions[tickIx + 1];\n\t } else {\n\t firstTickPosition = labelPos;\n\t nextTickPosition = labelPos + labelSize;\n\t }\n\n\t var labelY = lineBox.y1;\n\n\t if (mirror) {\n\t labelY -= labelOffset + label.box.height();\n\t label.options.rotationOrigin = BOTTOM;\n\t } else {\n\t labelY += labelOffset;\n\t label.options.rotationOrigin = TOP;\n\t }\n\n\t labelBox = new Box(firstTickPosition, labelY,\n\t nextTickPosition, labelY + label.box.height());\n\t }\n\n\t label.reflow(labelBox);\n\t }\n\t },\n\n\t autoRotateLabels: function() {\n\t if (this.options.autoRotateLabels && !this.options.vertical) {\n\t var tickPositions = this.getMajorTickPositions();\n\t var labels = this.labels;\n\t var angle;\n\n\t for (var idx = 0; idx < labels.length; idx++) {\n\t var width = Math.abs(tickPositions[idx + 1] - tickPositions[idx]);\n\t var labelBox = labels[idx].box;\n\n\t if (labelBox.width() > width) {\n\t if (labelBox.height() > width) {\n\t angle = -90;\n\t break;\n\t }\n\t angle = -45;\n\t }\n\t }\n\n\t if (angle) {\n\t for (var idx$1 = 0; idx$1 < labels.length; idx$1++) {\n\t labels[idx$1].options.rotation = angle;\n\t labels[idx$1].reflow(new Box());\n\t }\n\t return true;\n\t }\n\t }\n\t },\n\n\t arrangeTitle: function() {\n\t var ref = this;\n\t var options = ref.options;\n\t var title = ref.title;\n\t var mirror = options.labels.mirror;\n\t var vertical = options.vertical;\n\n\t if (title) {\n\t if (vertical) {\n\t title.options.align = mirror ? RIGHT : LEFT;\n\t title.options.vAlign = title.options.position;\n\t } else {\n\t title.options.align = title.options.position;\n\t title.options.vAlign = mirror ? TOP : BOTTOM;\n\t }\n\n\t title.reflow(this.box);\n\t }\n\t },\n\n\t arrangeNotes: function() {\n\t var this$1 = this;\n\n\t for (var idx = 0; idx < this.notes.length; idx++) {\n\t var item = this$1.notes[idx];\n\t var value = item.options.value;\n\t var slot = (void 0);\n\n\t if (defined(value)) {\n\t if (this$1.shouldRenderNote(value)) {\n\t item.show();\n\t } else {\n\t item.hide();\n\t }\n\n\t slot = this$1.noteSlot(value);\n\t } else {\n\t item.hide();\n\t }\n\n\t item.reflow(slot || this$1.lineBox());\n\t }\n\t },\n\n\t noteSlot: function(value) {\n\t return this.getSlot(value);\n\t },\n\n\t alignTo: function(secondAxis) {\n\t var lineBox = secondAxis.lineBox();\n\t var vertical = this.options.vertical;\n\t var pos = vertical ? Y : X;\n\n\t this.box.snapTo(lineBox, pos);\n\t if (vertical) {\n\t this.box.shrink(0, this.lineBox().height() - lineBox.height());\n\t } else {\n\t this.box.shrink(this.lineBox().width() - lineBox.width(), 0);\n\t }\n\t this.box[pos + 1] -= this.lineBox()[pos + 1] - lineBox[pos + 1];\n\t this.box[pos + 2] -= this.lineBox()[pos + 2] - lineBox[pos + 2];\n\t },\n\n\t axisLabelText: function(value, dataItem, options) {\n\t var tmpl = getTemplate(options);\n\t var text = value;\n\n\t if (tmpl) {\n\t text = tmpl({ value: value, dataItem: dataItem, format: options.format, culture: options.culture });\n\t } else if (options.format) {\n\t text = this.chartService.format.localeAuto(options.format, [ value ], options.culture);\n\t }\n\n\t return text;\n\t },\n\n\t slot: function(from , to, limit) {\n\t var slot = this.getSlot(from, to, limit);\n\t if (slot) {\n\t return slot.toRect();\n\t }\n\t },\n\n\t contentBox: function() {\n\t var box = this.box.clone();\n\t var labels = this.labels;\n\t if (labels.length) {\n\t var axis = this.options.vertical ? Y : X;\n\t if (this.chartService.isPannable(axis)) {\n\t var offset = this.maxLabelOffset();\n\t box[axis + 1] -= offset.start;\n\t box[axis + 2] += offset.end;\n\t } else {\n\t if (labels[0].options.visible) {\n\t box.wrap(labels[0].box);\n\t }\n\t var lastLabel = labels[labels.length - 1];\n\t if (lastLabel.options.visible) {\n\t box.wrap(lastLabel.box);\n\t }\n\t }\n\t }\n\n\t return box;\n\t },\n\n\t maxLabelOffset: function() {\n\t var this$1 = this;\n\n\t var ref = this.options;\n\t var vertical = ref.vertical;\n\t var reverse = ref.reverse;\n\t var labelsBetweenTicks = this.labelsBetweenTicks();\n\t var tickPositions = this.getLabelsTickPositions();\n\t var offsetField = vertical ? Y : X;\n\t var labels = this.labels;\n\t var startPosition = reverse ? 1 : 0;\n\t var endPosition = reverse ? 0 : 1;\n\t var maxStartOffset = 0;\n\t var maxEndOffset = 0;\n\n\t for (var idx = 0; idx < labels.length; idx++) {\n\t var label = labels[idx];\n\t var tickIx = this$1.labelTickIndex(label);\n\t var startTick = (void 0), endTick = (void 0);\n\n\t if (labelsBetweenTicks) {\n\t startTick = tickPositions[tickIx + startPosition];\n\t endTick = tickPositions[tickIx + endPosition];\n\t } else {\n\t startTick = endTick = tickPositions[tickIx];\n\t }\n\n\t maxStartOffset = Math.max(maxStartOffset, startTick - label.box[offsetField + 1]);\n\t maxEndOffset = Math.max(maxEndOffset, label.box[offsetField + 2] - endTick);\n\t }\n\n\t return {\n\t start: maxStartOffset,\n\t end: maxEndOffset\n\t };\n\t },\n\n\t limitRange: function(from, to, min, max, offset) {\n\t var options = this.options;\n\n\t if ((from < min && offset < 0 && (!defined(options.min) || options.min <= min)) || (max < to && offset > 0 && (!defined(options.max) || max <= options.max))) {\n\t return null;\n\t }\n\n\t if ((to < min && offset > 0) || (max < from && offset < 0)) {\n\t return {\n\t min: from,\n\t max: to\n\t };\n\t }\n\n\t var rangeSize = to - from;\n\t var minValue = from;\n\t var maxValue = to;\n\n\t if (from < min && offset < 0) {\n\t minValue = limitValue(from, min, max);\n\t maxValue = limitValue(from + rangeSize, min + rangeSize, max);\n\t } else if (to > max && offset > 0) {\n\t maxValue = limitValue(to, min, max);\n\t minValue = limitValue(to - rangeSize, min, max - rangeSize);\n\t }\n\n\t return {\n\t min: minValue,\n\t max: maxValue\n\t };\n\t },\n\n\t valueRange: function() {\n\t return {\n\t min: this.seriesMin,\n\t max: this.seriesMax\n\t };\n\t },\n\n\t labelsBetweenTicks: function() {\n\t return !this.options.justified;\n\t },\n\n\t prepareUserOptions: function() {\n\t }\n\t});\n\n\tsetDefaultOptions(Axis, {\n\t labels: {\n\t visible: true,\n\t rotation: 0,\n\t mirror: false,\n\t step: 1,\n\t skip: 0\n\t },\n\t line: {\n\t width: 1,\n\t color: BLACK,\n\t visible: true\n\t },\n\t title: {\n\t visible: true,\n\t position: CENTER\n\t },\n\t majorTicks: {\n\t align: OUTSIDE,\n\t size: 4,\n\t skip: 0,\n\t step: 1\n\t },\n\t minorTicks: {\n\t align: OUTSIDE,\n\t size: 3,\n\t skip: 0,\n\t step: 1\n\t },\n\t axisCrossingValue: 0,\n\t majorTickType: OUTSIDE,\n\t minorTickType: NONE,\n\t majorGridLines: {\n\t skip: 0,\n\t step: 1\n\t },\n\t minorGridLines: {\n\t visible: false,\n\t width: 1,\n\t color: BLACK,\n\t skip: 0,\n\t step: 1\n\t },\n\t // TODO: Move to line or labels options\n\t margin: 5,\n\t visible: true,\n\t reverse: false,\n\t justified: true,\n\t notes: {\n\t label: {\n\t text: \"\"\n\t }\n\t },\n\n\t _alignLines: true,\n\t _deferLabels: false\n\t});\n\n\tvar MILLISECONDS = \"milliseconds\";\n\tvar SECONDS = \"seconds\";\n\tvar MINUTES = \"minutes\";\n\tvar HOURS = \"hours\";\n\tvar DAYS = \"days\";\n\tvar WEEKS = \"weeks\";\n\tvar MONTHS = \"months\";\n\tvar YEARS = \"years\";\n\n\tvar TIME_PER_MILLISECOND = 1;\n\tvar TIME_PER_SECOND = 1000;\n\tvar TIME_PER_MINUTE = 60 * TIME_PER_SECOND;\n\tvar TIME_PER_HOUR = 60 * TIME_PER_MINUTE;\n\tvar TIME_PER_DAY = 24 * TIME_PER_HOUR;\n\tvar TIME_PER_WEEK = 7 * TIME_PER_DAY;\n\tvar TIME_PER_MONTH = 31 * TIME_PER_DAY;\n\tvar TIME_PER_YEAR = 365 * TIME_PER_DAY;\n\tvar TIME_PER_UNIT = {\n\t \"years\": TIME_PER_YEAR,\n\t \"months\": TIME_PER_MONTH,\n\t \"weeks\": TIME_PER_WEEK,\n\t \"days\": TIME_PER_DAY,\n\t \"hours\": TIME_PER_HOUR,\n\t \"minutes\": TIME_PER_MINUTE,\n\t \"seconds\": TIME_PER_SECOND,\n\t \"milliseconds\": TIME_PER_MILLISECOND\n\t};\n\n\tfunction absoluteDateDiff(a, b) {\n\t var diff = a.getTime() - b;\n\t var offsetDiff = a.getTimezoneOffset() - b.getTimezoneOffset();\n\n\t return diff - (offsetDiff * TIME_PER_MINUTE);\n\t}\n\n\tfunction addTicks(date, ticks) {\n\t return new Date(date.getTime() + ticks);\n\t}\n\n\tfunction toDate(value) {\n\t var result;\n\n\t if (value instanceof Date) {\n\t result = value;\n\t } else if (value) {\n\t result = new Date(value);\n\t }\n\n\t return result;\n\t}\n\n\tfunction startOfWeek(date, weekStartDay) {\n\t if (weekStartDay === void 0) { weekStartDay = 0; }\n\n\t var daysToSubtract = 0;\n\t var day = date.getDay();\n\n\t if (!isNaN(day)) {\n\t while (day !== weekStartDay) {\n\t if (day === 0) {\n\t day = 6;\n\t } else {\n\t day--;\n\t }\n\n\t daysToSubtract++;\n\t }\n\t }\n\n\t return addTicks(date, -daysToSubtract * TIME_PER_DAY);\n\t}\n\n\tfunction adjustDST(date, hours) {\n\t if (hours === 0 && date.getHours() === 23) {\n\t date.setHours(date.getHours() + 2);\n\t return true;\n\t }\n\n\t return false;\n\t}\n\n\tfunction addHours(date, hours) {\n\t var roundedDate = new Date(date);\n\n\t roundedDate.setMinutes(0, 0, 0);\n\n\t var tzDiff = (date.getTimezoneOffset() - roundedDate.getTimezoneOffset()) * TIME_PER_MINUTE;\n\n\t return addTicks(roundedDate, tzDiff + hours * TIME_PER_HOUR);\n\t}\n\n\tfunction addDuration(dateValue, value, unit, weekStartDay) {\n\t var result = dateValue;\n\n\t if (dateValue) {\n\t var date = toDate(dateValue);\n\t var hours = date.getHours();\n\n\t if (unit === YEARS) {\n\t result = new Date(date.getFullYear() + value, 0, 1);\n\t adjustDST(result, 0);\n\t } else if (unit === MONTHS) {\n\t result = new Date(date.getFullYear(), date.getMonth() + value, 1);\n\t adjustDST(result, hours);\n\t } else if (unit === WEEKS) {\n\t result = addDuration(startOfWeek(date, weekStartDay), value * 7, DAYS);\n\t adjustDST(result, hours);\n\t } else if (unit === DAYS) {\n\t result = new Date(date.getFullYear(), date.getMonth(), date.getDate() + value);\n\t adjustDST(result, hours);\n\t } else if (unit === HOURS) {\n\t result = addHours(date, value);\n\t } else if (unit === MINUTES) {\n\t result = addTicks(date, value * TIME_PER_MINUTE);\n\n\t if (result.getSeconds() > 0) {\n\t result.setSeconds(0);\n\t }\n\t } else if (unit === SECONDS) {\n\t result = addTicks(date, value * TIME_PER_SECOND);\n\t } else if (unit === MILLISECONDS) {\n\t result = addTicks(date, value);\n\t }\n\n\t if (unit !== MILLISECONDS && result.getMilliseconds() > 0) {\n\t result.setMilliseconds(0);\n\t }\n\t }\n\n\t return result;\n\t}\n\n\tfunction floorDate(date, unit, weekStartDay) {\n\t return addDuration(toDate(date), 0, unit, weekStartDay);\n\t}\n\n\tfunction ceilDate(dateValue, unit, weekStartDay) {\n\t var date = toDate(dateValue);\n\n\t if (date && floorDate(date, unit, weekStartDay).getTime() === date.getTime()) {\n\t return date;\n\t }\n\n\t return addDuration(date, 1, unit, weekStartDay);\n\t}\n\n\tfunction dateComparer(a, b) {\n\t if (a && b) {\n\t return a.getTime() - b.getTime();\n\t }\n\n\t return -1;\n\t}\n\n\tfunction dateDiff(a, b) {\n\t return a.getTime() - b;\n\t}\n\n\tfunction toTime(value) {\n\t if (isArray(value)) {\n\t var result = [];\n\t for (var idx = 0; idx < value.length; idx++) {\n\t result.push(toTime(value[idx]));\n\t }\n\n\t return result;\n\t } else if (value) {\n\t return toDate(value).getTime();\n\t }\n\t}\n\n\tfunction dateEquals(a, b) {\n\t if (a && b) {\n\t return toTime(a) === toTime(b);\n\t }\n\n\t return a === b;\n\t}\n\n\tfunction timeIndex(date, start, baseUnit) {\n\t return absoluteDateDiff(date, start) / TIME_PER_UNIT[baseUnit];\n\t}\n\n\tfunction dateIndex(value, start, baseUnit, baseUnitStep) {\n\t var date = toDate(value);\n\t var startDate = toDate(start);\n\t var index;\n\n\t if (baseUnit === MONTHS) {\n\t index = (date.getMonth() - startDate.getMonth() + (date.getFullYear() - startDate.getFullYear()) * 12) +\n\t timeIndex(date, new Date(date.getFullYear(), date.getMonth()), DAYS) / new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();\n\t } else if (baseUnit === YEARS) {\n\t index = date.getFullYear() - startDate.getFullYear() + dateIndex(date, new Date(date.getFullYear(), 0), MONTHS, 1) / 12;\n\t } else if (baseUnit === DAYS || baseUnit === WEEKS) {\n\t index = timeIndex(date, startDate, baseUnit);\n\t } else {\n\t index = dateDiff(date, start) / TIME_PER_UNIT[baseUnit];\n\t }\n\n\t return index / baseUnitStep;\n\t}\n\n\tfunction duration(a, b, unit) {\n\t var diff;\n\n\t if (unit === YEARS) {\n\t diff = b.getFullYear() - a.getFullYear();\n\t } else if (unit === MONTHS) {\n\t diff = duration(a, b, YEARS) * 12 + b.getMonth() - a.getMonth();\n\t } else if (unit === DAYS) {\n\t diff = Math.floor(dateDiff(b, a) / TIME_PER_DAY);\n\t } else {\n\t diff = Math.floor(dateDiff(b, a) / TIME_PER_UNIT[unit]);\n\t }\n\n\t return diff;\n\t}\n\n\tfunction lteDateIndex(date, sortedDates) {\n\t var low = 0;\n\t var high = sortedDates.length - 1;\n\t var index;\n\n\t while (low <= high) {\n\t index = Math.floor((low + high) / 2);\n\t var currentDate = sortedDates[index];\n\n\t if (currentDate < date) {\n\t low = index + 1;\n\t continue;\n\t }\n\n\t if (currentDate > date) {\n\t high = index - 1;\n\t continue;\n\t }\n\n\t while (dateEquals(sortedDates[index - 1], date)) {\n\t index--;\n\t }\n\n\t return index;\n\t }\n\n\t if (sortedDates[index] <= date) {\n\t return index;\n\t }\n\n\t return index - 1;\n\t}\n\n\tfunction parseDate(intlService, date) {\n\t var result;\n\t if (isString(date)) {\n\t result = intlService.parseDate(date) || toDate(date);\n\t } else {\n\t result = toDate(date);\n\t }\n\t return result;\n\t}\n\n\tfunction parseDates(intlService, dates) {\n\t if (isArray(dates)) {\n\t var result = [];\n\t for (var idx = 0; idx < dates.length; idx++) {\n\t result.push(parseDate(intlService, dates[idx]));\n\t }\n\n\t return result;\n\t }\n\n\t return parseDate(intlService, dates);\n\t}\n\n\tvar MIN_CATEGORY_POINTS_RANGE = 0.01;\n\n\tfunction indexOf(value, arr) {\n\t if (value instanceof Date) {\n\t var length = arr.length;\n\t for (var idx = 0; idx < length; idx++) {\n\t if (dateEquals(arr[idx], value)) {\n\t return idx;\n\t }\n\t }\n\n\t return -1;\n\t }\n\n\t return arr.indexOf(value);\n\t}\n\n\tvar CategoryAxis = Axis.extend({\n\t initFields: function() {\n\t this._ticks = {};\n\t },\n\n\t categoriesHash: function() {\n\t return \"\";\n\t },\n\n\t clone: function() {\n\t var copy = new CategoryAxis($.extend({}, this.options, {\n\t categories: this.options.srcCategories\n\t }), this.chartService);\n\t copy.createLabels();\n\n\t return copy;\n\t },\n\n\t initUserOptions: function(options) {\n\t var categories = options.categories || [];\n\t var definedMin = defined(options.min);\n\t var definedMax = defined(options.max);\n\t options.srcCategories = options.categories = categories;\n\n\t if ((definedMin || definedMax) && categories.length) {\n\t var min = definedMin ? Math.floor(options.min) : 0;\n\t var max;\n\n\t if (definedMax) {\n\t max = options.justified ? Math.floor(options.max) + 1 : Math.ceil(options.max);\n\t } else {\n\t max = categories.length;\n\t }\n\n\t options.categories = options.categories.slice(min, max);\n\t }\n\n\t return options;\n\t },\n\n\t rangeIndices: function() {\n\t var options = this.options;\n\t var length = options.categories.length || 1;\n\t var min = isNumber(options.min) ? options.min % 1 : 0;\n\t var max;\n\n\t if (isNumber(options.max) && options.max % 1 !== 0 && options.max < this.totalRange().max) {\n\t max = length - (1 - options.max % 1);\n\t } else {\n\t max = length - (options.justified ? 1 : 0);\n\t }\n\n\t return {\n\t min: min,\n\t max: max\n\t };\n\t },\n\n\t totalRangeIndices: function(limit) {\n\t var options = this.options;\n\t var min = isNumber(options.min) ? options.min : 0;\n\t var max;\n\n\t if (isNumber(options.max)) {\n\t max = options.max;\n\t } else if (isNumber(options.min)) {\n\t max = min + options.categories.length;\n\t } else {\n\t max = this.totalRange().max || 1;\n\t }\n\n\t if (limit) {\n\t var totalRange = this.totalRange();\n\t min = limitValue(min, 0, totalRange.max);\n\t max = limitValue(max, 0, totalRange.max);\n\t }\n\n\t return {\n\t min: min,\n\t max: max\n\t };\n\t },\n\n\t range: function() {\n\t var options = this.options;\n\t var min = isNumber(options.min) ? options.min : 0;\n\t var max = isNumber(options.max) ? options.max : this.totalRange().max;\n\n\t return {\n\t min: min,\n\t max: max\n\t };\n\t },\n\n\t roundedRange: function() {\n\t return this.range();\n\t },\n\n\t totalRange: function() {\n\t var options = this.options;\n\t return { min: 0, max: Math.max(this._seriesMax || 0, options.srcCategories.length) - (options.justified ? 1 : 0) };\n\t },\n\n\t scaleOptions: function() {\n\t var ref = this.rangeIndices();\n\t var min = ref.min;\n\t var max = ref.max;\n\t var lineBox = this.lineBox();\n\t var size = this.options.vertical ? lineBox.height() : lineBox.width();\n\t var scale = size / ((max - min) || 1);\n\n\t return {\n\t scale: scale * (this.options.reverse ? -1 : 1),\n\t box: lineBox,\n\t min: min,\n\t max: max\n\t };\n\t },\n\n\t arrangeLabels: function() {\n\t Axis.fn.arrangeLabels.call(this);\n\t this.hideOutOfRangeLabels();\n\t },\n\n\t hideOutOfRangeLabels: function() {\n\t var ref = this;\n\t var box = ref.box;\n\t var labels = ref.labels;\n\n\t if (labels.length) {\n\t var valueAxis = this.options.vertical ? Y : X;\n\t var start = box[valueAxis + 1];\n\t var end = box[valueAxis + 2];\n\t var firstLabel = labels[0];\n\t var lastLabel = last(labels);\n\n\t if (firstLabel.box[valueAxis + 1] > end || firstLabel.box[valueAxis + 2] < start) {\n\t firstLabel.options.visible = false;\n\t }\n\t if (lastLabel.box[valueAxis + 1] > end || lastLabel.box[valueAxis + 2] < start) {\n\t lastLabel.options.visible = false;\n\t }\n\t }\n\t },\n\n\t getMajorTickPositions: function() {\n\t return this.getTicks().majorTicks;\n\t },\n\n\t getMinorTickPositions: function() {\n\t return this.getTicks().minorTicks;\n\t },\n\n\t getLabelsTickPositions: function() {\n\t return this.getTicks().labelTicks;\n\t },\n\n\t tickIndices: function(stepSize) {\n\t var ref = this.rangeIndices();\n\t var min = ref.min;\n\t var max = ref.max;\n\t var limit = Math.ceil(max);\n\t var current = Math.floor(min);\n\t var indices = [];\n\n\t while (current <= limit) {\n\t indices.push(current);\n\t current += stepSize;\n\t }\n\n\t return indices;\n\t },\n\n\t getTickPositions: function(stepSize) {\n\t var ref = this.options;\n\t var vertical = ref.vertical;\n\t var reverse = ref.reverse;\n\t var ref$1 = this.scaleOptions();\n\t var scale = ref$1.scale;\n\t var box = ref$1.box;\n\t var min = ref$1.min;\n\t var pos = box[(vertical ? Y : X) + (reverse ? 2 : 1)];\n\t var indices = this.tickIndices(stepSize);\n\t var positions = [];\n\n\t for (var idx = 0; idx < indices.length; idx++) {\n\t positions.push(pos + round(scale * (indices[idx] - min), COORD_PRECISION));\n\t }\n\n\t return positions;\n\t },\n\n\t getTicks: function() {\n\t var options = this.options;\n\t var cache = this._ticks;\n\t var range = this.rangeIndices();\n\t var lineBox = this.lineBox();\n\t var hash = lineBox.getHash() + range.min + \",\" + range.max + options.reverse + options.justified;\n\n\t if (cache._hash !== hash) {\n\t var hasMinor = options.minorTicks.visible || options.minorGridLines.visible;\n\t cache._hash = hash;\n\t cache.labelTicks = this.getTickPositions(1);\n\t cache.majorTicks = this.filterOutOfRangePositions(cache.labelTicks, lineBox);\n\t cache.minorTicks = hasMinor ? this.filterOutOfRangePositions(this.getTickPositions(0.5), lineBox) : [];\n\t }\n\n\t return cache;\n\t },\n\n\t filterOutOfRangePositions: function(positions, lineBox) {\n\t if (!positions.length) {\n\t return positions;\n\t }\n\n\t var axis = this.options.vertical ? Y : X;\n\t var inRange = function (position) { return lineBox[axis + 1] <= position && position <= lineBox[axis + 2]; };\n\n\t var end = positions.length - 1;\n\t var startIndex = 0;\n\t while (!inRange(positions[startIndex]) && startIndex <= end) {\n\t startIndex++;\n\t }\n\n\t var endIndex = end;\n\n\t while (!inRange(positions[endIndex]) && endIndex >= 0) {\n\t endIndex--;\n\t }\n\n\t return positions.slice(startIndex, endIndex + 1);\n\t },\n\n\t getSlot: function(from, to, limit) {\n\t var options = this.options;\n\t var reverse = options.reverse;\n\t var justified = options.justified;\n\t var vertical = options.vertical;\n\t var ref = this.scaleOptions();\n\t var scale = ref.scale;\n\t var box = ref.box;\n\t var min = ref.min;\n\t var valueAxis = vertical ? Y : X;\n\t var lineStart = box[valueAxis + (reverse ? 2 : 1)];\n\t var slotBox = box.clone();\n\t var singleSlot = !defined(to);\n\n\t var start = valueOrDefault(from, 0);\n\t var end = valueOrDefault(to, start);\n\t end = Math.max(end - 1, start);\n\n\t // Fixes transient bug caused by iOS 6.0 JIT\n\t // (one can never be too sure)\n\t end = Math.max(start, end);\n\n\t var p1 = lineStart + (start - min) * scale;\n\t var p2 = lineStart + (end + 1 - min) * scale;\n\n\t if (singleSlot && justified) {\n\t p2 = p1;\n\t }\n\n\t if (limit) {\n\t p1 = limitValue(p1, box[valueAxis + 1], box[valueAxis + 2]);\n\t p2 = limitValue(p2, box[valueAxis + 1], box[valueAxis + 2]);\n\t }\n\n\t slotBox[valueAxis + 1] = reverse ? p2 : p1;\n\t slotBox[valueAxis + 2] = reverse ? p1 : p2;\n\n\t return slotBox;\n\t },\n\n\t limitSlot: function(slot) {\n\t var vertical = this.options.vertical;\n\t var valueAxis = vertical ? Y : X;\n\t var lineBox = this.lineBox();\n\t var limittedSlot = slot.clone();\n\n\t limittedSlot[valueAxis + 1] = limitValue(slot[valueAxis + 1], lineBox[valueAxis + 1], lineBox[valueAxis + 2]);\n\t limittedSlot[valueAxis + 2] = limitValue(slot[valueAxis + 2], lineBox[valueAxis + 1], lineBox[valueAxis + 2]);\n\n\t return limittedSlot;\n\t },\n\n\t slot: function(from, to, limit) {\n\t var min = Math.floor(this.options.min || 0);\n\t var start = from;\n\t var end = to;\n\n\t if (typeof start === \"string\") {\n\t start = this.categoryIndex(start);\n\t } else if (isNumber(start)) {\n\t start -= min;\n\t }\n\n\t if (typeof end === \"string\") {\n\t end = this.categoryIndex(end);\n\t } else if (isNumber(end)) {\n\t end -= min;\n\t }\n\n\t return Axis.fn.slot.call(this, start, end, limit);\n\t },\n\n\t pointCategoryIndex: function(point) {\n\t var ref = this.options;\n\t var reverse = ref.reverse;\n\t var justified = ref.justified;\n\t var vertical = ref.vertical;\n\t var valueAxis = vertical ? Y : X;\n\t var ref$1 = this.scaleOptions();\n\t var scale = ref$1.scale;\n\t var box = ref$1.box;\n\t var min = ref$1.min;\n\t var max = ref$1.max;\n\t var startValue = reverse ? max : min;\n\t var lineStart = box[valueAxis + 1];\n\t var lineEnd = box[valueAxis + 2];\n\t var pos = point[valueAxis];\n\n\t if (pos < lineStart || pos > lineEnd) {\n\t return null;\n\t }\n\n\t var value = startValue + (pos - lineStart) / scale;\n\t var diff = value % 1;\n\n\t if (justified) {\n\t value = Math.round(value);\n\t } else if (diff === 0 && value > 0) {\n\t value--;\n\t }\n\n\t return Math.floor(value);\n\t },\n\n\t getCategory: function(point) {\n\t var index = this.pointCategoryIndex(point);\n\n\t if (index === null) {\n\t return null;\n\t }\n\n\t return this.options.categories[index];\n\t },\n\n\t categoryIndex: function(value) {\n\t return this.totalIndex(value) - Math.floor(this.options.min || 0);\n\t },\n\n\t categoryAt: function(index, total) {\n\t var options = this.options;\n\n\t return (total ? options.srcCategories : options.categories)[index];\n\t },\n\n\t categoriesCount: function() {\n\t return (this.options.categories || []).length;\n\t },\n\n\t translateRange: function(delta) {\n\t var options = this.options;\n\t var lineBox = this.lineBox();\n\t var size = options.vertical ? lineBox.height() : lineBox.width();\n\t var range = options.categories.length;\n\t var scale = size / range;\n\t var offset = round(delta / scale, DEFAULT_PRECISION);\n\n\t return {\n\t min: offset,\n\t max: range + offset\n\t };\n\t },\n\n\t zoomRange: function(rate) {\n\t var rangeIndices = this.totalRangeIndices();\n\t var ref = this.totalRange();\n\t var totalMin = ref.min;\n\t var totalMax = ref.max;\n\t var min = limitValue(rangeIndices.min + rate, totalMin, totalMax);\n\t var max = limitValue(rangeIndices.max - rate, totalMin, totalMax);\n\n\t if (max - min > 0) {\n\t return {\n\t min: min,\n\t max: max\n\t };\n\t }\n\t },\n\n\t scaleRange: function(scale) {\n\t var range = this.options.categories.length;\n\t var delta = scale * range;\n\n\t return {\n\t min: -delta,\n\t max: range + delta\n\t };\n\t },\n\n\t labelsCount: function() {\n\t var labelsRange = this.labelsRange();\n\n\t return labelsRange.max - labelsRange.min;\n\t },\n\n\t labelsRange: function() {\n\t var options = this.options;\n\t var justified = options.justified;\n\t var labelOptions = options.labels;\n\t var ref = this.totalRangeIndices(true);\n\t var min = ref.min;\n\t var max = ref.max;\n\t var start = Math.floor(min);\n\n\t if (!justified) {\n\t min = Math.floor(min);\n\t max = Math.ceil(max);\n\t } else {\n\t min = Math.ceil(min);\n\t max = Math.floor(max);\n\t }\n\n\t var skip;\n\n\t if (min > labelOptions.skip) {\n\t skip = labelOptions.skip + labelOptions.step * Math.ceil((min - labelOptions.skip) / labelOptions.step);\n\t } else {\n\t skip = labelOptions.skip;\n\t }\n\n\t return {\n\t min: skip - start,\n\t max: (options.categories.length ? max + (justified ? 1 : 0) : 0) - start\n\t };\n\t },\n\n\t createAxisLabel: function(index, labelOptions) {\n\t var options = this.options;\n\t var dataItem = options.dataItems ? options.dataItems[index] : null;\n\t var category = valueOrDefault(options.categories[index], \"\");\n\t var text = this.axisLabelText(category, dataItem, labelOptions);\n\n\t return new AxisLabel(category, text, index, dataItem, labelOptions);\n\t },\n\n\t shouldRenderNote: function(value) {\n\t var range = this.totalRangeIndices();\n\n\t return Math.floor(range.min) <= value && value <= Math.ceil(range.max);\n\t },\n\n\t noteSlot: function(value) {\n\t var options = this.options;\n\t var index = value - Math.floor(options.min || 0);\n\t return this.getSlot(index);\n\t },\n\n\t arrangeNotes: function() {\n\t Axis.fn.arrangeNotes.call(this);\n\t this.hideOutOfRangeNotes();\n\t },\n\n\t hideOutOfRangeNotes: function() {\n\t var ref = this;\n\t var notes = ref.notes;\n\t var box = ref.box;\n\t if (notes && notes.length) {\n\t var valueAxis = this.options.vertical ? Y : X;\n\t var start = box[valueAxis + 1];\n\t var end = box[valueAxis + 2];\n\n\t for (var idx = 0; idx < notes.length; idx++) {\n\t var note = notes[idx];\n\t if (note.box && (end < note.box[valueAxis + 1] || note.box[valueAxis + 2] < start)) {\n\t note.hide();\n\t }\n\t }\n\t }\n\t },\n\n\t pan: function(delta) {\n\t var range = this.totalRangeIndices(true);\n\t var ref = this.scaleOptions();\n\t var scale = ref.scale;\n\t var offset = round(delta / scale, DEFAULT_PRECISION);\n\t var totalRange = this.totalRange();\n\t var min = range.min + offset;\n\t var max = range.max + offset;\n\n\t return this.limitRange(min, max, 0, totalRange.max, offset);\n\t },\n\n\t pointsRange: function(start, end) {\n\t var ref = this.options;\n\t var reverse = ref.reverse;\n\t var vertical = ref.vertical;\n\t var valueAxis = vertical ? Y : X;\n\t var range = this.totalRangeIndices(true);\n\t var ref$1 = this.scaleOptions();\n\t var scale = ref$1.scale;\n\t var box = ref$1.box;\n\t var lineStart = box[valueAxis + (reverse ? 2 : 1)];\n\n\t var diffStart = start[valueAxis] - lineStart;\n\t var diffEnd = end[valueAxis] - lineStart;\n\n\t var min = range.min + diffStart / scale;\n\t var max = range.min + diffEnd / scale;\n\t var rangeMin = Math.min(min, max);\n\t var rangeMax = Math.max(min, max);\n\n\t if (rangeMax - rangeMin >= MIN_CATEGORY_POINTS_RANGE) {\n\t return {\n\t min: rangeMin,\n\t max: rangeMax\n\t };\n\t }\n\t },\n\n\t valueRange: function() {\n\t return this.range();\n\t },\n\n\t totalIndex: function(value) {\n\t var options = this.options;\n\t var index = this._categoriesMap ?\n\t this._categoriesMap.get(value) : indexOf(value, options.srcCategories);\n\n\t return index;\n\t },\n\n\t currentRangeIndices: function() {\n\t var options = this.options;\n\t var min = 0;\n\n\t if (isNumber(options.min)) {\n\t min = Math.floor(options.min);\n\t }\n\n\t var max;\n\t if (isNumber(options.max)) {\n\t max = options.justified ? Math.floor(options.max) : Math.ceil(options.max) - 1;\n\t } else {\n\t max = this.totalCount() - 1;\n\t }\n\n\t return {\n\t min: min,\n\t max: max\n\t };\n\t },\n\n\t mapCategories: function() {\n\t if (!this._categoriesMap) {\n\t var map$$1 = this._categoriesMap = new HashMap();\n\t var srcCategories = this.options.srcCategories;\n\t for (var idx = 0; idx < srcCategories.length; idx++) {\n\t map$$1.set(srcCategories[idx], idx);\n\t }\n\t }\n\t },\n\n\t totalCount: function() {\n\t return Math.max(this.options.srcCategories.length, this._seriesMax || 0);\n\t }\n\t});\n\n\tsetDefaultOptions(CategoryAxis, {\n\t type: \"category\",\n\t vertical: false,\n\t majorGridLines: {\n\t visible: false,\n\t width: 1,\n\t color: BLACK\n\t },\n\t labels: {\n\t zIndex: 1\n\t },\n\t justified: false,\n\t _deferLabels: true\n\t});\n\n\tvar COORDINATE_LIMIT = 300000;\n\n\tvar DateLabelFormats = {\n\t milliseconds: \"HH:mm:ss.fff\",\n\t seconds: \"HH:mm:ss\",\n\t minutes: \"HH:mm\",\n\t hours: \"HH:mm\",\n\t days: \"M/d\",\n\t weeks: \"M/d\",\n\t months: \"MMM 'yy\",\n\t years: \"yyyy\"\n\t};\n\n\tvar ZERO_THRESHOLD = 0.2;\n\n\tvar AUTO = \"auto\";\n\tvar BASE_UNITS = [\n\t MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS, WEEKS, MONTHS, YEARS\n\t];\n\tvar FIT = \"fit\";\n\n\tfunction categoryRange(categories) {\n\t var range = categories._range;\n\t if (!range) {\n\t range = categories._range = sparseArrayLimits(categories);\n\t range.min = toDate(range.min);\n\t range.max = toDate(range.max);\n\t }\n\n\t return range;\n\t}\n\n\tvar EmptyDateRange = Class.extend({\n\t init: function(options) {\n\t this.options = options;\n\t },\n\n\t displayIndices: function() {\n\t return {\n\t min: 0,\n\t max: 1\n\t };\n\t },\n\n\t displayRange: function() {\n\t return {};\n\t },\n\n\t total: function() {\n\t return {};\n\t },\n\n\t valueRange: function() {\n\t return {};\n\t },\n\n\t valueIndex: function() {\n\t return -1;\n\t },\n\n\t values: function() {\n\t return [];\n\t },\n\n\t totalIndex: function() {\n\t return -1;\n\t },\n\n\t valuesCount: function() {\n\t return 0;\n\t },\n\n\t totalCount: function() {\n\t return 0;\n\t },\n\n\t dateAt: function() {\n\t return null;\n\t }\n\t});\n\n\tvar DateRange = Class.extend({\n\t init: function(start, end, options) {\n\t this.options = options;\n\t options.baseUnitStep = options.baseUnitStep || 1;\n\n\t var roundToBaseUnit = options.roundToBaseUnit;\n\t var justified = options.justified;\n\n\t this.start = addDuration(start, 0, options.baseUnit, options.weekStartDay);\n\t var lowerEnd = this.roundToTotalStep(end);\n\t var expandEnd = !justified && dateEquals(end, lowerEnd) && !options.justifyEnd;\n\n\t this.end = this.roundToTotalStep(end, !justified, expandEnd ? 1 : 0);\n\n\t var min = options.min || start;\n\t this.valueStart = this.roundToTotalStep(min);\n\t this.displayStart = roundToBaseUnit ? this.valueStart : min;\n\n\t var max = options.max;\n\t if (!max) {\n\t this.valueEnd = lowerEnd;\n\t this.displayEnd = roundToBaseUnit || expandEnd ? this.end : end;\n\t } else {\n\t this.valueEnd = this.roundToTotalStep(max, false, !justified && dateEquals(max, this.roundToTotalStep(max)) ? -1 : 0);\n\t this.displayEnd = roundToBaseUnit ? this.roundToTotalStep(max, !justified) : options.max;\n\t }\n\n\t if (this.valueEnd < this.valueStart) {\n\t this.valueEnd = this.valueStart;\n\t }\n\t if (this.displayEnd <= this.displayStart) {\n\t this.displayEnd = this.roundToTotalStep(this.displayStart, false, 1);\n\t }\n\t },\n\n\t displayRange: function() {\n\t return {\n\t min: this.displayStart,\n\t max: this.displayEnd\n\t };\n\t },\n\n\t displayIndices: function() {\n\t if (!this._indices) {\n\t var options = this.options;\n\n\t var baseUnit = options.baseUnit;\n\t var baseUnitStep = options.baseUnitStep;\n\n\t var minIdx = dateIndex(this.displayStart, this.valueStart, baseUnit, baseUnitStep);\n\t var maxIdx = dateIndex(this.displayEnd, this.valueStart, baseUnit, baseUnitStep);\n\n\t this._indices = { min: minIdx, max: maxIdx };\n\t }\n\n\t return this._indices;\n\t },\n\n\t total: function() {\n\t return {\n\t min: this.start,\n\t max: this.end\n\t };\n\t },\n\n\t totalCount: function() {\n\t var last$$1 = this.totalIndex(this.end);\n\n\t return last$$1 + (this.options.justified ? 1 : 0);\n\t },\n\n\t valueRange: function() {\n\t return {\n\t min: this.valueStart,\n\t max: this.valueEnd\n\t };\n\t },\n\n\t valueIndex: function(value) {\n\t var options = this.options;\n\t return Math.floor(dateIndex(value, this.valueStart, options.baseUnit, options.baseUnitStep));\n\t },\n\n\t totalIndex: function(value) {\n\t var options = this.options;\n\t return Math.floor(dateIndex(value, this.start, options.baseUnit, options.baseUnitStep));\n\t },\n\n\t dateIndex: function(value) {\n\t var options = this.options;\n\t return dateIndex(value, this.valueStart, options.baseUnit, options.baseUnitStep);\n\t },\n\n\t valuesCount: function() {\n\t var maxIdx = this.valueIndex(this.valueEnd);\n\n\t return maxIdx + 1;\n\t },\n\n\t values: function() {\n\t var values = this._values;\n\t if (!values) {\n\t var options = this.options;\n\t var range = this.valueRange();\n\t this._values = values = [];\n\n\t for (var date = range.min; date <= range.max;) {\n\t values.push(date);\n\t date = addDuration(date, options.baseUnitStep, options.baseUnit, options.weekStartDay);\n\t }\n\t }\n\n\t return values;\n\t },\n\n\t dateAt: function(index, total) {\n\t var options = this.options;\n\n\t return addDuration(total ? this.start : this.valueStart, options.baseUnitStep * index, options.baseUnit, options.weekStartDay);\n\t },\n\n\t roundToTotalStep: function(value, upper, next) {\n\t var ref = this.options;\n\t var baseUnit = ref.baseUnit;\n\t var baseUnitStep = ref.baseUnitStep;\n\t var weekStartDay = ref.weekStartDay;\n\t var start = this.start;\n\n\t var step = dateIndex(value, start, baseUnit, baseUnitStep);\n\t var roundedStep = upper ? Math.ceil(step) : Math.floor(step);\n\n\t if (next) {\n\t roundedStep += next;\n\t }\n\n\t return addDuration(start, roundedStep * baseUnitStep, baseUnit, weekStartDay);\n\t }\n\t});\n\n\tfunction autoBaseUnit(options, startUnit, startStep) {\n\t var categoryLimits = categoryRange(options.categories);\n\t var span = (options.max || categoryLimits.max) - (options.min || categoryLimits.min);\n\t var autoBaseUnitSteps = options.autoBaseUnitSteps;\n\t var maxDateGroups = options.maxDateGroups;\n\t var autoUnit = options.baseUnit === FIT;\n\t var autoUnitIx = startUnit ? BASE_UNITS.indexOf(startUnit) : 0;\n\t var baseUnit = autoUnit ? BASE_UNITS[autoUnitIx++] : options.baseUnit;\n\t var units = span / TIME_PER_UNIT[baseUnit];\n\t var totalUnits = units;\n\t var unitSteps, step, nextStep;\n\n\t while (!step || units >= maxDateGroups) {\n\t unitSteps = unitSteps || autoBaseUnitSteps[baseUnit].slice(0);\n\n\t do {\n\t nextStep = unitSteps.shift();\n\t } while (nextStep && startUnit === baseUnit && nextStep < startStep);\n\n\t if (nextStep) {\n\t step = nextStep;\n\t units = totalUnits / step;\n\t } else if (baseUnit === last(BASE_UNITS)) {\n\t step = Math.ceil(totalUnits / maxDateGroups);\n\t break;\n\t } else if (autoUnit) {\n\t baseUnit = BASE_UNITS[autoUnitIx++] || last(BASE_UNITS);\n\t totalUnits = span / TIME_PER_UNIT[baseUnit];\n\t unitSteps = null;\n\t } else {\n\t if (units > maxDateGroups) {\n\t step = Math.ceil(totalUnits / maxDateGroups);\n\t }\n\t break;\n\t }\n\t }\n\n\t options.baseUnitStep = step;\n\t options.baseUnit = baseUnit;\n\t}\n\n\tfunction defaultBaseUnit(options) {\n\t var categories = options.categories;\n\t var count = defined(categories) ? categories.length : 0;\n\t var minDiff = MAX_VALUE;\n\t var lastCategory, unit;\n\n\t for (var categoryIx = 0; categoryIx < count; categoryIx++) {\n\t var category = categories[categoryIx];\n\n\t if (category && lastCategory) {\n\t var diff = absoluteDateDiff(category, lastCategory);\n\t if (diff > 0) {\n\t minDiff = Math.min(minDiff, diff);\n\n\t if (minDiff >= TIME_PER_YEAR) {\n\t unit = YEARS;\n\t } else if (minDiff >= TIME_PER_MONTH - TIME_PER_DAY * 3) {\n\t unit = MONTHS;\n\t } else if (minDiff >= TIME_PER_WEEK) {\n\t unit = WEEKS;\n\t } else if (minDiff >= TIME_PER_DAY) {\n\t unit = DAYS;\n\t } else if (minDiff >= TIME_PER_HOUR) {\n\t unit = HOURS;\n\t } else if (minDiff >= TIME_PER_MINUTE) {\n\t unit = MINUTES;\n\t } else {\n\t unit = SECONDS;\n\t }\n\t }\n\t }\n\n\t lastCategory = category;\n\t }\n\n\t options.baseUnit = unit || DAYS;\n\t}\n\n\tfunction initUnit(options) {\n\t var baseUnit = (options.baseUnit || \"\").toLowerCase();\n\t var useDefault = baseUnit !== FIT && !inArray(baseUnit, BASE_UNITS);\n\n\t if (useDefault) {\n\t defaultBaseUnit(options);\n\t }\n\n\t if (baseUnit === FIT || options.baseUnitStep === AUTO) {\n\t autoBaseUnit(options);\n\t }\n\n\t return options;\n\t}\n\n\tvar DateCategoryAxis = CategoryAxis.extend({\n\t clone: function() {\n\t var copy = new DateCategoryAxis($.extend({}, this.options), this.chartService);\n\t copy.createLabels();\n\n\t return copy;\n\t },\n\n\t categoriesHash: function() {\n\t var start = this.dataRange.total().min;\n\t return this.options.baseUnit + this.options.baseUnitStep + start;\n\t },\n\n\t initUserOptions: function(options) {\n\t return options;\n\t },\n\n\t initFields: function() {\n\t CategoryAxis.fn.initFields.call(this);\n\n\t var chartService = this.chartService;\n\t var intlService = chartService.intl;\n\t var options = this.options;\n\n\t var categories = options.categories || [];\n\t if (!categories._parsed) {\n\t categories = parseDates(intlService, categories);\n\t categories._parsed = true;\n\t }\n\n\t options = deepExtend({\n\t roundToBaseUnit: true\n\t }, options, {\n\t categories: categories,\n\t min: parseDate(intlService, options.min),\n\t max: parseDate(intlService, options.max)\n\t });\n\n\t if (chartService.panning && chartService.isPannable(options.vertical ? Y : X)) {\n\t options.roundToBaseUnit = false;\n\t }\n\n\t options.userSetBaseUnit = options.userSetBaseUnit || options.baseUnit;\n\t options.userSetBaseUnitStep = options.userSetBaseUnitStep || options.baseUnitStep;\n\n\t this.options = options;\n\t options.srcCategories = categories;\n\n\t if (categories.length > 0) {\n\t var range = categoryRange(categories);\n\t var maxDivisions = options.maxDivisions;\n\n\t this.dataRange = new DateRange(range.min, range.max, initUnit(options));\n\n\t if (maxDivisions) {\n\t var dataRange = this.dataRange.displayRange();\n\n\t var divisionOptions = $.extend({}, options, {\n\t justified: true,\n\t roundToBaseUnit: false,\n\t baseUnit: 'fit',\n\t min: dataRange.min,\n\t max: dataRange.max,\n\t maxDateGroups: maxDivisions\n\t });\n\n\t var dataRangeOptions = this.dataRange.options;\n\n\t autoBaseUnit(divisionOptions, dataRangeOptions.baseUnit, dataRangeOptions.baseUnitStep);\n\n\t this.divisionRange = new DateRange(range.min, range.max, divisionOptions);\n\t } else {\n\t this.divisionRange = this.dataRange;\n\t }\n\n\t } else {\n\t options.baseUnit = options.baseUnit || DAYS;\n\t this.dataRange = this.divisionRange = new EmptyDateRange(options);\n\t }\n\t },\n\n\t tickIndices: function(stepSize) {\n\t var ref = this;\n\t var dataRange = ref.dataRange;\n\t var divisionRange = ref.divisionRange;\n\t var valuesCount = divisionRange.valuesCount();\n\n\t if (!this.options.maxDivisions || !valuesCount) {\n\t return CategoryAxis.fn.tickIndices.call(this, stepSize);\n\t }\n\n\t var indices = [];\n\t var values = divisionRange.values();\n\t var offset = 0;\n\n\t if (!this.options.justified) {\n\t values = values.concat(divisionRange.dateAt(valuesCount));\n\t offset = 0.5;//align ticks to the center of not justified categories\n\t }\n\n\t for (var idx = 0; idx < values.length; idx++) {\n\t indices.push(dataRange.dateIndex(values[idx]) + offset);\n\t if (stepSize !== 1 && idx >= 1) {\n\t var last$$1 = indices.length - 1;\n\t indices.splice(idx, 0, indices[last$$1 - 1] + (indices[last$$1] - indices[last$$1 - 1]) * stepSize);\n\t }\n\t }\n\n\t return indices;\n\t },\n\n\t shouldRenderNote: function(value) {\n\t var range = this.range();\n\t var categories = this.options.categories || [];\n\n\t return dateComparer(value, range.min) >= 0 && dateComparer(value, range.max) <= 0 && categories.length;\n\t },\n\n\t parseNoteValue: function(value) {\n\t return parseDate(this.chartService.intl, value);\n\t },\n\n\t noteSlot: function(value) {\n\t return this.getSlot(value);\n\t },\n\n\t translateRange: function(delta) {\n\t var options = this.options;\n\t var baseUnit = options.baseUnit;\n\t var weekStartDay = options.weekStartDay;\n\t var vertical = options.vertical;\n\t var lineBox = this.lineBox();\n\t var size = vertical ? lineBox.height() : lineBox.width();\n\t var range = this.range();\n\t var scale = size / (range.max - range.min);\n\t var offset = round(delta / scale, DEFAULT_PRECISION);\n\n\t if (range.min && range.max) {\n\t var from = addTicks(options.min || range.min, offset);\n\t var to = addTicks(options.max || range.max, offset);\n\n\t range = {\n\t min: addDuration(from, 0, baseUnit, weekStartDay),\n\t max: addDuration(to, 0, baseUnit, weekStartDay)\n\t };\n\t }\n\n\t return range;\n\t },\n\n\t scaleRange: function(delta) {\n\t var rounds = Math.abs(delta);\n\t var result = this.range();\n\t var from = result.min;\n\t var to = result.max;\n\n\t if (from && to) {\n\t while (rounds--) {\n\t var range = dateDiff(from, to);\n\t var step = Math.round(range * 0.1);\n\t if (delta < 0) {\n\t from = addTicks(from, step);\n\t to = addTicks(to, -step);\n\t } else {\n\t from = addTicks(from, -step);\n\t to = addTicks(to, step);\n\t }\n\t }\n\n\t result = { min: from, max: to };\n\t }\n\n\t return result;\n\t },\n\n\t labelsRange: function() {\n\t return {\n\t min: this.options.labels.skip,\n\t max: this.divisionRange.valuesCount()\n\t };\n\t },\n\n\t pan: function(delta) {\n\t if (this.isEmpty()) {\n\t return null;\n\t }\n\n\t var options = this.options;\n\t var lineBox = this.lineBox();\n\t var size = options.vertical ? lineBox.height() : lineBox.width();\n\t var ref = this.dataRange.displayRange();\n\t var min = ref.min;\n\t var max = ref.max;\n\t var totalLimits = this.dataRange.total();\n\t var scale = size / (max - min);\n\t var offset = round(delta / scale, DEFAULT_PRECISION) * (options.reverse ? -1 : 1);\n\t var from = addTicks(min, offset);\n\t var to = addTicks(max, offset);\n\n\t var panRange = this.limitRange(toTime(from), toTime(to), toTime(totalLimits.min), toTime(totalLimits.max), offset);\n\n\t if (panRange) {\n\t panRange.min = toDate(panRange.min);\n\t panRange.max = toDate(panRange.max);\n\t panRange.baseUnit = options.baseUnit;\n\t panRange.baseUnitStep = options.baseUnitStep || 1;\n\t panRange.userSetBaseUnit = options.userSetBaseUnit;\n\t panRange.userSetBaseUnitStep = options.userSetBaseUnitStep;\n\n\t return panRange;\n\t }\n\t },\n\n\t pointsRange: function(start, end) {\n\t if (this.isEmpty()) {\n\t return null;\n\t }\n\n\t var pointsRange = CategoryAxis.fn.pointsRange.call(this, start, end);\n\t var datesRange = this.dataRange.displayRange();\n\t var indicesRange = this.dataRange.displayIndices();\n\t var scale = dateDiff(datesRange.max, datesRange.min) / (indicesRange.max - indicesRange.min);\n\t var options = this.options;\n\n\t var min = addTicks(datesRange.min, pointsRange.min * scale);\n\t var max = addTicks(datesRange.min, pointsRange.max * scale);\n\n\t return {\n\t min: min,\n\t max: max,\n\t baseUnit: options.userSetBaseUnit || options.baseUnit,\n\t baseUnitStep: options.userSetBaseUnitStep || options.baseUnitStep\n\t };\n\t },\n\n\t zoomRange: function(delta) {\n\t if (this.isEmpty()) {\n\t return null;\n\t }\n\n\t var options = this.options;\n\t var fit = options.userSetBaseUnit === FIT;\n\t var totalLimits = this.dataRange.total();\n\t var ref = this.dataRange.displayRange();\n\t var rangeMin = ref.min;\n\t var rangeMax = ref.max;\n\t var ref$1 = this.dataRange.options;\n\t var weekStartDay = ref$1.weekStartDay;\n\t var baseUnit = ref$1.baseUnit;\n\t var baseUnitStep = ref$1.baseUnitStep;\n\t var min = addDuration(rangeMin, delta * baseUnitStep, baseUnit, weekStartDay);\n\t var max = addDuration(rangeMax, -delta * baseUnitStep, baseUnit, weekStartDay);\n\n\t if (fit) {\n\t var autoBaseUnitSteps = options.autoBaseUnitSteps;\n\t var maxDateGroups = options.maxDateGroups;\n\n\t var maxDiff = last(autoBaseUnitSteps[baseUnit]) * maxDateGroups * TIME_PER_UNIT[baseUnit];\n\t var rangeDiff = dateDiff(rangeMax, rangeMin);\n\t var diff = dateDiff(max, min);\n\t var baseUnitIndex = BASE_UNITS.indexOf(baseUnit);\n\t var autoBaseUnitStep, ticks;\n\n\t if (diff < TIME_PER_UNIT[baseUnit] && baseUnit !== MILLISECONDS) {\n\t baseUnit = BASE_UNITS[baseUnitIndex - 1];\n\t autoBaseUnitStep = last(autoBaseUnitSteps[baseUnit]);\n\t ticks = (rangeDiff - (maxDateGroups - 1) * autoBaseUnitStep * TIME_PER_UNIT[baseUnit]) / 2;\n\t min = addTicks(rangeMin, ticks);\n\t max = addTicks(rangeMax, -ticks);\n\n\t } else if (diff > maxDiff && baseUnit !== YEARS) {\n\t var stepIndex = 0;\n\n\t do {\n\t baseUnitIndex++;\n\t baseUnit = BASE_UNITS[baseUnitIndex];\n\t stepIndex = 0;\n\t ticks = 2 * TIME_PER_UNIT[baseUnit];\n\t do {\n\t autoBaseUnitStep = autoBaseUnitSteps[baseUnit][stepIndex];\n\t stepIndex++;\n\t } while (stepIndex < autoBaseUnitSteps[baseUnit].length && ticks * autoBaseUnitStep < rangeDiff);\n\t } while (baseUnit !== YEARS && ticks * autoBaseUnitStep < rangeDiff);\n\n\t ticks = (ticks * autoBaseUnitStep - rangeDiff) / 2;\n\t if (ticks > 0) {\n\t min = addTicks(rangeMin, -ticks);\n\t max = addTicks(rangeMax, ticks);\n\t min = addTicks(min, limitValue(max, totalLimits.min, totalLimits.max) - max);\n\t max = addTicks(max, limitValue(min, totalLimits.min, totalLimits.max) - min);\n\t }\n\t }\n\t }\n\n\t if (min < totalLimits.min) {\n\t min = totalLimits.min;\n\t }\n\t if (max > totalLimits.max) {\n\t max = totalLimits.max;\n\t }\n\n\t if (min && max && dateDiff(max, min) > 0) {\n\t return {\n\t min: min,\n\t max: max,\n\t baseUnit: options.userSetBaseUnit || options.baseUnit,\n\t baseUnitStep: options.userSetBaseUnitStep || options.baseUnitStep\n\t };\n\t }\n\t },\n\n\t range: function() {\n\t return this.dataRange.displayRange();\n\t },\n\n\t createAxisLabel: function(index, labelOptions) {\n\t var options = this.options;\n\t var dataItem = options.dataItems && !options.maxDivisions ? options.dataItems[index] : null;\n\t var date = this.divisionRange.dateAt(index);\n\t var unitFormat = labelOptions.dateFormats[this.divisionRange.options.baseUnit];\n\n\t labelOptions.format = labelOptions.format || unitFormat;\n\t var text = this.axisLabelText(date, dataItem, labelOptions);\n\t if (text) {\n\t return new AxisLabel(date, text, index, dataItem, labelOptions);\n\t }\n\t },\n\n\t categoryIndex: function(value) {\n\t return this.dataRange.valueIndex(value);\n\t },\n\n\t slot: function(from, to, limit) {\n\t var dateRange = this.dataRange;\n\t var start = from;\n\t var end = to;\n\n\t if (start instanceof Date) {\n\t start = dateRange.dateIndex(start);\n\t }\n\n\t if (end instanceof Date) {\n\t end = dateRange.dateIndex(end);\n\t }\n\n\t var slot = this.getSlot(start, end, limit);\n\t if (slot) {\n\t return slot.toRect();\n\t }\n\t },\n\n\t getSlot: function(a, b, limit) {\n\t var start = a;\n\t var end = b;\n\n\t if (typeof start === OBJECT) {\n\t start = this.categoryIndex(start);\n\t }\n\n\t if (typeof end === OBJECT) {\n\t end = this.categoryIndex(end);\n\t }\n\n\t return CategoryAxis.fn.getSlot.call(this, start, end, limit);\n\t },\n\n\t valueRange: function() {\n\t var options = this.options;\n\t var range = categoryRange(options.srcCategories);\n\n\t return {\n\t min: toDate(range.min),\n\t max: toDate(range.max)\n\t };\n\t },\n\n\t categoryAt: function(index, total) {\n\t return this.dataRange.dateAt(index, total);\n\t },\n\n\t categoriesCount: function() {\n\t return this.dataRange.valuesCount();\n\t },\n\n\t rangeIndices: function() {\n\t return this.dataRange.displayIndices();\n\t },\n\n\t labelsBetweenTicks: function() {\n\t return !this.divisionRange.options.justified;\n\t },\n\n\t prepareUserOptions: function() {\n\t if (this.isEmpty()) {\n\t return;\n\t }\n\n\t this.options.categories = this.dataRange.values();\n\t },\n\n\t getCategory: function(point) {\n\t var index = this.pointCategoryIndex(point);\n\n\t if (index === null) {\n\t return null;\n\t }\n\n\t return this.dataRange.dateAt(index);\n\t },\n\n\t totalIndex: function(value) {\n\t return this.dataRange.totalIndex(value);\n\t },\n\n\t currentRangeIndices: function() {\n\t var range = this.dataRange.valueRange();\n\t return {\n\t min: this.dataRange.totalIndex(range.min),\n\t max: this.dataRange.totalIndex(range.max)\n\t };\n\t },\n\n\t totalRange: function() {\n\t return this.dataRange.total();\n\t },\n\n\t totalCount: function() {\n\t return this.dataRange.totalCount();\n\t },\n\n\t isEmpty: function() {\n\t return !this.options.srcCategories.length;\n\t },\n\n\t roundedRange: function() {\n\t if (this.options.roundToBaseUnit !== false || this.isEmpty()) {\n\t return this.range();\n\t }\n\n\t var options = this.options;\n\t var datesRange = categoryRange(options.srcCategories);\n\n\t var dateRange = new DateRange(datesRange.min, datesRange.max, $.extend({}, options, {\n\t justified: false,\n\t roundToBaseUnit: true,\n\t justifyEnd: options.justified\n\t }));\n\n\t return dateRange.displayRange();\n\t }\n\t});\n\n\tsetDefaultOptions(DateCategoryAxis, {\n\t type: DATE,\n\t labels: {\n\t dateFormats: DateLabelFormats\n\t },\n\t autoBaseUnitSteps: {\n\t milliseconds: [ 1, 10, 100 ],\n\t seconds: [ 1, 2, 5, 15, 30 ],\n\t minutes: [ 1, 2, 5, 15, 30 ],\n\t hours: [ 1, 2, 3 ],\n\t days: [ 1, 2, 3 ],\n\t weeks: [ 1, 2 ],\n\t months: [ 1, 2, 3, 6 ],\n\t years: [ 1, 2, 3, 5, 10, 25, 50 ]\n\t },\n\t maxDateGroups: 10\n\t});\n\n\tfunction autoAxisMin(min, max, narrow) {\n\t if (!min && !max) {\n\t return 0;\n\t }\n\n\t var axisMin;\n\n\t if (min >= 0 && max >= 0) {\n\t var minValue = min === max ? 0 : min;\n\n\t var diff = (max - minValue) / max;\n\t if (narrow === false || (!narrow && diff > ZERO_THRESHOLD)) {\n\t return 0;\n\t }\n\n\t axisMin = Math.max(0, minValue - ((max - minValue) / 2));\n\t } else {\n\t axisMin = min;\n\t }\n\n\t return axisMin;\n\t}\n\n\tfunction autoAxisMax(min, max, narrow) {\n\t if (!min && !max) {\n\t return 1;\n\t }\n\n\t var axisMax;\n\n\t if (min <= 0 && max <= 0) {\n\t var maxValue = min === max ? 0 : max;\n\n\t var diff = Math.abs((maxValue - min) / maxValue);\n\t if (narrow === false || (!narrow && diff > ZERO_THRESHOLD)) {\n\t return 0;\n\t }\n\n\t axisMax = Math.min(0, maxValue - ((min - maxValue) / 2));\n\t } else {\n\t axisMax = max;\n\t }\n\n\t return axisMax;\n\t}\n\n\tfunction floor(value, step) {\n\t return round(Math.floor(value / step) * step, DEFAULT_PRECISION);\n\t}\n\n\tfunction ceil(value, step) {\n\t return round(Math.ceil(value / step) * step, DEFAULT_PRECISION);\n\t}\n\n\tfunction limitCoordinate(value) {\n\t return Math.max(Math.min(value, COORDINATE_LIMIT), -COORDINATE_LIMIT);\n\t}\n\n\tvar MIN_VALUE_RANGE = Math.pow(10, -DEFAULT_PRECISION + 1);\n\n\tvar NumericAxis = Axis.extend({\n\t init: function(seriesMin, seriesMax, options, chartService) {\n\t Axis.fn.init.call(this, $.extend({}, options, {\n\t seriesMin: seriesMin,\n\t seriesMax: seriesMax\n\t }), chartService);\n\t },\n\n\t initUserOptions: function(options) {\n\t var autoOptions = autoAxisOptions(options.seriesMin, options.seriesMax, options);\n\t this.totalOptions = totalAxisOptions(autoOptions, options);\n\n\t return axisOptions(autoOptions, options);\n\t },\n\n\t initFields: function() {\n\t this.totalMin = this.totalOptions.min;\n\t this.totalMax = this.totalOptions.max;\n\t this.totalMajorUnit = this.totalOptions.majorUnit;\n\t this.seriesMin = this.options.seriesMin;\n\t this.seriesMax = this.options.seriesMax;\n\t },\n\n\t clone: function() {\n\t return new NumericAxis(\n\t this.seriesMin,\n\t this.seriesMax,\n\t $.extend({}, this.options),\n\t this.chartService\n\t );\n\t },\n\n\t startValue: function() {\n\t return 0;\n\t },\n\n\t range: function() {\n\t var options = this.options;\n\t return { min: options.min, max: options.max };\n\t },\n\n\t getDivisions: function(stepValue) {\n\t if (stepValue === 0) {\n\t return 1;\n\t }\n\n\t var options = this.options;\n\t var range = options.max - options.min;\n\n\t return Math.floor(round(range / stepValue, COORD_PRECISION)) + 1;\n\t },\n\n\t getTickPositions: function(unit, skipUnit) {\n\t var options = this.options;\n\t var vertical = options.vertical;\n\t var reverse = options.reverse;\n\t var lineBox = this.lineBox();\n\t var lineSize = vertical ? lineBox.height() : lineBox.width();\n\t var range = options.max - options.min;\n\t var scale = lineSize / range;\n\t var step = unit * scale;\n\t var divisions = this.getDivisions(unit);\n\t var dir = (vertical ? -1 : 1) * (reverse ? -1 : 1);\n\t var startEdge = dir === 1 ? 1 : 2;\n\t var positions = [];\n\t var pos = lineBox[(vertical ? Y : X) + startEdge];\n\t var skipStep = 0;\n\n\t if (skipUnit) {\n\t skipStep = skipUnit / unit;\n\t }\n\n\t for (var idx = 0; idx < divisions; idx++) {\n\t if (idx % skipStep !== 0) {\n\t positions.push(round(pos, COORD_PRECISION));\n\t }\n\n\t pos = pos + step * dir;\n\t }\n\n\t return positions;\n\t },\n\n\t getMajorTickPositions: function() {\n\t return this.getTickPositions(this.options.majorUnit);\n\t },\n\n\t getMinorTickPositions: function() {\n\t return this.getTickPositions(this.options.minorUnit);\n\t },\n\n\t getSlot: function(a, b, limit) {\n\t if (limit === void 0) { limit = false; }\n\n\t var options = this.options;\n\t var vertical = options.vertical;\n\t var reverse = options.reverse;\n\t var valueAxis = vertical ? Y : X;\n\t var lineBox = this.lineBox();\n\t var lineStart = lineBox[valueAxis + (reverse ? 2 : 1)];\n\t var lineSize = vertical ? lineBox.height() : lineBox.width();\n\t var dir = reverse ? -1 : 1;\n\t var step = dir * (lineSize / (options.max - options.min));\n\t var slotBox = new Box(lineBox.x1, lineBox.y1, lineBox.x1, lineBox.y1);\n\n\t var start = a;\n\t var end = b;\n\n\t if (!defined(start)) {\n\t start = end || 0;\n\t }\n\n\t if (!defined(end)) {\n\t end = start || 0;\n\t }\n\n\t if (limit) {\n\t start = Math.max(Math.min(start, options.max), options.min);\n\t end = Math.max(Math.min(end, options.max), options.min);\n\t }\n\n\t var p1, p2;\n\n\t if (vertical) {\n\t p1 = options.max - Math.max(start, end);\n\t p2 = options.max - Math.min(start, end);\n\t } else {\n\t p1 = Math.min(start, end) - options.min;\n\t p2 = Math.max(start, end) - options.min;\n\t }\n\n\t slotBox[valueAxis + 1] = limitCoordinate(lineStart + step * (reverse ? p2 : p1));\n\t slotBox[valueAxis + 2] = limitCoordinate(lineStart + step * (reverse ? p1 : p2));\n\n\t return slotBox;\n\t },\n\n\t getValue: function(point) {\n\t var options = this.options;\n\t var vertical = options.vertical;\n\t var reverse = options.reverse;\n\t var max = Number(options.max);\n\t var min = Number(options.min);\n\t var valueAxis = vertical ? Y : X;\n\t var lineBox = this.lineBox();\n\t var lineStart = lineBox[valueAxis + (reverse ? 2 : 1)];\n\t var lineSize = vertical ? lineBox.height() : lineBox.width();\n\t var dir = reverse ? -1 : 1;\n\t var offset = dir * (point[valueAxis] - lineStart);\n\t var step = (max - min) / lineSize;\n\t var valueOffset = offset * step;\n\n\t if (offset < 0 || offset > lineSize) {\n\t return null;\n\t }\n\n\t var value = vertical ?\n\t max - valueOffset :\n\t min + valueOffset;\n\n\t return round(value, DEFAULT_PRECISION);\n\t },\n\n\t translateRange: function(delta) {\n\t var options = this.options;\n\t var vertical = options.vertical;\n\t var reverse = options.reverse;\n\t var max = options.max;\n\t var min = options.min;\n\t var lineBox = this.lineBox();\n\t var size = vertical ? lineBox.height() : lineBox.width();\n\t var range = max - min;\n\t var scale = size / range;\n\t var offset = round(delta / scale, DEFAULT_PRECISION);\n\n\t if ((vertical || reverse) && !(vertical && reverse )) {\n\t offset = -offset;\n\t }\n\n\t return {\n\t min: min + offset,\n\t max: max + offset,\n\t offset: offset\n\t };\n\t },\n\n\t scaleRange: function(delta) {\n\t var options = this.options;\n\t var offset = -delta * options.majorUnit;\n\n\t return {\n\t min: options.min - offset,\n\t max: options.max + offset\n\t };\n\t },\n\n\t labelsCount: function() {\n\t return this.getDivisions(this.options.majorUnit);\n\t },\n\n\t createAxisLabel: function(index, labelOptions) {\n\t var options = this.options;\n\t var value = round(options.min + (index * options.majorUnit), DEFAULT_PRECISION);\n\t var text = this.axisLabelText(value, null, labelOptions);\n\n\t return new AxisLabel(value, text, index, null, labelOptions);\n\t },\n\n\t shouldRenderNote: function(value) {\n\t var range = this.range();\n\t return range.min <= value && value <= range.max;\n\t },\n\n\t pan: function(delta) {\n\t var range = this.translateRange(delta);\n\t return this.limitRange(range.min, range.max, this.totalMin, this.totalMax, range.offset);\n\t },\n\n\t pointsRange: function(start, end) {\n\t var startValue = this.getValue(start);\n\t var endValue = this.getValue(end);\n\t var min = Math.min(startValue, endValue);\n\t var max = Math.max(startValue, endValue);\n\n\t if (this.isValidRange(min, max)) {\n\t return {\n\t min: min,\n\t max: max\n\t };\n\t }\n\t },\n\n\t zoomRange: function(delta) {\n\t var ref = this;\n\t var totalMin = ref.totalMin;\n\t var totalMax = ref.totalMax;\n\t var newRange = this.scaleRange(delta);\n\t var min = limitValue(newRange.min, totalMin, totalMax);\n\t var max = limitValue(newRange.max, totalMin, totalMax);\n\n\t if (this.isValidRange(min, max)) {\n\t return {\n\t min: min,\n\t max: max\n\t };\n\t }\n\t },\n\n\t isValidRange: function(min, max) {\n\t return max - min > MIN_VALUE_RANGE;\n\t }\n\t});\n\n\tfunction autoAxisOptions(seriesMin, seriesMax, options) {\n\t var narrowRange = options.narrowRange;\n\n\t var autoMin = autoAxisMin(seriesMin, seriesMax, narrowRange);\n\t var autoMax = autoAxisMax(seriesMin, seriesMax, narrowRange);\n\n\t var majorUnit = autoMajorUnit(autoMin, autoMax);\n\t var autoOptions = {\n\t majorUnit: majorUnit\n\t };\n\n\t if (options.roundToMajorUnit !== false) {\n\t if (autoMin < 0 && remainderClose(autoMin, majorUnit, 1 / 3)) {\n\t autoMin -= majorUnit;\n\t }\n\n\t if (autoMax > 0 && remainderClose(autoMax, majorUnit, 1 / 3)) {\n\t autoMax += majorUnit;\n\t }\n\t }\n\n\t autoOptions.min = floor(autoMin, majorUnit);\n\t autoOptions.max = ceil(autoMax, majorUnit);\n\n\t return autoOptions;\n\t}\n\n\tfunction totalAxisOptions(autoOptions, options) {\n\t return {\n\t min: defined(options.min) ? Math.min(autoOptions.min, options.min) : autoOptions.min,\n\t max: defined(options.max) ? Math.max(autoOptions.max, options.max) : autoOptions.max,\n\t majorUnit: autoOptions.majorUnit\n\t };\n\t}\n\n\tfunction clearNullValues(options, fields) {\n\t for (var idx = 0; idx < fields.length; idx++) {\n\t var field = fields[idx];\n\t if (options[field] === null) {\n\t options[field] = undefined;\n\t }\n\t }\n\t}\n\n\tfunction axisOptions(autoOptions, userOptions) {\n\t var options = userOptions;\n\t var userSetMin, userSetMax;\n\n\t if (userOptions) {\n\t clearNullValues(userOptions, [ 'min', 'max' ]);\n\n\t userSetMin = defined(userOptions.min);\n\t userSetMax = defined(userOptions.max);\n\n\t var userSetLimits = userSetMin || userSetMax;\n\n\t if (userSetLimits) {\n\t if (userOptions.min === userOptions.max) {\n\t if (userOptions.min > 0) {\n\t userOptions.min = 0;\n\t } else {\n\t userOptions.max = 1;\n\t }\n\t }\n\t }\n\n\t if (userOptions.majorUnit) {\n\t autoOptions.min = floor(autoOptions.min, userOptions.majorUnit);\n\t autoOptions.max = ceil(autoOptions.max, userOptions.majorUnit);\n\t } else if (userSetLimits) {\n\t options = deepExtend(autoOptions, userOptions);\n\n\t // Determine an auto major unit after min/max have been set\n\t autoOptions.majorUnit = autoMajorUnit(options.min, options.max);\n\t }\n\t }\n\n\t autoOptions.minorUnit = (options.majorUnit || autoOptions.majorUnit) / 5;\n\n\t var result = deepExtend(autoOptions, options);\n\t if (result.min >= result.max) {\n\t if (userSetMin && !userSetMax) {\n\t result.max = result.min + result.majorUnit;\n\t } else if (!userSetMin && userSetMax) {\n\t result.min = result.max - result.majorUnit;\n\t }\n\t }\n\n\t return result;\n\t}\n\n\tfunction remainderClose(value, divisor, ratio) {\n\t var remainder = round(Math.abs(value % divisor), DEFAULT_PRECISION);\n\t var threshold = divisor * (1 - ratio);\n\n\t return remainder === 0 || remainder > threshold;\n\t}\n\n\tsetDefaultOptions(NumericAxis, {\n\t type: \"numeric\",\n\t min: 0,\n\t max: 1,\n\t vertical: true,\n\t majorGridLines: {\n\t visible: true,\n\t width: 1,\n\t color: BLACK\n\t },\n\t labels: {\n\t format: \"#.####################\"\n\t },\n\t zIndex: 1\n\t});\n\n\tvar DateValueAxis = Axis.extend({\n\t init: function(seriesMin, seriesMax, axisOptions, chartService) {\n\t var min = toDate(seriesMin);\n\t var max = toDate(seriesMax);\n\n\t var intlService = chartService.intl;\n\t var options = axisOptions || {};\n\t options = deepExtend(options || {}, {\n\t min: parseDate(intlService, options.min),\n\t max: parseDate(intlService, options.max),\n\t axisCrossingValue: parseDates(intlService, options.axisCrossingValues || options.axisCrossingValue)\n\t });\n\t options = applyDefaults(min, max, options);\n\n\t Axis.fn.init.call(this, options, chartService);\n\n\t this.intlService = intlService;\n\t this.seriesMin = min;\n\t this.seriesMax = max;\n\n\t var weekStartDay = options.weekStartDay || 0;\n\t this.totalMin = toTime(floorDate(toTime(min) - 1, options.baseUnit, weekStartDay));\n\t this.totalMax = toTime(ceilDate(toTime(max) + 1, options.baseUnit, weekStartDay));\n\t },\n\n\t clone: function() {\n\t return new DateValueAxis(this.seriesMin, this.seriesMax, $.extend({}, this.options), this.chartService);\n\t },\n\n\t range: function() {\n\t var options = this.options;\n\t return { min: options.min, max: options.max };\n\t },\n\n\t getDivisions: function(stepValue) {\n\t var options = this.options;\n\n\t return Math.floor(\n\t duration(options.min, options.max, options.baseUnit) / stepValue + 1\n\t );\n\t },\n\n\t getTickPositions: function(step) {\n\t var options = this.options;\n\t var vertical = options.vertical;\n\t var lineBox = this.lineBox();\n\t var dir = (vertical ? -1 : 1) * (options.reverse ? -1 : 1);\n\t var startEdge = dir === 1 ? 1 : 2;\n\t var start = lineBox[(vertical ? Y : X) + startEdge];\n\t var divisions = this.getDivisions(step);\n\t var timeRange = dateDiff(options.max, options.min);\n\t var lineSize = vertical ? lineBox.height() : lineBox.width();\n\t var scale = lineSize / timeRange;\n\t var weekStartDay = options.weekStartDay || 0;\n\n\t var positions = [ start ];\n\t for (var i = 1; i < divisions; i++) {\n\t var date = addDuration(options.min, i * step, options.baseUnit, weekStartDay);\n\t var pos = start + dateDiff(date, options.min) * scale * dir;\n\n\t positions.push(round(pos, COORD_PRECISION));\n\t }\n\n\t return positions;\n\t },\n\n\t getMajorTickPositions: function() {\n\t return this.getTickPositions(this.options.majorUnit);\n\t },\n\n\t getMinorTickPositions: function() {\n\t return this.getTickPositions(this.options.minorUnit);\n\t },\n\n\t getSlot: function(a, b, limit) {\n\t return NumericAxis.prototype.getSlot.call(\n\t this, parseDate(this.intlService, a), parseDate(this.intlService, b), limit\n\t );\n\t },\n\n\t getValue: function(point) {\n\t var value = NumericAxis.prototype.getValue.call(this, point);\n\n\t return value !== null ? toDate(value) : null;\n\t },\n\n\t labelsCount: function() {\n\t return this.getDivisions(this.options.majorUnit);\n\t },\n\n\t createAxisLabel: function(index, labelOptions) {\n\t var options = this.options;\n\t var offset = index * options.majorUnit;\n\t var weekStartDay = options.weekStartDay || 0;\n\t var date = options.min;\n\n\t if (offset > 0) {\n\t date = addDuration(date, offset, options.baseUnit, weekStartDay);\n\t }\n\n\t var unitFormat = labelOptions.dateFormats[options.baseUnit];\n\t labelOptions.format = labelOptions.format || unitFormat;\n\n\t var text = this.axisLabelText(date, null, labelOptions);\n\t return new AxisLabel(date, text, index, null, labelOptions);\n\t },\n\n\t translateRange: function(delta, exact) {\n\t var options = this.options;\n\t var baseUnit = options.baseUnit;\n\t var weekStartDay = options.weekStartDay || 0;\n\t var lineBox = this.lineBox();\n\t var size = options.vertical ? lineBox.height() : lineBox.width();\n\t var range = this.range();\n\t var scale = size / dateDiff(range.max, range.min);\n\t var offset = round(delta / scale, DEFAULT_PRECISION) * (options.reverse ? -1 : 1);\n\t var from = addTicks(options.min, offset);\n\t var to = addTicks(options.max, offset);\n\n\t if (!exact) {\n\t from = addDuration(from, 0, baseUnit, weekStartDay);\n\t to = addDuration(to, 0, baseUnit, weekStartDay);\n\t }\n\n\t return {\n\t min: from,\n\t max: to,\n\t offset: offset\n\t };\n\t },\n\n\t scaleRange: function(delta) {\n\t var ref = this.options;\n\t var from = ref.min;\n\t var to = ref.max;\n\t var rounds = Math.abs(delta);\n\n\t while (rounds--) {\n\t var range = dateDiff(from, to);\n\t var step = Math.round(range * 0.1);\n\t if (delta < 0) {\n\t from = addTicks(from, step);\n\t to = addTicks(to, -step);\n\t } else {\n\t from = addTicks(from, -step);\n\t to = addTicks(to, step);\n\t }\n\t }\n\n\t return { min: from, max: to };\n\t },\n\n\t shouldRenderNote: function(value) {\n\t var range = this.range();\n\n\t return dateComparer(value, range.min) >= 0 && dateComparer(value, range.max) <= 0;\n\t },\n\n\t pan: function(delta) {\n\t var range = this.translateRange(delta, true);\n\t var limittedRange = this.limitRange(toTime(range.min), toTime(range.max), this.totalMin, this.totalMax, range.offset);\n\n\t if (limittedRange) {\n\t return {\n\t min: toDate(limittedRange.min),\n\t max: toDate(limittedRange.max)\n\t };\n\t }\n\t },\n\n\t pointsRange: function(start, end) {\n\t var startValue = this.getValue(start);\n\t var endValue = this.getValue(end);\n\t var min = Math.min(startValue, endValue);\n\t var max = Math.max(startValue, endValue);\n\n\t return {\n\t min: toDate(min),\n\t max: toDate(max)\n\t };\n\t },\n\n\t zoomRange: function(delta) {\n\t var range = this.scaleRange(delta);\n\t var min = toDate(limitValue(toTime(range.min), this.totalMin, this.totalMax));\n\t var max = toDate(limitValue(toTime(range.max), this.totalMin, this.totalMax));\n\n\t return {\n\t min: min,\n\t max: max\n\t };\n\t }\n\t});\n\n\tfunction timeUnits(delta) {\n\t var unit = HOURS;\n\n\t if (delta >= TIME_PER_YEAR) {\n\t unit = YEARS;\n\t } else if (delta >= TIME_PER_MONTH) {\n\t unit = MONTHS;\n\t } else if (delta >= TIME_PER_WEEK) {\n\t unit = WEEKS;\n\t } else if (delta >= TIME_PER_DAY) {\n\t unit = DAYS;\n\t }\n\n\t return unit;\n\t}\n\n\tfunction applyDefaults(seriesMin, seriesMax, options) {\n\t var min = options.min || seriesMin;\n\t var max = options.max || seriesMax;\n\t var baseUnit = options.baseUnit || (max && min ? timeUnits(absoluteDateDiff(max, min)) : HOURS);\n\t var baseUnitTime = TIME_PER_UNIT[baseUnit];\n\t var weekStartDay = options.weekStartDay || 0;\n\t var autoMin = floorDate(toTime(min) - 1, baseUnit, weekStartDay) || toDate(max);\n\t var autoMax = ceilDate(toTime(max) + 1, baseUnit, weekStartDay);\n\t var userMajorUnit = options.majorUnit ? options.majorUnit : undefined;\n\t var majorUnit = userMajorUnit || ceil(\n\t autoMajorUnit(autoMin.getTime(), autoMax.getTime()),\n\t baseUnitTime\n\t ) / baseUnitTime;\n\t var actualUnits = duration(autoMin, autoMax, baseUnit);\n\t var totalUnits = ceil(actualUnits, majorUnit);\n\t var unitsToAdd = totalUnits - actualUnits;\n\t var head = Math.floor(unitsToAdd / 2);\n\t var tail = unitsToAdd - head;\n\n\t if (!options.baseUnit) {\n\t delete options.baseUnit;\n\t }\n\n\t options.baseUnit = options.baseUnit || baseUnit;\n\t options.min = options.min || addDuration(autoMin, -head, baseUnit, weekStartDay);\n\t options.max = options.max || addDuration(autoMax, tail, baseUnit, weekStartDay);\n\t options.minorUnit = options.minorUnit || majorUnit / 5;\n\t options.majorUnit = majorUnit;\n\n\t return options;\n\t}\n\n\tsetDefaultOptions(DateValueAxis, {\n\t type: DATE,\n\t majorGridLines: {\n\t visible: true,\n\t width: 1,\n\t color: BLACK\n\t },\n\t labels: {\n\t dateFormats: DateLabelFormats\n\t }\n\t});\n\n\tvar DEFAULT_MAJOR_UNIT = 10;\n\n\tvar LogarithmicAxis = Axis.extend({\n\t init: function(seriesMin, seriesMax, options, chartService) {\n\n\t var axisOptions = deepExtend({ majorUnit: DEFAULT_MAJOR_UNIT, min: seriesMin, max: seriesMax }, options);\n\t var base = axisOptions.majorUnit;\n\t var autoMax = autoAxisMax$1(seriesMax, base);\n\t var autoMin = autoAxisMin$1(seriesMin, seriesMax, axisOptions);\n\t var range = initRange(autoMin, autoMax, axisOptions, options);\n\n\t axisOptions.max = range.max;\n\t axisOptions.min = range.min;\n\t axisOptions.minorUnit = options.minorUnit || round(base - 1, DEFAULT_PRECISION);\n\n\t Axis.fn.init.call(this, axisOptions, chartService);\n\n\t this.totalMin = defined(options.min) ? Math.min(autoMin, options.min) : autoMin;\n\t this.totalMax = defined(options.max) ? Math.max(autoMax, options.max) : autoMax;\n\t this.logMin = round(log(range.min, base), DEFAULT_PRECISION);\n\t this.logMax = round(log(range.max, base), DEFAULT_PRECISION);\n\t this.seriesMin = seriesMin;\n\t this.seriesMax = seriesMax;\n\n\t this.createLabels();\n\t },\n\n\t clone: function() {\n\t return new LogarithmicAxis(\n\t this.seriesMin,\n\t this.seriesMax,\n\t $.extend({}, this.options),\n\t this.chartService\n\t );\n\t },\n\n\t startValue: function() {\n\t return this.options.min;\n\t },\n\n\t getSlot: function(a, b, limit) {\n\t var ref = this;\n\t var options = ref.options;\n\t var logMin = ref.logMin;\n\t var logMax = ref.logMax;\n\t var reverse = options.reverse;\n\t var vertical = options.vertical;\n\t var base = options.majorUnit;\n\t var valueAxis = vertical ? Y : X;\n\t var lineBox = this.lineBox();\n\t var lineStart = lineBox[valueAxis + (reverse ? 2 : 1)];\n\t var lineSize = vertical ? lineBox.height() : lineBox.width();\n\t var dir = reverse ? -1 : 1;\n\t var step = dir * (lineSize / (logMax - logMin));\n\t var slotBox = new Box(lineBox.x1, lineBox.y1, lineBox.x1, lineBox.y1);\n\t var start = a;\n\t var end = b;\n\n\t if (!defined(start)) {\n\t start = end || 1;\n\t }\n\n\t if (!defined(end)) {\n\t end = start || 1;\n\t }\n\n\t if (start <= 0 || end <= 0) {\n\t return null;\n\t }\n\n\t if (limit) {\n\t start = Math.max(Math.min(start, options.max), options.min);\n\t end = Math.max(Math.min(end, options.max), options.min);\n\t }\n\n\t start = log(start, base);\n\t end = log(end, base);\n\n\t var p1, p2;\n\n\t if (vertical) {\n\t p1 = logMax - Math.max(start, end);\n\t p2 = logMax - Math.min(start, end);\n\t } else {\n\t p1 = Math.min(start, end) - logMin;\n\t p2 = Math.max(start, end) - logMin;\n\t }\n\n\t slotBox[valueAxis + 1] = limitCoordinate(lineStart + step * (reverse ? p2 : p1));\n\t slotBox[valueAxis + 2] = limitCoordinate(lineStart + step * (reverse ? p1 : p2));\n\n\t return slotBox;\n\t },\n\n\t getValue: function(point) {\n\t var ref = this;\n\t var options = ref.options;\n\t var logMin = ref.logMin;\n\t var logMax = ref.logMax;\n\t var reverse = options.reverse;\n\t var vertical = options.vertical;\n\t var base = options.majorUnit;\n\t var lineBox = this.lineBox();\n\t var dir = vertical === reverse ? 1 : -1;\n\t var startEdge = dir === 1 ? 1 : 2;\n\t var lineSize = vertical ? lineBox.height() : lineBox.width();\n\t var step = ((logMax - logMin) / lineSize);\n\t var valueAxis = vertical ? Y : X;\n\t var lineStart = lineBox[valueAxis + startEdge];\n\t var offset = dir * (point[valueAxis] - lineStart);\n\t var valueOffset = offset * step;\n\n\t if (offset < 0 || offset > lineSize) {\n\t return null;\n\t }\n\n\t var value = logMin + valueOffset;\n\n\t return round(Math.pow(base, value), DEFAULT_PRECISION);\n\t },\n\n\t range: function() {\n\t var options = this.options;\n\t return { min: options.min, max: options.max };\n\t },\n\n\t scaleRange: function(delta) {\n\t var base = this.options.majorUnit;\n\t var offset = -delta;\n\n\t return {\n\t min: Math.pow(base, this.logMin - offset),\n\t max: Math.pow(base, this.logMax + offset)\n\t };\n\t },\n\n\t translateRange: function(delta) {\n\t var ref = this;\n\t var options = ref.options;\n\t var logMin = ref.logMin;\n\t var logMax = ref.logMax;\n\t var reverse = options.reverse;\n\t var vertical = options.vertical;\n\t var base = options.majorUnit;\n\t var lineBox = this.lineBox();\n\t var size = vertical ? lineBox.height() : lineBox.width();\n\t var scale = size / (logMax - logMin);\n\t var offset = round(delta / scale, DEFAULT_PRECISION);\n\n\t if ((vertical || reverse) && !(vertical && reverse )) {\n\t offset = -offset;\n\t }\n\n\t return {\n\t min: Math.pow(base, logMin + offset),\n\t max: Math.pow(base, logMax + offset),\n\t offset: offset\n\t };\n\t },\n\n\t labelsCount: function() {\n\t var floorMax = Math.floor(this.logMax);\n\t var count = Math.floor(floorMax - this.logMin) + 1;\n\n\t return count;\n\t },\n\n\t getMajorTickPositions: function() {\n\t var ticks = [];\n\n\t this.traverseMajorTicksPositions(function (position) {\n\t ticks.push(position);\n\t }, { step: 1, skip: 0 });\n\n\t return ticks;\n\t },\n\n\t createTicks: function(lineGroup) {\n\t var options = this.options;\n\t var majorTicks = options.majorTicks;\n\t var minorTicks = options.minorTicks;\n\t var vertical = options.vertical;\n\t var mirror = options.labels.mirror;\n\t var lineBox = this.lineBox();\n\t var ticks = [];\n\t var tickLineOptions = {\n\t // TODO\n\t // _alignLines: options._alignLines,\n\t vertical: vertical\n\t };\n\n\t function render(tickPosition, tickOptions) {\n\t tickLineOptions.tickX = mirror ? lineBox.x2 : lineBox.x2 - tickOptions.size;\n\t tickLineOptions.tickY = mirror ? lineBox.y1 - tickOptions.size : lineBox.y1;\n\t tickLineOptions.position = tickPosition;\n\n\t lineGroup.append(createAxisTick(tickLineOptions, tickOptions));\n\t }\n\n\t if (majorTicks.visible) {\n\t this.traverseMajorTicksPositions(render, majorTicks);\n\t }\n\n\t if (minorTicks.visible) {\n\t this.traverseMinorTicksPositions(render, minorTicks);\n\t }\n\n\t return ticks;\n\t },\n\n\t createGridLines: function(altAxis) {\n\t var options = this.options;\n\t var minorGridLines = options.minorGridLines;\n\t var majorGridLines = options.majorGridLines;\n\t var vertical = options.vertical;\n\t var lineBox = altAxis.lineBox();\n\t var lineOptions = {\n\t lineStart: lineBox[vertical ? \"x1\" : \"y1\"],\n\t lineEnd: lineBox[vertical ? \"x2\" : \"y2\"],\n\t vertical: vertical\n\t };\n\t var majorTicks = [];\n\n\t var container = this.gridLinesVisual();\n\t function render(tickPosition, gridLine) {\n\t if (!inArray(tickPosition, majorTicks)) {\n\t lineOptions.position = tickPosition;\n\t container.append(createAxisGridLine(lineOptions, gridLine));\n\n\t majorTicks.push(tickPosition);\n\t }\n\t }\n\n\t if (majorGridLines.visible) {\n\t this.traverseMajorTicksPositions(render, majorGridLines);\n\t }\n\n\t if (minorGridLines.visible) {\n\t this.traverseMinorTicksPositions(render, minorGridLines);\n\t }\n\n\t return container.children;\n\t },\n\n\t traverseMajorTicksPositions: function(callback, tickOptions) {\n\t var ref = this._lineOptions();\n\t var lineStart = ref.lineStart;\n\t var step = ref.step;\n\t var ref$1 = this;\n\t var logMin = ref$1.logMin;\n\t var logMax = ref$1.logMax;\n\n\t for (var power = Math.ceil(logMin) + tickOptions.skip; power <= logMax; power += tickOptions.step) {\n\t var position = round(lineStart + step * (power - logMin), DEFAULT_PRECISION);\n\t callback(position, tickOptions);\n\t }\n\t },\n\n\t traverseMinorTicksPositions: function(callback, tickOptions) {\n\t var this$1 = this;\n\n\t var ref = this.options;\n\t var min = ref.min;\n\t var max = ref.max;\n\t var minorUnit = ref.minorUnit;\n\t var base = ref.majorUnit;\n\t var ref$1 = this._lineOptions();\n\t var lineStart = ref$1.lineStart;\n\t var step = ref$1.step;\n\t var ref$2 = this;\n\t var logMin = ref$2.logMin;\n\t var logMax = ref$2.logMax;\n\t var start = Math.floor(logMin);\n\n\t for (var power = start; power < logMax; power++) {\n\t var minorOptions = this$1._minorIntervalOptions(power);\n\t for (var idx = tickOptions.skip; idx < minorUnit; idx += tickOptions.step) {\n\t var value = minorOptions.value + idx * minorOptions.minorStep;\n\t if (value > max) {\n\t break;\n\t }\n\t if (value >= min) {\n\t var position = round(lineStart + step * (log(value, base) - logMin), DEFAULT_PRECISION);\n\t callback(position, tickOptions);\n\t }\n\t }\n\t }\n\t },\n\n\t createAxisLabel: function(index, labelOptions) {\n\t var power = Math.ceil(this.logMin + index);\n\t var value = Math.pow(this.options.majorUnit, power);\n\t var text = this.axisLabelText(value, null, labelOptions);\n\n\t return new AxisLabel(value, text, index, null, labelOptions);\n\t },\n\n\t shouldRenderNote: function(value) {\n\t var range = this.range();\n\t return range.min <= value && value <= range.max;\n\t },\n\n\t pan: function(delta) {\n\t var range = this.translateRange(delta);\n\t return this.limitRange(range.min, range.max, this.totalMin, this.totalMax, range.offset);\n\t },\n\n\t pointsRange: function(start, end) {\n\t var startValue = this.getValue(start);\n\t var endValue = this.getValue(end);\n\t var min = Math.min(startValue, endValue);\n\t var max = Math.max(startValue, endValue);\n\n\t return {\n\t min: min,\n\t max: max\n\t };\n\t },\n\n\t zoomRange: function(delta) {\n\t var ref = this;\n\t var options = ref.options;\n\t var totalMin = ref.totalMin;\n\t var totalMax = ref.totalMax;\n\t var newRange = this.scaleRange(delta);\n\t var min = limitValue(newRange.min, totalMin, totalMax);\n\t var max = limitValue(newRange.max, totalMin, totalMax);\n\t var base = options.majorUnit;\n\t var acceptOptionsRange = max > min && options.min && options.max && (round(log(options.max, base) - log(options.min, base), DEFAULT_PRECISION) < 1);\n\t var acceptNewRange = !(options.min === totalMin && options.max === totalMax) && round(log(max, base) - log(min, base), DEFAULT_PRECISION) >= 1;\n\n\t if (acceptOptionsRange || acceptNewRange) {\n\t return {\n\t min: min,\n\t max: max\n\t };\n\t }\n\t },\n\n\t _minorIntervalOptions: function(power) {\n\t var ref = this.options;\n\t var minorUnit = ref.minorUnit;\n\t var base = ref.majorUnit;\n\t var value = Math.pow(base, power);\n\t var nextValue = Math.pow(base, power + 1);\n\t var difference = nextValue - value;\n\t var minorStep = difference / minorUnit;\n\n\t return {\n\t value: value,\n\t minorStep: minorStep\n\t };\n\t },\n\n\t _lineOptions: function() {\n\t var ref = this.options;\n\t var reverse = ref.reverse;\n\t var vertical = ref.vertical;\n\t var valueAxis = vertical ? Y : X;\n\t var lineBox = this.lineBox();\n\t var dir = vertical === reverse ? 1 : -1;\n\t var startEdge = dir === 1 ? 1 : 2;\n\t var lineSize = vertical ? lineBox.height() : lineBox.width();\n\t var step = dir * (lineSize / (this.logMax - this.logMin));\n\t var lineStart = lineBox[valueAxis + startEdge];\n\n\t return {\n\t step: step,\n\t lineStart: lineStart,\n\t lineBox: lineBox\n\t };\n\t }\n\t});\n\n\tfunction initRange(autoMin, autoMax, axisOptions, options) {\n\t var min = axisOptions.min;\n\t var max = axisOptions.max;\n\n\t if (defined(axisOptions.axisCrossingValue) && axisOptions.axisCrossingValue <= 0) {\n\t throwNegativeValuesError();\n\t }\n\n\t if (!defined(options.max)) {\n\t max = autoMax;\n\t } else if (options.max <= 0) {\n\t throwNegativeValuesError();\n\t }\n\n\t if (!defined(options.min)) {\n\t min = autoMin;\n\t } else if (options.min <= 0) {\n\t throwNegativeValuesError();\n\t }\n\n\t return {\n\t min: min,\n\t max: max\n\t };\n\t}\n\n\tfunction autoAxisMin$1(min, max, options) {\n\t var base = options.majorUnit;\n\t var autoMin = min;\n\t if (min <= 0) {\n\t autoMin = max <= 1 ? Math.pow(base, -2) : 1;\n\t } else if (!options.narrowRange) {\n\t autoMin = Math.pow(base, Math.floor(log(min, base)));\n\t }\n\t return autoMin;\n\t}\n\n\tfunction autoAxisMax$1(max, base) {\n\t var logMaxRemainder = round(log(max, base), DEFAULT_PRECISION) % 1;\n\t var autoMax;\n\t if (max <= 0) {\n\t autoMax = base;\n\t } else if (logMaxRemainder !== 0 && (logMaxRemainder < 0.3 || logMaxRemainder > 0.9)) {\n\t autoMax = Math.pow(base, log(max, base) + 0.2);\n\t } else {\n\t autoMax = Math.pow(base, Math.ceil(log(max, base)));\n\t }\n\n\t return autoMax;\n\t}\n\n\tfunction throwNegativeValuesError() {\n\t throw new Error(\"Non positive values cannot be used for a logarithmic axis\");\n\t}\n\n\tfunction log(y, x) {\n\t return Math.log(y) / Math.log(x);\n\t}\n\n\tsetDefaultOptions(LogarithmicAxis, {\n\t type: \"log\",\n\t majorUnit: DEFAULT_MAJOR_UNIT,\n\t minorUnit: 1,\n\t axisCrossingValue: 1,\n\t vertical: true,\n\t majorGridLines: {\n\t visible: true,\n\t width: 1,\n\t color: BLACK\n\t },\n\t zIndex: 1,\n\t _deferLabels: true\n\t});\n\n\tvar GridLinesMixin = {\n\t createGridLines: function(altAxis) {\n\t var options = this.options;\n\t var radius = Math.abs(this.box.center().y - altAxis.lineBox().y1);\n\t var gridLines = [];\n\t var skipMajor = false;\n\t var majorAngles, minorAngles;\n\n\t if (options.majorGridLines.visible) {\n\t majorAngles = this.majorGridLineAngles(altAxis);\n\t skipMajor = true;\n\n\t gridLines = this.renderMajorGridLines(\n\t majorAngles, radius, options.majorGridLines\n\t );\n\t }\n\n\t if (options.minorGridLines.visible) {\n\t minorAngles = this.minorGridLineAngles(altAxis, skipMajor);\n\n\t append(gridLines, this.renderMinorGridLines(\n\t minorAngles, radius, options.minorGridLines, altAxis, skipMajor\n\t ));\n\t }\n\n\t return gridLines;\n\t },\n\n\t renderMajorGridLines: function(angles, radius, options) {\n\t return this.renderGridLines(angles, radius, options);\n\t },\n\n\t renderMinorGridLines: function(angles, radius, options, altAxis, skipMajor) {\n\t var radiusCallback = this.radiusCallback && this.radiusCallback(radius, altAxis, skipMajor);\n\t return this.renderGridLines(angles, radius, options, radiusCallback);\n\t },\n\n\t renderGridLines: function(angles, radius, options, radiusCallback) {\n\t var style = {\n\t stroke: {\n\t width: options.width,\n\t color: options.color,\n\t dashType: options.dashType\n\t }\n\t };\n\n\t var center = this.box.center();\n\t var circle = new Circle([ center.x, center.y ], radius);\n\t var container = this.gridLinesVisual();\n\n\t for (var i = 0; i < angles.length; i++) {\n\t var line = new Path(style);\n\t if (radiusCallback) {\n\t circle.radius = radiusCallback(angles[i]);\n\t }\n\n\t line.moveTo(circle.center)\n\t .lineTo(circle.pointAt(angles[i] + 180));\n\n\t container.append(line);\n\t }\n\n\t return container.children;\n\t },\n\n\t gridLineAngles: function(altAxis, size, skip, step, skipAngles) {\n\t var this$1 = this;\n\n\t var divs = this.intervals(size, skip, step, skipAngles);\n\t var options = altAxis.options;\n\t var altAxisVisible = options.visible && (options.line || {}).visible !== false;\n\n\t return map(divs, function (d) {\n\t var alpha = this$1.intervalAngle(d);\n\n\t if (!altAxisVisible || alpha !== 90) {\n\t return alpha;\n\t }\n\t });\n\t }\n\t};\n\n\tvar RadarCategoryAxis = CategoryAxis.extend({\n\t range: function() {\n\t return { min: 0, max: this.options.categories.length };\n\t },\n\n\t reflow: function(box) {\n\t this.box = box;\n\t this.reflowLabels();\n\t },\n\n\t lineBox: function() {\n\t return this.box;\n\t },\n\n\t reflowLabels: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var labels = ref.labels;\n\t var labelOptions = ref.options.labels;\n\t var skip = labelOptions.skip || 0;\n\t var step = labelOptions.step || 1;\n\t var measureBox = new Box();\n\n\t for (var i = 0; i < labels.length; i++) {\n\t labels[i].reflow(measureBox);\n\t var labelBox = labels[i].box;\n\n\t labels[i].reflow(this$1.getSlot(skip + i * step).adjacentBox(\n\t 0, labelBox.width(), labelBox.height()\n\t ));\n\t }\n\t },\n\n\t intervals: function(size, skipOption, stepOption, skipAngles) {\n\t if (skipAngles === void 0) { skipAngles = false; }\n\n\t var options = this.options;\n\t var categories = options.categories.length;\n\t var divCount = categories / size || 1;\n\t var divAngle = 360 / divCount;\n\t var skip = skipOption || 0;\n\t var step = stepOption || 1;\n\t var divs = [];\n\t var angle = 0;\n\n\t for (var i = skip; i < divCount; i += step) {\n\t if (options.reverse) {\n\t angle = 360 - i * divAngle;\n\t } else {\n\t angle = i * divAngle;\n\t }\n\n\t angle = round(angle, COORD_PRECISION) % 360;\n\n\t if (!(skipAngles && inArray(angle, skipAngles))) {\n\t divs.push(angle);\n\t }\n\t }\n\n\t return divs;\n\t },\n\n\t majorIntervals: function() {\n\t return this.intervals(1);\n\t },\n\n\t minorIntervals: function() {\n\t return this.intervals(0.5);\n\t },\n\n\t intervalAngle: function(interval) {\n\t return (360 + interval + this.options.startAngle) % 360;\n\t },\n\n\t majorAngles: function() {\n\t var this$1 = this;\n\n\t return map(this.majorIntervals(), function (interval) { return this$1.intervalAngle(interval); });\n\t },\n\n\t createLine: function() {\n\t return [];\n\t },\n\n\t majorGridLineAngles: function(altAxis) {\n\t var majorGridLines = this.options.majorGridLines;\n\t return this.gridLineAngles(altAxis, 1, majorGridLines.skip, majorGridLines.step);\n\t },\n\n\t minorGridLineAngles: function(altAxis, skipMajor) {\n\t var ref = this.options;\n\t var minorGridLines = ref.minorGridLines;\n\t var majorGridLines = ref.majorGridLines;\n\t var majorGridLineAngles = skipMajor ? this.intervals(1, majorGridLines.skip, majorGridLines.step) : null;\n\n\t return this.gridLineAngles(altAxis, 0.5, minorGridLines.skip, minorGridLines.step, majorGridLineAngles);\n\t },\n\n\t radiusCallback: function(radius, altAxis, skipMajor) {\n\t if (altAxis.options.type !== ARC) {\n\t var minorAngle = rad(360 / (this.options.categories.length * 2));\n\t var minorRadius = Math.cos(minorAngle) * radius;\n\t var majorAngles = this.majorAngles();\n\n\t var radiusCallback = function(angle) {\n\t if (!skipMajor && inArray(angle, majorAngles)) {\n\t return radius;\n\t }\n\n\t return minorRadius;\n\t };\n\t return radiusCallback;\n\t }\n\t },\n\n\t createPlotBands: function() {\n\t var this$1 = this;\n\n\t var plotBands = this.options.plotBands || [];\n\n\t var group = this._plotbandGroup = new Group({\n\t zIndex: -1\n\t });\n\n\t for (var i = 0; i < plotBands.length; i++) {\n\t var band = plotBands[i];\n\t var slot = this$1.plotBandSlot(band);\n\t var singleSlot = this$1.getSlot(band.from);\n\n\t var head = band.from - Math.floor(band.from);\n\t slot.startAngle += head * singleSlot.angle;\n\n\t var tail = Math.ceil(band.to) - band.to;\n\t slot.angle -= (tail + head) * singleSlot.angle;\n\n\t var ring = ShapeBuilder.current.createRing(slot, {\n\t fill: {\n\t color: band.color,\n\t opacity: band.opacity\n\t },\n\t stroke: {\n\t opacity: band.opacity\n\t }\n\t });\n\t group.append(ring);\n\t }\n\n\t this.appendVisual(group);\n\t },\n\n\t plotBandSlot: function(band) {\n\t return this.getSlot(band.from, band.to - 1);\n\t },\n\n\t getSlot: function(from, to) {\n\t var options = this.options;\n\t var justified = options.justified;\n\t var box = this.box;\n\t var divs = this.majorAngles();\n\t var totalDivs = divs.length;\n\t var slotAngle = 360 / totalDivs;\n\t var fromValue = from;\n\n\t if (options.reverse && !justified) {\n\t fromValue = (fromValue + 1) % totalDivs;\n\t }\n\n\t fromValue = limitValue(Math.floor(fromValue), 0, totalDivs - 1);\n\t var slotStart = divs[fromValue];\n\n\t if (justified) {\n\t slotStart = slotStart - slotAngle / 2;\n\n\t if (slotStart < 0) {\n\t slotStart += 360;\n\t }\n\t }\n\n\t var toValue = limitValue(Math.ceil(to || fromValue), fromValue, totalDivs - 1);\n\t var slots = toValue - fromValue + 1;\n\t var angle = slotAngle * slots;\n\n\t return new Ring(box.center(), 0, box.height() / 2, slotStart, angle);\n\t },\n\n\t slot: function(from, to) {\n\t var slot = this.getSlot(from, to);\n\t var startAngle = slot.startAngle + 180;\n\t var endAngle = startAngle + slot.angle;\n\n\t return new geometry.Arc([ slot.center.x, slot.center.y ], {\n\t startAngle: startAngle,\n\t endAngle: endAngle,\n\t radiusX: slot.radius,\n\t radiusY: slot.radius\n\t });\n\t },\n\n\t pointCategoryIndex: function(point) {\n\t var this$1 = this;\n\n\t var length = this.options.categories.length;\n\t var index = null;\n\n\t for (var i = 0; i < length; i++) {\n\t var slot = this$1.getSlot(i);\n\t if (slot.containsPoint(point)) {\n\t index = i;\n\t break;\n\t }\n\t }\n\n\t return index;\n\t }\n\t});\n\n\tsetDefaultOptions(RadarCategoryAxis, {\n\t startAngle: 90,\n\t labels: {\n\t margin: getSpacing(10)\n\t },\n\t majorGridLines: {\n\t visible: true\n\t },\n\t justified: true\n\t});\n\tdeepExtend(RadarCategoryAxis.prototype, GridLinesMixin);\n\n\tvar PolarAxis = Axis.extend({\n\t init: function(options, chartService) {\n\t Axis.fn.init.call(this, options, chartService);\n\n\t var instanceOptions = this.options;\n\n\t instanceOptions.minorUnit = instanceOptions.minorUnit || instanceOptions.majorUnit / 2;\n\t },\n\n\t getDivisions: function(stepValue) {\n\t return NumericAxis.prototype.getDivisions.call(this, stepValue) - 1;\n\t },\n\n\t reflow: function(box) {\n\t this.box = box;\n\t this.reflowLabels();\n\t },\n\n\t reflowLabels: function() {\n\t var this$1 = this;\n\n\t var ref = this;\n\t var options = ref.options;\n\t var labels = ref.labels;\n\t var labelOptions = ref.options.labels;\n\t var skip = labelOptions.skip || 0;\n\t var step = labelOptions.step || 1;\n\n\t var measureBox = new Box();\n\t var divs = this.intervals(options.majorUnit, skip, step);\n\n\t for (var i = 0; i < labels.length; i++) {\n\t labels[i].reflow(measureBox);\n\t var labelBox = labels[i].box;\n\n\t labels[i].reflow(this$1.getSlot(divs[i]).adjacentBox(0, labelBox.width(), labelBox.height()));\n\t }\n\t },\n\n\t lineBox: function() {\n\t return this.box;\n\t },\n\n\t intervals: function(size, skipOption, stepOption, skipAngles) {\n\t if (skipAngles === void 0) { skipAngles = false; }\n\n\t var min = this.options.min;\n\t var divisions = this.getDivisions(size);\n\t var divs = [];\n\t var skip = skipOption || 0;\n\t var step = stepOption || 1;\n\n\t for (var i = skip; i < divisions; i += step) {\n\t var current = (360 + min + i * size) % 360;\n\t if (!(skipAngles && inArray(current, skipAngles))) {\n\t divs.push(current);\n\t }\n\t }\n\n\t return divs;\n\t },\n\n\t majorIntervals: function() {\n\t return this.intervals(this.options.majorUnit);\n\t },\n\n\t minorIntervals: function() {\n\t return this.intervals(this.options.minorUnit);\n\t },\n\n\t intervalAngle: function(i) {\n\t return (540 - i - this.options.startAngle) % 360;\n\t },\n\n\t createLine: function() {\n\t return [];\n\t },\n\n\t majorGridLineAngles: function(altAxis) {\n\t var majorGridLines = this.options.majorGridLines;\n\t return this.gridLineAngles(altAxis, this.options.majorUnit, majorGridLines.skip, majorGridLines.step);\n\t },\n\n\t minorGridLineAngles: function(altAxis, skipMajor) {\n\t var options = this.options;\n\t var minorGridLines = options.minorGridLines;\n\t var majorGridLines = options.majorGridLines;\n\t var majorGridLineAngles = skipMajor ? this.intervals(options.majorUnit, majorGridLines.skip, majorGridLines.step) : null;\n\n\t return this.gridLineAngles(altAxis, options.minorUnit, minorGridLines.skip, minorGridLines.step, majorGridLineAngles);\n\t },\n\n\t plotBandSlot: function(band) {\n\t return this.getSlot(band.from, band.to);\n\t },\n\n\t getSlot: function(a, b) {\n\t var ref = this;\n\t var options = ref.options;\n\t var box = ref.box;\n\t var startAngle = options.startAngle;\n\t var start = limitValue(a, options.min, options.max);\n\t var end = limitValue(b || start, start, options.max);\n\n\t if (options.reverse) {\n\t start *= -1;\n\t end *= -1;\n\t }\n\n\t start = (540 - start - startAngle) % 360;\n\t end = (540 - end - startAngle) % 360;\n\n\t if (end < start) {\n\t var tmp = start;\n\t start = end;\n\t end = tmp;\n\t }\n\n\t return new Ring(box.center(), 0, box.height() / 2, start, end - start);\n\t },\n\n\t slot: function(from, to) {\n\t if (to === void 0) { to = from; }\n\n\t var options = this.options;\n\t var start = 360 - options.startAngle;\n\t var slot = this.getSlot(from, to);\n\t var min = Math.min(from, to);\n\t var max = Math.max(from, to);\n\t var startAngle, endAngle;\n\n\t if (options.reverse) {\n\t startAngle = min;\n\t endAngle = max;\n\t } else {\n\t startAngle = 360 - max;\n\t endAngle = 360 - min;\n\t }\n\n\t startAngle = (startAngle + start) % 360;\n\t endAngle = (endAngle + start) % 360;\n\n\t return new geometry.Arc([ slot.center.x, slot.center.y ], {\n\t startAngle: startAngle,\n\t endAngle: endAngle,\n\t radiusX: slot.radius,\n\t radiusY: slot.radius\n\t });\n\t },\n\n\t getValue: function(point) {\n\t var options = this.options;\n\t var center = this.box.center();\n\t var dx = point.x - center.x;\n\t var dy = point.y - center.y;\n\t var theta = Math.round(deg(Math.atan2(dy, dx)));\n\t var start = options.startAngle;\n\n\t if (!options.reverse) {\n\t theta *= -1;\n\t start *= -1;\n\t }\n\n\t return (theta + start + 360) % 360;\n\t },\n\n\t valueRange: function() {\n\t return {\n\t min: 0,\n\t max: Math.PI * 2\n\t };\n\t }\n\t});\n\n\tsetDefaultOptions(PolarAxis, {\n\t type: \"polar\",\n\t startAngle: 0,\n\t reverse: false,\n\t majorUnit: 60,\n\t min: 0,\n\t max: 360,\n\t labels: {\n\t margin: getSpacing(10)\n\t },\n\t majorGridLines: {\n\t color: BLACK,\n\t visible: true,\n\t width: 1\n\t },\n\t minorGridLines: {\n\t color: \"#aaa\"\n\t }\n\t});\n\n\tdeepExtend(PolarAxis.prototype, GridLinesMixin, {\n\t createPlotBands: RadarCategoryAxis.prototype.createPlotBands,\n\t majorAngles: RadarCategoryAxis.prototype.majorAngles,\n\t range: NumericAxis.prototype.range,\n\t labelsCount: NumericAxis.prototype.labelsCount,\n\t createAxisLabel: NumericAxis.prototype.createAxisLabel\n\t});\n\n\tvar RadarNumericAxisMixin = {\n\t options: {\n\t majorGridLines: {\n\t visible: true\n\t }\n\t },\n\n\t createPlotBands: function() {\n\t var this$1 = this;\n\n\t var ref = this.options;\n\t var type = ref.majorGridLines.type;\n\t var plotBands = ref.plotBands; if (plotBands === void 0) { plotBands = []; }\n\t var altAxis = this.plotArea.polarAxis;\n\t var majorAngles = altAxis.majorAngles();\n\t var center = altAxis.box.center();\n\t var group = this._plotbandGroup = new Group({\n\t zIndex: -1\n\t });\n\n\t for (var i = 0; i < plotBands.length; i++) {\n\t var band = plotBands[i];\n\t var bandStyle = {\n\t fill: {\n\t color: band.color,\n\t opacity: band.opacity\n\t },\n\t stroke: {\n\t opacity: band.opacity\n\t }\n\t };\n\n\t var slot = this$1.getSlot(band.from, band.to, true);\n\t var ring = new Ring(center, center.y - slot.y2, center.y - slot.y1, 0, 360);\n\n\t var shape = (void 0);\n\t if (type === ARC) {\n\t shape = ShapeBuilder.current.createRing(ring, bandStyle);\n\t } else {\n\t shape = Path.fromPoints(this$1.plotBandPoints(ring, majorAngles), bandStyle).close();\n\t }\n\n\t group.append(shape);\n\t }\n\n\t this.appendVisual(group);\n\t },\n\n\t plotBandPoints: function(ring, angles) {\n\t var innerPoints = [];\n\t var outerPoints = [];\n\t var center = [ ring.center.x, ring.center.y ];\n\t var innerCircle = new Circle(center, ring.innerRadius);\n\t var outerCircle = new Circle(center, ring.radius);\n\n\t for (var i = 0; i < angles.length; i++) {\n\t innerPoints.push(innerCircle.pointAt(angles[i] + 180));\n\t outerPoints.push(outerCircle.pointAt(angles[i] + 180));\n\t }\n\n\t innerPoints.reverse();\n\t innerPoints.push(innerPoints[0]);\n\t outerPoints.push(outerPoints[0]);\n\n\t return outerPoints.concat(innerPoints);\n\t },\n\n\t createGridLines: function(altAxis) {\n\t var options = this.options;\n\t var majorTicks = this.radarMajorGridLinePositions();\n\t var majorAngles = altAxis.majorAngles();\n\t var center = altAxis.box.center();\n\t var gridLines = [];\n\n\t if (options.majorGridLines.visible) {\n\t gridLines = this.renderGridLines(\n\t center, majorTicks, majorAngles, options.majorGridLines\n\t );\n\t }\n\n\t if (options.minorGridLines.visible) {\n\t var minorTicks = this.radarMinorGridLinePositions();\n\t append(gridLines, this.renderGridLines(\n\t center, minorTicks, majorAngles, options.minorGridLines\n\t ));\n\t }\n\n\t return gridLines;\n\t },\n\n\t renderGridLines: function(center, ticks, angles, options) {\n\t var style = {\n\t stroke: {\n\t width: options.width,\n\t color: options.color,\n\t dashType: options.dashType\n\t }\n\t };\n\t var skip = options.skip; if (skip === void 0) { skip = 0; }\n\t var step = options.step; if (step === void 0) { step = 0; }\n\t var container = this.gridLinesVisual();\n\n\t for (var tickIx = skip; tickIx < ticks.length; tickIx += step) {\n\t var tickRadius = center.y - ticks[tickIx];\n\t if (tickRadius > 0) {\n\t var circle = new Circle([ center.x, center.y ], tickRadius);\n\t if (options.type === ARC) {\n\t container.append(new drawing.Circle(circle, style));\n\t } else {\n\t var line = new Path(style);\n\t for (var angleIx = 0; angleIx < angles.length; angleIx++) {\n\t line.lineTo(circle.pointAt(angles[angleIx] + 180));\n\t }\n\n\t line.close();\n\t container.append(line);\n\t }\n\t }\n\t }\n\n\t return container.children;\n\t },\n\n\t getValue: function(point) {\n\t var lineBox = this.lineBox();\n\t var altAxis = this.plotArea.polarAxis;\n\t var majorAngles = altAxis.majorAngles();\n\t var center = altAxis.box.center();\n\t var radius = point.distanceTo(center);\n\t var distance = radius;\n\n\t if (this.options.majorGridLines.type !== ARC && majorAngles.length > 1) {\n\t var dx = point.x - center.x;\n\t var dy = point.y - center.y;\n\t var theta = (deg(Math.atan2(dy, dx)) + 540) % 360;\n\n\t majorAngles.sort(function(a, b) {\n\t return angularDistance(a, theta) - angularDistance(b, theta);\n\t });\n\n\t // Solve triangle (center, point, axis X) using one side (radius) and two angles.\n\t // Angles are derived from triangle (center, point, gridline X)\n\t var midAngle = angularDistance(majorAngles[0], majorAngles[1]) / 2;\n\t var alpha = angularDistance(theta, majorAngles[0]);\n\t var gamma = 90 - midAngle;\n\t var beta = 180 - alpha - gamma;\n\n\t distance = radius * (Math.sin(rad(beta)) / Math.sin(rad(gamma)));\n\t }\n\n\t return this.axisType().prototype.getValue.call(\n\t this, new Point(lineBox.x1, lineBox.y2 - distance)\n\t );\n\t }\n\t};\n\n\tfunction angularDistance(a, b) {\n\t return 180 - Math.abs(Math.abs(a - b) - 180);\n\t}\n\n\tvar RadarNumericAxis = NumericAxis.extend({\n\t radarMajorGridLinePositions: function() {\n\t return this.getTickPositions(this.options.majorUnit);\n\t },\n\n\t radarMinorGridLinePositions: function() {\n\t var options = this.options;\n\t var minorSkipStep = 0;\n\n\t if (options.majorGridLines.visible) {\n\t minorSkipStep = options.majorUnit;\n\t }\n\t return this.getTickPositions(options.minorUnit, minorSkipStep);\n\t },\n\n\t axisType: function() {\n\t return NumericAxis;\n\t }\n\t});\n\n\tdeepExtend(RadarNumericAxis.prototype, RadarNumericAxisMixin);\n\n\tvar RadarLogarithmicAxis = LogarithmicAxis.extend({\n\t radarMajorGridLinePositions: function() {\n\t var positions = [];\n\n\t this.traverseMajorTicksPositions(function(position) {\n\t positions.push(position);\n\t }, this.options.majorGridLines);\n\n\t return positions;\n\t },\n\n\t radarMinorGridLinePositions: function() {\n\t var positions = [];\n\n\t this.traverseMinorTicksPositions(function(position) {\n\t positions.push(position);\n\t }, this.options.minorGridLines);\n\n\t return positions;\n\t },\n\n\t axisType: function() {\n\t return LogarithmicAxis;\n\t }\n\t});\n\n\tdeepExtend(RadarLogarithmicAxis.prototype, RadarNumericAxisMixin);\n\n\tvar WEIGHT = 0.333;\n\tvar EXTREMUM_ALLOWED_DEVIATION = 0.01;\n\n\tvar CurveProcessor = Class.extend({\n\t init: function(closed) {\n\n\t this.closed = closed;\n\t },\n\n\t process: function(dataPoints) {\n\t var this$1 = this;\n\n\t var points = dataPoints.slice(0);\n\t var segments = [];\n\t var closed = this.closed;\n\t var length = points.length;\n\n\t if (length > 2) {\n\t this.removeDuplicates(0, points);\n\t length = points.length;\n\t }\n\n\t if (length < 2 || (length === 2 && points[0].equals(points[1]))) {\n\t return segments;\n\t }\n\n\t var p0 = points[0];\n\t var p1 = points[1];\n\t var p2 = points[2];\n\n\t segments.push(new Segment(p0));\n\n\t while (p0.equals(points[length - 1])) {\n\t closed = true;\n\t points.pop();\n\t length--;\n\t }\n\n\t if (length === 2) {\n\t var tangent = this.tangent(p0,p1, X, Y);\n\n\t last(segments).controlOut(\n\t this.firstControlPoint(tangent, p0, p1, X, Y)\n\t );\n\n\t segments.push(new Segment(\n\t p1,\n\t this.secondControlPoint(tangent, p0, p1, X, Y)\n\t ));\n\n\t return segments;\n\t }\n\n\t var initialControlPoint, lastControlPoint;\n\n\t if (closed) {\n\t p0 = points[length - 1]; p1 = points[0]; p2 = points[1];\n\t var controlPoints = this.controlPoints(p0, p1, p2);\n\t initialControlPoint = controlPoints[1];\n\t lastControlPoint = controlPoints[0];\n\t } else {\n\t var tangent$1 = this.tangent(p0, p1, X,Y);\n\t initialControlPoint = this.firstControlPoint(tangent$1, p0, p1, X, Y);\n\t }\n\n\t var cp0 = initialControlPoint;\n\t for (var idx = 0; idx <= length - 3; idx++) {\n\t this$1.removeDuplicates(idx, points);\n\t length = points.length;\n\t if (idx + 3 <= length) {\n\t p0 = points[idx]; p1 = points[idx + 1]; p2 = points[idx + 2];\n\t var controlPoints$1 = this$1.controlPoints(p0,p1,p2);\n\n\t last(segments).controlOut(cp0);\n\t cp0 = controlPoints$1[1];\n\n\t var cp1 = controlPoints$1[0];\n\t segments.push(new Segment(p1, cp1));\n\t }\n\t }\n\n\t if (closed) {\n\t p0 = points[length - 2]; p1 = points[length - 1]; p2 = points[0];\n\t var controlPoints$2 = this.controlPoints(p0, p1, p2);\n\n\t last(segments).controlOut(cp0);\n\t segments.push(new Segment(\n\t p1,\n\t controlPoints$2[0]\n\t ));\n\n\t last(segments).controlOut(controlPoints$2[1]);\n\t segments.push(new Segment(\n\t p2,\n\t lastControlPoint\n\t ));\n\t } else {\n\t var tangent$2 = this.tangent(p1, p2, X, Y);\n\n\t last(segments).controlOut(cp0);\n\t segments.push(new Segment(\n\t p2,\n\t this.secondControlPoint(tangent$2, p1, p2, X, Y)\n\t ));\n\t }\n\n\t return segments;\n\t },\n\n\t removeDuplicates: function(idx, points) {\n\t while (points[idx + 1] && (points[idx].equals(points[idx + 1]) || points[idx + 1].equals(points[idx + 2]))) {\n\t points.splice(idx + 1, 1);\n\t }\n\t },\n\n\t invertAxis: function(p0, p1, p2) {\n\t var invertAxis = false;\n\n\t if (p0.x === p1.x) {\n\t invertAxis = true;\n\t } else if (p1.x === p2.x) {\n\t if ((p1.y < p2.y && p0.y <= p1.y) || (p2.y < p1.y && p1.y <= p0.y)) {\n\t invertAxis = true;\n\t }\n\t } else {\n\t var fn = this.lineFunction(p0,p1);\n\t var y2 = this.calculateFunction(fn, p2.x);\n\t if (!(p0.y <= p1.y && p2.y <= y2) &&\n\t !(p1.y <= p0.y && p2.y >= y2)) {\n\t invertAxis = true;\n\t }\n\t }\n\n\t return invertAxis;\n\t },\n\n\t isLine: function(p0, p1, p2) {\n\t var fn = this.lineFunction(p0, p1);\n\t var y2 = this.calculateFunction(fn, p2.x);\n\n\t return (p0.x === p1.x && p1.x === p2.x) || round(y2, 1) === round(p2.y, 1);\n\t },\n\n\t lineFunction: function(p1, p2) {\n\t var a = (p2.y - p1.y) / (p2.x - p1.x);\n\t var b = p1.y - a * p1.x;\n\n\t return [ b, a ];\n\t },\n\n\t controlPoints: function(p0, p1, p2) {\n\t var xField = X;\n\t var yField = Y;\n\t var restrict = false;\n\t var switchOrientation = false;\n\t var tangent;\n\n\t if (this.isLine(p0, p1, p2)) {\n\t tangent = this.tangent(p0, p1, X, Y);\n\t } else {\n\t var monotonic = {\n\t x: this.isMonotonicByField(p0, p1, p2, X),\n\t y: this.isMonotonicByField(p0, p1, p2, Y)\n\t };\n\n\t if (monotonic.x && monotonic.y) {\n\t tangent = this.tangent(p0, p2, X, Y);\n\t restrict = true;\n\t } else {\n\t if (this.invertAxis(p0, p1, p2)) {\n\t xField = Y;\n\t yField = X;\n\t }\n\n\t if (monotonic[xField]) {\n\t tangent = 0;\n\t } else {\n\t var sign;\n\t if ((p2[yField] < p0[yField] && p0[yField] <= p1[yField]) ||\n\t (p0[yField] < p2[yField] && p1[yField] <= p0[yField])) {\n\t sign = numberSign((p2[yField] - p0[yField]) * (p1[xField] - p0[xField]));\n\t } else {\n\t sign = -numberSign((p2[xField] - p0[xField]) * (p1[yField] - p0[yField]));\n\t }\n\n\t tangent = EXTREMUM_ALLOWED_DEVIATION * sign;\n\t switchOrientation = true;\n\t }\n\t }\n\t }\n\n\t var secondControlPoint = this.secondControlPoint(tangent, p0, p1, xField, yField);\n\n\t if (switchOrientation) {\n\t var oldXField = xField;\n\t xField = yField;\n\t yField = oldXField;\n\t }\n\n\t var firstControlPoint = this.firstControlPoint(tangent, p1, p2, xField, yField);\n\n\t if (restrict) {\n\t this.restrictControlPoint(p0, p1, secondControlPoint, tangent);\n\t this.restrictControlPoint(p1, p2, firstControlPoint, tangent);\n\t }\n\n\t return [ secondControlPoint, firstControlPoint ];\n\t },\n\n\t restrictControlPoint: function(p1, p2, cp, tangent) {\n\t if (p1.y < p2.y) {\n\t if (p2.y < cp.y) {\n\t cp.x = p1.x + (p2.y - p1.y) / tangent;\n\t cp.y = p2.y;\n\t } else if (cp.y < p1.y) {\n\t cp.x = p2.x - (p2.y - p1.y) / tangent;\n\t cp.y = p1.y;\n\t }\n\t } else {\n\t if (cp.y < p2.y) {\n\t cp.x = p1.x - (p1.y - p2.y) / tangent;\n\t cp.y = p2.y;\n\t } else if (p1.y < cp.y) {\n\t cp.x = p2.x + (p1.y - p2.y) / tangent;\n\t cp.y = p1.y;\n\t }\n\t }\n\t },\n\n\t tangent: function(p0, p1, xField, yField) {\n\t var x = p1[xField] - p0[xField];\n\t var y = p1[yField] - p0[yField];\n\t var tangent;\n\n\t if (x === 0) {\n\t tangent = 0;\n\t } else {\n\t tangent = y / x;\n\t }\n\n\t return tangent;\n\t },\n\n\t isMonotonicByField: function(p0, p1, p2, field) {\n\t return (p2[field] > p1[field] && p1[field] > p0[field]) ||\n\t (p2[field] < p1[field] && p1[field] < p0[field]);\n\t },\n\n\t firstControlPoint: function(tangent, p0, p3, xField, yField) {\n\t var t1 = p0[xField];\n\t var t2 = p3[xField];\n\t var distance = (t2 - t1) * WEIGHT;\n\n\t return this.point(t1 + distance, p0[yField] + distance * tangent, xField, yField);\n\t },\n\n\t secondControlPoint: function(tangent, p0, p3, xField, yField) {\n\t var t1 = p0[xField];\n\t var t2 = p3[xField];\n\t var distance = (t2 - t1) * WEIGHT;\n\n\t return this.point(t2 - distance, p3[yField] - distance * tangent, xField, yField);\n\t },\n\n\t point: function(xValue, yValue, xField, yField) {\n\t var controlPoint = new geometry.Point();\n\t controlPoint[xField] = xValue;\n\t controlPoint[yField] = yValue;\n\n\t return controlPoint;\n\t },\n\n\t calculateFunction: function(fn, x) {\n\t var length = fn.length;\n\t var result = 0;\n\n\t for (var i = 0; i < length; i++) {\n\t result += Math.pow(x,i) * fn[i];\n\t }\n\t return result;\n\t }\n\t});\n\n\tfunction numberSign(value) {\n\t return value <= 0 ? -1 : 1;\n\t}\n\n\tdataviz.Gradients = GRADIENTS;\n\n\tkendo.deepExtend(kendo.dataviz, {\n\t constants: constants,\n\t services: services,\n\t autoMajorUnit: autoMajorUnit,\n\t Point: Point,\n\t Box: Box,\n\t Ring: Ring,\n\t Sector: Sector,\n\t ShapeBuilder: ShapeBuilder,\n\t ShapeElement: ShapeElement,\n\t ChartElement: ChartElement,\n\t BoxElement: BoxElement,\n\t RootElement: RootElement,\n\t FloatElement: FloatElement,\n\t Text: Text,\n\t TextBox: TextBox,\n\t Title: Title,\n\t AxisLabel: AxisLabel,\n\t Axis: Axis,\n\t Note: Note,\n\t CategoryAxis: CategoryAxis,\n\t DateCategoryAxis: DateCategoryAxis,\n\t DateValueAxis: DateValueAxis,\n\t NumericAxis: NumericAxis,\n\t LogarithmicAxis: LogarithmicAxis,\n\t PolarAxis: PolarAxis,\n\t RadarCategoryAxis: RadarCategoryAxis,\n\t RadarNumericAxis: RadarNumericAxis,\n\t RadarLogarithmicAxis: RadarLogarithmicAxis,\n\t CurveProcessor: CurveProcessor,\n\t rectToBox: rectToBox,\n\t addClass: addClass,\n\t removeClass: removeClass,\n\t alignPathToPixel: alignPathToPixel,\n\t clockwise: clockwise,\n\t convertableToNumber: convertableToNumber,\n\t deepExtend: deepExtend,\n\t elementStyles: elementStyles,\n\t getSpacing: getSpacing,\n\t getTemplate: getTemplate,\n\t getter: __common_getter_js,\n\t grep: grep,\n\t hasClasses: hasClasses,\n\t HashMap: HashMap,\n\t inArray: inArray,\n\t interpolateValue: interpolateValue,\n\t InstanceObserver: InstanceObserver,\n\t isArray: isArray,\n\t isFunction: isFunction,\n\t isNumber: isNumber,\n\t isObject: isObject,\n\t isString: isString,\n\t map: map,\n\t mousewheelDelta: mousewheelDelta,\n\t FontLoader: FontLoader,\n\t setDefaultOptions: setDefaultOptions,\n\t sparseArrayLimits: sparseArrayLimits,\n\t styleValue: styleValue,\n\t find: find,\n\t append: append,\n\t bindEvents: bindEvents,\n\t Class: Class,\n\t defined: defined,\n\t deg: deg,\n\t elementOffset: elementOffset,\n\t elementSize: elementSize,\n\t eventElement: eventElement,\n\t eventCoordinates: eventCoordinates,\n\t last: last,\n\t limitValue: limitValue,\n\t logToConsole: kendo.logToConsole,\n\t objectKey: objectKey,\n\t rad: rad,\n\t round: round,\n\t unbindEvents: unbindEvents,\n\t valueOrDefault: valueOrDefault,\n\t absoluteDateDiff: absoluteDateDiff,\n\t addDuration: addDuration,\n\t addTicks: addTicks,\n\t ceilDate: ceilDate,\n\t dateComparer: dateComparer,\n\t dateDiff: dateDiff,\n\t dateEquals: dateEquals,\n\t dateIndex: dateIndex,\n\t duration: duration,\n\t floorDate: floorDate,\n\t lteDateIndex: lteDateIndex,\n\t startOfWeek: startOfWeek,\n\t toDate: toDate,\n\t parseDate: parseDate,\n\t parseDates: parseDates,\n\t toTime: toTime\n\t});\n\n\t})(window.kendo.jQuery);\n\n\t}, __webpack_require__(3));\n\n/***/ })\n\n/******/ });","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n\n\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ 0:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tmodule.exports = __webpack_require__(868);\n\n\n/***/ }),\n\n/***/ 3:\n/***/ (function(module, exports) {\n\n\tmodule.exports = function() { throw new Error(\"define cannot be used indirect\"); };\r\n\n\n/***/ }),\n\n/***/ 857:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.data\");\n\n/***/ }),\n\n/***/ 858:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.dataviz.core\");\n\n/***/ }),\n\n/***/ 859:\n/***/ (function(module, exports) {\n\n\tmodule.exports = require(\"../../kendo.dataviz.themes\");\n\n/***/ }),\n\n/***/ 868:\n/***/ (function(module, exports, __webpack_require__) {\n\n\tvar __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (f, define) {\n\t !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(857), __webpack_require__(870), __webpack_require__(871),\n\t __webpack_require__(872),\n\t __webpack_require__(873),\n\t __webpack_require__(869),\n\t __webpack_require__(858),\n\t __webpack_require__(859),\n\t __webpack_require__(874),\n\t __webpack_require__(875),\n\t __webpack_require__(876) ], __WEBPACK_AMD_DEFINE_FACTORY__ = (f), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n\t})(function () {\n\n\t (function ($, undefined) {\n\t // Imports ================================================================\n\t var dataviz = kendo.dataviz,\n\t draw = kendo.drawing,\n\t geom = kendo.geometry,\n\t diagram = dataviz.diagram,\n\t Widget = kendo.ui.Widget,\n\t Class = kendo.Class,\n\t proxy = $.proxy,\n\t deepExtend = kendo.deepExtend,\n\t outerWidth = kendo._outerWidth,\n\t outerHeight = kendo._outerHeight,\n\t extend = $.extend,\n\t HierarchicalDataSource = kendo.data.HierarchicalDataSource,\n\t Canvas = diagram.Canvas,\n\t Group = diagram.Group,\n\t Rectangle = diagram.Rectangle,\n\t Circle = diagram.Circle,\n\t CompositeTransform = diagram.CompositeTransform,\n\t Rect = diagram.Rect,\n\t Path = diagram.Path,\n\t DeleteShapeUnit = diagram.DeleteShapeUnit,\n\t DeleteConnectionUnit = diagram.DeleteConnectionUnit,\n\t TextBlock = diagram.TextBlock,\n\t Image = diagram.Image,\n\t Point = diagram.Point,\n\t Intersect = diagram.Intersect,\n\t ConnectionEditAdorner = diagram.ConnectionEditAdorner,\n\t UndoRedoService = diagram.UndoRedoService,\n\t ToolService = diagram.ToolService,\n\t Selector = diagram.Selector,\n\t ResizingAdorner = diagram.ResizingAdorner,\n\t ConnectorsAdorner = diagram.ConnectorsAdorner,\n\t Cursors = diagram.Cursors,\n\t Utils = diagram.Utils,\n\t Observable = kendo.Observable,\n\t ToBackUnit = diagram.ToBackUnit,\n\t ToFrontUnit = diagram.ToFrontUnit,\n\t PolylineRouter = diagram.PolylineRouter,\n\t CascadingRouter = diagram.CascadingRouter,\n\t isUndefined = Utils.isUndefined,\n\t isDefined = Utils.isDefined,\n\t defined = draw.util.defined,\n\t isArray = $.isArray,\n\t isFunction = kendo.isFunction,\n\t isString = Utils.isString,\n\t isPlainObject = $.isPlainObject,\n\n\t math = Math;\n\n\t // Constants ==============================================================\n\t var NS = \".kendoDiagram\",\n\t CASCADING = \"cascading\",\n\t ITEMBOUNDSCHANGE = \"itemBoundsChange\",\n\t CHANGE = \"change\",\n\t CLICK = \"click\",\n\t DRAG = \"drag\",\n\t DRAG_END = \"dragEnd\",\n\t DRAG_START = \"dragStart\",\n\t MOUSE_ENTER = \"mouseEnter\",\n\t MOUSE_LEAVE = \"mouseLeave\",\n\t ERROR = \"error\",\n\t AUTO = \"Auto\",\n\t TOP = \"Top\",\n\t RIGHT = \"Right\",\n\t LEFT = \"Left\",\n\t BOTTOM = \"Bottom\",\n\t MAXINT = 9007199254740992,\n\t SELECT = \"select\",\n\t ITEMROTATE = \"itemRotate\",\n\t PAN = \"pan\",\n\t ZOOM_START = \"zoomStart\",\n\t ZOOM_END = \"zoomEnd\",\n\t NONE = \"none\",\n\t DEFAULT_CANVAS_WIDTH = 600,\n\t DEFAULT_CANVAS_HEIGHT = 600,\n\t DEFAULT_SHAPE_TYPE = \"rectangle\",\n\t DEFAULT_SHAPE_WIDTH = 100,\n\t DEFAULT_SHAPE_HEIGHT = 100,\n\t DEFAULT_SHAPE_MINWIDTH = 20,\n\t DEFAULT_SHAPE_MINHEIGHT = 20,\n\t DEFAULT_SHAPE_POSITION = 0,\n\t DEFAULT_CONNECTION_BACKGROUND = \"Yellow\",\n\t MAX_VALUE = Number.MAX_VALUE,\n\t MIN_VALUE = -Number.MAX_VALUE,\n\t ABSOLUTE = \"absolute\",\n\t TRANSFORMED = \"transformed\",\n\t ROTATED = \"rotated\",\n\t TRANSPARENT = \"transparent\",\n\t WIDTH = \"width\",\n\t HEIGHT = \"height\",\n\t X = \"x\",\n\t Y = \"y\",\n\t MOUSEWHEEL_NS = \"DOMMouseScroll\" + NS + \" mousewheel\" + NS,\n\t MOBILE_ZOOM_RATE = 0.05,\n\t MOBILE_PAN_DISTANCE = 5,\n\t BUTTON_TEMPLATE = '#=text#',\n\t CONNECTION_CONTENT_OFFSET = 5;\n\n\t diagram.DefaultConnectors = [{\n\t name: TOP\n\t }, {\n\t name: BOTTOM\n\t }, {\n\t name: LEFT\n\t }, {\n\t name: RIGHT\n\t }, {\n\t name: AUTO,\n\t position: function (shape) {\n\t return shape.getPosition(\"center\");\n\t }\n\t }];\n\n\t var defaultButtons = {\n\t cancel: {\n\t text: \"Cancel\",\n\t imageClass: \"k-i-cancel\",\n\t className: \"k-diagram-cancel\",\n\t iconClass: \"k-icon\"\n\t },\n\t update: {\n\t text: \"Update\",\n\t imageClass: \"k-i-checkmark\",\n\t className: \"k-diagram-update\",\n\t iconClass: \"k-icon\"\n\t }\n\t };\n\n\t diagram.shapeDefaults = function(extra) {\n\t var defaults = {\n\t type: DEFAULT_SHAPE_TYPE,\n\t path: \"\",\n\t autoSize: true,\n\t visual: null,\n\t x: DEFAULT_SHAPE_POSITION,\n\t y: DEFAULT_SHAPE_POSITION,\n\t minWidth: DEFAULT_SHAPE_MINWIDTH,\n\t minHeight: DEFAULT_SHAPE_MINHEIGHT,\n\t width: DEFAULT_SHAPE_WIDTH,\n\t height: DEFAULT_SHAPE_HEIGHT,\n\t hover: {},\n\t editable: {\n\t connect: true,\n\t tools: []\n\t },\n\t connectors: diagram.DefaultConnectors,\n\t rotation: {\n\t angle: 0\n\t }\n\t };\n\n\t Utils.simpleExtend(defaults, extra);\n\n\t return defaults;\n\t };\n\n\t function mwDelta(e) {\n\t var origEvent = e.originalEvent,\n\t delta = 0;\n\n\t if (origEvent.wheelDelta) {\n\t delta = -origEvent.wheelDelta / 40;\n\t delta = delta > 0 ? math.ceil(delta) : math.floor(delta);\n\t } else if (origEvent.detail) {\n\t delta = origEvent.detail;\n\t }\n\n\t return delta;\n\t }\n\n\t function isAutoConnector(connector) {\n\t return connector.options.name.toLowerCase() === AUTO.toLowerCase();\n\t }\n\n\t function closestConnector(point, connectors) {\n\t var minimumDistance = MAXINT, resCtr, connector;\n\t for (var i = 0; i < connectors.length; i++) {\n\t connector = connectors[i];\n\t if (!isAutoConnector(connector)) {\n\t var dist = point.distanceTo(connector.position());\n\t if (dist < minimumDistance) {\n\t minimumDistance = dist;\n\t resCtr = connector;\n\t }\n\t }\n\t }\n\t return resCtr;\n\t }\n\n\t function indicesOfItems(group, visuals) {\n\t var i, indices = [], visual;\n\t var children = group.drawingContainer().children;\n\t var length = children.length;\n\t for (i = 0; i < visuals.length; i++) {\n\t visual = visuals[i];\n\t for (var j = 0; j < length; j++) {\n\t if (children[j] == visual.drawingContainer()) {\n\t indices.push(j);\n\t break;\n\t }\n\t }\n\t }\n\t return indices;\n\t }\n\n\t var DiagramElement = Observable.extend({\n\t init: function (options) {\n\t var that = this;\n\t that.dataItem = (options || {}).dataItem;\n\t Observable.fn.init.call(that);\n\t that.options = deepExtend({ id: diagram.randomId() }, that.options, options);\n\t that.isSelected = false;\n\t that.visual = new Group({\n\t id: that.options.id,\n\t autoSize: that.options.autoSize\n\t });\n\t that.id = that.options.id;\n\t that._template();\n\t },\n\n\t options: {\n\t hover: {},\n\t cursor: Cursors.grip,\n\t content: {\n\t align: \"center middle\"\n\t },\n\t selectable: true,\n\t serializable: true,\n\t enable: true\n\t },\n\n\t _getCursor: function (point) {\n\t if (this.adorner) {\n\t return this.adorner._getCursor(point);\n\t }\n\t return this.options.cursor;\n\t },\n\n\t visible: function (value) {\n\t if (isUndefined(value)) {\n\t return this.visual.visible();\n\t } else {\n\t this.visual.visible(value);\n\t }\n\t },\n\n\t bounds: function () {\n\t },\n\n\t refresh: function () {\n\t this.visual.redraw();\n\t },\n\n\t position: function (point) {\n\t this.options.x = point.x;\n\t this.options.y = point.y;\n\t this.visual.position(point);\n\t },\n\n\t toString: function () {\n\t return this.options.id;\n\t },\n\n\t serialize: function () {\n\t // the options json object describes the shape perfectly. So this object can serve as shape serialization.\n\t var json = deepExtend({}, {options: this.options});\n\t if (this.dataItem) {\n\t json.dataItem = this.dataItem.toString();\n\t }\n\t return json;\n\t },\n\n\t _content: function (content) {\n\t if (content !== undefined) {\n\t var options = this.options;\n\n\t if (diagram.Utils.isString(content)) {\n\t options.content.text = content;\n\t } else {\n\t deepExtend(options.content, content);\n\t }\n\n\t var contentOptions = options.content;\n\t var contentVisual = this._contentVisual;\n\n\t if (!contentVisual) {\n\t this._createContentVisual(contentOptions);\n\t } else {\n\t this._updateContentVisual(contentOptions);\n\t }\n\t }\n\n\t return this.options.content.text;\n\t },\n\n\t _createContentVisual: function(options) {\n\t if (options.text) {\n\t this._contentVisual = new TextBlock(options);\n\t this._contentVisual._includeInBBox = false;\n\t this.visual.append(this._contentVisual);\n\t }\n\t },\n\n\t _updateContentVisual: function(options) {\n\t this._contentVisual.redraw(options);\n\t },\n\n\t _hitTest: function (point) {\n\t var bounds = this.bounds();\n\t return this.visible() && bounds.contains(point) && this.options.enable;\n\t },\n\n\t _template: function () {\n\t var that = this;\n\t if (that.options.content.template) {\n\t var data = that.dataItem || {},\n\t elementTemplate = kendo.template(that.options.content.template, {\n\t paramName: \"dataItem\"\n\t });\n\n\t that.options.content.text = elementTemplate(data);\n\t }\n\t },\n\n\t _canSelect: function () {\n\t return this.options.selectable !== false;\n\t },\n\n\t toJSON: function() {\n\t return {\n\t id: this.options.id\n\t };\n\t }\n\t });\n\n\t var Connector = Class.extend({\n\t init: function (shape, options) {\n\t this.options = deepExtend({}, this.options, options);\n\t this.connections = [];\n\t this.shape = shape;\n\t },\n\t options: {\n\t width: 7,\n\t height: 7,\n\t fill: {\n\t color: DEFAULT_CONNECTION_BACKGROUND\n\t },\n\t hover: {}\n\t },\n\t position: function () {\n\t if (this.options.position) {\n\t return this.options.position(this.shape);\n\t } else {\n\t return this.shape.getPosition(this.options.name);\n\t }\n\t },\n\t toJSON: function () {\n\t return {\n\t shapeId: this.shape.toString(),\n\t connector: this.options.name\n\t };\n\t }\n\t });\n\n\t Connector.parse = function (diagram, str) {\n\t var tempStr = str.split(\":\"),\n\t id = tempStr[0],\n\t name = tempStr[1] || AUTO;\n\n\t for (var i = 0; i < diagram.shapes.length; i++) {\n\t var shape = diagram.shapes[i];\n\t if (shape.options.id == id) {\n\t return shape.getConnector(name.trim());\n\t }\n\t }\n\t };\n\n\t var Shape = DiagramElement.extend({\n\t init: function (options, diagram) {\n\t var that = this;\n\t DiagramElement.fn.init.call(that, options);\n\t this.diagram = diagram;\n\t this.updateOptionsFromModel();\n\t options = that.options;\n\t that.connectors = [];\n\t that.type = options.type;\n\t that.createShapeVisual();\n\t that.updateBounds();\n\t that.content(that.content());\n\n\t that._createConnectors();\n\t },\n\n\t options: diagram.shapeDefaults(),\n\n\t _setOptionsFromModel: function(model) {\n\t var modelOptions = filterShapeDataItem(model || this.dataItem);\n\t this.options = deepExtend({}, this.options, modelOptions);\n\n\t this.redrawVisual();\n\t },\n\n\t updateOptionsFromModel: function(model, field) {\n\t if (this.diagram && this.diagram._isEditable) {\n\t var modelOptions = filterShapeDataItem(model || this.dataItem);\n\n\t if (model && field) {\n\t if (!dataviz.inArray(field, [\"x\", \"y\", \"width\", \"height\"])) {\n\t if (this.options.visual) {\n\t this._redrawVisual();\n\t } else if (modelOptions.type) {\n\t this.options = deepExtend({}, this.options, modelOptions);\n\t this._redrawVisual();\n\t }\n\n\t if (this.options.content) {\n\t this._template();\n\t this.content(this.options.content);\n\t }\n\t } else {\n\t var bounds = this.bounds();\n\t bounds[field] = model[field];\n\t this.bounds(bounds);\n\t }\n\t } else {\n\t this.options = deepExtend({}, this.options, modelOptions);\n\t }\n\t }\n\t },\n\n\t _redrawVisual: function() {\n\t this.visual.clear();\n\t this._contentVisual = null;\n\t this.options.dataItem = this.dataItem;\n\t this.createShapeVisual();\n\t this.updateBounds();\n\t },\n\n\t redrawVisual: function() {\n\t this._redrawVisual();\n\t if (this.options.content) {\n\t this._template();\n\t this.content(this.options.content);\n\t }\n\t },\n\n\t updateModel: function(syncChanges) {\n\t var diagram = this.diagram;\n\t if (diagram && diagram._isEditable) {\n\t var bounds = this._bounds;\n\t var model = this.dataItem;\n\n\t if (model) {\n\t diagram._suspendModelRefresh();\n\t if (defined(model.x) && bounds.x !== model.x) {\n\t model.set(\"x\", bounds.x);\n\t }\n\n\t if (defined(model.y) && bounds.y !== model.y) {\n\t model.set(\"y\", bounds.y);\n\t }\n\n\t if (defined(model.width) && bounds.width !== model.width) {\n\t model.set(\"width\", bounds.width);\n\t }\n\n\t if (defined(model.height) && bounds.height !== model.height) {\n\t model.set(\"height\", bounds.height);\n\t }\n\n\t this.dataItem = model;\n\t diagram._resumeModelRefresh();\n\n\t if (syncChanges) {\n\t diagram._syncShapeChanges();\n\t }\n\t }\n\t }\n\t },\n\n\t updateBounds: function() {\n\t var bounds = this.visual._measure(true);\n\t var options = this.options;\n\t this.bounds(new Rect(options.x, options.y, bounds.width, bounds.height));\n\t this._rotate();\n\t this._alignContent();\n\t },\n\n\t content: function(content) {\n\t var result = this._content(content);\n\n\t this._alignContent();\n\n\t return result;\n\t },\n\n\t _alignContent: function() {\n\t var contentOptions = this.options.content || {};\n\t var contentVisual = this._contentVisual;\n\t if (contentVisual && contentOptions.align) {\n\t var containerRect = this.visual._measure();\n\t var aligner = new diagram.RectAlign(containerRect);\n\t var contentBounds = contentVisual.drawingElement.bbox(null);\n\n\t var contentRect = new Rect(0, 0, contentBounds.width(), contentBounds.height());\n\t var alignedBounds = aligner.align(contentRect, contentOptions.align);\n\n\t contentVisual.position(alignedBounds.topLeft());\n\t }\n\t },\n\n\t _createConnectors: function() {\n\t var options = this.options,\n\t length = options.connectors.length,\n\t connectorDefaults = options.connectorDefaults,\n\t connector, i;\n\n\t for (i = 0; i < length; i++) {\n\t connector = new Connector(\n\t this, deepExtend({},\n\t connectorDefaults,\n\t options.connectors[i]\n\t )\n\t );\n\t this.connectors.push(connector);\n\t }\n\t },\n\n\t bounds: function (value) {\n\t var bounds;\n\n\t if (value) {\n\t if (isString(value)) {\n\t switch (value) {\n\t case TRANSFORMED :\n\t bounds = this._transformedBounds();\n\t break;\n\t case ABSOLUTE :\n\t bounds = this._transformedBounds();\n\t var pan = this.diagram._pan;\n\t bounds.x += pan.x;\n\t bounds.y += pan.y;\n\t break;\n\t case ROTATED :\n\t bounds = this._rotatedBounds();\n\t break;\n\t default:\n\t bounds = this._bounds;\n\t }\n\t } else {\n\t this._setBounds(value);\n\t this._triggerBoundsChange();\n\t if (!(this.diagram && this.diagram._layouting)) {\n\t this.refreshConnections();\n\t }\n\t }\n\t } else {\n\t bounds = this._bounds;\n\t }\n\n\t return bounds;\n\t },\n\n\t _setBounds: function(rect) {\n\t var options = this.options;\n\t var topLeft = rect.topLeft();\n\t var x = options.x = topLeft.x;\n\t var y = options.y = topLeft.y;\n\t var width = options.width = math.max(rect.width, options.minWidth);\n\t var height = options.height = math.max(rect.height, options.minHeight);\n\n\t this._bounds = new Rect(x, y, width, height);\n\n\t this.visual.redraw({\n\t x: x,\n\t y: y,\n\t width: width,\n\t height: height\n\t });\n\t },\n\n\t position: function (point) {\n\t if (point) {\n\t this.bounds(new Rect(point.x, point.y, this._bounds.width, this._bounds.height));\n\t } else {\n\t return this._bounds.topLeft();\n\t }\n\t },\n\t /**\n\t * Returns a clone of this shape.\n\t * @returns {Shape}\n\t */\n\t clone: function () {\n\t var json = this.serialize();\n\n\t json.options.id = diagram.randomId();\n\n\t if (this.diagram && this.diagram._isEditable && defined(this.dataItem)) {\n\t json.options.dataItem = cloneDataItem(this.dataItem);\n\t }\n\n\t return new Shape(json.options);\n\t },\n\n\t select: function (value) {\n\t var diagram = this.diagram, selected, deselected;\n\t if (isUndefined(value)) {\n\t value = true;\n\t }\n\n\t if (this._canSelect()) {\n\t if (this.isSelected != value) {\n\t selected = [];\n\t deselected = [];\n\t this.isSelected = value;\n\t if (this.isSelected) {\n\t diagram._selectedItems.push(this);\n\t selected.push(this);\n\t } else {\n\t Utils.remove(diagram._selectedItems, this);\n\t deselected.push(this);\n\t }\n\n\t if (!diagram._internalSelection) {\n\t diagram._selectionChanged(selected, deselected);\n\t }\n\n\t return true;\n\t }\n\t }\n\t },\n\n\t rotate: function (angle, center, undoable) { // we assume the center is always the center of the shape.\n\t var rotate = this.visual.rotate();\n\t if (angle !== undefined) {\n\t if (undoable !== false && this.diagram && this.diagram.undoRedoService && angle !== rotate.angle) {\n\t this.diagram.undoRedoService.add(\n\t new diagram.RotateUnit(this.diagram._resizingAdorner, [this], [rotate.angle]), false);\n\t }\n\n\t var b = this.bounds(),\n\t sc = new Point(b.width / 2, b.height / 2),\n\t deltaAngle,\n\t newPosition;\n\n\t if (center) {\n\t deltaAngle = angle - rotate.angle;\n\t newPosition = b.center().rotate(center, 360 - deltaAngle).minus(sc);\n\t this._rotationOffset = this._rotationOffset.plus(newPosition.minus(b.topLeft()));\n\t this.position(newPosition);\n\t }\n\n\t this.visual.rotate(angle, sc);\n\t this.options.rotation.angle = angle;\n\n\t if (this.diagram && this.diagram._connectorsAdorner) {\n\t this.diagram._connectorsAdorner.refresh();\n\t }\n\n\t this.refreshConnections();\n\n\t if (this.diagram) {\n\t this.diagram.trigger(ITEMROTATE, { item: this });\n\t }\n\t }\n\n\t return rotate;\n\t },\n\n\t connections: function (type) { // in, out, undefined = both\n\t var result = [], i, j, con, cons, ctr;\n\n\t for (i = 0; i < this.connectors.length; i++) {\n\t ctr = this.connectors[i];\n\t cons = ctr.connections;\n\t for (j = 0, cons; j < cons.length; j++) {\n\t con = cons[j];\n\t if (type == \"out\") {\n\t var source = con.source();\n\t if (source.shape && source.shape == this) {\n\t result.push(con);\n\t }\n\t } else if (type == \"in\") {\n\t var target = con.target();\n\t if (target.shape && target.shape == this) {\n\t result.push(con);\n\t }\n\t } else {\n\t result.push(con);\n\t }\n\t }\n\t }\n\n\t return result;\n\t },\n\n\t refreshConnections: function () {\n\t $.each(this.connections(), function () {\n\t this.refresh();\n\t });\n\t },\n\t /**\n\t * Gets a connector of this shape either by the connector's supposed name or\n\t * via a Point in which case the closest connector will be returned.\n\t * @param nameOrPoint The name of a Connector or a Point.\n\t * @returns {Connector}\n\t */\n\t getConnector: function (nameOrPoint) {\n\t var i, ctr;\n\t if (isString(nameOrPoint)) {\n\t nameOrPoint = nameOrPoint.toLocaleLowerCase();\n\t for (i = 0; i < this.connectors.length; i++) {\n\t ctr = this.connectors[i];\n\t if (ctr.options.name.toLocaleLowerCase() == nameOrPoint) {\n\t return ctr;\n\t }\n\t }\n\t } else if (nameOrPoint instanceof Point) {\n\t return closestConnector(nameOrPoint, this.connectors);\n\t } else {\n\t return this.connectors.length ? this.connectors[0] : null;\n\t }\n\t },\n\n\t getPosition: function (side) {\n\t var b = this.bounds(),\n\t fnName = side.charAt(0).toLowerCase() + side.slice(1);\n\n\t if (isFunction(b[fnName])) {\n\t return this._transformPoint(b[fnName]());\n\t }\n\n\t return b.center();\n\t },\n\n\t redraw: function (options) {\n\t if (options) {\n\t var shapeOptions = this.options;\n\t var boundsChange;\n\n\t this.shapeVisual.redraw(this._visualOptions(options));\n\n\t if (this._diffNumericOptions(options, [WIDTH, HEIGHT, X, Y])) {\n\t this.bounds(new Rect(shapeOptions.x, shapeOptions.y, shapeOptions.width, shapeOptions.height));\n\t boundsChange = true;\n\t }\n\n\t if (options.connectors) {\n\t shapeOptions.connectors = options.connectors;\n\t this._updateConnectors();\n\t }\n\n\t shapeOptions = deepExtend(shapeOptions, options);\n\n\t if (options.rotation || boundsChange) {\n\t this._rotate();\n\t }\n\n\t if (shapeOptions.content) {\n\t this.content(shapeOptions.content);\n\t }\n\t }\n\t },\n\n\t _updateConnectors: function() {\n\t var connections = this.connections();\n\t this.connectors = [];\n\t this._createConnectors();\n\t var connection;\n\t var source;\n\t var target;\n\n\t for (var idx = 0; idx < connections.length; idx++) {\n\t connection = connections[idx];\n\t source = connection.source();\n\t target = connection.target();\n\t if (source.shape && source.shape === this) {\n\t connection.source(this.getConnector(source.options.name) || null);\n\t } else if (target.shape && target.shape === this) {\n\t connection.target(this.getConnector(target.options.name) || null);\n\t }\n\t connection.updateModel();\n\t }\n\t },\n\n\t _diffNumericOptions: diagram.diffNumericOptions,\n\n\t _visualOptions: function(options) {\n\t return {\n\t data: options.path,\n\t source: options.source,\n\t hover: options.hover,\n\t fill: options.fill,\n\t stroke: options.stroke\n\t };\n\t },\n\n\t _triggerBoundsChange: function () {\n\t if (this.diagram) {\n\t this.diagram.trigger(ITEMBOUNDSCHANGE, {item: this, bounds: this._bounds.clone()}); // the trigger modifies the arguments internally.\n\t }\n\t },\n\n\t _transformPoint: function (point) {\n\t var rotate = this.rotate(),\n\t bounds = this.bounds(),\n\t tl = bounds.topLeft();\n\n\t if (rotate.angle) {\n\t point.rotate(rotate.center().plus(tl), 360 - rotate.angle);\n\t }\n\n\t return point;\n\t },\n\n\t _transformedBounds: function () {\n\t var bounds = this.bounds(),\n\t tl = bounds.topLeft(),\n\t br = bounds.bottomRight();\n\n\t return Rect.fromPoints(this.diagram.modelToView(tl), this.diagram.modelToView(br));\n\t },\n\n\t _rotatedBounds: function () {\n\t var bounds = this.bounds().rotatedBounds(this.rotate().angle),\n\t tl = bounds.topLeft(),\n\t br = bounds.bottomRight();\n\n\t return Rect.fromPoints(tl, br);\n\t },\n\n\t _rotate: function () {\n\t var rotation = this.options.rotation;\n\n\t if (rotation && rotation.angle) {\n\t this.rotate(rotation.angle);\n\t }\n\n\t this._rotationOffset = new Point();\n\t },\n\n\t _hover: function (value) {\n\t var options = this.options,\n\t hover = options.hover,\n\t stroke = options.stroke,\n\t fill = options.fill;\n\n\t if (value && isDefined(hover.stroke)) {\n\t stroke = deepExtend({}, stroke, hover.stroke);\n\t }\n\n\t if (value && isDefined(hover.fill)) {\n\t fill = hover.fill;\n\t }\n\n\t this.shapeVisual.redraw({\n\t stroke: stroke,\n\t fill: fill\n\t });\n\n\t if (options.editable && options.editable.connect) {\n\t this.diagram._showConnectors(this, value);\n\t }\n\t },\n\n\t _hitTest: function (value) {\n\t if (this.visible()) {\n\t var bounds = this.bounds(), rotatedPoint,\n\t angle = this.rotate().angle;\n\n\t if (value.isEmpty && !value.isEmpty()) { // rect selection\n\t return Intersect.rects(value, bounds, angle ? angle : 0);\n\t } else { // point\n\t rotatedPoint = value.clone().rotate(bounds.center(), angle); // cloning is important because rotate modifies the point inline.\n\t if (bounds.contains(rotatedPoint)) {\n\t return this;\n\t }\n\t }\n\t }\n\t },\n\n\t toJSON: function() {\n\t return {\n\t shapeId: this.options.id\n\t };\n\t },\n\n\t createShapeVisual: function() {\n\t var options = this.options;\n\t var visualOptions = this._visualOptions(options);\n\t var visualTemplate = options.visual;\n\t var type = (options.type + \"\").toLocaleLowerCase();\n\t var shapeVisual;\n\n\t visualOptions.width = options.width;\n\t visualOptions.height = options.height;\n\n\t if (isFunction(visualTemplate)) { // custom template\n\t shapeVisual = visualTemplate.call(this, options);\n\t } else if (visualOptions.data) {\n\t shapeVisual = new Path(visualOptions);\n\t translateToOrigin(shapeVisual);\n\t } else if (type == \"rectangle\"){\n\t shapeVisual = new Rectangle(visualOptions);\n\t } else if (type == \"circle\") {\n\t shapeVisual = new Circle(visualOptions);\n\t } else if (type == \"text\") {\n\t shapeVisual = new TextBlock(visualOptions);\n\t } else if (type == \"image\") {\n\t shapeVisual = new Image(visualOptions);\n\t } else {\n\t shapeVisual = new Path(visualOptions);\n\t }\n\n\t this.shapeVisual = shapeVisual;\n\t this.visual.append(this.shapeVisual);\n\t }\n\t });\n\n\t /**\n\t * The visual link between two Shapes through the intermediate of Connectors.\n\t */\n\t var Connection = DiagramElement.extend({\n\t init: function (from, to, options) {\n\t var that = this;\n\t DiagramElement.fn.init.call(that, options);\n\t this.updateOptionsFromModel();\n\t this._initRouter();\n\t that.path = new diagram.Polyline(that.options);\n\t that.path.fill(TRANSPARENT);\n\t that.visual.append(that.path);\n\t that._sourcePoint = that._targetPoint = new Point();\n\t that._setSource(from);\n\t that._setTarget(to);\n\t that.content(that.options.content);\n\t that.definers = [];\n\t if (defined(options) && options.points) {\n\t that.points(options.points);\n\t }\n\t },\n\n\t options: {\n\t hover: {\n\t stroke: {}\n\t },\n\t startCap: NONE,\n\t endCap: NONE,\n\t points: [],\n\t selectable: true,\n\t fromConnector: AUTO,\n\t toConnector: AUTO\n\t },\n\n\t _setOptionsFromModel: function(model) {\n\t this.updateOptionsFromModel(model || this.dataItem);\n\t },\n\n\t updateOptionsFromModel: function(model) {\n\t if (this.diagram && this.diagram._isEditable) {\n\t var dataMap = this.diagram._dataMap;\n\t var options = filterConnectionDataItem(model || this.dataItem);\n\n\t if (model) {\n\t if (defined(options.from)) {\n\t var from = dataMap[options.from];\n\t if (from && defined(options.fromConnector)) {\n\t from = from.getConnector(options.fromConnector);\n\t }\n\t this.source(from);\n\t } else if (defined(options.fromX) && defined(options.fromY)) {\n\t this.source(new Point(options.fromX, options.fromY));\n\t }\n\n\t if (defined(options.to)) {\n\t var to = dataMap[options.to];\n\t if (to && defined(options.toConnector)) {\n\t to = to.getConnector(options.toConnector);\n\t }\n\t this.target(to);\n\t } else if (defined(options.toX) && defined(options.toY)) {\n\t this.target(new Point(options.toX, options.toY));\n\t }\n\n\t if (defined(options.type) && this.type() !== options.type) {\n\t this.points([]);\n\t this.type(options.type);\n\t }\n\n\t this.dataItem = model;\n\n\t this._template();\n\t this.redraw(this.options);\n\t } else {\n\t this.options = deepExtend({}, options, this.options);\n\t }\n\t }\n\t },\n\n\t updateModel: function(syncChanges) {\n\t if (this.diagram && this.diagram._isEditable) {\n\t if (this.diagram.connectionsDataSource) {\n\t var model = this.diagram.connectionsDataSource.getByUid(this.dataItem.uid);\n\n\t if (model) {\n\t this.diagram._suspendModelRefresh();\n\t if (defined(this.options.fromX) && this.options.fromX !== null) {\n\t clearField(\"from\", model);\n\t clearField(\"fromConnector\", model);\n\t model.set(\"fromX\", this.options.fromX);\n\t model.set(\"fromY\", this.options.fromY);\n\t } else {\n\t model.set(\"from\", this.options.from);\n\t if (defined(model.fromConnector)) {\n\t model.set(\"fromConnector\", this.sourceConnector ? this.sourceConnector.options.name : null);\n\t }\n\t clearField(\"fromX\", model);\n\t clearField(\"fromY\", model);\n\t }\n\n\t if (defined(this.options.toX) && this.options.toX !== null) {\n\t clearField(\"to\", model);\n\t clearField(\"toConnector\", model);\n\t model.set(\"toX\", this.options.toX);\n\t model.set(\"toY\", this.options.toY);\n\t } else {\n\t model.set(\"to\", this.options.to);\n\t if (defined(model.toConnector)) {\n\t model.set(\"toConnector\", this.targetConnector ? this.targetConnector.options.name : null);\n\t }\n\t clearField(\"toX\", model);\n\t clearField(\"toY\", model);\n\t }\n\n\t if (defined(this.options.type) && defined(model.type)) {\n\t model.set(\"type\", this.options.type);\n\t }\n\n\t this.dataItem = model;\n\t this.diagram._resumeModelRefresh();\n\n\t if (syncChanges) {\n\t this.diagram._syncConnectionChanges();\n\t }\n\t }\n\t }\n\t }\n\t },\n\n\t /**\n\t * Gets the Point where the source of the connection resides.\n\t * If the endpoint in Auto-connector the location of the resolved connector will be returned.\n\t * If the endpoint is floating the location of the endpoint is returned.\n\t */\n\t sourcePoint: function () {\n\t return this._resolvedSourceConnector ? this._resolvedSourceConnector.position() : this._sourcePoint;\n\t },\n\n\t _setSource: function(source) {\n\t var shapeSource = source instanceof Shape;\n\t var defaultConnector = this.options.fromConnector || AUTO;\n\t var dataItem;\n\t if (shapeSource && !source.getConnector(defaultConnector)) {\n\t return;\n\t }\n\n\t if (source !== undefined) {\n\t this.from = source;\n\t }\n\n\t this._removeFromSourceConnector();\n\n\t if (source === null) { // detach\n\t if (this.sourceConnector) {\n\t this._sourcePoint = (this._resolvedSourceConnector || this.sourceConnector).position();\n\t this._clearSourceConnector();\n\t this._setFromOptions(null, this._sourcePoint);\n\t }\n\t } else if (source instanceof Connector) {\n\t dataItem = source.shape.dataItem;\n\t if (dataItem) {\n\t this._setFromOptions(dataItem.id);\n\t }\n\t this.sourceConnector = source;\n\t this.sourceConnector.connections.push(this);\n\t } else if (source instanceof Point) {\n\t this._setFromOptions(null, source);\n\t this._sourcePoint = source;\n\t if (this.sourceConnector) {\n\t this._clearSourceConnector();\n\t }\n\n\t } else if (shapeSource) {\n\t dataItem = source.dataItem;\n\t if (dataItem) {\n\t this._setFromOptions(dataItem.id);\n\t }\n\n\t this.sourceConnector = source.getConnector(defaultConnector);\n\t this.sourceConnector.connections.push(this);\n\t }\n\t },\n\n\t source: function (source, undoable) {\n\t if (isDefined(source)) {\n\t if (undoable && this.diagram) {\n\t this.diagram.undoRedoService.addCompositeItem(new diagram.ConnectionEditUnit(this, source));\n\t }\n\t this._setSource(source);\n\t this.refresh();\n\t }\n\t return this.sourceConnector ? this.sourceConnector : this._sourcePoint;\n\t },\n\n\t _setFromOptions: function(from, fromPoint) {\n\t this.options.from = from;\n\t if (fromPoint) {\n\t this.options.fromX = fromPoint.x;\n\t this.options.fromY = fromPoint.y;\n\t } else {\n\t this.options.fromX = null;\n\t this.options.fromY = null;\n\t }\n\t },\n\n\t /**\n\t * Gets or sets the PathDefiner of the sourcePoint.\n\t * The left part of this definer is always null since it defines the source tangent.\n\t * @param value\n\t * @returns {*}\n\t */\n\t sourceDefiner: function (value) {\n\t if (value) {\n\t if (value instanceof diagram.PathDefiner) {\n\t value.left = null;\n\t this._sourceDefiner = value;\n\t this.source(value.point); // refresh implicit here\n\t } else {\n\t throw \"The sourceDefiner needs to be a PathDefiner.\";\n\t }\n\t } else {\n\t if (!this._sourceDefiner) {\n\t this._sourceDefiner = new diagram.PathDefiner(this.sourcePoint(), null, null);\n\t }\n\t return this._sourceDefiner;\n\t }\n\t },\n\n\t /**\n\t * Gets the Point where the target of the connection resides.\n\t */\n\t targetPoint: function () {\n\t return this._resolvedTargetConnector ? this._resolvedTargetConnector.position() : this._targetPoint;\n\t },\n\n\t _setTarget: function(target) {\n\t var shapeTarget = target instanceof Shape;\n\t var defaultConnector = this.options.toConnector || AUTO;\n\t var dataItem;\n\n\t if (shapeTarget && !target.getConnector(defaultConnector)) {\n\t return;\n\t }\n\n\t if (target !== undefined) {\n\t this.to = target;\n\t }\n\n\t this._removeFromTargetConnector();\n\n\t if (target === null) { // detach\n\t if (this.targetConnector) {\n\t this._targetPoint = (this._resolvedTargetConnector || this.targetConnector).position();\n\t this._clearTargetConnector();\n\t this._setToOptions(null, this._targetPoint);\n\t }\n\t } else if (target instanceof Connector) {\n\t dataItem = target.shape.dataItem;\n\t if (dataItem) {\n\t this._setToOptions(dataItem.id);\n\t }\n\t this.targetConnector = target;\n\t this.targetConnector.connections.push(this);\n\t } else if (target instanceof Point) {\n\t this._setToOptions(null, target);\n\t this._targetPoint = target;\n\t if (this.targetConnector) {\n\t this._clearTargetConnector();\n\t }\n\t } else if (shapeTarget) {\n\t dataItem = target.dataItem;\n\t if (dataItem) {\n\t this._setToOptions(dataItem.id);\n\t }\n\t this.targetConnector = target.getConnector(defaultConnector);\n\t this.targetConnector.connections.push(this);\n\t }\n\t },\n\n\t target: function (target, undoable) {\n\t if (isDefined(target)) {\n\t if (undoable && this.diagram) {\n\t this.diagram.undoRedoService.addCompositeItem(new diagram.ConnectionEditUnit(this, undefined, target));\n\t }\n\t this._setTarget(target);\n\n\t this.refresh();\n\t }\n\t return this.targetConnector ? this.targetConnector : this._targetPoint;\n\t },\n\n\t _setToOptions: function(to, toPoint) {\n\t this.options.to = to;\n\t if (toPoint) {\n\t this.options.toX = toPoint.x;\n\t this.options.toY = toPoint.y;\n\t } else {\n\t this.options.toX = null;\n\t this.options.toY = null;\n\t }\n\t },\n\n\t /**\n\t * Gets or sets the PathDefiner of the targetPoint.\n\t * The right part of this definer is always null since it defines the target tangent.\n\t * @param value\n\t * @returns {*}\n\t */\n\t targetDefiner: function (value) {\n\t if (value) {\n\t if (value instanceof diagram.PathDefiner) {\n\t value.right = null;\n\t this._targetDefiner = value;\n\t this.target(value.point); // refresh implicit here\n\t } else {\n\t throw \"The sourceDefiner needs to be a PathDefiner.\";\n\t }\n\t } else {\n\t if (!this._targetDefiner) {\n\t this._targetDefiner = new diagram.PathDefiner(this.targetPoint(), null, null);\n\t }\n\t return this._targetDefiner;\n\t }\n\t },\n\n\t _updateConnectors: function() {\n\t this._updateConnector(this.source(), \"source\");\n\t this._updateConnector(this.target(), \"target\");\n\t },\n\n\t _updateConnector: function(instance, name) {\n\t var that = this;\n\t var diagram = that.diagram;\n\t if (instance instanceof Connector && !diagram.getShapeById(instance.shape.id)) {\n\t var dataItem = instance.shape.dataItem;\n\t var connectorName = instance.options.name;\n\t var setNewTarget = function() {\n\t var shape = diagram._dataMap[dataItem.id];\n\t instance = shape.getConnector(connectorName);\n\t that[name](instance, false);\n\t that.updateModel();\n\t };\n\t if (diagram._dataMap[dataItem.id]) {\n\t setNewTarget();\n\t } else {\n\t var inactiveItem = diagram._inactiveShapeItems.getByUid(dataItem.uid);\n\t if (inactiveItem) {\n\t diagram._deferredConnectionUpdates.push(inactiveItem.onActivate(setNewTarget));\n\t }\n\t }\n\t } else {\n\t that[name](instance, false);\n\t }\n\t },\n\n\t content: function(content) {\n\t var result = this._content(content);\n\t if (defined(content)) {\n\t this._alignContent();\n\t }\n\t return result;\n\t },\n\n\t _createContentVisual: function(options) {\n\t var visual;\n\t if (isFunction(options.visual)) {\n\t visual = options.visual.call(this, options);\n\t } else if (options.text) {\n\t visual = new TextBlock(options);\n\t }\n\n\t if (visual) {\n\t this._contentVisual = visual;\n\t visual._includeInBBox = false;\n\t this.visual.append(visual);\n\t }\n\n\t return visual;\n\t },\n\n\t _updateContentVisual: function(options) {\n\t if (isFunction(options.visual)) {\n\t this.visual.remove(this._contentVisual);\n\t this._createContentVisual(options);\n\t } else {\n\t this._contentVisual.redraw(options);\n\t }\n\t },\n\n\t _alignContent: function() {\n\t if (this._contentVisual) {\n\t var offset = CONNECTION_CONTENT_OFFSET;\n\t var points = this.allPoints();\n\t var endIdx = math.floor(points.length / 2);\n\t var startIdx = endIdx - 1;\n\n\t while(startIdx > 0 && points[startIdx].equals(points[endIdx])) {\n\t startIdx--;\n\t endIdx++;\n\t }\n\n\t var endPoint = points[endIdx];\n\t var startPoint = points[startIdx];\n\n\t var boundingBox = this._contentVisual._measure();\n\t var width = boundingBox.width;\n\t var height = boundingBox.height;\n\t var alignToPath = points.length % 2 === 0;\n\t var distance = startPoint.distanceTo(endPoint);\n\n\t if (alignToPath && points.length > 2 && distance > 0 &&\n\t ((startPoint.y === endPoint.y && distance < width) || (startPoint.x === endPoint.x && distance < height))) {\n\t alignToPath = false;\n\t offset = 0;\n\t }\n\n\t var point;\n\n\t if (alignToPath) {\n\t var angle = draw.util.deg(math.atan2(endPoint.y - startPoint.y, endPoint.x - startPoint.x));\n\t point = new Point((endPoint.x - startPoint.x) / 2 + startPoint.x, (endPoint.y - startPoint.y) / 2 + startPoint.y);\n\n\t if (math.abs(angle) === 90) {\n\t point.x += offset;\n\t point.y-= height / 2;\n\t } else if (angle % 180 === 0) {\n\t point.x -= width / 2;\n\t point.y -= height + offset;\n\t } else if (angle < -90 || (0 < angle && angle < 90)) {\n\t point.y-= height;\n\t } else if (angle < 0 || angle > 90) {\n\t point.x -= width;\n\t point.y -= height;\n\t }\n\t } else {\n\t var midIdx = math.floor(points.length / 2);\n\t point = points[midIdx].clone();\n\t startPoint = points[midIdx - 1];\n\t endPoint = points[midIdx + 1];\n\n\t var offsetX = startPoint.x <= point.x && endPoint.x <= point.x ? offset : -boundingBox.width - offset;\n\t var offsetY = startPoint.y <= point.y && endPoint.y <= point.y ? offset : -boundingBox.height - offset;\n\n\t point.x += offsetX;\n\t point.y += offsetY;\n\t }\n\n\t this._contentVisual.position(point);\n\t }\n\t },\n\n\t /**\n\t * Selects or unselects this connections.\n\t * @param value True to select, false to unselect.\n\t */\n\t select: function (value) {\n\t var diagram = this.diagram, selected, deselected;\n\t if (this._canSelect()) {\n\t if (this.isSelected !== value) {\n\t this.isSelected = value;\n\t selected = [];\n\t deselected = [];\n\t if (this.isSelected) {\n\t this.adorner = new ConnectionEditAdorner(this, this.options.selection);\n\t diagram._adorn(this.adorner, true);\n\t diagram._selectedItems.push(this);\n\t selected.push(this);\n\t } else {\n\t if (this.adorner) {\n\t diagram._adorn(this.adorner, false);\n\t Utils.remove(diagram._selectedItems, this);\n\t this.adorner = undefined;\n\t deselected.push(this);\n\t }\n\t }\n\n\t if (this.adorner) {\n\t this.adorner.refresh();\n\t }\n\n\t if (!diagram._internalSelection) {\n\t diagram._selectionChanged(selected, deselected);\n\t }\n\t return true;\n\t }\n\t }\n\t },\n\t /**\n\t * Gets or sets the bounds of this connection.\n\t * @param value A Rect object.\n\t * @remark This is automatically set in the refresh().\n\t * @returns {Rect}\n\t */\n\t bounds: function (value) {\n\t if (value && !isString(value)) {\n\t this._bounds = value;\n\t } else {\n\t return this._bounds;\n\t }\n\t },\n\t /**\n\t * Gets or sets the connection type (see ConnectionType enumeration).\n\t * @param value A ConnectionType value.\n\t * @returns {ConnectionType}\n\t */\n\t type: function (value) {\n\t var options = this.options;\n\t if (value) {\n\t if (value !== options.type) {\n\t options.type = value;\n\t this._initRouter();\n\t this.refresh();\n\t }\n\t } else {\n\t return options.type;\n\t }\n\t },\n\n\t _initRouter: function() {\n\t var type = (this.options.type || \"\").toLowerCase();\n\t if (type == CASCADING) {\n\t this._router = new CascadingRouter(this);\n\t } else {\n\t this._router = new PolylineRouter(this);\n\t }\n\t },\n\t /**\n\t * Gets or sets the collection of *intermediate* points.\n\t * The 'allPoints()' property will return all the points.\n\t * The 'definers' property returns the definers of the intermediate points.\n\t * The 'sourceDefiner' and 'targetDefiner' return the definers of the endpoints.\n\t * @param value\n\t */\n\t points: function (value) {\n\t if (value) {\n\t this.definers = [];\n\t for (var i = 0; i < value.length; i++) {\n\t var definition = value[i];\n\t if (definition instanceof diagram.Point) {\n\t this.definers.push(new diagram.PathDefiner(definition));\n\t } else if (definition.hasOwnProperty(\"x\") && definition.hasOwnProperty(\"y\")) { // e.g. Clipboard does not preserve the Point definition and tunred into an Object\n\t this.definers.push(new diagram.PathDefiner(new Point(definition.x, definition.y)));\n\t } else {\n\t throw \"A Connection point needs to be a Point or an object with x and y properties.\";\n\t }\n\t }\n\n\t } else {\n\t var pts = [];\n\t if (isDefined(this.definers)) {\n\t for (var k = 0; k < this.definers.length; k++) {\n\t pts.push(this.definers[k].point);\n\t }\n\t }\n\t return pts;\n\t }\n\t },\n\t /**\n\t * Gets all the points of this connection. This is the combination of the sourcePoint, the points and the targetPoint.\n\t * @returns {Array}\n\t */\n\t allPoints: function () {\n\t var pts = [this.sourcePoint()];\n\t if (this.definers) {\n\t for (var k = 0; k < this.definers.length; k++) {\n\t pts.push(this.definers[k].point);\n\t }\n\t }\n\t pts.push(this.targetPoint());\n\t return pts;\n\t },\n\n\t refresh: function () {\n\t this._resolveConnectors();\n\t this._refreshPath();\n\t this._alignContent();\n\n\t if (this.adorner) {\n\t this.adorner.refresh();\n\t }\n\t },\n\n\t _resolveConnectors: function () {\n\t var connection = this,\n\t sourcePoint, targetPoint,\n\t sourceConnectors, targetConnectors,\n\t source = connection.source(),\n\t target = connection.target();\n\n\t if (source instanceof Point) {\n\t sourcePoint = source;\n\t } else if (source instanceof Connector) {\n\t if (isAutoConnector(source)) {\n\t sourceConnectors = source.shape.connectors;\n\t } else {\n\t sourceConnectors = [source];\n\t }\n\t }\n\n\t if (target instanceof Point) {\n\t targetPoint = target;\n\t } else if (target instanceof Connector) {\n\t if (isAutoConnector(target)) {\n\t targetConnectors = target.shape.connectors;\n\t } else {\n\t targetConnectors = [target];\n\t }\n\t }\n\n\t if (sourcePoint) {\n\t if (targetConnectors) {\n\t connection._resolvedTargetConnector = closestConnector(sourcePoint, targetConnectors);\n\t }\n\t } else if (sourceConnectors) {\n\t if (targetPoint) {\n\t connection._resolvedSourceConnector = closestConnector(targetPoint, sourceConnectors);\n\t } else if (targetConnectors) {\n\t this._resolveAutoConnectors(sourceConnectors, targetConnectors);\n\t }\n\t }\n\t },\n\n\t _resolveAutoConnectors: function(sourceConnectors, targetConnectors) {\n\t var minNonConflict = MAXINT;\n\t var minDist = MAXINT;\n\t var minNonConflictSource, minNonConflictTarget;\n\t var sourcePoint, targetPoint;\n\t var minSource, minTarget;\n\t var sourceConnector, targetConnector;\n\t var sourceIdx, targetIdx;\n\t var dist;\n\n\t for (sourceIdx = 0; sourceIdx < sourceConnectors.length; sourceIdx++) {\n\t sourceConnector = sourceConnectors[sourceIdx];\n\t if (!isAutoConnector(sourceConnector)) {\n\t sourcePoint = sourceConnector.position();\n\n\t for (targetIdx = 0; targetIdx < targetConnectors.length; targetIdx++) {\n\t targetConnector = targetConnectors[targetIdx];\n\t if (!isAutoConnector(targetConnector)) {\n\t targetPoint = targetConnector.position();\n\t dist = math.round(sourcePoint.distanceTo(targetPoint));\n\n\t if (dist < minNonConflict && this.diagram && this._testRoutePoints(sourcePoint, targetPoint, sourceConnector, targetConnector)) {\n\t minNonConflict = dist;\n\t minNonConflictSource = sourceConnector;\n\t minNonConflictTarget = targetConnector;\n\t }\n\n\t if (dist < minDist) {\n\t minSource = sourceConnector;\n\t minTarget = targetConnector;\n\t minDist = dist;\n\t }\n\t }\n\t }\n\t }\n\t }\n\n\t if (minNonConflictSource) {\n\t minSource = minNonConflictSource;\n\t minTarget = minNonConflictTarget;\n\t }\n\n\t this._resolvedSourceConnector = minSource;\n\t this._resolvedTargetConnector = minTarget;\n\t },\n\n\t _testRoutePoints: function(sourcePoint, targetPoint, sourceConnector, targetConnector) {\n\t var router = this._router;\n\t var passRoute = true;\n\t if (router instanceof CascadingRouter) {\n\t var points = router.routePoints(sourcePoint, targetPoint, sourceConnector, targetConnector),\n\t start, end,\n\t rect, exclude;\n\n\t exclude = this._getRouteExclude(sourcePoint, targetPoint, sourceConnector.shape, targetConnector.shape);\n\t points.unshift(sourcePoint);\n\t points.push(targetPoint);\n\n\n\t for (var idx = 1; idx < points.length; idx++) {\n\t start = points[idx - 1];\n\t end = points[idx];\n\t rect = new Rect(math.min(start.x, end.x), math.min(start.y, end.y),\n\t math.abs(start.x - end.x), math.abs(start.y - end.y));\n\t if (rect.width > 0) {\n\t rect.x++;\n\t rect.width-=2;\n\t }\n\t if (rect.height > 0) {\n\t rect.y++;\n\t rect.height-=2;\n\t }\n\n\t if (!rect.isEmpty() && this.diagram._shapesQuadTree.hitTestRect(rect, exclude)) {\n\t passRoute = false;\n\t break;\n\t }\n\t }\n\t }\n\t return passRoute;\n\t },\n\n\t _getRouteExclude: function(sourcePoint, targetPoint, sourceShape, targetShape) {\n\t var exclude = [];\n\t if (this._isPointInsideShape(sourcePoint, sourceShape)){\n\t exclude.push(sourceShape);\n\t }\n\t if (this._isPointInsideShape(targetPoint, targetShape)){\n\t exclude.push(targetShape);\n\t }\n\t return exclude;\n\t },\n\n\t _isPointInsideShape: function (point, shape) {\n\t var bounds = shape.bounds(), rotatedPoint,\n\t angle = shape.rotate().angle,\n\t pointX, pointY,\n\t boundsX = bounds.x,\n\t boundsY = bounds.y;\n\n\t rotatedPoint = point.clone().rotate(bounds.center(), angle);\n\t pointX = rotatedPoint.x;\n\t pointY = rotatedPoint.y;\n\t return pointX > boundsX && pointX < (boundsX + bounds.width) && pointY > boundsY && pointY < (boundsY + bounds.height);\n\t },\n\n\t redraw: function (options) {\n\t if (options) {\n\t this.options = deepExtend({}, this.options, options);\n\n\t var points = this.options.points;\n\n\t if (defined(points) && points.length > 0) {\n\t this.points(points);\n\t this._refreshPath();\n\t }\n\n\t if ((options && options.content) || options.text) {\n\t this.content(options.content);\n\t }\n\n\t this.path.redraw({\n\t fill: options.fill,\n\t stroke: options.stroke,\n\t startCap: options.startCap,\n\t endCap: options.endCap\n\t });\n\t }\n\t },\n\t /**\n\t * Returns a clone of this connection.\n\t * @returns {Connection}\n\t */\n\t clone: function () {\n\t var json = this.serialize();\n\n\t if (this.diagram && this.diagram._isEditable && defined(this.dataItem)) {\n\t json.options.dataItem = cloneDataItem(this.dataItem);\n\t }\n\n\t return new Connection(this.from, this.to, json.options);\n\t },\n\t /**\n\t * Returns a serialized connection in json format. Consist of the options and the dataItem.\n\t * @returns {Connection}\n\t */\n\t serialize: function () {\n\t var from = this.from.toJSON ? this.from.toJSON : this.from.toString(),\n\t to = this.to.toJSON ? this.to.toJSON : this.to.toString();\n\n\t var json = deepExtend({}, {\n\t options: this.options,\n\t from: from,\n\t to: to\n\t });\n\n\t if (defined(this.dataItem)) {\n\t json.dataItem = this.dataItem.toString();\n\t }\n\n\t json.options.points = this.points();\n\t return json;\n\t },\n\n\t /**\n\t * Returns whether the given Point or Rect hits this connection.\n\t * @param value\n\t * @returns {Connection}\n\t * @private\n\t */\n\t _hitTest: function (value) {\n\t if (this.visible()) {\n\t var p = new Point(value.x, value.y), from = this.sourcePoint(), to = this.targetPoint();\n\t if (value.isEmpty && !value.isEmpty() && value.contains(from) && value.contains(to)) {\n\t return this;\n\t }\n\t if (this._router.hitTest(p)) {\n\t return this;\n\t }\n\t }\n\t },\n\n\t _hover: function (value) {\n\t var color = (this.options.stroke || {}).color;\n\n\t if (value && isDefined(this.options.hover.stroke.color)) {\n\t color = this.options.hover.stroke.color;\n\t }\n\n\t this.path.redraw({\n\t stroke: {\n\t color: color\n\t }\n\t });\n\t },\n\n\t _refreshPath: function () {\n\t if (!defined(this.path)) {\n\t return;\n\t }\n\t this._drawPath();\n\t this.bounds(this._router.getBounds());\n\t },\n\n\t _drawPath: function () {\n\t if (this._router) {\n\t this._router.route(); // sets the intermediate points\n\t }\n\t var source = this.sourcePoint();\n\t var target = this.targetPoint();\n\t var points = this.points();\n\n\t this.path.redraw({\n\t points: [source].concat(points, [target])\n\t });\n\t },\n\n\t _clearSourceConnector: function () {\n\t this.sourceConnector = undefined;\n\t this._resolvedSourceConnector = undefined;\n\t },\n\n\t _clearTargetConnector: function () {\n\t this.targetConnector = undefined;\n\t this._resolvedTargetConnector = undefined;\n\t },\n\n\t _removeFromSourceConnector: function() {\n\t if (this.sourceConnector) {\n\t Utils.remove(this.sourceConnector.connections, this);\n\t }\n\t },\n\n\t _removeFromTargetConnector: function() {\n\t if (this.targetConnector) {\n\t Utils.remove(this.targetConnector.connections, this);\n\t }\n\t },\n\n\t toJSON: function() {\n\t var connection = this;\n\t var from, to, point;\n\t if (connection.from && connection.from.toJSON) {\n\t from = connection.from.toJSON();\n\t } else {\n\t point = connection._sourcePoint;\n\t from = {\n\t x: point.x,\n\t y: point.y\n\t };\n\t }\n\n\t if (connection.to && connection.to.toJSON) {\n\t to = connection.to.toJSON();\n\t } else {\n\t point = connection._targetPoint;\n\t to = {\n\t x: point.x,\n\t y: point.y\n\t };\n\t }\n\n\t return {\n\t from : from,\n\t to: to\n\t };\n\t }\n\t });\n\n\t var Diagram = Widget.extend({\n\t init: function (element, userOptions) {\n\t var that = this;\n\n\t kendo.destroy(element);\n\t Widget.fn.init.call(that, element, userOptions);\n\n\t that._initTheme();\n\n\t that._initElements();\n\t that._extendLayoutOptions(that.options);\n\t that._initDefaults(userOptions);\n\t that._interactionDefaults();\n\n\t that._initCanvas();\n\n\t that.mainLayer = new Group({\n\t id: \"main-layer\"\n\t });\n\t that.canvas.append(that.mainLayer);\n\n\t that._shapesQuadTree = new ShapesQuadTree(that);\n\n\t that._pan = new Point();\n\t that._adorners = [];\n\t that.adornerLayer = new Group({\n\t id: \"adorner-layer\"\n\t });\n\t that.canvas.append(that.adornerLayer);\n\n\t that._createHandlers();\n\n\t that._initialize();\n\n\t that._resizingAdorner = new ResizingAdorner(that, { editable: that.options.editable });\n\t that._connectorsAdorner = new ConnectorsAdorner(that);\n\n\t that._adorn(that._resizingAdorner, true);\n\t that._adorn(that._connectorsAdorner, true);\n\n\t that.selector = new Selector(that);\n\t // TODO: We may consider using real Clipboard API once is supported by the standard.\n\t that._clipboard = [];\n\n\t that.pauseMouseHandlers = false;\n\n\t that._fetchFreshData();\n\n\t that._createGlobalToolBar();\n\n\t that._createOptionElements();\n\n\t that.zoom(that.options.zoom);\n\n\t that.canvas.draw();\n\t },\n\n\t options: {\n\t name: \"Diagram\",\n\t theme: \"default\",\n\t layout: \"\",\n\t zoomRate: 0.1,\n\t zoom: 1,\n\t zoomMin: 0,\n\t zoomMax: 2,\n\t dataSource: {},\n\t draggable: true,\n\t template: \"\",\n\t autoBind: true,\n\t editable: {\n\t rotate: {},\n\t resize: {},\n\t text: true,\n\t tools: [],\n\t drag: {\n\t snap: {\n\t size: 10,\n\t angle: 10\n\t }\n\t },\n\t remove: true\n\t },\n\t pannable: {},\n\t selectable: {\n\t key: \"none\"\n\t },\n\t tooltip: { enabled: true, format: \"{0}\" },\n\t copy: {\n\t enabled: true,\n\t offsetX: 20,\n\t offsetY: 20\n\t },\n\t shapeDefaults: diagram.shapeDefaults({ undoable: true }),\n\t connectionDefaults: {\n\t editable: {\n\t tools: []\n\t },\n\t type: CASCADING\n\t },\n\t shapes: [],\n\t connections: []\n\t },\n\n\t events: [\n\t ZOOM_END,\n\t ZOOM_START,\n\t PAN, SELECT,\n\t ITEMROTATE,\n\t ITEMBOUNDSCHANGE,\n\t CHANGE,\n\t CLICK,\n\t MOUSE_ENTER,\n\t MOUSE_LEAVE,\n\t \"toolBarClick\",\n\t \"save\",\n\t \"cancel\",\n\t \"edit\",\n\t \"remove\",\n\t \"add\",\n\t \"dataBound\",\n\t DRAG_START,\n\t DRAG,\n\t DRAG_END\n\t ],\n\n\t items: function() {\n\t return $();\n\t },\n\n\t _createGlobalToolBar: function() {\n\t var editable = this.options.editable;\n\t if (editable) {\n\t var tools = editable.tools;\n\t if (this._isEditable && tools !== false && (!tools || tools.length === 0)) {\n\t tools = [\"createShape\", \"undo\", \"redo\", \"rotateClockwise\", \"rotateAnticlockwise\"];\n\t }\n\n\t if (tools && tools.length) {\n\t this.toolBar = new DiagramToolBar(this, {\n\t tools: tools || {},\n\t click: proxy(this._toolBarClick, this),\n\t modal: false\n\t });\n\n\t this.toolBar.element.css({\n\t textAlign: \"left\"\n\t });\n\n\t this.element.prepend(this.toolBar.element);\n\t this._resize();\n\t }\n\t }\n\t },\n\n\t createShape: function() {\n\t if ((this.editor && this.editor.end()) || !this.editor) {\n\t var dataSource = this.dataSource;\n\t var view = dataSource.view() || [];\n\t var index = view.length;\n\t var model = createModel(dataSource, {});\n\t var shape = this._createShape(model, {});\n\n\t if (!this.trigger(\"add\", { shape: shape })) {\n\t dataSource.insert(index, model);\n\t var inactiveItem = this._inactiveShapeItems.getByUid(model.uid);\n\t inactiveItem.element = shape;\n\t this.edit(shape);\n\t }\n\t }\n\t },\n\n\t _createShape: function(dataItem, options) {\n\t options = deepExtend({}, this.options.shapeDefaults, options);\n\t options.dataItem = dataItem;\n\t var shape = new Shape(options, this);\n\t return shape;\n\t },\n\n\t createConnection: function() {\n\t if (((this.editor && this.editor.end()) || !this.editor)) {\n\t var connectionsDataSource = this.connectionsDataSource;\n\t var view = connectionsDataSource.view() || [];\n\t var index = view.length;\n\t var model = createModel(connectionsDataSource, {});\n\t var connection = this._createConnection(model);\n\t if (!this.trigger(\"add\", { connection: connection })) {\n\t this._connectionsDataMap[model.uid] = connection;\n\t connectionsDataSource.insert(index, model);\n\t this.addConnection(connection, false);\n\t this.edit(connection);\n\t }\n\t }\n\t },\n\n\t _createConnection: function(dataItem, source, target) {\n\t var options = deepExtend({}, this.options.connectionDefaults);\n\t options.dataItem = dataItem;\n\n\t var connection = new Connection(source || new Point(), target || new Point(), options);\n\n\t return connection;\n\t },\n\n\t editModel: function(dataItem, editorType) {\n\t this.cancelEdit();\n\t var editors, template;\n\t var editable = this.options.editable;\n\n\t if (editorType == \"shape\") {\n\t editors = editable.shapeEditors;\n\t template = editable.shapeTemplate;\n\t } else if (editorType == \"connection\") {\n\t var connectionSelectorHandler = proxy(connectionSelector, this);\n\t editors = deepExtend({}, { from: connectionSelectorHandler, to: connectionSelectorHandler }, editable.connectionEditors);\n\t template = editable.connectionTemplate;\n\t } else {\n\t return;\n\t }\n\n\t this.editor = new PopupEditor(this.element, {\n\t update: proxy(this._update, this),\n\t cancel: proxy(this._cancel, this),\n\t model: dataItem,\n\t type: editorType,\n\t target: this,\n\t editors: editors,\n\t template: template\n\t });\n\n\t this.trigger(\"edit\", this._editArgs());\n\t },\n\n\t edit: function(item) {\n\t if (item.dataItem) {\n\t var editorType = item instanceof Shape ? \"shape\" : \"connection\";\n\t this.editModel(item.dataItem, editorType);\n\t }\n\t },\n\n\t cancelEdit: function() {\n\t if (this.editor) {\n\t this._getEditDataSource().cancelChanges(this.editor.model);\n\n\t this._destroyEditor();\n\t }\n\t },\n\n\t saveEdit: function() {\n\t if (this.editor && this.editor.end() &&\n\t !this.trigger(\"save\", this._editArgs())) {\n\t this._getEditDataSource().sync();\n\t }\n\t },\n\n\t _update: function() {\n\t if (this.editor && this.editor.end() &&\n\t !this.trigger(\"save\", this._editArgs())) {\n\t this._getEditDataSource().sync();\n\t this._destroyEditor();\n\t }\n\t },\n\n\t _cancel: function() {\n\t if (this.editor && !this.trigger(\"cancel\", this._editArgs())) {\n\t var model = this.editor.model;\n\t this._getEditDataSource().cancelChanges(model);\n\t var element = this._connectionsDataMap[model.uid] || this._dataMap[model.id];\n\t if (element) {\n\t element._setOptionsFromModel(model);\n\t }\n\t this._destroyEditor();\n\t }\n\t },\n\n\t _getEditDataSource: function() {\n\t return this.editor.options.type === \"shape\" ? this.dataSource : this.connectionsDataSource;\n\t },\n\n\t _editArgs: function() {\n\t var result = { container: this.editor.wrapper };\n\t result[this.editor.options.type] = this.editor.model;\n\t return result;\n\t },\n\n\t _destroyEditor: function() {\n\t if (this.editor) {\n\t this.editor.close();\n\t this.editor = null;\n\t }\n\t },\n\n\t _initElements: function() {\n\t this.wrapper = this.element.empty()\n\t .css(\"position\", \"relative\")\n\t .attr(\"tabindex\", 0)\n\t .addClass(\"k-widget k-diagram\");\n\n\t this.scrollable = $(\"\").appendTo(this.element);\n\t },\n\n\t _initDefaults: function(userOptions) {\n\t var options = this.options;\n\t var editable = options.editable;\n\t var shapeDefaults = options.shapeDefaults;\n\t var connectionDefaults = options.connectionDefaults;\n\t var userShapeDefaults = (userOptions || {}).shapeDefaults;\n\t if (editable === false) {\n\t shapeDefaults.editable = false;\n\t connectionDefaults.editable = false;\n\t } else {\n\t copyDefaultOptions(editable, shapeDefaults.editable, [\"drag\", \"remove\", \"connect\"]);\n\t copyDefaultOptions(editable, connectionDefaults.editable, [\"drag\", \"remove\"]);\n\t }\n\n\t if (userShapeDefaults && userShapeDefaults.connectors) {\n\t options.shapeDefaults.connectors = userShapeDefaults.connectors;\n\t }\n\t },\n\n\t _interactionDefaults: function() {\n\t var options = this.options;\n\t var selectable = options.selectable;\n\t var pannable = options.pannable;\n\t var mobile = kendo.support.mobileOS;\n\n\t if (selectable && !defined(selectable.multiple)) {\n\t options.selectable = deepExtend({\n\t multiple: mobile ? false : true\n\t }, options.selectable);\n\t }\n\n\t if (pannable && !defined(pannable.key)) {\n\t options.pannable = deepExtend({\n\t key: mobile ? \"none\" : \"ctrl\"\n\t }, options.pannable);\n\t }\n\t },\n\n\t _initCanvas: function() {\n\t var canvasContainer = $(\"\").appendTo(this.scrollable)[0];\n\t var viewPort = this.viewport();\n\t this.canvas = new Canvas(canvasContainer, {\n\t width: viewPort.width || DEFAULT_CANVAS_WIDTH,\n\t height: viewPort.height || DEFAULT_CANVAS_HEIGHT\n\t });\n\t },\n\n\t _createHandlers: function () {\n\t var that = this;\n\t var element = that.element;\n\n\t element.on(MOUSEWHEEL_NS, proxy(that._wheel, that))\n\t .on(\"keydown\" + NS, proxy(that._keydown, that));\n\n\t that._userEvents = new kendo.UserEvents(this.scrollable, {\n\t multiTouch: true,\n\t fastTap: true,\n\t tap: proxy(that._tap, that),\n\t start: proxy(that._dragStart, that),\n\t move: proxy(that._drag, that),\n\t end: proxy(that._dragEnd, that),\n\t gesturestart: proxy(that._gestureStart, that),\n\t gesturechange: proxy(that._gestureChange, that),\n\t gestureend: proxy(that._gestureEnd, that),\n\t doubleTap: proxy(that._doubleTap, that),\n\t supportDoubleTap: true\n\t });\n\n\t that.toolService = new ToolService(that);\n\n\t this.scrollable\n\t .on(\"mouseover\" + NS, proxy(that._mouseover, that))\n\t .on(\"mouseout\" + NS, proxy(that._mouseout, that))\n\t .on(\"mousemove\" + NS, proxy(that._mouseMove, that))\n\t .on(\"mousedown\" + NS, proxy(that._mouseDown, that))\n\t .on(\"mouseup\" + NS, proxy(that._mouseUp, that));\n\n\t this._syncHandler = proxy(that._syncChanges, that);\n\n\t that._resizeHandler = proxy(that.resize, that, false);\n\t kendo.onResize(that._resizeHandler);\n\n\t this.bind(ZOOM_START, proxy(that._destroyToolBar, that));\n\t this.bind(PAN, proxy(that._destroyToolBar, that));\n\t },\n\n\t _dragStart: function (e) {\n\t this._pauseMouseHandlers = true;\n\t var point = this._eventPositions(e, true);\n\n\t var event = e.event;\n\t if (this.toolService.start(point, this._meta(event))) {\n\t this._destroyToolBar();\n\t event.preventDefault();\n\t }\n\t },\n\n\t _drag: function (e) {\n\t var p = this._eventPositions(e);\n\t var event = e.event;\n\t if (this.toolService.move(p, this._meta(event))) {\n\t event.preventDefault();\n\t }\n\t },\n\n\t _dragEnd: function (e) {\n\t this._pauseMouseHandlers = false;\n\t var p = this._eventPositions(e);\n\t var event = e.event;\n\t if (this.toolService.end(p, this._meta(event))) {\n\t this._createToolBar();\n\t event.preventDefault();\n\t }\n\t },\n\n\t _mouseMove: function (e) {\n\t if (!this._pauseMouseHandlers) {\n\t var p = this._eventPositions(e);\n\t this.toolService._updateHoveredItem(p);\n\t this.toolService._updateCursor(p);\n\t }\n\t },\n\n\t _mouseDown: function () {\n\t this._pauseMouseHandlers = true;\n\t },\n\n\t _mouseUp: function () {\n\t this._pauseMouseHandlers = false;\n\t },\n\n\t _tap: function(e) {\n\t var toolService = this.toolService;\n\t var selectable = this.options.selectable;\n\t var point = this._eventPositions(e);\n\t var focused = this.focus();\n\n\t toolService._updateHoveredItem(point);\n\n\t if (toolService.hoveredItem) {\n\t var item = toolService.hoveredItem;\n\n\t this.trigger(\"click\", {\n\t item: item,\n\t point: point\n\t });\n\n\t if (selectable && item.options.selectable !== false) {\n\t var multiple = selectable.multiple !== false;\n\t var ctrlPressed = kendo.support.mobileOS || this._meta(e.event).ctrlKey;\n\n\t if (item.isSelected) {\n\t if (ctrlPressed) {\n\t this._destroyToolBar();\n\t item.select(false);\n\t } else {\n\t this._createToolBar(focused);\n\t }\n\t } else {\n\t this._destroyToolBar();\n\t this.select(item, {\n\t addToSelection: multiple && ctrlPressed\n\t });\n\t this._createToolBar(focused);\n\t }\n\t }\n\t } else if (selectable) {\n\t this._destroyToolBar();\n\t this.deselect();\n\t }\n\t },\n\n\t _keydown: function (e) {\n\t if (this.toolService.keyDown(e.keyCode, this._meta(e))) {\n\t e.preventDefault();\n\t }\n\t },\n\n\t _wheel: function (e) {\n\t var delta = mwDelta(e),\n\t p = this._eventPositions(e),\n\t meta = deepExtend(this._meta(e), { delta: delta });\n\n\t if (this.toolService.wheel(p, meta)) {\n\t e.preventDefault();\n\t }\n\t },\n\n\t _meta: function (e) {\n\t return { ctrlKey: e.ctrlKey, metaKey: e.metaKey, altKey: e.altKey, shiftKey: e.shiftKey, type: e.type };\n\t },\n\n\t _eventPositions: function (e, start) {\n\t var point;\n\t if (e.touch) {\n\t var field = start ? \"startLocation\" : \"location\";\n\t point = new Point(e.x[field], e.y[field]);\n\t } else {\n\t var event = e.originalEvent;\n\t point = new Point(event.pageX, event.pageY);\n\t }\n\n\t return this.documentToModel(point);\n\t },\n\n\t _gestureStart: function(e) {\n\t this._destroyToolBar();\n\t this.scroller.disable();\n\t var initialCenter = this.documentToModel(new Point(e.center.x, e.center.y));\n\t var eventArgs = {\n\t point: initialCenter,\n\t zoom: this.zoom()\n\t };\n\n\t if (this.trigger(ZOOM_START, eventArgs)) {\n\t return;\n\t }\n\n\t this._gesture = e;\n\t this._initialCenter = initialCenter;\n\t },\n\n\t _gestureChange: function(e) {\n\t var previousGesture = this._gesture;\n\t var initialCenter = this._initialCenter;\n\t var center = this.documentToView(new Point(e.center.x, e.center.y));\n\t var scaleDelta = e.distance / previousGesture.distance;\n\t var zoom = this._zoom;\n\t var updateZoom = false;\n\n\t if (math.abs(scaleDelta - 1) >= MOBILE_ZOOM_RATE) {\n\t this._zoom = zoom = this._getValidZoom(zoom * scaleDelta);\n\t this.options.zoom = zoom;\n\t this._gesture = e;\n\t updateZoom = true;\n\t }\n\n\t var zoomedPoint = initialCenter.times(zoom);\n\t var pan = center.minus(zoomedPoint);\n\t if (updateZoom || this._pan.distanceTo(pan) >= MOBILE_PAN_DISTANCE) {\n\t this._panTransform(pan);\n\t this._updateAdorners();\n\t }\n\n\t e.preventDefault();\n\t },\n\n\t _doubleTap: function(e) {\n\t var diagram = this;\n\t var pointPosition = this._eventPositions(e);\n\t var options = diagram.options;\n\t var zoomRate = options.zoomRate;\n\t var zoom = diagram.zoom() + zoomRate;\n\t var meta = this._meta(e);\n\t var zoomOptions = { point: pointPosition, meta: meta, zoom: zoom };\n\n\n\t if (diagram.trigger(ZOOM_START, zoomOptions)) {\n\t return;\n\t }\n\n\t zoom = kendo.dataviz.round(Math.max(options.zoomMin, Math.min(options.zoomMax, zoom)), 2);\n\t zoomOptions.zoom = zoom;\n\n\t diagram.zoom(zoom, zoomOptions);\n\t diagram.trigger(ZOOM_END, zoomOptions);\n\t },\n\n\t _gestureEnd: function() {\n\t if (this.options.pannable !== false) {\n\t this.scroller.enable();\n\t }\n\t this.trigger(ZOOM_END, {\n\t point: this._initialCenter,\n\t zoom: this.zoom()\n\t });\n\t },\n\n\t _resize: function() {\n\t var viewport = this.viewport();\n\t if (this.canvas) {\n\t this.canvas.size(viewport);\n\t }\n\n\t if (this.scrollable && this.toolBar) {\n\t this.scrollable.height(viewport.height);\n\t }\n\t },\n\n\t _mouseover: function(e) {\n\t var node = e.target._kendoNode;\n\t if (node && node.srcElement._hover) {\n\t node.srcElement._hover(true, node.srcElement);\n\t }\n\t },\n\n\t _mouseout: function(e) {\n\t var node = e.target._kendoNode;\n\t if (node && node.srcElement._hover) {\n\t node.srcElement._hover(false, node.srcElement);\n\t }\n\t },\n\n\t _initTheme: function() {\n\t var that = this;\n\t var themeName = ((that.options || {}).theme || \"\").toLowerCase();\n\t var themes = dataviz.ui.themes || {};\n\t var themeOptions;\n\n\t if(dataviz.SASS_THEMES.indexOf(themeName) != -1) {\n\t themeOptions = dataviz.autoTheme().diagram;\n\t }\n\t else {\n\t themeOptions = (themes[themeName] || {}).diagram;\n\t }\n\n\t that.options = deepExtend({}, themeOptions, that.options);\n\t if (that.options.editable === true) {\n\t deepExtend(that.options, {\n\t editable: (themeOptions || {}).editable\n\t });\n\t }\n\t },\n\n\t _createOptionElements: function() {\n\t var options = this.options;\n\t var shapesLength = options.shapes.length;\n\n\t if (shapesLength) {\n\t this._createShapes();\n\t }\n\n\t if (options.connections.length) {\n\t this._createConnections();\n\t }\n\n\t if (shapesLength && options.layout) {\n\t this.layout(options.layout);\n\t }\n\t },\n\n\t _createShapes: function() {\n\t var that = this,\n\t options = that.options,\n\t shapes = options.shapes,\n\t shape, i;\n\n\t for (i = 0; i < shapes.length; i++) {\n\t shape = shapes[i];\n\t that.addShape(shape);\n\t }\n\t },\n\n\t _createConnections: function() {\n\t var diagram = this,\n\t options = diagram.options,\n\t defaults = options.connectionDefaults,\n\t connections = options.connections,\n\t conn, source, target, i;\n\n\t for(i = 0; i < connections.length; i++) {\n\t conn = connections[i];\n\t source = diagram._findConnectionTarget(conn.from);\n\t target = diagram._findConnectionTarget(conn.to);\n\n\t diagram.connect(source, target, deepExtend({}, defaults, conn));\n\t }\n\t },\n\n\t _findConnectionTarget: function(options) {\n\t options = options || {};\n\t var diagram = this;\n\t var shapeId = isString(options) ? options : options.shapeId || options.id;\n\t var target;\n\t if (shapeId) {\n\t target = diagram.getShapeById(shapeId);\n\t if (options.connector) {\n\t target = target.getConnector(options.connector);\n\t }\n\t } else {\n\t target = new Point(options.x || 0, options.y || 0);\n\t }\n\n\t return target;\n\t },\n\n\t destroy: function () {\n\t var that = this;\n\t Widget.fn.destroy.call(that);\n\n\t if (this._userEvents) {\n\t this._userEvents.destroy();\n\t }\n\n\t kendo.unbindResize(that._resizeHandler);\n\n\t that.clear();\n\t that.element.off(NS);\n\t that.scroller.wrapper.off(NS);\n\t that.canvas.destroy(true);\n\t that.canvas = undefined;\n\n\t that._destroyEditor();\n\t that.destroyScroller();\n\t that._destroyGlobalToolBar();\n\t that._destroyToolBar();\n\t },\n\n\t destroyScroller: function () {\n\t var scroller = this.scroller;\n\n\t if (!scroller) {\n\t return;\n\t }\n\n\t scroller.destroy();\n\t scroller.element.remove();\n\t this.scroller = null;\n\t },\n\n\t save: function () {\n\t var json = {\n\t shapes: [],\n\t connections: []\n\t };\n\t var i, connection, shape;\n\n\t for (i = 0; i < this.shapes.length; i++) {\n\t shape = this.shapes[i];\n\t if (shape.options.serializable) {\n\t json.shapes.push(shape.options);\n\t }\n\t }\n\n\t for (i = 0; i < this.connections.length; i++) {\n\t connection = this.connections[i];\n\n\t json.connections.push(deepExtend({}, connection.options, connection.toJSON()));\n\t }\n\n\t return json;\n\t },\n\n\t focus: function() {\n\t if (!this.element.is(kendo._activeElement())) {\n\t var element = this.element,\n\t scrollContainer = element[0],\n\t containers = [],\n\t offsets = [],\n\t documentElement = document.documentElement,\n\t i;\n\n\t do {\n\t scrollContainer = scrollContainer.parentNode;\n\n\t if (scrollContainer.scrollHeight > scrollContainer.clientHeight) {\n\t containers.push(scrollContainer);\n\t offsets.push(scrollContainer.scrollTop);\n\t }\n\t } while (scrollContainer != documentElement);\n\n\t element.focus();\n\n\t for (i = 0; i < containers.length; i++) {\n\t containers[i].scrollTop = offsets[i];\n\t }\n\t return true;\n\t }\n\t },\n\n\t load: function(options) {\n\t this.clear();\n\n\t this.setOptions(options);\n\t this._createShapes();\n\t this._createConnections();\n\t },\n\n\t setOptions: function(options) {\n\t deepExtend(this.options, options);\n\t },\n\n\t clear: function () {\n\t var that = this;\n\n\t that.select(false);\n\t that.mainLayer.clear();\n\t that._shapesQuadTree.clear();\n\t that._initialize();\n\t },\n\t /**\n\t * Connects two items.\n\t * @param source Shape, Connector, Point.\n\t * @param target Shape, Connector, Point.\n\t * @param options Connection options that will be passed to the newly created connection.\n\t * @returns The newly created connection.\n\t */\n\t connect: function (source, target, options) {\n\t var connection;\n\t if (this.connectionsDataSource && this._isEditable) {\n\t var dataItem = this.connectionsDataSource.add({});\n\t connection = this._connectionsDataMap[dataItem.uid];\n\t connection.source(source);\n\t connection.target(target);\n\t connection.redraw(options);\n\t connection.updateModel();\n\t } else {\n\t connection = new Connection(source, target,\n\t deepExtend({ }, this.options.connectionDefaults, options));\n\n\t this.addConnection(connection);\n\t }\n\n\t return connection;\n\t },\n\t /**\n\t * Determines whether the the two items are connected.\n\t * @param source Shape, Connector, Point.\n\t * @param target Shape, Connector, Point.\n\t * @returns true if the two items are connected.\n\t */\n\t connected: function (source, target) {\n\t for (var i = 0; i < this.connections.length; i++) {\n\t var c = this.connections[i];\n\t if (c.from == source && c.to == target) {\n\t return true;\n\t }\n\t }\n\n\t return false;\n\t },\n\t /**\n\t * Adds connection to the diagram.\n\t * @param connection Connection.\n\t * @param undoable Boolean.\n\t * @returns The newly created connection.\n\t */\n\t addConnection: function (connection, undoable) {\n\t if (undoable !== false) {\n\t this.undoRedoService.add(\n\t new diagram.AddConnectionUnit(connection, this), false);\n\t }\n\n\t connection.diagram = this;\n\t connection._setOptionsFromModel();\n\t connection.refresh();\n\t this.mainLayer.append(connection.visual);\n\t this.connections.push(connection);\n\n\t this.trigger(CHANGE, {\n\t added: [connection],\n\t removed: []\n\t });\n\n\t return connection;\n\t },\n\n\t _addConnection: function (connection, undoable) {\n\t var connectionsDataSource = this.connectionsDataSource;\n\t var dataItem;\n\t if (connectionsDataSource && this._isEditable) {\n\t dataItem = createModel(connectionsDataSource, cloneDataItem(connection.dataItem));\n\t connection.dataItem = dataItem;\n\t connection.updateModel();\n\n\t if (!this.trigger(\"add\", { connection: connection })) {\n\t this._connectionsDataMap[dataItem.uid] = connection;\n\n\t connectionsDataSource.add(dataItem);\n\t this.addConnection(connection, undoable);\n\t connection._updateConnectors();\n\n\t return connection;\n\t }\n\t } else if (!this.trigger(\"add\", { connection: connection })) {\n\t this.addConnection(connection, undoable);\n\t connection._updateConnectors();\n\t return connection;\n\t }\n\t },\n\n\t /**\n\t * Adds shape to the diagram.\n\t * @param item Shape, Point. If point is passed it will be created new Shape and positioned at that point.\n\t * @param options. The options to be passed to the newly created Shape.\n\t * @returns The newly created shape.\n\t */\n\t addShape: function(item, undoable) {\n\t var shape,\n\t shapeDefaults = this.options.shapeDefaults;\n\n\t if (item instanceof Shape) {\n\t shape = item;\n\t } else if (!(item instanceof kendo.Class)) {\n\t shapeDefaults = deepExtend({}, shapeDefaults, item || {});\n\t shape = new Shape(shapeDefaults, this);\n\t } else {\n\t return;\n\t }\n\n\t if (undoable !== false) {\n\t this.undoRedoService.add(new diagram.AddShapeUnit(shape, this), false);\n\t }\n\n\t this.shapes.push(shape);\n\t if (shape.diagram !== this) {\n\t this._shapesQuadTree.insert(shape);\n\t shape.diagram = this;\n\t }\n\t this.mainLayer.append(shape.visual);\n\n\t this.trigger(CHANGE, {\n\t added: [shape],\n\t removed: []\n\t });\n\n\t return shape;\n\t },\n\n\t _addShape: function(shape, undoable) {\n\t var that = this;\n\t var dataSource = that.dataSource;\n\t var dataItem;\n\t if (dataSource && this._isEditable) {\n\t dataItem = createModel(dataSource, cloneDataItem(shape.dataItem));\n\t shape.dataItem = dataItem;\n\t shape.updateModel();\n\n\t if (!this.trigger(\"add\", { shape: shape })) {\n\t this.dataSource.add(dataItem);\n\t var inactiveItem = this._inactiveShapeItems.getByUid(dataItem.uid);\n\t inactiveItem.element = shape;\n\t inactiveItem.undoable = undoable;\n\t return shape;\n\t }\n\t } else if (!this.trigger(\"add\", { shape: shape })) {\n\t return this.addShape(shape, undoable);\n\t }\n\t },\n\t /**\n\t * Removes items (or single item) from the diagram.\n\t * @param items DiagramElement, Array of Items.\n\t * @param undoable.\n\t */\n\n\t remove: function(items, undoable) {\n\t items = isArray(items) ? items.slice(0) : [items];\n\t var elements = splitDiagramElements(items);\n\t var shapes = elements.shapes;\n\t var connections = elements.connections;\n\t var i;\n\n\t if (!defined(undoable)) {\n\t undoable = true;\n\t }\n\n\t if (undoable) {\n\t this.undoRedoService.begin();\n\t }\n\n\t this._suspendModelRefresh();\n\t for (i = shapes.length - 1; i >= 0; i--) {\n\t this._removeItem(shapes[i], undoable, connections);\n\t }\n\n\t for (i = connections.length - 1; i >= 0; i--) {\n\t this._removeItem(connections[i], undoable);\n\t }\n\n\t this._resumeModelRefresh();\n\n\t if (undoable) {\n\t this.undoRedoService.commit(false);\n\t }\n\n\t this.trigger(CHANGE, {\n\t added: [],\n\t removed: items\n\t });\n\t },\n\n\t _removeShapeDataItem: function(item) {\n\t if (this._isEditable) {\n\t this.dataSource.remove(item.dataItem);\n\t delete this._dataMap[item.dataItem.id];\n\t }\n\t },\n\n\t _removeConnectionDataItem: function(item) {\n\t if (this._isEditable) {\n\t this.connectionsDataSource.remove(item.dataItem);\n\t delete this._connectionsDataMap[item.dataItem.uid];\n\t }\n\t },\n\n\t _triggerRemove: function(items){\n\t var toRemove = [];\n\t var item, args, editable;\n\n\t for (var idx = 0; idx < items.length; idx++) {\n\t item = items[idx];\n\t editable = item.options.editable;\n\t if (item instanceof Shape) {\n\t args = { shape: item };\n\t } else {\n\t args = { connection: item };\n\t }\n\t if (editable && editable.remove !== false && !this.trigger(\"remove\", args)) {\n\t toRemove.push(item);\n\t }\n\t }\n\t return toRemove;\n\t },\n\n\t /**\n\t * Executes the next undoable action on top of the undo stack if any.\n\t */\n\t undo: function () {\n\t this.undoRedoService.undo();\n\t },\n\t /**\n\t * Executes the previous undoable action on top of the redo stack if any.\n\t */\n\t redo: function () {\n\t this.undoRedoService.redo();\n\t },\n\t /**\n\t * Selects items on the basis of the given input or returns the current selection if none.\n\t * @param itemsOrRect DiagramElement, Array of elements, \"All\", false or Rect. A value 'false' will deselect everything.\n\t * @param options\n\t * @returns {Array}\n\t */\n\t select: function (item, options) {\n\t if (isDefined(item)) {\n\t options = deepExtend({ addToSelection: false }, options);\n\n\t var addToSelection = options.addToSelection,\n\t items = [],\n\t selected = [],\n\t i, element;\n\n\t if (!addToSelection) {\n\t this.deselect();\n\t }\n\n\t this._internalSelection = true;\n\n\t if (item instanceof Array) {\n\t items = item;\n\t } else if (item instanceof DiagramElement) {\n\t items = [ item ];\n\t }\n\n\t for (i = 0; i < items.length; i++) {\n\t element = items[i];\n\t if (element.select(true)) {\n\t selected.push(element);\n\t }\n\t }\n\n\t this._selectionChanged(selected, []);\n\n\t this._internalSelection = false;\n\t } else {\n\t return this._selectedItems;\n\t }\n\t },\n\n\t selectAll: function() {\n\t this.select(this.shapes.concat(this.connections));\n\t },\n\n\t selectArea: function(rect) {\n\t var i, items, item;\n\t this._internalSelection = true;\n\t var selected = [];\n\t if (rect instanceof Rect) {\n\t items = this.shapes.concat(this.connections);\n\t for (i = 0; i < items.length; i++) {\n\t item = items[i];\n\t if ((!rect || item._hitTest(rect)) && item.options.enable) {\n\t if (item.select(true)) {\n\t selected.push(item);\n\t }\n\t }\n\t }\n\t }\n\n\t this._selectionChanged(selected, []);\n\t this._internalSelection = false;\n\t },\n\n\t deselect: function(item) {\n\t this._internalSelection = true;\n\t var deselected = [],\n\t items = [],\n\t element, i;\n\n\t if (item instanceof Array) {\n\t items = item;\n\t } else if (item instanceof DiagramElement) {\n\t items.push(item);\n\t } else if (!isDefined(item)) {\n\t items = this._selectedItems.slice(0);\n\t }\n\n\t for (i = 0; i < items.length; i++) {\n\t element = items[i];\n\t if (element.select(false)) {\n\t deselected.push(element);\n\t }\n\t }\n\n\t this._selectionChanged([], deselected);\n\t this._internalSelection = false;\n\t },\n\t /**\n\t * Brings to front the passed items.\n\t * @param items DiagramElement, Array of Items.\n\t * @param undoable. By default the action is undoable.\n\t */\n\t toFront: function (items, undoable) {\n\t if (!items) {\n\t items = this._selectedItems.slice();\n\t }\n\n\t var result = this._getDiagramItems(items), indices;\n\t if (!defined(undoable) || undoable) {\n\t indices = indicesOfItems(this.mainLayer, result.visuals);\n\t var unit = new ToFrontUnit(this, items, indices);\n\t this.undoRedoService.add(unit);\n\t } else {\n\t this.mainLayer.toFront(result.visuals);\n\t this._fixOrdering(result, true);\n\t }\n\t },\n\t /**\n\t * Sends to back the passed items.\n\t * @param items DiagramElement, Array of Items.\n\t * @param undoable. By default the action is undoable.\n\t */\n\t toBack: function (items, undoable) {\n\t if (!items) {\n\t items = this._selectedItems.slice();\n\t }\n\n\t var result = this._getDiagramItems(items), indices;\n\t if (!defined(undoable) || undoable) {\n\t indices = indicesOfItems(this.mainLayer, result.visuals);\n\t var unit = new ToBackUnit(this, items, indices);\n\t this.undoRedoService.add(unit);\n\t } else {\n\t this.mainLayer.toBack(result.visuals);\n\t this._fixOrdering(result, false);\n\t }\n\t },\n\t /**\n\t * Bring into view the passed item(s) or rectangle.\n\t * @param items DiagramElement, Array of Items, Rect.\n\t * @param options. align - controls the position of the calculated rectangle relative to the viewport.\n\t * \"Center middle\" will position the items in the center. animate - controls if the pan should be animated.\n\t */\n\t bringIntoView: function (item, options) { // jQuery|Item|Array|Rect\n\t var viewport = this.viewport();\n\t var aligner = new diagram.RectAlign(viewport);\n\t var current, rect, original, newPan;\n\n\t if (viewport.width === 0 || viewport.height === 0) {\n\t return;\n\t }\n\n\t options = deepExtend({animate: false, align: \"center middle\"}, options);\n\t if (options.align == \"none\") {\n\t options.align = \"center middle\";\n\t }\n\n\t if (item instanceof DiagramElement) {\n\t rect = item.bounds(TRANSFORMED);\n\t } else if (isArray(item)) {\n\t rect = this.boundingBox(item);\n\t } else if (item instanceof Rect) {\n\t rect = item.clone();\n\t }\n\n\t original = rect.clone();\n\n\t rect.zoom(this._zoom);\n\n\t if (rect.width > viewport.width || rect.height > viewport.height) {\n\t this._zoom = this._getValidZoom(math.min(viewport.width / original.width, viewport.height / original.height));\n\t rect = original.clone().zoom(this._zoom);\n\t }\n\n\t this._zoomMainLayer();\n\n\t current = rect.clone();\n\t aligner.align(rect, options.align);\n\n\t newPan = rect.topLeft().minus(current.topLeft());\n\t this.pan(newPan.times(-1), options.animate);\n\t },\n\n\t alignShapes: function (direction) {\n\t if (isUndefined(direction)) {\n\t direction = \"Left\";\n\t }\n\t var items = this.select(),\n\t val,\n\t item,\n\t i;\n\n\t if (items.length === 0) {\n\t return;\n\t }\n\n\t switch (direction.toLowerCase()) {\n\t case \"left\":\n\t case \"top\":\n\t val = MAX_VALUE;\n\t break;\n\t case \"right\":\n\t case \"bottom\":\n\t val = MIN_VALUE;\n\t break;\n\t }\n\n\t for (i = 0; i < items.length; i++) {\n\t item = items[i];\n\t if (item instanceof Shape) {\n\t switch (direction.toLowerCase()) {\n\t case \"left\":\n\t val = math.min(val, item.options.x);\n\t break;\n\t case \"top\":\n\t val = math.min(val, item.options.y);\n\t break;\n\t case \"right\":\n\t val = math.max(val, item.options.x);\n\t break;\n\t case \"bottom\":\n\t val = math.max(val, item.options.y);\n\t break;\n\t }\n\t }\n\t }\n\t var undoStates = [];\n\t var shapes = [];\n\t for (i = 0; i < items.length; i++) {\n\t item = items[i];\n\t if (item instanceof Shape) {\n\t shapes.push(item);\n\t undoStates.push(item.bounds());\n\t switch (direction.toLowerCase()) {\n\t case \"left\":\n\t case \"right\":\n\t item.position(new Point(val, item.options.y));\n\t break;\n\t case \"top\":\n\t case \"bottom\":\n\t item.position(new Point(item.options.x, val));\n\t break;\n\t }\n\t }\n\t }\n\t var unit = new diagram.TransformUnit(shapes, undoStates);\n\t this.undoRedoService.add(unit, false);\n\t },\n\n\t zoom: function (zoom, options) {\n\t if (zoom) {\n\t var staticPoint = options ? options.point : new diagram.Point(0, 0);\n\t // var meta = options ? options.meta : 0;\n\t zoom = this._zoom = this._getValidZoom(zoom);\n\n\t if (!isUndefined(staticPoint)) {//Viewpoint vector is constant\n\t staticPoint = new diagram.Point(math.round(staticPoint.x), math.round(staticPoint.y));\n\t var zoomedPoint = staticPoint.times(zoom);\n\t var viewportVector = this.modelToView(staticPoint);\n\t var raw = viewportVector.minus(zoomedPoint);//pan + zoomed point = viewpoint vector\n\t this._storePan(new diagram.Point(math.round(raw.x), math.round(raw.y)));\n\t }\n\n\t if (options) {\n\t options.zoom = zoom;\n\t }\n\n\t this._panTransform();\n\n\t this.canvas.surface.hideTooltip();\n\n\t this._updateAdorners();\n\t }\n\n\t return this._zoom;\n\t },\n\n\t _getPan: function(pan) {\n\t var canvas = this.canvas;\n\t if (!canvas.translate) {\n\t pan = pan.plus(this._pan);\n\t }\n\t return pan;\n\t },\n\n\t pan: function (pan, animate) {\n\t if (pan instanceof Point) {\n\t var that = this;\n\t var scroller = that.scroller;\n\t pan = that._getPan(pan);\n\t pan = pan.times(-1);\n\n\t if (animate) {\n\t scroller.animatedScrollTo(pan.x, pan.y, function() {\n\t that._updateAdorners();\n\t });\n\t } else {\n\t scroller.scrollTo(pan.x, pan.y);\n\t that._updateAdorners();\n\t }\n\t } else {\n\t return this._pan.times(-1);\n\t }\n\t },\n\n\t viewport: function () {\n\t var element = this.element;\n\t var width = element.width();\n\t var height = element.height();\n\n\t if (this.toolBar) {\n\t height -= outerHeight(this.toolBar.element);\n\t }\n\n\t return new Rect(0, 0, width, height);\n\t },\n\t copy: function () {\n\t if (this.options.copy.enabled) {\n\t this._clipboard = [];\n\t this._copyOffset = 1;\n\t for (var i = 0; i < this._selectedItems.length; i++) {\n\t var item = this._selectedItems[i];\n\t this._clipboard.push(item);\n\t }\n\t }\n\t },\n\t cut: function () {\n\t if (this.options.copy.enabled) {\n\t this._clipboard = [];\n\t this._copyOffset = 0;\n\t for (var i = 0; i < this._selectedItems.length; i++) {\n\t var item = this._selectedItems[i];\n\t this._clipboard.push(item);\n\t }\n\t this.remove(this._clipboard, true);\n\t }\n\t },\n\n\t paste: function () {\n\t if (this._clipboard.length > 0) {\n\t var item, copied, i;\n\t var mapping = {};\n\t var elements = splitDiagramElements(this._clipboard);\n\t var connections = elements.connections;\n\t var shapes = elements.shapes;\n\t var offset = {\n\t x: this._copyOffset * this.options.copy.offsetX,\n\t y: this._copyOffset * this.options.copy.offsetY\n\t };\n\t this.deselect();\n\t // first the shapes\n\t for (i = 0; i < shapes.length; i++) {\n\t item = shapes[i];\n\t copied = item.clone();\n\t mapping[item.id] = copied;\n\t copied.position(new Point(item.options.x + offset.x, item.options.y + offset.y));\n\t copied.diagram = this;\n\t copied = this._addShape(copied);\n\t if (copied) {\n\t copied.select();\n\t }\n\t }\n\t // then the connections\n\t for (i = 0; i < connections.length; i++) {\n\t item = connections[i];\n\t copied = this._addConnection(item.clone());\n\t if (copied) {\n\t this._updateCopiedConnection(copied, item, \"source\", mapping, offset);\n\t this._updateCopiedConnection(copied, item, \"target\", mapping, offset);\n\n\t copied.select(true);\n\t copied.updateModel();\n\t }\n\t }\n\n\t this._syncChanges();\n\n\t this._copyOffset += 1;\n\t }\n\t },\n\n\t _updateCopiedConnection: function(connection, sourceConnection, connectorName, mapping, offset) {\n\t var onActivate, inactiveItem, targetShape;\n\t var target = sourceConnection[connectorName]();\n\t var diagram = this;\n\t if (target instanceof Connector && mapping[target.shape.id]) {\n\t targetShape = mapping[target.shape.id];\n\t if (diagram.getShapeById(targetShape.id)) {\n\t connection[connectorName](targetShape.getConnector(target.options.name));\n\t } else {\n\t inactiveItem = diagram._inactiveShapeItems.getByUid(targetShape.dataItem.uid);\n\t if (inactiveItem) {\n\t onActivate = function(item) {\n\t targetShape = diagram._dataMap[item.id];\n\t connection[connectorName](targetShape.getConnector(target.options.name));\n\t connection.updateModel();\n\t };\n\t diagram._deferredConnectionUpdates.push(inactiveItem.onActivate(onActivate));\n\t }\n\t }\n\t } else {\n\t connection[connectorName](new Point(sourceConnection[connectorName + \"Point\"]().x + offset.x, sourceConnection[connectorName + \"Point\"]().y + offset.y));\n\t }\n\t },\n\t /**\n\t * Gets the bounding rectangle of the given items.\n\t * @param items DiagramElement, Array of elements.\n\t * @param origin Boolean. Pass 'true' if you need to get the bounding box of the shapes without their rotation offset.\n\t * @returns {Rect}\n\t */\n\t boundingBox: function (items, origin) {\n\t var rect = Rect.empty(), temp,\n\t di = isDefined(items) ? this._getDiagramItems(items) : {shapes: this.shapes};\n\t if (di.shapes.length > 0) {\n\t var item = di.shapes[0];\n\t rect = item.bounds(ROTATED);\n\t for (var i = 1; i < di.shapes.length; i++) {\n\t item = di.shapes[i];\n\t temp = item.bounds(ROTATED);\n\t if (origin === true) {\n\t temp.x -= item._rotationOffset.x;\n\t temp.y -= item._rotationOffset.y;\n\t }\n\t rect = rect.union(temp);\n\t }\n\t }\n\t return rect;\n\t },\n\n\t _containerOffset: function() {\n\t var containerOffset = this.element.offset();\n\t if (this.toolBar) {\n\t containerOffset.top += outerHeight(this.toolBar.element);\n\t }\n\t return containerOffset;\n\t },\n\n\t documentToView: function(point) {\n\t var containerOffset = this._containerOffset();\n\n\t return new Point(point.x - containerOffset.left, point.y - containerOffset.top);\n\t },\n\t viewToDocument: function(point) {\n\t var containerOffset = this._containerOffset();\n\n\t return new Point(point.x + containerOffset.left, point.y + containerOffset.top);\n\t },\n\t viewToModel: function(point) {\n\t return this._transformWithMatrix(point, this._matrixInvert);\n\t },\n\t modelToView: function(point) {\n\t return this._transformWithMatrix(point, this._matrix);\n\t },\n\t modelToLayer: function(point) {\n\t return this._transformWithMatrix(point, this._layerMatrix);\n\t },\n\t layerToModel: function(point) {\n\t return this._transformWithMatrix(point, this._layerMatrixInvert);\n\t },\n\t documentToModel: function(point) {\n\t var viewPoint = this.documentToView(point);\n\t if (!this.canvas.translate) {\n\t viewPoint.x = viewPoint.x + this.scroller.scrollLeft;\n\t viewPoint.y = viewPoint.y + this.scroller.scrollTop;\n\t }\n\t return this.viewToModel(viewPoint);\n\t },\n\t modelToDocument: function(point) {\n\t return this.viewToDocument(this.modelToView(point));\n\t },\n\t _transformWithMatrix: function(point, matrix) {\n\t var result = point;\n\t if (point instanceof Point) {\n\t if (matrix) {\n\t result = matrix.apply(point);\n\t }\n\t }\n\t else {\n\t var tl = this._transformWithMatrix(point.topLeft(), matrix),\n\t br = this._transformWithMatrix(point.bottomRight(), matrix);\n\t result = Rect.fromPoints(tl, br);\n\t }\n\t return result;\n\t },\n\n\t setDataSource: function(dataSource) {\n\t this.options.dataSource = dataSource;\n\t this._dataSource();\n\t if (this.options.autoBind) {\n\t this.dataSource.fetch();\n\t }\n\t },\n\n\t setConnectionsDataSource: function(dataSource) {\n\t this.options.connectionsDataSource = dataSource;\n\t this._connectionDataSource();\n\t if (this.options.autoBind) {\n\t this.connectionsDataSource.fetch();\n\t }\n\t },\n\n\t /**\n\t * Performs a diagram layout of the given type.\n\t * @param layoutType The layout algorithm to be applied (TreeLayout, LayeredLayout, SpringLayout).\n\t * @param options Layout-specific options.\n\t */\n\t layout: function (options) {\n\t this._layouting = true;\n\t // TODO: raise layout event?\n\t var type;\n\t if(isUndefined(options)) {\n\t options = this.options.layout;\n\t }\n\t if (isUndefined(options) || isUndefined(options.type)) {\n\t type = \"Tree\";\n\t }\n\t else {\n\t type = options.type;\n\t }\n\t var l;\n\t switch (type.toLowerCase()) {\n\t case \"tree\":\n\t l = new diagram.TreeLayout(this);\n\t break;\n\n\t case \"layered\":\n\t l = new diagram.LayeredLayout(this);\n\t break;\n\n\t case \"forcedirected\":\n\t case \"force\":\n\t case \"spring\":\n\t case \"springembedder\":\n\t l = new diagram.SpringLayout(this);\n\t break;\n\t default:\n\t throw \"Layout algorithm '\" + type + \"' is not supported.\";\n\t }\n\t var initialState = new diagram.LayoutState(this);\n\t var finalState = l.layout(options);\n\t if (finalState) {\n\t var unit = new diagram.LayoutUndoUnit(initialState, finalState, options ? options.animate : null);\n\t this.undoRedoService.add(unit);\n\t }\n\t this._layouting = false;\n\t this._redrawConnections();\n\t },\n\t /**\n\t * Gets a shape on the basis of its identifier.\n\t * @param id (string) the identifier of a shape.\n\t * @returns {Shape}\n\t */\n\t getShapeById: function (id) {\n\t var found;\n\t found = Utils.first(this.shapes, function (s) {\n\t return s.visual.id === id;\n\t });\n\t if (found) {\n\t return found;\n\t }\n\t found = Utils.first(this.connections, function (c) {\n\t return c.visual.id === id;\n\t });\n\t return found;\n\t },\n\n\t getShapeByModelId: function (id) {\n\t var shape;\n\t if (this._isEditable) {\n\t shape = this._dataMap[id];\n\t } else {\n\t shape = Utils.first(this.shapes, function(shape) {\n\t return (shape.dataItem || {}).id === id;\n\t });\n\t }\n\t return shape;\n\t },\n\n\t getShapeByModelUid: function(uid) {\n\t var shape;\n\t if (this._isEditable) {\n\t shape = Utils.first(this.shapes, function(shape) {\n\t return (shape.dataItem || {}).uid === uid;\n\t });\n\t } else {\n\t shape = this._dataMap[uid];\n\t }\n\t return shape;\n\t },\n\n\t getConnectionByModelId: function(id) {\n\t var connection;\n\t if (this.connectionsDataSource) {\n\t connection = Utils.first(this.connections, function(connection) {\n\t return (connection.dataItem || {}).id === id;\n\t });\n\t }\n\t return connection;\n\t },\n\n\t getConnectionByModelUid: function(uid) {\n\t var connection;\n\t if (this.connectionsDataSource) {\n\t connection = this._connectionsDataMap[uid];\n\t }\n\t return connection;\n\t },\n\n\t _extendLayoutOptions: function(options) {\n\t if(options.layout) {\n\t options.layout = deepExtend({}, diagram.LayoutBase.fn.defaultOptions || {}, options.layout);\n\t }\n\t },\n\n\t _selectionChanged: function (selected, deselected) {\n\t if (selected.length || deselected.length) {\n\t this.trigger(SELECT, { selected: selected, deselected: deselected });\n\t }\n\t },\n\t _getValidZoom: function (zoom) {\n\t return math.min(math.max(zoom, this.options.zoomMin), this.options.zoomMax);\n\t },\n\t _panTransform: function (pos) {\n\t var diagram = this,\n\t pan = pos || diagram._pan;\n\n\t if (diagram.canvas.translate) {\n\t diagram.scroller.scrollTo(pan.x, pan.y);\n\t diagram._zoomMainLayer();\n\t } else {\n\t diagram._storePan(pan);\n\t diagram._transformMainLayer();\n\t }\n\t },\n\n\t _finishPan: function () {\n\t this.trigger(PAN, {total: this._pan, delta: Number.NaN});\n\t },\n\t _storePan: function (pan) {\n\t this._pan = pan;\n\t this._storeViewMatrix();\n\t },\n\t _zoomMainLayer: function () {\n\t var zoom = this._zoom;\n\n\t var transform = new CompositeTransform(0, 0, zoom, zoom);\n\t transform.render(this.mainLayer);\n\t this._storeLayerMatrix(transform);\n\t this._storeViewMatrix();\n\t },\n\t _transformMainLayer: function () {\n\t var pan = this._pan,\n\t zoom = this._zoom;\n\n\t var transform = new CompositeTransform(pan.x, pan.y, zoom, zoom);\n\t transform.render(this.mainLayer);\n\t this._storeLayerMatrix(transform);\n\t this._storeViewMatrix();\n\t },\n\t _storeLayerMatrix: function(canvasTransform) {\n\t this._layerMatrix = canvasTransform.toMatrix();\n\t this._layerMatrixInvert = canvasTransform.invert().toMatrix();\n\t },\n\t _storeViewMatrix: function() {\n\t var pan = this._pan,\n\t zoom = this._zoom;\n\n\t var transform = new CompositeTransform(pan.x, pan.y, zoom, zoom);\n\t this._matrix = transform.toMatrix();\n\t this._matrixInvert = transform.invert().toMatrix();\n\t },\n\t _toIndex: function (items, indices) {\n\t var result = this._getDiagramItems(items);\n\t this.mainLayer.toIndex(result.visuals, indices);\n\t this._fixOrdering(result, false);\n\t },\n\t _fixOrdering: function (result, toFront) {\n\t var shapePos = toFront ? this.shapes.length - 1 : 0,\n\t conPos = toFront ? this.connections.length - 1 : 0,\n\t i, item;\n\t for (i = 0; i < result.shapes.length; i++) {\n\t item = result.shapes[i];\n\t Utils.remove(this.shapes, item);\n\t Utils.insert(this.shapes, item, shapePos);\n\t }\n\t for (i = 0; i < result.cons.length; i++) {\n\t item = result.cons[i];\n\t Utils.remove(this.connections, item);\n\t Utils.insert(this.connections, item, conPos);\n\t }\n\t },\n\t _getDiagramItems: function (items) {\n\t var i, result = {}, args = items;\n\t result.visuals = [];\n\t result.shapes = [];\n\t result.cons = [];\n\n\t if (!items) {\n\t args = this._selectedItems.slice();\n\t } else if (!isArray(items)) {\n\t args = [items];\n\t }\n\n\t for (i = 0; i < args.length; i++) {\n\t var item = args[i];\n\t if (item instanceof Shape) {\n\t result.shapes.push(item);\n\t result.visuals.push(item.visual);\n\t } else if (item instanceof Connection) {\n\t result.cons.push(item);\n\t result.visuals.push(item.visual);\n\t }\n\t }\n\n\t return result;\n\t },\n\n\t _removeItem: function (item, undoable, removedConnections) {\n\t item.select(false);\n\t if (item instanceof Shape) {\n\t this._removeShapeDataItem(item);\n\t this._removeShape(item, undoable, removedConnections);\n\t } else if (item instanceof Connection) {\n\t this._removeConnectionDataItem(item);\n\t this._removeConnection(item, undoable);\n\t }\n\n\t this.mainLayer.remove(item.visual);\n\t },\n\n\t _removeShape: function (shape, undoable, removedConnections) {\n\t var i, connection, connector,\n\t sources = [], targets = [];\n\t this.toolService._removeHover();\n\n\t if (undoable) {\n\t this.undoRedoService.addCompositeItem(new DeleteShapeUnit(shape));\n\t }\n\t Utils.remove(this.shapes, shape);\n\t this._shapesQuadTree.remove(shape);\n\n\t for (i = 0; i < shape.connectors.length; i++) {\n\t connector = shape.connectors[i];\n\t for (var j = 0; j < connector.connections.length; j++) {\n\t connection = connector.connections[j];\n\t if (!removedConnections || !dataviz.inArray(connection, removedConnections)) {\n\t if (connection.sourceConnector == connector) {\n\t sources.push(connection);\n\t } else if (connection.targetConnector == connector) {\n\t targets.push(connection);\n\t }\n\t }\n\t }\n\t }\n\n\t for (i = 0; i < sources.length; i++) {\n\t sources[i].source(null, undoable);\n\t sources[i].updateModel();\n\t }\n\t for (i = 0; i < targets.length; i++) {\n\t targets[i].target(null, undoable);\n\t targets[i].updateModel();\n\t }\n\t },\n\n\t _removeConnection: function (connection, undoable) {\n\t if (connection.sourceConnector) {\n\t Utils.remove(connection.sourceConnector.connections, connection);\n\t }\n\t if (connection.targetConnector) {\n\t Utils.remove(connection.targetConnector.connections, connection);\n\t }\n\t if (undoable) {\n\t this.undoRedoService.addCompositeItem(new DeleteConnectionUnit(connection));\n\t }\n\n\t Utils.remove(this.connections, connection);\n\t },\n\n\t _removeDataItems: function(items, recursive) {\n\t var item, children, shape, idx;\n\t items = isArray(items) ? items : [items];\n\n\t while (items.length) {\n\t item = items.shift();\n\t shape = this._dataMap[item.uid];\n\t if (shape) {\n\t this._removeShapeConnections(shape);\n\t this._removeItem(shape, false);\n\t delete this._dataMap[item.uid];\n\t if (recursive && item.hasChildren && item.loaded()) {\n\t children = item.children.data();\n\t for (idx = 0; idx < children.length; idx++) {\n\t items.push(children[idx]);\n\t }\n\t }\n\t }\n\t }\n\t },\n\n\t _removeShapeConnections: function(shape) {\n\t var connections = shape.connections();\n\t var idx;\n\n\t if (connections) {\n\t for (idx = 0; idx < connections.length; idx++) {\n\t this._removeItem(connections[idx], false);\n\t }\n\t }\n\t },\n\n\t _addDataItem: function(dataItem, undoable) {\n\t if (!defined(dataItem)) {\n\t return;\n\t }\n\n\t var shape = this._dataMap[dataItem.id];\n\t if (shape) {\n\t return shape;\n\t }\n\n\t var options = deepExtend({}, this.options.shapeDefaults);\n\t options.dataItem = dataItem;\n\t shape = new Shape(options, this);\n\t this.addShape(shape, undoable !== false);\n\t this._dataMap[dataItem.id] = shape;\n\t return shape;\n\t },\n\n\t _addDataItemByUid: function(dataItem) {\n\t if (!defined(dataItem)) {\n\t return;\n\t }\n\n\t var shape = this._dataMap[dataItem.uid];\n\t if (shape) {\n\t return shape;\n\t }\n\n\t var options = deepExtend({}, this.options.shapeDefaults);\n\t options.dataItem = dataItem;\n\t shape = new Shape(options, this);\n\t this.addShape(shape);\n\t this._dataMap[dataItem.uid] = shape;\n\t return shape;\n\t },\n\n\t _addDataItems: function(items, parent) {\n\t var item, idx, shape, parentShape, connection;\n\t for (idx = 0; idx < items.length; idx++) {\n\t item = items[idx];\n\t shape = this._addDataItemByUid(item);\n\t parentShape = this._addDataItemByUid(parent);\n\t if (parentShape && !this.connected(parentShape, shape)) { // check if connected to not duplicate connections.\n\t connection = this.connect(parentShape, shape);\n\t }\n\t }\n\t },\n\n\t _refreshSource: function (e) {\n\t var that = this,\n\t node = e.node,\n\t action = e.action,\n\t items = e.items,\n\t options = that.options,\n\t idx,\n\t dataBound;\n\n\t if (e.field) {\n\t for (idx = 0; idx < items.length; idx++) {\n\t if (this._dataMap[items[idx].uid]) {\n\t this._dataMap[items[idx].uid].redrawVisual();\n\t }\n\t }\n\t return;\n\t }\n\n\t if (action == \"remove\") {\n\t this._removeDataItems(e.items, true);\n\t } else {\n\n\t if ((!action || action === \"itemloaded\") && !this._bindingRoots) {\n\t this._bindingRoots = true;\n\t dataBound = true;\n\t }\n\n\t if (!action && !node) {\n\t that.clear();\n\t }\n\n\t this._addDataItems(items, node);\n\n\t for (idx = 0; idx < items.length; idx++) {\n\t items[idx].load();\n\t }\n\t }\n\n\t if (options.layout && (dataBound || action == \"remove\" || action == \"add\")) {\n\t that.layout(options.layout);\n\t }\n\n\t if (dataBound) {\n\t this.trigger(\"dataBound\");\n\t this._bindingRoots = false;\n\t }\n\t },\n\n\t _addItem: function (item) {\n\t if (item instanceof Shape) {\n\t this.addShape(item);\n\t } else if (item instanceof Connection) {\n\t this.addConnection(item);\n\t }\n\t },\n\n\t _createToolBar: function(preventClosing) {\n\t var diagram = this.toolService.diagram;\n\n\t if (!this.singleToolBar && diagram.select().length === 1) {\n\t var element = diagram.select()[0];\n\t if (element && element.options.editable !== false) {\n\t var editable = element.options.editable;\n\t var tools = editable.tools;\n\t if (this._isEditable && tools.length === 0) {\n\t if (element instanceof Shape) {\n\t tools = [\"edit\", \"rotateClockwise\", \"rotateAnticlockwise\"];\n\t } else if (element instanceof Connection) {\n\t tools = [\"edit\"];\n\t }\n\n\t if (editable && editable.remove !== false) {\n\t tools.push(\"delete\");\n\t }\n\t }\n\n\t if (tools && tools.length) {\n\t var padding = 20;\n\t var point;\n\t this.singleToolBar = new DiagramToolBar(diagram, {\n\t tools: tools,\n\t click: proxy(this._toolBarClick, this),\n\t modal: true,\n\t popupZIndex: parseInt(diagram.element.closest(\".k-window\").css(\"zIndex\"), 10) + 10\n\t });\n\t var popupWidth = outerWidth(this.singleToolBar._popup.element);\n\t var popupHeight = outerHeight(this.singleToolBar._popup.element);\n\t if (element instanceof Shape) {\n\t var shapeBounds = this.modelToView(element.bounds(ROTATED));\n\t point = new Point(shapeBounds.x, shapeBounds.y).minus(new Point(\n\t (popupWidth - shapeBounds.width) / 2,\n\t popupHeight + padding));\n\t } else if (element instanceof Connection) {\n\t var connectionBounds = this.modelToView(element.bounds());\n\n\t point = new Point(connectionBounds.x, connectionBounds.y)\n\t .minus(new Point(\n\t (popupWidth - connectionBounds.width - 20) / 2,\n\t popupHeight + padding\n\t ));\n\t }\n\n\t if (point) {\n\t if (!this.canvas.translate) {\n\t point = point.minus(new Point(this.scroller.scrollLeft, this.scroller.scrollTop));\n\t }\n\t point = this.viewToDocument(point);\n\t point = new Point(math.max(point.x, 0), math.max(point.y, 0));\n\t this.singleToolBar.showAt(point);\n\t if (preventClosing) {\n\t this.singleToolBar._popup.one(\"close\", preventDefault);\n\t }\n\t } else {\n\t this._destroyToolBar();\n\t }\n\t }\n\t }\n\t }\n\t },\n\n\t _toolBarClick: function(e) {\n\t this.trigger(\"toolBarClick\", e);\n\t this._destroyToolBar();\n\t },\n\n\t _normalizePointZoom: function (point) {\n\t return point.times(1 / this.zoom());\n\t },\n\n\t _initialize: function () {\n\t this.shapes = [];\n\t this._selectedItems = [];\n\t this.connections = [];\n\t this._dataMap = {};\n\t this._connectionsDataMap = {};\n\t this._inactiveShapeItems = new InactiveItemsCollection();\n\t this._deferredConnectionUpdates = [];\n\t this.undoRedoService = new UndoRedoService({\n\t undone: this._syncHandler,\n\t redone: this._syncHandler\n\t });\n\t this.id = diagram.randomId();\n\t },\n\n\t _fetchFreshData: function () {\n\t var that = this;\n\t that._dataSource();\n\n\t if (that._isEditable) {\n\t that._connectionDataSource();\n\t }\n\n\t if (that.options.autoBind) {\n\t if (that._isEditable) {\n\t this._loadingShapes = true;\n\t this._loadingConnections = true;\n\t that.dataSource.fetch();\n\t that.connectionsDataSource.fetch();\n\t } else {\n\t that.dataSource.fetch();\n\t }\n\t }\n\t },\n\n\t _dataSource: function() {\n\t if (defined(this.options.connectionsDataSource)) {\n\t this._isEditable = true;\n\t var dsOptions = this.options.dataSource || {};\n\t var ds = isArray(dsOptions) ? { data: dsOptions } : dsOptions;\n\n\t if (this.dataSource && this._shapesRefreshHandler) {\n\t this.dataSource\n\t .unbind(\"change\", this._shapesRefreshHandler)\n\t .unbind(\"requestStart\", this._shapesRequestStartHandler)\n\t .unbind(\"error\", this._shapesErrorHandler);\n\t } else {\n\t this._shapesRefreshHandler = proxy(this._refreshShapes, this);\n\t this._shapesRequestStartHandler = proxy(this._shapesRequestStart, this);\n\t this._shapesErrorHandler = proxy(this._error, this);\n\t }\n\n\t this.dataSource = kendo.data.DataSource.create(ds)\n\t .bind(\"change\", this._shapesRefreshHandler)\n\t .bind(\"requestStart\", this._shapesRequestStartHandler)\n\t .bind(\"error\", this._shapesErrorHandler);\n\t } else {\n\t this._treeDataSource();\n\t this._isEditable = false;\n\t }\n\t },\n\n\t _connectionDataSource: function() {\n\t var dsOptions = this.options.connectionsDataSource;\n\t if (dsOptions) {\n\t var ds = isArray(dsOptions) ? { data: dsOptions } : dsOptions;\n\n\t if (this.connectionsDataSource && this._connectionsRefreshHandler) {\n\t this.connectionsDataSource\n\t .unbind(\"change\", this._connectionsRefreshHandler)\n\t .unbind(\"requestStart\", this._connectionsRequestStartHandler)\n\t .unbind(\"error\", this._connectionsErrorHandler);\n\t } else {\n\t this._connectionsRefreshHandler = proxy(this._refreshConnections, this);\n\t this._connectionsRequestStartHandler = proxy(this._connectionsRequestStart, this);\n\t this._connectionsErrorHandler = proxy(this._connectionsError, this);\n\t }\n\n\t this.connectionsDataSource = kendo.data.DataSource.create(ds)\n\t .bind(\"change\", this._connectionsRefreshHandler)\n\t .bind(\"requestStart\", this._connectionsRequestStartHandler)\n\t .bind(\"error\", this._connectionsErrorHandler);\n\t }\n\t },\n\n\t _shapesRequestStart: function(e) {\n\t if (e.type == \"read\") {\n\t this._loadingShapes = true;\n\t }\n\t },\n\n\t _connectionsRequestStart: function(e) {\n\t if (e.type == \"read\") {\n\t this._loadingConnections = true;\n\t }\n\t },\n\n\t _error: function () {\n\t this._loadingShapes = false;\n\t },\n\n\t _connectionsError: function() {\n\t this._loadingConnections = false;\n\t },\n\n\t _refreshShapes: function(e) {\n\t if (e.action === \"remove\") {\n\t if (this._shouldRefresh()) {\n\t this._removeShapes(e.items);\n\t }\n\t } else if (e.action === \"itemchange\") {\n\t if (this._shouldRefresh()) {\n\t this._updateShapes(e.items, e.field);\n\t }\n\t } else if (e.action === \"add\") {\n\t this._inactiveShapeItems.add(e.items);\n\t } else if (e.action === \"sync\") {\n\t this._syncShapes(e.items);\n\t } else {\n\t this.refresh();\n\t }\n\t },\n\n\t _shouldRefresh: function() {\n\t return !this._suspended;\n\t },\n\n\t _suspendModelRefresh: function() {\n\t this._suspended = (this._suspended || 0) + 1;\n\t },\n\n\t _resumeModelRefresh: function() {\n\t this._suspended = math.max((this._suspended || 0) - 1, 0);\n\t },\n\n\t refresh: function() {\n\t this._loadingShapes = false;\n\t if (!this._loadingConnections) {\n\t this._rebindShapesAndConnections();\n\t }\n\t },\n\n\t _rebindShapesAndConnections: function() {\n\t this.clear();\n\t this._addShapes(this.dataSource.view());\n\t if (this.connectionsDataSource) {\n\t this._addConnections(this.connectionsDataSource.view(), false);\n\t }\n\n\t if (this.options.layout) {\n\t this.layout(this.options.layout);\n\t } else {\n\t this._redrawConnections();\n\t }\n\t this.trigger(\"dataBound\");\n\t },\n\n\t refreshConnections: function() {\n\t this._loadingConnections = false;\n\t if (!this._loadingShapes) {\n\t this._rebindShapesAndConnections();\n\t }\n\t },\n\n\t _redrawConnections: function() {\n\t var connections = this.connections;\n\t for (var idx = 0; idx < connections.length; idx++) {\n\t connections[idx].refresh();\n\t }\n\t },\n\n\t _removeShapes: function(items) {\n\t var dataMap = this._dataMap;\n\t var item, i;\n\t for (i = 0; i < items.length; i++) {\n\t item = items[i];\n\t if (dataMap[item.id]) {\n\t this.remove(dataMap[item.id], false);\n\t dataMap[item.id] = null;\n\t }\n\t }\n\t },\n\n\t _syncShapes: function() {\n\t var diagram = this;\n\t var inactiveItems = diagram._inactiveShapeItems;\n\t inactiveItems.forEach(function(inactiveItem) {\n\t var dataItem = inactiveItem.dataItem;\n\t var shape = inactiveItem.element;\n\t if (!dataItem.isNew()) {\n\t if (shape) {\n\t shape._setOptionsFromModel();\n\t diagram.addShape(shape, inactiveItem.undoable);\n\t diagram._dataMap[dataItem.id] = shape;\n\t } else {\n\t diagram._addDataItem(dataItem);\n\t }\n\t inactiveItem.activate();\n\t inactiveItems.remove(dataItem);\n\t }\n\t });\n\t },\n\n\t _updateShapes: function(items, field) {\n\t for (var i = 0; i < items.length; i++) {\n\t var dataItem = items[i];\n\n\t var shape = this._dataMap[dataItem.id];\n\t if (shape) {\n\t shape.updateOptionsFromModel(dataItem, field);\n\t }\n\t }\n\t },\n\n\t _addShapes: function(dataItems) {\n\t for (var i = 0; i < dataItems.length; i++) {\n\t this._addDataItem(dataItems[i], false);\n\t }\n\t },\n\n\t _refreshConnections: function(e) {\n\t if (e.action === \"remove\") {\n\t if (this._shouldRefresh()) {\n\t this._removeConnections(e.items);\n\t }\n\t } else if (e.action === \"add\") {\n\t this._addConnections(e.items);\n\t } else if (e.action === \"sync\") {\n\t //TO DO: include logic to update the connections with different values returned from the server.\n\t } else if (e.action === \"itemchange\") {\n\t if (this._shouldRefresh()) {\n\t this._updateConnections(e.items);\n\t }\n\t } else {\n\t this.refreshConnections();\n\t }\n\t },\n\n\t _removeConnections: function(items) {\n\t for (var i = 0; i < items.length; i++) {\n\t this.remove(this._connectionsDataMap[items[i].uid], false);\n\t this._connectionsDataMap[items[i].uid] = null;\n\t }\n\t },\n\n\t _updateConnections: function(items) {\n\t for (var i = 0; i < items.length; i++) {\n\t var dataItem = items[i];\n\n\t var connection = this._connectionsDataMap[dataItem.uid];\n\t connection.updateOptionsFromModel(dataItem);\n\t }\n\t },\n\n\t _addConnections: function(connections, undoable) {\n\t var length = connections.length;\n\n\t for (var i = 0; i < length; i++) {\n\t var dataItem = connections[i];\n\t this._addConnectionDataItem(dataItem, undoable);\n\t }\n\t },\n\n\t _addConnectionDataItem: function(dataItem, undoable) {\n\t if (!this._connectionsDataMap[dataItem.uid]) {\n\t var from = this._validateConnector(dataItem.from);\n\t if (!defined(from) || from === null) {\n\t from = new Point(dataItem.fromX, dataItem.fromY);\n\t }\n\n\t var to = this._validateConnector(dataItem.to);\n\t if (!defined(to) || to === null) {\n\t to = new Point(dataItem.toX, dataItem.toY);\n\t }\n\n\t if (defined(from) && defined(to)) {\n\t var options = deepExtend({}, this.options.connectionDefaults);\n\t options.dataItem = dataItem;\n\t var connection = new Connection(from, to, options);\n\n\t this._connectionsDataMap[dataItem.uid] = connection;\n\t this.addConnection(connection, undoable);\n\t }\n\t }\n\t },\n\n\t _validateConnector: function(value) {\n\t var connector;\n\n\t if (defined(value) && value !== null) {\n\t connector = this._dataMap[value];\n\t }\n\n\t return connector;\n\t },\n\n\t _treeDataSource: function () {\n\t var that = this,\n\t options = that.options,\n\t dataSource = options.dataSource;\n\n\t dataSource = isArray(dataSource) ? { data: dataSource } : dataSource;\n\n\t if (dataSource instanceof kendo.data.DataSource && !(dataSource instanceof kendo.data.HierarchicalDataSource)) {\n\t throw new Error(\"Incorrect DataSource type. If a single dataSource instance is set to the diagram then it should be a HierarchicalDataSource. You should set only the options instead of an instance or a HierarchicalDataSource instance or supply connectionsDataSource as well.\");\n\t }\n\n\t if (!dataSource.fields) {\n\t dataSource.fields = [\n\t { field: \"text\" },\n\t { field: \"url\" },\n\t { field: \"spriteCssClass\" },\n\t { field: \"imageUrl\" }\n\t ];\n\t }\n\t if (that.dataSource && that._refreshHandler) {\n\t that._unbindDataSource();\n\t }\n\n\t that._refreshHandler = proxy(that._refreshSource, that);\n\t that._errorHandler = proxy(that._error, that);\n\n\t that.dataSource = HierarchicalDataSource.create(dataSource)\n\t .bind(CHANGE, that._refreshHandler)\n\t .bind(ERROR, that._errorHandler);\n\t },\n\n\t _unbindDataSource: function () {\n\t var that = this;\n\n\t that.dataSource.unbind(CHANGE, that._refreshHandler).unbind(ERROR, that._errorHandler);\n\t },\n\n\t _adorn: function (adorner, isActive) {\n\t if (isActive !== undefined && adorner) {\n\t if (isActive) {\n\t this._adorners.push(adorner);\n\t this.adornerLayer.append(adorner.visual);\n\t }\n\t else {\n\t Utils.remove(this._adorners, adorner);\n\t this.adornerLayer.remove(adorner.visual);\n\t }\n\t }\n\t },\n\n\t _showConnectors: function (shape, value) {\n\t if (value) {\n\t this._connectorsAdorner.show(shape);\n\t } else {\n\t this._connectorsAdorner.destroy();\n\t }\n\t },\n\n\t _updateAdorners: function() {\n\t var adorners = this._adorners;\n\n\t for(var i = 0; i < adorners.length; i++) {\n\t var adorner = adorners[i];\n\n\t if (adorner.refreshBounds) {\n\t adorner.refreshBounds();\n\t }\n\t adorner.refresh();\n\t }\n\t },\n\n\t _refresh: function () {\n\t for (var i = 0; i < this.connections.length; i++) {\n\t this.connections[i].refresh();\n\t }\n\t },\n\n\t _destroyToolBar: function() {\n\t if (this.singleToolBar) {\n\t this.singleToolBar.hide();\n\t this.singleToolBar.destroy();\n\t this.singleToolBar = null;\n\t }\n\t },\n\n\t _destroyGlobalToolBar: function() {\n\t if (this.toolBar) {\n\t this.toolBar.hide();\n\t this.toolBar.destroy();\n\t this.toolBar = null;\n\t }\n\t },\n\n\t exportDOMVisual: function() {\n\t var viewBox = this.canvas._viewBox;\n\t var scrollOffset = geom.transform()\n\t .translate(-viewBox.x, -viewBox.y);\n\n\t var viewRect = new geom.Rect([0, 0], [viewBox.width, viewBox.height]);\n\t var clipPath = draw.Path.fromRect(viewRect);\n\t var wrap = new draw.Group({ transform: scrollOffset });\n\t var clipWrap = new draw.Group({ clip: clipPath });\n\t var root = this.canvas.drawingElement.children[0];\n\n\t clipWrap.append(wrap);\n\n\t // Don't reparent the root\n\t wrap.children.push(root);\n\n\t return clipWrap;\n\t },\n\n\t exportVisual: function() {\n\t var scale = geom.transform().scale(1 / this._zoom);\n\t var wrap = new draw.Group({\n\t transform: scale\n\t });\n\n\t var root = this.mainLayer.drawingElement;\n\t wrap.children.push(root);\n\n\t return wrap;\n\t },\n\n\t _syncChanges: function() {\n\t this._syncShapeChanges();\n\t this._syncConnectionChanges();\n\t },\n\n\t _syncShapeChanges: function() {\n\t if (this.dataSource && this._isEditable) {\n\t this.dataSource.sync();\n\t }\n\t },\n\n\t _syncConnectionChanges: function() {\n\t var that = this;\n\t if (that.connectionsDataSource && that._isEditable) {\n\t $.when.apply($, that._deferredConnectionUpdates).then(function() {\n\t that.connectionsDataSource.sync();\n\t });\n\t that.deferredConnectionUpdates = [];\n\t }\n\t }\n\t });\n\n\t dataviz.ExportMixin.extend(Diagram.fn, true);\n\n\t if (kendo.PDFMixin) {\n\t kendo.PDFMixin.extend(Diagram.fn);\n\t }\n\n\t function filterShapeDataItem(dataItem) {\n\t var result = {};\n\n\t dataItem = dataItem || {};\n\n\t if (defined(dataItem.text) && dataItem.text !== null) {\n\t result.text = dataItem.text;\n\t }\n\n\t if (defined(dataItem.x) && dataItem.x !== null) {\n\t result.x = dataItem.x;\n\t }\n\n\t if (defined(dataItem.y) && dataItem.y !== null) {\n\t result.y = dataItem.y;\n\t }\n\n\t if (defined(dataItem.width) && dataItem.width !== null) {\n\t result.width = dataItem.width;\n\t }\n\n\t if (defined(dataItem.height) && dataItem.height !== null) {\n\t result.height = dataItem.height;\n\t }\n\n\t if (defined(dataItem.type) && dataItem.type !== null) {\n\t result.type = dataItem.type;\n\t }\n\n\t return result;\n\t }\n\n\t function filterConnectionDataItem(dataItem) {\n\t var result = {};\n\n\t dataItem = dataItem || {};\n\n\t if (defined(dataItem.text) && dataItem.text !== null) {\n\t result.content = dataItem.text;\n\t }\n\n\t if (defined(dataItem.type) && dataItem.type !== null) {\n\t result.type = dataItem.type;\n\t }\n\n\t if (defined(dataItem.from) && dataItem.from !== null) {\n\t result.from = dataItem.from;\n\t }\n\n\t if (defined(dataItem.fromConnector) && dataItem.fromConnector !== null) {\n\t result.fromConnector = dataItem.fromConnector;\n\t }\n\n\t if (defined(dataItem.fromX) && dataItem.fromX !== null) {\n\t result.fromX = dataItem.fromX;\n\t }\n\n\t if (defined(dataItem.fromY) && dataItem.fromY !== null) {\n\t result.fromY = dataItem.fromY;\n\t }\n\n\t if (defined(dataItem.to) && dataItem.to !== null) {\n\t result.to = dataItem.to;\n\t }\n\n\t if (defined(dataItem.toConnector) && dataItem.toConnector !== null) {\n\t result.toConnector = dataItem.toConnector;\n\t }\n\n\t if (defined(dataItem.toX) && dataItem.toX !== null) {\n\t result.toX = dataItem.toX;\n\t }\n\n\t if (defined(dataItem.toY) && dataItem.toY !== null) {\n\t result.toY = dataItem.toY;\n\t }\n\n\t return result;\n\t }\n\n\n\t var DiagramToolBar = kendo.Observable.extend({\n\t init: function(diagram, options) {\n\t kendo.Observable.fn.init.call(this);\n\t this.diagram = diagram;\n\t this.options = deepExtend({}, this.options, options);\n\t this._tools = [];\n\t this.createToolBar();\n\t this.createTools();\n\t this.appendTools();\n\n\t if (this.options.modal) {\n\t this.createPopup();\n\t }\n\n\t this.bind(this.events, options);\n\t },\n\n\t events: [\"click\"],\n\n\t createPopup: function() {\n\t this.container = $(\"\").append(this.element);\n\t this._popup = this.container.kendoPopup({}).getKendoPopup();\n\t },\n\n\t appendTools: function() {\n\t for (var i = 0; i < this._tools.length; i++) {\n\t var tool = this._tools[i];\n\t if (tool.buttons && tool.buttons.length || !defined(tool.buttons)) {\n\t this._toolBar.add(tool);\n\t }\n\t }\n\t },\n\n\t createToolBar: function() {\n\t this.element = $(\"\");\n\t this._toolBar = this.element\n\t .kendoToolBar({\n\t click: proxy(this.click, this),\n\t resizable: false\n\t }).getKendoToolBar();\n\n\t this.element.css(\"border\", \"none\");\n\t },\n\n\t createTools: function() {\n\t for (var i = 0; i < this.options.tools.length; i++) {\n\t this.createTool(this.options.tools[i]);\n\t }\n\t },\n\n\t createTool: function(tool) {\n\t if (!isPlainObject(tool)) {\n\t tool = {\n\t name: tool\n\t };\n\t }\n\t var toolName = tool.name + \"Tool\";\n\t if (this[toolName]) {\n\t this[toolName](tool);\n\t } else {\n\t this._tools.push(deepExtend({}, tool, {\n\t attributes: this._setAttributes({action: tool.name})\n\t }));\n\t }\n\t },\n\n\t showAt: function(point) {\n\t var popupZIndex = parseInt(this.options.popupZIndex, 10);\n\n\t if (this._popup) {\n\t this._popup.open(point.x, point.y);\n\n\t if (popupZIndex) {\n\t this._popup.wrapper.css(\"zIndex\", popupZIndex);\n\t }\n\t }\n\t },\n\n\t hide: function() {\n\t if (this._popup) {\n\t this._popup.close();\n\t }\n\t },\n\n\t newGroup: function() {\n\t return {\n\t type: \"buttonGroup\",\n\t buttons: []\n\t };\n\t },\n\n\t editTool: function() {\n\t this._tools.push({\n\t icon: \"edit\",\n\t showText: \"overflow\",\n\t type: \"button\",\n\t text: \"Edit\",\n\t attributes: this._setAttributes({ action: \"edit\" })\n\t });\n\t },\n\n\t deleteTool: function() {\n\t this._tools.push({\n\t icon: \"close\",\n\t showText: \"overflow\",\n\t type: \"button\",\n\t text: \"Delete\",\n\t attributes: this._setAttributes({ action: \"delete\" })\n\t });\n\t },\n\n\t rotateAnticlockwiseTool: function(options) {\n\t this._appendGroup(\"rotate\");\n\t this._rotateGroup.buttons.push({\n\t icon: \"rotate-left\",\n\t showText: \"overflow\",\n\t text: \"RotateAnticlockwise\",\n\t group: \"rotate\",\n\t attributes: this._setAttributes({ action: \"rotateAnticlockwise\", step: options.step })\n\t });\n\t },\n\n\t rotateClockwiseTool: function(options) {\n\t this._appendGroup(\"rotate\");\n\t this._rotateGroup.buttons.push({\n\t icon: \"rotate-right\",\n\t attributes: this._setAttributes({ action: \"rotateClockwise\", step: options.step }),\n\t showText: \"overflow\",\n\t text: \"RotateClockwise\",\n\t group: \"rotate\"\n\t });\n\t },\n\n\t createShapeTool: function() {\n\t this._appendGroup(\"create\");\n\t this._createGroup.buttons.push({\n\t icon: \"shape\",\n\t showText: \"overflow\",\n\t text: \"CreateShape\",\n\t group: \"create\",\n\t attributes: this._setAttributes({ action: \"createShape\" })\n\t });\n\t },\n\n\t createConnectionTool: function() {\n\t this._appendGroup(\"create\");\n\t this._createGroup.buttons.push({\n\t icon: \"connector\",\n\t showText: \"overflow\",\n\t text: \"CreateConnection\",\n\t group: \"create\",\n\t attributes: this._setAttributes({ action: \"createConnection\" })\n\t });\n\t },\n\n\t undoTool: function() {\n\t this._appendGroup(\"history\");\n\t this._historyGroup.buttons.push({\n\t icon: \"undo\",\n\t showText: \"overflow\",\n\t text: \"Undo\",\n\t group: \"history\",\n\t attributes: this._setAttributes({ action: \"undo\" })\n\t });\n\t },\n\n\t redoTool: function() {\n\t this._appendGroup(\"history\");\n\t this._historyGroup.buttons.push({\n\t icon: \"redo\",\n\t showText: \"overflow\",\n\t text: \"Redo\",\n\t group: \"history\",\n\t attributes: this._setAttributes({ action: \"redo\" })\n\t });\n\t },\n\n\t _appendGroup: function(name) {\n\t var prop = \"_\" + name + \"Group\";\n\t if (!this[prop]) {\n\t this[prop] = this.newGroup();\n\t this._tools.push(this[prop]);\n\t }\n\t },\n\n\t _setAttributes: function(attributes) {\n\t var attr = {};\n\n\t if (attributes.action) {\n\t attr[kendo.attr(\"action\")] = attributes.action;\n\t }\n\n\t if (attributes.step) {\n\t attr[kendo.attr(\"step\")] = attributes.step;\n\t }\n\n\t return attr;\n\t },\n\n\t _getAttributes: function(element) {\n\t var attr = {};\n\n\t var action = element.attr(kendo.attr(\"action\"));\n\t if (action) {\n\t attr.action = action;\n\t }\n\n\t var step = element.attr(kendo.attr(\"step\"));\n\t if (step) {\n\t attr.step = step;\n\t }\n\n\t return attr;\n\t },\n\n\t click: function(e) {\n\t var attributes = this._getAttributes($(e.target));\n\t var action = attributes.action;\n\n\t if (action && this[action]) {\n\t this[action](attributes);\n\t }\n\n\t this.trigger(\"click\", this.eventData(action, e.target));\n\t },\n\n\t eventData: function(action, target) {\n\t var elements = this.selectedElements(),\n\t length = elements.length,\n\t shapes = [], connections = [], element;\n\n\t for (var idx = 0; idx < length; idx++) {\n\t element = elements[idx];\n\t if (element instanceof Shape) {\n\t shapes.push(element);\n\t } else {\n\t connections.push(element);\n\t }\n\t }\n\n\t return {\n\t shapes: shapes,\n\t connections: connections,\n\t action: action,\n\t target: target\n\t };\n\t },\n\n\t \"delete\": function() {\n\t var diagram = this.diagram;\n\t var toRemove = diagram._triggerRemove(this.selectedElements());\n\t if (toRemove.length) {\n\t this.diagram.remove(toRemove, true);\n\t this.diagram._syncChanges();\n\t }\n\t },\n\n\t edit: function() {\n\t var selectedElemens = this.selectedElements();\n\t if (selectedElemens.length === 1) {\n\t this.diagram.edit(selectedElemens[0]);\n\t }\n\t },\n\n\t rotateClockwise: function(options) {\n\t var angle = parseFloat(options.step || 90);\n\t this._rotate(angle);\n\t },\n\n\t rotateAnticlockwise: function(options) {\n\t var angle = parseFloat(options.step || 90);\n\t this._rotate(-angle);\n\t },\n\n\t _rotate: function(angle) {\n\t var adorner = this.diagram._resizingAdorner;\n\t adorner.angle(adorner.angle() + angle);\n\t adorner.rotate();\n\t },\n\n\t selectedElements: function() {\n\t return this.diagram.select();\n\t },\n\n\t createShape: function() {\n\t this.diagram.createShape();\n\t },\n\n\t createConnection: function() {\n\t this.diagram.createConnection();\n\t },\n\n\t undo: function() {\n\t this.diagram.undo();\n\t },\n\n\t redo: function() {\n\t this.diagram.redo();\n\t },\n\n\t destroy: function() {\n\t this.diagram = null;\n\t this.element = null;\n\t this.options = null;\n\n\t if (this._toolBar) {\n\t this._toolBar.destroy();\n\t }\n\n\t if (this._popup) {\n\t this._popup.destroy();\n\t }\n\t }\n\t });\n\n\t var Editor = kendo.Observable.extend({\n\t init: function(element, options) {\n\t kendo.Observable.fn.init.call(this);\n\n\t this.options = extend(true, {}, this.options, options);\n\t this.element = element;\n\t this.model = this.options.model;\n\t this.fields = this._getFields();\n\t this._initContainer();\n\t this.createEditable();\n\t },\n\n\t options: {\n\t editors: {}\n\t },\n\n\t _initContainer: function() {\n\t this.wrapper = this.element;\n\t },\n\n\t createEditable: function() {\n\t var options = this.options;\n\n\t this.editable = new kendo.ui.Editable(this.wrapper, {\n\t fields: this.fields,\n\t target: options.target,\n\t clearContainer: false,\n\t model: this.model\n\t });\n\t },\n\n\t _isEditable: function(field) {\n\t return this.model.editable && this.model.editable(field);\n\t },\n\n\t _getFields: function() {\n\t var fields = [];\n\t var modelFields = this.model.fields;\n\n\t for (var field in modelFields) {\n\t var result = {};\n\t if (this._isEditable(field)) {\n\t var editor = this.options.editors[field];\n\t if (editor) {\n\t result.editor = editor;\n\t }\n\t result.field = field;\n\t fields.push(result);\n\t }\n\t }\n\n\t return fields;\n\t },\n\n\t end: function() {\n\t return this.editable.end();\n\t },\n\n\t destroy: function() {\n\t this.editable.destroy();\n\t this.editable.element.find(\"[\" + kendo.attr(\"container-for\") + \"]\").empty();\n\t this.model = this.wrapper = this.element = this.columns = this.editable = null;\n\t }\n\t });\n\n\t var PopupEditor = Editor.extend({\n\t init: function(element, options) {\n\t Editor.fn.init.call(this, element, options);\n\t this.bind(this.events, this.options);\n\n\t this.open();\n\t },\n\n\t events: [ \"update\", \"cancel\" ],\n\n\t options: {\n\t window: {\n\t modal: true,\n\t resizable: false,\n\t draggable: true,\n\t title: \"Edit\",\n\t visible: false\n\t }\n\t },\n\n\t _initContainer: function() {\n\t var that = this;\n\t this.wrapper = $('