st-h/ember-content-editable

Placeholder should reappear after deleting content (Firefox)

markusm7 opened this issue · 4 comments

In my application and also on the demo page, if you enter some text and then delete everything, the placeholder does not reappear, because the component contains a single br-tag, hence the :empty selector won't apply.

This is even the case if allowNewLines is set to false, which would make no difference in my case, cause i need new lines

Is there any possibility to change this? I would really appreciate such behaviour.

EDIT: This is a Firefox behaviour with contenteditable, but my point still remains: could we add something like a check if nothing else remains in the input except a br-tag, we remove this from the DOM?

st-h commented

Thanks for reporting. I had a look and it seems like this is a browser bug. Firefox and Safari seem to add the br tag you mentioned once the last character is deleted. Chrome never seems to be doing any of this.

Firefox seems to add new <div> elements for each newline. Interestingly, if you enter multiple lines and delete them again, this bug does not appear.

Safari, however, seems to use <br> tags internally when a newline is entered. It also seems to add additional whitespace characters, so you quickly can end up with something like this:

<div contenteditable="true">
""
""
<br>
""
""
</div>

I am afraid if we just try to remove the <br> tag some browser sometimes add, we will break other stuff, like removing an intentionally entered newline character at the beginning.

You can all reproduce this with just a plain <div contenteditable="true"></div> and looking at the dom, so this is nothing specific to this add-on.

I think the "right" way to fix this would be to report those bugs to browser vendors. However, I know how that usually goes as I opened a severe bug regarding web audio at apple a few months ago, which still has not been noticed or acknowledged in any way.

For now the only way I can think of to fix it within this add-on would be to add browser specific code and behaviour, which very easily will end up in a complicated mess. However, if you have any good ideas to fix this, I'll happily accept a PR.

I was also thinking if we could make use of textContent instead of innerText, as this does not contain the offending newline, however that also comes with modifications on whitespaces which will mess up other things.

I am really lacking a good idea to work around this right now.

I came upon the css :blank pseudo class and was wondering if we could use that as a workaround - however, unfortunately it is kind of not supported anywhere... However, I am inclined to think that using css to workaround the issue will be the easiest way. Probably something like assigning a class when we think the content is blank, which however would be overridden by the actual content, in case we missed it. But that is rather a guess than something I know would work.

Yeah, i digged in a bit for myself. As you mentioned reporting the bug and hoping it gets noticed, acknowledged and fixed in a reasonable time is not very likely.

Adding browser specific code isn't a thing i would encourage and is, as you mentioned, a complicated mess in the long run.

The longer im thinking of it the less I'm sure if it's worth try to figure out a fix/workaround which wouldn't lead to other side effects or just bad code.

One thing i came across is the web based application of whatsapp, which seems to solve this by doing everything with javascript -> "cleaning" the input on every keypress/insertion or something like that

If no one else is having a problem with it or has a solution for this, I don't mind if we close the issue and continue as it never was a thing :)

st-h commented

Well the idea behind the current implementation was that browsers know how to handle and manage a element where contenteditable is enabled. The add-on pretty much listens to changes of the content of that field and then only needs to manage its own variable. If the change is initiated by the user editing the field, the element should already be in its desired state and we don't need to modify the element. If the change comes from changing the value of the bound variable, then we need to change the content of the element, so that the user sees the current value.
I think the downside with trying to clean the element content on each keypress is that we would need to start managing the cursor position. For instance if the user edits a different position than the end of the string, and we erase the content of the element and fill it with the current value, the cursor position will end up at the wrong position (likely at the end or the beginning of the string).
If I can find enough time in the next time, I will have a look how other frameworks are dealing with contenteditable elements and placeholders - maybe there is a good idea buried somewhere.

You are absolutely right. Ideally every browser knows how to deal with it and implements features like that the same way, but we both know that won't happen in a forseeable future.

If I find some time myself and/or stumble upon another solution I'll let you know