PHP Cross Reference of WordPress Subversion HEAD

[ Index ]     [ Classes ]     [ Functions ]     [ Variables ]     [ Constants ]

title

Body

[close]

/wp-includes/js/tinymce/ -> tiny_mce.js (source)

   1  
   2  /* file:jscripts/tiny_mce/classes/TinyMCE_Engine.class.js */
   3  
   4  function TinyMCE_Engine() {
   5      var ua;
   6  
   7      this.majorVersion = "2";
   8      this.minorVersion = "1.1.1";
   9      this.releaseDate = "2007-05-14";
  10  
  11      this.instances = [];
  12      this.switchClassCache = [];
  13      this.windowArgs = [];
  14      this.loadedFiles = [];
  15      this.pendingFiles = [];
  16      this.loadingIndex = 0;
  17      this.configs = [];
  18      this.currentConfig = 0;
  19      this.eventHandlers = [];
  20      this.log = [];
  21      this.undoLevels = [];
  22      this.undoIndex = 0;
  23      this.typingUndoIndex = -1;
  24      this.settings = [];
  25  
  26      // Browser check
  27      ua = navigator.userAgent;
  28      this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
  29      this.isMSIE5 = this.isMSIE && (ua.indexOf('MSIE 5') != -1);
  30      this.isMSIE5_0 = this.isMSIE && (ua.indexOf('MSIE 5.0') != -1);
  31      this.isMSIE7 = this.isMSIE && (ua.indexOf('MSIE 7') != -1);
  32      this.isGecko = ua.indexOf('Gecko') != -1; // Will also be true on Safari
  33      this.isSafari = ua.indexOf('Safari') != -1;
  34      this.isOpera = window['opera'] && opera.buildNumber ? true : false;
  35      this.isMac = ua.indexOf('Mac') != -1;
  36      this.isNS7 = ua.indexOf('Netscape/7') != -1;
  37      this.isNS71 = ua.indexOf('Netscape/7.1') != -1;
  38      this.dialogCounter = 0;
  39      this.plugins = [];
  40      this.themes = [];
  41      this.menus = [];
  42      this.loadedPlugins = [];
  43      this.buttonMap = [];
  44      this.isLoaded = false;
  45  
  46      // Fake MSIE on Opera and if Opera fakes IE, Gecko or Safari cancel those
  47      if (this.isOpera) {
  48          this.isMSIE = true;
  49          this.isGecko = false;
  50          this.isSafari =  false;
  51      }
  52  
  53      this.isIE = this.isMSIE;
  54      this.isRealIE = this.isMSIE && !this.isOpera;
  55  
  56      // TinyMCE editor id instance counter
  57      this.idCounter = 0;
  58  };
  59  
  60  TinyMCE_Engine.prototype = {
  61      init : function(settings) {
  62          var theme, nl, baseHREF = "", i, cssPath, entities, h, p, src, elements = [], head;
  63  
  64          // IE 5.0x is no longer supported since 5.5, 6.0 and 7.0 now exists. We can't support old browsers forever, sorry.
  65          if (this.isMSIE5_0)
  66              return;
  67  
  68          this.settings = settings;
  69  
  70          // Check if valid browser has execcommand support
  71          if (typeof(document.execCommand) == 'undefined')
  72              return;
  73  
  74          // Get script base path
  75          if (!tinyMCE.baseURL) {
  76              // Search through head
  77              head = document.getElementsByTagName('head')[0];
  78  
  79              if (head) {
  80                  for (i=0, nl = head.getElementsByTagName('script'); i<nl.length; i++)
  81                      elements.push(nl[i]);
  82              }
  83  
  84              // Search through rest of document
  85              for (i=0, nl = document.getElementsByTagName('script'); i<nl.length; i++)
  86                  elements.push(nl[i]);
  87  
  88              // If base element found, add that infront of baseURL
  89              nl = document.getElementsByTagName('base');
  90              for (i=0; i<nl.length; i++) {
  91                  if (nl[i].href)
  92                      baseHREF = nl[i].href;
  93              }
  94  
  95              for (i=0; i<elements.length; i++) {
  96                  if (elements[i].src && (elements[i].src.indexOf("tiny_mce.js") != -1 || elements[i].src.indexOf("tiny_mce_dev.js") != -1 || elements[i].src.indexOf("tiny_mce_src.js") != -1 || elements[i].src.indexOf("tiny_mce_gzip") != -1)) {
  97                      src = elements[i].src;
  98  
  99                      tinyMCE.srcMode = (src.indexOf('_src') != -1 || src.indexOf('_dev') != -1) ? '_src' : '';
 100                      tinyMCE.gzipMode = src.indexOf('_gzip') != -1;
 101                      src = src.substring(0, src.lastIndexOf('/'));
 102  
 103                      if (settings.exec_mode == "src" || settings.exec_mode == "normal")
 104                          tinyMCE.srcMode = settings.exec_mode == "src" ? '_src' : '';
 105  
 106                      // Force it absolute if page has a base href
 107                      if (baseHREF !== '' && src.indexOf('://') == -1)
 108                          tinyMCE.baseURL = baseHREF + src;
 109                      else
 110                          tinyMCE.baseURL = src;
 111  
 112                      break;
 113                  }
 114              }
 115          }
 116  
 117          // Get document base path
 118          this.documentBasePath = document.location.href;
 119          if (this.documentBasePath.indexOf('?') != -1)
 120              this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.indexOf('?'));
 121          this.documentURL = this.documentBasePath;
 122          this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.lastIndexOf('/'));
 123  
 124          // If not HTTP absolute
 125          if (tinyMCE.baseURL.indexOf('://') == -1 && tinyMCE.baseURL.charAt(0) != '/') {
 126              // If site absolute
 127              tinyMCE.baseURL = this.documentBasePath + "/" + tinyMCE.baseURL;
 128          }
 129  
 130          // Set default values on settings
 131          this._def("mode", "none");
 132          this._def("theme", "advanced");
 133          this._def("plugins", "", true);
 134          this._def("language", "en");
 135          this._def("docs_language", this.settings.language);
 136          this._def("elements", "");
 137          this._def("textarea_trigger", "mce_editable");
 138          this._def("editor_selector", "");
 139          this._def("editor_deselector", "mceNoEditor");
 140          this._def("valid_elements", "+a[id|style|rel|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|style],-ul[class|style],-li[class|style],br,img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align],-sub[style|class],-sup[style|class],-blockquote[dir|style],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[style|class|align],-pre[class|align|style],address[class|align|style],-h1[id|style|dir|class|align],-h2[id|style|dir|class|align],-h3[id|style|dir|class|align],-h4[id|style|dir|class|align],-h5[id|style|dir|class|align],-h6[id|style|dir|class|align],hr[class|style],-font[face|size|style|id|class|dir|color],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],cite[title|id|class|style|dir|lang],abbr[title|id|class|style|dir|lang],acronym[title|id|class|style|dir|lang],del[title|id|class|style|dir|lang|datetime|cite],ins[title|id|class|style|dir|lang|datetime|cite]");
 141          this._def("extended_valid_elements", "");
 142          this._def("invalid_elements", "");
 143          this._def("encoding", "");
 144          this._def("urlconverter_callback", tinyMCE.getParam("urlconvertor_callback", "TinyMCE_Engine.prototype.convertURL"));
 145          this._def("save_callback", "");
 146          this._def("force_br_newlines", false);
 147          this._def("force_p_newlines", true);
 148          this._def("add_form_submit_trigger", true);
 149          this._def("relative_urls", true);
 150          this._def("remove_script_host", true);
 151          this._def("focus_alert", true);
 152          this._def("document_base_url", this.documentURL);
 153          this._def("visual", true);
 154          this._def("visual_table_class", "mceVisualAid");
 155          this._def("setupcontent_callback", "");
 156          this._def("fix_content_duplication", true);
 157          this._def("custom_undo_redo", true);
 158          this._def("custom_undo_redo_levels", -1);
 159          this._def("custom_undo_redo_keyboard_shortcuts", true);
 160          this._def("custom_undo_redo_restore_selection", true);
 161          this._def("custom_undo_redo_global", false);
 162          this._def("verify_html", true);
 163          this._def("apply_source_formatting", false);
 164          this._def("directionality", "ltr");
 165          this._def("cleanup_on_startup", false);
 166          this._def("inline_styles", false);
 167          this._def("convert_newlines_to_brs", false);
 168          this._def("auto_reset_designmode", true);
 169          this._def("entities", "39,#39,160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,34,quot,38,amp,60,lt,62,gt,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro", true);
 170          this._def("entity_encoding", "named");
 171          this._def("cleanup_callback", "");
 172          this._def("add_unload_trigger", true);
 173          this._def("ask", false);
 174          this._def("nowrap", false);
 175          this._def("auto_resize", false);
 176          this._def("auto_focus", false);
 177          this._def("cleanup", true);
 178          this._def("remove_linebreaks", true);
 179          this._def("button_tile_map", false);
 180          this._def("submit_patch", true);
 181          this._def("browsers", "msie,safari,gecko,opera", true);
 182          this._def("dialog_type", "window");
 183          this._def("accessibility_warnings", true);
 184          this._def("accessibility_focus", true);
 185          this._def("merge_styles_invalid_parents", "");
 186          this._def("force_hex_style_colors", true);
 187          this._def("trim_span_elements", true);
 188          this._def("convert_fonts_to_spans", false);
 189          this._def("doctype", '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">');
 190          this._def("font_size_classes", '');
 191          this._def("font_size_style_values", 'xx-small,x-small,small,medium,large,x-large,xx-large', true);
 192          this._def("event_elements", 'a,img', true);
 193          this._def("convert_urls", true);
 194          this._def("table_inline_editing", false);
 195          this._def("object_resizing", true);
 196          this._def("custom_shortcuts", true);
 197          this._def("convert_on_click", false);
 198          this._def("content_css", '');
 199          this._def("fix_list_elements", true);
 200          this._def("fix_table_elements", false);
 201          this._def("strict_loading_mode", document.contentType == 'application/xhtml+xml');
 202          this._def("hidden_tab_class", '');
 203          this._def("display_tab_class", '');
 204          this._def("gecko_spellcheck", false);
 205          this._def("hide_selects_on_submit", true);
 206          this._def("forced_root_block", false);
 207          this._def("remove_trailing_nbsp", false);
 208  
 209          // Force strict loading mode to false on non Gecko browsers
 210          if (this.isMSIE && !this.isOpera)
 211              this.settings.strict_loading_mode = false;
 212  
 213          // Browser check IE
 214          if (this.isMSIE && this.settings.browsers.indexOf('msie') == -1)
 215              return;
 216  
 217          // Browser check Gecko
 218          if (this.isGecko && this.settings.browsers.indexOf('gecko') == -1)
 219              return;
 220  
 221          // Browser check Safari
 222          if (this.isSafari && this.settings.browsers.indexOf('safari') == -1)
 223              return;
 224  
 225          // Browser check Opera
 226          if (this.isOpera && this.settings.browsers.indexOf('opera') == -1)
 227              return;
 228  
 229          // If not super absolute make it so
 230          baseHREF = tinyMCE.settings.document_base_url;
 231          h = document.location.href;
 232          p = h.indexOf('://');
 233          if (p > 0 && document.location.protocol != "file:") {
 234              p = h.indexOf('/', p + 3);
 235              h = h.substring(0, p);
 236  
 237              if (baseHREF.indexOf('://') == -1)
 238                  baseHREF = h + baseHREF;
 239  
 240              tinyMCE.settings.document_base_url = baseHREF;
 241              tinyMCE.settings.document_base_prefix = h;
 242          }
 243  
 244          // Trim away query part
 245          if (baseHREF.indexOf('?') != -1)
 246              baseHREF = baseHREF.substring(0, baseHREF.indexOf('?'));
 247  
 248          this.settings.base_href = baseHREF.substring(0, baseHREF.lastIndexOf('/')) + "/";
 249  
 250          theme = this.settings.theme;
 251          this.inlineStrict = 'A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';
 252          this.inlineTransitional = 'A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';
 253          this.blockElms = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';
 254          this.blockRegExp = new RegExp("^(" + this.blockElms + ")$", "i");
 255          this.posKeyCodes = [13,45,36,35,33,34,37,38,39,40];
 256          this.uniqueURL = 'javascript:void(091039730);'; // Make unique URL non real URL
 257          this.uniqueTag = '<div id="mceTMPElement" style="display: none">TMP</div>';
 258          this.callbacks = ['onInit', 'getInfo', 'getEditorTemplate', 'setupContent', 'onChange', 'onPageLoad', 'handleNodeChange', 'initInstance', 'execCommand', 'getControlHTML', 'handleEvent', 'cleanup', 'removeInstance'];
 259  
 260          // Theme url
 261          this.settings.theme_href = tinyMCE.baseURL + "/themes/" + theme;
 262  
 263          if (!tinyMCE.isIE || tinyMCE.isOpera)
 264              this.settings.force_br_newlines = false;
 265  
 266          if (tinyMCE.getParam("popups_css", false)) {
 267              cssPath = tinyMCE.getParam("popups_css", "");
 268  
 269              // Is relative
 270              if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')
 271                  this.settings.popups_css = this.documentBasePath + "/" + cssPath;
 272              else
 273                  this.settings.popups_css = cssPath;
 274          } else
 275              this.settings.popups_css = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_popup.css";
 276  
 277          if (tinyMCE.getParam("editor_css", false)) {
 278              cssPath = tinyMCE.getParam("editor_css", "");
 279  
 280              // Is relative
 281              if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')
 282                  this.settings.editor_css = this.documentBasePath + "/" + cssPath;
 283              else
 284                  this.settings.editor_css = cssPath;
 285          } else {
 286              if (this.settings.editor_css !== '')
 287                  this.settings.editor_css = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_ui.css";
 288          }
 289  
 290          // Only do this once
 291          if (this.configs.length == 0) {
 292              if (typeof(TinyMCECompressed) == "undefined") {
 293                  tinyMCE.addEvent(window, "DOMContentLoaded", TinyMCE_Engine.prototype.onLoad);
 294  
 295                  if (tinyMCE.isRealIE) {
 296                      if (document.body)
 297                          tinyMCE.addEvent(document.body, "readystatechange", TinyMCE_Engine.prototype.onLoad);
 298                      else
 299                          tinyMCE.addEvent(document, "readystatechange", TinyMCE_Engine.prototype.onLoad);
 300                  }
 301  
 302                  tinyMCE.addEvent(window, "load", TinyMCE_Engine.prototype.onLoad);
 303                  tinyMCE._addUnloadEvents();
 304              }
 305          }
 306  
 307          this.loadScript(tinyMCE.baseURL + '/themes/' + this.settings.theme + '/editor_template' + tinyMCE.srcMode + '.js');
 308          this.loadScript(tinyMCE.baseURL + '/langs/' + this.settings.language +  '.js');
 309          this.loadCSS(this.settings.editor_css);
 310  
 311          // Add plugins
 312          p = tinyMCE.getParam('plugins', '', true, ',');
 313          if (p.length > 0) {
 314              for (i=0; i<p.length; i++) {
 315                  if (p[i].charAt(0) != '-')
 316                      this.loadScript(tinyMCE.baseURL + '/plugins/' + p[i] + '/editor_plugin' + tinyMCE.srcMode + '.js');
 317              }
 318          }
 319  
 320          // Setup entities
 321          if (tinyMCE.getParam('entity_encoding') == 'named') {
 322              settings.cleanup_entities = [];
 323              entities = tinyMCE.getParam('entities', '', true, ',');
 324              for (i=0; i<entities.length; i+=2)
 325                  settings.cleanup_entities['c' + entities[i]] = entities[i+1];
 326          }
 327  
 328          // Save away this config
 329          settings.index = this.configs.length;
 330          this.configs[this.configs.length] = settings;
 331  
 332          // Start loading first one in chain
 333          this.loadNextScript();
 334  
 335          // Force flicker free CSS backgrounds in IE
 336          if (this.isIE && !this.isOpera) {
 337              try {
 338                  document.execCommand('BackgroundImageCache', false, true);
 339              } catch (e) {
 340                  // Ignore
 341              }
 342          }
 343  
 344          // Setup XML encoding regexps
 345          this.xmlEncodeRe = new RegExp('[<>&"]', 'g');
 346      },
 347  
 348      _addUnloadEvents : function() {
 349          var st = tinyMCE.settings.add_unload_trigger;
 350  
 351          if (tinyMCE.isIE) {
 352              if (st) {
 353                  tinyMCE.addEvent(window, "unload", TinyMCE_Engine.prototype.unloadHandler);
 354                  tinyMCE.addEvent(window.document, "beforeunload", TinyMCE_Engine.prototype.unloadHandler);
 355              }
 356          } else {
 357              if (st)
 358                  tinyMCE.addEvent(window, "unload", function () {tinyMCE.triggerSave(true, true);});
 359          }
 360      },
 361  
 362      _def : function(key, def_val, t) {
 363          var v = tinyMCE.getParam(key, def_val);
 364  
 365          v = t ? v.replace(/\s+/g, "") : v;
 366  
 367          this.settings[key] = v;
 368      },
 369  
 370      hasPlugin : function(n) {
 371          return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;
 372      },
 373  
 374      addPlugin : function(n, p) {
 375          var op = this.plugins[n];
 376  
 377          // Use the previous plugin object base URL used when loading external plugins
 378          p.baseURL = op ? op.baseURL : tinyMCE.baseURL + "/plugins/" + n;
 379          this.plugins[n] = p;
 380  
 381          this.loadNextScript();
 382      },
 383  
 384      setPluginBaseURL : function(n, u) {
 385          var op = this.plugins[n];
 386  
 387          if (op)
 388              op.baseURL = u;
 389          else
 390              this.plugins[n] = {baseURL : u};
 391      },
 392  
 393      loadPlugin : function(n, u) {
 394          u = u.indexOf('.js') != -1 ? u.substring(0, u.lastIndexOf('/')) : u;
 395          u = u.charAt(u.length-1) == '/' ? u.substring(0, u.length-1) : u;
 396          this.plugins[n] = {baseURL : u};
 397          this.loadScript(u + "/editor_plugin" + (tinyMCE.srcMode ? '_src' : '') + ".js");
 398      },
 399  
 400      hasTheme : function(n) {
 401          return typeof(this.themes[n]) != "undefined" && this.themes[n] != null;
 402      },
 403  
 404      addTheme : function(n, t) {
 405          this.themes[n] = t;
 406  
 407          this.loadNextScript();
 408      },
 409  
 410      addMenu : function(n, m) {
 411          this.menus[n] = m;
 412      },
 413  
 414      hasMenu : function(n) {
 415          return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;
 416      },
 417  
 418      loadScript : function(url) {
 419          var i;
 420  
 421          for (i=0; i<this.loadedFiles.length; i++) {
 422              if (this.loadedFiles[i] == url)
 423                  return;
 424          }
 425  
 426          if (tinyMCE.settings.strict_loading_mode)
 427              this.pendingFiles[this.pendingFiles.length] = url;
 428          else
 429              document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></script>');
 430  
 431          this.loadedFiles[this.loadedFiles.length] = url;
 432      },
 433  
 434      loadNextScript : function() {
 435          var d = document, se;
 436  
 437          if (!tinyMCE.settings.strict_loading_mode)
 438              return;
 439  
 440          if (this.loadingIndex < this.pendingFiles.length) {
 441              se = d.createElementNS('http://www.w3.org/1999/xhtml', 'script');
 442              se.setAttribute('language', 'javascript');
 443              se.setAttribute('type', 'text/javascript');
 444              se.setAttribute('src', this.pendingFiles[this.loadingIndex++]);
 445  
 446              d.getElementsByTagName("head")[0].appendChild(se);
 447          } else
 448              this.loadingIndex = -1; // Done with loading
 449      },
 450  
 451      loadCSS : function(url) {
 452          var ar = url.replace(/\s+/, '').split(',');
 453          var lflen = 0, csslen = 0, skip = false;
 454          var x = 0, i = 0, nl, le;
 455  
 456          for (x = 0,csslen = ar.length; x<csslen; x++) {
 457              if (ar[x] != null && ar[x] != 'null' && ar[x].length > 0) {
 458                  /* Make sure it doesn't exist. */
 459                  for (i=0, lflen=this.loadedFiles.length; i<lflen; i++) {
 460                      if (this.loadedFiles[i] == ar[x]) {
 461                          skip = true;
 462                          break;
 463                      }
 464                  }
 465  
 466                  if (!skip) {
 467                      if (tinyMCE.settings.strict_loading_mode) {
 468                          nl = document.getElementsByTagName("head");
 469  
 470                          le = document.createElement('link');
 471                          le.setAttribute('href', ar[x]);
 472                          le.setAttribute('rel', 'stylesheet');
 473                          le.setAttribute('type', 'text/css');
 474  
 475                          nl[0].appendChild(le);            
 476                      } else
 477                          document.write('<link href="' + ar[x] + '" rel="stylesheet" type="text/css" />');
 478  
 479                      this.loadedFiles[this.loadedFiles.length] = ar[x];
 480                  }
 481              }
 482          }
 483      },
 484  
 485      importCSS : function(doc, css) {
 486          var css_ary = css.replace(/\s+/, '').split(',');
 487          var csslen, elm, headArr, x, css_file;
 488  
 489          for (x = 0, csslen = css_ary.length; x<csslen; x++) {
 490              css_file = css_ary[x];
 491  
 492              if (css_file != null && css_file != 'null' && css_file.length > 0) {
 493                  // Is relative, make absolute
 494                  if (css_file.indexOf('://') == -1 && css_file.charAt(0) != '/')
 495                      css_file = this.documentBasePath + "/" + css_file;
 496  
 497                  if (typeof(doc.createStyleSheet) == "undefined") {
 498                      elm = doc.createElement("link");
 499  
 500                      elm.rel = "stylesheet";
 501                      elm.href = css_file;
 502  
 503                      if ((headArr = doc.getElementsByTagName("head")) != null && headArr.length > 0)
 504                          headArr[0].appendChild(elm);
 505                  } else
 506                      doc.createStyleSheet(css_file);
 507              }
 508          }
 509      },
 510  
 511      confirmAdd : function(e, settings) {
 512          var elm = tinyMCE.isIE ? event.srcElement : e.target;
 513          var elementId = elm.name ? elm.name : elm.id;
 514  
 515          tinyMCE.settings = settings;
 516  
 517          if (tinyMCE.settings.convert_on_click || (!elm.getAttribute('mce_noask') && confirm(tinyMCELang.lang_edit_confirm)))
 518              tinyMCE.addMCEControl(elm, elementId);
 519  
 520          elm.setAttribute('mce_noask', 'true');
 521      },
 522  
 523      updateContent : function(form_element_name) {
 524          var formElement, n, inst, doc;
 525  
 526          // Find MCE instance linked to given form element and copy it's value
 527          formElement = document.getElementById(form_element_name);
 528          for (n in tinyMCE.instances) {
 529              inst = tinyMCE.instances[n];
 530  
 531              if (!tinyMCE.isInstance(inst))
 532                  continue;
 533  
 534              inst.switchSettings();
 535  
 536              if (inst.formElement == formElement) {
 537                  doc = inst.getDoc();
 538  
 539                  tinyMCE._setHTML(doc, inst.formElement.value);
 540  
 541                  if (!tinyMCE.isIE)
 542                      doc.body.innerHTML = tinyMCE._cleanupHTML(inst, doc, this.settings, doc.body, inst.visualAid);
 543              }
 544          }
 545      },
 546  
 547      addMCEControl : function(replace_element, form_element_name, target_document) {
 548          var id = "mce_editor_" + tinyMCE.idCounter++;
 549          var inst = new TinyMCE_Control(tinyMCE.settings);
 550  
 551          inst.editorId = id;
 552          this.instances[id] = inst;
 553  
 554          inst._onAdd(replace_element, form_element_name, target_document);
 555      },
 556  
 557      removeInstance : function(ti) {
 558          var t = [], n, i;
 559  
 560          // Remove from instances
 561          for (n in tinyMCE.instances) {
 562              i = tinyMCE.instances[n];
 563  
 564              if (tinyMCE.isInstance(i) && ti != i)
 565                      t[n] = i;
 566          }
 567  
 568          tinyMCE.instances = t;
 569  
 570          // Remove from global undo/redo
 571          n = [];
 572          t = tinyMCE.undoLevels;
 573  
 574          for (i=0; i<t.length; i++) {
 575              if (t[i] != ti)
 576                  n.push(t[i]);
 577          }
 578  
 579          tinyMCE.undoLevels = n;
 580          tinyMCE.undoIndex = n.length;
 581  
 582          // Dispatch remove instance call
 583          tinyMCE.dispatchCallback(ti, 'remove_instance_callback', 'removeInstance', ti);
 584  
 585          return ti;
 586      },
 587  
 588      removeMCEControl : function(editor_id) {
 589          var inst = tinyMCE.getInstanceById(editor_id), h, re, ot, tn;
 590  
 591          if (inst) {
 592              inst.switchSettings();
 593  
 594              editor_id = inst.editorId;
 595              h = tinyMCE.getContent(editor_id);
 596  
 597              this.removeInstance(inst);
 598  
 599              tinyMCE.selectedElement = null;
 600              tinyMCE.selectedInstance = null;
 601  
 602              // Remove element
 603              re = document.getElementById(editor_id + "_parent");
 604              ot = inst.oldTargetElement;
 605              tn = ot.nodeName.toLowerCase();
 606  
 607              if (tn == "textarea" || tn == "input") {
 608                  re.parentNode.removeChild(re);
 609                  ot.style.display = "inline";
 610                  ot.value = h;
 611              } else {
 612                  ot.innerHTML = h;
 613                  ot.style.display = 'block';
 614                  re.parentNode.insertBefore(ot, re);
 615                  re.parentNode.removeChild(re);
 616              }
 617          }
 618      },
 619  
 620      triggerSave : function(skip_cleanup, skip_callback) {
 621          var inst, n;
 622  
 623          // Default to false
 624          if (typeof(skip_cleanup) == "undefined")
 625              skip_cleanup = false;
 626  
 627          // Default to false
 628          if (typeof(skip_callback) == "undefined")
 629              skip_callback = false;
 630  
 631          // Cleanup and set all form fields
 632          for (n in tinyMCE.instances) {
 633              inst = tinyMCE.instances[n];
 634  
 635              if (!tinyMCE.isInstance(inst))
 636                  continue;
 637  
 638              inst.triggerSave(skip_cleanup, skip_callback);
 639          }
 640      },
 641  
 642      resetForm : function(form_index) {
 643          var i, inst, n, formObj = document.forms[form_index];
 644  
 645          for (n in tinyMCE.instances) {
 646              inst = tinyMCE.instances[n];
 647  
 648              if (!tinyMCE.isInstance(inst))
 649                  continue;
 650  
 651              inst.switchSettings();
 652  
 653              for (i=0; i<formObj.elements.length; i++) {
 654                  if (inst.formTargetElementId == formObj.elements[i].name)
 655                      inst.getBody().innerHTML = inst.startContent;
 656              }
 657          }
 658      },
 659  
 660      execInstanceCommand : function(editor_id, command, user_interface, value, focus) {
 661          var inst = tinyMCE.getInstanceById(editor_id), r;
 662  
 663          if (inst) {
 664              r = inst.selection.getRng();
 665  
 666              if (typeof(focus) == "undefined")
 667                  focus = true;
 668  
 669              // IE bug lost focus on images in absolute divs Bug #1534575
 670              if (focus && (!r || !r.item))
 671                  inst.contentWindow.focus();
 672  
 673              // Reset design mode if lost
 674              inst.autoResetDesignMode();
 675  
 676              this.selectedElement = inst.getFocusElement();
 677              inst.select();
 678              tinyMCE.execCommand(command, user_interface, value);
 679  
 680              // Cancel event so it doesn't call onbeforeonunlaod
 681              if (tinyMCE.isIE && window.event != null)
 682                  tinyMCE.cancelEvent(window.event);
 683          }
 684      },
 685  
 686      execCommand : function(command, user_interface, value) {
 687          var inst = tinyMCE.selectedInstance, n, pe, te;
 688  
 689          // Default input
 690          user_interface = user_interface ? user_interface : false;
 691          value = value ? value : null;
 692  
 693          if (inst)
 694              inst.switchSettings();
 695  
 696          switch (command) {
 697              case "Undo":
 698                  if (this.getParam('custom_undo_redo_global')) {
 699                      if (this.undoIndex > 0) {
 700                          tinyMCE.nextUndoRedoAction = 'Undo';
 701                          inst = this.undoLevels[--this.undoIndex];
 702                          inst.select();
 703  
 704                          if (!tinyMCE.nextUndoRedoInstanceId)
 705                              inst.execCommand('Undo');
 706                      }
 707                  } else
 708                      inst.execCommand('Undo');
 709                  return true;
 710  
 711              case "Redo":
 712                  if (this.getParam('custom_undo_redo_global')) {
 713                      if (this.undoIndex <= this.undoLevels.length - 1) {
 714                          tinyMCE.nextUndoRedoAction = 'Redo';
 715                          inst = this.undoLevels[this.undoIndex++];
 716                          inst.select();
 717  
 718                          if (!tinyMCE.nextUndoRedoInstanceId)
 719                              inst.execCommand('Redo');
 720                      }
 721                  } else
 722                      inst.execCommand('Redo');
 723  
 724                  return true;
 725  
 726              case 'mceFocus':
 727                  inst = tinyMCE.getInstanceById(value);
 728  
 729                  if (inst)
 730                      inst.getWin().focus();
 731              return;
 732  
 733              case "mceAddControl":
 734              case "mceAddEditor":
 735                  tinyMCE.addMCEControl(tinyMCE._getElementById(value), value);
 736                  return;
 737  
 738              case "mceAddFrameControl":
 739                  tinyMCE.addMCEControl(tinyMCE._getElementById(value.element, value.document), value.element, value.document);
 740                  return;
 741  
 742              case "mceRemoveControl":
 743              case "mceRemoveEditor":
 744                  tinyMCE.removeMCEControl(value);
 745                  return;
 746  
 747              case "mceToggleEditor":
 748                  inst = tinyMCE.getInstanceById(value);
 749  
 750                  if (inst) {
 751                      pe = document.getElementById(inst.editorId + '_parent');
 752                      te = inst.oldTargetElement;
 753  
 754                      if (typeof(inst.enabled) == 'undefined')
 755                          inst.enabled = true;
 756  
 757                      inst.enabled = !inst.enabled;
 758  
 759                      if (!inst.enabled) {
 760                          pe.style.display = 'none';
 761  
 762                          if (te.nodeName == 'TEXTAREA' || te.nodeName == 'INPUT')
 763                              te.value = inst.getHTML();
 764                          else
 765                              te.innerHTML = inst.getHTML();
 766  
 767                          te.style.display = inst.oldTargetDisplay;
 768                          tinyMCE.dispatchCallback(inst, 'hide_instance_callback', 'hideInstance', inst);
 769                      } else {
 770                          pe.style.display = 'block';
 771                          te.style.display = 'none';
 772  
 773                          if (te.nodeName == 'TEXTAREA' || te.nodeName == 'INPUT')
 774                              inst.setHTML(te.value);
 775                          else
 776                              inst.setHTML(te.innerHTML);
 777  
 778                          inst.useCSS = false;
 779                          tinyMCE.dispatchCallback(inst, 'show_instance_callback', 'showInstance', inst);
 780                      }
 781                  } else
 782                      tinyMCE.addMCEControl(tinyMCE._getElementById(value), value);
 783  
 784                  return;
 785  
 786              case "mceResetDesignMode":
 787                  // Resets the designmode state of the editors in Gecko
 788                  if (tinyMCE.isGecko) {
 789                      for (n in tinyMCE.instances) {
 790                          if (!tinyMCE.isInstance(tinyMCE.instances[n]))
 791                              continue;
 792  
 793                          try {
 794                              tinyMCE.instances[n].getDoc().designMode = "off";
 795                              tinyMCE.instances[n].getDoc().designMode = "on";
 796                              tinyMCE.instances[n].useCSS = false;
 797                          } catch (e) {
 798                              // Ignore any errors
 799                          }
 800                      }
 801                  }
 802  
 803                  return;
 804          }
 805  
 806          if (inst) {
 807              inst.execCommand(command, user_interface, value);
 808          } else if (tinyMCE.settings.focus_alert)
 809              alert(tinyMCELang.lang_focus_alert);
 810      },
 811  
 812      _createIFrame : function(replace_element, doc, win) {
 813          var iframe, id = replace_element.getAttribute("id");
 814          var aw, ah;
 815  
 816          if (typeof(doc) == "undefined")
 817              doc = document;
 818  
 819          if (typeof(win) == "undefined")
 820              win = window;
 821  
 822          iframe = doc.createElement("iframe");
 823  
 824          aw = "" + tinyMCE.settings.area_width;
 825          ah = "" + tinyMCE.settings.area_height;
 826  
 827          if (aw.indexOf('%') == -1) {
 828              aw = parseInt(aw);
 829              aw = (isNaN(aw) || aw < 0) ? 300 : aw;
 830              aw = aw + "px";
 831          }
 832  
 833          if (ah.indexOf('%') == -1) {
 834              ah = parseInt(ah);
 835              ah = (isNaN(ah) || ah < 0) ? 240 : ah;
 836              ah = ah + "px";
 837          }
 838  
 839          iframe.setAttribute("id", id);
 840          iframe.setAttribute("name", id);
 841          iframe.setAttribute("class", "mceEditorIframe");
 842          iframe.setAttribute("border", "0");
 843          iframe.setAttribute("frameBorder", "0");
 844          iframe.setAttribute("marginWidth", "0");
 845          iframe.setAttribute("marginHeight", "0");
 846          iframe.setAttribute("leftMargin", "0");
 847          iframe.setAttribute("topMargin", "0");
 848          iframe.setAttribute("width", aw);
 849          iframe.setAttribute("height", ah);
 850          iframe.setAttribute("allowtransparency", "true");
 851          iframe.className = 'mceEditorIframe';
 852  
 853          if (tinyMCE.settings.auto_resize)
 854              iframe.setAttribute("scrolling", "no");
 855  
 856          // Must have a src element in MSIE HTTPs breaks aswell as absoute URLs
 857          if (tinyMCE.isRealIE)
 858              iframe.setAttribute("src", this.settings.default_document);
 859  
 860          iframe.style.width = aw;
 861          iframe.style.height = ah;
 862  
 863          // Ugly hack for Gecko problem in strict mode
 864          if (tinyMCE.settings.strict_loading_mode)
 865              iframe.style.marginBottom = '-5px';
 866  
 867          // MSIE 5.0 issue
 868          if (tinyMCE.isRealIE)
 869              replace_element.outerHTML = iframe.outerHTML;
 870          else
 871              replace_element.parentNode.replaceChild(iframe, replace_element);
 872  
 873          if (tinyMCE.isRealIE)
 874              return win.frames[id];
 875          else
 876              return iframe;
 877      },
 878  
 879      setupContent : function(editor_id) {
 880          var inst = tinyMCE.instances[editor_id], i, doc = inst.getDoc(), head = doc.getElementsByTagName('head').item(0);
 881          var content = inst.startContent, contentElement, body;
 882  
 883          // HTML values get XML encoded in strict mode
 884          if (tinyMCE.settings.strict_loading_mode) {
 885              content = content.replace(/&lt;/g, '<');
 886              content = content.replace(/&gt;/g, '>');
 887              content = content.replace(/&quot;/g, '"');
 888              content = content.replace(/&amp;/g, '&');
 889          }
 890  
 891          tinyMCE.selectedInstance = inst;
 892          inst.switchSettings();
 893  
 894          // Not loaded correctly hit it again, Mozilla bug #997860
 895          if (!tinyMCE.isIE && tinyMCE.getParam("setupcontent_reload", false) && doc.title != "blank_page") {
 896              // This part will remove the designMode status
 897              // Failes first time in Firefox 1.5b2 on Mac
 898              try {doc.location.href = tinyMCE.baseURL + "/blank.htm";} catch (ex) {}
 899              window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 1000);
 900              return;
 901          }
 902  
 903          // Wait for it to load
 904          if (!head || !doc.body) {
 905              window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 10);
 906              return;
 907          }
 908  
 909          // Import theme specific content CSS the user specific
 910          tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/themes/" + inst.settings.theme + "/css/editor_content.css");
 911          tinyMCE.importCSS(inst.getDoc(), inst.settings.content_css);
 912          tinyMCE.dispatchCallback(inst, 'init_instance_callback', 'initInstance', inst);
 913  
 914          // Setup keyboard shortcuts
 915          if (tinyMCE.getParam('custom_undo_redo_keyboard_shortcuts')) {
 916              inst.addShortcut('ctrl', 'z', 'lang_undo_desc', 'Undo');
 917              inst.addShortcut('ctrl', 'y', 'lang_redo_desc', 'Redo');
 918          }
 919  
 920          // BlockFormat shortcuts keys
 921          for (i=1; i<=6; i++)
 922              inst.addShortcut('ctrl', '' + i, '', 'FormatBlock', false, '<h' + i + '>');
 923  
 924          inst.addShortcut('ctrl', '7', '', 'FormatBlock', false, '<p>');
 925          inst.addShortcut('ctrl', '8', '', 'FormatBlock', false, '<div>');
 926          inst.addShortcut('ctrl', '9', '', 'FormatBlock', false, '<address>');
 927  
 928          // Add default shortcuts for gecko
 929          if (tinyMCE.isGecko) {
 930              inst.addShortcut('ctrl', 'b', 'lang_bold_desc', 'Bold');
 931              inst.addShortcut('ctrl', 'i', 'lang_italic_desc', 'Italic');
 932              inst.addShortcut('ctrl', 'u', 'lang_underline_desc', 'Underline');
 933          }
 934  
 935          // Setup span styles
 936          if (tinyMCE.getParam("convert_fonts_to_spans"))
 937              inst.getBody().setAttribute('id', 'mceSpanFonts');
 938  
 939          if (tinyMCE.settings.nowrap)
 940              doc.body.style.whiteSpace = "nowrap";
 941  
 942          doc.body.dir = this.settings.directionality;
 943          doc.editorId = editor_id;
 944  
 945          // Add on document element in Mozilla
 946          if (!tinyMCE.isIE)
 947              doc.documentElement.editorId = editor_id;
 948  
 949          inst.setBaseHREF(tinyMCE.settings.base_href);
 950  
 951          // Replace new line characters to BRs
 952          if (tinyMCE.settings.convert_newlines_to_brs) {
 953              content = tinyMCE.regexpReplace(content, "\r\n", "<br />", "gi");
 954              content = tinyMCE.regexpReplace(content, "\r", "<br />", "gi");
 955              content = tinyMCE.regexpReplace(content, "\n", "<br />", "gi");
 956          }
 957  
 958          // Open closed anchors
 959      //    content = content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');
 960  
 961          // Call custom cleanup code
 962          content = tinyMCE.storeAwayURLs(content);
 963          content = tinyMCE._customCleanup(inst, "insert_to_editor", content);
 964  
 965          if (tinyMCE.isIE) {
 966              // Ugly!!!
 967              window.setInterval('try{tinyMCE.getCSSClasses(tinyMCE.instances["' + editor_id + '"].getDoc(), "' + editor_id + '");}catch(e){}', 500);
 968  
 969              if (tinyMCE.settings.force_br_newlines)
 970                  doc.styleSheets[0].addRule("p", "margin: 0;");
 971  
 972              body = inst.getBody();
 973              body.editorId = editor_id;
 974          }
 975  
 976          content = tinyMCE.cleanupHTMLCode(content);
 977  
 978          // Fix for bug #958637
 979          if (!tinyMCE.isIE) {
 980              contentElement = inst.getDoc().createElement("body");
 981              doc = inst.getDoc();
 982  
 983              contentElement.innerHTML = content;
 984  
 985              if (tinyMCE.settings.cleanup_on_startup)
 986                  tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, doc, this.settings, contentElement));
 987              else
 988                  tinyMCE.setInnerHTML(inst.getBody(), content);
 989  
 990              tinyMCE.convertAllRelativeURLs(inst.getBody());
 991          } else {
 992              if (tinyMCE.settings.cleanup_on_startup) {
 993                  tinyMCE._setHTML(inst.getDoc(), content);
 994  
 995                  // Produces permission denied error in MSIE 5.5
 996                  try {
 997                      tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, inst.contentDocument, this.settings, inst.getBody()));
 998                  } catch(e) {
 999                      // Ignore
1000                  }
1001              } else
1002                  tinyMCE._setHTML(inst.getDoc(), content);
1003          }
1004  
1005          // Fix for bug #957681
1006          //inst.getDoc().designMode = inst.getDoc().designMode;
1007  
1008          tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings.visual, inst);
1009          tinyMCE.dispatchCallback(inst, 'setupcontent_callback', 'setupContent', editor_id, inst.getBody(), inst.getDoc());
1010  
1011          // Re-add design mode on mozilla
1012          if (!tinyMCE.isIE)
1013              tinyMCE.addEventHandlers(inst);
1014  
1015          // Add blur handler
1016          if (tinyMCE.isIE) {
1017              tinyMCE.addEvent(inst.getBody(), "blur", TinyMCE_Engine.prototype._eventPatch);
1018              tinyMCE.addEvent(inst.getBody(), "beforedeactivate", TinyMCE_Engine.prototype._eventPatch); // Bug #1439953
1019  
1020              // Workaround for drag drop/copy paste base href bug
1021              if (!tinyMCE.isOpera) {
1022                  tinyMCE.addEvent(doc.body, "mousemove", TinyMCE_Engine.prototype.onMouseMove);
1023                  tinyMCE.addEvent(doc.body, "beforepaste", TinyMCE_Engine.prototype._eventPatch);
1024                  tinyMCE.addEvent(doc.body, "drop", TinyMCE_Engine.prototype._eventPatch);
1025              }
1026          }
1027  
1028          // Trigger node change, this call locks buttons for tables and so forth
1029          inst.select();
1030          tinyMCE.selectedElement = inst.contentWindow.document.body;
1031  
1032          // Call custom DOM cleanup
1033          tinyMCE._customCleanup(inst, "insert_to_editor_dom", inst.getBody());
1034          tinyMCE._customCleanup(inst, "setup_content_dom", inst.getBody());
1035          tinyMCE._setEventsEnabled(inst.getBody(), false);
1036          tinyMCE.cleanupAnchors(inst.getDoc());
1037  
1038          if (tinyMCE.getParam("convert_fonts_to_spans"))
1039              tinyMCE.convertSpansToFonts(inst.getDoc());
1040  
1041          inst.startContent = tinyMCE.trim(inst.getBody().innerHTML);
1042          inst.undoRedo.add({ content : inst.startContent });
1043  
1044          // Cleanup any mess left from storyAwayURLs
1045          if (tinyMCE.isGecko) {
1046              // Remove mce_src from textnodes and comments
1047              tinyMCE.selectNodes(inst.getBody(), function(n) {
1048                  if (n.nodeType == 3 || n.nodeType == 8)
1049                      n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");
1050  
1051                  return false;
1052              });
1053          }
1054  
1055          // Remove Gecko spellchecking
1056          if (tinyMCE.isGecko)
1057              inst.getBody().spellcheck = tinyMCE.getParam("gecko_spellcheck");
1058  
1059          // Cleanup any mess left from storyAwayURLs
1060          tinyMCE._removeInternal(inst.getBody());
1061  
1062          inst.select();
1063          tinyMCE.triggerNodeChange(false, true);
1064      },
1065  
1066      storeAwayURLs : function(s) {
1067          // Remove all mce_src, mce_href and replace them with new ones
1068          // s = s.replace(new RegExp('mce_src\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');
1069          // s = s.replace(new RegExp('mce_href\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');
1070  
1071          if (!s.match(/(mce_src|mce_href)/gi, s)) {
1072              s = s.replace(new RegExp('src\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'src="$1" mce_src="$1"');
1073              s = s.replace(new RegExp('href\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'href="$1" mce_href="$1"');
1074          }
1075  
1076          return s;
1077      },
1078  
1079      _removeInternal : function(n) {
1080          if (tinyMCE.isGecko) {
1081              // Remove mce_src from textnodes and comments
1082              tinyMCE.selectNodes(n, function(n) {
1083                  if (n.nodeType == 3 || n.nodeType == 8)
1084                      n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");
1085  
1086                  return false;
1087              });
1088          }
1089      },
1090  
1091      removeTinyMCEFormElements : function(form_obj) {
1092          var i, elementId;
1093  
1094          // Skip form element removal
1095          if (!tinyMCE.getParam('hide_selects_on_submit'))
1096              return;
1097  
1098          // Check if form is valid
1099          if (typeof(form_obj) == "undefined" || form_obj == null)
1100              return;
1101  
1102          // If not a form, find the form
1103          if (form_obj.nodeName != "FORM") {
1104              if (form_obj.form)
1105                  form_obj = form_obj.form;
1106              else
1107                  form_obj = tinyMCE.getParentElement(form_obj, "form");
1108          }
1109  
1110          // Still nothing
1111          if (form_obj == null)
1112              return;
1113  
1114          // Disable all UI form elements that TinyMCE created
1115          for (i=0; i<form_obj.elements.length; i++) {
1116              elementId = form_obj.elements[i].name ? form_obj.elements[i].name : form_obj.elements[i].id;
1117  
1118              if (elementId.indexOf('mce_editor_') == 0)
1119                  form_obj.elements[i].disabled = true;
1120          }
1121      },
1122  
1123      handleEvent : function(e) {
1124          var inst = tinyMCE.selectedInstance, i, elm, keys;
1125  
1126          // Remove odd, error
1127          if (typeof(tinyMCE) == "undefined")
1128              return true;
1129  
1130          //tinyMCE.debug(e.type + " " + e.target.nodeName + " " + (e.relatedTarget ? e.relatedTarget.nodeName : ""));
1131  
1132          if (tinyMCE.executeCallback(tinyMCE.selectedInstance, 'handle_event_callback', 'handleEvent', e))
1133              return false;
1134  
1135          switch (e.type) {
1136              case "beforedeactivate": // Was added due to bug #1439953
1137              case "blur":
1138                  if (tinyMCE.selectedInstance)
1139                      tinyMCE.selectedInstance.execCommand('mceEndTyping');
1140  
1141                  tinyMCE.hideMenus();
1142  
1143                  return;
1144  
1145              // Workaround for drag drop/copy paste base href bug
1146              case "drop":
1147              case "beforepaste":
1148                  if (tinyMCE.selectedInstance)
1149                      tinyMCE.selectedInstance.setBaseHREF(null);
1150  
1151                  // Fixes odd MSIE bug where drag/droping elements in a iframe with height 100% breaks
1152                  // This logic forces the width/height to be in pixels while the user is drag/dropping
1153                  if (tinyMCE.isRealIE) {
1154                      var ife = tinyMCE.selectedInstance.iframeElement;
1155  
1156                      /*if (ife.style.width.indexOf('%') != -1) {
1157                          ife._oldWidth = ife.width.height;
1158                          ife.style.width = ife.clientWidth;
1159                      }*/
1160  
1161                      if (ife.style.height.indexOf('%') != -1) {
1162                          ife._oldHeight = ife.style.height;
1163                          ife.style.height = ife.clientHeight;
1164                      }
1165                  }
1166  
1167                  window.setTimeout("tinyMCE.selectedInstance.setBaseHREF(tinyMCE.settings.base_href);tinyMCE._resetIframeHeight();", 1);
1168                  return;
1169  
1170              case "submit":
1171                  tinyMCE.formSubmit(tinyMCE.isMSIE ? window.event.srcElement : e.target);
1172                  return;
1173  
1174              case "reset":
1175                  var formObj = tinyMCE.isIE ? window.event.srcElement : e.target;
1176  
1177                  for (i=0; i<document.forms.length; i++) {
1178                      if (document.forms[i] == formObj)
1179                          window.setTimeout('tinyMCE.resetForm(' + i + ');', 10);
1180                  }
1181  
1182                  return;
1183  
1184              case "keypress":
1185                  if (inst && inst.handleShortcut(e))
1186                      return false;
1187  
1188                  if (e.target.editorId) {
1189                      tinyMCE.instances[e.target.editorId].select();
1190                  } else {
1191                      if (e.target.ownerDocument.editorId)
1192                          tinyMCE.instances[e.target.ownerDocument.editorId].