UNPKG

@syncfusion/ej2-diagrams

Version:

Feature-rich diagram control to create diagrams like flow charts, organizational charts, mind maps, and BPMN diagrams. Its rich feature set includes built-in shapes, editing, serializing, exporting, printing, overview, data binding, and automatic layouts.

1,248 lines (1,247 loc) 46.9 kB
import { Rect } from '../primitives/rect'; import { Size } from '../primitives/size'; import { processPathData, splitArrayCollection, transformPath } from './path-util'; import { whiteSpaceToString, wordBreakToString, textAlignToString, bBoxText, cloneObject } from './base-util'; import { identityMatrix, transformPointByMatrix, rotateMatrix } from '../primitives/matrix'; import { compile, createElement, Browser } from '@syncfusion/ej2-base'; import { Node } from '../objects/node'; import { getElement } from './diagram-util'; import { templateCompiler } from '../utility/base-util'; import { Diagram } from './../diagram'; import { FlipDirection } from '../enum/enum'; /** * Defines the functionalities that need to access DOM */ /** * removeElementsByClass method \ * * @returns {void} removeElementsByClass method .\ * @param { string } className - provide the element value. * @param {string} id - provide the string value. * @private */ export function removeElementsByClass(className, id) { var elements; if (id && document.getElementById(id).classList.contains(className)) { elements = document.getElementById(id).getElementsByClassName(className); } else { elements = document.getElementsByClassName(className); } while (elements.length > 0) { elements[0].parentNode.removeChild(elements[0]); } } /** * findSegmentPoints method \ * * @returns {PointModel[]} findSegmentPoints method .\ * @param { PathElement } element - provide the element value. * @private */ export function findSegmentPoints(element) { var pts = []; var sample; var sampleLength; var measureWindowElement = 'measureElement'; window["" + measureWindowElement].style.visibility = 'visible'; var svg = window["" + measureWindowElement].children[2]; var pathNode = getChildNode(svg)[0]; pathNode.setAttributeNS(null, 'd', element.data); var pathBounds = element.absoluteBounds; // || pathNode.getBBox(); var pathData = updatePath(element, pathBounds, element); pathNode.setAttributeNS(null, 'd', pathData); var pathLength = pathNode.getTotalLength(); // 930450: Diagram Taking Too Long to Load Due to Complex Hierarchical Tree Layout with Path Nodes var storedPoints = Diagram.prototype.getPathData(pathData); if (storedPoints.length === 0) { for (sampleLength = 0; sampleLength <= pathLength; sampleLength += 10) { sample = pathNode.getPointAtLength(sampleLength); pts.push({ x: sample.x, y: sample.y }); } // Push the calculated points into the shared storage Diagram.prototype.setPathData(pathData, pts); } else { pts = storedPoints; } window["" + measureWindowElement].style.visibility = 'hidden'; return pts; } /** * getChildNode method \ * * @returns {SVGElement[] | HTMLCollection} findSegmentPoints method .\ * @param { SVGElement } node - provide the element value. * @private */ export function getChildNode(node) { var child; var collection = []; if (Browser.info.name === 'msie' || Browser.info.name === 'edge') { for (var i = 0; i < node.childNodes.length; i++) { child = node.childNodes[parseInt(i.toString(), 10)]; if (child.nodeType === 1) { collection.push(child); } } } else { collection = node.children; } return collection; } /** * translatePoints method \ * * @returns {PointModel[]} translatePoints method .\ * @param { SVGElement } element - provide the element value. * @param { PointModel[] } points - provide the element value. * @private */ export function translatePoints(element, points) { var translatedPts = []; //895069: Update Connector docking position in node after flipping the node var left = element.offsetX - element.actualSize.width * element.pivot.x; var top = element.offsetY - element.actualSize.height * element.pivot.y; for (var _i = 0, points_1 = points; _i < points_1.length; _i++) { var point = points_1[_i]; var pt1 = void 0; var baseX = left + point.x; var baseY = top + point.y; var flipX = left + element.actualSize.width - point.x; var flipY = top + element.actualSize.height - point.y; // 895069: Updating the node and connector's docking point for node's fliped position switch (element.flip) { case FlipDirection.Both: pt1 = { x: flipX, y: flipY }; break; case FlipDirection.Horizontal: pt1 = { x: flipX, y: baseY }; break; case FlipDirection.Vertical: pt1 = { x: baseX, y: flipY }; break; default: pt1 = { x: baseX, y: baseY }; break; } var matrix = void 0; var angle = element.rotateAngle + element.parentTransform; if (angle) { matrix = identityMatrix(); rotateMatrix(matrix, angle, element.offsetX, element.offsetY); } if (matrix) { pt1 = transformPointByMatrix(matrix, pt1); } translatedPts.push(pt1); } return translatedPts; } // Cache to store connector decorator bounds var decoratorPathCache = {}; /** * Function to clear the cache * * @returns {void} * @private */ export function clearDecoratorPathCache() { decoratorPathCache = {}; } /** * measurePath method \ * * @returns {Rect} measurePath method .\ * @param { string } data - provide the element value. * @private */ export function measurePath(data) { if (data) { // return the cached decorator path bounds. if (decoratorPathCache["" + data]) { return decoratorPathCache["" + data]; } var measureWindowElement = 'measureElement'; window["" + measureWindowElement].style.visibility = 'visible'; var svg = window["" + measureWindowElement].children[2]; var element = getChildNode(svg)[0]; element.setAttribute('d', data); var bounds = element.getBBox(); var svgBounds = new Rect(bounds.x, bounds.y, bounds.width, bounds.height); window["" + measureWindowElement].style.visibility = 'hidden'; // Store the measured bounds in the cache. decoratorPathCache["" + data] = svgBounds; return svgBounds; } return new Rect(0, 0, 0, 0); } /** * getTextOptions method \ * * @returns {BaseAttributes} getTextOptions method .\ * @param { TextElement } element - provide the element value. * @param { number } maxWidth - provide the maxWidth value. * @private */ function getTextOptions(element, maxWidth) { var options = { fill: element.style.fill, stroke: element.style.strokeColor, angle: element.rotateAngle + element.parentTransform, pivotX: element.pivot.x, pivotY: element.pivot.y, strokeWidth: element.style.strokeWidth, dashArray: element.style.strokeDashArray, opacity: element.style.opacity, shadow: element.shadow, gradient: element.style.gradient, visible: element.visible, id: element.id, description: element.description, width: maxWidth || element.actualSize.width, height: element.actualSize.height, x: element.offsetX - element.actualSize.width * element.pivot.x + 0.5, y: element.offsetY - element.actualSize.height * element.pivot.y + 0.5 }; options.fontSize = element.style.fontSize; options.fontFamily = element.style.fontFamily; options.textOverflow = element.style.textOverflow; options.textDecoration = element.style.textDecoration; options.doWrap = element.doWrap; options.whiteSpace = whiteSpaceToString(element.style.whiteSpace, element.style.textWrapping); options.content = element.content; options.textWrapping = element.style.textWrapping; options.breakWord = wordBreakToString(element.style.textWrapping); options.textAlign = textAlignToString(element.style.textAlign); options.color = element.style.color; options.italic = element.style.italic; options.bold = element.style.bold; options.dashArray = ''; options.strokeWidth = 0; options.fill = ''; return options; } /** * wrapSvgText method \ * * @returns {SubTextElement[]} wrapSvgText method .\ * @param { TextAttributes } text - provide the element value. * @param { string } textValue - provide the maxWidth value. * @param { number } laneWidth - provide the maxWidth value. * @private */ function wrapSvgText(text, textValue, laneWidth) { var childNodes = []; var k = 0; var txtValue; var bounds1; var content = textValue || text.content; if (text.whiteSpace !== 'nowrap' && text.whiteSpace !== 'pre') { if (text.breakWord === 'breakall') { txtValue = ''; txtValue += content[0]; for (k = 0; k < content.length; k++) { bounds1 = bBoxText(txtValue, text); if (bounds1 >= text.width && txtValue.length > 0) { childNodes[childNodes.length] = { text: txtValue, x: 0, dy: 0, width: bounds1 }; txtValue = ''; } else { txtValue = txtValue + (content[k + 1] || ''); if (txtValue.indexOf('\n') > -1) { childNodes[childNodes.length] = { text: txtValue, x: 0, dy: 0, width: bBoxText(txtValue, text) }; txtValue = ''; } var width = bBoxText(txtValue, text); if (Math.ceil(width) + 2 >= text.width && txtValue.length > 0) { childNodes[childNodes.length] = { text: txtValue, x: 0, dy: 0, width: width }; txtValue = ''; } if (k === content.length - 1 && txtValue.length > 0) { childNodes[childNodes.length] = { text: txtValue, x: 0, dy: 0, width: width }; txtValue = ''; } } } } else { childNodes = wordWrapping(text, textValue, laneWidth); } } else { childNodes[childNodes.length] = { text: content, x: 0, dy: 0, width: bBoxText(content, text) }; } return childNodes; } /** * wordWrapping method \ * * @returns {SubTextElement[]} wordWrapping method .\ * @param { TextAttributes } text - provide the element value. * @param { string } textValue - provide the maxWidth value. * @param { number } laneWidth - provide the maxWidth value. * @private */ function wordWrapping(text, textValue, laneWidth) { var childNodes = []; var txtValue = ''; var j = 0; var i = 0; var wrap = text.whiteSpace !== 'nowrap' ? true : false; var content = textValue || text.content; var eachLine = content.split('\n'); var txt; var words; var newText; var existingWidth; var existingText; for (j = 0; j < eachLine.length; j++) { // eslint-disable-next-line @typescript-eslint/no-unused-vars txt = ''; words = text.textWrapping !== 'NoWrap' ? eachLine[parseInt(j.toString(), 10)].split(' ') : [eachLine[parseInt(j.toString(), 10)]]; for (i = 0; i < words.length; i++) { txtValue += (((i !== 0 || words.length === 1) && wrap && txtValue.length > 0) ? ' ' : '') + words[parseInt(i.toString(), 10)]; //Bug 885842: Position of annotation inside the node is not aligned center. //Extra space is added when we have single word as annotation text and due to this the width of the text is increased. if (words[i + 1]) { newText = txtValue + ' ' + (words[i + 1]); } else { newText = txtValue; } var width = bBoxText(newText, text); if (Math.floor(width) > (laneWidth || text.width) - 2 && txtValue.length > 0) { childNodes[childNodes.length] = { text: txtValue, x: 0, dy: 0, width: newText === txtValue ? width : (txtValue === existingText) ? existingWidth : bBoxText(txtValue, text) }; txtValue = ''; } else { if (i === words.length - 1) { childNodes[childNodes.length] = { text: txtValue, x: 0, dy: 0, width: width }; txtValue = ''; } } existingText = newText; existingWidth = width; } } return childNodes; } /** * wrapSvgTextAlign method \ * * @returns {TextBounds} wrapSvgTextAlign method .\ * @param { TextAttributes } text - provide the element value. * @param { string } childNodes - provide the maxWidth value. * @private */ function wrapSvgTextAlign(text, childNodes) { var wrapBounds = { x: 0, width: 0 }; var k = 0; var txtWidth; var width; for (k = 0; k < childNodes.length; k++) { txtWidth = childNodes[parseInt(k.toString(), 10)].width; width = txtWidth; //EJ2-863489 - Node annotation textAlign "Justify" option is not working correctly if (text.textAlign === 'left' || text.textAlign === 'justify') { txtWidth = 0; } else if (text.textAlign === 'center') { if (txtWidth > text.width && (text.textOverflow === 'Ellipsis' || text.textOverflow === 'Clip')) { txtWidth = 0; } else { txtWidth = -txtWidth / 2; } } else if (text.textAlign === 'right') { txtWidth = -txtWidth; } else { txtWidth = childNodes.length > 1 ? 0 : -txtWidth / 2; } childNodes[parseInt(k.toString(), 10)].dy = text.fontSize * 1.2; childNodes[parseInt(k.toString(), 10)].x = txtWidth; wrapBounds.x = Math.min(wrapBounds.x, txtWidth); wrapBounds.width = Math.max(wrapBounds.width, width); } return wrapBounds; } /** * measureHtmlText method \ * * @returns {TextBounds} measureHtmlText method .\ * @param { TextStyleModel } style - provide the style value. * @param { string } content - provide the content value. * @param { string } width - provide the width value. * @param { string } height - provide the height value. * @param { string } maxWidth - provide the maxWidth value. * @private */ export function measureHtmlText(style, content, width, height, maxWidth) { var bounds = new Size(); // 986032 - Annotation text field size updates incorrectly when the display style is set to flex on the body element var text = createHtmlElement('span', { 'style': 'position:absolute; display:inline-block; line-height:normal; left:0px; top:0px' }); if (style.bold) { text.style.fontWeight = 'bold'; } if (style.italic) { text.style.fontStyle = 'italic'; } if (width !== undefined) { text.style.width = width.toString() + 'px'; } if (height !== undefined) { text.style.height = height.toString() + 'px'; } if (maxWidth !== undefined) { text.style.maxWidth = maxWidth.toString() + 'px'; } text.style.fontFamily = style.fontFamily; text.style.fontSize = style.fontSize + 'px'; text.style.color = style.color; text.textContent = content; text.style.whiteSpace = whiteSpaceToString(style.whiteSpace, style.textWrapping); if (maxWidth !== undefined) { text.style.wordBreak = 'break-word'; } else { text.style.wordBreak = wordBreakToString(style.textWrapping); } document.body.appendChild(text); bounds.width = text.offsetWidth; bounds.height = text.offsetHeight; document.body.removeChild(text); return bounds; } /** * measureText method \ * * @returns {Size} measureText method .\ * @param { TextStyleModel } text - provide the text value. * @param { string } style - provide the style value. * @param { string } content - provide the content value. * @param { number } maxWidth - provide the maxWidth value. * @param { string } textValue - provide the textValue value. * @private */ export function measureText(text, style, content, maxWidth, textValue) { var bounds = new Size(0, 0); var childNodes; var wrapBounds; var options = getTextOptions(text, maxWidth); text.childNodes = childNodes = wrapSvgText(options, textValue, text.isLaneOrientation ? maxWidth : undefined); text.wrapBounds = wrapBounds = wrapSvgTextAlign(options, childNodes); bounds.width = wrapBounds.width; if (text.wrapBounds.width >= maxWidth && options.textOverflow !== 'Wrap') { bounds.width = maxWidth; } bounds.height = childNodes.length * text.style.fontSize * 1.2; return bounds; } /** * measureImage method \ * * @returns {Size} measureImage method .\ * @param { string } source - provide the text value. * @param { Size } contentSize - provide the style value. * @param { string } id - provide the content value. * @param { Function } callback - provide the maxWidth value. * @private */ // eslint-disable-next-line export function measureImage(source, contentSize, id, callback) { var measureWindowElement = 'measureElement'; window["" + measureWindowElement].style.visibility = 'visible'; var imageElement = window["" + measureWindowElement].children[1]; imageElement.setAttribute('src', source); var bounds = imageElement.getBoundingClientRect(); var width = bounds.width; var height = bounds.height; contentSize = new Size(width, height); window["" + measureWindowElement].style.visibility = 'hidden'; var element = document.createElement('img'); element.setAttribute('src', source); setAttributeHtml(element, { id: id + 'sf-imageNode' }); element.style.display = 'none'; document.body.appendChild(element); // eslint-disable-next-line element.onload = function (event) { var loadedImage = event.currentTarget; if (callback) { callback(id, { width: loadedImage.width, height: loadedImage.height }); } }; return contentSize; } /* eslint-disable */ /** * measureNativeContent method \ * * @returns {Rect} measureNativeContent method .\ * @param { SVGElement } nativeContent - provide the text value. * @private */ export function measureNativeContent(nativeContent) { var measureWindowElement = 'measureElement'; var nativeSVG = window[measureWindowElement].children[2]; nativeSVG.appendChild(nativeContent); var bounds = nativeContent.getBoundingClientRect(); var svgBounds = nativeSVG.getBoundingClientRect(); var rect = bounds; rect.x = bounds.left - svgBounds.left; rect.y = bounds.top - svgBounds.top; nativeSVG.removeChild(nativeContent); return rect; } /** * measureNativeSvg method \ * * @returns {Rect} measureNativeSvg method .\ * @param { SVGElement } nativeContent - provide the text value. * @private */ export function measureNativeSvg(nativeContent) { var measureWindowElement = 'measureElement'; window[measureWindowElement].style.visibility = 'visible'; var nativeSVG = window[measureWindowElement].children[2]; nativeSVG.appendChild(nativeContent); // eslint-disable-next-line @typescript-eslint/no-explicit-any var svgBounds = nativeSVG.getBoundingClientRect(); nativeSVG.removeChild(nativeContent); window[measureWindowElement].style.visibility = 'hidden'; return svgBounds; } /** * updatePath method \ * * @returns {string} updatePath method .\ * @param { SVGElement } element - provide the element value. * @param { Rect } bounds - provide the bounds value. * @param { PathElement } child - provide the child value. * @param { BaseAttributes } options - provide the options value. * @private */ export function updatePath(element, bounds, child, options) { var initX = 0; var initY = 0; var scaleX = 0; var scaleY = 0; var isScale = false; var newPathString = ''; var arrayCollection = []; var bBox = bounds; if (initX !== bBox.x || initY !== bBox.y) { scaleX = initX - Number(bBox.x); scaleY = initY - Number(bBox.y); } if (element.actualSize.width !== bBox.width || element.actualSize.height !== bBox.height || options) { scaleX = (options && options.width || element.actualSize.width) / Number(bBox.width ? bBox.width : 1); scaleY = (options && options.height || element.actualSize.height) / Number(bBox.height ? bBox.height : 1); isScale = true; } arrayCollection = processPathData(element.data); arrayCollection = splitArrayCollection(arrayCollection); newPathString = transformPath(arrayCollection, scaleX, scaleY, isScale, bBox.x, bBox.y, initX, initY); isScale = false; return newPathString; } /** * getDiagramLayerSvg method \ * * @returns {string} getDiagramLayerSvg method .\ * @param { string } diagramId - provide the element value. * @private */ export function getDiagramLayerSvg(diagramId) { //let diagramLayerSvg: SVGSVGElement; var diagramElement = getDiagramElement(diagramId); // eslint-disable-next-line @typescript-eslint/no-explicit-any var elementcoll = diagramElement.getElementsByClassName('e-diagram-layer'); var diagramLayerSvg = elementcoll[0]; return diagramLayerSvg; } /** * getDiagramElement method \ * * @returns {HTMLElement} getDiagramElement method .\ * @param { string } elementId - provide the elementId value. * @param { string } contentId - provide the elementId value. * @private */ export function getDiagramElement(elementId, contentId) { var diagramElement; var element; if (contentId) { element = document.getElementById(contentId); } if (Browser.info.name === 'msie' || Browser.info.name === 'edge') { diagramElement = (element) ? element.querySelector('#' + elementId) : document.getElementById(elementId); } else { diagramElement = (element) ? element.querySelector('#' + CSS.escape(elementId)) : document.getElementById(elementId); } return diagramElement; } /** * getDomIndex method \ * * @returns {HTMLElement} getDomIndex method .\ * @param { string } viewId - provide the elementId value. * @param { string } elementId - provide the elementId value. * @param { string } layer - provide the elementId value. * @private */ export function getDomIndex(viewId, elementId, layer) { var index; var parentElement; var postId = ''; if (layer === 'native') { parentElement = getNativeLayer(viewId); postId = '_content_groupElement'; } else if (layer === 'html') { parentElement = getHTMLLayer(viewId).childNodes[0]; postId = '_html_element'; } else { parentElement = getDiagramLayer(viewId); postId = '_groupElement'; } var targetId = elementId + postId; var targetElement = document.getElementById(targetId); if (targetElement && parentElement.contains(targetElement)) { return Array.prototype.indexOf.call(parentElement.childNodes, targetElement); } return index; } /** * getAdornerLayerSvg method \ * * @returns {SVGSVGElement} getAdornerLayerSvg method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getAdornerLayerSvg(diagramId) { var adornerLayerSvg = null; var diagramElement = getDiagramElement(diagramId); // eslint-disable-next-line @typescript-eslint/no-explicit-any var elementcoll = diagramElement.getElementsByClassName('e-adorner-layer'); adornerLayerSvg = elementcoll[0]; return adornerLayerSvg; } /** * getSelectorElement method \ * * @returns {SVGSVGElement} getSelectorElement method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getSelectorElement(diagramId) { var adornerLayer = null; var adornerSvg = getAdornerLayerSvg(diagramId); adornerLayer = adornerSvg.getElementById(diagramId + '_SelectorElement'); return adornerLayer; } /** * getAdornerLayer method \ * * @returns {SVGSVGElement} getAdornerLayer method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getAdornerLayer(diagramId) { var adornerLayer = null; var diagramAdornerSvg = getAdornerLayerSvg(diagramId); adornerLayer = diagramAdornerSvg.getElementById(diagramId + '_diagramAdorner'); return adornerLayer; } /** * getUserHandleLayer method \ * * @returns {HTMLElement} getUserHandleLayer method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getUserHandleLayer(diagramId) { var adornerLayer = null; var diagramUserHandleLayer = getDiagramElement(diagramId); // eslint-disable-next-line @typescript-eslint/no-explicit-any var elementcoll = diagramUserHandleLayer.getElementsByClassName('e-userHandle-layer'); adornerLayer = elementcoll[0]; return adornerLayer; } /** * getDiagramLayer method \ * * @returns {HTMLElement} getDiagramLayer method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getDiagramLayer(diagramId) { //let diagramLayer: SVGElement; var diagramLayerSvg = getDiagramLayerSvg(diagramId); var diagramLayer = diagramLayerSvg.getElementById(diagramId + '_diagramLayer'); return diagramLayer; } /** * getPortLayerSvg method \ * * @returns {SVGSVGElement} getPortLayerSvg method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getPortLayerSvg(diagramId) { var adornerLayerSvg = null; var diagramElement = getDiagramElement(diagramId); // eslint-disable-next-line @typescript-eslint/no-explicit-any var elementcoll = diagramElement.getElementsByClassName('e-ports-expand-layer'); adornerLayerSvg = elementcoll[0]; return adornerLayerSvg; } /** * getNativeLayerSvg method \ * * @returns {SVGSVGElement} getNativeLayerSvg method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getNativeLayerSvg(diagramId) { var nativeLayerSvg; var diagramElement = getDiagramElement(diagramId); // eslint-disable-next-line @typescript-eslint/no-explicit-any var elementcoll = diagramElement.getElementsByClassName('e-native-layer'); nativeLayerSvg = elementcoll[0]; return nativeLayerSvg; } /** * getGridLayerSvg method \ * * @returns {SVGSVGElement} getNativeLayerSvg method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getGridLayerSvg(diagramId) { var gridLayerSvg = null; var diagramElement = getDiagramElement(diagramId); // eslint-disable-next-line @typescript-eslint/no-explicit-any var elementcoll = diagramElement.getElementsByClassName('e-grid-layer'); gridLayerSvg = elementcoll[0]; return gridLayerSvg; } /** * getBackgroundLayerSvg method \ * * @returns {SVGSVGElement} getBackgroundLayerSvg method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getBackgroundLayerSvg(diagramId) { var gridLayerSvg = null; var diagramElement = getDiagramElement(diagramId); // eslint-disable-next-line @typescript-eslint/no-explicit-any var elementcoll = diagramElement.getElementsByClassName('e-background-layer'); return elementcoll[0].parentNode; } /** * getBackgroundImageLayer method \ * * @returns {SVGSVGElement} getBackgroundImageLayer method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getBackgroundImageLayer(diagramId) { var imageLayer = null; var diagramElement = getDiagramElement(diagramId); // eslint-disable-next-line @typescript-eslint/no-explicit-any var elementcoll = diagramElement.getElementsByClassName('e-background-image-layer'); imageLayer = elementcoll[0]; return imageLayer; } /** * getBackgroundLayer method \ * * @returns {SVGSVGElement} getBackgroundLayer method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getBackgroundLayer(diagramId) { var imageLayer = null; var diagramElement = getDiagramElement(diagramId); // eslint-disable-next-line @typescript-eslint/no-explicit-any var elementcoll = diagramElement.getElementsByClassName('e-background-layer'); imageLayer = elementcoll[0]; return imageLayer; } /** * getGridLayer method \ * * @returns {SVGSVGElement} getGridLayer method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getGridLayer(diagramId) { var domTable = 'domTable'; var expandCollapse = null; if (!window[domTable][diagramId + '_gridline']) { var diagramGridSvg = getGridLayerSvg(diagramId); expandCollapse = diagramGridSvg.getElementById(diagramId + '_gridline'); window[domTable][diagramId + '_gridline'] = expandCollapse; } else { expandCollapse = window[domTable][diagramId + '_gridline']; } return expandCollapse; } // /** @private */ // export function getExpandCollapseLayer(diagramId: string): SVGElement { // let expandCollapse: SVGElement = null; // let diagramPortSvg: SVGSVGElement = getPortLayerSvg(diagramId); // expandCollapse = diagramPortSvg.getElementById(diagramId + '_diagramExpander') as SVGElement; // return expandCollapse; // } // /** @private */ // export function getPortsLayer(diagramId: string): SVGElement { // let expandCollapse: SVGElement = null; // let diagramPortSvg: SVGSVGElement = getPortLayerSvg(diagramId); // expandCollapse = diagramPortSvg.getElementById(diagramId + '_diagramPorts') as SVGElement; // return expandCollapse; // } /** * getNativeLayer method \ * * @returns {SVGSVGElement} getNativeLayer method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getNativeLayer(diagramId) { var nativeLayer = null; var nativeLayerSvg = getNativeLayerSvg(diagramId); nativeLayer = nativeLayerSvg.getElementById(diagramId + '_nativeLayer'); return nativeLayer; } /** * getHTMLLayer method \ * * @returns {SVGSVGElement} getHTMLLayer method .\ * @param { string } diagramId - provide the diagramId value. * @private */ export function getHTMLLayer(diagramId) { var htmlLayer = null; var domTable = 'domTable'; if (!window[domTable][diagramId + 'html_layer']) { var element = getDiagramElement(diagramId); // eslint-disable-next-line @typescript-eslint/no-explicit-any var elementcoll = element.getElementsByClassName('e-html-layer'); htmlLayer = elementcoll[0]; window[domTable][diagramId + 'html_layer'] = htmlLayer; } else { htmlLayer = window[domTable][diagramId + 'html_layer']; } return htmlLayer; } /* eslint-enable */ /** * createHtmlElement method \ * * @returns {SVGSVGElement} createHtmlElement method .\ * @param { string } elementType - provide the diagramId value. * @param { Object } attribute - provide the diagramId value. * @private */ export function createHtmlElement(elementType, attribute) { var element = createElement(elementType); setAttributeHtml(element, attribute); return element; } /** * createSvgElement method \ * * @returns {SVGSVGElement} createSvgElement method .\ * @param { string } elementType - provide the elementType value. * @param { Object } attribute - provide the attribute value. * @private */ export function createSvgElement(elementType, attribute) { var element = document.createElementNS('http://www.w3.org/2000/svg', elementType); setAttributeSvg(element, attribute); return element; } /** @hidden */ /** * parentsUntil method \ * * @returns {SVGSVGElement} parentsUntil method .\ * @param { Element } elem - provide the elementType value. * @param { string } selector - provide the attribute value. * @param { boolean } isID - provide the attribute value. * @private */ export function parentsUntil(elem, selector, isID) { var parent = elem; while (parent) { if (isID ? parent.id === selector : hasClass(parent, selector)) { break; } parent = parent.parentNode; } return parent; } /** * hasClass method \ * * @returns {SVGSVGElement} hasClass method .\ * @param { HTMLElement } element - provide the element value. * @param { string } className - provide the className value. * @private */ export function hasClass(element, className) { var eClassName = (typeof element.className === 'object') ? element.className.animVal : element.className; return ((' ' + eClassName + ' ').indexOf(' ' + className + ' ') > -1) ? true : false; } /** * getScrollerWidth method \ * * @returns {number} getScrollerWidth method .\ * @private */ export function getScrollerWidth() { var outer = createHtmlElement('div', { 'style': 'visibility:hidden; width: 100px' }); document.body.appendChild(outer); var widthNoScroll = outer.getBoundingClientRect().width; // force scrollbars outer.style.overflow = 'scroll'; // add innerdiv var inner = createHtmlElement('div', { 'style': 'width:100%' }); outer.appendChild(inner); var widthWithScroll = inner.getBoundingClientRect().width; // remove divs outer.parentNode.removeChild(outer); return widthNoScroll - widthWithScroll; } /** * addTouchPointer method \ * * @returns {ITouches[]} addTouchPointer method .\ * @param { ITouches[] } touchList - provide the touchList value. * @param { PointerEvent } e - provide the e value. * @param { TouchList } touches - provide the touches value. * @private */ export function addTouchPointer(touchList, e, touches) { touchList = []; for (var i = 0, length_1 = touches.length; i < length_1; i++) { touchList.push({ pageX: touches[parseInt(i.toString(), 10)].clientX, pageY: touches[parseInt(i.toString(), 10)].clientY, pointerId: null }); } return touchList; } /** * removes the element from dom \ * * @returns {void} removes the element from dom .\ * @param { ITouches[] } elementId - provide the elementId value. * @param { PointerEvent } contentId - provide the contentId value. * @private */ export function removeElement(elementId, contentId) { var div = getDiagramElement(elementId, contentId); if (div) { div.parentNode.removeChild(div); } } /** * getContent method \ * * @returns {void} getContent method .\ * @param { DiagramHtmlElement | DiagramNativeElement } element - provide the elementId value. * @param { boolean } isHtml - provide the boolean value. * @param { Node | Annotation | PathAnnotation | NodeFixedUserHandle | ConnectorFixedUserHandle } nodeObject - provide the nodeObject value. * @private */ export function getContent(element, isHtml, nodeObject) { var div; /* eslint-disable */ if (isHtml) { var attr = { 'style': 'height: 100%; width: 100%' }; div = createHtmlElement('div', attr); } else { div = document.createElementNS('http://www.w3.org/2000/svg', 'g'); } var diagramElement = document.getElementById(element.diagramId); var instance = 'ej2_instances'; var diagram = diagramElement[instance][0]; var node; if (!diagram.initNodeTemplate || !(diagram instanceof Diagram)) { node = getElement(element); } var content = ''; var sentNode = {}; var isSvg = false; var propertyName; if ((!node && diagram.initNodeTemplate)) { sentNode = sentNode = (diagram.tempTable && diagram.tempTable[element.nodeId]) || sentNode; propertyName = "nodeTemplate"; } else if (node instanceof Node) { sentNode = node; ////Removed svg content re-assign from outerHtml to improve performance. //let blazor: string = 'Blazor'; //Removed isBlazor code propertyName = "nodeTemplate"; } else { sentNode = node; //new //Removed isBlazor code propertyName = "annotationTemplate"; } var item; if ((typeof element.content === 'string' || typeof element.content === 'function') && (!element.isTemplate)) { var template = document.getElementById(element.content); if (template) { div.appendChild(template); } else { /* eslint-disable */ var compiledString = void 0; compiledString = compile(element.content); for (var _i = 0, _a = compiledString(sentNode, diagram, propertyName, content); _i < _a.length; _i++) { item = _a[_i]; div.appendChild(item); } //new // for (item of compiledString(sentNode, null, null, content, undefined, undefined, isSvg)) { // div.appendChild(item); // } } } else if (element.isTemplate) { var compiledString = void 0; if (diagram.isReact) { compiledString = element.getNodeTemplate()( /* eslint-enable */ // eslint-disable-next-line quotes cloneObject(nodeObject), diagram, propertyName + "_" + ((propertyName === "nodeTemplate") ? nodeObject.id : element.nodeId + nodeObject.id), undefined, undefined, false, div); } else if (diagram.isVue || diagram.isVue3) { // EJ2-57563 - Added the below code to provide slot template support for Vue and Vue 3 var templateFn = element.getNodeTemplate(); if (templateFn) { // If other than slot template, this if block gets execute and template get returned. compiledString = element.getNodeTemplate()( /* eslint-enable */ // eslint-disable-next-line quotes cloneObject(nodeObject), diagram, propertyName + "_" + ((propertyName === "nodeTemplate") ? nodeObject.id : element.nodeId + nodeObject.id), undefined, undefined, false, div); } else { // If we provide slot template means then it enters in this block and returns a template if (propertyName === 'nodeTemplate') { compiledString = compile(diagram.nodeTemplate); } else { compiledString = compile(diagram.annotationTemplate); } compiledString = compiledString( /* eslint-enable */ // eslint-disable-next-line quotes cloneObject(nodeObject), diagram, propertyName + "_" + ((propertyName === "nodeTemplate") ? nodeObject.id : element.nodeId + nodeObject.id), undefined, undefined, false, div); } } else { compiledString = element.getNodeTemplate()( /* eslint-enable */ // eslint-disable-next-line quotes cloneObject(nodeObject), diagram, propertyName + "_" + ((propertyName === "nodeTemplate") ? nodeObject.id : element.nodeId + nodeObject.id), undefined, undefined, false); } if (compiledString) { for (var i = 0; i < compiledString.length; i++) { div.appendChild(compiledString[parseInt(i.toString(), 10)]); } } } else { if (element.content && element.content.outerHTML) { div.appendChild(element.content); } } return element.isTemplate ? div : (isHtml ? div.cloneNode(true) : div.cloneNode(true)); } /* eslint-enable */ /** * setAttributeSvg method \ * * @returns {void} setAttributeSvg method .\ * @param { SVGElement } svg - provide the svg value. * @param { Object } attributes - provide the boolean value. * @private */ export function setAttributeSvg(svg, attributes) { var keys = Object.keys(attributes); for (var i = 0; i < keys.length; i++) { // Added below condition to check whether svg is undefined or not if (svg && keys[parseInt(i.toString(), 10)] !== 'style') { svg.setAttribute(keys[parseInt(i.toString(), 10)], attributes[keys[parseInt(i.toString(), 10)]]); } else { applyStyleAgainstCsp(svg, attributes[keys[parseInt(i.toString(), 10)]]); } } } /** * applyStyleAgainstCsp method \ * * @returns {void} applyStyleAgainstCsp method .\ * @param { SVGElement } svg - provide the svg value. * @param { string } attributes - provide the boolean value. * @private */ export function applyStyleAgainstCsp(svg, attributes) { var keys = attributes.split(';'); for (var i = 0; i < keys.length; i++) { var attribute = keys[parseInt(i.toString(), 10)].split(':'); if (attribute.length === 2) { svg.style[attribute[0].trim()] = attribute[1].trim(); } } } /** * setAttributeHtml method \ * * @returns {void} setAttributeHtml method .\ * @param { HTMLElement } element - provide the svg value. * @param { Object } attributes - provide the boolean value. * @private */ export function setAttributeHtml(element, attributes) { var keys = Object.keys(attributes); for (var i = 0; i < keys.length; i++) { if (keys[parseInt(i.toString(), 10)] !== 'style') { element.setAttribute(keys[parseInt(i.toString(), 10)], attributes[keys[parseInt(i.toString(), 10)]]); } else { applyStyleAgainstCsp(element, attributes[keys[parseInt(i.toString(), 10)]]); } } } /** * createMeasureElements method \ * * @returns {void} createMeasureElements method .\ * @private */ export function createMeasureElements() { var measureWindowElement = 'measureElement'; if (!window["" + measureWindowElement]) { var divElement = createHtmlElement('div', { id: 'measureElement', style: 'visibility:hidden ; height: 0px ; width: 0px; overflow: hidden;' }); var text = createHtmlElement('span', { 'style': 'display:inline-block ; line-height: normal' }); divElement.appendChild(text); //let imageElement: HTMLImageElement; var imageElement = createHtmlElement('img', { 'alt': 'measureElementImage', 'src': 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' }); divElement.appendChild(imageElement); var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink'); divElement.appendChild(svg); var element = document.createElementNS('http://www.w3.org/2000/svg', 'path'); element.setAttribute('d', ''); svg.appendChild(element); // eslint-disable-next-line @typescript-eslint/no-unused-vars var data = document.createTextNode(''); var tSpan = document.createElementNS('http://www.w3.org/2000/svg', 'text'); tSpan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); svg.appendChild(tSpan); window["" + measureWindowElement] = divElement; window["" + measureWindowElement].usageCount = 1; document.body.appendChild(divElement); var measureElementCount = 'measureElementCount'; if (!window["" + measureElementCount]) { window["" + measureElementCount] = 1; } else { window["" + measureElementCount]++; } } else { window["" + measureWindowElement].usageCount += 1; } } /** * setChildPosition method \ * * @returns {number} setChildPosition method .\ * @param {SubTextElement} temp - provide the temp value. * @param {SubTextElement[]} childNodes - provide the childNodes value. * @param {number} i - provide the i value. * @param {TextAttributes} options - provide the options value. * @private */ export function setChildPosition(temp, childNodes, i, options) { if (childNodes.length >= 1 && temp.x === 0 && (options.textOverflow === 'Clip' || options.textOverflow === 'Ellipsis') && (options.textWrapping === 'Wrap' || options.textWrapping === 'WrapWithOverflow')) { temp.x = childNodes[i - 1] ? childNodes[i - 1].x : -(temp.width / 2); return temp.x; } return temp.x; } /** * getTemplateContent method\ * * @returns {DiagramHtmlElement} getTemplateContent method .\ * @param {DiagramHtmlElement} annotationcontent - provide the annotationcontent value. * @param {Annotation} annotation - provide the annotation value. * @param {number} annotationTemplate - provide the annotationTemplate value. * @param {Object} diagram - provide the diagram value. * @private */ export function getTemplateContent( // eslint-disable-next-line @typescript-eslint/ban-types annotationcontent, annotation, annotationTemplate, diagram) { if ((annotationTemplate && !annotation.template) || (annotation.template && typeof annotation.template === 'function' && diagram.isReact)) { annotationcontent.isTemplate = true; annotationcontent.template = annotationcontent.content = getContent(annotationcontent, true, annotation); } else { annotationcontent.content = annotation.template; } return annotationcontent; } /* eslint-disable */ /** @private */ export function createUserHandleTemplates(userHandleTemplate, template, selectedItems, diagramID) { var userHandleFn; var handle; var compiledString; var i; var div; var diagramElement = document.getElementById(diagramID); var instance = 'ej2_instances'; var diagram = diagramElement[instance][0]; if (userHandleTemplate && template) { userHandleFn = templateCompiler(userHandleTemplate); for (var _i = 0, _a = selectedItems.userHandles; _i < _a.length; _i++) { handle = _a[_i]; if (userHandleFn) { compiledString = userHandleFn(cloneObject(handle), diagram, 'userHandleTemplate' + '_' + handle.name, undefined, undefined, false); for (i = 0; i < compiledString.length; i++) { var attr = { 'style': 'height: 100%; width: 100%; pointer-events: all', 'id': handle.name + '_template_hiddenUserHandle' }; div = createHtmlElement('div', attr); div.appendChild(compiledString[i]); } template[0].appendChild(div); } } } //Removed isBlazor code } /* eslint-enable */