deform icon indicating copy to clipboard operation
deform copied to clipboard

RichtText content dissapear on form submission when embeded in a sequence

Open tonthon opened this issue 9 years ago • 6 comments

Create a sequence of Mappings with RichTexts Add a sequence item Delete that item Add a sequence item Fill the text Submit your form

The text you filled has disappeared

tonthon avatar Sep 17 '15 13:09 tonthon

import deform
import colander

class DemoMapping(colander.MappingSchema):
    item = colander.SchemaNode(
        colander.String(), 
        widget=deform.widget.RichTextWidget()
)

class DemoSeq(colander.SequenceSchema):
    items = DemoMapping()


schema = DemoSeq()
form = Form(schema, buttons=('valid',))

tonthon avatar Sep 17 '15 13:09 tonthon

I'm not sure whether this is the issue here, but I think the top-level schema should always (or usually?) be a MappingSchema (aka Schema). (FormWidget inherits from MappingWidget, and really wants to work with a value that is a mapping, not a sequence.)

See http://deform2demo.repoze.org/sequence_of_richtext/ for an example.

dairiki avatar Sep 18 '15 00:09 dairiki

No, it's not related to the use of a MappingSchema or a SequenceSchema. It's related to the js code that binds the editor to the hidden textarea. Something like

delete tinyMCE.editors.<editor_name>

should be thrown while adding a sequence item.

tinyMCE.execCommand('mceAddEditor', false, 'editor_name');

should be thrown while adding a sequence item.

I should lead more investigation on this issue in the coming days. Hope I'll come with a solution.

tonthon avatar Sep 21 '15 09:09 tonthon

The problem comes from tinymce's triggerSave method. Since we don't delete the tinymce instances we create, tinyMCE.editors contains editors not matching an existing textarea. tinyMCE.triggerSave() fails on the first editor not matching an element existing in the DOM.

1- I add an item in my sequence (item1) 2- I remove the line (the tinyMCE editor item1 still exists) 3- I add and fill a line (item2) 4- I submit 5- triggerSave fails while setting the content of the editor on the item1's textarea and doesn't set the content of the following one (item2). The error : NS_ERROR_UNEXPECTED (impl = node.ownerDocument.implementation;) 6- Most important point : :-1: The end user has lost his datas

The following hack fixes the issue. I'm not sure how it should be implemented in deform, if anyone has an idea, I'll be glad to make a PR

function cleanTinyMceEditors(event, form){                                      
  for (var i=0; i < tinyMCE.editors.length; i++){                               
    var editor = tinyMCE.editors[i];                                            
    if ($("#" + editor.id).length === 0){
      try{                                                                      
        i = i-1;                                                                
        delete tinyMCE.remove(editor);                                          
      } catch (e){}                                                             
    }                                                                           
  }                                                                             
  tinyMCE.triggerSave();                                                        
}
$('form').on('submit.cleanEditors', cleanTinyMceEditors);

tonthon avatar Sep 22 '15 08:09 tonthon

PR's still welcome :)

miohtama avatar Dec 06 '16 09:12 miohtama

@tonthon I'd like to see this get into an upcoming release of Deform. I'm happy to help. The function would go into deform.js with a check, making sure it only loads for sequence of mappings of richtexts, if possible. I can also help with functional tests in deformdemo. Please let me know. Thank you!

stevepiercy avatar Aug 24 '20 12:08 stevepiercy