Opened 10 years ago

Closed 7 years ago

#9638 closed defect (fixed)

RichText emits textarea element into HTML head when included in a layer

Reported by: hwinkler Owned by: bill
Priority: high Milestone: 1.7
Component: Editor Version: 1.3.2
Keywords: RichText Cc:
Blocked By: Blocking:

Description

When dijit._editor.RichText?.js gets included in a layer using the dojo build system, and you load that layer file via a <script> tag in the <head> , that RichText? declaration code emits a <textarea> into the <head>, causing some browsers (Safari 4, FF 3.5) to close off the <head> and insert a fake <body> element. The resulting DOM is pretty borked and causes other dojo/dijit stuff to render unpredictably. I'm uploading files that demonstrate the problem. Unzip the the file to your hard disk ond view richtext-bug.html in Safari 4 or FF 3.5.

richtext-bug.html: demonstrates the problem. ws.js is a custom layer file with the single dependency 'dijit.Editor'. The resulting ws.js pulls in several files including dijit._editor.RichText?. Following the <script> tag that loads ws.js, there is a <link> element. Its true parent should be the <head>. However, because the RichText? declaration borks the DOM, the browser emits everything following the <script> element into the <body>, and that link element's parent becomes the <body>. If that link element's parent is the <body> the test page prints out an error message.

richtext-ok.html demonstrates one workaround -- load the ws.js file from a script tag in the body. Unsure if that's practical in some situations.

Also included is the generated ws.js, the profile.js I used to make it, and the dojo.js from 1.3.2 for completeness.

Attachments (1)

dojo RichText bug.zip (171.2 KB) - added by hwinkler 10 years ago.

Download all attachments as: .zip

Change History (11)

Changed 10 years ago by hwinkler

Attachment: dojo RichText bug.zip added

comment:1 Changed 10 years ago by hwinkler

Oh I forgot to mention, the offending line is line 4320-21 in ws.js:

dojo.doc.write('<textarea id="' + dijit._scopeName + '._editor.RichText.savedContent" ' +
				'style="display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;"></textarea>');

comment:2 Changed 10 years ago by hwinkler

Here's a patch that works for me. If dojo._postLoad is false, just execute the textarea creation in a dojo.addOnLoad:

--- a/dijit/_editor/RichText.js +++ b/dijit/_editor/RichText.js @@ -13,25 +13,24 @@ dojo.requireLocalization("dijit.form", "Textarea");

file. If it is included in dojo.js and you want to allow rich text saving for back/forward actions, then set dojo.config.allowXdRichTextSave = true.

if(!dojo.configuseXDomain?
dojo.configallowXdRichTextSave?){
  • if(dojo._postLoad){
  • (function(){

+ var scopeName = dijit._scopeName; + var fn = function(){

var savetextarea = dojo.doc.createElement('textarea');

  • savetextarea.id = dijit._scopeName + "._editor.RichText?.savedContent";

+ savetextarea.id = scopeName + "._editor.RichText?.savedContent";

dojo.style(savetextarea, {

display:'none', position:'absolute', top:"-100px", height:"3px", width:"3px"

  • });
  • dojo.body().appendChild(savetextarea);
  • })();

+ }); + dojo.body().appendChild(savetextarea); + }; + if(dojo._postLoad){ + fn();

}else{

dojo.body() is not available before onLoad is fired

  • try {
  • dojo.doc.write('<textarea id="' + dijit._scopeName + '._editor.RichText?.savedContent" ' +
  • 'style="display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;"></
  • }catch(e){ }

+ dojo.addOnLoad (fn);

}

}

comment:3 Changed 10 years ago by hwinkler

oops, format the patch better:

--- a/dijit/_editor/RichText.js
+++ b/dijit/_editor/RichText.js
@@ -13,25 +13,24 @@ dojo.requireLocalization("dijit.form", "Textarea");
 // file. If it is included in dojo.js and you want to allow rich text saving
 // for back/forward actions, then set dojo.config.allowXdRichTextSave = true.
 if(!dojo.config["useXDomain"] || dojo.config["allowXdRichTextSave"]){
-       if(dojo._postLoad){
-               (function(){
+       var scopeName = dijit._scopeName;
+       var fn = function(){
                        var savetextarea = dojo.doc.createElement('textarea');
-                       savetextarea.id = dijit._scopeName + "._editor.RichText.savedContent";
+                       savetextarea.id = scopeName + "._editor.RichText.savedContent";
                        dojo.style(savetextarea, {
                                display:'none',
                                position:'absolute',
                                top:"-100px",
                                height:"3px",
                                width:"3px"
-                       });
-                       dojo.body().appendChild(savetextarea);
-               })();
+                               });
+               dojo.body().appendChild(savetextarea);
+       };
+       if(dojo._postLoad){
+               fn();
        }else{
                //dojo.body() is not available before onLoad is fired
-               try {
-                       dojo.doc.write('<textarea id="' + dijit._scopeName + '._editor.RichText.savedContent" ' +
-                               'style="display:none;position:absolute;top:-100px;left:-100px;height:3px;width:3px;overflow:hidden;"></
-               }catch(e){ }
+               dojo.addOnLoad (fn);
        }
 }

comment:4 Changed 10 years ago by bill

Milestone: tbd1.4
Owner: set to bill
Status: newassigned

Hmm, sounds pretty bad. We can try to put that textarea creation in an onLoad() event as you suggested... I just need to check two things:

  1. Does the stabile code still work? The idea is that when a user clicks a link etc. the Editor save it's contents into that textarea, and then the browser saves the contents of the fields on the page (in particular this <textarea>)... then when the user presses the back button the browser renders the page and restores the value of the textarea, and the Editor restores it's value from the textarea. However, IIRC that's dependent on the textarea existing when the page is initially rendered.
  1. If dijit.Editor widgets are initialized before that textarea exists, will bad things happen? I think so, because when Editor initializes it tries to restore it's contents from that textarea. So addOnLoad() may be a little late.

IIRC there are some cases where the developer has to manually add a textarea to the boilerplate of the page, rather than depending on dijit to create it.

In any case this definitely sounds like a bug (with the only workaround to not put the editor into a layer.

comment:5 Changed 10 years ago by hwinkler

Maybe we need dojo.addOnLoad(priority). Default priority would be 0. Dojo would execute onload tasks in descending priority order. Then my patch would do the trick if it called dojo.addOnLoad(10).

comment:6 Changed 10 years ago by bill

Milestone: 1.41.5

comment:7 Changed 9 years ago by Adam Peller

Milestone: 1.51.6

comment:8 Changed 9 years ago by bill

Milestone: 1.62.0

I'll just remove all that textarea code for 2.0.

comment:9 Changed 8 years ago by bill

Component: DijitDijit - Form

comment:10 Changed 7 years ago by bill

Component: Dijit - FormEditor
Milestone: 2.01.7
Resolution: fixed
Status: assignedclosed

Actually, it was removed when we converted everything to AMD, in in [24328].

Note: See TracTickets for help on using tickets.