1

Topic: Dynamically loading TinyMCE's JS files

Is there any solution to load tinyMCE js files after loading the page?

I have read THIS topic but i get this error --> tinyMCE is not defined.

Image: Firebug error report

my full.htm example

Thanks

2

Re: Dynamically loading TinyMCE's JS files

Nothing?

3

Re: Dynamically loading TinyMCE's JS files

no.

Greetings from Germany,

Felix Riesterer.
(-> about me and this forum <-)

4

Re: Dynamically loading TinyMCE's JS files

Use the gzip compressor. It will load tinymce on demand. Check the online examples and wiki documentation.

Best regards,
Spocke - Main developer of TinyMCE

5

Re: Dynamically loading TinyMCE's JS files

Thanks for your reply

but is another way to use this function to load TinyMCE's JS files?

function LoadScript(file){
   var e = document.createElement("script");
   e.src = file;
   e.type="text/javascript";
   document.getElementsByTagName("head")[0].appendChild(e);
}

LoadScript('../jscripts/tiny_mce/tiny_mce.js');
LoadScript('mytinymce.js');

When i use this function i get error.

Thanks

6

Re: Dynamically loading TinyMCE's JS files

I am also running into this, because I want to load TinyMCE scripts dynamically.

It looks like this *could* be related to the fact that in tiny_mce.js there are lots of document.write commands - for example, to load plugin scripts.  Document.write won't work too well after you've completely loaded the page.

More as I work on this...

7

Re: Dynamically loading TinyMCE's JS files

Whew!  I've managed to fix this problem.  The problem is indeed that TinyMCE is doing document.write calls incorrectly, even if the entire page has been loaded.  However, there are variables you can set in TinyMCE that other parts of the code obey perfectly.  So you only have to change one line of code in tiny_mce_src.js (in 3.2.1.1).   That variable to change is Event.domLoaded - just set it to true.

Look for these lines at 2725 and 2726:

    // Shorten name
    Event = tinymce.dom.Event;

Simply add the following line after these lines:

    Event.domLoaded = true; // LINE ADDED TO PREVENT INLINE LOADING ERRORS ('Error: tinymce is not defined' due to erroneous document.write's)

The reason you have to add it after that line is because the Event variable (or the tinymce.dom.Event varable) isn't created until this line, so the only way to access the .domLoaded variable is after these lines.


This is more of a monkey patch rather than a full solution (and has only been tested in Mac FF and Mac Safari, and not IE).  That begs the question of how to turn it into a more scalable solution.



Spocke, is there any way to either:
   (1) take out all document.write calls and replace them with calls to tinymce.ScriptLoader.load() (which seems like less of a hack); or
   (2) have tiny_mce_src.js know whether or not the document has finished loading so you can avoid the document.write command; or
   (3) let the developer set some variable before tiny_mce_src.js is loaded so that it knows the dom has already completed loading and can avoid the document.write commands?

8

Re: Dynamically loading TinyMCE's JS files

Hi,
  I tried this solution and it works for me...
  in tiny_mce_src.js file, where ever we have document.write("<script>.....")
I have replaced with the following code and it works perfect...

var oHead = document.getElementsByTagName('HEAD').item(0);
var oScript= document.createElement("script");
oScript.type = "text/javascript";
oScript.src=tinymce._addVer(u);
oHead.appendChild( oScript);

It works in FF3 and IE6.

FYI:
majorVersion : '3',
minorVersion : '2.3.1',
releaseDate : '2009-05-05',

line no is: 6449 and  6598


Here is the code which will take all textarea and convert into tinymce editor based on its class name... this way you can have any number of configuration in a single page...
-------------------------------------------------
function loadEditors()
{
  var editors = document.getElementsByTagName('textarea');
var smpl = {
        theme : "simple",
        mode : "none",
        language : "en",
        height:"200",
        width:"100%",
        theme_advanced_layout_manager : "SimpleLayout",
        theme_advanced_toolbar_location : "top",
        theme_advanced_toolbar_align : "left",
        theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
        theme_advanced_buttons2 : "",
        theme_advanced_buttons3 : "" ,
    invalid_elements:'b',
    delta_width:"100"
  };
  var adv = { theme : "advanced",
        mode : "none",
        language : "en",
        height:"200",
        width:"100%",
        theme_advanced_layout_manager : "SimpleLayout",
        theme_advanced_toolbar_location : "top",
        theme_advanced_toolbar_align : "left",
    invalid_elements:'b',
    delta_width:"100"
  };
    for(var i = 0; i < editors.length; i++)
    {
      var id = editors[i].getAttribute('id');
      alert(id);
      var theme = null;
      if(editors[i].className == 'fullEditor')
    tinyMCE.settings=adv;
      else if(editors[i].className == 'simpleEditor')
    tinyMCE.settings=smpl;
      tinyMCE.execCommand('mceAddControl', false, id);

    }
}
-------------------------------------------------------------------------------------------------

Thanks for : http://tinymce.moxiecode.com/punbb/view … p?id=15382

9

Re: Dynamically loading TinyMCE's JS files

moorage wrote:

Look for these lines at 2725 and 2726:

    // Shorten name
    Event = tinymce.dom.Event;

Simply add the following line after these lines:

    Event.domLoaded = true; // LINE ADDED TO PREVENT INLINE LOADING ERRORS ('Error: tinymce is not defined' due to erroneous document.write's)

We also load and build up our pages with ajax, and two out of three times Tiny_Mce fails to load and gives us a blank page with an js-error(Tiny_Mce.js not defined). The above hack works great in FF3.0 but only works the first time in IE6, an improvement but still not perfekt.

I will try kunfupanda example next...

10

Re: Dynamically loading TinyMCE's JS files

Has anybody succeeded in making this work? I'm struggling yet still hasn't come up with a solution. As mentioned above, the script loads.. only sometimes (both in Firefox and IE).

11

Re: Dynamically loading TinyMCE's JS files

Can't see why you can't simply use the compressor it lazy loads tinymce or the jquery plugin it also lazy loads tinymce.

Best regards,
Spocke - Main developer of TinyMCE

12

Re: Dynamically loading TinyMCE's JS files

spocke wrote:

Can't see why you can't simply use the compressor it lazy loads tinymce or the jquery plugin it also lazy loads tinymce.

There is a problem with dynamic loading both "native" tinymce and lazy  loading
with compressor.
Saying "dynamic loading" I mean complete dynamic loading  when  tiny_mce.js  or
tiny_mce_gzip.js also loaded into the page dynamically.

Here is my use case:
I have GUI builder which creates dynamically tabled views  (for  example,  news
list) and edit forms where none or one or more textareas with tinyMCE can be used.
Forms are added to the page dynamically into jQuery / UI Dialog.
Forms is generated as a set of widget and I have a widget for tinyMCE.

Since this GUI builder is generic I do not want to include tinymce core script
to all pages, but load it dynamically when appropriate widget is rendered on the
form.

Now I get to work both loading tiny_mce.js or tiny_mce_gzip.js dynamically  and
had to solve some problems.

1. Dynamic loading of tiny_mce.js.
We have here two major issues:  first  - tinyMCE._init fails to set correct baseURL so  other  scripts  not
loaded and second -  scriptLoader.loadScripts  by  default
loads scripts with document.write and this breaks the page (all page content is gone).

Both problems where solved with following approach:

    if (!window.tinymce) {
       //set base URL for tinymce
       window.tinyMCEPreInit = {base : '$assets/tinymce', suffix : '', query : ''};

       //load tinymce
       jQuery.ajax({
                        type : 'GET',
                        url : '$assets/tinymce/tiny_mce.js',
                        async : false,
                        success : function(co) {
                            var w = window;

                            // Evaluate script
                            if (!w.execScript) {
                               try {
                                   eval.call(w, co);
                               } catch (ex) {
                                   eval(co, w); // Firefox 3.0a8
                               }
                            } else {
                              w.execScript(co); // IE
                            }
                            //load scripts with dom manipulation instead of document.write
                            w.tinymce.dom.Event.domLoaded = true;
                         }

       });
    }
    // Init textarea with jquery plugin (from Yii tinymce extension http://www.yiiframework.com/extension/tinymce/#download)
    jQuery("#{$id}").tinyMCE({$tinyOptions}, '{$jsMode}', {$jsUseCookies});

I add js code to the page to load core tinymce script  dynamically  and  create
window.tinyMCEPreInit object before script is loaded to set correct baseURL to solve first problem
and set tinymce.dom.Event.domLoaded = true after  script  is  loaded  to  solve second.

2. Dynamic loading of tiny_mce_gzip.js
Here also two problems exist: first with base URL mentionad above and second  -
with sequential calls of tinyMCE_GZ.init for more then one textareas.
I need to call tinyMCE_GZ.init more then once becuse when dialog with form is  generated  I
could not know how many tinymce widgets  exists  and  each  widget  initializes
itself with such code:

       function initTinyGZ_$id() {
           // Init textarea with jquery plugin
           jQuery("#{$id}").tinyMCE({$tinyOptions}, '{$jsMode}', {$jsUseCookies});
       }
       // this is for tinymce core when it will be loaded by tiny_mce_gzip.js
       window.tinyMCEPreInit = {base : '$assets/tinymce', suffix : '', query : ''};
       // init compressor and pass textarea initialization as callback
       tinyMCE_GZ.init({$gzOptions}, function() { initTinyGZ_$id(); });

To solve problems I have with tiny_mce_gzip.js I had to modify its code:

var tinyMCE_GZ = {
    settings : {
        themes : '',
        plugins : '',
        languages : '',
        disk_cache : true,
        page_name : 'tiny_mce_gzip.php',
        debug : false,
        suffix : '',
        // SEB - exteral base url
        baseURL : '',
    },

   init : function(s, cb, sc) {
        var t = this, n, i, nl = document.getElementsByTagName('script');

        for (n in s)
            t.settings[n] = s[n];

        s = t.settings;

        if (t.settings.baseURL == '') {

           for (i=0; i<nl.length; i++) {
            n = nl[i];

            if (n.src && n.src.indexOf('tiny_mce') != -1)
                t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));
           }
        } else {
           // SEB - if script is loaded into the page dynamically it can not be found in the scripts array
           // in this case we can specify external base url where tiny mce scripts are located
           t.baseURL = t.settings.baseURL;
        }

        if (!t.coreLoaded)
            t.loadScripts(1, s.themes, s.plugins, s.languages, cb, sc);
        else
           // SEB - scripts are loaded only once (loadScripts method sets t.coreLoaded to true)
           // if we have two textareas on the page and provide tiniymce initialization in the
           // callback function then second callback was never called
           cb.call(sc || t, null);
    },


    loadScripts : function(co, th, pl, la, cb, sc) {
        var t = this, x, w = window, q, c = 0, ti, s = t.settings;

        function get(s) {
            x = 0;

            try {
                x = new ActiveXObject(s);
            } catch (s) {
            }

            return x;
        };

        // Build query string
        q = 'js=true&diskcache=' + (s.disk_cache ? 'true' : 'false') + '&core=' + (co ? 'true' : 'false') + '&suffix=' + escape(s.suffix) + '&themes=' + escape(th) + '&plugins=' + escape(pl) + '&languages=' + escape(la);

        // SEB - Here also was a problem withis.two or more textareas on the page
        // request was asyncronous and "t.coreLoaded = 1" was set before request is even started.
        // When tinyMCE_GZ.init was invoked for the second area we have "t.coreLoaded = 1" and
        // scripts are not loaded yet. So second area initialization was failed.
        // Now request for script is sent syncronously and problem is gone.

        // Send request
        x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Msxml2.XMLHTTP') || get('Microsoft.XMLHTTP');
        x.overrideMimeType && x.overrideMimeType('text/javascript');
        //x.open('GET', t.baseURL + '/' + s.page_name + '?' + q, !!cb);
        //SEB - make syncronous call
        x.open('GET', t.baseURL + '/' + s.page_name + '?' + q, false);
//      x.setRequestHeader('Content-Type', 'text/javascript');
        x.send('');

        if (co)
            t.coreLoaded = 1;

        // SEB - Handle syncronous loading
        if (cb && x.status == 200) {
           t.loaded = 1;
           t.eval(x.responseText);
           tinymce.dom.Event.domLoaded = true;

           cb.call(sc || t, x);
        } else {
          t.eval(x.responseText);
        }

        /*
        // Handle asyncronous loading
        if (cb) {
            // Wait for response
            ti = w.setInterval(function() {
                if (x.readyState == 4 || c++ > 10000) {
                    w.clearInterval(ti);

                    if (c < 10000 && x.status == 200) {
                        t.loaded = 1;
                        t.eval(x.responseText);
                        tinymce.dom.Event.domLoaded = true;

                        cb.call(sc || t, x);
                    }

                    ti = x = null;
                }
            }, 10);

        } else
            t.eval(x.responseText);*/
    },

    ...

To solve problem with base URL I added special setting to provide external base
URL through options and changed init() method to take that parameter.

To solve problem with sequential init() calls  I  changed  init()  function  to
invoke callback even if core scripts are already loaded:

       if (!t.coreLoaded)
            t.loadScripts(1, s.themes, s.plugins, s.languages, cb, sc);
       else
           // SEB - scripts are loaded only once (loadScripts method sets t.coreLoaded to true)
           // if we have two textareas on the page and provide tiniymce initialization in the
           // callback function then second callback was never called
           cb.call(sc || t, null);

and changed loadScripts to load core synchronously so second init() call will be
performed when scripts are actually loaded into the page.

By   the   way   this   issue   can   be    reproduced    with    example    13
(http://tinymce.moxiecode.com/examples/example_13.php).
If I add second textarea and change setup() function  to  call  tinyMCE_GZ.init
twice for each textarea then tinymce will be loaded for first textarea only:

<script type="text/javascript" src="example_13.php_files/tiny_mce_gzip.js"></script>
<script type="text/javascript">
function setup() {
   tinyMCE_GZ.init({
      themes : "advanced",
      plugins : "safari,pagebreak,...",
      languages : "en",
      disk_cache : true
   }, function() {
      tinyMCE.init({
         mode : "exact",
         elements : "content",
         theme : "advanced",
         ...
      });
   });

   tinyMCE_GZ.init({
      themes : "advanced",
      plugins : "safari,pagebreak,...",
      languages : "en",
      disk_cache : true
   }, function() {
      tinyMCE.init({
         mode : "exact",
         elements : "content2",
         ...
      });
   });

}
</script>
          <form method="post" action="dump.php">
              <div>
                  <textarea name="content" id="content" style="width: 100%;" rows="5" cols="20">
                  ...
                  </textarea>

                  <textarea name="content2" id="content2" style="width: 100%;" rows="5" cols="20">
                  ...
                  </textarea>
                  <div><a href="javascript:setup();">[Load TinyMCE]</a></div>

                  <input class="image" src="example_13.php_files/input_form_submit.gif" type="image">
              </div>
          </form>

As I described above I need this behavior exactly because each textarea  widget
initializes itself and know nothing about other widgets.

13

Re: Dynamically loading TinyMCE's JS files

Does anyone have a solution to implement example13.php (load editor on demand) with more than one instance of editor via ajax?
i would be very grateful if someone posted an example

Many tks!!

14

Re: Dynamically loading TinyMCE's JS files

Got this working without modifying the sourcefiles, hope this helps someone and hope it will keep working with future versions.

// after dynamically loading the core file:
if (!tinymce.dom.Event.domLoaded) {
    tinymce.dom.Event.domLoaded = true;
}
tinymce.baseURL = 'http://yourdomain/path/to/tinymce/root'; // change to your correct value
tinyMCE.init({
    // etc.

Tinymce now won't automatically load _src plugin files when using tinymce_src.js
If you can probably do this by adding an extra line, but haven't tested it:
tinymce.suffix = '_src';

15

Re: Dynamically loading TinyMCE's JS files

Thanks alot this has been a problem for me for a while now.


Hope that this can be fixed in TinyMce in the future.