Todo list improvements

I created a demo on how to display a todo list with check boxes in prosemirror (kudos to kiejo for sharing the initial code): https://glitch.com/edit/#!/brass-hiss

It works quite well, but there are a few problems that i need help with:

Error in chrome when using backspace on an item

(This happens only in Chrome) When using backspace on a todo item, once i’ve reached the very first character and erase it (so that the todo item text is empty), i get an error in the console:

prosemirror.js:1 The given range isn't in document.

This doesn’t happen in Safari.

Splitting items

When splitting a todo item that is already marked as done, the new item will also be marked as done. How can i avoid that? I’d like a new todo item to be initialized always unchecked.

Lifting multiple items is not possible

It is not possible to lift a selection of multiple items. This is also true for the standard bullet and ordered list items. How can it be done?

2 Likes

This appears to be a combination of you setting the paragraph to be inline, Chrome deleting all parent nodes when an inline node is emptied, and ProseMirror not being able to deal with a node’s inner structure (the li > span structure you create for the items) being messed with.

You can probably work around this by using block structure for your list items (either with flexbox, absolute positioning, or inline blocks).

The default block-splitting command keeps the block markup for both sides of the split (unless it happens at the very end of the block). You can define your own special-purpose splitting command for when the cursor is in the middle of a task list item, and bind that to enter with a higher priority than the default.

The liftListItem command from prosemirror-schema-list does handle lifting multiple items.

Error in chrome when using backspace on an item

Ok, the core problem was contenteditable=false being set on the span for the checkbox - removing that solved it. Additionally, i refactored the code to not use inline elements and instead use flexbox - thanks for the hint.

Lifting multiple items is not possible

I’m not sure what i’m doing wrong then. For example, in the basic example, with the standard bullet list, the menu item for lifting items is not visible at all if the selection spans multiple items. Is there something i’m missing?

Clicking checkbox puts caret at beginning of input

I’m able to solve this in Safari by using user-select: none on the respective element. This fix does not work in Chrome unfortunately. I think what’s missing in the ProseMirror API is a handleMouseDownOn / handleMouseUpOn alongside the handleClickOn handler (unless i’m missing something). With the MouseDown handler i think i could call e.preventDefault() to solve the problem. I can create an issue for that on GitHub if you think it’s a feasible suggestion.

Here’s the updated version: https://glitch.com/edit/#!/peridot-velvet

That’s not the list-aware command, that’s the basic one from prosemirror-commands.

You could use handleDOMEvents and do the position resolution yourself.

Ok, i tried to get this working, but i need some help. Here’s my code: Glitch :・゚✧

The liftListItem command seems to return false always. What am i doing wrong?

In the glitch demo, the problem is that you’re reading .node.list_item from schema, rather than mySchema, and that’s undefined.

Ouch, indeed! Thanks for catching that.

Here’s the final version (i like the auto generated name on this one): Glitch :・゚✧

It supports multiple levels of todos. Checking a parent todo will mark all child todos as done (this is done with css only). It includes a menu item for lifting multiple list and todo items.

There’s some room for improvement:

  • splitting a checked todo will create two checked todos. It might be preferable to create an unchecked one
  • when checking all child todos, their parent todo is not automatically checked
  • conversely, when unchecking a parent todo, it’s child todos are not automatically unchecked

Thanks @marijn for your help and also for creating this awesome library.

2 Likes