Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom inline blot with <span> and className not working. #1866

Closed
andresinaka opened this issue Dec 13, 2017 · 11 comments
Closed

Custom inline blot with <span> and className not working. #1866

andresinaka opened this issue Dec 13, 2017 · 11 comments

Comments

@andresinaka
Copy link

I'm creating a custom inline blot. I want to use span and style it with css. I read in the: "Cloning Medium with Parchment" tutorial the following:

Note Inline blots use <span> and Block Blots use <p> by default, so if you would like to use these tags for your custom Blots, you will have to specify a className in addition to a tagName.

And I'm creating this:

class TestBlot extends Inline { }
TestBlot.blotName = 'thick';
TestBlot.tagName = 'span';
TestBlot.className = 'test-class';
Quill.register(TestBlot);

And it's not working. But if I change the tagName to spann it does work! What am I missing here?! What's the right way of doing this?

Thanks!

@benbro
Copy link
Contributor

benbro commented Dec 14, 2017

Please follow the issue template and include all the requested info.
Also, fork the CodePen show what you tried to do and what doesn't work.

@andresinaka
Copy link
Author

andresinaka commented Dec 14, 2017

Thanks @benbro! Here is the template!

Steps for Reproduction

  1. https://codepen.io/andresyo990/pen/jYPmmo?editors=0110
  2. Write something on the editor, select what you wrote, and touch the "Test" button
  3. Nothing happens.

Expected behavior:

A new <span class="test-class">selected text</span> is created in the html editor.

Actual behavior:

Nothing happens.

Platforms:

Chrome, Safari, Firefox (and I think all the others but those are the ones I have)

Version:

Version: 1.3.4

@benbro
Copy link
Contributor

benbro commented Dec 15, 2017

Duplicate:
https://stackoverflow.com/questions/47811541/custom-inline-blot-with-span-and-classname-not-working/47820727#47820727

@benbro benbro closed this as completed Dec 15, 2017
@chrisronline
Copy link

Hi @benbro,

That link doesn't resolve anymore. Is it possible for someone to repeat the information? I'm interested in how to get around this too.

@dannyrb
Copy link

dannyrb commented Aug 30, 2018

@benbro. I am experiencing the same issue, and finding that the link is now a dead end.

@dkreft
Copy link

dkreft commented Sep 14, 2018

@dannyrb, @chrisronline : Take a look at https://github.com/quilljs/parchment/blob/master/src/blot/inline.ts#L23

There you will see this:

if (domNode.tagName === InlineBlot.tagName) return undefined;

It's not clear why this line is there or why it should return undefined, but if that line is commented out, you then invoke FormatBlot.formats(domNode) (https://github.com/quilljs/parchment/blob/master/src/blot/abstract/format.ts#L11-L18)

static formats(domNode: HTMLElement): any {
    if (typeof this.tagName === 'string') {
      return true;
    } else if (Array.isArray(this.tagName)) {
      return domNode.tagName.toLowerCase();
    }
    return undefined;
  }

On a whim, I simply did this:

export default MyCustomInline extends Inline {
  static tagName = 'span'

  formats() {
    return MyCustomInline.tagName
  }
}

...and that got things working for me.

I have no idea what side effects my "solution" will have, as I'm still learning my way about the API, and the documentation only says:

  // Returns format values represented by domNode if it is this Blot's type
  // No checking that domNode is this Blot's type is required.
  static formats(domNode: Node);

...which seems rather arcane and unhelpful.

When I set a breakpoint inside InlineBlot#parchment() (https://github.com/quilljs/parchment/blob/master/src/blot/inline.ts#L50-L61), I can see that other inline elements (e.g. <b> and <i>) return an object from .formats():

  {
    bold: true
  }

But it really doesn't seem to matter (as far as I've cared to dig) whether you return a mapping of tags to truthy values or if you simply return a string...though I am assuming that the mapping is more correct...again, for reasons that do not appear to be documented.

It probably goes without saying that It's very disappointing to have this issue unceremoniously closed by @benbro with nothing more than a link to SO (which has been noted already, is dead), and then pretty much ignored as others have expressed a desire for a real resolution. This does not reflect well on the project.

@dannyrb
Copy link

dannyrb commented Sep 14, 2018

@dkreft completely forgot about this issue. I had a similar experience. I kept playing and landed on something that looked like this:

// https://github.com/quilljs/parchment/#blots
import Quill from 'quill'
let Inline = Quill.import('blots/inline')

class SpellingBlot extends Inline {
  static create(value) {
    let node = super.create(value)
    node.setAttribute('data-invalid-spelling', '')
    node.setAttribute('data-alternative-spellings', [])
    return node
  }

  static formats(domNode) {
    return {
      isInvalidSpelling: domNode.hasAttribute('data-invalid-spelling'),
      alternativeSpellings: domNode.getAttribute('data-alternative-spellings'),
    }
  }
}

SpellingBlot.blotName = 'spelling'
SpellingBlot.className = 'spelling'
SpellingBlot.tagName = 'SPAN'

export default SpellingBlot

Originally, I only wanted the spelling class applied to the formatted section. When I couldn't get that to work, I began looking at code that would allow me to set a custom data-* annotation. After adding the create and formats methods, the spelling class appeared.

This seems to imply that there is more required to creating an extended Inline Blot than suggested in the documentation. 🤷‍♂️

@Doidel
Copy link

Doidel commented Oct 19, 2019

I'm having the same issue. Any updates here? I'm unable to figure out Inline with span and class.

@scrimothy
Copy link

scrimothy commented Oct 28, 2019

Adding to what @dkreft said (which completely fixed my same issue):

Looking at that codeblock (from https://github.com/quilljs/parchment/blob/master/src/blot/abstract/format.ts#L11-L18)

static formats(domNode: HTMLElement): any {
    if (typeof this.tagName === 'string') {
      return true;
    } else if (Array.isArray(this.tagName)) {
      return domNode.tagName.toLowerCase();
    }
    return undefined;
  }

Because the first check in formats is to determine if tagName is a string, and thus returns true, then since my tagName = 'span', then I just added my own formats function like this:

static formats(): boolean {
  return true;
}

Still seems silly for this to be required, but until there's a legit fix internally, this seems to be working properly. I can't think of any possible side effects this would have since in my case (with tagName = 'span') this function should've normally returned true. Only thing I don't quite understand why the InlineBlot would first do this if (domNode.tagName === InlineBlot.tagName) return undefined; in its formats function.

So, my stripped down blot class looks like this:

export class TagBlot extends Inline {
  static blotName = 'tag';
  static className = 'aur-tag';
  static tagName = 'span';

  static formats(): boolean {
    return true;
  }
}

And it's finally appending the span.aur-tag element to the selection in my editor

@falk-stefan
Copy link

@scrimothy somehow this is not working for me slab/parchment#118

@WindySpoon
Copy link

I'm going to bump this, @scrimothy 's fix worked for me but I'm wondering if there's any plans on fixing this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants