Opened 8 years ago

Closed 6 years ago

#5517 closed Bug (duplicate)

Extra <p>&nbsp;</p> when pasting in webkit

Reported by: Pablo Vanwoerkom Owned by:
Priority: Normal Milestone:
Component: Core : Pasting Version: 3.0
Keywords: HasPatch Cc:

Description

When pasting in Webkit, there is often an extra <p>&nbsp;</p> added when you look at it in the Source view. The reasons seem to be:

  1. Webkit adds a <meta> tag on html paste.
  1. Webkit adds a <span class='Apple-style-span'> wrapper to the pasted content.
  1. When pasting onto a new paragraph, if the pasted html contains block elements such as <p> or <h1>, it seems the ckeditor tries to clean that the nonstandard DOM but an empty <p>&nbsp;</p> is added as a result.
  1. When the current selection is on a block element and you paste other block elements at that point, an extra block element gets prepend before the pasted content. This extra block element has the same tagName as the existing block element (same attributes as well) and its inner HTML contains only "&nbsp;".

I've come up with a way to deal with issues 1-3, but not 4. Right now I apply the following clean up code on a paste event when it doesn't contain Microsoft word junk. If you have some feedback or know of a better way please let me know. I am not sure where this would go if it were to be a patch.

CKEDITOR.on('instanceCreated', function(e) {


  if(CKEDITOR.env.webkit){
    editorInstance.on('paste', function(evt) {
      var data = evt.data;
      data['html'] = data['html'].replace(/<(META|LINK)[^>]*>\s*/gi, '' );
      /* If not pasting from word and pasting into a new paragraph,
       * clean up code, replace paragraph element, and cancel paste action.
       * Otherwise continue with paste event. */
      if( !( /(class=\"?Mso|style=\"[^\"]*\bmso\-|w:WordDocument)/ ).test( data['html'] ) ){
        var temp_div = document.createElement("div");
        temp_div.innerHTML = data['html'];
        //remove Webkit span wrapper tag
        if( (temp_div.childElements().length == 1) && (temp_div.childElements()[0].className.indexOf('Apple-style-span') > -1 ) ){
            data['html'] = $(temp_div).childElements()[0].innerHTML;
            temp_div = document.createElement("div");
            temp_div.innerHTML = data['html'];
        }
        var selection = editorInstance.getSelection(),
                range = selection.getRanges()[0],
                    orgStart = range.startContainer,
                       orgEnd = range.endContainer,
                         nextElement = orgStart.getNext();

        if(/^\s*<br>\s*$/.match(orgStart.$.innerHTML) && (orgStart.$.tagName =='P') ){
            var newRange = new CKEDITOR.dom.range(range.document),
              fragment=document.createDocumentFragment();
              
            for(var mynode=0;mynode< temp_div.childNodes.length; ++mynode){
                if(typeof temp_div.childNodes[mynode] == 'object'){
                    if(temp_div.childNodes[mynode].nodeName == '#text'){
                      fragment.appendChild(document.createTextNode( temp_div.childNodes[mynode].data ) );
                    }else{
                      fragment.appendChild(temp_div.childNodes[mynode].cloneNode(true));
                    }
                }
            }

            orgStart.$.parentNode.replaceChild(fragment, orgStart.$);
            //Reset cursor to before next element or end of the editor's content
            if(nextElement){
                newRange.setStartAt(nextElement, CKEDITOR.POSITION_BEFORE_START);
                newRange.setEndAt(nextElement, CKEDITOR.POSITION_BEFORE_START);
            }else{
                newRange.setStartAt(editorInstance.document.getBody(), CKEDITOR.POSITION_BEFORE_END);
                newRange.setEndAt(editorInstance.document.getBody(), CKEDITOR.POSITION_BEFORE_END);
            }
            newRange.select();
            evt.cancel();
        }
      }
   });



});



Change History (3)

comment:1 Changed 8 years ago by Pablo Vanwoerkom

I forgot to add the code for initializing editorInstance. It should be:

CKEDITOR.on('instanceCreated', function(e) {

var editorInstance = e.editor;

...etc...

comment:2 Changed 6 years ago by Jakub Ś

Keywords: HasPatch added; pasting webkit extra paragraphs removed
Status: newconfirmed
Version: 3.23.0

Points 1 & 2 are no longer reproducible in latest Webkit and latest CKEditor. There is no meta tag and span tag is now replaced by div.

Points 3 & 4 on the other hand have been reproducible in Webkit from CKEditor 3.0.

To reproduce point 3:

  1. Switch to source and paste the below code into CKEditor
    <h1>
    	<img alt="" src="http://a.cksource.com/c/1/inc/img/demo-little-red.jpg" style="margin-left: 10px; margin-right: 10px; float: left; width: 120px; height: 168px;" />Little Red Riding Hood</h1>
    
  2. Switch to WYSIWYG and copy contents using CRTL+A CRTL+C
  3. Open another page with CKEditor, clear contents using CRTL+A Backspace
  4. Paste using CRTL+V

Reproducible in Chrome and Safari.

To reproduce point 4:

  1. Open any CKEditor with sample text. Press CRTL+A, CRTL+C, CRTL+V. It is best if paragraph would contain some attributes E.g.
    <p id="someElemId">
    		This is some&nbsp;sample text. You are using&nbsp;CKEditor.</p>
    

Result:

<p id="someElemId">
	&nbsp;</p>
<div style="font-family: Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, 255, 255); ">
	<p id="someElemId">
		This is some&nbsp;sample text. You are using&nbsp;CKEditor.</p>
</div>
<p>
	&nbsp;</p>

Reproducible in Safari (Chrome 17 is free of this bug).

Last edited 6 years ago by Jakub Ś (previous) (diff)

comment:3 Changed 6 years ago by Jakub Ś

Resolution: duplicate
Status: confirmedclosed

Points 3 and 4 are actually the same.
Further more this issue has been described in smaller parts in #6131, #8231 and #7146.

I'm closing this one as DUP.

Note: See TracTickets for help on using tickets.
© 2003 – 2017 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy