ueberdosis/tiptap

Using non-vue html constructor in custom node

mvind opened this issue · 5 comments

mvind commented

Hello,

I'm currently prototyping a custom image node so you can resize the image. I found this snippet for a constructor which creates a span and inside that an image.

class FootnoteView {
    constructor(node, view, getPos) {    
    const outer = document.createElement("span")
    outer.style.position = "relative"
    outer.style.width = node.attrs.width
    //outer.style.border = "1px solid blue"
    outer.style.display = "inline-block"
    //outer.style.paddingRight = "0.25em"
    outer.style.lineHeight = "0"; // necessary so the bottom right arrow is aligned nicely    
    const img = document.createElement("img")
    img.setAttribute("src", node.attrs.src)
    img.style.width = "100%"
    //img.style.border = "1px solid red"    
    const handle = document.createElement("span")
    handle.style.position = "absolute"
    handle.style.bottom = "0px"
    handle.style.right = "0px"
    handle.style.width = "10px"
    handle.style.height = "10px"
    handle.style.border = "3px solid black"
    handle.style.borderTop = "none"
    handle.style.borderLeft = "none"
    handle.style.display = "none"
    handle.style.cursor = "nwse-resize"
    
    handle.onmousedown = function(e) {
      e.preventDefault()
      
      const startX = e.pageX;
      const startY = e.pageY;
      
      const fontSize = getFontSize(outer)
      
      const startWidth = parseFloat(node.attrs.width.match(/(.+)em/)[1])
            
      const onMouseMove = (e) => {
        const currentX = e.pageX;
        const currentY = e.pageY;
        
        const diffInPx = currentX - startX
        const diffInEm = diffInPx / fontSize
                
        outer.style.width = `${startWidth + diffInEm}em`
      }
      
      const onMouseUp = (e) => {        
        e.preventDefault()
        
        document.removeEventListener("mousemove", onMouseMove)
        document.removeEventListener("mouseup", onMouseUp)
                
        const transaction = view.state.tr.setNodeMarkup(getPos(), null, {src: node.attrs.src, width: outer.style.width} ).setSelection(view.state.selection);
              
        view.dispatch(transaction)
      }
      
      document.addEventListener("mousemove", onMouseMove)
      document.addEventListener("mouseup", onMouseUp)
    }
    
    outer.appendChild(handle)
    outer.appendChild(img)
        
    this.dom = outer
    this.img = img
    this.handle = handle
  }
  
  selectNode() {
    this.img.classList.add("ProseMirror-selectednode")
    
    this.handle.style.display = ""
  }

  deselectNode() {
    this.img.classList.remove("ProseMirror-selectednode")
    
    this.handle.style.display = "none"
  }
}

from this guy here https://glitch.com/edit/#!/toothsome-shoemaker?path=index.js%3A127%3A6.

Is it possible to use this constructor inside the custom node?

I have tried to

get view() {
    return new FootnoteView(node, view, getPos)
}

But then I get that the node is not defined. Do anyone know if you have to use a vue component in this view getter - or if I can somehow use this constructor?

Thanks for reading.

mvind commented

Sorry forgot to mention that the constructor is used for a prossemirror custom node!

mvind commented

I rewrote this extension for image resizing as vue component.. I will close this issue now..

I rewrote this extension for image resizing as vue component.. I will close this issue now..

That sounds great! Can you share what you've written? Thanks @mvind!

mvind commented

Sure! Here is a link to a gist with the vue component
https://gist.github.com/mvind/e89948b9ab1c1f2557805bf3c9ea7f6c.

@mvind I basically did the same, how to you handle active state? It's done by selectNode and deselectNode in prosemirror, what you did in example doesn't properly work when moving cursor.