1. #1
    Sencha Premium Member
    Join Date
    Jul 2012
    Posts
    105
    Vote Rating
    5
    Answers
    5
    Maxeta is on a distinguished road

      0  

    Question Unanswered: draggable:true event handling?

    Unanswered: draggable:true event handling?


    So I've been playing about with setting draggable:true in a few places, like on some Ext.Img objects. Works great for dragging them. At the moment I don't intend on dropping them (as in into a droppable zone). However I would like to know when the user has stopped dragging the object so I can kickoff a handle. However I'm having a little trouble, events like endDrag don't seem to work... does anyone have a short example on how to do this? Do I need to use the Ext.dd.DragDrop class? If so how do I integrate it with my Ext.Img?


    UPDATE: More Info

    Looks like I can override the onEnd event or setup a listener for dragend based on the Ext.util.ComponentDragger, like this:

    Code:
          draggable:
          {
            onEnd: function (e) {
              alert('onEnd');
            },
            listeners: {
              dragend: function (me, e, eOpts) {
                alert('dragend');
              }
            }
          },
    but I have no idea how to get a reference back to the element being dragged. I'd really like to get the itemId of the component that was just dragged (in my case my Ext.Img object), but I'm a little lost on getting to that value...


    UPDATE: Fixed (mostly... still want to try this as MVC)

    So took a bit of reading / trail & error, but it appears this works:

    Code:
          draggable: {
            listeners: {
              dragend: function (me, e, eOpts) {
                var img = Ext.getCmp(e.getTarget().id);
                alert(img.itemId);
              }
            }
          },
    So now I can track and update positions of my images (which is what I needed in order to store the locations offline for reloading the next time the app is opened).

  2. #2
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    9,154
    Vote Rating
    475
    Answers
    685
    scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future

      0  

    Default


    still want to try this as MVC
    Make sure you perform this in the controller and not in the view when using MVC.

  3. #3
    Sencha Premium Member
    Join Date
    Jul 2012
    Posts
    105
    Vote Rating
    5
    Answers
    5
    Maxeta is on a distinguished road

      0  

    Default


    Do you have a code snippet for setting up the listener for drag events on specific items in a controller?

    I tried something like this (but it didn't work):
    Code:
      init: function () {
        var me = this;
        me.control({
          'image[itemId=draggableImage]': {
            dragend: me.imgDragEnd
          }
        });
      },
    
      imgDragEnd: function (me, e, eOpts) {
        var el = Ext.getCmp(e.getTarget().id);
        alert(el.id);
      }
    I think I need to somehow access the Ext.dd.DragTracker... but I'm a bit lost on this.

  4. #4
    Sencha Premium Member
    Join Date
    Jul 2012
    Posts
    105
    Vote Rating
    5
    Answers
    5
    Maxeta is on a distinguished road

      0  

    Default


    Still no luck on this one... what I'd really like to do, is find out how to create a mvc handler for drag and drop events for controls marked as draggable:true. I already now I can directly put a listener on the object itself, so I'm hoping there is a way to just move this to a controller, but so far I'm stumped.

    If I extend a container like this:
    Code:
    Ext.define('appName.view.vIcons1', {
      extend: 'Ext.container.Container',
    
    
      alias: 'widget.Icons1',
      xtype: 'Icons1',
    
    
      style: 'background-color:transparent;',
    
    
      data: [
        {
          "ID": 1,
          "Name": "cmd.exe",
          "Icon": "./res/images/ICO/48x48/CMD.png",
          "Title": "Console",
          "X": 10,
          "Y": 10
        },
        {
          "ID": 2,
          "Name": "ftp.exe",
          "Icon": "./res/images/ICO/48x48/FTP.png",
          "Title": "File Transfer",
          "X": 100,
          "Y": 10
        },
        {
          "ID": 3,
          "Name": "src.exe",
          "Icon": "./res/images/ICO/48x48/SRC.png",
          "Title": 'A Very Long Internet Search Title',
          "X": 190,
          "Y": 10
        }
      ],
    
    
      tpl: [
        '<tpl for=".">',
          '<div class="x-dataview-item" role="option">',
            '<div class="thumb-wrap" style="left:{X}px; top:{Y}px;" title="{Title}">',
              '<div class="thumb">',
                '<img alt="{Name}" src="{Icon}"></img>',
              '</div>',
              '<span>',
                '{Title}',
              '</span>',
            '</div>',
          '</div>',
        '</tpl>'
      ].join(''),
    
    
      initComponent: function () {
        var me = this;
        me.callParent();
        clog('vIcons.initComponent()');
      },
    
    
      afterRender: function () {
        var me = this;
        alert(me.itemId);
        me.callParent();
        var container = Ext.get(me.el.id).select('div.thumb-wrap');
        alert(container.getCount());
        Ext.each(container.elements, function (el) {
          alert(el);
          var dd = Ext.create('Ext.dd.DD', el, 'icons', {
            isTarget: false
          });
        });
      }
    
    
    });
    I am able to drag the elements around. However doing a similar setup but extending a view and moving the data to a store like this, does not work:
    Code:
    
    Ext.define('appName.view.vIcons2', {
      extend: 'Ext.view.View',
    
    
      alias: 'widget.Icons2',
      xtype: 'Icons2',
    
    
      style: 'background-color:transparent;',
    
    
      store: 'sDesktop',
      itemTpl: ['<div class="thumb-wrap" style="left:{X}px; top:{Y}px;" title="{Title}"><div class="thumb"><img alt="{Name}" src="{Icon}"></img></div>{Title}</div>'].join(''),
      overItemCls: 'x-view-over',
      itemSelector: 'div.thumb-wrap',
    
    
      initComponent: function () {
        var me = this;
        me.callParent();
        clog('vIcons.initComponent()');
      },
    
    
      afterRender: function () {
        var me = this;
        alert(me.itemId);
        me.callParent();
        var container = Ext.get(me.el.id).select('div.thumb-wrap');
        alert(container.getCount());
        Ext.each(container.elements, function (el) {
          alert(el);
          var dd = Ext.create('Ext.dd.DD', el, 'icons', {
            isTarget: false
          });
        });
      }
    
    
    });
    BUT... if I move the data out of the store and back into a data section, it works with the view?

    any ideas on why that happens?


    UPDATE: More Info

    Seems like when I use a store, the afterrender element count is always 0? Is there another event I should be using in order to hook my drag and drop when using a store?

  5. #5
    Sencha Premium Member
    Join Date
    Jul 2012
    Posts
    105
    Vote Rating
    5
    Answers
    5
    Maxeta is on a distinguished road

      0  

    Default


    Okay, it turns out it was a timing scenario. This is probably not the correct solution (I couldn't locate the proper event to use). After setting up the store and moving the handler to the controller, I needed to set a timer because afterrender always had 0 elements (I tried viewready and had the same issue). Here is my code:

    VIEW
    Code:
    Ext.define('appName.view.vIcons', {
      extend: 'Ext.view.View',
    
      alias: 'widget.Icons',
      xtype: 'Icons',
    
      store: 'sDesktop',
      itemTpl: ['<div class="thumb-wrap" style="left:{X}px; top:{Y}px;" title="{Title}"><div class="thumb"><img alt="{Name}" src="{Icon}"></img></div>{Title}</div>'].join(''),
      overItemCls: 'x-view-over',
      itemSelector: 'div.thumb-wrap',
    
      initComponent: function () {
        var me = this;
        me.callParent();
        clog('vIcons.initComponent()');
      }
    
    
    });
    CONTROLLER
    Code:
    Ext.define('appName.controller.cIcons', {
      extend: 'Ext.app.Controller',
      views: ['vIcons'],
    
      init: function () {
        var me = this;
        me.control({
          'Icons[itemId=icons]': {
            afterrender: me.setIcon
          }
        });
        clog('cIcons.init()');
      },
    
    
      setIcon: function (me, eOpts) {
        var task = Ext.create('Ext.util.DelayedTask', function () {
          var container = Ext.get(me.el.id).select('div.thumb-wrap');
          Ext.each(container.elements, function (el) {
            var dd = Ext.create('Ext.dd.DD', el, 'icons', {
              isTarget: false
            });
          });
        });
        task.delay(500);
      }
    
    });
    If anyone knows where I should be setting up the Drag and Drop please fill me in, I really dislike timing events like this...


    UPDATE: More Info

    So I overode Ext.dd.DD and added an endDrag handler, but I'm stuck on how to get a reference to the element I was dragging. endDrag is apparently passed an event object, but I need the X and Y coordinate of the element I just dragged, not the cursor.

  6. #6
    Sencha Premium Member
    Join Date
    Jul 2012
    Posts
    105
    Vote Rating
    5
    Answers
    5
    Maxeta is on a distinguished road

      0  

    Default


    Okay I figured this one out, my new class is below:
    Code:
    Ext.define('appName.class.GridSnap', {
      extend: 'Ext.dd.DD',
    
    
      gridX: 80,
      gridY: 90,
    
    
      endDrag: function (e) {
        var me = this;
        var el = Ext.fly(me.getDragEl());
        var X = (Math.round(el.getLocalX() / me.gridX) * me.gridX);
        var Y = (Math.round(el.getLocalY() / me.gridY) * me.gridY);
        el.setLeft(X);
        el.setTop(Y);
      }
    
    
    });
    I ended up using endDrag rather than onDragDrop/onInvalidDrop mainly because if an item is dragged to the edge of it's container (which it may bound to), and the mouse cursor exceeds those bounds, then onInvalidDrop will fire. But I wanted the element to snap to the closest grid point anyways.

    P.S. This still doesn't answer my initial question of how we can handle for generic drag and drop events on an component that is marked as draggable:true, in a MVC architecture. So if anyone has an answer to that, please still post and let me know.

Thread Participants: 1

Tags for this Thread