tagify icon indicating copy to clipboard operation
tagify copied to clipboard

Backspace key does not remove tag in mix mode under specific situation

Open YoonHan opened this issue 1 month ago • 4 comments

I have searched around issues related to this issue in this repository but I could not found one so that I post this. Please let me know if there is any workaround of this issue.

Prerequisites

  • [x] I am running the latest version
  • [x] I checked the documentation and found no answer
  • [x] I checked to make sure that this issue has not already been filed

💥 Demo Page

  1. See Tagify documentation's Mix Text & Tags section(https://yaireo.github.io/tagify/#section-mix).
  2. Type @kenny and Enter. This creates a new tag(kenny).
  3. Make a newline by pressing enter.
  4. Type @stan and Enter. This creates a new tag(stan).
  5. Make a newline by pressing enter.
  6. Try to remove the tag stan by pressing Backspace key but it doesn't work.

https://github.com/user-attachments/assets/af432942-f995-439c-b85c-0a74fb9bb542

Explanation

  • What is the expected behavior? Backspace key should remove the tag when the caret position is right next to a tag.

  • What is happening instead? Backspace key does not remove the tag located at the left to the caret position.

  • What error message are you getting? No error message.

YoonHan avatar Nov 17 '25 04:11 YoonHan

I guess this issue arises when the previous sibling of <tag> element is just <br />.

Image

YoonHan avatar Nov 17 '25 04:11 YoonHan

So, I came up with a solution that puts ZERO_WIDTH_CHAR as a previous sibling of a newly created tag element. Would it be right approach to this issue?

YoonHan avatar Nov 17 '25 04:11 YoonHan

My possible workaround for this issue is like below,

// src/tagify.js
...
import { UPDATE_DELAY, ZERO_WIDTH_CHAR } from './parts/constants'

function Tagify(input, settings) {
...

    /**
     * Adds a tag which was activly typed by the user
     * @param {String/Array} tagData   [A string (single or multiple values with a delimiter), or an Array of Objects or just Array of Strings]
     */
    prefixedTextToTag( tagData ){
        ...

        if( !createdFromDelimiters ) {
            var elm = this.insertAfterTag(tagElm) || tagElm;
            this.insertBeforeTag(tagElm, ZERO_WIDTH_CHAR) // <-- THIS LINE!!!
            // a timeout is needed when selecting a tag from the suggestions via mouse.
            // Without it, it seems the caret is placed right after the tag and not after the
            // node which was inserted after the tag (whitespace by default)
            setTimeout(placeCaretAfterNode, 0, elm);
        }

        ...
    },

...

    insertBeforeTag( tagElm, newNode ){
        if( !tagElm || !tagElm.parentNode || !newNode ) return
    
        newNode = typeof newNode == 'string'
            ? document.createTextNode(newNode)
            : newNode
    
        tagElm.parentNode.insertBefore(newNode, tagElm)
        return newNode
    },

...
}

YoonHan avatar Nov 17 '25 05:11 YoonHan

That is one solution but first I would like to research why this happens, maybe the are solutions to this which do not involve such a hack

yairEO avatar Nov 17 '25 17:11 yairEO