Copy NodeSelected nodes


#1

I have the node structured as below,

<blockquote>
   <el1>el1 content</el1>
   <el2>el2 content</el2>
</blockquote>

After i triple clicked the node, the whole node is selected and the current selection is a node selection. Then when i press ctrl-c to copy the node, i found that sometimes the node can be copied but sometimes it is not. When i drill into the function in prosemirror-view, i found that sometime when i press ctrl-c, it doesn’t trigger the event handler below and the result is the node is not copied:

handlers.copy = editHandlers.cut = function (view, e) {
  console.log('handle copy')
  var sel = view.state.selection, cut = e.type == "cut";
  if (sel.empty) { return }

  // IE and Edge's clipboard interface is completely broken
  var data = brokenClipboardAPI ? null : e.clipboardData;
  var slice = sel.content();
  var ref = serializeForClipboard(view, slice);
  var dom = ref.dom;
  var text = ref.text;
  if (data) {
    e.preventDefault();
    data.clearData();
    data.setData("text/html", dom.innerHTML);
    data.setData("text/plain", text);
  } else {
    captureCopy(view, dom);
  }
  if (cut) { view.dispatch(view.state.tr.deleteSelection().scrollIntoView().setMeta("uiEvent", "cut")); }
};

Does anyone have any idea on what could be the possible reason for this? Any help would be great, thanks. Below is my schema:

blockquote: {
  group: 'block',
  content: 'el1 el2',
  selectable: true,
  draggable: false,
  parseDOM: [
    {
      tag: 'blockquote'
    }
  ],
  toDOM() {
    return ['blockquote', 0]
  }
},
el1: {
   content: 'text*',
   defining: true,
   parseDOM: [
     {
       tag: 'div[node-type="el1"]'
     }
   ],
   toDOM() {
     return ['div', { 'node-type': 'el1' }, 0]
   }
}
el2: {
    content: 'text*',
    defining: true,
    parseDOM: [
      {
        tag: 'div[node-type="el2"]'
      }
    ],
    toDOM() {
      return ['div', { 'node-type': 'el2' }, 0]
    }
  }

#2

It’s possible that your browser decides that the selection is not a ‘real selection’ and therefore doesn’t start a copy event when you press ctrl-c. Can you set up a minimal demo of the problem (and tell me which browser this happens on)? When a node selection is active, ProseMirror creates a selection across the selected node, but browsers can be weird about selections that start/end in block context, so maybe it’s being normalized to an empty selection somehow.


#3

@marjin Thanks for the reply, when i try to set up a demo to replicate the problem, i found that the problem doesn’t occur in my demo, so i dig into it further. Finally i found that, when i have only 1 blockquote, i can copy without problem but if there is consecutive blockquotes like this:

<blockquote></blockquote>
<blockquote></blockquote>
<blockquote></blockquote>

starting from the second blockquote, i cannot copy. If i insert a paragraph to between 2 blockquotes like this:

<blockquote></blockquote>
<p></p>
<blockquote></blockquote>

both blockquotes can be copied.

The cause to the copy failure seems to be due to my blockquote nodeview structure. I have the following structure for my nodeview dom:

<div>
   <div contenteditable="false">something</div>
   <blockquote>This is content dom</blockquote>
   <div contenteditable="false">something</div>
</div>

When i remove the contenteditable="false" on the divs, the copy works well. So the contenteditable should be the cause.

But I do not quite understand why it would works when i have one separate blockquote, but it won’t works when i have consecutive blockquotes.

I am using the chrome version 69

This is the mini demo that i tried on with my schema on it


#4

Ah, I think that this hack, which works around the issue of some browsers not allowing selection endpoints between non-editable nodes, fails to work in this case, since the non-editable nodes aren’t actually the direct siblings of the selection position, but rather descendants of those siblings.

I think, for now, the easiest way to solve this would be to use CSS :before and :after pseudo elements for whatever markers you’re adding before and after the blockquotes. If that’s not an option, maybe try some other DOM structures.