GetmeUK / ContentTools

A JS library for building WYSIWYG editors for HTML content.
http://getcontenttools.com
MIT License
3.95k stars 393 forks source link

Ability to unformat by class #492

Open koutsenko opened 6 years ago

koutsenko commented 6 years ago

Hello.

content-tools.js, String.prototype.unformat. Seems it can operate only with specified tags (b, i, span, div etc).

But what if I applied span class="fontsized", span class="fontfamily" etc? (with some style applied, but it doesn't matter).

How can I work, for example, with spans which differs only by class or another attribute?

anthonyjb commented 6 years ago

Hi @koutsenko,

It's a while since I've worked with that code but I believe the following is how it's intended to work and I hope that answers your question.

const myString = new String('some <span class="fontsized">text</span> some <span class="fontfamily">other</span> text')

// Remove all spans
myString.unformat(0, -1, 'span')

// Remove a span with the given head (attributes)
myString.unformat(0, -1, new Tag('span', {'class': 'fontsized'}))

Relevant code is here: https://github.com/GetmeUK/HTMLString/blob/master/src/characters.coffee#L113

Let me know if that helps you out.

koutsenko commented 6 years ago

Hello, @anthonyjb I already tried that, but seems it does not work (source). If i apply tool to selected range 3 times , i 'll get 3 wrapped spans :(

anthonyjb commented 6 years ago

@koutsenko OK but from the code you sent me it looks like you're always sending a tag not a string, if you want to clear all span tags you should just send the string 'span'?

Apologises if I'm missing something here :(

koutsenko commented 6 years ago

You say about lines 33-39?

image

I just try to overwrite old span. But because i can only replace tags, i trying delete old span tag and wrap content to new span tag. Maybe I do something wrong?

anthonyjb commented 6 years ago

Does this resolve?

element.content = element.content.unformat(from, to, 'span')
element.content = element.content.format(
    from, 
    to, 
    new Tag('span', {'class': 'fontfamilied', 'style': 'font-family: ' + family})
)
element.updateInnerHTML()
koutsenko commented 6 years ago

element.content = element.content.unformat(from, to, 'span')

hmmm.... first line of your snippet. It will remove any span, even if it is span class = "fontsized", or another feature not related to "fontfamily"?

anthonyjb commented 6 years ago

@koutsenko that's correct, you can remove all spans, or spans that match exactly some head (e.g <span attr="value">), there's nothing inbetween I'm afraid, you'd have to write something that went through each character and performed your required match and manually removed applicable tags.

koutsenko commented 6 years ago

But i don't want to remove all spans in selected region. I want remove only spans with font-sized class. And apply a new font-sized class with new style attr got from Tool.

anthonyjb commented 6 years ago

@koutsenko like I say it wont part match tags, if the existing span has other attributes it wont match your initial unformat tag (which doesn't have a style attribute against it).

koutsenko commented 6 years ago

I checked your code now. Use case:

Before: <span class="fontsized" style="font-size: '15px'> <span class="fontfamilied" style="font-family: 'roboto'"> blablabla </span> </span>

Expectation: I selected all text, used tool "fontsized", chose 22px and expected next result: <span class="fontsized" style="font-size: '22px'> <span class="fontfamilied" style="font-family: 'roboto'"> blablabla </span> </span>

Real behaviour: <span class="fontsized" style="font-size: '22px'> blablabla </span>

koutsenko commented 6 years ago

Okay, lets try again.

Lets assume that we have p class 'ce-element' -> span class 'fontsized' -> span class 'fontfamilied' -> span class 'fontsized' -> ... -> some text node. Some of that spans have class 'font-sized'.

I selected all text node. And applied a 60px font size. I want remove all span class 'font-sized' nodes and wrap them to new font-sized with new 60px style. Result would be p class 'ce-element' -> span class 'font-sized' style font-height 60px -> span class 'fontfamilied' -> some text node.

All fontsized spans must be dropped recursively. All non-fontsized spans must leave as is. And in the end, i wrap it to new fontsized span with my style.

Is it real and with what algorithm?