What is the preferred method for setting an attribute on the nodes in the current selection?
I’m looking at doing something like this, but it feels a bit…unnatural.
startSlice = pm.doc.resolve(pm.selection.from).pos - pm.doc.resolve(pm.selection.from).parentOffset
endSlice = pm.doc.resolve(pm.selection.to).pos - pm.doc.resolve(pm.selection.to).parentOffset + pm.doc.resolve(pm.selection.to).parent.content.size + 1
pm.doc.forEach(((node, offset, index) =>
if offset < startSlice || offset > endSlice
return
newAttrs = Object.assign(node.attrs)
newAttrs['some_attribute'] = 'some_value'
if node.isTextblock
pm.tr.setBlockType( offset, node.content.size, node.type, newAttrs ).apply()
else
from = this.editor.selection.from
pm.tr.setNodeType( offset, node.type, newAttrs ).apply()
).bind(this))
marijn
August 26, 2016, 8:51am
2
What is the role of the attribute you’re trying to set?
What is the role of the attribute you’re trying to set?
The attribute is for text alignment
marijn
August 26, 2016, 7:42pm
4
Ah, I see. So you want to make a change to all applicable blocks touched by the selection?
(For one thing, doing doc.resolve(x).pos
is just going to give you x
, so don’t do that.)
Something like this might work (untested):
function setAlign(pm, align) {
let tr = pm.tr
pm.doc.nodesBetween(pm.selection.from, pm.selection.to, (node, pos) => {
if (typeSupportsAlign(node.type) && node.attrs.align != align)
tr.setNodeType(pos, node.type, Object.assign({}, node.attrs, {align}))
})
tr.apply()
}
1 Like
Thanks, this is much cleaner than what I was thinking.
The document doesn’t re-render itself after applying that transform though…eg. if I open the basic demo , place my caret in the first heading node, and run this in my JS console
var tr = pm.tr
pm.doc.nodesBetween(pm.selection.from, pm.selection.to, (node, pos) => {
if (node.type.attrs.level) {
newAttrs = Object.assign(node.attrs)
newAttrs.level = 3
tr.setNodeType(pos, node.type, newAttrs)
}
})
tr.apply()
I can inspect the document (window.pm.doc) and see that the document has changed appropriately, but hasn’t rerendered the node as an h3.
marijn
August 29, 2016, 7:34pm
6
I don’t think Object.assign
, when used like that, is going to copy the object. So you end up mutating the original object and the diffing algorithm that does the redraw isn’t going to notice that the document changed.
Ah yes, that seems to be the case. This works, thanks again!
var tr = pm.tr
pm.doc.nodesBetween(pm.selection.from, pm.selection.to, (node, pos) => {
if (node.type.attrs.level) {
newAttrs = Object.assign({}, node.attrs)
newAttrs.level = 3
tr.setNodeType(pos, node.type, newAttrs)
}
})
tr.apply()
1 Like