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

Text inside editable span wrongly wrapped with <p> #865

Open
wollmers opened this issue Nov 1, 2015 · 10 comments
Open

Text inside editable span wrongly wrapped with <p> #865

wollmers opened this issue Nov 1, 2015 · 10 comments
Labels

Comments

@wollmers
Copy link

wollmers commented Nov 1, 2015

For proofreading and corrections of OCR output I want to allow only editing on the lowest level of <span>word</span>.

This is a (very simplified) example of the HTML structure:

<p>
   <span class='line'>
      <span class='word'>The</span> 
      <span class='word'>quick</span>
   </span>
</p>

<script>var editor = new MediumEditor('.word');</script>

Now when I click into one of the words, the text inside the span is wrapped with <p> at the first key stroke and looks like this:

<p>
   <span class='line'>
      <span class='word'>
          <p>The</p>
      </span> 
      <span class='word'>quick</span>
   </span>
</p>

Tried hard, but could not find a configuration option, work-around or the location in the source code causing this.

I would expect to keep the HTML elements as they are if valid HTML. Also wrapping with an element without some class like e.g. 'medium-created' does not give me the chance to overrule the CSS with display: inline; So the lines are split into paragraphs for each word, when I want to navigate from one editable word to the next with the TAB key. That destroys the WYSIWYG.

@wollmers
Copy link
Author

wollmers commented Nov 1, 2015

Same behaviour with a plain

<h1>Header</h1>

which also gets the text wrapped with <p> after any keystroke, even just cursor right:

<h1><p>Header</p></h1>

Also the layout does not keep position. Before:

bildschirmfoto 2015-11-01 um 19 37 57

After:

bildschirmfoto 2015-11-01 um 19 40 14

And worse for the spans:

bildschirmfoto 2015-11-01 um 19 43 18

Ok, seems to be a browser specific issue. The above is for Chrome Version 46.0.2490.80 (64-bit).

Here Safari Version 9.0 (9537.86.1.56.2):

bildschirmfoto 2015-11-01 um 19 51 34

And Firefox 41.0.2 seams visually ok:

bildschirmfoto 2015-11-01 um 19 55 13

But copies the parent element and leaves one of the copies empty:

Before:

<p>
   <span class='line'>
      <span class='word'>The</span> 
      <span class='word'>quick</span>
   </span>
</p>

After:

<p>
   <span class='line'>
      <span class='word'>The</span> 
  </span>
  <span class='line'>
  </span>
  <span class='line'>
     <span class='word'>quick</span>
  </span>
  <span class='line'>
  </span>
</p>

So I will get two lines for each word in my final application, because I have

span.line { display: block; }

defined in the CSS.

@forgandenny
Copy link

Using Chrome 46.0.2490.80. This line does it - what is the reason for it?

if (MediumEditor.util.isMediumEditorElement(node) && node.children.length === 0) {
    this.options.ownerDocument.execCommand('formatBlock', false, 'p');
}

It fails to add a paragraph in Firefox though -- either a bug or Firefox feature?

@wollmers
Copy link
Author

wollmers commented Nov 6, 2015

@forgandenny Commented it out but nothing changes on the wrong behaviour. Chrome version is the same as yours.

Don't know what the reason is. I want to edit the text in a span and medium editor should not change the span, only the text in it should change.

@nmielnik
Copy link
Member

So the browser would be the one splitting/adding/removing these <span> elements. Normally, this won't be a problem because <span> are inline elements. By style <span> as display: block you're causing these <span> elements to have line breaks.

Would there be a problem with using <div> tags instead of <span> for you elements? They are block elements that browser understands and won't split up. Implementing a solution for not allowing the browser to insert <span> elements seems almost unreasonable because of the many situations this occurs.

@forgandenny
Copy link

Not sure about <span> issue but <h1><p>Header</p></h1> doesn't look right.

@wollmers
Copy link
Author

Yes, this is a problem, because the HTML is hOCR, a widespread format produced by OCR programs and many tools supporting it. So a possible work around would be converting to

<div class='word' style="display: inline">

and then convert back?

Tried it, and it doesn't work. Same behaviour.

@nmielnik are you sure the browser is the reason? I don't think so.

@nmielnik
Copy link
Member

The browser will attempt to insert <span> elements into the editor with the assumption that they will remain inline elements. If there is CSS on the page that makes the <span> be display: block I think you'll run into a lot of problems.

Can you try starting with this html instead? If the class line is just making things be display block, then I think you should try just using plain <div> or <p> elements instead (they are block elements that the browser expects to be block elements).

<p>
   <span class='word'>The</span> 
   <span class='word'>quick</span>
</p>

@wollmers
Copy link
Author

@nmielnik I tried now nearly every combination. Try yourself:

<p>
  <span class='word'>The</span>
  <span class='word'>quick</span>
</p>
<script>var editor = new MediumEditor('.word',{});</script>

Then try this:

<p>
  <span class='word' contenteditable="true">The</span>
  <span class='word' contenteditable="true">quick</span>
</p>

Without medium-editor it works like a charm. So it's not the browsers problem, it's a bug in medium-editor. The browser (Chrome) only inserts
on the enter/submit key. Nothing else.

Without medium-editor I can also wrap the words with a span of display:block. Also the navigation with or from word to word works. Seems I should use the plain contenteditable and base my js on this.

@Dattaya
Copy link

Dattaya commented Jan 5, 2016

I use this code (in my React app) as a workaround for this bug (it allows for editing inside a non-block element, because in editing mode I don't want it to transform to block-level and take all the space):

      <span>
        <div style={{margin: 0, padding: 0, display: 'inline-block'}} dangerouslySetInnerHTML={{__html: html}}/>
      </span>

Medium editor is attached to the span; this is how html is collected on editableInput event: mediumElement.firstElementChild.innerHTML. Everything works fine when initial html is present. But when I create a new field, the editor puts new text inside the span element instead of the div:

<span data-medium-focused="true" class="" data-placeholder="Enter text here." medium-editor-index="0" aria-multiline="true" role="textbox" data-medium-editor-element="true" spellcheck="true" data-reactid=".1tjlu9nhreo.1.0.1.0.1.0.2.1.0" contenteditable="true">
  test
  <div style="margin:0;padding:0;display:inline-block;" data-reactid=".1tjlu9nhreo.1.0.1.0.1.0.2.1.0.0">
  </div>
</span>

Is it possible to somehow tell the editor to always put new data inside that inner div tag?

@Dattaya
Copy link

Dattaya commented Jan 15, 2016

Using a single div with inline-block and disableReturn + disableDoubleReturn options completely (seems like it is) solved my problem. Now my component looks like this:
componentDidMount:

if (inline) {
      opts.disableReturn = true;
      opts.disableDoubleReturn = true;
    }

render:

    let props = {className};
    if (html) {
      props.dangerouslySetInnerHTML = {__html: html};
    }

    return (
      <div style={{margin: 0, padding: 0, display: 'inline-block'}} {...props} />
    );

, and I don't mind having a div inside a, say, h1, because this Editable component is only activated for moderators.

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

No branches or pull requests

4 participants