Search code examples
javascriptjqueryjquery-uidrag-and-dropmeteor-blaze

Jquery Droppable not working for file upload drag and drop, throws Error: Expected DOM element or View


I have been working on a https://github.com/wekan/ fork where I try to implement additional drag and drop functionality. Out of the box wekan already came with labels/member drag and drop where the hover overlay is done via droppable hoverClass:

    const selector = $cards.find(itemsSelector);
    selector.droppable({
      hoverClass: 'draggable-hover-card',
      accept: '.js-member,.js-label',
      'drop'(evt, ui) {
        evt.preventDefault();
        evt.stopPropagation();
        const cardId = Blaze.getData(this)._id;
        const card = Cards.findOne(cardId); //get current card I am hovering
        //stuff
      },
    });

I added attachment drag and drop functionality, which won't work exactly like above code and produces the problem that I cannot add the hoverClass cleanly. When I implement it as shown below the logic of doing addClass is sound but I get an error:

Exception from Tracker afterFlush function:
debug.js:41 Error: Expected DOM element or View
at Object.Blaze.getData (view.js:757)
at list.js:116
at Object.Tracker._runFlush (tracker.js:511)
at onGlobalMessage (setimmediate.js:102)

My code where I want to get an overlay/hover functionality for a single card that I hover over with a file:

    const cardId = Blaze.getData(this)._id;
    const card = Cards.findOne(cardId); //get current card I am hovering
    selector.on({'': (evt) => { //.droppable as above does not work
      evt.preventDefault(); //prevent default browser behavior
      evt.stopPropagation();
    },
    dragover(e) { // pulled out of selector.on() to add/removeClass
      e.preventDefault();
      e.stopPropagation();
      card.addClass('is-selected'); //add overlay on hover
    },
    dragenter(e) {
      e.preventDefault();
      e.stopPropagation();
    },
    dragleave(e) {
      e.preventDefault();
      e.stopPropagation();
      card.removeClass('is-selected');
    },
    drop(evt, ui) {
      card.removeClass('is-selected');
      if(!ui){ // prevent complications with other drop events
        evt.preventDefault();
        evt.stopImmediatePropagation(); // prevent x -times actions
        evt.target.files = evt.dataTransfer.files; // working file upload
        _.each(evt.dataTransfer.files, (f) => {
          const file = new FS.File(f);
          file.boardId = card.boardId;
          file.cardId = card._id;
          Attachments.insert(file);
        });}
    },
    });  

When I move

const cardId = Blaze.getData(this)._id;
const card = Cards.findOne(cardId);

back into the drop event like in the first code block and try/test e.g. selector.addClass('') instead, the overlay works, but not correctly(selector basically returns the whole card list instead of a single card). I am a novice currently in training and I just can't understand what error I am making.


Template.currentData() instead of Blaze.getData() does not work. When I try selector.droppable() my dropped file isn't accepted and all the other events won't fire either. After trying different varieties I am pretty sure that Blaze.getData() is the problem here. I don't know how to replace its function though.


Solution

  • The problem was a syntax and logic error on my side. While I knew that this in Blaze.getData() would point to the div I wanted, this.addClass() would throw an error. So I thought I'd need the whole Blaze-Block which then lead to the problem above.

    Right Syntax:

    $(this).addClass('');