Inconsistencies for draggable node views

Hi, I found some inconsistencies regarding draggable node views I would like to understand. For now this looks like a bug to me.

Let’s say I have a simple node (called rectangle) as a node view.

const rectangleSpec = {
  group: "block",
  draggable: true,
  selectable: false,
  toDOM: node => ["div", { class: "rectangle" }],
  parseDOM: [{
    tag: "div.rectangle",
  }]
}

class RectangleView {
  constructor(node) {
    this.dom = document.createElement("div")
    this.dom.className = 'rectangle'
    this.contentDOM = undefined
  }

  stopEvent() { return true }
}

As you can see stopEvent returns always true. I would expect, that I can’t drag this node because of that. This is true but prosemirror-dropcursor still renders a drop cursor.

I created another node called circle. It’s the same like rectangle but it has a contentDOM.

const circleSpec = {
  group: "block",
  draggable: true,
  selectable: false,
  toDOM: node => ["div", { class: "circle" }],
  parseDOM: [{
    tag: "div.circle",
  }]
}

class CircleView {
  constructor(node) {
    this.dom = document.createElement("div")
    this.dom.className = 'circle'
    
    const child = document.createElement("div")
    this.dom.appendChild(child)
    this.contentDOM = child
  }

  stopEvent() { return true }
}

For that circle node prosemirror-dropcursor doesn’t render a drop cursor. And when I’m looking at the rendered HTML I can also see some differnces:

rectangle markup:

<div class="rectangle" contenteditable="false" draggable="true"></div>

circle markup:

<div class="circle"><div></div></div>

In the end, this causes me problems in the implementation of custom drag handles – whether with or without contentDOM.

I created a demo here: https://glitch.com/edit/#!/stop-event-bug

The dropcursor plugin is listening for the dom dragover event. It looks like the browser is firing that even though the dragstart event was canceled. I haven’t looked into this yet, but it shouldn’t be too hard to debug (see prosemirror-dropcursor/src/dropcursor.js).

But no content? What does the contentDOM do then?

Of course only in this demo. I just noticed that it behaves differently (correct) once contentDOM is defined.

@marijn Hmm I think it’s another bug. It can’t be just an issue with prosemirror-dropcursor, because both elements shouldn’t be draggable at all, right?

Mar-02-2020 09-14-50

Are you relying on stopEvent returning true to cancel the dragstart event? That might be the issue—stopEvent just filters which events ProseMirror itself looks at, it doesn’t actually cause preventDefault to be called.