title: Kendo UI Dataviz diagram position shape on drop event
body: <p>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?</p>
  
  <p>Perhaps I am completely misunderstanding how the X Y thing works for this?</p>
  
  <pre><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 &amp;&amp;
                  $.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 + "&amp;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;
  }
  </code></pre>