Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,28 @@
# ej2-showcase-js-json-xml-to-diagram-visualizer
A JSON/XML-to-Diagram Visualizer converts JSON or XML data into interactive diagrams, helping users easily understand data structures, hierarchies, and relationships visually
# Essential® JS 2 for JavaScript - JSON and XML to Diagram Visualizer

A JSON/XML-to-Diagram Visualizer converts JSON or XML data into interactive diagrams, helping users easily understand data structures, hierarchies, and relationships visually.


## Deployment

### Install

* To install all dependent packages, use the below command.

```
npm install
```

### Run

To run the sample, use the below command

```
npm start
```

## Demo

#### <a href="https://ej2.syncfusion.com/showcase/javascript/jsonandxmltodiagramvisualizer/" target="_blank">https://ej2.syncfusion.com/showcase/javascript/jsonandxmltodiagramvisualizer/</a>

Check all the showcase and tutorial samples from <a href="https://ej2.syncfusion.com/home/javascript.html" target="_blank">here</a>.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"terser-webpack-plugin": "^5.3.9",
"webpack": "^5.88.1",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.2.1"
"webpack-dev-server": "^4.15.1"
},
"dependencies": {
"fast-xml-parser": "^5.2.3",
Expand Down
75 changes: 37 additions & 38 deletions src/hamburger-menu.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,46 @@
// Enable ripple effect for UI components
ej.base.enableRipple(true);

export function initHamburgerMenu(getGraphCollapseState) {
// Define menu items configuration with text, id, and icon properties
const hamburgerMenuItems = [
{ text: 'Export as Image', id: 'exportImage', iconCss: 'e-icons e-export' },
{ text: 'Rotate Layout', id: 'rotateLayout', iconCss: 'e-icons e-refresh' },
{ text: 'Collapse Graph', id: 'collapseGraph', iconCss: 'e-icons e-collapse-2' }
];

// Initialize dropdown button component with menu configuration
const hamburgerDropdownButton = new ej.splitbuttons.DropDownButton({
iconCss: 'e-icons e-menu',
cssClass: 'e-caret-hide',
items: hamburgerMenuItems,
// Handle menu item selection and dispatch corresponding events
select: function(menuSelectionArgs) {
switch (menuSelectionArgs.item.id) {
case 'exportImage':
window.dispatchEvent(new CustomEvent('exportImage'));
break;
case 'rotateLayout':
window.dispatchEvent(new CustomEvent('rotateLayout'));
break;
case 'collapseGraph':
window.dispatchEvent(new CustomEvent('collapseGraph'));
updateCollapseMenuText();
break;
}
}
});
// Toggle menu text and icon based on current graph collapse state
export function updateCollapseMenuText(isGraphCollapsed) {
const isCurrentlyCollapsed = isGraphCollapsed;
const collapseMenuItem = hamburgerMenuItems.find(menuItem => menuItem.id === 'collapseGraph');
if (collapseMenuItem) {
collapseMenuItem.text = isCurrentlyCollapsed ? 'Expand Graph' : 'Collapse Graph';
collapseMenuItem.iconCss = isCurrentlyCollapsed ? 'e-icons e-expand' : 'e-icons e-collapse-2';
hamburgerDropdownButton.items = hamburgerMenuItems;
hamburgerDropdownButton.dataBind();
}
}
// Define menu items configuration with text, id, and icon properties
const hamburgerMenuItems = [
{ text: 'Export as Image', id: 'exportImage', iconCss: 'e-icons e-export' },
{ text: 'Rotate Layout', id: 'rotateLayout', iconCss: 'e-icons e-refresh' },
{ text: 'Collapse Graph', id: 'collapseGraph', iconCss: 'e-icons e-collapse-2' }
];

// Toggle menu text and icon based on current graph collapse state
function updateCollapseMenuText() {
const isCurrentlyCollapsed = getGraphCollapseState();
const collapseMenuItem = hamburgerMenuItems.find(menuItem => menuItem.id === 'collapseGraph');
if (collapseMenuItem) {
collapseMenuItem.text = isCurrentlyCollapsed ? 'Expand Graph' : 'Collapse Graph';
collapseMenuItem.iconCss = isCurrentlyCollapsed ? 'e-icons e-expand' : 'e-icons e-collapse-2';
hamburgerDropdownButton.items = hamburgerMenuItems;
hamburgerDropdownButton.dataBind();
// Initialize dropdown button component with menu configuration
const hamburgerDropdownButton = new ej.splitbuttons.DropDownButton({
iconCss: 'e-icons e-menu',
cssClass: 'e-caret-hide',
items: hamburgerMenuItems,
// Handle menu item selection and dispatch corresponding events
select: function (menuSelectionArgs) {
switch (menuSelectionArgs.item.id) {
case 'exportImage':
window.dispatchEvent(new CustomEvent('exportImage'));
break;
case 'rotateLayout':
window.dispatchEvent(new CustomEvent('rotateLayout'));
break;
case 'collapseGraph':
window.dispatchEvent(new CustomEvent('collapseGraph'));
updateCollapseMenuText(false);
break;
}
}
});
export function initHamburgerMenu(getGraphCollapseState) {

// Append the hamburger menu to the designated DOM element
hamburgerDropdownButton.appendTo('#hamburger-menu');
Expand Down
31 changes: 26 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { initToolBar } from "./toolbar.js";
import { initExportDetailsDialog } from "./export-details-dialog.js";
import * as monaco from "monaco-editor";
import { XMLBuilder, XMLParser } from "fast-xml-parser";
import { updateCollapseMenuText } from "./hamburger-menu.js";

// Inject required modules into the diagram
ej.diagrams.Diagram.Inject(
Expand Down Expand Up @@ -134,6 +135,8 @@ function handleEditorContentChange() {
updateEditorStatus(false);
showSpinner();
}
isGraphCollapsed = false;
updateCollapseMenuText(isGraphCollapsed);
}

// Initializes and configures the diagram including nodes, connectors, and layout settings
Expand All @@ -159,6 +162,7 @@ function initializeDiagram() {
scrollSettings: { scrollLimit: "Infinity" },
getNodeDefaults: getNodeDefaults,
getConnectorDefaults: getConnectorDefaults,
expandStateChange: handleExpandStateChange
});
diagram.appendTo("#diagram");
}
Expand Down Expand Up @@ -353,8 +357,8 @@ function configureParentNodeAnnotations(
left: showChildItemsCount
? annotationMargin
: showExpandCollapseIcon
? -annotationMargin
: 0,
? -annotationMargin
: 0,
};
keyAnnotation.horizontalAlignment = showChildItemsCount ? "Left" : "Center";

Expand Down Expand Up @@ -432,6 +436,19 @@ function getConnectorDefaults(connector) {
connector.targetDecorator = { shape: "None" };
return connector;
}
// To handle expand and collapse
function handleExpandStateChange(args) {
const node = args.element;
if (!node || typeof node !== 'object') {
return;
}
// Check if it's a root node (no incoming edges)
const isRootNode = !node.inEdges || node.inEdges.length === 0;
if (isRootNode) {
isGraphCollapsed = !node.isExpanded;
updateCollapseMenuText(isGraphCollapsed);
}
};

// Calculates and returns the size of the node based on its content
function calculateNodeSize(
Expand Down Expand Up @@ -868,7 +885,7 @@ document.addEventListener("fileAction", function (fileActionEvent) {
if (fileAction === "import") {
importFromFile()
.then((importedFileContent) => {
try {
try {
editor.setValue(importedFileContent); // Update the Monaco editor with imported content

let processedDiagramData;
Expand Down Expand Up @@ -925,7 +942,7 @@ function importFromFile() {
const fileReader = new FileReader();
fileReader.onload = (fileLoadEvent) => {
resolve(fileLoadEvent.target.result);
};
};
fileReader.onerror = () => {
reject("Error reading the file");
};
Expand Down Expand Up @@ -970,10 +987,12 @@ document.addEventListener("viewOptionToggled", function (viewOptionEvent) {
break;
case "view-count":
showChildItemsCount = !showChildItemsCount;
diagram.fitToPage({ mode: "Page", region: "Content", canZoomIn: true });
diagram.refresh();
break;
case "expand-collapse":
showExpandCollapseIcon = !showExpandCollapseIcon;
diagram.fitToPage({ mode: "Page", region: "Content", canZoomIn: true });
diagram.refresh();
break;
}
Expand Down Expand Up @@ -1090,7 +1109,7 @@ document.addEventListener("editorTypeChanged", (editorTypeChangeEvent) => {
jsonToXmlObject
); // Process the original JSON data using JsonDiagramParser
updateEditorStatus(true); // Update editor status to valid
}
}
} catch (conversionError) {
console.error("Parsing Error:", conversionError); // Log parsing errors
updateEditorStatus(false); // Update status to invalid on error
Expand All @@ -1103,4 +1122,6 @@ document.addEventListener("editorTypeChanged", (editorTypeChangeEvent) => {
convertedDiagramData.connectors
);
}
isGraphCollapsed = false;
updateCollapseMenuText(isGraphCollapsed);
});