[ Index ]

PHP Cross Reference of Limb3

title

Body

[close]

/wysiwyg/shared/tiny_mce/ -> tiny_mce_src.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";
   9      this.releaseDate = "2007-05-08";
  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);