Trouble with scrollRectIntoView use of body tag

I am attempting to incorporate ProseMirror into a form field widget for the popular open-source ERP product Odoo. When updating the editor with a newly created state the function EditorView.prototype.updateState() is calling scrollRectIntoView() which walks up the DOM tree looking for the body tag. Odoo is doing a lot of DOM manipulation, so the div at which ProseMirror is anchored has no body node as a parent. The walk up the DOM ends in an exception when the parent is null.

Is there some way to suppress the scrolling or to provide it with a alternative rectangle to use instead of searching for the body? In any case, the true bounding box would be the immediate parent div, not the page body.

Thanks,

Ed

Could you describe the exception in a bit more detail – I’m seeing an if (!parent) break at the top of the loop in scrollRectIntoView, which seems like it should cover the case of the editor being in a detached DOM tree.

Hello Marjin,

Thank you for looking at this. The full exception trace is as follows (Odoo bundles the javascript files)

at parentNode (http://localhost:8069/web/content/541-ad2a281/web.assets_backend.js:4782:67)
at scrollRectIntoView (http://localhost:8069/web/content/541-ad2a281/web.assets_backend.js:4784:33)
at EditorView.updateState (http://localhost:8069/web/content/541-ad2a281/web.assets_backend.js:5414:2)

The actual locations of the error is at the access of node.parentNode at line 9 of dom.js

exports.parentNode = function(node) { let parent = node.parentNode return parent.nodeType == 11 ? parent.host : parent } called from line 11 of domcoord.js

function scrollRectIntoView(view, rect) { let scrollThreshold = view.someProp(“scrollThreshold”) || 0, scrollMargin = view.someProp(“scrollMargin”) if (scrollMargin == null) scrollMargin = 5 for (let parent = view.dom;; parent = parentNode(parent)) { let atBody = parent == document.body

called from updateState() at line 137 of index.js

if (scrollToSelection) { if (state.selection.node) scrollRectIntoView(this, this.docView.domAfterPos(state.selection.from).getBoundingClientRect()) else

Evidently at the time of this call the div that the ProseMirror editor is anchored to has no element as a parent. The DOM is shown in this screen capture

The outer div evidently has a null parent node.

Ed

What I’m doing in my code that causes the error is this calling updateState with the state created by this function:

  _new_state: function(jsonStr) {
  let editor_inputs = {
    schema: this.schema,
    plugins: this.plugins
  }

  try {
    editor_inputs.doc = this.schema.nodeFromJSON(JSON.parse(jsonStr))
  } catch(err) {
    // pass
  }
  //editor_inputs.selection = {}
  let newstate = pm_lib.pm_state.EditorState.create(editor_inputs)
  return newstate
}

});

The input to the above function is either an empty string or a stringified JSON representation of a ProseMirror document. That same JSON does work in the ProseMirror editor when constructing a new editor in the following way

  let view = new pm_lib.pm_view.EditorView(this.$el[0], {
    state: this._new_state(this.get('value')),
    onAction: action =>
      view.updateState(view.state.applyAction(action)),
  })

so I know that the state I’m updating with is good.

Thank you Marjin,

I updated my node packages and the problem is indeed fixed. I see that it goes back to a fix you made on March 9th with a commit message that gets right to the point of my problem “Make sure parentNode doesn’t crash when reaching null”. I’ll be sure to keep my node packages more up-to-date and thank you again for fixing issues before I can even find them.

If I get the ProseMirror field pluin for Odoo working well and my employer is OK with open-sourcing the Odoo module then I’ll let you know. ProseMirror would add tremendous capabilities for Odoo form fields.

Ed