Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

How to Dynamically Update the TinyMCE Styles Select List

Posted on 2010-09-16
2
Medium Priority
?
1,654 Views
Last Modified: 2012-05-10
I've been using the TinyMCE Javascript WYSIWYG editor for several years now, and although I wouldn't claim to be expert in its inner workings, I believe that I have a fairly solid grasp of the fundamentals. One thing however that I have never managed to accomplish is to dynamically update the Styles Select List.

I know I'm certainly not the only one to say this either, as these TinyMCE forum postings attest to...

http://tinymce.moxiecode.com/punbb/viewtopic.php?id=23068
http://tinymce.moxiecode.com/punbb/viewtopic.php?pid=74958
http://tinymce.moxiecode.com/punbb/viewtopic.php?id=15212

I am currently developing an application which updates the TinyMCE editor content using Ajax. I also want to be able to re-load the associated stylesheet(s) when the content is changed. This is because the stylesheets can also be edited independently from the content and also because different content can come from a different HTML file with different stylesheets associated with it.

When TinyMCE is first initialised it dynamically adds any user-defined stylesheets to the head of the HTML page and then, (I think) populates the Styles Select Listbox by reading all the styles. Since this is only done once when TinyMCE is first constructed, I need a way to request TinyMCE to  re-read the styles. I attempted an ugly work-around by reloading the entire page, but this ran into browser caching problems and in any case is not a good solution.

After reading the API documentation I naturally assumed that calling "tinyMCE.activeEditor.dom.loadCSS()" would do the job for me. What I discovered, (and what others before me have also discovered), is that "loadCSS()" works when you're re-creating the entire editor instance, but NOT when you wish to simply update an existing editor instance.

After spending several days with FireBug and PhpEdit I am no closer to resolving this issue, hence this posting. If anyone knows how to do this then I would greatly appreciate some assistance please.

Thanks.


NOTE: I did write a function to clear the associated styles which I call prior to "loadCSS()" and it appears to work quite well, so I have included this below:

// Note: "isDef(arg)" is a function that checks if the argument is defined and not null

function clearStyles(editorStyles)  // "editorStyles" is an array of stylesheet relative paths
{
 try
 {
  if (!isDef(editorStyles)) return false;

  var Editor = tinyMCE.activeEditor;

  var head = Editor.dom.select('head')[0];
  for (var i=0; i<head.childNodes.length; i++)
  {
   var childNode = head.childNodes[i];
   if (isDef(childNode.rel) && childNode.rel.toLowerCase() == 'stylesheet' && isDef(childNode.href))
   {
    var href = childNode.href.toLowerCase();
    for (var j=0; j<editorStyles.length; j++)
    {
     var style = editorStyles[j];
     if (href.indexOf(style) >= 0)
     {
      Editor.dom.remove(childNode);
      delete Editor.dom.files[style];  // I also have to clear the entry out of the dom file list or else it won't be added when I call loadCSS next time this page is loaded
     }
    }
   }
  }

  Editor.controlManager.get('styleselect').items.length = 0;  // The style list will be re-populated (if empty) when the menu is shown in the function "_importClasses()" in the file "editor_template_src.js"

  if (isDef(Editor.dom.classes))
  {
   Editor.dom.classes.length = 0;  // Remove all elements before de-assigning, (just in case)
   delete Editor.dom.classes;      // De-assign the internal dom "classes" object to force it to re-parse the loaded page's DOM for style classes in the function "_importClasses()" in the file "editor_template_src.js".
  }

  return true;
 }
 catch(e) {}

 return false;
}

Open in new window

0
Comment
Question by:NetSoftDS
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
2 Comments
 

Author Comment

by:NetSoftDS
ID: 33697855
It has occured to me that if TinyMCE is dynamically adding any user-defined stylesheets to the head of the HTML page when its initialised, then precisely how TinyMCE extracts the styles is unclear.  I assume that once an additonal stylesheet has been appended to the end of the head, then its styles are immediately available to the DOM allowing TinyMCE to parse them and then ultimately, to add them to the Styles Select Listbox.

(The TinyMCE "init()" function is called in a <script> tag section in the page's <head> section.)

This means that any attempts to dynamically update the Styles Select Listbox after an included stylesheet has been updated by some external process is doomed to failure, since the entire web page would need to be reloaded first, (which leads to the follwoing browser caching issue.

I have been unable to  fully disable browser caching. if I use FireFox's "Web Developer" add-on to disable the cache, everything works correctly and the styles select listsbox is properly refreshed. If I attempt to programmatically disable caching then the wheels fall off. I am using the following PHP function to do this:

function disableCache()
{
 header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
 header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
 header("Cache-Control: post-check=0, pre-check=0", false);
 header("Pragma: no-cache");
// header("Cache-Control: max-age=0, s-maxage=0, must-revalidate, proxy-revalidate, no-cache");
}

I have also tried creating a unique URL for the web page by appending a generated timestamp argument to the end of the containing web page's url... see code below:

var timeStamp = new Date();
editorFrame.window.location.href = editorFrame.window.location.href + '&timestamp=' + timeStamp.getTime();  // Add a unique url argument to force the browser to refresh, (ie. disabling any caching)

So in order to get my workaround happenning I need some help to prevent the browse caching the web page containing the TinyMCE instance.


A Further Note:
-----------------
It should be possible to dynamically remove the stylesheet from the head and then re-append it. Then the problem becomes finding the appropriate TinyMCE API call to reload the styles, (hopefully "loadCSS()" will now work). I will try this approach as soon as I get the page reload work-around functioning correctly.
0
 

Accepted Solution

by:
NetSoftDS earned 0 total points
ID: 33706356
The answer to my question can be found here: http://wiki.moxiecode.com/index.php/TinyMCE:Configuration/content_css#Note:

In my case, I am loading the stylesheets dynamically using "loadCSS()" but I simply appended a unique timestamp parameter to every stylesheet in the string passed to "loadCSS()".

Its interesting to note that disabling the browser caching via the use of PHP headers, meta tags and bogus unique timestamp parameters in the HTML page itself had no effect. The stylesheets files were still being cached. I suspect this is a consequence of them being added dynamically by tinyMCE using "loadCSS()" in my application.
0

Featured Post

Tech or Treat! - Giveaway

Submit an article about your scariest tech experience—and the solution—and you’ll be automatically entered to win one of 4 fantastic tech gadgets.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
3 proven steps to speed up Magento powered sites. The article focus is on optimizing time to first byte (TTFB), full page caching and configuring server for optimal performance.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…
Suggested Courses

618 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question