UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

1,488 lines (1,415 loc) • 76.5 kB
/** * DevExtreme (viz/core/renderers/renderer.js) * Version: 20.1.7 * Build date: Tue Aug 25 2020 * * Copyright (c) 2012 - 2020 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; var _renderer = require("../../../core/renderer"); var _renderer2 = _interopRequireDefault(_renderer); var _dom_adapter = require("../../../core/dom_adapter"); var _dom_adapter2 = _interopRequireDefault(_dom_adapter); var _window = require("../../../core/utils/window"); var _window2 = _interopRequireDefault(_window); var _call_once = require("../../../core/utils/call_once"); var _call_once2 = _interopRequireDefault(_call_once); var _events_engine = require("../../../events/core/events_engine"); var _events_engine2 = _interopRequireDefault(_events_engine); var _browser = require("../../../core/utils/browser"); var _browser2 = _interopRequireDefault(_browser); var _svg = require("../../../core/utils/svg"); var _animation = require("./animation"); var _animation2 = _interopRequireDefault(_animation); var _utils = require("../utils"); var _type = require("../../../core/utils/type"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj } } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest() } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.") } function _unsupportedIterableToArray(o, minLen) { if (!o) { return } if ("string" === typeof o) { return _arrayLikeToArray(o, minLen) } var n = Object.prototype.toString.call(o).slice(8, -1); if ("Object" === n && o.constructor) { n = o.constructor.name } if ("Map" === n || "Set" === n) { return Array.from(o) } if ("Arguments" === n || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) { return _arrayLikeToArray(o, minLen) } } function _arrayLikeToArray(arr, len) { if (null == len || len > arr.length) { len = arr.length } for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i] } return arr2 } function _iterableToArrayLimit(arr, i) { if ("undefined" === typeof Symbol || !(Symbol.iterator in Object(arr))) { return } var _arr = []; var _n = true; var _d = false; var _e = void 0; try { for (var _s, _i = arr[Symbol.iterator](); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) { break } } } catch (err) { _d = true; _e = err } finally { try { if (!_n && null != _i.return) { _i.return() } } finally { if (_d) { throw _e } } } return _arr } function _arrayWithHoles(arr) { if (Array.isArray(arr)) { return arr } } var window = _window2.default.getWindow(); var max = Math.max, min = Math.min, floor = Math.floor, round = Math.round, sin = Math.sin, cos = Math.cos, abs = Math.abs, PI = Math.PI; var PI_DIV_180 = PI / 180; var SHARPING_CORRECTION = .5; var ARC_COORD_PREC = 5; var pxAddingExceptions = { "column-count": true, "fill-opacity": true, "flex-grow": true, "flex-shrink": true, "font-weight": true, "line-height": true, opacity: true, order: true, orphans: true, widows: true, "z-index": true, zoom: true }; var KEY_TEXT = "text"; var KEY_STROKE = "stroke"; var KEY_STROKE_WIDTH = "stroke-width"; var KEY_STROKE_OPACITY = "stroke-opacity"; var KEY_FONT_SIZE = "font-size"; var KEY_FONT_STYLE = "font-style"; var KEY_FONT_WEIGHT = "font-weight"; var KEY_TEXT_DECORATION = "text-decoration"; var KEY_TEXTS_ALIGNMENT = "textsAlignment"; var NONE = "none"; var DEFAULT_FONT_SIZE = 12; var ELLIPSIS = "..."; var objectCreate = function() { if (!Object.create) { return function(proto) { var F = function() {}; F.prototype = proto; return new F } } else { return function(proto) { return Object.create(proto) } } }(); var DEFAULTS = { scaleX: 1, scaleY: 1, "pointer-events": null }; var getBackup = (0, _call_once2.default)(function() { var backupContainer = _dom_adapter2.default.createElement("div"); var backupCounter = 0; backupContainer.style.left = "-9999px"; backupContainer.style.position = "absolute"; return { backupContainer: backupContainer, backupCounter: backupCounter } }); function backupRoot(root) { if (0 === getBackup().backupCounter) { _dom_adapter2.default.getBody().appendChild(getBackup().backupContainer) }++getBackup().backupCounter; root.append({ element: getBackup().backupContainer }) } function restoreRoot(root, container) { root.append({ element: container }); --getBackup().backupCounter; if (0 === getBackup().backupCounter) { _dom_adapter2.default.getBody().removeChild(getBackup().backupContainer) } } var getNextDefsSvgId = function() { var numDefsSvgElements = 1; return function() { return "DevExpress_" + numDefsSvgElements++ } }(); function isObjectArgument(value) { return value && "string" !== typeof value } function createElement(tagName) { return _dom_adapter2.default.createElementNS("http://www.w3.org/2000/svg", tagName) } function getFuncIri(id, pathModified) { return null !== id ? "url(" + (pathModified ? window.location.href.split("#")[0] : "") + "#" + id + ")" : id } module.exports.getFuncIri = getFuncIri; function extend(target, source) { var key; for (key in source) { target[key] = source[key] } return target } function roundValue(value, exp) { value = value.toString().split("e"); value = round(+(value[0] + "e" + (value[1] ? +value[1] + exp : exp))); value = value.toString().split("e"); return +(value[0] + "e" + (value[1] ? +value[1] - exp : -exp)) } function getBoundingClientRect(element) { var box; try { box = element.getBoundingClientRect() } catch (e) {} return box || { left: 0, top: 0 } } var preserveAspectRatioMap = { full: NONE, lefttop: "xMinYMin", leftcenter: "xMinYMid", leftbottom: "xMinYMax", centertop: "xMidYMin", center: "xMidYMid", centerbottom: "xMidYMax", righttop: "xMaxYMin", rightcenter: "xMaxYMid", rightbottom: "xMaxYMax" }; function processHatchingAttrs(element, attrs) { if (attrs.hatching && "none" !== (0, _utils.normalizeEnum)(attrs.hatching.direction)) { attrs = extend({}, attrs); attrs.fill = element._hatching = element.renderer.lockHatching(attrs.fill, attrs.hatching, element._hatching); delete attrs.hatching } else { if (element._hatching) { element.renderer.releaseHatching(element._hatching); element._hatching = null } } return attrs } module.exports.processHatchingAttrs = processHatchingAttrs; function normalizeArcParams(x, y, innerR, outerR, startAngle, endAngle) { var isCircle; var noArc = true; var angleDiff = roundValue(endAngle, 3) - roundValue(startAngle, 3); if (angleDiff) { if (abs(angleDiff) % 360 === 0) { startAngle = 0; endAngle = 360; isCircle = true; endAngle -= .01 } if (startAngle > 360) { startAngle %= 360 } if (endAngle > 360) { endAngle %= 360 } if (startAngle > endAngle) { startAngle -= 360 } noArc = false } startAngle *= PI_DIV_180; endAngle *= PI_DIV_180; return [x, y, min(outerR, innerR), max(outerR, innerR), cos(startAngle), sin(startAngle), cos(endAngle), sin(endAngle), isCircle, floor(abs(endAngle - startAngle) / PI) % 2 ? "1" : "0", noArc] } var buildArcPath = function(x, y, innerR, outerR, startAngleCos, startAngleSin, endAngleCos, endAngleSin, isCircle, longFlag) { return ["M", (x + outerR * startAngleCos).toFixed(ARC_COORD_PREC), (y - outerR * startAngleSin).toFixed(ARC_COORD_PREC), "A", outerR.toFixed(ARC_COORD_PREC), outerR.toFixed(ARC_COORD_PREC), 0, longFlag, 0, (x + outerR * endAngleCos).toFixed(ARC_COORD_PREC), (y - outerR * endAngleSin).toFixed(ARC_COORD_PREC), isCircle ? "M" : "L", (x + innerR * endAngleCos).toFixed(5), (y - innerR * endAngleSin).toFixed(ARC_COORD_PREC), "A", innerR.toFixed(ARC_COORD_PREC), innerR.toFixed(ARC_COORD_PREC), 0, longFlag, 1, (x + innerR * startAngleCos).toFixed(ARC_COORD_PREC), (y - innerR * startAngleSin).toFixed(ARC_COORD_PREC), "Z"].join(" ") }; function buildPathSegments(points, type) { var list = [ ["M", 0, 0] ]; switch (type) { case "line": list = buildLineSegments(points); break; case "area": list = buildLineSegments(points, true); break; case "bezier": list = buildCurveSegments(points); break; case "bezierarea": list = buildCurveSegments(points, true) } return list } function buildLineSegments(points, close) { return buildSegments(points, buildSimpleLineSegment, close) } function buildCurveSegments(points, close) { return buildSegments(points, buildSimpleCurveSegment, close) } function buildSegments(points, buildSimpleSegment, close) { var _points$; var i; var ii; var list = []; if (null === (_points$ = points[0]) || void 0 === _points$ ? void 0 : _points$.length) { for (i = 0, ii = points.length; i < ii; ++i) { buildSimpleSegment(points[i], close, list) } } else { buildSimpleSegment(points, close, list) } return list } function buildSimpleLineSegment(points, close, list) { var i = 0; var k0 = list.length; var k = k0; var ii = (points || []).length; if (ii) { if (void 0 !== points[0].x) { for (; i < ii;) { list[k++] = ["L", points[i].x, points[i++].y] } } else { for (; i < ii;) { list[k++] = ["L", points[i++], points[i++]] } } list[k0][0] = "M" } else { list[k] = ["M", 0, 0] } close && list.push(["Z"]); return list } function buildSimpleCurveSegment(points, close, list) { var i; var k = list.length; var ii = (points || []).length; if (ii) { if (void 0 !== points[0].x) { list[k++] = ["M", points[0].x, points[0].y]; for (i = 1; i < ii;) { list[k++] = ["C", points[i].x, points[i++].y, points[i].x, points[i++].y, points[i].x, points[i++].y] } } else { list[k++] = ["M", points[0], points[1]]; for (i = 2; i < ii;) { list[k++] = ["C", points[i++], points[i++], points[i++], points[i++], points[i++], points[i++]] } } } else { list[k] = ["M", 0, 0] } close && list.push(["Z"]); return list } function combinePathParam(segments) { var d = []; var k = 0; var i; var ii = segments.length; var segment; var j; var jj; for (i = 0; i < ii; ++i) { segment = segments[i]; for (j = 0, jj = segment.length; j < jj; ++j) { d[k++] = segment[j] } } return d.join(" ") } function compensateSegments(oldSegments, newSegments, type) { var oldLength = oldSegments.length; var newLength = newSegments.length; var i; var originalNewSegments; var makeEqualSegments = type.indexOf("area") !== -1 ? makeEqualAreaSegments : makeEqualLineSegments; if (0 === oldLength) { for (i = 0; i < newLength; i++) { oldSegments.push(newSegments[i].slice(0)) } } else { if (oldLength < newLength) { makeEqualSegments(oldSegments, newSegments, type) } else { if (oldLength > newLength) { originalNewSegments = newSegments.slice(0); makeEqualSegments(newSegments, oldSegments, type) } } } return originalNewSegments } function prepareConstSegment(constSeg, type) { var x = constSeg[constSeg.length - 2]; var y = constSeg[constSeg.length - 1]; switch (type) { case "line": case "area": constSeg[0] = "L"; break; case "bezier": case "bezierarea": constSeg[0] = "C"; constSeg[1] = constSeg[3] = constSeg[5] = x; constSeg[2] = constSeg[4] = constSeg[6] = y } } function makeEqualLineSegments(short, long, type) { var constSeg = short[short.length - 1].slice(); var i = short.length; prepareConstSegment(constSeg, type); for (; i < long.length; i++) { short[i] = constSeg.slice(0) } } function makeEqualAreaSegments(short, long, type) { var i; var head; var shortLength = short.length; var longLength = long.length; var constsSeg1; var constsSeg2; if ((shortLength - 1) % 2 === 0 && (longLength - 1) % 2 === 0) { i = (shortLength - 1) / 2 - 1; head = short.slice(0, i + 1); constsSeg1 = head[head.length - 1].slice(0); constsSeg2 = short.slice(i + 1)[0].slice(0); prepareConstSegment(constsSeg1, type); prepareConstSegment(constsSeg2, type); for (var j = i; j < (longLength - 1) / 2 - 1; j++) { short.splice(j + 1, 0, constsSeg1); short.splice(j + 3, 0, constsSeg2) } } } function baseCss(that, styles) { var elemStyles = that._styles; var str = ""; var key; var value; styles = styles || {}; for (key in styles) { value = styles[key]; if ((0, _type.isDefined)(value)) { value += "number" === typeof value && !pxAddingExceptions[key] ? "px" : ""; elemStyles[key] = "" !== value ? value : null } } for (key in elemStyles) { value = elemStyles[key]; if (value) { str += key + ":" + value + ";" } } str && that.element.setAttribute("style", str); return that } function fixFuncIri(wrapper, attribute) { var element = wrapper.element; var id = wrapper.attr(attribute); if (id && id.indexOf("DevExpress") !== -1) { element.removeAttribute(attribute); element.setAttribute(attribute, getFuncIri(id, wrapper.renderer.pathModified)) } } function baseAttr(that, attrs) { attrs = attrs || {}; var settings = that._settings; var attributes = {}; var key; var value; var elem = that.element; var renderer = that.renderer; var rtl = renderer.rtl; var hasTransformations; var recalculateDashStyle; var sw; var i; if (!isObjectArgument(attrs)) { if (attrs in settings) { return settings[attrs] } if (attrs in DEFAULTS) { return DEFAULTS[attrs] } return 0 } extend(attributes, attrs); for (key in attributes) { value = attributes[key]; if (void 0 === value) { continue } settings[key] = value; if ("align" === key) { key = "text-anchor"; value = { left: rtl ? "end" : "start", center: "middle", right: rtl ? "start" : "end" } [value] || null } else { if ("dashStyle" === key) { recalculateDashStyle = true; continue } else { if (key === KEY_STROKE_WIDTH) { recalculateDashStyle = true } else { if (value && ("fill" === key || "clip-path" === key || "filter" === key) && 0 === value.indexOf("DevExpress")) { that._addFixIRICallback(); value = getFuncIri(value, renderer.pathModified) } else { if (/^(translate(X|Y)|rotate[XY]?|scale(X|Y)|sharp|sharpDirection)$/i.test(key)) { hasTransformations = true; continue } else { if (/^(x|y|d)$/i.test(key)) { hasTransformations = true } } } } } } if (null === value) { elem.removeAttribute(key) } else { elem.setAttribute(key, value) } } if (recalculateDashStyle && "dashStyle" in settings) { value = settings.dashStyle; sw = ("_originalSW" in that ? that._originalSW : settings[KEY_STROKE_WIDTH]) || 1; key = "stroke-dasharray"; value = null === value ? "" : (0, _utils.normalizeEnum)(value); if ("" === value || "solid" === value || value === NONE) { that.element.removeAttribute(key) } else { value = value.replace(/longdash/g, "8,3,").replace(/dash/g, "4,3,").replace(/dot/g, "1,3,").replace(/,$/, "").split(","); i = value.length; while (i--) { value[i] = parseInt(value[i]) * sw } that.element.setAttribute(key, value.join(",")) } } if (hasTransformations) { that._applyTransformation() } return that } function pathAttr(attrs) { var that = this; var segments; if (isObjectArgument(attrs)) { attrs = extend({}, attrs); segments = attrs.segments; if ("points" in attrs) { segments = buildPathSegments(attrs.points, that.type); delete attrs.points } if (segments) { attrs.d = combinePathParam(segments); that.segments = segments; delete attrs.segments } } return baseAttr(that, attrs) } function arcAttr(attrs) { var settings = this._settings; var x; var y; var innerRadius; var outerRadius; var startAngle; var endAngle; if (isObjectArgument(attrs)) { attrs = extend({}, attrs); if ("x" in attrs || "y" in attrs || "innerRadius" in attrs || "outerRadius" in attrs || "startAngle" in attrs || "endAngle" in attrs) { settings.x = x = "x" in attrs ? attrs.x : settings.x; delete attrs.x; settings.y = y = "y" in attrs ? attrs.y : settings.y; delete attrs.y; settings.innerRadius = innerRadius = "innerRadius" in attrs ? attrs.innerRadius : settings.innerRadius; delete attrs.innerRadius; settings.outerRadius = outerRadius = "outerRadius" in attrs ? attrs.outerRadius : settings.outerRadius; delete attrs.outerRadius; settings.startAngle = startAngle = "startAngle" in attrs ? attrs.startAngle : settings.startAngle; delete attrs.startAngle; settings.endAngle = endAngle = "endAngle" in attrs ? attrs.endAngle : settings.endAngle; delete attrs.endAngle; attrs.d = buildArcPath.apply(null, normalizeArcParams(x, y, innerRadius, outerRadius, startAngle, endAngle)) } } return baseAttr(this, attrs) } function rectAttr(attrs) { var that = this; var x; var y; var width; var height; var sw; var maxSW; var newSW; if (isObjectArgument(attrs)) { attrs = extend({}, attrs); if (void 0 !== attrs.x || void 0 !== attrs.y || void 0 !== attrs.width || void 0 !== attrs.height || void 0 !== attrs[KEY_STROKE_WIDTH]) { void 0 !== attrs.x ? x = that._originalX = attrs.x : x = that._originalX || 0; void 0 !== attrs.y ? y = that._originalY = attrs.y : y = that._originalY || 0; void 0 !== attrs.width ? width = that._originalWidth = attrs.width : width = that._originalWidth || 0; void 0 !== attrs.height ? height = that._originalHeight = attrs.height : height = that._originalHeight || 0; void 0 !== attrs[KEY_STROKE_WIDTH] ? sw = that._originalSW = attrs[KEY_STROKE_WIDTH] : sw = that._originalSW; maxSW = ~~((width < height ? width : height) / 2); newSW = (sw || 0) < maxSW ? sw || 0 : maxSW; attrs.x = x + newSW / 2; attrs.y = y + newSW / 2; attrs.width = width - newSW; attrs.height = height - newSW; ((sw || 0) !== newSW || !(0 === newSW && void 0 === sw)) && (attrs[KEY_STROKE_WIDTH] = newSW) } if ("sharp" in attrs) { delete attrs.sharp } } return baseAttr(that, attrs) } function textAttr(attrs) { var that = this; var isResetRequired; if (!isObjectArgument(attrs)) { return baseAttr(that, attrs) } attrs = extend({}, attrs); var settings = that._settings; var wasStroked = (0, _type.isDefined)(settings[KEY_STROKE]) && (0, _type.isDefined)(settings[KEY_STROKE_WIDTH]); if (void 0 !== attrs[KEY_TEXT]) { settings[KEY_TEXT] = attrs[KEY_TEXT]; delete attrs[KEY_TEXT]; isResetRequired = true } if (void 0 !== attrs[KEY_STROKE]) { settings[KEY_STROKE] = attrs[KEY_STROKE]; delete attrs[KEY_STROKE] } if (void 0 !== attrs[KEY_STROKE_WIDTH]) { settings[KEY_STROKE_WIDTH] = attrs[KEY_STROKE_WIDTH]; delete attrs[KEY_STROKE_WIDTH] } if (void 0 !== attrs[KEY_STROKE_OPACITY]) { settings[KEY_STROKE_OPACITY] = attrs[KEY_STROKE_OPACITY]; delete attrs[KEY_STROKE_OPACITY] } if (void 0 !== attrs[KEY_TEXTS_ALIGNMENT]) { alignTextNodes(that, attrs[KEY_TEXTS_ALIGNMENT]); delete attrs[KEY_TEXTS_ALIGNMENT] } var isStroked = (0, _type.isDefined)(settings[KEY_STROKE]) && (0, _type.isDefined)(settings[KEY_STROKE_WIDTH]); baseAttr(that, attrs); isResetRequired = isResetRequired || isStroked !== wasStroked && settings[KEY_TEXT]; if (isResetRequired) { createTextNodes(that, settings.text, isStroked); that._hasEllipsis = false } if (isResetRequired || void 0 !== attrs.x || void 0 !== attrs.y) { locateTextNodes(that) } if (isStroked) { strokeTextNodes(that) } return that } function textCss(styles) { styles = styles || {}; baseCss(this, styles); if (KEY_FONT_SIZE in styles) { locateTextNodes(this) } return this } function orderHtmlTree(list, line, node, parentStyle, parentClassName) { var style; var realStyle; var i; var ii; var nodes; if (void 0 !== node.wholeText) { list.push({ value: node.wholeText, style: parentStyle, className: parentClassName, line: line, height: parentStyle[KEY_FONT_SIZE] || 0 }) } else { if ("BR" === node.tagName) { ++line } else { if (_dom_adapter2.default.isElementNode(node)) { extend(style = {}, parentStyle); switch (node.tagName) { case "B": case "STRONG": style[KEY_FONT_WEIGHT] = "bold"; break; case "I": case "EM": style[KEY_FONT_STYLE] = "italic"; break; case "U": style[KEY_TEXT_DECORATION] = "underline" } realStyle = node.style; realStyle.color && (style.fill = realStyle.color); realStyle.fontSize && (style[KEY_FONT_SIZE] = realStyle.fontSize); realStyle.fontStyle && (style[KEY_FONT_STYLE] = realStyle.fontStyle); realStyle.fontWeight && (style[KEY_FONT_WEIGHT] = realStyle.fontWeight); realStyle.textDecoration && (style[KEY_TEXT_DECORATION] = realStyle.textDecoration); for (i = 0, nodes = node.childNodes, ii = nodes.length; i < ii; ++i) { line = orderHtmlTree(list, line, nodes[i], style, node.className || parentClassName) } } } } return line } function adjustLineHeights(items) { var i; var ii; var currentItem = items[0]; var item; for (i = 1, ii = items.length; i < ii; ++i) { item = items[i]; if (item.line === currentItem.line) { currentItem.height = maxLengthFontSize(currentItem.height, item.height); currentItem.inherits = currentItem.inherits || 0 === parseFloat(item.height); item.height = NaN } else { currentItem = item } } } function removeExtraAttrs(html) { var findTagAttrs = /(?:(<[a-z0-9]+\s*))([\s\S]*?)(>|\/>)/gi; var findStyleAndClassAttrs = /(style|class)\s*=\s*(["'])(?:(?!\2).)*\2\s?/gi; return html.replace(findTagAttrs, function(allTagAttrs, p1, p2, p3) { p2 = (p2 && p2.match(findStyleAndClassAttrs) || []).map(function(str) { return str }).join(" "); return p1 + p2 + p3 }) } function parseHTML(text) { var items = []; var div = _dom_adapter2.default.createElement("div"); div.innerHTML = text.replace(/\r/g, "").replace(/\n/g, "<br/>"); orderHtmlTree(items, 0, div, {}, ""); adjustLineHeights(items); return items } function parseMultiline(text) { var texts = text.replace(/\r/g, "").split(/\n/g); var i = 0; var items = []; for (; i < texts.length; i++) { items.push({ value: texts[i].trim(), height: 0, line: i }) } return items } function createTspans(items, element, fieldName) { var i; var ii; var item; for (i = 0, ii = items.length; i < ii; ++i) { item = items[i]; item[fieldName] = createElement("tspan"); item[fieldName].appendChild(_dom_adapter2.default.createTextNode(item.value)); item.style && baseCss({ element: item[fieldName], _styles: {} }, item.style); item.className && item[fieldName].setAttribute("class", item.className); element.appendChild(item[fieldName]) } } function restoreText() { if (this._hasEllipsis) { this.attr({ text: this._settings.text }) } } function applyEllipsis(maxWidth) { var that = this; var lines; var hasEllipsis = false; var i; var ii; var lineParts; var j; var jj; var text; restoreText.call(that); var ellipsis = that.renderer.text(ELLIPSIS).attr(that._styles).append(that.renderer.root); var ellipsisWidth = ellipsis.getBBox().width; if (that._getElementBBox().width > maxWidth) { if (maxWidth - ellipsisWidth < 0) { maxWidth = 0 } else { maxWidth -= ellipsisWidth } lines = prepareLines(that.element, that._texts, maxWidth); for (i = 0, ii = lines.length; i < ii; ++i) { lineParts = lines[i].parts; if (1 === lines[i].commonLength) { continue } for (j = 0, jj = lineParts.length; j < jj; ++j) { text = lineParts[j]; if ((0, _type.isDefined)(text.endIndex)) { setNewText(text, text.endIndex); hasEllipsis = true } else { if (text.startBox > maxWidth) { removeTextSpan(text) } } } } } ellipsis.remove(); that._hasEllipsis = hasEllipsis; return hasEllipsis } function cloneAndRemoveAttrs(node) { var clone; if (node) { clone = node.cloneNode(); clone.removeAttribute("y"); clone.removeAttribute("x") } return clone || node } function detachAndStoreTitleElements(element) { var titleElements = _dom_adapter2.default.querySelectorAll(element, "title"); for (var i = 0; i < titleElements.length; i++) { element.removeChild(titleElements[i]) } return function() { for (var _i = 0; _i < titleElements.length; _i++) { element.appendChild(titleElements[_i]) } } } function setMaxSize(maxWidth, maxHeight) { var options = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {}; var that = this; var lines = []; var textChanged = false; var textIsEmpty = false; var ellipsisMaxWidth = maxWidth; restoreText.call(that); var restoreTitleElement = detachAndStoreTitleElements(this.element); var ellipsis = that.renderer.text(ELLIPSIS).attr(that._styles).append(that.renderer.root); var ellipsisWidth = ellipsis.getBBox().width; var _that$_getElementBBox = that._getElementBBox(), width = _that$_getElementBBox.width, height = _that$_getElementBBox.height; if ((width || height) && (width > maxWidth || maxHeight && height > maxHeight)) { if (maxWidth - ellipsisWidth < 0) { ellipsisMaxWidth = 0 } else { ellipsisMaxWidth -= ellipsisWidth } lines = applyOverflowRules(that.element, that._texts, maxWidth, ellipsisMaxWidth, options, maxHeight); lines = setMaxHeight(lines, ellipsisMaxWidth, options, maxHeight, parseFloat(this._getLineHeight())); this._texts = lines.reduce(function(texts, line) { return texts.concat(line.parts) }, []).filter(function(t) { return "" !== t.value }).map(function(t) { t.stroke && t.tspan.parentNode.appendChild(t.stroke); return t }).map(function(t) { t.tspan.parentNode.appendChild(t.tspan); return t }); !this._texts.length && (this._texts = null); textChanged = true; if (this._texts) { locateTextNodes(this) } else { this.element.textContent = ""; textIsEmpty = true } } ellipsis.remove(); that._hasEllipsis = textChanged; restoreTitleElement(); return { rowCount: lines.length, textChanged: textChanged, textIsEmpty: textIsEmpty } } function getIndexForEllipsis(text, maxWidth, startBox, endBox) { var k; var kk; if (startBox <= maxWidth && endBox > maxWidth) { for (k = 1, kk = text.value.length; k <= kk; ++k) { if (startBox + text.tspan.getSubStringLength(0, k) > maxWidth) { return k - 1 } } } } function getTextWidth(text) { return text.value.length ? text.tspan.getSubStringLength(0, text.value.length) : 0 } function prepareLines(element, texts, maxWidth) { var lines = []; var i; var ii; var text; var startBox; var endBox; if (texts) { for (i = 0, ii = texts.length; i < ii; ++i) { text = texts[i]; if (!lines[text.line]) { text.startBox = startBox = 0; lines.push({ commonLength: text.value.length, parts: [text] }) } else { text.startBox = startBox; lines[text.line].parts.push(text); lines[text.line].commonLength += text.value.length } endBox = startBox + text.tspan.getSubStringLength(0, text.value.length); text.endIndex = getIndexForEllipsis(text, maxWidth, startBox, endBox); startBox = endBox } } else { text = { value: element.textContent, tspan: element }; text.startBox = startBox = 0; endBox = startBox + getTextWidth(text); text.endIndex = getIndexForEllipsis(text, maxWidth, startBox, endBox); lines = [{ commonLength: element.textContent.length, parts: [text] }] } return lines } function getSpaceBreakIndex(text, maxWidth) { var initialIndices = text.startBox > 0 ? [0] : []; var spaceIndices = text.value.split("").reduce(function(indices, char, index) { if (" " === char) { indices.push(index) } return indices }, initialIndices); var spaceIndex = 0; while (void 0 !== spaceIndices[spaceIndex + 1] && text.startBox + text.tspan.getSubStringLength(0, spaceIndices[spaceIndex + 1]) < maxWidth) { spaceIndex++ } return spaceIndices[spaceIndex] } function getWordBreakIndex(text, maxWidth) { for (var i = 0; i < text.value.length - 1; i++) { if (text.startBox + text.tspan.getSubStringLength(0, i + 1) > maxWidth) { return i } } } function getEllipsisString(ellipsisMaxWidth, _ref) { var hideOverflowEllipsis = _ref.hideOverflowEllipsis; return hideOverflowEllipsis && 0 === ellipsisMaxWidth ? "" : ELLIPSIS } function setEllipsis(text, ellipsisMaxWidth, options) { var ellipsis = getEllipsisString(ellipsisMaxWidth, options); if (text.value.length && text.tspan.parentNode) { for (var i = text.value.length - 1; i >= 1; i--) { if (text.startBox + text.tspan.getSubStringLength(0, i) < ellipsisMaxWidth) { setNewText(text, i, ellipsis); break } else { if (1 === i) { setNewText(text, 0, ellipsis) } } } } } function wordWrap(text, maxWidth, ellipsisMaxWidth, options) { var wholeText = text.value; var breakIndex; if ("none" !== options.wordWrap) { breakIndex = "normal" === options.wordWrap ? getSpaceBreakIndex(text, maxWidth) : getWordBreakIndex(text, maxWidth) } var restLines = []; var restText; if (isFinite(breakIndex)) { setNewText(text, breakIndex, ""); var newTextOffset = " " === wholeText[breakIndex] ? 1 : 0; var restString = wholeText.slice(breakIndex + newTextOffset); if (restString.length) { var restTspan = cloneAndRemoveAttrs(text.tspan); restTspan.textContent = restString; text.tspan.parentNode.appendChild(restTspan); restText = extend(extend({}, text), { value: restString, startBox: 0, height: 0, tspan: restTspan, stroke: cloneAndRemoveAttrs(text.stroke), endBox: restTspan.getSubStringLength(0, restString.length) }); restText.stroke && (restText.stroke.textContent = restString); if (restText.endBox > maxWidth) { restLines = wordWrap(restText, maxWidth, ellipsisMaxWidth, options); if (!restLines.length) { return [] } } } } if (text.value.length) { if ("ellipsis" === options.textOverflow && text.tspan.getSubStringLength(0, text.value.length) > maxWidth) { setEllipsis(text, ellipsisMaxWidth, options) } if ("hide" === options.textOverflow && text.tspan.getSubStringLength(0, text.value.length) > maxWidth) { return [] } } else { text.tspan.parentNode.removeChild(text.tspan) } var parts = []; if (restText) { parts.push(restText) } return [{ commonLength: wholeText.length, parts: parts }].concat(restLines) } function calculateLineHeight(line, lineHeight) { return line.parts.reduce(function(height, text) { return max(height, getItemLineHeight(text, lineHeight)) }, 0) } function setMaxHeight(lines, ellipsisMaxWidth, options, maxHeight, lineHeight) { var textOverflow = options.textOverflow; if (!isFinite(maxHeight) || 0 === Number(maxHeight) || "none" === textOverflow) { return lines } var result = lines.reduce(function(_ref2, l, index, arr) { var _ref3 = _slicedToArray(_ref2, 2), lines = _ref3[0], commonHeight = _ref3[1]; var height = calculateLineHeight(l, lineHeight); commonHeight += height; if (commonHeight < maxHeight) { lines.push(l) } else { l.parts.forEach(function(item) { removeTextSpan(item) }); if ("ellipsis" === textOverflow) { var prevLine = arr[index - 1]; if (prevLine) { var text = prevLine.parts[prevLine.parts.length - 1]; if (!text.hasEllipsis) { if (0 === ellipsisMaxWidth || text.endBox < ellipsisMaxWidth) { setNewText(text, text.value.length, getEllipsisString(ellipsisMaxWidth, options)) } else { setEllipsis(text, ellipsisMaxWidth, options) } } } } } return [lines, commonHeight] }, [ [], 0 ]); if ("hide" === textOverflow && result[1] > maxHeight) { result[0].forEach(function(l) { l.parts.forEach(function(item) { removeTextSpan(item) }) }); return [] } return result[0] } function applyOverflowRules(element, texts, maxWidth, ellipsisMaxWidth, options) { if (!texts) { var textValue = element.textContent; var text = { value: textValue, height: 0, line: 0 }; element.textContent = ""; createTspans([text], element, "tspan"); texts = [text] } return texts.reduce(function(_ref4, text) { var _ref5 = _slicedToArray(_ref4, 5), lines = _ref5[0], startBox = _ref5[1], endBox = _ref5[2], stop = _ref5[3], lineNumber = _ref5[4]; var line = lines[lines.length - 1]; if (stop) { return [lines, startBox, endBox, stop] } if (!line || text.line !== lineNumber) { text.startBox = startBox = 0; lines.push({ commonLength: text.value.length, parts: [text] }) } else { text.startBox = startBox; if (startBox > ellipsisMaxWidth && "none" === options.wordWrap && "ellipsis" === options.textOverflow) { removeTextSpan(text); return [lines, startBox, endBox, stop, lineNumber] } line.parts.push(text); line.commonLength += text.value.length } text.endBox = endBox = startBox + getTextWidth(text); startBox = endBox; if ((0, _type.isDefined)(maxWidth) && endBox > maxWidth) { var wordWrapLines = wordWrap(text, maxWidth, ellipsisMaxWidth, options); if (!wordWrapLines.length) { lines = []; stop = true } else { lines = lines.concat(wordWrapLines.filter(function(l) { return l.parts.length > 0 })) } } return [lines, startBox, endBox, stop, text.line] }, [ [], 0, 0, false, 0 ])[0] } function setNewText(text, index) { var insertString = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : ELLIPSIS; var newText = text.value.substr(0, index) + insertString; text.value = text.tspan.textContent = newText; text.stroke && (text.stroke.textContent = newText); if (insertString === ELLIPSIS) { text.hasEllipsis = true } } function removeTextSpan(text) { text.tspan.parentNode && text.tspan.parentNode.removeChild(text.tspan); text.stroke && text.stroke.parentNode && text.stroke.parentNode.removeChild(text.stroke) } function createTextNodes(wrapper, text, isStroked) { var items; var parsedHtml; wrapper._texts = null; wrapper.clear(); if (null === text) { return } text = "" + text; if (!wrapper.renderer.encodeHtml && (/<[a-z][\s\S]*>/i.test(text) || text.indexOf("&") !== -1)) { parsedHtml = removeExtraAttrs(text); items = parseHTML(parsedHtml) } else { if (/\n/g.test(text)) { items = parseMultiline(text) } else { if (isStroked) { items = [{ value: text.trim(), height: 0 }] } } } if (items) { if (items.length) { wrapper._texts = items; if (isStroked) { createTspans(items, wrapper.element, KEY_STROKE) } createTspans(items, wrapper.element, "tspan") } } else { wrapper.element.appendChild(_dom_adapter2.default.createTextNode(text)) } } function setTextNodeAttribute(item, name, value) { item.tspan.setAttribute(name, value); item.stroke && item.stroke.setAttribute(name, value) } function getItemLineHeight(item, defaultValue) { return item.inherits ? maxLengthFontSize(item.height, defaultValue) : item.height || defaultValue } function locateTextNodes(wrapper) { if (!wrapper._texts) { return } var items = wrapper._texts; var x = wrapper._settings.x; var lineHeight = wrapper._getLineHeight(); var i; var ii; var item = items[0]; setTextNodeAttribute(item, "x", x); setTextNodeAttribute(item, "y", wrapper._settings.y); for (i = 1, ii = items.length; i < ii; ++i) { item = items[i]; if (parseFloat(item.height) >= 0) { setTextNodeAttribute(item, "x", x); var height = getItemLineHeight(item, lineHeight); setTextNodeAttribute(item, "dy", height) } } } function alignTextNodes(wrapper, alignment) { if (!wrapper._texts || "center" === alignment) { return } var items = wrapper._texts; var direction = "left" === alignment ? -1 : 1; var maxTextWidth = Math.max.apply(Math, items.map(function(t) { return getTextWidth(t) })); for (var i = 0; i < items.length; i++) { var item = items[i]; var textWidth = getTextWidth(item); if (0 !== maxTextWidth && maxTextWidth !== textWidth) { setTextNodeAttribute(item, "dx", direction * round((maxTextWidth - textWidth) / 2 * 10) / 10) } } } function maxLengthFontSize(fontSize1, fontSize2) { var parsedHeight1 = parseFloat(fontSize1); var parsedHeight2 = parseFloat(fontSize2); var height1 = parsedHeight1 || DEFAULT_FONT_SIZE; var height2 = parsedHeight2 || DEFAULT_FONT_SIZE; return height1 > height2 ? !isNaN(parsedHeight1) ? fontSize1 : height1 : !isNaN(parsedHeight2) ? fontSize2 : height2 } function strokeTextNodes(wrapper) { if (!wrapper._texts) { return } var items = wrapper._texts; var stroke = wrapper._settings[KEY_STROKE]; var strokeWidth = wrapper._settings[KEY_STROKE_WIDTH]; var strokeOpacity = wrapper._settings[KEY_STROKE_OPACITY] || 1; var tspan; var i; var ii; for (i = 0, ii = items.length; i < ii; ++i) { tspan = items[i].stroke; tspan.setAttribute(KEY_STROKE, stroke); tspan.setAttribute(KEY_STROKE_WIDTH, strokeWidth); tspan.setAttribute(KEY_STROKE_OPACITY, strokeOpacity); tspan.setAttribute("stroke-linejoin", "round") } } function baseAnimate(that, params, options, complete) { options = options || {}; var key; var value; var renderer = that.renderer; var settings = that._settings; var animationParams = {}; var defaults = { translateX: 0, translateY: 0, scaleX: 1, scaleY: 1, rotate: 0, rotateX: 0, rotateY: 0 }; if (complete) { options.complete = complete } if (renderer.animationEnabled()) { for (key in params) { value = params[key]; if (/^(translate(X|Y)|rotate[XY]?|scale(X|Y))$/i.test(key)) { animationParams.transform = animationParams.transform || { from: {}, to: {} }; animationParams.transform.from[key] = key in settings ? Number(settings[key].toFixed(3)) : defaults[key]; animationParams.transform.to[key] = value } else { if ("arc" === key || "segments" === key) { animationParams[key] = value } else { animationParams[key] = { from: key in settings ? settings[key] : parseFloat(that.element.getAttribute(key) || 0), to: value } } } } renderer.animateElement(that, animationParams, extend(extend({}, renderer._animation), options)) } else { options.step && options.step.call(that, 1, 1); options.complete && options.complete.call(that); that.attr(params) } return that } function pathAnimate(params, options, complete) { var that = this; var curSegments = that.segments || []; var newSegments; var endSegments; if (that.renderer.animationEnabled() && "points" in params) { newSegments = buildPathSegments(params.points, that.type); endSegments = compensateSegments(curSegments, newSegments, that.type); params.segments = { from: curSegments, to: newSegments, end: endSegments }; delete params.points } return baseAnimate(that, params, options, complete) } function arcAnimate(params, options, complete) { var that = this; var settings = that._settings; var arcParams = { from: {}, to: {} }; if (that.renderer.animationEnabled() && ("x" in params || "y" in params || "innerRadius" in params || "outerRadius" in params || "startAngle" in params || "endAngle" in params)) { arcParams.from.x = settings.x || 0; arcParams.from.y = settings.y || 0; arcParams.from.innerRadius = settings.innerRadius || 0; arcParams.from.outerRadius = settings.outerRadius || 0; arcParams.from.startAngle = settings.startAngle || 0; arcParams.from.endAngle = settings.endAngle || 0; arcParams.to.x = "x" in params ? params.x : settings.x; delete params.x; arcParams.to.y = "y" in params ? params.y : settings.y; delete params.y; arcParams.to.innerRadius = "innerRadius" in params ? params.innerRadius : settings.innerRadius; delete params.innerRadius; arcParams.to.outerRadius = "outerRadius" in params ? params.outerRadius : settings.outerRadius; delete params.outerRadius; arcParams.to.startAngle = "startAngle" in params ? params.startAngle : settings.startAngle; delete params.startAngle; arcParams.to.endAngle = "endAngle" in params ? params.endAngle : settings.endAngle; delete params.endAngle; params.arc = arcParams } return baseAnimate(that, params, options, complete) } function buildLink(target, parameters) { var obj = { is: false, name: parameters.name || parameters, after: parameters.after }; if (target) { obj.to = target } else { obj.virtual = true } return obj } function SvgElement(renderer, tagName, type) { var that = this; that.renderer = renderer; that.element = createElement(tagName); that._settings = {}; that._styles = {}; if ("path" === tagName) { that.type = type || "line" } } function removeFuncIriCallback(callback) { fixFuncIriCallbacks.remove(callback) } exports.SvgElement = SvgElement; SvgElement.prototype = { constructor: SvgElement, _getJQElement: function() { return this._$element || (this._$element = (0, _