Creating a span node with text content

Hello,

First of all, sorry if this has been asked before. I have looked as much as I can but have not find an answer.

I want to create a <span> node with a text content. I’m basing my solution on the “Dinos in the document” example. The changes I have made are the following:

First, I have changed all the dinos in the index.html file to be <span>:s instead of <img>:s

  <p>This paragraph <span class="dinosaur" dino-type="stegosaurus">stegosaurus</span>, for example,
  <span class="dinosaur" dino-type="triceratops">triceratops</span>
  is full <span class="dinosaur" dino-type="tyrannosaurus">tyrannosaurus</span> of
  dinosaurs.</p>

Second, I have updated the dinoNodeSpec object to generate span instead of img

  // These nodes are rendered as images with a `dino-type` attribute.
  // There are pictures for all dino types under /img/dino/.
  toDOM: node => ["span", {"dino-type": node.attrs.type,
                          class: "dinosaur"}],
  // When parsing, such an image, if its type matches one of the known
  // types, is converted to a dino node.
  parseDOM: [{
    tag: "span[dino-type]",
    getAttrs: dom => {
      let type = dom.getAttribute("dino-type")
      return dinos.indexOf(type) > -1 ? {type} : false
    }
  }]

My problem is that the “content” is not rendered. I basically get an empty span like this (example for “stegosaurus”):

<span dino-type="stegosaurus" class="dinosaur" contenteditable="false" draggable="true"></span>

I have tried adding text: node.attrs.type or content: node.attrs.type to the object in toDOM, but none of them has worked.

My tries so far is here: Glitch :・゚✧

What am I doing wrong?

You must specify a content for your custom nodes (dinosaurs don’t have content), and include a 0 in the result of your toDOM methods to indicate the position of the content. Check the relevant docs for details.

@marijn thanks, it got me a bit on my way. Now I have the following:

  content: "text*",

  // These nodes are rendered as images with a `dino-type` attribute.
  // There are pictures for all dino types under /img/dino/.
  toDOM: node => ["span", {"dino-type": node.attrs.type, class: "dinosaur"}, 0],
  // When parsing, such an image, if its type matches one of the known
  // types, is converted to a dino node.
  parseDOM: [{
    tag: "span[dino-type]",
    getAttrs: dom => {
      let type = dom.getAttribute("dino-type")
      return dinos.indexOf(type) > -1 ? {type} : false
    }
  }]

Now, the “initial” dinosaurs are rendered correctly, but I still have a couple of problems.

First, any new dinosaur added from the dropdown is still added as an empty span like in my original question. I don’t understand what I am doing wrong?

Second, the draggable feature does not seem to work. Maybe the don’t work on text nodes?

Sorry if I’m asking simple questions. I’ve been spending two whole days reading through your documentation and I really really don’t understand what I am supposed to do to get it to work. The reason for me asking this is not to make you do the work. I’m the kind of person that has a really hard time understanding documentations, and I really don’t understand whan I’m doing wrong.

Nodes with visible content generally can’t be dragged, because dragging already means something there (text selection). I have no idea what you’re doing in your dropdown—if you’re using the old code, it’s going to insert empty nodes which are expected to not contain text.

@marijn I have a full “copy” of what I’m trying to do here: Glitch :・゚✧

This is where you’re creating an empty node:

dispatch(state.tr.replaceSelectionWith(dinoType.create({type})))

@marijn so sorry for asking really stupid questions. I do understand that it’s at that line I create the empty node. But I don’t understand how I make the node not being empty. I’ve been trying through the weekend but have not gotten any further.

Also, to clarify: So there is no way to make the editor behave exactly as in the Dino example, but instead of showing pictures of a dino, I instead show the text? Unless I create a bunch of images that contains the text?

The docs can help a lot in cases like this. For NodeType.create, for example. Doing something like dinoType.create(null, [schema.text("abc")]).