$(function () {
let generatedID = 100;
const store = new DevExpress.data.ArrayStore({
key: 'ID',
data: employees,
onInserting(values) {
values.ID = values.ID || (generatedID += 1);
values.Full_Name = values.Full_Name || "Employee's Name";
values.Title = values.Title || "Employee's Title";
},
});
$('#diagram').dxDiagram({
customShapes: [{
type: 'employee',
category: 'employee',
baseType: 'rectangle',
title: 'New Employee',
defaultWidth: 1.5,
defaultHeight: 1,
toolboxWidthToHeightRatio: 2,
minWidth: 1.5,
minHeight: 1,
maxWidth: 3,
maxHeight: 2,
allowEditText: false,
}],
customShapeTemplate(item, $container) {
const employee = item.dataItem;
const svgNS = 'http://www.w3.org/2000/svg';
const $content = $(document.createElementNS(svgNS, 'svg')).addClass('template');
$(document.createElementNS(svgNS, 'text'))
.addClass('template-name')
.attr({ x: '50%', y: '20%' })
.text(employee ? employee.Full_Name : "Employee's Name")
.appendTo($content);
$(document.createElementNS(svgNS, 'text'))
.addClass('template-title')
.attr({ x: '50%', y: '45%' })
.text(employee ? employee.Title : "Employee's Title")
.appendTo($content);
$(document.createElementNS(svgNS, 'text'))
.addClass('template-button')
.attr({ id: 'employee-edit', x: '40%', y: '85%' })
.text('Edit')
.click(() => { editEmployee(employee); })
.appendTo($content);
$(document.createElementNS(svgNS, 'text'))
.addClass('template-button')
.attr({ id: 'employee-delete', x: '62%', y: '85%' })
.text('Delete')
.click(() => { deleteEmployee(employee); })
.appendTo($content);
$container.append($content);
},
customShapeToolboxTemplate(item, $container) {
const $content = $("<svg class='template'>"
+ "<text x='50%' y='40%'>New</text>"
+ "<text x='50%' y='70%'>Employee</text>"
+ '</svg >');
$container.append($content);
},
nodes: {
dataSource: store,
keyExpr: 'ID',
typeExpr() { return 'employee'; },
parentKeyExpr: 'Head_ID',
customDataExpr(obj, value) {
if (value === undefined) {
return {
Full_Name: obj.Full_Name,
Prefix: obj.Prefix,
Title: obj.Title,
City: obj.City,
State: obj.State,
Email: obj.Email,
Skype: obj.Skype,
Mobile_Phone: obj.Mobile_Phone,
};
}
obj.Full_Name = value.Full_Name;
obj.Prefix = value.Prefix;
obj.Title = value.Title;
obj.City = value.City;
obj.State = value.State;
obj.Email = value.Email;
obj.Skype = value.Skype;
obj.Mobile_Phone = value.Mobile_Phone;
return null;
},
autoLayout: {
type: 'tree',
},
},
onRequestLayoutUpdate(e) {
for (let i = 0; i < e.changes.length; i += 1) {
if (e.changes[i].type === 'remove') {
e.allowed = true;
} else if (e.changes[i].data.Head_ID !== undefined && e.changes[i].data.Head_ID !== null) {
e.allowed = true;
}
}
},
contextToolbox: {
shapeIconsPerRow: 1,
width: 100,
},
toolbox: {
shapeIconsPerRow: 1,
showSearch: false,
groups: [
{ category: 'employee', title: 'Employee', expanded: true },
],
},
propertiesPanel: {
tabs: [
{
groups: [{ title: 'Page Properties', commands: ['pageSize', 'pageOrientation', 'pageColor'] }],
},
],
},
}).dxDiagram('instance');
const popupContentTemplate = function ($container) {
const $editorsContainer = $('<div class="dx-fieldset" />').appendTo($container);
const $nameField = $('<div class="dx-field"><div class="dx-field-label">Name</div><div class="dx-field-value" data-field="Full_Name" /></div>');
$nameField.find('.dx-field-value').append('<div />').dxTextBox();
const $titleField = $('<div class="dx-field"><div class="dx-field-label">Title</div><div class="dx-field-value" data-field="Title" /></div>');
$titleField.find('.dx-field-value').append('<div /').dxTextBox();
const $cityField = $('<div class="dx-field"><div class="dx-field-label">City</div><div class="dx-field-value" data-field="City" /></div>');
$cityField.find('.dx-field-value').append('<div /').dxTextBox();
const $stateField = $('<div class="dx-field"><div class="dx-field-label">State</div><div class="dx-field-value" data-field="State" /></div>');
$stateField.find('.dx-field-value').append('<div /').dxTextBox();
const $emailField = $('<div class="dx-field"><div class="dx-field-label">Email</div><div class="dx-field-value" data-field="Email" /></div>');
$emailField.find('.dx-field-value').append('<div /').dxTextBox();
const $skypeField = $('<div class="dx-field"><div class="dx-field-label">Skype</div><div class="dx-field-value" data-field="Skype" /></div>');
$skypeField.find('.dx-field-value').append('<div /').dxTextBox();
const $phoneField = $('<div class="dx-field"><div class="dx-field-label">Phone</div><div class="dx-field-value" data-field="Mobile_Phone" /></div>');
$phoneField.find('.dx-field-value').append('<div /').dxTextBox();
$editorsContainer.append(
$nameField,
$titleField,
$cityField,
$stateField,
$emailField,
$skypeField,
$phoneField,
);
const $buttonsContainer = $('<div class="dx-fieldset buttons" />').appendTo($container);
$buttonsContainer.append(
$('<button />').dxButton({
text: 'Update',
type: 'default',
onClick: updateEmployee,
}),
$('<button />').dxButton({
text: 'Cancel',
onClick: cancelEditEmployee,
}),
);
};
const popup = $('#popup').dxPopup({
width: 400,
height: 480,
showTitle: true,
title: 'Edit Employee',
visible: false,
dragEnabled: false,
contentTemplate: popupContentTemplate.bind(this),
}).dxPopup('instance');
let currentEmployee = {};
const editEmployee = function (employee) {
currentEmployee = { ...employee };
popup.show();
popup.content().find('.dx-field-value').each(function () {
const field = $(this).attr('data-field');
const edit = $(this).dxTextBox('instance');
edit.option({
value: currentEmployee[field],
onValueChanged(e) { handleChange(field, e.value); },
});
});
};
const deleteEmployee = function (employee) {
store.push([{ type: 'remove', key: employee.ID }]);
};
const updateEmployee = function () {
store.push([{
type: 'update',
key: currentEmployee.ID,
data: {
Full_Name: currentEmployee.Full_Name,
Title: currentEmployee.Title,
City: currentEmployee.City,
State: currentEmployee.State,
Email: currentEmployee.Email,
Skype: currentEmployee.Skype,
Mobile_Phone: currentEmployee.Mobile_Phone,
},
}]);
popup.hide();
};
const cancelEditEmployee = function () {
currentEmployee = {};
popup.hide();
};
const handleChange = function (field, value) {
currentEmployee[field] = value;
};
});
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>window.jQuery || document.write(decodeURIComponent('%3Cscript src="js/jquery.min.js"%3E%3C/script%3E'))</script>
<script src="https://cdn3.devexpress.com/jslib/23.1.6/js/dx-diagram.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/23.1.6/css/dx.light.css" />
<link rel="stylesheet" href="https://cdn3.devexpress.com/jslib/23.1.6/css/dx-diagram.css" />
<script src="https://cdn3.devexpress.com/jslib/23.1.6/js/dx.all.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css" />
<script src="data.js"></script>
<script src="index.js"></script>
</head>
<body class="dx-viewport">
<div class="demo-container">
<div id="diagram"> </div>
<div id="popup"> </div>
</div>
</body>
</html>
#diagram {
height: 725px;
}
#diagram .template .template-name {
font-weight: bold;
text-decoration: underline;
}
#diagram .template .template-title {
font-style: italic;
}
#diagram .template .template-button {
cursor: pointer;
font-size: 8pt;
fill: navy;
}
#diagram .template .template-button:hover {
text-decoration: underline;
}
.dx-popup-content {
padding: 0;
}
.dx-popup-content .dx-fieldset.buttons {
display: flex;
justify-content: flex-end;
}
.dx-popup-content .dx-fieldset.buttons > * {
margin-left: 8px;
}
const employees = [{
ID: 1,
Head_ID: 0,
Full_Name: 'John Heart',
Prefix: 'Mr.',
Title: 'CEO',
City: 'Los Angeles',
State: 'California',
Email: 'jheart@dx-email.com',
Skype: 'jheart_DX_skype',
Mobile_Phone: '(213) 555-9392',
Birth_Date: '1964-03-16',
Hire_Date: '1995-01-15',
}, {
ID: 2,
Head_ID: 1,
Full_Name: 'Samantha Bright',
Prefix: 'Dr.',
Title: 'COO',
City: 'Los Angeles',
State: 'California',
Email: 'samanthab@dx-email.com',
Skype: 'samanthab_DX_skype',
Mobile_Phone: '(213) 555-2858',
Birth_Date: '1966-05-02',
Hire_Date: '2004-05-24',
}, {
ID: 3,
Head_ID: 1,
Full_Name: 'Arthur Miller',
Prefix: 'Mr.',
Title: 'CTO',
City: 'Denver',
State: 'Colorado',
Email: 'arthurm@dx-email.com',
Skype: 'arthurm_DX_skype',
Mobile_Phone: '(310) 555-8583',
Birth_Date: '1972-07-11',
Hire_Date: '2007-12-18',
}, {
ID: 4,
Head_ID: 1,
Full_Name: 'Robert Reagan',
Prefix: 'Mr.',
Title: 'CMO',
City: 'Bentonville',
State: 'Arkansas',
Email: 'robertr@dx-email.com',
Skype: 'robertr_DX_skype',
Mobile_Phone: '(818) 555-2387',
Birth_Date: '1974-09-07',
Hire_Date: '2002-11-08',
}, {
ID: 5,
Head_ID: 1,
Full_Name: 'Greta Sims',
Prefix: 'Ms.',
Title: 'HR Manager',
City: 'Atlanta',
State: 'Georgia',
Email: 'gretas@dx-email.com',
Skype: 'gretas_DX_skype',
Mobile_Phone: '(818) 555-6546',
Birth_Date: '1977-11-22',
Hire_Date: '1998-04-23',
}, {
ID: 6,
Head_ID: 3,
Full_Name: 'Brett Wade',
Prefix: 'Mr.',
Title: 'IT Manager',
City: 'Reno',
State: 'Nevada',
Email: 'brettw@dx-email.com',
Skype: 'brettw_DX_skype',
Mobile_Phone: '(626) 555-0358',
Birth_Date: '1968-12-01',
Hire_Date: '2009-03-06',
}, {
ID: 7,
Head_ID: 5,
Full_Name: 'Sandra Johnson',
Prefix: 'Mrs.',
Title: 'Controller',
City: 'Beaver',
State: 'Utah',
Email: 'sandraj@dx-email.com',
Skype: 'sandraj_DX_skype',
Mobile_Phone: '(562) 555-2082',
Birth_Date: '1974-11-15',
Hire_Date: '2005-05-11',
}, {
ID: 8,
Head_ID: 4,
Full_Name: 'Ed Holmes',
Prefix: 'Dr.',
Title: 'Sales Manager',
City: 'Malibu',
State: 'California',
Email: 'edwardh@dx-email.com',
Skype: 'edwardh_DX_skype',
Mobile_Phone: '(310) 555-1288',
Birth_Date: '1973-07-14',
Hire_Date: '2005-06-19',
}, {
ID: 9,
Head_ID: 3,
Full_Name: 'Barb Banks',
Prefix: 'Mrs.',
Title: 'Support Manager',
City: 'Phoenix',
State: 'Arizona',
Email: 'barbarab@dx-email.com',
Skype: 'barbarab_DX_skype',
Mobile_Phone: '(310) 555-3355',
Birth_Date: '1979-04-14',
Hire_Date: '2002-08-07',
}, {
ID: 10,
Head_ID: 2,
Full_Name: 'Kevin Carter',
Prefix: 'Mr.',
Title: 'Shipping Manager',
City: 'San Diego',
State: 'California',
Email: 'kevinc@dx-email.com',
Skype: 'kevinc_DX_skype',
Mobile_Phone: '(213) 555-2840',
Birth_Date: '1978-01-09',
Hire_Date: '2009-08-11',
}, {
ID: 11,
Head_ID: 5,
Full_Name: 'Cindy Stanwick',
Prefix: 'Ms.',
Title: 'HR Assistant',
City: 'Little Rock',
State: 'Arkansas',
Email: 'cindys@dx-email.com',
Skype: 'cindys_DX_skype',
Mobile_Phone: '(818) 555-6655',
Birth_Date: '1985-06-05',
Hire_Date: '2008-03-24',
}, {
ID: 12,
Head_ID: 8,
Full_Name: 'Sammy Hill',
Prefix: 'Mr.',
Title: 'Sales Assistant',
City: 'Pasadena',
State: 'California',
Email: 'sammyh@dx-email.com',
Skype: 'sammyh_DX_skype',
Mobile_Phone: '(626) 555-7292',
Birth_Date: '1984-02-17',
Hire_Date: '2012-02-01',
}, {
ID: 13,
Head_ID: 10,
Full_Name: 'Davey Jones',
Prefix: 'Mr.',
Title: 'Shipping Assistant',
City: 'Pasadena',
State: 'California',
Email: 'davidj@dx-email.com',
Skype: 'davidj_DX_skype',
Mobile_Phone: '(626) 555-0281',
Birth_Date: '1983-03-06',
Hire_Date: '2011-04-24',
}, {
ID: 14,
Head_ID: 10,
Full_Name: 'Victor Norris',
Prefix: 'Mr.',
Title: 'Shipping Assistant',
City: 'Little Rock',
State: 'Arkansas',
Email: 'victorn@dx-email.com',
Skype: 'victorn_DX_skype',
Mobile_Phone: '(213) 555-9278',
Birth_Date: '1986-07-23',
Hire_Date: '2012-07-23',
}, {
ID: 15,
Head_ID: 10,
Full_Name: 'Mary Stern',
Prefix: 'Ms.',
Title: 'Shipping Assistant',
City: 'Beaver',
State: 'Utah',
Email: 'marys@dx-email.com',
Skype: 'marys_DX_skype',
Mobile_Phone: '(818) 555-7857',
Birth_Date: '1982-04-08',
Hire_Date: '2012-08-12',
}, {
ID: 16,
Head_ID: 10,
Full_Name: 'Robin Cosworth',
Prefix: 'Mrs.',
Title: 'Shipping Assistant',
City: 'Los Angeles',
State: 'California',
Email: 'robinc@dx-email.com',
Skype: 'robinc_DX_skype',
Mobile_Phone: '(818) 555-0942',
Birth_Date: '1981-06-12',
Hire_Date: '2012-09-01',
}, {
ID: 17,
Head_ID: 9,
Full_Name: 'Kelly Rodriguez',
Prefix: 'Ms.',
Title: 'Support Assistant',
City: 'Boise',
State: 'Idaho',
Email: 'kellyr@dx-email.com',
Skype: 'kellyr_DX_skype',
Mobile_Phone: '(818) 555-9248',
Birth_Date: '1988-05-11',
Hire_Date: '2012-10-13',
}, {
ID: 18,
Head_ID: 9,
Full_Name: 'James Anderson',
Prefix: 'Mr.',
Title: 'Support Assistant',
City: 'Atlanta',
State: 'Georgia',
Email: 'jamesa@dx-email.com',
Skype: 'jamesa_DX_skype',
Mobile_Phone: '(323) 555-4702',
Birth_Date: '1987-01-29',
Hire_Date: '2012-10-18',
}, {
ID: 19,
Head_ID: 9,
Full_Name: 'Antony Remmen',
Prefix: 'Mr.',
Title: 'Support Assistant',
City: 'Boise',
State: 'Idaho',
Email: 'anthonyr@dx-email.com',
Skype: 'anthonyr_DX_skype',
Mobile_Phone: '(310) 555-6625',
Birth_Date: '1986-02-19',
Hire_Date: '2013-01-19',
}, {
ID: 20,
Head_ID: 8,
Full_Name: 'Olivia Peyton',
Prefix: 'Mrs.',
Title: 'Sales Assistant',
City: 'Atlanta',
State: 'Georgia',
Email: 'oliviap@dx-email.com',
Skype: 'oliviap_DX_skype',
Mobile_Phone: '(310) 555-2728',
Birth_Date: '1981-06-03',
Hire_Date: '2012-05-14',
}, {
ID: 21,
Head_ID: 6,
Full_Name: 'Taylor Riley',
Prefix: 'Mr.',
Title: 'Network Admin',
City: 'San Jose',
State: 'California',
Email: 'taylorr@dx-email.com',
Skype: 'taylorr_DX_skype',
Mobile_Phone: '(310) 555-7276',
Birth_Date: '1982-08-14',
Hire_Date: '2012-04-14',
}, {
ID: 22,
Head_ID: 6,
Full_Name: 'Amelia Harper',
Prefix: 'Mrs.',
Title: 'Network Admin',
City: 'Los Angeles',
State: 'California',
Email: 'ameliah@dx-email.com',
Skype: 'ameliah_DX_skype',
Mobile_Phone: '(213) 555-4276',
Birth_Date: '1983-11-19',
Hire_Date: '2011-02-10',
}, {
ID: 23,
Head_ID: 6,
Full_Name: 'Wally Hobbs',
Prefix: 'Mr.',
Title: 'Programmer',
City: 'Chatsworth',
State: 'California',
Email: 'wallyh@dx-email.com',
Skype: 'wallyh_DX_skype',
Mobile_Phone: '(818) 555-8872',
Birth_Date: '1984-12-24',
Hire_Date: '2011-02-17',
}, {
ID: 24,
Head_ID: 6,
Full_Name: 'Brad Jameson',
Prefix: 'Mr.',
Title: 'Programmer',
City: 'San Fernando',
State: 'California',
Email: 'bradleyj@dx-email.com',
Skype: 'bradleyj_DX_skype',
Mobile_Phone: '(818) 555-4646',
Birth_Date: '1988-10-12',
Hire_Date: '2011-03-02',
}, {
ID: 25,
Head_ID: 6,
Full_Name: 'Karen Goodson',
Prefix: 'Miss',
Title: 'Programmer',
City: 'South Pasadena',
State: 'California',
Email: 'kareng@dx-email.com',
Skype: 'kareng_DX_skype',
Mobile_Phone: '(626) 555-0908',
Birth_Date: '1987-04-26',
Hire_Date: '2011-03-14',
}, {
ID: 26,
Head_ID: 5,
Full_Name: 'Marcus Orbison',
Prefix: 'Mr.',
Title: 'Travel Coordinator',
City: 'Los Angeles',
State: 'California',
Email: 'marcuso@dx-email.com',
Skype: 'marcuso_DX_skype',
Mobile_Phone: '(213) 555-7098',
Birth_Date: '1982-03-02',
Hire_Date: '2005-05-19',
}];