I have a webapp set up that I use a tree view to drag file names from and drop them on a diagram to use as a visual processing system (ETL). I have a working system and I pass the X and Y coordinates (from drop event) to the datasource (item.X, item.Y), which, when I drop the file onto the diagram space, puts the group (invisible with the yellow dots for connection points) in the top left corner, and the textBlock and Image (within the grouping) at the appropriate places based on the drop location. Is there a way to specify the X and Y coordinates for the Group as a whole?
5 Answers, 1 is accepted
0
Aaron
Top achievements
Rank 1
answered on 02 Apr 2014, 08:39 PM
My apologies...I hit "post" too quickly. here is the code...
function load_kendo() {
// global variable used to save off the editor file name to be saved later
var file;
var parentMenu;
var X;
var Y;
var appServer = "https://endeavour:3000";
document.onmousemove = function(e) {
X = e.pageX;
Y = e.pageY;
}
var popup = $("#popupNotification").kendoNotification().data("kendoNotification");
// Navigation menu, top-left of screen
$("#user-menu").kendoMenu();
// Set up the popup window, but default state is closed
var settings = $("#settings");
settings.kendoWindow({
title: "Settings",
modal: true,
actions: ["Minimize","Maximize","Close"],
width: "600px",
height: "600px",
visible: false
});
// Add click event handler to open popup for settings
$("#open-settings").click(function() {
settings.data("kendoWindow").center();
settings.data("kendoWindow").open();
});
// Left navigation panelbar
var panelbar = $("#panelbar");
panelbar.kendoPanelBar({
expandMode: "single"
});
//
var dragDropFilesDS = new kendo.data.HierarchicalDataSource();
var dragDropFiles = $("#dragDropFiles").kendoDiagram({
dataSource : dragDropFilesDS,
shapeDefaults: {
visual: visualTemplate
}
}).data('kendoDiagram');
//
// File browsers
var parserLibraryDS = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: appServer + "/directory_list?directory=parser-library"
}
},
schema: {
model: {
children: "files"
}
}
});
var parserLibrary = $("#parser-library").kendoTreeView({
dataSource: parserLibraryDS,
dragAndDrop: true
}).data('kendoTreeView');
var parserLibraryUserDS = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: appServer + "/directory_list?directory=parser-library-user"
}
},
schema: {
model: {
children: "files"
}
}
});
var parserLibraryUser = $("#parser-library-user").kendoTreeView({
dataSource: parserLibraryUserDS,
dragAndDrop: true
}).data('kendoTreeView');
var filebrowserDS = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: appServer + "/directory_list"
}
},
schema: {
model: {
children: "files"
}
}
});
var filebrowser = $("#filebrowser").kendoTreeView({
dataSource: filebrowserDS,
dragAndDrop: true,
drag: function(e) {
if (!$("#filebrowser").data('kendoTreeView').dataItem(e.sourceNode).hasChildren &&
$.contains($("#dragDropFiles")[0], e.dropTarget)) {
e.setStatusClass('k-add');
}
else {
e.setStatusClass('k-denied');
}
},
drop: function(e) {
if (e.valid) {
var item = $("#filebrowser").data('kendoTreeView').dataItem(e.sourceNode);
var extPat = /\.([0-9a-z]{1,5})$/i;
var extension = item.text.match(extPat);
var imgUrl = "images/file_icons/" + extension[1] + ".png";
if (imageExists(imgUrl)) {
dragDropFilesDS.add({text: item.text, path: item.fullPath, image: imgUrl, x: X, y: Y});
}
else {
imgUrl = "images/file_icons/generic_file.png";
dragDropFilesDS.add({text: item.text, path: item.fullPath, image: imgUrl, x: X, y: Y});
}
}
e.preventDefault();
}
}).data('kendoTreeView');
var previewWindow = $("#preview-file-contents").kendoWindow({
visible: false,
actions: ["Save", "Minimize", "Maximize", "Restore", "Close"],
width: 600,
height: 400
}).data('kendoWindow');
var codemirror = CodeMirror.fromTextArea(codemirrorTextarea); //, { lineNumbers: true }
$("#preview-file-contents").data('kendoWindow').wrapper.find('.k-i-save').click(function(e) {
var regex = /\/(.[^\/]+)$/;
var filename = regex.exec(file);
$.post("fileops", { operation: 'save', filename: file, contents: codemirror.getValue() }, function(data) {
if (parentMenu === "#filebrowser") {
filebrowserDS.read();
}
else if (parentMenu === "#parser-library") {
parserLibraryDS.read();
}
else if (parentMenu === "#parser-library-user") {
parserLibraryUserDS.read();
}
previewWindow.close();
}).done(function(data, textStatus, xhr) {
popup.success(filename[1] + " saved!");
}).fail(function(xhr) {
popup.error("Error, " + filename[1] + " not saved! (" + xhr.status + " " + xhr.statusText + ")");
});
});
$.contextMenu({
selector: '#panelbar li',
items: {
"Preview": {name: "Preview",
icon: "preview",
callback: function(key, options) {
parentMenu = '#' + $(this).closest('div').attr('id');
file = $(parentMenu).data('kendoTreeView').dataItem($(this)).fullPath;
var regex = /\/(.[^\/]+)$/;
var filename = regex.exec(file);
var qparameters;
// The basic logic here is that if it is a script, load the whole thing...otherwise restrain it to N lines (100 for now, configurable later)
// TODO: Implement a mechanism for the user to define and then adjust the number of lines returned, perhaps even a "load more" button?
if (parentMenu === '#filebrowser') {
qparameters = "fileSample?file=" + file + "&lines=100";
}
else {
qparameters = "fileSample?file=" + file;
}
$.getJSON(qparameters, function(data) {
if (data.includes) {
s = document.createElement('script');
s.type = 'text/javascript';
s.src = data.includes;
$("head").append(s);
}
previewWindow.center().open();
codemirror.setOption('mode', data.type);
codemirror.setValue(data.fileContents);
codemirror.refresh();
}).fail(function(xhr) {
popup.error("Error, " + filename[1] + " not opened! (" + xhr.status + " " + xhr.statusText + ")");
});
}},
"Delete": { name: "Delete",
icon: "delete",
callback: function(key, options) {
parentMenu = '#' + $(this).closest('div').attr('id');
file = $(parentMenu).data('kendoTreeView').dataItem($(this)).fullPath;
var qparameters;
var regex = /\/(.[^\/]+)$/;
var filename = regex.exec(file);
$.post("fileops", { operation: 'delete', filename: file }, function(data) {
if (parentMenu === "#filebrowser") {
filebrowserDS.read();
}
else if (parentMenu === "#parser-library") {
parserLibraryDS.read();
}
else if (parentMenu === "#parser-library-user") {
parserLibraryUserDS.read();
}
}).done(function(data, textStatus, xhr) {
popup.success(filename[1] + " deleted!");
}).fail(function(xhr) {
popup.error("Error, " + filename[1] + " not deleted! (" + xhr.status + " " + xhr.statusText + ")");
});
}}
}
});
}
function imageExists(url) {
var img = new Image();
img.src = url;
return img.height != 0;
}
function visualTemplate (options) {
var dataviz = kendo.dataviz;
var g = new dataviz.diagram.Group();
var dataItem = options.dataItem;
g.append(new dataviz.diagram.Image({
source: dataItem.image,
width: 50,
height: 50,
x: dataItem.x,
y: dataItem.Y
}));
g.append(new dataviz.diagram.TextBlock({
text: dataItem.text,
x: dataItem.x - 25,
y: dataItem.y + 25,
color: "#000"
}));
return g;
}
// global variable used to save off the editor file name to be saved later
var file;
var parentMenu;
var X;
var Y;
var appServer = "https://endeavour:3000";
document.onmousemove = function(e) {
X = e.pageX;
Y = e.pageY;
}
var popup = $("#popupNotification").kendoNotification().data("kendoNotification");
// Navigation menu, top-left of screen
$("#user-menu").kendoMenu();
// Set up the popup window, but default state is closed
var settings = $("#settings");
settings.kendoWindow({
title: "Settings",
modal: true,
actions: ["Minimize","Maximize","Close"],
width: "600px",
height: "600px",
visible: false
});
// Add click event handler to open popup for settings
$("#open-settings").click(function() {
settings.data("kendoWindow").center();
settings.data("kendoWindow").open();
});
// Left navigation panelbar
var panelbar = $("#panelbar");
panelbar.kendoPanelBar({
expandMode: "single"
});
//
var dragDropFilesDS = new kendo.data.HierarchicalDataSource();
var dragDropFiles = $("#dragDropFiles").kendoDiagram({
dataSource : dragDropFilesDS,
shapeDefaults: {
visual: visualTemplate
}
}).data('kendoDiagram');
//
// File browsers
var parserLibraryDS = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: appServer + "/directory_list?directory=parser-library"
}
},
schema: {
model: {
children: "files"
}
}
});
var parserLibrary = $("#parser-library").kendoTreeView({
dataSource: parserLibraryDS,
dragAndDrop: true
}).data('kendoTreeView');
var parserLibraryUserDS = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: appServer + "/directory_list?directory=parser-library-user"
}
},
schema: {
model: {
children: "files"
}
}
});
var parserLibraryUser = $("#parser-library-user").kendoTreeView({
dataSource: parserLibraryUserDS,
dragAndDrop: true
}).data('kendoTreeView');
var filebrowserDS = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: appServer + "/directory_list"
}
},
schema: {
model: {
children: "files"
}
}
});
var filebrowser = $("#filebrowser").kendoTreeView({
dataSource: filebrowserDS,
dragAndDrop: true,
drag: function(e) {
if (!$("#filebrowser").data('kendoTreeView').dataItem(e.sourceNode).hasChildren &&
$.contains($("#dragDropFiles")[0], e.dropTarget)) {
e.setStatusClass('k-add');
}
else {
e.setStatusClass('k-denied');
}
},
drop: function(e) {
if (e.valid) {
var item = $("#filebrowser").data('kendoTreeView').dataItem(e.sourceNode);
var extPat = /\.([0-9a-z]{1,5})$/i;
var extension = item.text.match(extPat);
var imgUrl = "images/file_icons/" + extension[1] + ".png";
if (imageExists(imgUrl)) {
dragDropFilesDS.add({text: item.text, path: item.fullPath, image: imgUrl, x: X, y: Y});
}
else {
imgUrl = "images/file_icons/generic_file.png";
dragDropFilesDS.add({text: item.text, path: item.fullPath, image: imgUrl, x: X, y: Y});
}
}
e.preventDefault();
}
}).data('kendoTreeView');
var previewWindow = $("#preview-file-contents").kendoWindow({
visible: false,
actions: ["Save", "Minimize", "Maximize", "Restore", "Close"],
width: 600,
height: 400
}).data('kendoWindow');
var codemirror = CodeMirror.fromTextArea(codemirrorTextarea); //, { lineNumbers: true }
$("#preview-file-contents").data('kendoWindow').wrapper.find('.k-i-save').click(function(e) {
var regex = /\/(.[^\/]+)$/;
var filename = regex.exec(file);
$.post("fileops", { operation: 'save', filename: file, contents: codemirror.getValue() }, function(data) {
if (parentMenu === "#filebrowser") {
filebrowserDS.read();
}
else if (parentMenu === "#parser-library") {
parserLibraryDS.read();
}
else if (parentMenu === "#parser-library-user") {
parserLibraryUserDS.read();
}
previewWindow.close();
}).done(function(data, textStatus, xhr) {
popup.success(filename[1] + " saved!");
}).fail(function(xhr) {
popup.error("Error, " + filename[1] + " not saved! (" + xhr.status + " " + xhr.statusText + ")");
});
});
$.contextMenu({
selector: '#panelbar li',
items: {
"Preview": {name: "Preview",
icon: "preview",
callback: function(key, options) {
parentMenu = '#' + $(this).closest('div').attr('id');
file = $(parentMenu).data('kendoTreeView').dataItem($(this)).fullPath;
var regex = /\/(.[^\/]+)$/;
var filename = regex.exec(file);
var qparameters;
// The basic logic here is that if it is a script, load the whole thing...otherwise restrain it to N lines (100 for now, configurable later)
// TODO: Implement a mechanism for the user to define and then adjust the number of lines returned, perhaps even a "load more" button?
if (parentMenu === '#filebrowser') {
qparameters = "fileSample?file=" + file + "&lines=100";
}
else {
qparameters = "fileSample?file=" + file;
}
$.getJSON(qparameters, function(data) {
if (data.includes) {
s = document.createElement('script');
s.type = 'text/javascript';
s.src = data.includes;
$("head").append(s);
}
previewWindow.center().open();
codemirror.setOption('mode', data.type);
codemirror.setValue(data.fileContents);
codemirror.refresh();
}).fail(function(xhr) {
popup.error("Error, " + filename[1] + " not opened! (" + xhr.status + " " + xhr.statusText + ")");
});
}},
"Delete": { name: "Delete",
icon: "delete",
callback: function(key, options) {
parentMenu = '#' + $(this).closest('div').attr('id');
file = $(parentMenu).data('kendoTreeView').dataItem($(this)).fullPath;
var qparameters;
var regex = /\/(.[^\/]+)$/;
var filename = regex.exec(file);
$.post("fileops", { operation: 'delete', filename: file }, function(data) {
if (parentMenu === "#filebrowser") {
filebrowserDS.read();
}
else if (parentMenu === "#parser-library") {
parserLibraryDS.read();
}
else if (parentMenu === "#parser-library-user") {
parserLibraryUserDS.read();
}
}).done(function(data, textStatus, xhr) {
popup.success(filename[1] + " deleted!");
}).fail(function(xhr) {
popup.error("Error, " + filename[1] + " not deleted! (" + xhr.status + " " + xhr.statusText + ")");
});
}}
}
});
}
function imageExists(url) {
var img = new Image();
img.src = url;
return img.height != 0;
}
function visualTemplate (options) {
var dataviz = kendo.dataviz;
var g = new dataviz.diagram.Group();
var dataItem = options.dataItem;
g.append(new dataviz.diagram.Image({
source: dataItem.image,
width: 50,
height: 50,
x: dataItem.x,
y: dataItem.Y
}));
g.append(new dataviz.diagram.TextBlock({
text: dataItem.text,
x: dataItem.x - 25,
y: dataItem.y + 25,
color: "#000"
}));
return g;
}
0
Hi,
You should be able to specify the group x/y position directly:
var g = new dataviz.diagram.Group({
x: dataItem.x, y: dataItem.y
});
-- Live demo --
The documentation omits these properties and this will be fixed.
I hope this helps.
Regards,
T. Tsonev
Telerik
You should be able to specify the group x/y position directly:
var g = new dataviz.diagram.Group({
x: dataItem.x, y: dataItem.y
});
-- Live demo --
The documentation omits these properties and this will be fixed.
I hope this helps.
Regards,
T. Tsonev
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
0
Aaron
Top achievements
Rank 1
answered on 04 Apr 2014, 03:51 PM
So, I am starting to see the issue...I think! Even in your demo, I see that the square is in the right place, but I see that when I hover over the top left corner, the control points (for connections) are still at 0,0...So, how do I get the whole "shebang" to be where I dropped it?
0
Hi,
Well, I definitely missed that. The shape is still at 0, 0 - only the group has moved effectively outside of it.
I've inspected the code and there appears to be no way to specify the shape position in the visual template. The only chance we have is to handle the change event:
change: function(e) {
if (e.added.length === 1) {
var shape = e.added[0];
// shape.model will be renamed to shape.dataItem
var dataItem = shape.dataItem || shape.model;
shape.position({ x: dataItem.x, y: dataItem.y });
}
}
-- Updated demo --
You can remove the code that checks for the shape.model alias after the official release.
Apologies for the caused inconvenience.
Regards,
T. Tsonev
Telerik
Well, I definitely missed that. The shape is still at 0, 0 - only the group has moved effectively outside of it.
I've inspected the code and there appears to be no way to specify the shape position in the visual template. The only chance we have is to handle the change event:
change: function(e) {
if (e.added.length === 1) {
var shape = e.added[0];
// shape.model will be renamed to shape.dataItem
var dataItem = shape.dataItem || shape.model;
shape.position({ x: dataItem.x, y: dataItem.y });
}
}
-- Updated demo --
You can remove the code that checks for the shape.model alias after the official release.
Apologies for the caused inconvenience.
Regards,
T. Tsonev
Telerik
Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.
0
Aaron
Top achievements
Rank 1
answered on 07 Apr 2014, 02:54 PM
Thanks! that seems to have done the trick...