includes/clientside/tinymce/tiny_mce_src.js
changeset 1 fe660c52c48f
child 40 723bb7acf914
equal deleted inserted replaced
0:902822492a68 1:fe660c52c48f
       
     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.0";
       
     9 	this.releaseDate = "2007-02-13";
       
    10 
       
    11 	this.instances = new Array();
       
    12 	this.switchClassCache = new Array();
       
    13 	this.windowArgs = new Array();
       
    14 	this.loadedFiles = new Array();
       
    15 	this.pendingFiles = new Array();
       
    16 	this.loadingIndex = 0;
       
    17 	this.configs = new Array();
       
    18 	this.currentConfig = 0;
       
    19 	this.eventHandlers = new Array();
       
    20 	this.log = new Array();
       
    21 	this.undoLevels = [];
       
    22 	this.undoIndex = 0;
       
    23 	this.typingUndoIndex = -1;
       
    24 
       
    25 	// Browser check
       
    26 	ua = navigator.userAgent;
       
    27 	this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
       
    28 	this.isMSIE5 = this.isMSIE && (ua.indexOf('MSIE 5') != -1);
       
    29 	this.isMSIE5_0 = this.isMSIE && (ua.indexOf('MSIE 5.0') != -1);
       
    30 	this.isMSIE7 = this.isMSIE && (ua.indexOf('MSIE 7') != -1);
       
    31 	this.isGecko = ua.indexOf('Gecko') != -1;
       
    32 	this.isSafari = ua.indexOf('Safari') != -1;
       
    33 	this.isOpera = ua.indexOf('Opera') != -1;
       
    34 	this.isMac = ua.indexOf('Mac') != -1;
       
    35 	this.isNS7 = ua.indexOf('Netscape/7') != -1;
       
    36 	this.isNS71 = ua.indexOf('Netscape/7.1') != -1;
       
    37 	this.dialogCounter = 0;
       
    38 	this.plugins = new Array();
       
    39 	this.themes = new Array();
       
    40 	this.menus = new Array();
       
    41 	this.loadedPlugins = new Array();
       
    42 	this.buttonMap = new Array();
       
    43 	this.isLoaded = false;
       
    44 
       
    45 	// Fake MSIE on Opera and if Opera fakes IE, Gecko or Safari cancel those
       
    46 	if (this.isOpera) {
       
    47 		this.isMSIE = true;
       
    48 		this.isGecko = false;
       
    49 		this.isSafari =  false;
       
    50 	}
       
    51 
       
    52 	this.isIE = this.isMSIE;
       
    53 	this.isRealIE = this.isMSIE && !this.isOpera;
       
    54 
       
    55 	// TinyMCE editor id instance counter
       
    56 	this.idCounter = 0;
       
    57 };
       
    58 
       
    59 TinyMCE_Engine.prototype = {
       
    60 	init : function(settings) {
       
    61 		var theme, nl, baseHREF = "", i;
       
    62 
       
    63 		// 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.
       
    64 		if (this.isMSIE5_0)
       
    65 			return;
       
    66 
       
    67 		this.settings = settings;
       
    68 
       
    69 		// Check if valid browser has execcommand support
       
    70 		if (typeof(document.execCommand) == 'undefined')
       
    71 			return;
       
    72 
       
    73 		// Get script base path
       
    74 		if (!tinyMCE.baseURL) {
       
    75 			var elements = document.getElementsByTagName('script');
       
    76 
       
    77 			// If base element found, add that infront of baseURL
       
    78 			nl = document.getElementsByTagName('base');
       
    79 			for (i=0; i<nl.length; i++) {
       
    80 				if (nl[i].href)
       
    81 					baseHREF = nl[i].href;
       
    82 			}
       
    83 
       
    84 			for (var i=0; i<elements.length; i++) {
       
    85 				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)) {
       
    86 					var src = elements[i].src;
       
    87 
       
    88 					tinyMCE.srcMode = (src.indexOf('_src') != -1 || src.indexOf('_dev') != -1) ? '_src' : '';
       
    89 					tinyMCE.gzipMode = src.indexOf('_gzip') != -1;
       
    90 					src = src.substring(0, src.lastIndexOf('/'));
       
    91 
       
    92 					if (settings.exec_mode == "src" || settings.exec_mode == "normal")
       
    93 						tinyMCE.srcMode = settings.exec_mode == "src" ? '_src' : '';
       
    94 
       
    95 					// Force it absolute if page has a base href
       
    96 					if (baseHREF != "" && src.indexOf('://') == -1)
       
    97 						tinyMCE.baseURL = baseHREF + src;
       
    98 					else
       
    99 						tinyMCE.baseURL = src;
       
   100 
       
   101 					break;
       
   102 				}
       
   103 			}
       
   104 		}
       
   105 
       
   106 		// Get document base path
       
   107 		this.documentBasePath = document.location.href;
       
   108 		if (this.documentBasePath.indexOf('?') != -1)
       
   109 			this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.indexOf('?'));
       
   110 		this.documentURL = this.documentBasePath;
       
   111 		this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.lastIndexOf('/'));
       
   112 
       
   113 		// If not HTTP absolute
       
   114 		if (tinyMCE.baseURL.indexOf('://') == -1 && tinyMCE.baseURL.charAt(0) != '/') {
       
   115 			// If site absolute
       
   116 			tinyMCE.baseURL = this.documentBasePath + "/" + tinyMCE.baseURL;
       
   117 		}
       
   118 
       
   119 		// Set default values on settings
       
   120 		this._def("mode", "none");
       
   121 		this._def("theme", "advanced");
       
   122 		this._def("plugins", "", true);
       
   123 		this._def("language", "en");
       
   124 		this._def("docs_language", this.settings['language']);
       
   125 		this._def("elements", "");
       
   126 		this._def("textarea_trigger", "mce_editable");
       
   127 		this._def("editor_selector", "");
       
   128 		this._def("editor_deselector", "mceNoEditor");
       
   129 		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]");
       
   130 		this._def("extended_valid_elements", "");
       
   131 		this._def("invalid_elements", "");
       
   132 		this._def("encoding", "");
       
   133 		this._def("urlconverter_callback", tinyMCE.getParam("urlconvertor_callback", "TinyMCE_Engine.prototype.convertURL"));
       
   134 		this._def("save_callback", "");
       
   135 		this._def("debug", false);
       
   136 		this._def("force_br_newlines", false);
       
   137 		this._def("force_p_newlines", true);
       
   138 		this._def("add_form_submit_trigger", true);
       
   139 		this._def("relative_urls", true);
       
   140 		this._def("remove_script_host", true);
       
   141 		this._def("focus_alert", true);
       
   142 		this._def("document_base_url", this.documentURL);
       
   143 		this._def("visual", true);
       
   144 		this._def("visual_table_class", "mceVisualAid");
       
   145 		this._def("setupcontent_callback", "");
       
   146 		this._def("fix_content_duplication", true);
       
   147 		this._def("custom_undo_redo", true);
       
   148 		this._def("custom_undo_redo_levels", -1);
       
   149 		this._def("custom_undo_redo_keyboard_shortcuts", true);
       
   150 		this._def("custom_undo_redo_restore_selection", true);
       
   151 		this._def("custom_undo_redo_global", false);
       
   152 		this._def("verify_html", true);
       
   153 		this._def("apply_source_formatting", false);
       
   154 		this._def("directionality", "ltr");
       
   155 		this._def("cleanup_on_startup", false);
       
   156 		this._def("inline_styles", false);
       
   157 		this._def("convert_newlines_to_brs", false);
       
   158 		this._def("auto_reset_designmode", true);
       
   159 		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);
       
   160 		this._def("entity_encoding", "named");
       
   161 		this._def("cleanup_callback", "");
       
   162 		this._def("add_unload_trigger", true);
       
   163 		this._def("ask", false);
       
   164 		this._def("nowrap", false);
       
   165 		this._def("auto_resize", false);
       
   166 		this._def("auto_focus", false);
       
   167 		this._def("cleanup", true);
       
   168 		this._def("remove_linebreaks", true);
       
   169 		this._def("button_tile_map", false);
       
   170 		this._def("submit_patch", true);
       
   171 		this._def("browsers", "msie,safari,gecko,opera", true);
       
   172 		this._def("dialog_type", "window");
       
   173 		this._def("accessibility_warnings", true);
       
   174 		this._def("accessibility_focus", true);
       
   175 		this._def("merge_styles_invalid_parents", "");
       
   176 		this._def("force_hex_style_colors", true);
       
   177 		this._def("trim_span_elements", true);
       
   178 		this._def("convert_fonts_to_spans", false);
       
   179 		this._def("doctype", '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">');
       
   180 		this._def("font_size_classes", '');
       
   181 		this._def("font_size_style_values", 'xx-small,x-small,small,medium,large,x-large,xx-large', true);
       
   182 		this._def("event_elements", 'a,img', true);
       
   183 		this._def("convert_urls", true);
       
   184 		this._def("table_inline_editing", false);
       
   185 		this._def("object_resizing", true);
       
   186 		this._def("custom_shortcuts", true);
       
   187 		this._def("convert_on_click", false);
       
   188 		this._def("content_css", '');
       
   189 		this._def("fix_list_elements", true);
       
   190 		this._def("fix_table_elements", false);
       
   191 		this._def("strict_loading_mode", ( ( IE ) ? true : true ) ); // document.contentType == 'application/xhtml+xml');
       
   192 		this._def("hidden_tab_class", '');
       
   193 		this._def("display_tab_class", '');
       
   194 		this._def("gecko_spellcheck", false);
       
   195 		this._def("hide_selects_on_submit", true);
       
   196 
       
   197 		// Force strict loading mode to false on non Gecko browsers
       
   198 		//if (this.isMSIE && !this.isOpera)
       
   199 		//	this.settings.strict_loading_mode = false;
       
   200 
       
   201 		// Browser check IE
       
   202 		if (this.isMSIE && this.settings['browsers'].indexOf('msie') == -1)
       
   203 			return;
       
   204 
       
   205 		// Browser check Gecko
       
   206 		if (this.isGecko && this.settings['browsers'].indexOf('gecko') == -1)
       
   207 			return;
       
   208 
       
   209 		// Browser check Safari
       
   210 		if (this.isSafari && this.settings['browsers'].indexOf('safari') == -1)
       
   211 			return;
       
   212 
       
   213 		// Browser check Opera
       
   214 		if (this.isOpera && this.settings['browsers'].indexOf('opera') == -1)
       
   215 			return;
       
   216 
       
   217 		// If not super absolute make it so
       
   218 		baseHREF = tinyMCE.settings['document_base_url'];
       
   219 		var h = document.location.href;
       
   220 		var p = h.indexOf('://');
       
   221 		if (p > 0 && document.location.protocol != "file:") {
       
   222 			p = h.indexOf('/', p + 3);
       
   223 			h = h.substring(0, p);
       
   224 
       
   225 			if (baseHREF.indexOf('://') == -1)
       
   226 				baseHREF = h + baseHREF;
       
   227 
       
   228 			tinyMCE.settings['document_base_url'] = baseHREF;
       
   229 			tinyMCE.settings['document_base_prefix'] = h;
       
   230 		}
       
   231 
       
   232 		// Trim away query part
       
   233 		if (baseHREF.indexOf('?') != -1)
       
   234 			baseHREF = baseHREF.substring(0, baseHREF.indexOf('?'));
       
   235 
       
   236 		this.settings['base_href'] = baseHREF.substring(0, baseHREF.lastIndexOf('/')) + "/";
       
   237 
       
   238 		theme = this.settings['theme'];
       
   239 		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';
       
   240 		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';
       
   241 		this.blockElms = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';
       
   242 		this.blockRegExp = new RegExp("^(" + this.blockElms + ")$", "i");
       
   243 		this.posKeyCodes = new Array(13,45,36,35,33,34,37,38,39,40);
       
   244 		this.uniqueURL = 'javascript:void(091039730);'; // Make unique URL non real URL
       
   245 		this.uniqueTag = '<div id="mceTMPElement" style="display: none">TMP</div>';
       
   246 		this.callbacks = new Array('onInit', 'getInfo', 'getEditorTemplate', 'setupContent', 'onChange', 'onPageLoad', 'handleNodeChange', 'initInstance', 'execCommand', 'getControlHTML', 'handleEvent', 'cleanup', 'removeInstance');
       
   247 
       
   248 		// Theme url
       
   249 		this.settings['theme_href'] = tinyMCE.baseURL + "/themes/" + theme;
       
   250 
       
   251 		if (!tinyMCE.isIE || tinyMCE.isOpera)
       
   252 			this.settings['force_br_newlines'] = false;
       
   253 
       
   254 		if (tinyMCE.getParam("popups_css", false)) {
       
   255 			var cssPath = tinyMCE.getParam("popups_css", "");
       
   256 
       
   257 			// Is relative
       
   258 			if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')
       
   259 				this.settings['popups_css'] = this.documentBasePath + "/" + cssPath;
       
   260 			else
       
   261 				this.settings['popups_css'] = cssPath;
       
   262 		} else
       
   263 			this.settings['popups_css'] = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_popup.css";
       
   264 
       
   265 		if (tinyMCE.getParam("editor_css", false)) {
       
   266 			var cssPath = tinyMCE.getParam("editor_css", "");
       
   267 
       
   268 			// Is relative
       
   269 			if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')
       
   270 				this.settings['editor_css'] = this.documentBasePath + "/" + cssPath;
       
   271 			else
       
   272 				this.settings['editor_css'] = cssPath;
       
   273 		} else {
       
   274 			if (this.settings.editor_css != '')
       
   275 				this.settings['editor_css'] = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_ui.css";
       
   276 		}
       
   277 
       
   278 		if (tinyMCE.settings['debug']) {
       
   279 			var msg = "Debug: \n";
       
   280 
       
   281 			msg += "baseURL: " + this.baseURL + "\n";
       
   282 			msg += "documentBasePath: " + this.documentBasePath + "\n";
       
   283 			msg += "content_css: " + this.settings['content_css'] + "\n";
       
   284 			msg += "popups_css: " + this.settings['popups_css'] + "\n";
       
   285 			msg += "editor_css: " + this.settings['editor_css'] + "\n";
       
   286 
       
   287 			alert(msg);
       
   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 		var p = tinyMCE.getParam('plugins', '', true, ',');
       
   313 		if (p.length > 0) {
       
   314 			for (var 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'] = new Array();
       
   323 			var entities = tinyMCE.getParam('entities', '', true, ',');
       
   324 			for (var 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 			}
       
   341 		}
       
   342 
       
   343 		// Setup XML encoding regexps
       
   344 		this.xmlEncodeAposRe = new RegExp('[<>&"\']', 'g');
       
   345 		this.xmlEncodeRe = new RegExp('[<>&"]', 'g');
       
   346 //		this.xmlEncodeEnts = {'&':'&amp;','"':'&quot;',"'":'&#39;','<':'&lt;','>':'&gt;'};
       
   347 	},
       
   348 
       
   349 	_addUnloadEvents : function() {
       
   350 		if (tinyMCE.isIE) {
       
   351 			if (tinyMCE.settings['add_unload_trigger']) {
       
   352 				tinyMCE.addEvent(window, "unload", TinyMCE_Engine.prototype.unloadHandler);
       
   353 				tinyMCE.addEvent(window.document, "beforeunload", TinyMCE_Engine.prototype.unloadHandler);
       
   354 			}
       
   355 		} else {
       
   356 			if (tinyMCE.settings['add_unload_trigger'])
       
   357 				tinyMCE.addEvent(window, "unload", function () {tinyMCE.triggerSave(true, true);});
       
   358 		}
       
   359 	},
       
   360 
       
   361 	_def : function(key, def_val, t) {
       
   362 		var v = tinyMCE.getParam(key, def_val);
       
   363 
       
   364 		v = t ? v.replace(/\s+/g, "") : v;
       
   365 
       
   366 		this.settings[key] = v;
       
   367 	},
       
   368 
       
   369 	hasPlugin : function(n) {
       
   370 		return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;
       
   371 	},
       
   372 
       
   373 	addPlugin : function(n, p) {
       
   374 		var op = this.plugins[n];
       
   375 
       
   376 		// Use the previous plugin object base URL used when loading external plugins
       
   377 		p.baseURL = op ? op.baseURL : tinyMCE.baseURL + "/plugins/" + n;
       
   378 		this.plugins[n] = p;
       
   379 
       
   380 		this.loadNextScript();
       
   381 	},
       
   382 
       
   383 	setPluginBaseURL : function(n, u) {
       
   384 		var op = this.plugins[n];
       
   385 
       
   386 		if (op)
       
   387 			op.baseURL = u;
       
   388 		else
       
   389 			this.plugins[n] = {baseURL : u};
       
   390 	},
       
   391 
       
   392 	loadPlugin : function(n, u) {
       
   393 		u = u.indexOf('.js') != -1 ? u.substring(0, u.lastIndexOf('/')) : u;
       
   394 		u = u.charAt(u.length-1) == '/' ? u.substring(0, u.length-1) : u;
       
   395 		this.plugins[n] = {baseURL : u};
       
   396 		this.loadScript(u + "/editor_plugin" + (tinyMCE.srcMode ? '_src' : '') + ".js");
       
   397 	},
       
   398 
       
   399 	hasTheme : function(n) {
       
   400 		return typeof(this.themes[n]) != "undefined" && this.themes[n] != null;
       
   401 	},
       
   402 
       
   403 	addTheme : function(n, t) {
       
   404 		this.themes[n] = t;
       
   405 
       
   406 		this.loadNextScript();
       
   407 	},
       
   408 
       
   409 	addMenu : function(n, m) {
       
   410 		this.menus[n] = m;
       
   411 	},
       
   412 
       
   413 	hasMenu : function(n) {
       
   414 		return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;
       
   415 	},
       
   416 
       
   417 	loadScript : function(url) {
       
   418 		var i;
       
   419 
       
   420 		for (i=0; i<this.loadedFiles.length; i++) {
       
   421 			if (this.loadedFiles[i] == url)
       
   422 				return;
       
   423 		}
       
   424 
       
   425 		if (tinyMCE.settings.strict_loading_mode)
       
   426 			this.pendingFiles[this.pendingFiles.length] = url;
       
   427 		else
       
   428     {
       
   429       document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></script>');
       
   430     }
       
   431 
       
   432 		this.loadedFiles[this.loadedFiles.length] = url;
       
   433 	},
       
   434 
       
   435 	loadNextScript : function() {
       
   436 		var d = document, se;
       
   437 
       
   438 		if (!tinyMCE.settings.strict_loading_mode)
       
   439 			return;
       
   440 
       
   441 		if (this.loadingIndex < this.pendingFiles.length) {
       
   442 			se = d.createElementNS('http://www.w3.org/1999/xhtml', 'script');
       
   443 			se.setAttribute('language', 'javascript');
       
   444 			se.setAttribute('type', 'text/javascript');
       
   445 			se.setAttribute('src', this.pendingFiles[this.loadingIndex++]);
       
   446 
       
   447 			d.getElementsByTagName("head")[0].appendChild(se);
       
   448 		} else
       
   449 			this.loadingIndex = -1; // Done with loading
       
   450 	},
       
   451 
       
   452 	loadCSS : function(url) {
       
   453 		var ar = url.replace(/\s+/, '').split(',');
       
   454 		var lflen = 0, csslen = 0;
       
   455 		var skip = false;
       
   456 		var x = 0, i = 0, nl, le;
       
   457 
       
   458 		for (x = 0,csslen = ar.length; x<csslen; x++) {
       
   459 			if (ar[x] != null && ar[x] != 'null' && ar[x].length > 0) {
       
   460 				/* Make sure it doesn't exist. */
       
   461 				for (i=0, lflen=this.loadedFiles.length; i<lflen; i++) {
       
   462 					if (this.loadedFiles[i] == ar[x]) {
       
   463 						skip = true;
       
   464 						break;
       
   465 					}
       
   466 				}
       
   467 
       
   468 				if (!skip) {
       
   469 					if (tinyMCE.settings.strict_loading_mode) {
       
   470 						nl = document.getElementsByTagName("head");
       
   471 
       
   472 						le = document.createElement('link');
       
   473 						le.setAttribute('href', ar[x]);
       
   474 						le.setAttribute('rel', 'stylesheet');
       
   475 						le.setAttribute('type', 'text/css');
       
   476 
       
   477 						nl[0].appendChild(le);			
       
   478 					} else
       
   479           {
       
   480             document.write('<link href="' + ar[x] + '" rel="stylesheet" type="text/css" />');
       
   481           }
       
   482 
       
   483 					this.loadedFiles[this.loadedFiles.length] = ar[x];
       
   484 				}
       
   485 			}
       
   486 		}
       
   487 	},
       
   488 
       
   489 	importCSS : function(doc, css) {
       
   490 		var css_ary = css.replace(/\s+/, '').split(',');
       
   491 		var csslen, elm, headArr, x, css_file;
       
   492 
       
   493 		for (x = 0, csslen = css_ary.length; x<csslen; x++) {
       
   494 			css_file = css_ary[x];
       
   495 
       
   496 			if (css_file != null && css_file != 'null' && css_file.length > 0) {
       
   497 				// Is relative, make absolute
       
   498 				if (css_file.indexOf('://') == -1 && css_file.charAt(0) != '/')
       
   499 					css_file = this.documentBasePath + "/" + css_file;
       
   500 
       
   501 				if (typeof(doc.createStyleSheet) == "undefined") {
       
   502 					elm = doc.createElement("link");
       
   503 
       
   504 					elm.rel = "stylesheet";
       
   505 					elm.href = css_file;
       
   506 
       
   507 					if ((headArr = doc.getElementsByTagName("head")) != null && headArr.length > 0)
       
   508 						headArr[0].appendChild(elm);
       
   509 				} else
       
   510 					doc.createStyleSheet(css_file);
       
   511 			}
       
   512 		}
       
   513 	},
       
   514 
       
   515 	confirmAdd : function(e, settings) {
       
   516 		var elm = tinyMCE.isIE ? event.srcElement : e.target;
       
   517 		var elementId = elm.name ? elm.name : elm.id;
       
   518 
       
   519 		tinyMCE.settings = settings;
       
   520 
       
   521 		if (tinyMCE.settings['convert_on_click'] || (!elm.getAttribute('mce_noask') && confirm(tinyMCELang['lang_edit_confirm'])))
       
   522 			tinyMCE.addMCEControl(elm, elementId);
       
   523 
       
   524 		elm.setAttribute('mce_noask', 'true');
       
   525 	},
       
   526 
       
   527 	updateContent : function(form_element_name) {
       
   528 		// Find MCE instance linked to given form element and copy it's value
       
   529 		var formElement = document.getElementById(form_element_name);
       
   530 		for (var n in tinyMCE.instances) {
       
   531 			var inst = tinyMCE.instances[n];
       
   532 			if (!tinyMCE.isInstance(inst))
       
   533 				continue;
       
   534 
       
   535 			inst.switchSettings();
       
   536 
       
   537 			if (inst.formElement == formElement) {
       
   538 				var doc = inst.getDoc();
       
   539 		
       
   540 				tinyMCE._setHTML(doc, inst.formElement.value);
       
   541 
       
   542 				if (!tinyMCE.isIE)
       
   543 					doc.body.innerHTML = tinyMCE._cleanupHTML(inst, doc, this.settings, doc.body, inst.visualAid);
       
   544 			}
       
   545 		}
       
   546 	},
       
   547 
       
   548 	addMCEControl : function(replace_element, form_element_name, target_document) {
       
   549 		var id = "mce_editor_" + tinyMCE.idCounter++;
       
   550 		var inst = new TinyMCE_Control(tinyMCE.settings);
       
   551 
       
   552 		inst.editorId = id;
       
   553 		this.instances[id] = inst;
       
   554 
       
   555 		inst._onAdd(replace_element, form_element_name, target_document);
       
   556 	},
       
   557 
       
   558 	removeInstance : function(ti) {
       
   559 		var t = [], n, i;
       
   560 
       
   561 		// Remove from instances
       
   562 		for (n in tinyMCE.instances) {
       
   563 			i = tinyMCE.instances[n];
       
   564 
       
   565 			if (tinyMCE.isInstance(i) && ti != i)
       
   566 					t[n] = i;
       
   567 		}
       
   568 
       
   569 		tinyMCE.instances = t;
       
   570 
       
   571 		// Remove from global undo/redo
       
   572 		n = [];
       
   573 		t = tinyMCE.undoLevels;
       
   574 
       
   575 		for (i=0; i<t.length; i++) {
       
   576 			if (t[i] != ti)
       
   577 				n.push(t[i]);
       
   578 		}
       
   579 
       
   580 		tinyMCE.undoLevels = n;
       
   581 		tinyMCE.undoIndex = n.length;
       
   582 
       
   583 		// Dispatch remove instance call
       
   584 		tinyMCE.dispatchCallback(ti, 'remove_instance_callback', 'removeInstance', ti);
       
   585 
       
   586 		return ti;
       
   587 	},
       
   588 
       
   589 	removeMCEControl : function(editor_id) {
       
   590 		var inst = tinyMCE.getInstanceById(editor_id), h, re, ot, tn;
       
   591 
       
   592 		if (inst) {
       
   593 			inst.switchSettings();
       
   594 
       
   595 			editor_id = inst.editorId;
       
   596 			h = tinyMCE.getContent(editor_id);
       
   597 
       
   598 			this.removeInstance(inst);
       
   599 
       
   600 			tinyMCE.selectedElement = null;
       
   601 			tinyMCE.selectedInstance = null;
       
   602 
       
   603 			// Remove element
       
   604 			re = document.getElementById(editor_id + "_parent");
       
   605 			ot = inst.oldTargetElement;
       
   606 			tn = ot.nodeName.toLowerCase();
       
   607 
       
   608 			if (tn == "textarea" || tn == "input") {
       
   609 				re.parentNode.removeChild(re);
       
   610 				ot.style.display = "inline";
       
   611 				ot.value = h;
       
   612 			} else {
       
   613 				ot.innerHTML = h;
       
   614 				ot.style.display = 'block';
       
   615 				re.parentNode.insertBefore(ot, re);
       
   616 				re.parentNode.removeChild(re);
       
   617 			}
       
   618 		}
       
   619 	},
       
   620 
       
   621 	triggerSave : function(skip_cleanup, skip_callback) {
       
   622 		var inst, n;
       
   623 
       
   624 		// Default to false
       
   625 		if (typeof(skip_cleanup) == "undefined")
       
   626 			skip_cleanup = false;
       
   627 
       
   628 		// Default to false
       
   629 		if (typeof(skip_callback) == "undefined")
       
   630 			skip_callback = false;
       
   631 
       
   632 		// Cleanup and set all form fields
       
   633 		for (n in tinyMCE.instances) {
       
   634 			inst = tinyMCE.instances[n];
       
   635 
       
   636 			if (!tinyMCE.isInstance(inst))
       
   637 				continue;
       
   638 
       
   639 			inst.triggerSave(skip_cleanup, skip_callback);
       
   640 		}
       
   641 	},
       
   642 
       
   643 	resetForm : function(form_index) {
       
   644 		var i, inst, n, formObj = document.forms[form_index];
       
   645 
       
   646 		for (n in tinyMCE.instances) {
       
   647 			inst = tinyMCE.instances[n];
       
   648 
       
   649 			if (!tinyMCE.isInstance(inst))
       
   650 				continue;
       
   651 
       
   652 			inst.switchSettings();
       
   653 
       
   654 			for (i=0; i<formObj.elements.length; i++) {
       
   655 				if (inst.formTargetElementId == formObj.elements[i].name)
       
   656 					inst.getBody().innerHTML = inst.startContent;
       
   657 			}
       
   658 		}
       
   659 	},
       
   660 
       
   661 	execInstanceCommand : function(editor_id, command, user_interface, value, focus) {
       
   662 		var inst = tinyMCE.getInstanceById(editor_id), r;
       
   663 
       
   664 		if (inst) {
       
   665 			r = inst.selection.getRng();
       
   666 
       
   667 			if (typeof(focus) == "undefined")
       
   668 				focus = true;
       
   669 
       
   670 			// IE bug lost focus on images in absolute divs Bug #1534575
       
   671 			if (focus && (!r || !r.item))
       
   672 				inst.contentWindow.focus();
       
   673 
       
   674 			// Reset design mode if lost
       
   675 			inst.autoResetDesignMode();
       
   676 
       
   677 			this.selectedElement = inst.getFocusElement();
       
   678 			inst.select();
       
   679 			tinyMCE.execCommand(command, user_interface, value);
       
   680 
       
   681 			// Cancel event so it doesn't call onbeforeonunlaod
       
   682 			if (tinyMCE.isIE && window.event != null)
       
   683 				tinyMCE.cancelEvent(window.event);
       
   684 		}
       
   685 	},
       
   686 
       
   687 	execCommand : function(command, user_interface, value) {
       
   688 		var inst = tinyMCE.selectedInstance;
       
   689 
       
   690 		// Default input
       
   691 		user_interface = user_interface ? user_interface : false;
       
   692 		value = value ? value : null;
       
   693 
       
   694 		if (inst)
       
   695 			inst.switchSettings();
       
   696 
       
   697 		switch (command) {
       
   698 			case "Undo":
       
   699 				if (this.getParam('custom_undo_redo_global')) {
       
   700 					if (this.undoIndex > 0) {
       
   701 						tinyMCE.nextUndoRedoAction = 'Undo';
       
   702 						inst = this.undoLevels[--this.undoIndex];
       
   703 						inst.select();
       
   704 
       
   705 						if (!tinyMCE.nextUndoRedoInstanceId)
       
   706 							inst.execCommand('Undo');
       
   707 					}
       
   708 				} else
       
   709 					inst.execCommand('Undo');
       
   710 				return true;
       
   711 
       
   712 			case "Redo":
       
   713 				if (this.getParam('custom_undo_redo_global')) {
       
   714 					if (this.undoIndex <= this.undoLevels.length - 1) {
       
   715 						tinyMCE.nextUndoRedoAction = 'Redo';
       
   716 						inst = this.undoLevels[this.undoIndex++];
       
   717 						inst.select();
       
   718 
       
   719 						if (!tinyMCE.nextUndoRedoInstanceId)
       
   720 							inst.execCommand('Redo');
       
   721 					}
       
   722 				} else
       
   723 					inst.execCommand('Redo');
       
   724 
       
   725 				return true;
       
   726 
       
   727 			case 'mceFocus':
       
   728 				var inst = tinyMCE.getInstanceById(value);
       
   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 				var inst = tinyMCE.getInstanceById(value), pe, te;
       
   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 						te.value = inst.getHTML();
       
   762 						te.style.display = inst.oldTargetDisplay;
       
   763 						tinyMCE.dispatchCallback(inst, 'hide_instance_callback', 'hideInstance', inst);
       
   764 					} else {
       
   765 						pe.style.display = 'block';
       
   766 						te.style.display = 'none';
       
   767 						inst.setHTML(te.value);
       
   768 						inst.useCSS = false;
       
   769 						tinyMCE.dispatchCallback(inst, 'show_instance_callback', 'showInstance', inst);
       
   770 					}
       
   771 				} else
       
   772 					tinyMCE.addMCEControl(tinyMCE._getElementById(value), value);
       
   773 
       
   774 				return;
       
   775 
       
   776 			case "mceResetDesignMode":
       
   777 				// Resets the designmode state of the editors in Gecko
       
   778 				if (!tinyMCE.isIE) {
       
   779 					for (var n in tinyMCE.instances) {
       
   780 						if (!tinyMCE.isInstance(tinyMCE.instances[n]))
       
   781 							continue;
       
   782 
       
   783 						try {
       
   784 							tinyMCE.instances[n].getDoc().designMode = "on";
       
   785 						} catch (e) {
       
   786 							// Ignore any errors
       
   787 						}
       
   788 					}
       
   789 				}
       
   790 
       
   791 				return;
       
   792 		}
       
   793 
       
   794 		if (inst) {
       
   795 			inst.execCommand(command, user_interface, value);
       
   796 		} else if (tinyMCE.settings['focus_alert'])
       
   797 			alert(tinyMCELang['lang_focus_alert']);
       
   798 	},
       
   799 
       
   800 	_createIFrame : function(replace_element, doc, win) {
       
   801 		var iframe, id = replace_element.getAttribute("id");
       
   802 		var aw, ah;
       
   803 
       
   804 		if (typeof(doc) == "undefined")
       
   805 			doc = document;
       
   806 
       
   807 		if (typeof(win) == "undefined")
       
   808 			win = window;
       
   809 
       
   810 		iframe = doc.createElement("iframe");
       
   811 
       
   812 		aw = "" + tinyMCE.settings['area_width'];
       
   813 		ah = "" + tinyMCE.settings['area_height'];
       
   814 
       
   815 		if (aw.indexOf('%') == -1) {
       
   816 			aw = parseInt(aw);
       
   817 			aw = (isNaN(aw) || aw < 0) ? 300 : aw;
       
   818 			aw = aw + "px";
       
   819 		}
       
   820 
       
   821 		if (ah.indexOf('%') == -1) {
       
   822 			ah = parseInt(ah);
       
   823 			ah = (isNaN(ah) || ah < 0) ? 240 : ah;
       
   824 			ah = ah + "px";
       
   825 		}
       
   826 
       
   827 		iframe.setAttribute("id", id);
       
   828 		iframe.setAttribute("name", id);
       
   829 		iframe.setAttribute("class", "mceEditorIframe");
       
   830 		iframe.setAttribute("border", "0");
       
   831 		iframe.setAttribute("frameBorder", "0");
       
   832 		iframe.setAttribute("marginWidth", "0");
       
   833 		iframe.setAttribute("marginHeight", "0");
       
   834 		iframe.setAttribute("leftMargin", "0");
       
   835 		iframe.setAttribute("topMargin", "0");
       
   836 		iframe.setAttribute("width", aw);
       
   837 		iframe.setAttribute("height", ah);
       
   838 		iframe.setAttribute("allowtransparency", "true");
       
   839 		iframe.className = 'mceEditorIframe';
       
   840 
       
   841 		if (tinyMCE.settings["auto_resize"])
       
   842 			iframe.setAttribute("scrolling", "no");
       
   843 
       
   844 		// Must have a src element in MSIE HTTPs breaks aswell as absoute URLs
       
   845 		if (tinyMCE.isRealIE)
       
   846 			iframe.setAttribute("src", this.settings['default_document']);
       
   847 
       
   848 		iframe.style.width = aw;
       
   849 		iframe.style.height = ah;
       
   850 
       
   851 		// Ugly hack for Gecko problem in strict mode
       
   852 		if (tinyMCE.settings.strict_loading_mode)
       
   853 			iframe.style.marginBottom = '-5px';
       
   854 
       
   855 		// MSIE 5.0 issue
       
   856 		if (tinyMCE.isRealIE)
       
   857 			replace_element.outerHTML = iframe.outerHTML;
       
   858 		else
       
   859 			replace_element.parentNode.replaceChild(iframe, replace_element);
       
   860 
       
   861 		if (tinyMCE.isRealIE)
       
   862 			return win.frames[id];
       
   863 		else
       
   864 			return iframe;
       
   865 	},
       
   866 
       
   867 	setupContent : function(editor_id) {
       
   868 		var inst = tinyMCE.instances[editor_id], i;
       
   869 		var doc = inst.getDoc();
       
   870 		var head = doc.getElementsByTagName('head').item(0);
       
   871 		var content = inst.startContent;
       
   872 
       
   873 		// HTML values get XML encoded in strict mode
       
   874 		if (tinyMCE.settings.strict_loading_mode) {
       
   875 			content = content.replace(/&lt;/g, '<');
       
   876 			content = content.replace(/&gt;/g, '>');
       
   877 			content = content.replace(/&quot;/g, '"');
       
   878 			content = content.replace(/&amp;/g, '&');
       
   879 		}
       
   880 
       
   881 		tinyMCE.selectedInstance = inst;
       
   882 		inst.switchSettings();
       
   883 
       
   884 		// Not loaded correctly hit it again, Mozilla bug #997860
       
   885 		if (!tinyMCE.isIE && tinyMCE.getParam("setupcontent_reload", false) && doc.title != "blank_page") {
       
   886 			// This part will remove the designMode status
       
   887 			// Failes first time in Firefox 1.5b2 on Mac
       
   888 			try {doc.location.href = tinyMCE.baseURL + "/blank.htm";} catch (ex) {}
       
   889 			window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 1000);
       
   890 			return;
       
   891 		}
       
   892 
       
   893 		if (!head) {
       
   894 			window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 10);
       
   895 			return;
       
   896 		}
       
   897 
       
   898 		// Import theme specific content CSS the user specific
       
   899 		tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/themes/" + inst.settings['theme'] + "/css/editor_content.css");
       
   900 		tinyMCE.importCSS(inst.getDoc(), inst.settings['content_css']);
       
   901 		tinyMCE.dispatchCallback(inst, 'init_instance_callback', 'initInstance', inst);
       
   902 
       
   903 		// Setup keyboard shortcuts
       
   904 		if (tinyMCE.getParam('custom_undo_redo_keyboard_shortcuts')) {
       
   905 			inst.addShortcut('ctrl', 'z', 'lang_undo_desc', 'Undo');
       
   906 			inst.addShortcut('ctrl', 'y', 'lang_redo_desc', 'Redo');
       
   907 		}
       
   908 
       
   909 		// BlockFormat shortcuts keys
       
   910 		for (i=1; i<=6; i++)
       
   911 			inst.addShortcut('ctrl', '' + i, '', 'FormatBlock', false, '<h' + i + '>');
       
   912 
       
   913 		inst.addShortcut('ctrl', '7', '', 'FormatBlock', false, '<p>');
       
   914 		inst.addShortcut('ctrl', '8', '', 'FormatBlock', false, '<div>');
       
   915 		inst.addShortcut('ctrl', '9', '', 'FormatBlock', false, '<address>');
       
   916 
       
   917 		// Add default shortcuts for gecko
       
   918 		if (tinyMCE.isGecko) {
       
   919 			inst.addShortcut('ctrl', 'b', 'lang_bold_desc', 'Bold');
       
   920 			inst.addShortcut('ctrl', 'i', 'lang_italic_desc', 'Italic');
       
   921 			inst.addShortcut('ctrl', 'u', 'lang_underline_desc', 'Underline');
       
   922 		}
       
   923 
       
   924 		// Setup span styles
       
   925 		if (tinyMCE.getParam("convert_fonts_to_spans"))
       
   926 			inst.getBody().setAttribute('id', 'mceSpanFonts');
       
   927 
       
   928 		if (tinyMCE.settings['nowrap'])
       
   929 			doc.body.style.whiteSpace = "nowrap";
       
   930 
       
   931 		doc.body.dir = this.settings['directionality'];
       
   932 		doc.editorId = editor_id;
       
   933 
       
   934 		// Add on document element in Mozilla
       
   935 		if (!tinyMCE.isIE)
       
   936 			doc.documentElement.editorId = editor_id;
       
   937 
       
   938 		inst.setBaseHREF(tinyMCE.settings['base_href']);
       
   939 
       
   940 		// Replace new line characters to BRs
       
   941 		if (tinyMCE.settings['convert_newlines_to_brs']) {
       
   942 			content = tinyMCE.regexpReplace(content, "\r\n", "<br />", "gi");
       
   943 			content = tinyMCE.regexpReplace(content, "\r", "<br />", "gi");
       
   944 			content = tinyMCE.regexpReplace(content, "\n", "<br />", "gi");
       
   945 		}
       
   946 
       
   947 		// Open closed anchors
       
   948 	//	content = content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');
       
   949 
       
   950 		// Call custom cleanup code
       
   951 		content = tinyMCE.storeAwayURLs(content);
       
   952 		content = tinyMCE._customCleanup(inst, "insert_to_editor", content);
       
   953 
       
   954 		if (tinyMCE.isIE) {
       
   955 			// Ugly!!!
       
   956 			window.setInterval('try{tinyMCE.getCSSClasses(tinyMCE.instances["' + editor_id + '"].getDoc(), "' + editor_id + '");}catch(e){}', 500);
       
   957 
       
   958 			if (tinyMCE.settings["force_br_newlines"])
       
   959 				doc.styleSheets[0].addRule("p", "margin: 0;");
       
   960 
       
   961 			var body = inst.getBody();
       
   962 			body.editorId = editor_id;
       
   963 		}
       
   964 
       
   965 		content = tinyMCE.cleanupHTMLCode(content);
       
   966 
       
   967 		// Fix for bug #958637
       
   968 		if (!tinyMCE.isIE) {
       
   969 			var contentElement = inst.getDoc().createElement("body");
       
   970 			var doc = inst.getDoc();
       
   971 
       
   972 			contentElement.innerHTML = content;
       
   973 
       
   974 			// Remove weridness!
       
   975 			if (tinyMCE.isGecko && tinyMCE.settings['remove_lt_gt'])
       
   976 				content = content.replace(new RegExp('&lt;&gt;', 'g'), "");
       
   977 
       
   978 			if (tinyMCE.settings['cleanup_on_startup'])
       
   979 				tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, doc, this.settings, contentElement));
       
   980 			else
       
   981 				tinyMCE.setInnerHTML(inst.getBody(), content);
       
   982 
       
   983 			tinyMCE.convertAllRelativeURLs(inst.getBody());
       
   984 		} else {
       
   985 			if (tinyMCE.settings['cleanup_on_startup']) {
       
   986 				tinyMCE._setHTML(inst.getDoc(), content);
       
   987 
       
   988 				// Produces permission denied error in MSIE 5.5
       
   989 				eval('try {tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, inst.contentDocument, this.settings, inst.getBody()));} catch(e) {}');
       
   990 			} else
       
   991 				tinyMCE._setHTML(inst.getDoc(), content);
       
   992 		}
       
   993 
       
   994 		// Fix for bug #957681
       
   995 		//inst.getDoc().designMode = inst.getDoc().designMode;
       
   996 
       
   997 		tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings['visual'], inst);
       
   998 		tinyMCE.dispatchCallback(inst, 'setupcontent_callback', 'setupContent', editor_id, inst.getBody(), inst.getDoc());
       
   999 
       
  1000 		// Re-add design mode on mozilla
       
  1001 		if (!tinyMCE.isIE)
       
  1002 			tinyMCE.addEventHandlers(inst);
       
  1003 
       
  1004 		// Add blur handler
       
  1005 		if (tinyMCE.isIE) {
       
  1006 			tinyMCE.addEvent(inst.getBody(), "blur", TinyMCE_Engine.prototype._eventPatch);
       
  1007 			tinyMCE.addEvent(inst.getBody(), "beforedeactivate", TinyMCE_Engine.prototype._eventPatch); // Bug #1439953
       
  1008 
       
  1009 			// Workaround for drag drop/copy paste base href bug
       
  1010 			if (!tinyMCE.isOpera) {
       
  1011 				tinyMCE.addEvent(doc.body, "mousemove", TinyMCE_Engine.prototype.onMouseMove);
       
  1012 				tinyMCE.addEvent(doc.body, "beforepaste", TinyMCE_Engine.prototype._eventPatch);
       
  1013 				tinyMCE.addEvent(doc.body, "drop", TinyMCE_Engine.prototype._eventPatch);
       
  1014 			}
       
  1015 		}
       
  1016 
       
  1017 		// Trigger node change, this call locks buttons for tables and so forth
       
  1018 		inst.select();
       
  1019 		tinyMCE.selectedElement = inst.contentWindow.document.body;
       
  1020 
       
  1021 		// Call custom DOM cleanup
       
  1022 		tinyMCE._customCleanup(inst, "insert_to_editor_dom", inst.getBody());
       
  1023 		tinyMCE._customCleanup(inst, "setup_content_dom", inst.getBody());
       
  1024 		tinyMCE._setEventsEnabled(inst.getBody(), false);
       
  1025 		tinyMCE.cleanupAnchors(inst.getDoc());
       
  1026 
       
  1027 		if (tinyMCE.getParam("convert_fonts_to_spans"))
       
  1028 			tinyMCE.convertSpansToFonts(inst.getDoc());
       
  1029 
       
  1030 		inst.startContent = tinyMCE.trim(inst.getBody().innerHTML);
       
  1031 		inst.undoRedo.add({ content : inst.startContent });
       
  1032 
       
  1033 		// Cleanup any mess left from storyAwayURLs
       
  1034 		if (tinyMCE.isGecko) {
       
  1035 			// Remove mce_src from textnodes and comments
       
  1036 			tinyMCE.selectNodes(inst.getBody(), function(n) {
       
  1037 				if (n.nodeType == 3 || n.nodeType == 8)
       
  1038 					n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");
       
  1039 
       
  1040 				return false;
       
  1041 			});
       
  1042 		}
       
  1043 
       
  1044 		// Remove Gecko spellchecking
       
  1045 		if (tinyMCE.isGecko)
       
  1046 			inst.getBody().spellcheck = tinyMCE.getParam("gecko_spellcheck");
       
  1047 
       
  1048 		// Cleanup any mess left from storyAwayURLs
       
  1049 		tinyMCE._removeInternal(inst.getBody());
       
  1050 
       
  1051 		inst.select();
       
  1052 		tinyMCE.triggerNodeChange(false, true);
       
  1053 	},
       
  1054 
       
  1055 	storeAwayURLs : function(s) {
       
  1056 		// Remove all mce_src, mce_href and replace them with new ones
       
  1057 		// s = s.replace(new RegExp('mce_src\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');
       
  1058 		// s = s.replace(new RegExp('mce_href\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');
       
  1059 
       
  1060 		if (!s.match(/(mce_src|mce_href)/gi, s)) {
       
  1061 			s = s.replace(new RegExp('src\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'src="$1" mce_src="$1"');
       
  1062 			s = s.replace(new RegExp('href\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'href="$1" mce_href="$1"');
       
  1063 		}
       
  1064 
       
  1065 		return s;
       
  1066 	},
       
  1067 
       
  1068 	_removeInternal : function(n) {
       
  1069 		if (tinyMCE.isGecko) {
       
  1070 			// Remove mce_src from textnodes and comments
       
  1071 			tinyMCE.selectNodes(n, function(n) {
       
  1072 				if (n.nodeType == 3 || n.nodeType == 8)
       
  1073 					n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");
       
  1074 
       
  1075 				return false;
       
  1076 			});
       
  1077 		}
       
  1078 	},
       
  1079 
       
  1080 	removeTinyMCEFormElements : function(form_obj) {
       
  1081 		var i, elementId;
       
  1082 
       
  1083 		// Skip form element removal
       
  1084 		if (!tinyMCE.getParam('hide_selects_on_submit'))
       
  1085 			return;
       
  1086 
       
  1087 		// Check if form is valid
       
  1088 		if (typeof(form_obj) == "undefined" || form_obj == null)
       
  1089 			return;
       
  1090 
       
  1091 		// If not a form, find the form
       
  1092 		if (form_obj.nodeName != "FORM") {
       
  1093 			if (form_obj.form)
       
  1094 				form_obj = form_obj.form;
       
  1095 			else
       
  1096 				form_obj = tinyMCE.getParentElement(form_obj, "form");
       
  1097 		}
       
  1098 
       
  1099 		// Still nothing
       
  1100 		if (form_obj == null)
       
  1101 			return;
       
  1102 
       
  1103 		// Disable all UI form elements that TinyMCE created
       
  1104 		for (i=0; i<form_obj.elements.length; i++) {
       
  1105 			elementId = form_obj.elements[i].name ? form_obj.elements[i].name : form_obj.elements[i].id;
       
  1106 
       
  1107 			if (elementId.indexOf('mce_editor_') == 0)
       
  1108 				form_obj.elements[i].disabled = true;
       
  1109 		}
       
  1110 	},
       
  1111 
       
  1112 	handleEvent : function(e) {
       
  1113 		var inst = tinyMCE.selectedInstance;
       
  1114 
       
  1115 		// Remove odd, error
       
  1116 		if (typeof(tinyMCE) == "undefined")
       
  1117 			return true;
       
  1118 
       
  1119 		//tinyMCE.debug(e.type + " " + e.target.nodeName + " " + (e.relatedTarget ? e.relatedTarget.nodeName : ""));
       
  1120 
       
  1121 		if (tinyMCE.executeCallback(tinyMCE.selectedInstance, 'handle_event_callback', 'handleEvent', e))
       
  1122 			return false;
       
  1123 
       
  1124 		switch (e.type) {
       
  1125 			case "beforedeactivate": // Was added due to bug #1439953
       
  1126 			case "blur":
       
  1127 				if (tinyMCE.selectedInstance)
       
  1128 					tinyMCE.selectedInstance.execCommand('mceEndTyping');
       
  1129 
       
  1130 				tinyMCE.hideMenus();
       
  1131 
       
  1132 				return;
       
  1133 
       
  1134 			// Workaround for drag drop/copy paste base href bug
       
  1135 			case "drop":
       
  1136 			case "beforepaste":
       
  1137 				if (tinyMCE.selectedInstance)
       
  1138 					tinyMCE.selectedInstance.setBaseHREF(null);
       
  1139 
       
  1140 				// Fixes odd MSIE bug where drag/droping elements in a iframe with height 100% breaks
       
  1141 				// This logic forces the width/height to be in pixels while the user is drag/dropping
       
  1142 				if (tinyMCE.isRealIE) {
       
  1143 					var ife = tinyMCE.selectedInstance.iframeElement;
       
  1144 
       
  1145 					/*if (ife.style.width.indexOf('%') != -1) {
       
  1146 						ife._oldWidth = ife.width.height;
       
  1147 						ife.style.width = ife.clientWidth;
       
  1148 					}*/
       
  1149 
       
  1150 					if (ife.style.height.indexOf('%') != -1) {
       
  1151 						ife._oldHeight = ife.style.height;
       
  1152 						ife.style.height = ife.clientHeight;
       
  1153 					}
       
  1154 				}
       
  1155 
       
  1156 				window.setTimeout("tinyMCE.selectedInstance.setBaseHREF(tinyMCE.settings['base_href']);tinyMCE._resetIframeHeight();", 1);
       
  1157 				return;
       
  1158 
       
  1159 			case "submit":
       
  1160 				tinyMCE.removeTinyMCEFormElements(tinyMCE.isMSIE ? window.event.srcElement : e.target);
       
  1161 				tinyMCE.triggerSave();
       
  1162 				tinyMCE.isNotDirty = true;
       
  1163 				return;
       
  1164 
       
  1165 			case "reset":
       
  1166 				var formObj = tinyMCE.isIE ? window.event.srcElement : e.target;
       
  1167 
       
  1168 				for (var i=0; i<document.forms.length; i++) {
       
  1169 					if (document.forms[i] == formObj)
       
  1170 						window.setTimeout('tinyMCE.resetForm(' + i + ');', 10);
       
  1171 				}
       
  1172 
       
  1173 				return;
       
  1174 
       
  1175 			case "keypress":
       
  1176 				if (inst && inst.handleShortcut(e))
       
  1177 					return false;
       
  1178 
       
  1179 				if (e.target.editorId) {
       
  1180 					tinyMCE.instances[e.target.editorId].select();
       
  1181 				} else {
       
  1182 					if (e.target.ownerDocument.editorId)
       
  1183 						tinyMCE.instances[e.target.ownerDocument.editorId].select();
       
  1184 				}
       
  1185 
       
  1186 				if (tinyMCE.selectedInstance)
       
  1187 					tinyMCE.selectedInstance.switchSettings();
       
  1188 
       
  1189 				// Insert P element
       
  1190 				if ((tinyMCE.isGecko || tinyMCE.isOpera || tinyMCE.isSafari) && tinyMCE.settings['force_p_newlines'] && e.keyCode == 13 && !e.shiftKey) {
       
  1191 					// Insert P element instead of BR
       
  1192 					if (TinyMCE_ForceParagraphs._insertPara(tinyMCE.selectedInstance, e)) {
       
  1193 						// Cancel event
       
  1194 						tinyMCE.execCommand("mceAddUndoLevel");
       
  1195 						return tinyMCE.cancelEvent(e);
       
  1196 					}
       
  1197 				}
       
  1198 
       
  1199 				// Handle backspace
       
  1200 				if ((tinyMCE.isGecko && !tinyMCE.isSafari) && tinyMCE.settings['force_p_newlines'] && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) {
       
  1201 					// Insert P element instead of BR
       
  1202 					if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) {
       
  1203 						// Cancel event
       
  1204 						tinyMCE.execCommand("mceAddUndoLevel");
       
  1205 						return tinyMCE.cancelEvent(e);
       
  1206 					}
       
  1207 				}
       
  1208 
       
  1209 				// Return key pressed
       
  1210 				if (tinyMCE.isIE && tinyMCE.settings['force_br_newlines'] && e.keyCode == 13) {
       
  1211 					if (e.target.editorId)
       
  1212 						tinyMCE.instances[e.target.editorId].select();
       
  1213 
       
  1214 					if (tinyMCE.selectedInstance) {
       
  1215 						var sel = tinyMCE.selectedInstance.getDoc().selection;
       
  1216 						var rng = sel.createRange();
       
  1217 
       
  1218 						if (tinyMCE.getParentElement(rng.parentElement(), "li") != null)
       
  1219 							return false;
       
  1220 
       
  1221 						// Cancel event
       
  1222 						e.returnValue = false;
       
  1223 						e.cancelBubble = true;
       
  1224 
       
  1225 						// Insert BR element
       
  1226 						rng.pasteHTML("<br />");
       
  1227 						rng.collapse(false);
       
  1228 						rng.select();
       
  1229 
       
  1230 						tinyMCE.execCommand("mceAddUndoLevel");
       
  1231 						tinyMCE.triggerNodeChange(false);
       
  1232 						return false;
       
  1233 					}
       
  1234 				}
       
  1235 
       
  1236 				// Backspace or delete
       
  1237 				if (e.keyCode == 8 || e.keyCode == 46) {
       
  1238 					tinyMCE.selectedElement = e.target;
       
  1239 					tinyMCE.linkElement = tinyMCE.getParentElement(e.target, "a");
       
  1240 					tinyMCE.imgElement = tinyMCE.getParentElement(e.target, "img");
       
  1241 					tinyMCE.triggerNodeChange(false);
       
  1242 				}
       
  1243 
       
  1244 				return false;
       
  1245 			break;
       
  1246 
       
  1247 			case "keyup":
       
  1248 			case "keydown":
       
  1249 				tinyMCE.hideMenus();
       
  1250 				tinyMCE.hasMouseMoved = false;
       
  1251 
       
  1252 				if (inst && inst.handleShortcut(e))
       
  1253 					return false;
       
  1254 
       
  1255 				if (e.target.editorId)
       
  1256 					tinyMCE.instances[e.target.editorId].select();
       
  1257 
       
  1258 				if (tinyMCE.selectedInstance)
       
  1259 					tinyMCE.selectedInstance.switchSettings();
       
  1260 
       
  1261 				var inst = tinyMCE.selectedInstance;
       
  1262 
       
  1263 				// Handle backspace
       
  1264 				if (tinyMCE.isGecko && tinyMCE.settings['force_p_newlines'] && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) {
       
  1265 					// Insert P element instead of BR
       
  1266 					if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) {
       
  1267 						// Cancel event
       
  1268 						tinyMCE.execCommand("mceAddUndoLevel");
       
  1269 						e.preventDefault();
       
  1270 						return false;
       
  1271 					}
       
  1272 				}
       
  1273 
       
  1274 				tinyMCE.selectedElement = null;
       
  1275 				tinyMCE.selectedNode = null;
       
  1276 				var elm = tinyMCE.selectedInstance.getFocusElement();
       
  1277 				tinyMCE.linkElement = tinyMCE.getParentElement(elm, "a");
       
  1278 				tinyMCE.imgElement = tinyMCE.getParentElement(elm, "img");
       
  1279 				tinyMCE.selectedElement = elm;
       
  1280 
       
  1281 				// Update visualaids on tabs
       
  1282 				if (tinyMCE.isGecko && e.type == "keyup" && e.keyCode == 9)
       
  1283 					tinyMCE.handleVisualAid(tinyMCE.selectedInstance.getBody(), true, tinyMCE.settings['visual'], tinyMCE.selectedInstance);
       
  1284 
       
  1285 				// Fix empty elements on return/enter, check where enter occured
       
  1286 				if (tinyMCE.isIE && e.type == "keydown" && e.keyCode == 13)
       
  1287 					tinyMCE.enterKeyElement = tinyMCE.selectedInstance.getFocusElement();
       
  1288 
       
  1289 				// Fix empty elements on return/enter
       
  1290 				if (tinyMCE.isIE && e.type == "keyup" && e.keyCode == 13) {
       
  1291 					var elm = tinyMCE.enterKeyElement;
       
  1292 					if (elm) {
       
  1293 						var re = new RegExp('^HR|IMG|BR$','g'); // Skip these
       
  1294 						var dre = new RegExp('^H[1-6]$','g'); // Add double on these
       
  1295 
       
  1296 						if (!elm.hasChildNodes() && !re.test(elm.nodeName)) {
       
  1297 							if (dre.test(elm.nodeName))
       
  1298 								elm.innerHTML = "&nbsp;&nbsp;";
       
  1299 							else
       
  1300 								elm.innerHTML = "&nbsp;";
       
  1301 						}
       
  1302 					}
       
  1303 				}
       
  1304 
       
  1305 				// Check if it's a position key
       
  1306 				var keys = tinyMCE.posKeyCodes;
       
  1307 				var posKey = false;
       
  1308 				for (var i=0; i<keys.length; i++) {
       
  1309 					if (keys[i] == e.keyCode) {
       
  1310 						posKey = true;
       
  1311 						break;
       
  1312 					}
       
  1313 				}
       
  1314 
       
  1315 				// MSIE custom key handling
       
  1316 				if (tinyMCE.isIE && tinyMCE.settings['custom_undo_redo']) {
       
  1317 					var keys = new Array(8,46); // Backspace,Delete
       
  1318 
       
  1319 					for (var i=0; i<keys.length; i++) {
       
  1320 						if (keys[i] == e.keyCode) {
       
  1321 							if (e.type == "keyup")
       
  1322 								tinyMCE.triggerNodeChange(false);
       
  1323 						}
       
  1324 					}
       
  1325 				}
       
  1326 
       
  1327 				// If Ctrl key
       
  1328 				if (e.keyCode == 17)
       
  1329 					return true;
       
  1330 
       
  1331 				// Handle Undo/Redo when typing content
       
  1332 
       
  1333 				if (tinyMCE.isGecko) {
       
  1334 					// Start typing (not a position key or ctrl key, but ctrl+x and ctrl+p is ok)
       
  1335 					if (!posKey && e.type == "keyup" && !e.ctrlKey || (e.ctrlKey && (e.keyCode == 86 || e.keyCode == 88)))
       
  1336 						tinyMCE.execCommand("mceStartTyping");
       
  1337 				} else {
       
  1338 					// IE seems to be working better with this setting
       
  1339 					if (!posKey && e.type == "keyup")
       
  1340 						tinyMCE.execCommand("mceStartTyping");
       
  1341 				}
       
  1342 
       
  1343 				// Store undo bookmark
       
  1344 				if (e.type == "keydown" && (posKey || e.ctrlKey) && inst)
       
  1345 					inst.undoBookmark = inst.selection.getBookmark();
       
  1346 
       
  1347 				// End typing (position key) or some Ctrl event
       
  1348 				if (e.type == "keyup" && (posKey || e.ctrlKey))
       
  1349 					tinyMCE.execCommand("mceEndTyping");
       
  1350 
       
  1351 				if (posKey && e.type == "keyup")
       
  1352 					tinyMCE.triggerNodeChange(false);
       
  1353 
       
  1354 				if (tinyMCE.isIE && e.ctrlKey)
       
  1355 					window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
       
  1356 			break;
       
  1357 
       
  1358 			case "mousedown":
       
  1359 			case "mouseup":
       
  1360 			case "click":
       
  1361 			case "dblclick":
       
  1362 			case "focus":
       
  1363 				tinyMCE.hideMenus();
       
  1364 
       
  1365 				if (tinyMCE.selectedInstance) {
       
  1366 					tinyMCE.selectedInstance.switchSettings();
       
  1367 					tinyMCE.selectedInstance.isFocused = true;
       
  1368 				}
       
  1369 
       
  1370 				// Check instance event trigged on
       
  1371 				var targetBody = tinyMCE.getParentElement(e.target, "html");
       
  1372 				for (var instanceName in tinyMCE.instances) {
       
  1373 					if (!tinyMCE.isInstance(tinyMCE.instances[instanceName]))
       
  1374 						continue;
       
  1375 
       
  1376 					var inst = tinyMCE.instances[instanceName];
       
  1377 
       
  1378 					// Reset design mode if lost (on everything just in case)
       
  1379 					inst.autoResetDesignMode();
       
  1380 
       
  1381 					// Use HTML element since users might click outside of body element
       
  1382 					if (inst.getBody().parentNode == targetBody) {
       
  1383 						inst.select();
       
  1384 						tinyMCE.selectedElement = e.target;
       
  1385 						tinyMCE.linkElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "a");
       
  1386 						tinyMCE.imgElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "img");
       
  1387 						break;
       
  1388 					}
       
  1389 				}
       
  1390 
       
  1391 				// Add first bookmark location
       
  1392 				if (!tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark && (e.type == "mouseup" || e.type == "dblclick"))
       
  1393 					tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark = tinyMCE.selectedInstance.selection.getBookmark();
       
  1394 
       
  1395 				// Reset selected node
       
  1396 				if (e.type != "focus")
       
  1397 					tinyMCE.selectedNode = null;
       
  1398 
       
  1399 				tinyMCE.triggerNodeChange(false);
       
  1400 				tinyMCE.execCommand("mceEndTyping");
       
  1401 
       
  1402 				if (e.type == "mouseup")
       
  1403 					tinyMCE.execCommand("mceAddUndoLevel");
       
  1404 
       
  1405 				// Just in case
       
  1406 				if (!tinyMCE.selectedInstance && e.target.editorId)
       
  1407 					tinyMCE.instances[e.target.editorId].select();
       
  1408 
       
  1409 				return false;
       
  1410 			break;
       
  1411 		}
       
  1412 	},
       
  1413 
       
  1414 	getButtonHTML : function(id, lang, img, cmd, ui, val) {
       
  1415 		var h = '', m, x, io = '';
       
  1416 
       
  1417 		cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';
       
  1418 
       
  1419 		if (typeof(ui) != "undefined" && ui != null)
       
  1420 			cmd += ',' + ui;
       
  1421 
       
  1422 		if (typeof(val) != "undefined" && val != null)
       
  1423 			cmd += ",'" + val + "'";
       
  1424 
       
  1425 		cmd += ');';
       
  1426 
       
  1427 		// Patch for IE7 bug with hover out not restoring correctly
       
  1428 		if (tinyMCE.isRealIE)
       
  1429 			io = 'onmouseover="tinyMCE.lastHover = this;"';
       
  1430 
       
  1431 		// Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled
       
  1432 		if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isIE || tinyMCE.isOpera) && (m = this.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {
       
  1433 			// Tiled button
       
  1434 			x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);
       
  1435 			h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceTiledButton mceButtonNormal" target="_self">';
       
  1436 			h += '<img src="{$themeurl}/images/spacer.gif" style="background-position: ' + x + 'px 0" title="{$' + lang + '}" />';
       
  1437 			h += '</a>';
       
  1438 		} else {
       
  1439 			// Normal button
       
  1440 			h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceButtonNormal" target="_self">';
       
  1441 			h += '<img src="' + img + '" title="{$' + lang + '}" />';
       
  1442 			h += '</a>';
       
  1443 		}
       
  1444 
       
  1445 		return h;
       
  1446 	},
       
  1447 
       
  1448 	getMenuButtonHTML : function(id, lang, img, mcmd, cmd, ui, val) {
       
  1449 		var h = '', m, x;
       
  1450 
       
  1451 		mcmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + mcmd + '\');';
       
  1452 		cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';
       
  1453 
       
  1454 		if (typeof(ui) != "undefined" && ui != null)
       
  1455 			cmd += ',' + ui;
       
  1456 
       
  1457 		if (typeof(val) != "undefined" && val != null)
       
  1458 			cmd += ",'" + val + "'";
       
  1459 
       
  1460 		cmd += ');';
       
  1461 
       
  1462 		// Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled
       
  1463 		if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isIE || tinyMCE.isOpera) && (m = tinyMCE.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {
       
  1464 			x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);
       
  1465 
       
  1466 			if (tinyMCE.isRealIE)
       
  1467 				h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';
       
  1468 			else
       
  1469 				h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton">';
       
  1470 
       
  1471 			h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceTiledButton mceMenuButtonNormal" target="_self">';
       
  1472 			h += '<img src="{$themeurl}/images/spacer.gif" style="width: 20px; height: 20px; background-position: ' + x + 'px 0" title="{$' + lang + '}" /></a>';
       
  1473 			h += '<a href="javascript:' + mcmd + '" onclick="' + mcmd + 'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';
       
  1474 			h += '</a></span>';
       
  1475 		} else {
       
  1476 			if (tinyMCE.isRealIE)
       
  1477 				h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';
       
  1478 			else
       
  1479 				h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton">';
       
  1480 
       
  1481 			h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceMenuButtonNormal" target="_self">';
       
  1482 			h += '<img src="' + img + '" title="{$' + lang + '}" /></a>';
       
  1483 			h += '<a href="javascript:' + mcmd + '" onclick="' + mcmd + 'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';
       
  1484 			h += '</a></span>';
       
  1485 		}
       
  1486 
       
  1487 		return h;
       
  1488 	},
       
  1489 
       
  1490 	_menuButtonEvent : function(e, o) {
       
  1491 		if (o.className == 'mceMenuButtonFocus')
       
  1492 			return;
       
  1493 
       
  1494 		if (e == 'over')
       
  1495 			o.className = o.className + ' mceMenuHover';
       
  1496 		else
       
  1497 			o.className = o.className.replace(/\s.*$/, '');
       
  1498 	},
       
  1499 
       
  1500 	addButtonMap : function(m) {
       
  1501 		var i, a = m.replace(/\s+/, '').split(',');
       
  1502 
       
  1503 		for (i=0; i<a.length; i++)
       
  1504 			this.buttonMap[a[i]] = i;
       
  1505 	},
       
  1506 
       
  1507 	submitPatch : function() {
       
  1508 		tinyMCE.removeTinyMCEFormElements(this);
       
  1509 		tinyMCE.triggerSave();
       
  1510 		tinyMCE.isNotDirty = true;
       
  1511 		this.mceOldSubmit();
       
  1512 	},
       
  1513 
       
  1514 	onLoad : function() {
       
  1515 		var r;
       
  1516 
       
  1517 		// Wait for everything to be loaded first
       
  1518 		if (tinyMCE.settings.strict_loading_mode && this.loadingIndex != -1) {
       
  1519 			window.setTimeout('tinyMCE.onLoad();', 1);
       
  1520 			return;
       
  1521 		}
       
  1522 
       
  1523 		if (tinyMCE.isRealIE && window.event.type == "readystatechange" && document.readyState != "complete")
       
  1524 			return true;
       
  1525 
       
  1526 		if (tinyMCE.isLoaded)
       
  1527 			return true;
       
  1528 
       
  1529 		tinyMCE.isLoaded = true;
       
  1530 
       
  1531 		// IE produces JS error if TinyMCE is placed in a frame
       
  1532 		// It seems to have something to do with the selection not beeing
       
  1533 		// correctly initialized in IE so this hack solves the problem
       
  1534 		if (tinyMCE.isRealIE && document.body) {
       
  1535 			r = document.body.createTextRange();
       
  1536 			r.collapse(true);
       
  1537 			r.select();
       
  1538 		}
       
  1539 
       
  1540 		tinyMCE.dispatchCallback(null, 'onpageload', 'onPageLoad');
       
  1541 
       
  1542 		for (var c=0; c<tinyMCE.configs.length; c++) {
       
  1543 			tinyMCE.settings = tinyMCE.configs[c];
       
  1544 
       
  1545 			var selector = tinyMCE.getParam("editor_selector");
       
  1546 			var deselector = tinyMCE.getParam("editor_deselector");
       
  1547 			var elementRefAr = new Array();
       
  1548 
       
  1549 			// Add submit triggers
       
  1550 			if (document.forms && tinyMCE.settings['add_form_submit_trigger'] && !tinyMCE.submitTriggers) {
       
  1551 				for (var i=0; i<document.forms.length; i++) {
       
  1552 					var form = document.forms[i];
       
  1553 
       
  1554 					tinyMCE.addEvent(form, "submit", TinyMCE_Engine.prototype.handleEvent);
       
  1555 					tinyMCE.addEvent(form, "reset", TinyMCE_Engine.prototype.handleEvent);
       
  1556 					tinyMCE.submitTriggers = true; // Do it only once
       
  1557 
       
  1558 					// Patch the form.submit function
       
  1559 					if (tinyMCE.settings['submit_patch']) {
       
  1560 						try {
       
  1561 							form.mceOldSubmit = form.submit;
       
  1562 							form.submit = TinyMCE_Engine.prototype.submitPatch;
       
  1563 						} catch (e) {
       
  1564 							// Do nothing
       
  1565 						}
       
  1566 					}
       
  1567 				}
       
  1568 			}
       
  1569 
       
  1570 			// Add editor instances based on mode
       
  1571 			var mode = tinyMCE.settings['mode'];
       
  1572 			switch (mode) {
       
  1573 				case "exact":
       
  1574 					var elements = tinyMCE.getParam('elements', '', true, ',');
       
  1575 
       
  1576 					for (var i=0; i<elements.length; i++) {
       
  1577 						var element = tinyMCE._getElementById(elements[i]);
       
  1578 						var trigger = element ? element.getAttribute(tinyMCE.settings['textarea_trigger']) : "";
       
  1579 
       
  1580 						if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(element, "class")))
       
  1581 							continue;
       
  1582 
       
  1583 						if (trigger == "false")
       
  1584 							continue;
       
  1585 
       
  1586 						if ((tinyMCE.settings['ask'] || tinyMCE.settings['convert_on_click']) && element) {
       
  1587 							elementRefAr[elementRefAr.length] = element;
       
  1588 							continue;
       
  1589 						}
       
  1590 
       
  1591 						if (element)
       
  1592 							tinyMCE.addMCEControl(element, elements[i]);
       
  1593 						else if (tinyMCE.settings['debug'])
       
  1594 							alert("Error: Could not find element by id or name: " + elements[i]);
       
  1595 					}
       
  1596 				break;
       
  1597 
       
  1598 				case "specific_textareas":
       
  1599 				case "textareas":
       
  1600 					var nodeList = document.getElementsByTagName("textarea");
       
  1601 
       
  1602 					for (var i=0; i<nodeList.length; i++) {
       
  1603 						var elm = nodeList.item(i);
       
  1604 						var trigger = elm.getAttribute(tinyMCE.settings['textarea_trigger']);
       
  1605 
       
  1606 						if (selector != '' && !new RegExp('\\b' + selector + '\\b').test(tinyMCE.getAttrib(elm, "class")))
       
  1607 							continue;
       
  1608 
       
  1609 						if (selector != '')
       
  1610 							trigger = selector != "" ? "true" : "";
       
  1611 
       
  1612 						if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(elm, "class")))
       
  1613 							continue;
       
  1614 
       
  1615 						if ((mode == "specific_textareas" && trigger == "true") || (mode == "textareas" && trigger != "false"))
       
  1616 							elementRefAr[elementRefAr.length] = elm;
       
  1617 					}
       
  1618 				break;
       
  1619 			}
       
  1620 
       
  1621 			for (var i=0; i<elementRefAr.length; i++) {
       
  1622 				var element = elementRefAr[i];
       
  1623 				var elementId = element.name ? element.name : element.id;
       
  1624 
       
  1625 				if (tinyMCE.settings['ask'] || tinyMCE.settings['convert_on_click']) {
       
  1626 					// Focus breaks in Mozilla
       
  1627 					if (tinyMCE.isGecko) {
       
  1628 						var settings = tinyMCE.settings;
       
  1629 
       
  1630 						tinyMCE.addEvent(element, "focus", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
       
  1631 
       
  1632 						if (element.nodeName != "TEXTAREA" && element.nodeName != "INPUT")
       
  1633 							tinyMCE.addEvent(element, "click", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
       
  1634 						// tinyMCE.addEvent(element, "mouseover", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
       
  1635 					} else {
       
  1636 						var settings = tinyMCE.settings;
       
  1637 
       
  1638 						tinyMCE.addEvent(element, "focus", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
       
  1639 						tinyMCE.addEvent(element, "click", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
       
  1640 						// tinyMCE.addEvent(element, "mouseenter", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
       
  1641 					}
       
  1642 				} else
       
  1643 					tinyMCE.addMCEControl(element, elementId);
       
  1644 			}
       
  1645 
       
  1646 			// Handle auto focus
       
  1647 			if (tinyMCE.settings['auto_focus']) {
       
  1648 				window.setTimeout(function () {
       
  1649 					var inst = tinyMCE.getInstanceById(tinyMCE.settings['auto_focus']);
       
  1650 					inst.selection.selectNode(inst.getBody(), true, true);
       
  1651 					inst.contentWindow.focus();
       
  1652 				}, 100);
       
  1653 			}
       
  1654 
       
  1655 			tinyMCE.dispatchCallback(null, 'oninit', 'onInit');
       
  1656 		}
       
  1657 	},
       
  1658 
       
  1659 	isInstance : function(o) {
       
  1660 		return o != null && typeof(o) == "object" && o.isTinyMCE_Control;
       
  1661 	},
       
  1662 
       
  1663 	getParam : function(name, default_value, strip_whitespace, split_chr) {
       
  1664 		var value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name];
       
  1665 
       
  1666 		// Fix bool values
       
  1667 		if (value == "true" || value == "false")
       
  1668 			return (value == "true");
       
  1669 
       
  1670 		if (strip_whitespace)
       
  1671 			value = tinyMCE.regexpReplace(value, "[ \t\r\n]", "") + '';
       
  1672 
       
  1673 		if (typeof(split_chr) != "undefined" && split_chr != null) {
       
  1674 			value = value.split(split_chr);
       
  1675 			var outArray = new Array();
       
  1676 
       
  1677 			for (var i=0; i<value.length; i++) {
       
  1678 				if (value[i] && value[i] != "")
       
  1679 					outArray[outArray.length] = value[i];
       
  1680 			}
       
  1681 
       
  1682 			value = outArray;
       
  1683 		}
       
  1684 
       
  1685 		return value;
       
  1686 	},
       
  1687 
       
  1688 	getLang : function(name, default_value, parse_entities, va) {
       
  1689 		var v = (typeof(tinyMCELang[name]) == "undefined") ? default_value : tinyMCELang[name], n;
       
  1690 
       
  1691 		if (parse_entities)
       
  1692 			v = tinyMCE.entityDecode(v);
       
  1693 
       
  1694 		if (va) {
       
  1695 			for (n in va)
       
  1696 				v = this.replaceVar(v, n, va[n]);
       
  1697 		}
       
  1698 
       
  1699 		return v;
       
  1700 	},
       
  1701 
       
  1702 	entityDecode : function(s) {
       
  1703 		var e = document.createElement("div");
       
  1704 
       
  1705 		e.innerHTML = s;
       
  1706 
       
  1707 		return e.firstChild.nodeValue;
       
  1708 	},
       
  1709 
       
  1710 	addToLang : function(prefix, ar) {
       
  1711 		for (var key in ar) {
       
  1712 			if (typeof(ar[key]) == 'function')
       
  1713 				continue;
       
  1714 
       
  1715 			tinyMCELang[(key.indexOf('lang_') == -1 ? 'lang_' : '') + (prefix != '' ? (prefix + "_") : '') + key] = ar[key];
       
  1716 		}
       
  1717 
       
  1718 		this.loadNextScript();
       
  1719 
       
  1720 	//	for (var key in ar)
       
  1721 	//		tinyMCELang[(key.indexOf('lang_') == -1 ? 'lang_' : '') + (prefix != '' ? (prefix + "_") : '') + key] = "|" + ar[key] + "|";
       
  1722 	},
       
  1723 
       
  1724 	triggerNodeChange : function(focus, setup_content) {
       
  1725 		var elm, inst, editorId, undoIndex = -1, undoLevels = -1, doc, anySelection = false, st;
       
  1726 
       
  1727 		if (tinyMCE.selectedInstance) {
       
  1728 			inst = tinyMCE.selectedInstance;
       
  1729 			elm = (typeof(setup_content) != "undefined" && setup_content) ? tinyMCE.selectedElement : inst.getFocusElement();
       
  1730 
       
  1731 /*			if (elm == inst.lastTriggerEl)
       
  1732 				return;
       
  1733 
       
  1734 			inst.lastTriggerEl = elm;*/
       
  1735 
       
  1736 			editorId = inst.editorId;
       
  1737 			st = inst.selection.getSelectedText();
       
  1738 
       
  1739 			if (tinyMCE.settings.auto_resize)
       
  1740 				inst.resizeToContent();
       
  1741 
       
  1742 			if (setup_content && tinyMCE.isGecko && inst.isHidden())
       
  1743 				elm = inst.getBody();
       
  1744 
       
  1745 			inst.switchSettings();
       
  1746 
       
  1747 			if (tinyMCE.selectedElement)
       
  1748 				anySelection = (tinyMCE.selectedElement.nodeName.toLowerCase() == "img") || (st && st.length > 0);
       
  1749 
       
  1750 			if (tinyMCE.settings['custom_undo_redo']) {
       
  1751 				undoIndex = inst.undoRedo.undoIndex;
       
  1752 				undoLevels = inst.undoRedo.undoLevels.length;
       
  1753 			}
       
  1754 
       
  1755 			tinyMCE.dispatchCallback(inst, 'handle_node_change_callback', 'handleNodeChange', editorId, elm, undoIndex, undoLevels, inst.visualAid, anySelection, setup_content);
       
  1756 		}
       
  1757 
       
  1758 		if (this.selectedInstance && (typeof(focus) == "undefined" || focus))
       
  1759 			this.selectedInstance.contentWindow.focus();
       
  1760 	},
       
  1761 
       
  1762 	_customCleanup : function(inst, type, content) {
       
  1763 		var pl, po, i;
       
  1764 
       
  1765 		// Call custom cleanup
       
  1766 		var customCleanup = tinyMCE.settings['cleanup_callback'];
       
  1767 		if (customCleanup != "" && eval("typeof(" + customCleanup + ")") != "undefined")
       
  1768 			content = eval(customCleanup + "(type, content, inst);");
       
  1769 
       
  1770 		// Trigger theme cleanup
       
  1771 		po = tinyMCE.themes[tinyMCE.settings['theme']];
       
  1772 		if (po && po.cleanup)
       
  1773 			content = po.cleanup(type, content, inst);
       
  1774 
       
  1775 		// Trigger plugin cleanups
       
  1776 		pl = inst.plugins;
       
  1777 		for (i=0; i<pl.length; i++) {
       
  1778 			po = tinyMCE.plugins[pl[i]];
       
  1779 
       
  1780 			if (po && po.cleanup)
       
  1781 				content = po.cleanup(type, content, inst);
       
  1782 		}
       
  1783 
       
  1784 		return content;
       
  1785 	},
       
  1786 
       
  1787 	setContent : function(h) {
       
  1788 		if (tinyMCE.selectedInstance) {
       
  1789 			tinyMCE.selectedInstance.execCommand('mceSetContent', false, h);
       
  1790 			tinyMCE.selectedInstance.repaint();
       
  1791 		}
       
  1792 	},
       
  1793 
       
  1794 	importThemeLanguagePack : function(name) {
       
  1795 		if (typeof(name) == "undefined")
       
  1796 			name = tinyMCE.settings['theme'];
       
  1797 
       
  1798 		tinyMCE.loadScript(tinyMCE.baseURL + '/themes/' + name + '/langs/' + tinyMCE.settings['language'] + '.js');
       
  1799 	},
       
  1800 
       
  1801 	importPluginLanguagePack : function(name) {
       
  1802 		var b = tinyMCE.baseURL + '/plugins/' + name;
       
  1803 
       
  1804 		if (this.plugins[name])
       
  1805 			b = this.plugins[name].baseURL;
       
  1806 
       
  1807 		tinyMCE.loadScript(b + '/langs/' + tinyMCE.settings['language'] +  '.js');
       
  1808 	},
       
  1809 
       
  1810 	applyTemplate : function(h, as) {
       
  1811 		return h.replace(new RegExp('\\{\\$([a-z0-9_]+)\\}', 'gi'), function(m, s) {
       
  1812 			if (s.indexOf('lang_') == 0 && tinyMCELang[s])
       
  1813 				return tinyMCELang[s];
       
  1814 
       
  1815 			if (as && as[s])
       
  1816 				return as[s];
       
  1817 
       
  1818 			if (tinyMCE.settings[s])
       
  1819 				return tinyMCE.settings[s];
       
  1820 
       
  1821 			if (m == 'themeurl')
       
  1822 				return tinyMCE.themeURL;
       
  1823 
       
  1824 			return m;
       
  1825 		});
       
  1826 	},
       
  1827 
       
  1828 	replaceVar : function(h, r, v) {
       
  1829 		return h.replace(new RegExp('{\\\$' + r + '}', 'g'), v);
       
  1830 	},
       
  1831 
       
  1832 	openWindow : function(template, args) {
       
  1833 		var html, width, height, x, y, resizable, scrollbars, url;
       
  1834 
       
  1835 		args = !args ? {} : args;
       
  1836 
       
  1837 		args['mce_template_file'] = template['file'];
       
  1838 		args['mce_width'] = template['width'];
       
  1839 		args['mce_height'] = template['height'];
       
  1840 		tinyMCE.windowArgs = args;
       
  1841 
       
  1842 		html = template['html'];
       
  1843 		if (!(width = parseInt(template['width'])))
       
  1844 			width = 320;
       
  1845 
       
  1846 		if (!(height = parseInt(template['height'])))
       
  1847 			height = 200;
       
  1848 
       
  1849 		// Add to height in M$ due to SP2 WHY DON'T YOU GUYS IMPLEMENT innerWidth of windows!!
       
  1850 		if (tinyMCE.isIE)
       
  1851 			height += 40;
       
  1852 		else
       
  1853 			height += 20;
       
  1854 
       
  1855 		x = parseInt(screen.width / 2.0) - (width / 2.0);
       
  1856 		y = parseInt(screen.height / 2.0) - (height / 2.0);
       
  1857 
       
  1858 		resizable = (args && args['resizable']) ? args['resizable'] : "no";
       
  1859 		scrollbars = (args && args['scrollbars']) ? args['scrollbars'] : "no";
       
  1860 
       
  1861 		if (template['file'].charAt(0) != '/' && template['file'].indexOf('://') == -1)
       
  1862 			url = tinyMCE.baseURL + "/themes/" + tinyMCE.getParam("theme") + "/" + template['file'];
       
  1863 		else
       
  1864 			url = template['file'];
       
  1865 
       
  1866 		// Replace all args as variables in URL
       
  1867 		for (var name in args) {
       
  1868 			if (typeof(args[name]) == 'function')
       
  1869 				continue;
       
  1870 
       
  1871 			url = tinyMCE.replaceVar(url, name, escape(args[name]));
       
  1872 		}
       
  1873 
       
  1874 		if (html) {
       
  1875 			html = tinyMCE.replaceVar(html, "css", this.settings['popups_css']);
       
  1876 			html = tinyMCE.applyTemplate(html, args);
       
  1877 
       
  1878 			var win = window.open("", "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=yes,minimizable=" + resizable + ",modal=yes,width=" + width + ",height=" + height + ",resizable=" + resizable);
       
  1879 			if (win == null) {
       
  1880 				alert(tinyMCELang['lang_popup_blocked']);
       
  1881 				return;
       
  1882 			}
       
  1883 
       
  1884       //alert('docwrite 2');
       
  1885 			win.document.write(html);
       
  1886 			win.document.close();
       
  1887 			win.resizeTo(width, height);
       
  1888 			win.focus();
       
  1889 		} else {
       
  1890 			if ((tinyMCE.isRealIE) && resizable != 'yes' && tinyMCE.settings["dialog_type"] == "modal") {
       
  1891 				height += 10;
       
  1892 
       
  1893 				var features = "resizable:" + resizable 
       
  1894 					+ ";scroll:"
       
  1895 					+ scrollbars + ";status:yes;center:yes;help:no;dialogWidth:"
       
  1896 					+ width + "px;dialogHeight:" + height + "px;";
       
  1897 
       
  1898 				window.showModalDialog(url, window, features);
       
  1899 			} else {
       
  1900 				var modal = (resizable == "yes") ? "no" : "yes";
       
  1901 
       
  1902 				if (tinyMCE.isGecko && tinyMCE.isMac)
       
  1903 					modal = "no";
       
  1904 
       
  1905 				if (template['close_previous'] != "no")
       
  1906 					try {tinyMCE.lastWindow.close();} catch (ex) {}
       
  1907 
       
  1908 				var win = window.open(url, "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=" + modal + ",minimizable=" + resizable + ",modal=" + modal + ",width=" + width + ",height=" + height + ",resizable=" + resizable);
       
  1909 				if (win == null) {
       
  1910 					alert(tinyMCELang['lang_popup_blocked']);
       
  1911 					return;
       
  1912 				}
       
  1913 
       
  1914 				if (template['close_previous'] != "no")
       
  1915 					tinyMCE.lastWindow = win;
       
  1916 
       
  1917 				eval('try { win.resizeTo(width, height); } catch(e) { }');
       
  1918 
       
  1919 				// Make it bigger if statusbar is forced
       
  1920 				if (tinyMCE.isGecko) {
       
  1921 					if (win.document.defaultView.statusbar.visible)
       
  1922 						win.resizeBy(0, tinyMCE.isMac ? 10 : 24);
       
  1923 				}
       
  1924 
       
  1925 				win.focus();
       
  1926 			}
       
  1927 		}
       
  1928 	},
       
  1929 
       
  1930 	closeWindow : function(win) {
       
  1931 		win.close();
       
  1932 	},
       
  1933 
       
  1934 	getVisualAidClass : function(class_name, state) {
       
  1935 		var aidClass = tinyMCE.settings['visual_table_class'];
       
  1936 
       
  1937 		if (typeof(state) == "undefined")
       
  1938 			state = tinyMCE.settings['visual'];
       
  1939 
       
  1940 		// Split
       
  1941 		var classNames = new Array();
       
  1942 		var ar = class_name.split(' ');
       
  1943 		for (var i=0; i<ar.length; i++) {
       
  1944 			if (ar[i] == aidClass)
       
  1945 				ar[i] = "";
       
  1946 
       
  1947 			if (ar[i] != "")
       
  1948 				classNames[classNames.length] = ar[i];
       
  1949 		}
       
  1950 
       
  1951 		if (state)
       
  1952 			classNames[classNames.length] = aidClass;
       
  1953 
       
  1954 		// Glue
       
  1955 		var className = "";
       
  1956 		for (var i=0; i<classNames.length; i++) {
       
  1957 			if (i > 0)
       
  1958 				className += " ";
       
  1959 
       
  1960 			className += classNames[i];
       
  1961 		}
       
  1962 
       
  1963 		return className;
       
  1964 	},
       
  1965 
       
  1966 	handleVisualAid : function(el, deep, state, inst, skip_dispatch) {
       
  1967 		if (!el)
       
  1968 			return;
       
  1969 
       
  1970 		if (!skip_dispatch)
       
  1971 			tinyMCE.dispatchCallback(inst, 'handle_visual_aid_callback', 'handleVisualAid', el, deep, state, inst);
       
  1972 
       
  1973 		var tableElement = null;
       
  1974 
       
  1975 		switch (el.nodeName) {
       
  1976 			case "TABLE":
       
  1977 				var oldW = el.style.width;
       
  1978 				var oldH = el.style.height;
       
  1979 				var bo = tinyMCE.getAttrib(el, "border");
       
  1980 
       
  1981 				bo = bo == "" || bo == "0" ? true : false;
       
  1982 
       
  1983 				tinyMCE.setAttrib(el, "class", tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el, "class"), state && bo));
       
  1984 
       
  1985 				el.style.width = oldW;
       
  1986 				el.style.height = oldH;
       
  1987 
       
  1988 				for (var y=0; y<el.rows.length; y++) {
       
  1989 					for (var x=0; x<el.rows[y].cells.length; x++) {
       
  1990 						var cn = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el.rows[y].cells[x], "class"), state && bo);
       
  1991 						tinyMCE.setAttrib(el.rows[y].cells[x], "class", cn);
       
  1992 					}
       
  1993 				}
       
  1994 
       
  1995 				break;
       
  1996 
       
  1997 			case "A":
       
  1998 				var anchorName = tinyMCE.getAttrib(el, "name");
       
  1999 
       
  2000 				if (anchorName != '' && state) {
       
  2001 					el.title = anchorName;
       
  2002 					tinyMCE.addCSSClass(el, 'mceItemAnchor');
       
  2003 				} else if (anchorName != '' && !state)
       
  2004 					el.className = '';
       
  2005 
       
  2006 				break;
       
  2007 		}
       
  2008 
       
  2009 		if (deep && el.hasChildNodes()) {
       
  2010 			for (var i=0; i<el.childNodes.length; i++)
       
  2011 				tinyMCE.handleVisualAid(el.childNodes[i], deep, state, inst, true);
       
  2012 		}
       
  2013 	},
       
  2014 
       
  2015 	/*
       
  2016 	applyClassesToFonts : function(doc, size) {
       
  2017 		var f = doc.getElementsByTagName("font");
       
  2018 		for (var i=0; i<f.length; i++) {
       
  2019 			var s = tinyMCE.getAttrib(f[i], "size");
       
  2020 
       
  2021 			if (s != "")
       
  2022 				tinyMCE.setAttrib(f[i], 'class', "mceItemFont" + s);
       
  2023 		}
       
  2024 
       
  2025 		if (typeof(size) != "undefined") {
       
  2026 			var css = "";
       
  2027 
       
  2028 			for (var x=0; x<doc.styleSheets.length; x++) {
       
  2029 				for (var i=0; i<doc.styleSheets[x].rules.length; i++) {
       
  2030 					if (doc.styleSheets[x].rules[i].selectorText == '#mceSpanFonts .mceItemFont' + size) {
       
  2031 						css = doc.styleSheets[x].rules[i].style.cssText;
       
  2032 						break;
       
  2033 					}
       
  2034 				}
       
  2035 
       
  2036 				if (css != "")
       
  2037 					break;
       
  2038 			}
       
  2039 
       
  2040 			if (doc.styleSheets[0].rules[0].selectorText == "FONT")
       
  2041 				doc.styleSheets[0].removeRule(0);
       
  2042 
       
  2043 			doc.styleSheets[0].addRule("FONT", css, 0);
       
  2044 		}
       
  2045 	},
       
  2046 	*/
       
  2047 
       
  2048 	fixGeckoBaseHREFBug : function(m, e, h) {
       
  2049 		var xsrc, xhref;
       
  2050 
       
  2051 		if (tinyMCE.isGecko) {
       
  2052 			if (m == 1) {
       
  2053 				h = h.replace(/\ssrc=/gi, " mce_tsrc=");
       
  2054 				h = h.replace(/\shref=/gi, " mce_thref=");
       
  2055 
       
  2056 				return h;
       
  2057 			} else {
       
  2058 				// Why bother if there is no src or href broken
       
  2059 				if (!new RegExp('(src|href)=', 'g').test(h))
       
  2060 					return h;
       
  2061 
       
  2062 				// Restore src and href that gets messed up by Gecko
       
  2063 				tinyMCE.selectElements(e, 'A,IMG,SELECT,AREA,IFRAME,BASE,INPUT,SCRIPT,EMBED,OBJECT,LINK', function (n) {
       
  2064 					xsrc = tinyMCE.getAttrib(n, "mce_tsrc");
       
  2065 					xhref = tinyMCE.getAttrib(n, "mce_thref");
       
  2066 
       
  2067 					if (xsrc != "") {
       
  2068 						try {
       
  2069 							n.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xsrc);
       
  2070 						} catch (e) {
       
  2071 							// Ignore, Firefox cast exception if local file wasn't found
       
  2072 						}
       
  2073 
       
  2074 						n.removeAttribute("mce_tsrc");
       
  2075 					}
       
  2076 
       
  2077 					if (xhref != "") {
       
  2078 						try {
       
  2079 							n.href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xhref);
       
  2080 						} catch (e) {
       
  2081 							// Ignore, Firefox cast exception if local file wasn't found
       
  2082 						}
       
  2083 
       
  2084 						n.removeAttribute("mce_thref");
       
  2085 					}
       
  2086 
       
  2087 					return false;
       
  2088 				});
       
  2089 
       
  2090 				// Restore text/comment nodes
       
  2091 				tinyMCE.selectNodes(e, function(n) {
       
  2092 					if (n.nodeType == 3 || n.nodeType == 8) {
       
  2093 						n.nodeValue = n.nodeValue.replace(/\smce_tsrc=/gi, " src=");
       
  2094 						n.nodeValue = n.nodeValue.replace(/\smce_thref=/gi, " href=");
       
  2095 					}
       
  2096 
       
  2097 					return false;
       
  2098 				});
       
  2099 			}
       
  2100 		}
       
  2101 
       
  2102 		return h;
       
  2103 	},
       
  2104 
       
  2105 	_setHTML : function(doc, html_content) {
       
  2106 		// Force closed anchors open
       
  2107 		//html_content = html_content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');
       
  2108 
       
  2109 		html_content = tinyMCE.cleanupHTMLCode(html_content);
       
  2110 
       
  2111 		// Try innerHTML if it fails use pasteHTML in MSIE
       
  2112 		try {
       
  2113 			tinyMCE.setInnerHTML(doc.body, html_content);
       
  2114 		} catch (e) {
       
  2115 			if (this.isMSIE)
       
  2116 				doc.body.createTextRange().pasteHTML(html_content);
       
  2117 		}
       
  2118 
       
  2119 		// Content duplication bug fix
       
  2120 		if (tinyMCE.isIE && tinyMCE.settings['fix_content_duplication']) {
       
  2121 			// Remove P elements in P elements
       
  2122 			var paras = doc.getElementsByTagName("P");
       
  2123 			for (var i=0; i<paras.length; i++) {
       
  2124 				var node = paras[i];
       
  2125 				while ((node = node.parentNode) != null) {
       
  2126 					if (node.nodeName == "P")
       
  2127 						node.outerHTML = node.innerHTML;
       
  2128 				}
       
  2129 			}
       
  2130 
       
  2131 			// Content duplication bug fix (Seems to be word crap)
       
  2132 			var html = doc.body.innerHTML;
       
  2133 /*
       
  2134 			if (html.indexOf('="mso') != -1) {
       
  2135 				for (var i=0; i<doc.body.all.length; i++) {
       
  2136 					var el = doc.body.all[i];
       
  2137 					el.removeAttribute("className","",0);
       
  2138 					el.removeAttribute("style","",0);
       
  2139 				}
       
  2140 
       
  2141 				html = doc.body.innerHTML;
       
  2142 				html = tinyMCE.regexpReplace(html, "<o:p><\/o:p>", "<br />");
       
  2143 				html = tinyMCE.regexpReplace(html, "<o:p>&nbsp;<\/o:p>", "");
       
  2144 				html = tinyMCE.regexpReplace(html, "<st1:.*?>", "");
       
  2145 				html = tinyMCE.regexpReplace(html, "<p><\/p>", "");
       
  2146 				html = tinyMCE.regexpReplace(html, "<p><\/p>\r\n<p><\/p>", "");
       
  2147 				html = tinyMCE.regexpReplace(html, "<p>&nbsp;<\/p>", "<br />");
       
  2148 				html = tinyMCE.regexpReplace(html, "<p>\s*(<p>\s*)?", "<p>");
       
  2149 				html = tinyMCE.regexpReplace(html, "<\/p>\s*(<\/p>\s*)?", "</p>");
       
  2150 			}*/
       
  2151 
       
  2152 			// Always set the htmlText output
       
  2153 			tinyMCE.setInnerHTML(doc.body, html);
       
  2154 		}
       
  2155 
       
  2156 		tinyMCE.cleanupAnchors(doc);
       
  2157 
       
  2158 		if (tinyMCE.getParam("convert_fonts_to_spans"))
       
  2159 			tinyMCE.convertSpansToFonts(doc);
       
  2160 	},
       
  2161 
       
  2162 	getEditorId : function(form_element) {
       
  2163 		var inst = this.getInstanceById(form_element);
       
  2164 		if (!inst)
       
  2165 			return null;
       
  2166 
       
  2167 		return inst.editorId;
       
  2168 	},
       
  2169 
       
  2170 	getInstanceById : function(editor_id) {
       
  2171 		var inst = this.instances[editor_id];
       
  2172 		if (!inst) {
       
  2173 			for (var n in tinyMCE.instances) {
       
  2174 				var instance = tinyMCE.instances[n];
       
  2175 				if (!tinyMCE.isInstance(instance))
       
  2176 					continue;
       
  2177 
       
  2178 				if (instance.formTargetElementId == editor_id) {
       
  2179 					inst = instance;
       
  2180 					break;
       
  2181 				}
       
  2182 			}
       
  2183 		}
       
  2184 
       
  2185 		return inst;
       
  2186 	},
       
  2187 
       
  2188 	queryInstanceCommandValue : function(editor_id, command) {
       
  2189 		var inst = tinyMCE.getInstanceById(editor_id);
       
  2190 		if (inst)
       
  2191 			return inst.queryCommandValue(command);
       
  2192 
       
  2193 		return false;
       
  2194 	},
       
  2195 
       
  2196 	queryInstanceCommandState : function(editor_id, command) {
       
  2197 		var inst = tinyMCE.getInstanceById(editor_id);
       
  2198 		if (inst)
       
  2199 			return inst.queryCommandState(command);
       
  2200 
       
  2201 		return null;
       
  2202 	},
       
  2203 
       
  2204 	setWindowArg : function(n, v) {
       
  2205 		this.windowArgs[n] = v;
       
  2206 	},
       
  2207 
       
  2208 	getWindowArg : function(n, d) {
       
  2209 		return (typeof(this.windowArgs[n]) == "undefined") ? d : this.windowArgs[n];
       
  2210 	},
       
  2211 
       
  2212 	getCSSClasses : function(editor_id, doc) {
       
  2213 		var inst = tinyMCE.getInstanceById(editor_id);
       
  2214 
       
  2215 		// Is cached, use that
       
  2216 		if (inst && inst.cssClasses.length > 0)
       
  2217 			return inst.cssClasses;
       
  2218 
       
  2219 		if (typeof(editor_id) == "undefined" && typeof(doc) == "undefined") {
       
  2220 			var instance;
       
  2221 
       
  2222 			for (var instanceName in tinyMCE.instances) {
       
  2223 				instance = tinyMCE.instances[instanceName];
       
  2224 				if (!tinyMCE.isInstance(instance))
       
  2225 					continue;
       
  2226 
       
  2227 				break;
       
  2228 			}
       
  2229 
       
  2230 			doc = instance.getDoc();
       
  2231 		}
       
  2232 
       
  2233 		if (typeof(doc) == "undefined") {
       
  2234 			var instance = tinyMCE.getInstanceById(editor_id);
       
  2235 			doc = instance.getDoc();
       
  2236 		}
       
  2237 
       
  2238 		if (doc) {
       
  2239 			var styles = doc.styleSheets;
       
  2240 
       
  2241 			if (styles && styles.length > 0) {
       
  2242 				for (var x=0; x<styles.length; x++) {
       
  2243 					var csses = null;
       
  2244 
       
  2245 					// Just ignore any errors
       
  2246 					eval("try {var csses = tinyMCE.isIE ? doc.styleSheets(" + x + ").rules : styles[" + x + "].cssRules;} catch(e) {}");
       
  2247 					if (!csses)
       
  2248 						return new Array();
       
  2249 
       
  2250 					for (var i=0; i<csses.length; i++) {
       
  2251 						var selectorText = csses[i].selectorText;
       
  2252 
       
  2253 						// Can be multiple rules per selector
       
  2254 						if (selectorText) {
       
  2255 							var rules = selectorText.split(',');
       
  2256 							for (var c=0; c<rules.length; c++) {
       
  2257 								var rule = rules[c];
       
  2258 
       
  2259 								// Strip spaces between selectors
       
  2260 								while (rule.indexOf(' ') == 0)
       
  2261 									rule = rule.substring(1);
       
  2262 
       
  2263 								// Invalid rule
       
  2264 								if (rule.indexOf(' ') != -1 || rule.indexOf(':') != -1 || rule.indexOf('mceItem') != -1)
       
  2265 									continue;
       
  2266 
       
  2267 								if (rule.indexOf(tinyMCE.settings['visual_table_class']) != -1 || rule.indexOf('mceEditable') != -1 || rule.indexOf('mceNonEditable') != -1)
       
  2268 									continue;
       
  2269 
       
  2270 								// Is class rule
       
  2271 								if (rule.indexOf('.') != -1) {
       
  2272 									var cssClass = rule.substring(rule.indexOf('.') + 1);
       
  2273 									var addClass = true;
       
  2274 
       
  2275 									for (var p=0; p<inst.cssClasses.length && addClass; p++) {
       
  2276 										if (inst.cssClasses[p] == cssClass)
       
  2277 											addClass = false;
       
  2278 									}
       
  2279 
       
  2280 									if (addClass)
       
  2281 										inst.cssClasses[inst.cssClasses.length] = cssClass;
       
  2282 								}
       
  2283 							}
       
  2284 						}
       
  2285 					}
       
  2286 				}
       
  2287 			}
       
  2288 		}
       
  2289 
       
  2290 		return inst.cssClasses;
       
  2291 	},
       
  2292 
       
  2293 	regexpReplace : function(in_str, reg_exp, replace_str, opts) {
       
  2294 		if (in_str == null)
       
  2295 			return in_str;
       
  2296 
       
  2297 		if (typeof(opts) == "undefined")
       
  2298 			opts = 'g';
       
  2299 
       
  2300 		var re = new RegExp(reg_exp, opts);
       
  2301 		return in_str.replace(re, replace_str);
       
  2302 	},
       
  2303 
       
  2304 	trim : function(s) {
       
  2305 		return s.replace(/^\s*|\s*$/g, "");
       
  2306 	},
       
  2307 
       
  2308 	cleanupEventStr : function(s) {
       
  2309 		s = "" + s;
       
  2310 		s = s.replace('function anonymous()\n{\n', '');
       
  2311 		s = s.replace('\n}', '');
       
  2312 		s = s.replace(/^return true;/gi, ''); // Remove event blocker
       
  2313 
       
  2314 		return s;
       
  2315 	},
       
  2316 
       
  2317 	getControlHTML : function(c) {
       
  2318 		var i, l, n, o, v, rtl = tinyMCE.getLang('lang_dir') == 'rtl';
       
  2319 
       
  2320 		l = tinyMCE.plugins;
       
  2321 		for (n in l) {
       
  2322 			o = l[n];
       
  2323 
       
  2324 			if (o.getControlHTML && (v = o.getControlHTML(c)) != '') {
       
  2325 				if (rtl)
       
  2326 					return '<span dir="rtl">' + tinyMCE.replaceVar(v, "pluginurl", o.baseURL) + '</span>';
       
  2327 
       
  2328 				return tinyMCE.replaceVar(v, "pluginurl", o.baseURL);
       
  2329 			}
       
  2330 		}
       
  2331 
       
  2332 		o = tinyMCE.themes[tinyMCE.settings['theme']];
       
  2333 		if (o.getControlHTML && (v = o.getControlHTML(c)) != '') {
       
  2334 			if (rtl)
       
  2335 				return '<span dir="rtl">' + v + '</span>';
       
  2336 
       
  2337 			return v;
       
  2338 		}
       
  2339 
       
  2340 		return '';
       
  2341 	},
       
  2342 
       
  2343 	evalFunc : function(f, idx, a, o) {
       
  2344 		o = !o ? window : o;
       
  2345 		f = typeof(f) == 'function' ? f : o[f];
       
  2346 
       
  2347 		return f.apply(o, Array.prototype.slice.call(a, idx));
       
  2348 	},
       
  2349 
       
  2350 	dispatchCallback : function(i, p, n) {
       
  2351 		return this.callFunc(i, p, n, 0, this.dispatchCallback.arguments);
       
  2352 	},
       
  2353 
       
  2354 	executeCallback : function(i, p, n) {
       
  2355 		return this.callFunc(i, p, n, 1, this.executeCallback.arguments);
       
  2356 	},
       
  2357 
       
  2358 	execCommandCallback : function(i, p, n) {
       
  2359 		return this.callFunc(i, p, n, 2, this.execCommandCallback.arguments);
       
  2360 	},
       
  2361 
       
  2362 	callFunc : function(ins, p, n, m, a) {
       
  2363 		var l, i, on, o, s, v;
       
  2364 
       
  2365 		s = m == 2;
       
  2366 
       
  2367 		l = tinyMCE.getParam(p, '');
       
  2368 
       
  2369 		if (l != '' && (v = tinyMCE.evalFunc(l, 3, a)) == s && m > 0)
       
  2370 			return true;
       
  2371 
       
  2372 		if (ins != null) {
       
  2373 			for (i=0, l = ins.plugins; i<l.length; i++) {
       
  2374 				o = tinyMCE.plugins[l[i]];
       
  2375 
       
  2376 				if (o[n] && (v = tinyMCE.evalFunc(n, 3, a, o)) == s && m > 0)
       
  2377 					return true;
       
  2378 			}
       
  2379 		}
       
  2380 
       
  2381 		l = tinyMCE.themes;
       
  2382 		for (on in l) {
       
  2383 			o = l[on];
       
  2384 
       
  2385 			if (o[n] && (v = tinyMCE.evalFunc(n, 3, a, o)) == s && m > 0)
       
  2386 				return true;
       
  2387 		}
       
  2388 
       
  2389 		return false;
       
  2390 	},
       
  2391 
       
  2392 	xmlEncode : function(s, skip_apos) {
       
  2393 		return s ? ('' + s).replace(!skip_apos ? this.xmlEncodeAposRe : this.xmlEncodeRe, function (c, b) {
       
  2394 			switch (c) {
       
  2395 				case '&':
       
  2396 					return '&amp;';
       
  2397 
       
  2398 				case '"':
       
  2399 					return '&quot;';
       
  2400 
       
  2401 				case '\'':
       
  2402 					return '&#39;'; // &apos; is not working in MSIE
       
  2403 
       
  2404 				case '<':
       
  2405 					return '&lt;';
       
  2406 
       
  2407 				case '>':
       
  2408 					return '&gt;';
       
  2409 			}
       
  2410 
       
  2411 			return c;
       
  2412 		}) : s;
       
  2413 	},
       
  2414 
       
  2415 	extend : function(p, np) {
       
  2416 		var o = {};
       
  2417 
       
  2418 		o.parent = p;
       
  2419 
       
  2420 		for (n in p)
       
  2421 			o[n] = p[n];
       
  2422 
       
  2423 		for (n in np)
       
  2424 			o[n] = np[n];
       
  2425 
       
  2426 		return o;
       
  2427 	},
       
  2428 
       
  2429 	hideMenus : function() {
       
  2430 		var e = tinyMCE.lastSelectedMenuBtn;
       
  2431 
       
  2432 		if (tinyMCE.lastMenu) {
       
  2433 			tinyMCE.lastMenu.hide();
       
  2434 			tinyMCE.lastMenu = null;
       
  2435 		}
       
  2436 
       
  2437 		if (e) {
       
  2438 			tinyMCE.switchClass(e, tinyMCE.lastMenuBtnClass);
       
  2439 			tinyMCE.lastSelectedMenuBtn = null;
       
  2440 		}
       
  2441 	}
       
  2442 
       
  2443 	};
       
  2444 
       
  2445 // Global instances
       
  2446 var TinyMCE = TinyMCE_Engine; // Compatiblity with gzip compressors
       
  2447 var tinyMCE = new TinyMCE_Engine();
       
  2448 var tinyMCELang = {};
       
  2449 
       
  2450 /* file:jscripts/tiny_mce/classes/TinyMCE_Control.class.js */
       
  2451 
       
  2452 function TinyMCE_Control(settings) {
       
  2453 	var t, i, to, fu, p, x, fn, fu, pn, s = settings;
       
  2454 
       
  2455 	this.undoRedoLevel = true;
       
  2456 	this.isTinyMCE_Control = true;
       
  2457 
       
  2458 	// Default settings
       
  2459 	this.settings = s;
       
  2460 	this.settings['theme'] = tinyMCE.getParam("theme", "default");
       
  2461 	this.settings['width'] = tinyMCE.getParam("width", -1);
       
  2462 	this.settings['height'] = tinyMCE.getParam("height", -1);
       
  2463 	this.selection = new TinyMCE_Selection(this);
       
  2464 	this.undoRedo = new TinyMCE_UndoRedo(this);
       
  2465 	this.cleanup = new TinyMCE_Cleanup();
       
  2466 	this.shortcuts = new Array();
       
  2467 	this.hasMouseMoved = false;
       
  2468 	this.foreColor = this.backColor = "#999999";
       
  2469 	this.data = {};
       
  2470 	this.cssClasses = [];
       
  2471 
       
  2472 	this.cleanup.init({
       
  2473 		valid_elements : s.valid_elements,
       
  2474 		extended_valid_elements : s.extended_valid_elements,
       
  2475 		valid_child_elements : s.valid_child_elements,
       
  2476 		entities : s.entities,
       
  2477 		entity_encoding : s.entity_encoding,
       
  2478 		debug : s.cleanup_debug,
       
  2479 		indent : s.apply_source_formatting,
       
  2480 		invalid_elements : s.invalid_elements,
       
  2481 		verify_html : s.verify_html,
       
  2482 		fix_content_duplication : s.fix_content_duplication,
       
  2483 		convert_fonts_to_spans : s.convert_fonts_to_spans
       
  2484 	});
       
  2485 
       
  2486 	// Wrap old theme
       
  2487 	t = this.settings['theme'];
       
  2488 	if (!tinyMCE.hasTheme(t)) {
       
  2489 		fn = tinyMCE.callbacks;
       
  2490 		to = {};
       
  2491 
       
  2492 		for (i=0; i<fn.length; i++) {
       
  2493 			if ((fu = window['TinyMCE_' + t + "_" + fn[i]]))
       
  2494 				to[fn[i]] = fu;
       
  2495 		}
       
  2496 
       
  2497 		tinyMCE.addTheme(t, to);
       
  2498 	}
       
  2499 
       
  2500 	// Wrap old plugins
       
  2501 	this.plugins = new Array();
       
  2502 	p = tinyMCE.getParam('plugins', '', true, ',');
       
  2503 	if (p.length > 0) {
       
  2504 		for (i=0; i<p.length; i++) {
       
  2505 			pn = p[i];
       
  2506 
       
  2507 			if (pn.charAt(0) == '-')
       
  2508 				pn = pn.substring(1);
       
  2509 
       
  2510 			if (!tinyMCE.hasPlugin(pn)) {
       
  2511 				fn = tinyMCE.callbacks;
       
  2512 				to = {};
       
  2513 
       
  2514 				for (x=0; x<fn.length; x++) {
       
  2515 					if ((fu = window['TinyMCE_' + pn + "_" + fn[x]]))
       
  2516 						to[fn[x]] = fu;
       
  2517 				}
       
  2518 
       
  2519 				tinyMCE.addPlugin(pn, to);
       
  2520 			}
       
  2521 
       
  2522 			this.plugins[this.plugins.length] = pn; 
       
  2523 		}
       
  2524 	}
       
  2525 };
       
  2526 
       
  2527 TinyMCE_Control.prototype = {
       
  2528 	selection : null,
       
  2529 
       
  2530 	settings : null,
       
  2531 
       
  2532 	cleanup : null,
       
  2533 
       
  2534 	getData : function(na) {
       
  2535 		var o = this.data[na];
       
  2536 
       
  2537 		if (!o)
       
  2538 			o = this.data[na] = {};
       
  2539 
       
  2540 		return o;
       
  2541 	},
       
  2542 
       
  2543 	hasPlugin : function(n) {
       
  2544 		var i;
       
  2545 
       
  2546 		for (i=0; i<this.plugins.length; i++) {
       
  2547 			if (this.plugins[i] == n)
       
  2548 				return true;
       
  2549 		}
       
  2550 
       
  2551 		return false;
       
  2552 	},
       
  2553 
       
  2554 	addPlugin : function(n, p) {
       
  2555 		if (!this.hasPlugin(n)) {
       
  2556 			tinyMCE.addPlugin(n, p);
       
  2557 			this.plugins[this.plugins.length] = n;
       
  2558 		}
       
  2559 	},
       
  2560 
       
  2561 	repaint : function() {
       
  2562 		var s, b, ex;
       
  2563 
       
  2564 		if (tinyMCE.isRealIE)
       
  2565 			return;
       
  2566 
       
  2567 		try {
       
  2568 			s = this.selection;
       
  2569 			b = s.getBookmark(true);
       
  2570 			this.getBody().style.display = 'none';
       
  2571 			this.getDoc().execCommand('selectall', false, null);
       
  2572 			this.getSel().collapseToStart();
       
  2573 			this.getBody().style.display = 'block';
       
  2574 			s.moveToBookmark(b);
       
  2575 		} catch (ex) {
       
  2576 			// Ignore
       
  2577 		}
       
  2578 	},
       
  2579 
       
  2580 	switchSettings : function() {
       
  2581 		if (tinyMCE.configs.length > 1 && tinyMCE.currentConfig != this.settings['index']) {
       
  2582 			tinyMCE.settings = this.settings;
       
  2583 			tinyMCE.currentConfig = this.settings['index'];
       
  2584 		}
       
  2585 	},
       
  2586 
       
  2587 	select : function() {
       
  2588 		var oldInst = tinyMCE.selectedInstance;
       
  2589 
       
  2590 		if (oldInst != this) {
       
  2591 			if (oldInst)
       
  2592 				oldInst.execCommand('mceEndTyping');
       
  2593 
       
  2594 			tinyMCE.dispatchCallback(this, 'select_instance_callback', 'selectInstance', this, oldInst);
       
  2595 			tinyMCE.selectedInstance = this;
       
  2596 		}
       
  2597 	},
       
  2598 
       
  2599 	getBody : function() {
       
  2600 		return this.contentBody ? this.contentBody : this.getDoc().body;
       
  2601 	},
       
  2602 
       
  2603 	getDoc : function() {
       
  2604 //		return this.contentDocument ? this.contentDocument : this.contentWindow.document; // Removed due to IE 5.5 ?
       
  2605 		return this.contentWindow.document;
       
  2606 	},
       
  2607 
       
  2608 	getWin : function() {
       
  2609 		return this.contentWindow;
       
  2610 	},
       
  2611 
       
  2612 	getContainerWin : function() {
       
  2613 		return this.containerWindow ? this.containerWindow : window;
       
  2614 	},
       
  2615 
       
  2616 	getViewPort : function() {
       
  2617 		return tinyMCE.getViewPort(this.getWin());
       
  2618 	},
       
  2619 
       
  2620 	getParentNode : function(n, f) {
       
  2621 		return tinyMCE.getParentNode(n, f, this.getBody());
       
  2622 	},
       
  2623 
       
  2624 	getParentElement : function(n, na, f) {
       
  2625 		return tinyMCE.getParentElement(n, na, f, this.getBody());
       
  2626 	},
       
  2627 
       
  2628 	getParentBlockElement : function(n) {
       
  2629 		return tinyMCE.getParentBlockElement(n, this.getBody());
       
  2630 	},
       
  2631 
       
  2632 	resizeToContent : function() {
       
  2633 		var d = this.getDoc(), b = d.body, de = d.documentElement;
       
  2634 
       
  2635 		this.iframeElement.style.height = (tinyMCE.isRealIE) ? b.scrollHeight : de.offsetHeight + 'px';
       
  2636 	},
       
  2637 
       
  2638 	addShortcut : function(m, k, d, cmd, ui, va) {
       
  2639 		var n = typeof(k) == "number", ie = tinyMCE.isIE, c, sc, i, scl = this.shortcuts;
       
  2640 
       
  2641 		if (!tinyMCE.getParam('custom_shortcuts'))
       
  2642 			return false;
       
  2643 
       
  2644 		m = m.toLowerCase();
       
  2645 		k = ie && !n ? k.toUpperCase() : k;
       
  2646 		c = n ? null : k.charCodeAt(0);
       
  2647 		d = d && d.indexOf('lang_') == 0 ? tinyMCE.getLang(d) : d;
       
  2648 
       
  2649 		sc = {
       
  2650 			alt : m.indexOf('alt') != -1,
       
  2651 			ctrl : m.indexOf('ctrl') != -1,
       
  2652 			shift : m.indexOf('shift') != -1,
       
  2653 			charCode : c,
       
  2654 			keyCode : n ? k : (ie ? c : null),
       
  2655 			desc : d,
       
  2656 			cmd : cmd,
       
  2657 			ui : ui,
       
  2658 			val : va
       
  2659 		};
       
  2660 
       
  2661 		for (i=0; i<scl.length; i++) {
       
  2662 			if (sc.alt == scl[i].alt && sc.ctrl == scl[i].ctrl && sc.shift == scl[i].shift
       
  2663 				&& sc.charCode == scl[i].charCode && sc.keyCode == scl[i].keyCode) {
       
  2664 				return false;
       
  2665 			}
       
  2666 		}
       
  2667 
       
  2668 		scl[scl.length] = sc;
       
  2669 
       
  2670 		return true;
       
  2671 	},
       
  2672 
       
  2673 	handleShortcut : function(e) {
       
  2674 		var i, s, o;
       
  2675 
       
  2676 		// Normal key press, then ignore it
       
  2677 		if (!e.altKey && !e.ctrlKey)
       
  2678 			return false;
       
  2679 
       
  2680 		s = this.shortcuts;
       
  2681 
       
  2682 		for (i=0; i<s.length; i++) {
       
  2683 			o = s[i];
       
  2684 
       
  2685 			if (o.alt == e.altKey && o.ctrl == e.ctrlKey && (o.keyCode == e.keyCode || o.charCode == e.charCode)) {
       
  2686 				if (o.cmd && (e.type == "keydown" || (e.type == "keypress" && !tinyMCE.isOpera)))
       
  2687 					tinyMCE.execCommand(o.cmd, o.ui, o.val);
       
  2688 
       
  2689 				tinyMCE.cancelEvent(e);
       
  2690 				return true;
       
  2691 			}
       
  2692 		}
       
  2693 
       
  2694 		return false;
       
  2695 	},
       
  2696 
       
  2697 	autoResetDesignMode : function() {
       
  2698 		// Add fix for tab/style.display none/block problems in Gecko
       
  2699 		if (!tinyMCE.isIE && this.isHidden() && tinyMCE.getParam('auto_reset_designmode'))
       
  2700 			eval('try { this.getDoc().designMode = "On"; this.useCSS = false; } catch(e) {}');
       
  2701 	},
       
  2702 
       
  2703 	isHidden : function() {
       
  2704 		var s;
       
  2705 
       
  2706 		if (tinyMCE.isIE)
       
  2707 			return false;
       
  2708 
       
  2709 		s = this.getSel();
       
  2710 
       
  2711 		// Weird, wheres that cursor selection?
       
  2712 		return (!s || !s.rangeCount || s.rangeCount == 0);
       
  2713 	},
       
  2714 
       
  2715 	isDirty : function() {
       
  2716 		// Is content modified and not in a submit procedure
       
  2717 		return tinyMCE.trim(this.startContent) != tinyMCE.trim(this.getBody().innerHTML) && !tinyMCE.isNotDirty;
       
  2718 	},
       
  2719 
       
  2720 	_mergeElements : function(scmd, pa, ch, override) {
       
  2721 		if (scmd == "removeformat") {
       
  2722 			pa.className = "";
       
  2723 			pa.style.cssText = "";
       
  2724 			ch.className = "";
       
  2725 			ch.style.cssText = "";
       
  2726 			return;
       
  2727 		}
       
  2728 
       
  2729 		var st = tinyMCE.parseStyle(tinyMCE.getAttrib(pa, "style"));
       
  2730 		var stc = tinyMCE.parseStyle(tinyMCE.getAttrib(ch, "style"));
       
  2731 		var className = tinyMCE.getAttrib(pa, "class");
       
  2732 
       
  2733 		// Removed class adding due to bug #1478272
       
  2734 		className = tinyMCE.getAttrib(ch, "class");
       
  2735 
       
  2736 		if (override) {
       
  2737 			for (var n in st) {
       
  2738 				if (typeof(st[n]) == 'function')
       
  2739 					continue;
       
  2740 
       
  2741 				stc[n] = st[n];
       
  2742 			}
       
  2743 		} else {
       
  2744 			for (var n in stc) {
       
  2745 				if (typeof(stc[n]) == 'function')
       
  2746 					continue;
       
  2747 
       
  2748 				st[n] = stc[n];
       
  2749 			}
       
  2750 		}
       
  2751 
       
  2752 		tinyMCE.setAttrib(pa, "style", tinyMCE.serializeStyle(st));
       
  2753 		tinyMCE.setAttrib(pa, "class", tinyMCE.trim(className));
       
  2754 		ch.className = "";
       
  2755 		ch.style.cssText = "";
       
  2756 		ch.removeAttribute("class");
       
  2757 		ch.removeAttribute("style");
       
  2758 	},
       
  2759 
       
  2760 	_setUseCSS : function(b) {
       
  2761 		var d = this.getDoc();
       
  2762 
       
  2763 		try {d.execCommand("useCSS", false, !b);} catch (ex) {}
       
  2764 		try {d.execCommand("styleWithCSS", false, b);} catch (ex) {}
       
  2765 
       
  2766 		if (!tinyMCE.getParam("table_inline_editing"))
       
  2767 			try {d.execCommand('enableInlineTableEditing', false, "false");} catch (ex) {}
       
  2768 
       
  2769 		if (!tinyMCE.getParam("object_resizing"))
       
  2770 			try {d.execCommand('enableObjectResizing', false, "false");} catch (ex) {}
       
  2771 	},
       
  2772 
       
  2773 	execCommand : function(command, user_interface, value) {
       
  2774 		var doc = this.getDoc(), win = this.getWin(), focusElm = this.getFocusElement();
       
  2775 
       
  2776 		// Is not a undo specific command
       
  2777 		if (!new RegExp('mceStartTyping|mceEndTyping|mceBeginUndoLevel|mceEndUndoLevel|mceAddUndoLevel', 'gi').test(command))
       
  2778 			this.undoBookmark = null;
       
  2779 
       
  2780 		// Mozilla issue
       
  2781 		if (!tinyMCE.isIE && !this.useCSS) {
       
  2782 			this._setUseCSS(false);
       
  2783 			this.useCSS = true;
       
  2784 		}
       
  2785 
       
  2786 		//debug("command: " + command + ", user_interface: " + user_interface + ", value: " + value);
       
  2787 		this.contentDocument = doc; // <-- Strange, unless this is applied Mozilla 1.3 breaks
       
  2788 
       
  2789 		// Don't dispatch key commands
       
  2790 		if (!/mceStartTyping|mceEndTyping/.test(command)) {
       
  2791 			if (tinyMCE.execCommandCallback(this, 'execcommand_callback', 'execCommand', this.editorId, this.getBody(), command, user_interface, value))
       
  2792 				return;
       
  2793 		}
       
  2794 
       
  2795 		// Fix align on images
       
  2796 		if (focusElm && focusElm.nodeName == "IMG") {
       
  2797 			var align = focusElm.getAttribute('align');
       
  2798 			var img = command == "JustifyCenter" ? focusElm.cloneNode(false) : focusElm;
       
  2799 
       
  2800 			switch (command) {
       
  2801 				case "JustifyLeft":
       
  2802 					if (align == 'left')
       
  2803 						img.removeAttribute('align');
       
  2804 					else
       
  2805 						img.setAttribute('align', 'left');
       
  2806 
       
  2807 					// Remove the div
       
  2808 					var div = focusElm.parentNode;
       
  2809 					if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
       
  2810 						div.parentNode.replaceChild(img, div);
       
  2811 
       
  2812 					this.selection.selectNode(img);
       
  2813 					this.repaint();
       
  2814 					tinyMCE.triggerNodeChange();
       
  2815 					return;
       
  2816 
       
  2817 				case "JustifyCenter":
       
  2818 					img.removeAttribute('align');
       
  2819 
       
  2820 					// Is centered
       
  2821 					var div = tinyMCE.getParentElement(focusElm, "div");
       
  2822 					if (div && div.style.textAlign == "center") {
       
  2823 						// Remove div
       
  2824 						if (div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
       
  2825 							div.parentNode.replaceChild(img, div);
       
  2826 					} else {
       
  2827 						// Add div
       
  2828 						var div = this.getDoc().createElement("div");
       
  2829 						div.style.textAlign = 'center';
       
  2830 						div.appendChild(img);
       
  2831 						focusElm.parentNode.replaceChild(div, focusElm);
       
  2832 					}
       
  2833 
       
  2834 					this.selection.selectNode(img);
       
  2835 					this.repaint();
       
  2836 					tinyMCE.triggerNodeChange();
       
  2837 					return;
       
  2838 
       
  2839 				case "JustifyRight":
       
  2840 					if (align == 'right')
       
  2841 						img.removeAttribute('align');
       
  2842 					else
       
  2843 						img.setAttribute('align', 'right');
       
  2844 
       
  2845 					// Remove the div
       
  2846 					var div = focusElm.parentNode;
       
  2847 					if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
       
  2848 						div.parentNode.replaceChild(img, div);
       
  2849 
       
  2850 					this.selection.selectNode(img);
       
  2851 					this.repaint();
       
  2852 					tinyMCE.triggerNodeChange();
       
  2853 					return;
       
  2854 			}
       
  2855 		}
       
  2856 
       
  2857 		if (tinyMCE.settings['force_br_newlines']) {
       
  2858 			var alignValue = "";
       
  2859 
       
  2860 			if (doc.selection.type != "Control") {
       
  2861 				switch (command) {
       
  2862 						case "JustifyLeft":
       
  2863 							alignValue = "left";
       
  2864 							break;
       
  2865 
       
  2866 						case "JustifyCenter":
       
  2867 							alignValue = "center";
       
  2868 							break;
       
  2869 
       
  2870 						case "JustifyFull":
       
  2871 							alignValue = "justify";
       
  2872 							break;
       
  2873 
       
  2874 						case "JustifyRight":
       
  2875 							alignValue = "right";
       
  2876 							break;
       
  2877 				}
       
  2878 
       
  2879 				if (alignValue != "") {
       
  2880 					var rng = doc.selection.createRange();
       
  2881 
       
  2882 					if ((divElm = tinyMCE.getParentElement(rng.parentElement(), "div")) != null)
       
  2883 						divElm.setAttribute("align", alignValue);
       
  2884 					else if (rng.pasteHTML && rng.htmlText.length > 0)
       
  2885 						rng.pasteHTML('<div align="' + alignValue + '">' + rng.htmlText + "</div>");
       
  2886 
       
  2887 					tinyMCE.triggerNodeChange();
       
  2888 					return;
       
  2889 				}
       
  2890 			}
       
  2891 		}
       
  2892 
       
  2893 		switch (command) {
       
  2894 			case "mceRepaint":
       
  2895 				this.repaint();
       
  2896 				return true;
       
  2897 
       
  2898 			case "unlink":
       
  2899 				// Unlink if caret is inside link
       
  2900 				if (tinyMCE.isGecko && this.getSel().isCollapsed) {
       
  2901 					focusElm = tinyMCE.getParentElement(focusElm, 'A');
       
  2902 
       
  2903 					if (focusElm)
       
  2904 						this.selection.selectNode(focusElm, false);
       
  2905 				}
       
  2906 
       
  2907 				this.getDoc().execCommand(command, user_interface, value);
       
  2908 
       
  2909 				tinyMCE.isGecko && this.getSel().collapseToEnd();
       
  2910 
       
  2911 				tinyMCE.triggerNodeChange();
       
  2912 
       
  2913 				return true;
       
  2914 
       
  2915 			case "InsertUnorderedList":
       
  2916 			case "InsertOrderedList":
       
  2917 				this.getDoc().execCommand(command, user_interface, value);
       
  2918 				tinyMCE.triggerNodeChange();
       
  2919 				break;
       
  2920 
       
  2921 			case "Strikethrough":
       
  2922 				this.getDoc().execCommand(command, user_interface, value);
       
  2923 				tinyMCE.triggerNodeChange();
       
  2924 				break;
       
  2925 
       
  2926 			case "mceSelectNode":
       
  2927 				this.selection.selectNode(value);
       
  2928 				tinyMCE.triggerNodeChange();
       
  2929 				tinyMCE.selectedNode = value;
       
  2930 				break;
       
  2931 
       
  2932 			case "FormatBlock":
       
  2933 				if (value == null || value == "") {
       
  2934 					var elm = tinyMCE.getParentElement(this.getFocusElement(), "p,div,h1,h2,h3,h4,h5,h6,pre,address,blockquote,dt,dl,dd,samp");
       
  2935 
       
  2936 					if (elm)
       
  2937 						this.execCommand("mceRemoveNode", false, elm);
       
  2938 				} else {
       
  2939 					if (!this.cleanup.isValid(value))
       
  2940 						return true;
       
  2941 
       
  2942 					if (tinyMCE.isGecko && new RegExp('<(div|blockquote|code|dt|dd|dl|samp)>', 'gi').test(value))
       
  2943 						value = value.replace(/[^a-z]/gi, '');
       
  2944 
       
  2945 					if (tinyMCE.isIE && new RegExp('blockquote|code|samp', 'gi').test(value)) {
       
  2946 						var b = this.selection.getBookmark();
       
  2947 						this.getDoc().execCommand("FormatBlock", false, '<p>');
       
  2948 						tinyMCE.renameElement(tinyMCE.getParentBlockElement(this.getFocusElement()), value);
       
  2949 						this.selection.moveToBookmark(b);
       
  2950 					} else
       
  2951 						this.getDoc().execCommand("FormatBlock", false, value);
       
  2952 				}
       
  2953 
       
  2954 				tinyMCE.triggerNodeChange();
       
  2955 
       
  2956 				break;
       
  2957 
       
  2958 			case "mceRemoveNode":
       
  2959 				if (!value)
       
  2960 					value = tinyMCE.getParentElement(this.getFocusElement());
       
  2961 
       
  2962 				if (tinyMCE.isIE) {
       
  2963 					value.outerHTML = value.innerHTML;
       
  2964 				} else {
       
  2965 					var rng = value.ownerDocument.createRange();
       
  2966 					rng.setStartBefore(value);
       
  2967 					rng.setEndAfter(value);
       
  2968 					rng.deleteContents();
       
  2969 					rng.insertNode(rng.createContextualFragment(value.innerHTML));
       
  2970 				}
       
  2971 
       
  2972 				tinyMCE.triggerNodeChange();
       
  2973 
       
  2974 				break;
       
  2975 
       
  2976 			case "mceSelectNodeDepth":
       
  2977 				var parentNode = this.getFocusElement();
       
  2978 				for (var i=0; parentNode; i++) {
       
  2979 					if (parentNode.nodeName.toLowerCase() == "body")
       
  2980 						break;
       
  2981 
       
  2982 					if (parentNode.nodeName.toLowerCase() == "#text") {
       
  2983 						i--;
       
  2984 						parentNode = parentNode.parentNode;
       
  2985 						continue;
       
  2986 					}
       
  2987 
       
  2988 					if (i == value) {
       
  2989 						this.selection.selectNode(parentNode, false);
       
  2990 						tinyMCE.triggerNodeChange();
       
  2991 						tinyMCE.selectedNode = parentNode;
       
  2992 						return;
       
  2993 					}
       
  2994 
       
  2995 					parentNode = parentNode.parentNode;
       
  2996 				}
       
  2997 
       
  2998 				break;
       
  2999 
       
  3000 			case "mceSetStyleInfo":
       
  3001 			case "SetStyleInfo":
       
  3002 				var rng = this.getRng();
       
  3003 				var sel = this.getSel();
       
  3004 				var scmd = value['command'];
       
  3005 				var sname = value['name'];
       
  3006 				var svalue = value['value'] == null ? '' : value['value'];
       
  3007 				//var svalue = value['value'] == null ? '' : value['value'];
       
  3008 				var wrapper = value['wrapper'] ? value['wrapper'] : "span";
       
  3009 				var parentElm = null;
       
  3010 				var invalidRe = new RegExp("^BODY|HTML$", "g");
       
  3011 				var invalidParentsRe = tinyMCE.settings['merge_styles_invalid_parents'] != '' ? new RegExp(tinyMCE.settings['merge_styles_invalid_parents'], "gi") : null;
       
  3012 
       
  3013 				// Whole element selected check
       
  3014 				if (tinyMCE.isIE) {
       
  3015 					// Control range
       
  3016 					if (rng.item)
       
  3017 						parentElm = rng.item(0);
       
  3018 					else {
       
  3019 						var pelm = rng.parentElement();
       
  3020 						var prng = doc.selection.createRange();
       
  3021 						prng.moveToElementText(pelm);
       
  3022 
       
  3023 						if (rng.htmlText == prng.htmlText || rng.boundingWidth == 0) {
       
  3024 							if (invalidParentsRe == null || !invalidParentsRe.test(pelm.nodeName))
       
  3025 								parentElm = pelm;
       
  3026 						}
       
  3027 					}
       
  3028 				} else {
       
  3029 					var felm = this.getFocusElement();
       
  3030 					if (sel.isCollapsed || (new RegExp('td|tr|tbody|table', 'gi').test(felm.nodeName) && sel.anchorNode == felm.parentNode))
       
  3031 						parentElm = felm;
       
  3032 				}
       
  3033 
       
  3034 				// Whole element selected
       
  3035 				if (parentElm && !invalidRe.test(parentElm.nodeName)) {
       
  3036 					if (scmd == "setstyle")
       
  3037 						tinyMCE.setStyleAttrib(parentElm, sname, svalue);
       
  3038 
       
  3039 					if (scmd == "setattrib")
       
  3040 						tinyMCE.setAttrib(parentElm, sname, svalue);
       
  3041 
       
  3042 					if (scmd == "removeformat") {
       
  3043 						parentElm.style.cssText = '';
       
  3044 						tinyMCE.setAttrib(parentElm, 'class', '');
       
  3045 					}
       
  3046 
       
  3047 					// Remove style/attribs from all children
       
  3048 					var ch = tinyMCE.getNodeTree(parentElm, new Array(), 1);
       
  3049 					for (var z=0; z<ch.length; z++) {
       
  3050 						if (ch[z] == parentElm)
       
  3051 							continue;
       
  3052 
       
  3053 						if (scmd == "setstyle")
       
  3054 							tinyMCE.setStyleAttrib(ch[z], sname, '');
       
  3055 
       
  3056 						if (scmd == "setattrib")
       
  3057 							tinyMCE.setAttrib(ch[z], sname, '');
       
  3058 
       
  3059 						if (scmd == "removeformat") {
       
  3060 							ch[z].style.cssText = '';
       
  3061 							tinyMCE.setAttrib(ch[z], 'class', '');
       
  3062 						}
       
  3063 					}
       
  3064 				} else {
       
  3065 					this._setUseCSS(false); // Bug in FF when running in fullscreen
       
  3066 					doc.execCommand("FontName", false, "#mce_temp_font#");
       
  3067 					var elementArray = tinyMCE.getElementsByAttributeValue(this.getBody(), "font", "face", "#mce_temp_font#");
       
  3068 
       
  3069 					// Change them all
       
  3070 					for (var x=0; x<elementArray.length; x++) {
       
  3071 						elm = elementArray[x];
       
  3072 						if (elm) {
       
  3073 							var spanElm = doc.createElement(wrapper);
       
  3074 
       
  3075 							if (scmd == "setstyle")
       
  3076 								tinyMCE.setStyleAttrib(spanElm, sname, svalue);
       
  3077 
       
  3078 							if (scmd == "setattrib")
       
  3079 								tinyMCE.setAttrib(spanElm, sname, svalue);
       
  3080 
       
  3081 							if (scmd == "removeformat") {
       
  3082 								spanElm.style.cssText = '';
       
  3083 								tinyMCE.setAttrib(spanElm, 'class', '');
       
  3084 							}
       
  3085 
       
  3086 							if (elm.hasChildNodes()) {
       
  3087 								for (var i=0; i<elm.childNodes.length; i++)
       
  3088 									spanElm.appendChild(elm.childNodes[i].cloneNode(true));
       
  3089 							}
       
  3090 
       
  3091 							spanElm.setAttribute("mce_new", "true");
       
  3092 							elm.parentNode.replaceChild(spanElm, elm);
       
  3093 
       
  3094 							// Remove style/attribs from all children
       
  3095 							var ch = tinyMCE.getNodeTree(spanElm, new Array(), 1);
       
  3096 							for (var z=0; z<ch.length; z++) {
       
  3097 								if (ch[z] == spanElm)
       
  3098 									continue;
       
  3099 
       
  3100 								if (scmd == "setstyle")
       
  3101 									tinyMCE.setStyleAttrib(ch[z], sname, '');
       
  3102 
       
  3103 								if (scmd == "setattrib")
       
  3104 									tinyMCE.setAttrib(ch[z], sname, '');
       
  3105 
       
  3106 								if (scmd == "removeformat") {
       
  3107 									ch[z].style.cssText = '';
       
  3108 									tinyMCE.setAttrib(ch[z], 'class', '');
       
  3109 								}
       
  3110 							}
       
  3111 						}
       
  3112 					}
       
  3113 				}
       
  3114 
       
  3115 				// Cleaup wrappers
       
  3116 				var nodes = doc.getElementsByTagName(wrapper);
       
  3117 				for (var i=nodes.length-1; i>=0; i--) {
       
  3118 					var elm = nodes[i];
       
  3119 					var isNew = tinyMCE.getAttrib(elm, "mce_new") == "true";
       
  3120 
       
  3121 					elm.removeAttribute("mce_new");
       
  3122 
       
  3123 					// Is only child a element
       
  3124 					if (elm.childNodes && elm.childNodes.length == 1 && elm.childNodes[0].nodeType == 1) {
       
  3125 						//tinyMCE.debug("merge1" + isNew);
       
  3126 						this._mergeElements(scmd, elm, elm.childNodes[0], isNew);
       
  3127 						continue;
       
  3128 					}
       
  3129 
       
  3130 					// Is I the only child
       
  3131 					if (elm.parentNode.childNodes.length == 1 && !invalidRe.test(elm.nodeName) && !invalidRe.test(elm.parentNode.nodeName)) {
       
  3132 						//tinyMCE.debug("merge2" + isNew + "," + elm.nodeName + "," + elm.parentNode.nodeName);
       
  3133 						if (invalidParentsRe == null || !invalidParentsRe.test(elm.parentNode.nodeName))
       
  3134 							this._mergeElements(scmd, elm.parentNode, elm, false);
       
  3135 					}
       
  3136 				}
       
  3137 
       
  3138 				// Remove empty wrappers
       
  3139 				var nodes = doc.getElementsByTagName(wrapper);
       
  3140 				for (var i=nodes.length-1; i>=0; i--) {
       
  3141 					var elm = nodes[i];
       
  3142 					var isEmpty = true;
       
  3143 
       
  3144 					// Check if it has any attribs
       
  3145 					var tmp = doc.createElement("body");
       
  3146 					tmp.appendChild(elm.cloneNode(false));
       
  3147 
       
  3148 					// Is empty span, remove it
       
  3149 					tmp.innerHTML = tmp.innerHTML.replace(new RegExp('style=""|class=""', 'gi'), '');
       
  3150 					//tinyMCE.debug(tmp.innerHTML);
       
  3151 					if (new RegExp('<span>', 'gi').test(tmp.innerHTML)) {
       
  3152 						for (var x=0; x<elm.childNodes.length; x++) {
       
  3153 							if (elm.parentNode != null)
       
  3154 								elm.parentNode.insertBefore(elm.childNodes[x].cloneNode(true), elm);
       
  3155 						}
       
  3156 
       
  3157 						elm.parentNode.removeChild(elm);
       
  3158 					}
       
  3159 				}
       
  3160 
       
  3161 				// Re add the visual aids
       
  3162 				if (scmd == "removeformat")
       
  3163 					tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
       
  3164 
       
  3165 				tinyMCE.triggerNodeChange();
       
  3166 
       
  3167 				break;
       
  3168 
       
  3169 			case "FontName":
       
  3170 				if (value == null) {
       
  3171 					var s = this.getSel();
       
  3172 
       
  3173 					// Find font and select it
       
  3174 					if (tinyMCE.isGecko && s.isCollapsed) {
       
  3175 						var f = tinyMCE.getParentElement(this.getFocusElement(), "font");
       
  3176 
       
  3177 						if (f != null)
       
  3178 							this.selection.selectNode(f, false);
       
  3179 					}
       
  3180 
       
  3181 					// Remove format
       
  3182 					this.getDoc().execCommand("RemoveFormat", false, null);
       
  3183 
       
  3184 					// Collapse range if font was found
       
  3185 					if (f != null && tinyMCE.isGecko) {
       
  3186 						var r = this.getRng().cloneRange();
       
  3187 						r.collapse(true);
       
  3188 						s.removeAllRanges();
       
  3189 						s.addRange(r);
       
  3190 					}
       
  3191 				} else
       
  3192 					this.getDoc().execCommand('FontName', false, value);
       
  3193 
       
  3194 				if (tinyMCE.isGecko)
       
  3195 					window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
       
  3196 
       
  3197 				return;
       
  3198 
       
  3199 			case "FontSize":
       
  3200 				this.getDoc().execCommand('FontSize', false, value);
       
  3201 
       
  3202 				if (tinyMCE.isGecko)
       
  3203 					window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
       
  3204 
       
  3205 				return;
       
  3206 
       
  3207 			case "forecolor":
       
  3208 				value = value == null ? this.foreColor : value;
       
  3209 				value = tinyMCE.trim(value);
       
  3210 				value = value.charAt(0) != '#' ? (isNaN('0x' + value) ? value : '#' + value) : value;
       
  3211 
       
  3212 				this.foreColor = value;
       
  3213 				this.getDoc().execCommand('forecolor', false, value);
       
  3214 				break;
       
  3215 
       
  3216 			case "HiliteColor":
       
  3217 				value = value == null ? this.backColor : value;
       
  3218 				value = tinyMCE.trim(value);
       
  3219 				value = value.charAt(0) != '#' ? (isNaN('0x' + value) ? value : '#' + value) : value;
       
  3220 				this.backColor = value;
       
  3221 
       
  3222 				if (tinyMCE.isGecko) {
       
  3223 					this._setUseCSS(true);
       
  3224 					this.getDoc().execCommand('hilitecolor', false, value);
       
  3225 					this._setUseCSS(false);
       
  3226 				} else
       
  3227 					this.getDoc().execCommand('BackColor', false, value);
       
  3228 				break;
       
  3229 
       
  3230 			case "Cut":
       
  3231 			case "Copy":
       
  3232 			case "Paste":
       
  3233 				var cmdFailed = false;
       
  3234 
       
  3235 				// Try executing command
       
  3236 				eval('try {this.getDoc().execCommand(command, user_interface, value);} catch (e) {cmdFailed = true;}');
       
  3237 
       
  3238 				if (tinyMCE.isOpera && cmdFailed)
       
  3239 					alert('Currently not supported by your browser, use keyboard shortcuts instead.');
       
  3240 
       
  3241 				// Alert error in gecko if command failed
       
  3242 				if (tinyMCE.isGecko && cmdFailed) {
       
  3243 					// Confirm more info
       
  3244 					if (confirm(tinyMCE.entityDecode(tinyMCE.getLang('lang_clipboard_msg'))))
       
  3245 						window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal');
       
  3246 
       
  3247 					return;
       
  3248 				} else
       
  3249 					tinyMCE.triggerNodeChange();
       
  3250 			break;
       
  3251 
       
  3252 			case "mceSetContent":
       
  3253 				if (!value)
       
  3254 					value = "";
       
  3255 
       
  3256 				// Call custom cleanup code
       
  3257 				value = tinyMCE.storeAwayURLs(value);
       
  3258 				value = tinyMCE._customCleanup(this, "insert_to_editor", value);
       
  3259 
       
  3260 				if (this.getBody().nodeName == 'BODY')
       
  3261 					tinyMCE._setHTML(doc, value);
       
  3262 				else
       
  3263 					this.getBody().innerHTML = value;
       
  3264 
       
  3265 				tinyMCE.setInnerHTML(this.getBody(), tinyMCE._cleanupHTML(this, doc, this.settings, this.getBody(), false, false, false, true));
       
  3266 				tinyMCE.convertAllRelativeURLs(this.getBody());
       
  3267 
       
  3268 				// Cleanup any mess left from storyAwayURLs
       
  3269 				tinyMCE._removeInternal(this.getBody());
       
  3270 
       
  3271 				// When editing always use fonts internaly
       
  3272 				if (tinyMCE.getParam("convert_fonts_to_spans"))
       
  3273 					tinyMCE.convertSpansToFonts(doc);
       
  3274 
       
  3275 				tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
       
  3276 				tinyMCE._setEventsEnabled(this.getBody(), false);
       
  3277 				return true;
       
  3278 
       
  3279 			case "mceCleanup":
       
  3280 				var b = this.selection.getBookmark();
       
  3281 				tinyMCE._setHTML(this.contentDocument, this.getBody().innerHTML);
       
  3282 				tinyMCE.setInnerHTML(this.getBody(), tinyMCE._cleanupHTML(this, this.contentDocument, this.settings, this.getBody(), this.visualAid));
       
  3283 				tinyMCE.convertAllRelativeURLs(doc.body);
       
  3284 
       
  3285 				// When editing always use fonts internaly
       
  3286 				if (tinyMCE.getParam("convert_fonts_to_spans"))
       
  3287 					tinyMCE.convertSpansToFonts(doc);
       
  3288 
       
  3289 				tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
       
  3290 				tinyMCE._setEventsEnabled(this.getBody(), false);
       
  3291 				this.repaint();
       
  3292 				this.selection.moveToBookmark(b);
       
  3293 				tinyMCE.triggerNodeChange();
       
  3294 			break;
       
  3295 
       
  3296 			case "mceReplaceContent":
       
  3297 				// Force empty string
       
  3298 				if (!value)
       
  3299 					value = '';
       
  3300 
       
  3301 				this.getWin().focus();
       
  3302 
       
  3303 				var selectedText = "";
       
  3304 
       
  3305 				if (tinyMCE.isIE) {
       
  3306 					var rng = doc.selection.createRange();
       
  3307 					selectedText = rng.text;
       
  3308 				} else
       
  3309 					selectedText = this.getSel().toString();
       
  3310 
       
  3311 				if (selectedText.length > 0) {
       
  3312 					value = tinyMCE.replaceVar(value, "selection", selectedText);
       
  3313 					tinyMCE.execCommand('mceInsertContent', false, value);
       
  3314 				}
       
  3315 
       
  3316 				tinyMCE.triggerNodeChange();
       
  3317 			break;
       
  3318 
       
  3319 			case "mceSetAttribute":
       
  3320 				if (typeof(value) == 'object') {
       
  3321 					var targetElms = (typeof(value['targets']) == "undefined") ? "p,img,span,div,td,h1,h2,h3,h4,h5,h6,pre,address" : value['targets'];
       
  3322 					var targetNode = tinyMCE.getParentElement(this.getFocusElement(), targetElms);
       
  3323 
       
  3324 					if (targetNode) {
       
  3325 						targetNode.setAttribute(value['name'], value['value']);
       
  3326 						tinyMCE.triggerNodeChange();
       
  3327 					}
       
  3328 				}
       
  3329 			break;
       
  3330 
       
  3331 			case "mceSetCSSClass":
       
  3332 				this.execCommand("mceSetStyleInfo", false, {command : "setattrib", name : "class", value : value});
       
  3333 			break;
       
  3334 
       
  3335 			case "mceInsertRawHTML":
       
  3336 				var key = 'tiny_mce_marker';
       
  3337 
       
  3338 				this.execCommand('mceBeginUndoLevel');
       
  3339 
       
  3340 				// Insert marker key
       
  3341 				this.execCommand('mceInsertContent', false, key);
       
  3342 
       
  3343 				// Store away scroll pos
       
  3344 				var scrollX = this.getBody().scrollLeft + this.getDoc().documentElement.scrollLeft;
       
  3345 				var scrollY = this.getBody().scrollTop + this.getDoc().documentElement.scrollTop;
       
  3346 
       
  3347 				// Find marker and replace with RAW HTML
       
  3348 				var html = this.getBody().innerHTML;
       
  3349 				if ((pos = html.indexOf(key)) != -1)
       
  3350 					tinyMCE.setInnerHTML(this.getBody(), html.substring(0, pos) + value + html.substring(pos + key.length));
       
  3351 
       
  3352 				// Restore scoll pos
       
  3353 				this.contentWindow.scrollTo(scrollX, scrollY);
       
  3354 
       
  3355 				this.execCommand('mceEndUndoLevel');
       
  3356 
       
  3357 				break;
       
  3358 
       
  3359 			case "mceInsertContent":
       
  3360 				// Force empty string
       
  3361 				if (!value)
       
  3362 					value = '';
       
  3363 
       
  3364 				var insertHTMLFailed = false;
       
  3365 
       
  3366 				// Removed since it produced problems in IE
       
  3367 				// this.getWin().focus();
       
  3368 
       
  3369 				if (tinyMCE.isGecko || tinyMCE.isOpera) {
       
  3370 					try {
       
  3371 						// Is plain text or HTML, &amp;, &nbsp; etc will be encoded wrong in FF
       
  3372 						if (value.indexOf('<') == -1 && !value.match(/(&#38;|&#160;|&#60;|&#62;)/g)) {
       
  3373 							var r = this.getRng();
       
  3374 							var n = this.getDoc().createTextNode(tinyMCE.entityDecode(value));
       
  3375 							var s = this.getSel();
       
  3376 							var r2 = r.cloneRange();
       
  3377 
       
  3378 							// Insert text at cursor position
       
  3379 							s.removeAllRanges();
       
  3380 							r.deleteContents();
       
  3381 							r.insertNode(n);
       
  3382 
       
  3383 							// Move the cursor to the end of text
       
  3384 							r2.selectNode(n);
       
  3385 							r2.collapse(false);
       
  3386 							s.removeAllRanges();
       
  3387 							s.addRange(r2);
       
  3388 						} else {
       
  3389 							value = tinyMCE.fixGeckoBaseHREFBug(1, this.getDoc(), value);
       
  3390 							this.getDoc().execCommand('inserthtml', false, value);
       
  3391 							tinyMCE.fixGeckoBaseHREFBug(2, this.getDoc(), value);
       
  3392 						}
       
  3393 					} catch (ex) {
       
  3394 						insertHTMLFailed = true;
       
  3395 					}
       
  3396 
       
  3397 					if (!insertHTMLFailed) {
       
  3398 						tinyMCE.triggerNodeChange();
       
  3399 						return;
       
  3400 					}
       
  3401 				}
       
  3402 
       
  3403 				if (!tinyMCE.isIE) {
       
  3404 					var isHTML = value.indexOf('<') != -1;
       
  3405 					var sel = this.getSel();
       
  3406 					var rng = this.getRng();
       
  3407 
       
  3408 					if (isHTML) {
       
  3409 						if (tinyMCE.isSafari) {
       
  3410 							var tmpRng = this.getDoc().createRange();
       
  3411 
       
  3412 							tmpRng.setStart(this.getBody(), 0);
       
  3413 							tmpRng.setEnd(this.getBody(), 0);
       
  3414 
       
  3415 							value = tmpRng.createContextualFragment(value);
       
  3416 						} else
       
  3417 							value = rng.createContextualFragment(value);
       
  3418 					} else {
       
  3419 						// Setup text node
       
  3420 						var el = document.createElement("div");
       
  3421 						el.innerHTML = value;
       
  3422 						value = el.firstChild.nodeValue;
       
  3423 						value = doc.createTextNode(value);
       
  3424 					}
       
  3425 
       
  3426 					// Insert plain text in Safari
       
  3427 					if (tinyMCE.isSafari && !isHTML) {
       
  3428 						this.execCommand('InsertText', false, value.nodeValue);
       
  3429 						tinyMCE.triggerNodeChange();
       
  3430 						return true;
       
  3431 					} else if (tinyMCE.isSafari && isHTML) {
       
  3432 						rng.deleteContents();
       
  3433 						rng.insertNode(value);
       
  3434 						tinyMCE.triggerNodeChange();
       
  3435 						return true;
       
  3436 					}
       
  3437 
       
  3438 					rng.deleteContents();
       
  3439 
       
  3440 					// If target node is text do special treatment, (Mozilla 1.3 fix)
       
  3441 					if (rng.startContainer.nodeType == 3) {
       
  3442 						var node = rng.startContainer.splitText(rng.startOffset);
       
  3443 						node.parentNode.insertBefore(value, node); 
       
  3444 					} else
       
  3445 						rng.insertNode(value);
       
  3446 
       
  3447 					if (!isHTML) {
       
  3448 						// Removes weird selection trails
       
  3449 						sel.selectAllChildren(doc.body);
       
  3450 						sel.removeAllRanges();
       
  3451 
       
  3452 						// Move cursor to end of content
       
  3453 						var rng = doc.createRange();
       
  3454 
       
  3455 						rng.selectNode(value);
       
  3456 						rng.collapse(false);
       
  3457 
       
  3458 						sel.addRange(rng);
       
  3459 					} else
       
  3460 						rng.collapse(false);
       
  3461 
       
  3462 					tinyMCE.fixGeckoBaseHREFBug(2, this.getDoc(), value);
       
  3463 				} else {
       
  3464 					var rng = doc.selection.createRange(), tmpRng = null;
       
  3465 					var c = value.indexOf('<!--') != -1;
       
  3466 
       
  3467 					// Fix comment bug, add tag before comments
       
  3468 					if (c)
       
  3469 						value = tinyMCE.uniqueTag + value;
       
  3470 
       
  3471 					//	tmpRng = rng.duplicate(); // Store away range (Fixes Undo bookmark bug in IE)
       
  3472 
       
  3473 					if (rng.item)
       
  3474 						rng.item(0).outerHTML = value;
       
  3475 					else
       
  3476 						rng.pasteHTML(value);
       
  3477 
       
  3478 					//if (tmpRng)
       
  3479 					//	tmpRng.select(); // Restore range  (Fixes Undo bookmark bug in IE)
       
  3480 
       
  3481 					// Remove unique tag
       
  3482 					if (c) {
       
  3483 						var e = this.getDoc().getElementById('mceTMPElement');
       
  3484 						e.parentNode.removeChild(e);
       
  3485 					}
       
  3486 				}
       
  3487 
       
  3488 				tinyMCE.execCommand("mceAddUndoLevel");
       
  3489 				tinyMCE.triggerNodeChange();
       
  3490 			break;
       
  3491 
       
  3492 			case "mceStartTyping":
       
  3493 				if (tinyMCE.settings['custom_undo_redo'] && this.undoRedo.typingUndoIndex == -1) {
       
  3494 					this.undoRedo.typingUndoIndex = this.undoRedo.undoIndex;
       
  3495 					tinyMCE.typingUndoIndex = tinyMCE.undoIndex;
       
  3496 					this.execCommand('mceAddUndoLevel');
       
  3497 				}
       
  3498 				break;
       
  3499 
       
  3500 			case "mceEndTyping":
       
  3501 				if (tinyMCE.settings['custom_undo_redo'] && this.undoRedo.typingUndoIndex != -1) {
       
  3502 					this.execCommand('mceAddUndoLevel');
       
  3503 					this.undoRedo.typingUndoIndex = -1;
       
  3504 				}
       
  3505 
       
  3506 				tinyMCE.typingUndoIndex = -1;
       
  3507 				break;
       
  3508 
       
  3509 			case "mceBeginUndoLevel":
       
  3510 				this.undoRedoLevel = false;
       
  3511 				break;
       
  3512 
       
  3513 			case "mceEndUndoLevel":
       
  3514 				this.undoRedoLevel = true;
       
  3515 				this.execCommand('mceAddUndoLevel');
       
  3516 				break;
       
  3517 
       
  3518 			case "mceAddUndoLevel":
       
  3519 				if (tinyMCE.settings['custom_undo_redo'] && this.undoRedoLevel) {
       
  3520 					if (this.undoRedo.add())
       
  3521 						tinyMCE.triggerNodeChange(false);
       
  3522 				}
       
  3523 				break;
       
  3524 
       
  3525 			case "Undo":
       
  3526 				if (tinyMCE.settings['custom_undo_redo']) {
       
  3527 					tinyMCE.execCommand("mceEndTyping");
       
  3528 					this.undoRedo.undo();
       
  3529 					tinyMCE.triggerNodeChange();
       
  3530 				} else
       
  3531 					this.getDoc().execCommand(command, user_interface, value);
       
  3532 				break;
       
  3533 
       
  3534 			case "Redo":
       
  3535 				if (tinyMCE.settings['custom_undo_redo']) {
       
  3536 					tinyMCE.execCommand("mceEndTyping");
       
  3537 					this.undoRedo.redo();
       
  3538 					tinyMCE.triggerNodeChange();
       
  3539 				} else
       
  3540 					this.getDoc().execCommand(command, user_interface, value);
       
  3541 				break;
       
  3542 
       
  3543 			case "mceToggleVisualAid":
       
  3544 				this.visualAid = !this.visualAid;
       
  3545 				tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
       
  3546 				tinyMCE.triggerNodeChange();
       
  3547 				break;
       
  3548 
       
  3549 			case "Indent":
       
  3550 				this.getDoc().execCommand(command, user_interface, value);
       
  3551 				tinyMCE.triggerNodeChange();
       
  3552 
       
  3553 				if (tinyMCE.isIE) {
       
  3554 					var n = tinyMCE.getParentElement(this.getFocusElement(), "blockquote");
       
  3555 					do {
       
  3556 						if (n && n.nodeName == "BLOCKQUOTE") {
       
  3557 							n.removeAttribute("dir");
       
  3558 							n.removeAttribute("style");
       
  3559 						}
       
  3560 					} while (n != null && (n = n.parentNode) != null);
       
  3561 				}
       
  3562 				break;
       
  3563 
       
  3564 			case "RemoveFormat":
       
  3565 			case "removeformat":
       
  3566 				var text = this.selection.getSelectedText();
       
  3567 
       
  3568 				if (tinyMCE.isOpera) {
       
  3569 					this.getDoc().execCommand("RemoveFormat", false, null);
       
  3570 					return;
       
  3571 				}
       
  3572 
       
  3573 				if (tinyMCE.isIE) {
       
  3574 					try {
       
  3575 						var rng = doc.selection.createRange();
       
  3576 						rng.execCommand("RemoveFormat", false, null);
       
  3577 					} catch (e) {
       
  3578 						// Do nothing
       
  3579 					}
       
  3580 
       
  3581 					this.execCommand("mceSetStyleInfo", false, {command : "removeformat"});
       
  3582 				} else {
       
  3583 					this.getDoc().execCommand(command, user_interface, value);
       
  3584 
       
  3585 					this.execCommand("mceSetStyleInfo", false, {command : "removeformat"});
       
  3586 				}
       
  3587 
       
  3588 				// Remove class
       
  3589 				if (text.length == 0)
       
  3590 					this.execCommand("mceSetCSSClass", false, "");
       
  3591 
       
  3592 				tinyMCE.triggerNodeChange();
       
  3593 				break;
       
  3594 
       
  3595 			default:
       
  3596 				this.getDoc().execCommand(command, user_interface, value);
       
  3597 
       
  3598 				if (tinyMCE.isGecko)
       
  3599 					window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
       
  3600 				else
       
  3601 					tinyMCE.triggerNodeChange();
       
  3602 		}
       
  3603 
       
  3604 		// Add undo level after modification
       
  3605 		if (command != "mceAddUndoLevel" && command != "Undo" && command != "Redo" && command != "mceStartTyping" && command != "mceEndTyping")
       
  3606 			tinyMCE.execCommand("mceAddUndoLevel");
       
  3607 	},
       
  3608 
       
  3609 	queryCommandValue : function(c) {
       
  3610 		try {
       
  3611 			return this.getDoc().queryCommandValue(c);
       
  3612 		} catch (e) {
       
  3613 			return null;
       
  3614 		}
       
  3615 	},
       
  3616 
       
  3617 	queryCommandState : function(c) {
       
  3618 		return this.getDoc().queryCommandState(c);
       
  3619 	},
       
  3620 
       
  3621 	_onAdd : function(replace_element, form_element_name, target_document) {
       
  3622 		var hc, th, to, editorTemplate;
       
  3623 
       
  3624 		th = this.settings['theme'];
       
  3625 		to = tinyMCE.themes[th];
       
  3626 
       
  3627 		var targetDoc = target_document ? target_document : document;
       
  3628 
       
  3629 		this.targetDoc = targetDoc;
       
  3630 
       
  3631 		tinyMCE.themeURL = tinyMCE.baseURL + "/themes/" + this.settings['theme'];
       
  3632 		this.settings['themeurl'] = tinyMCE.themeURL;
       
  3633 
       
  3634 		if (!replace_element) {
       
  3635 			alert("Error: Could not find the target element.");
       
  3636 			return false;
       
  3637 		}
       
  3638 
       
  3639 		if (to.getEditorTemplate)
       
  3640 			editorTemplate = to.getEditorTemplate(this.settings, this.editorId);
       
  3641 
       
  3642 		var deltaWidth = editorTemplate['delta_width'] ? editorTemplate['delta_width'] : 0;
       
  3643 		var deltaHeight = editorTemplate['delta_height'] ? editorTemplate['delta_height'] : 0;
       
  3644 		var html = '<span id="' + this.editorId + '_parent" class="mceEditorContainer">' + editorTemplate['html'];
       
  3645 
       
  3646 		html = tinyMCE.replaceVar(html, "editor_id", this.editorId);
       
  3647 		this.settings['default_document'] = tinyMCE.baseURL + "/blank.htm";
       
  3648 
       
  3649 		this.settings['old_width'] = this.settings['width'];
       
  3650 		this.settings['old_height'] = this.settings['height'];
       
  3651 
       
  3652 		// Set default width, height
       
  3653 		if (this.settings['width'] == -1)
       
  3654 			this.settings['width'] = replace_element.offsetWidth;
       
  3655 
       
  3656 		if (this.settings['height'] == -1)
       
  3657 			this.settings['height'] = replace_element.offsetHeight;
       
  3658 
       
  3659 		// Try the style width
       
  3660 		if (this.settings['width'] == 0)
       
  3661 			this.settings['width'] = replace_element.style.width;
       
  3662 
       
  3663 		// Try the style height
       
  3664 		if (this.settings['height'] == 0)
       
  3665 			this.settings['height'] = replace_element.style.height; 
       
  3666 
       
  3667 		// If no width/height then default to 320x240, better than nothing
       
  3668 		if (this.settings['width'] == 0)
       
  3669 			this.settings['width'] = 320;
       
  3670 
       
  3671 		if (this.settings['height'] == 0)
       
  3672 			this.settings['height'] = 240;
       
  3673 
       
  3674 		this.settings['area_width'] = parseInt(this.settings['width']);
       
  3675 		this.settings['area_height'] = parseInt(this.settings['height']);
       
  3676 		this.settings['area_width'] += deltaWidth;
       
  3677 		this.settings['area_height'] += deltaHeight;
       
  3678 
       
  3679 		this.settings['width_style'] = "" + this.settings['width'];
       
  3680 		this.settings['height_style'] = "" + this.settings['height'];
       
  3681 
       
  3682 		// Special % handling
       
  3683 		if (("" + this.settings['width']).indexOf('%') != -1)
       
  3684 			this.settings['area_width'] = "100%";
       
  3685 		else
       
  3686 			this.settings['width_style'] += 'px';
       
  3687 
       
  3688 		if (("" + this.settings['height']).indexOf('%') != -1)
       
  3689 			this.settings['area_height'] = "100%";
       
  3690 		else
       
  3691 			this.settings['height_style'] += 'px';
       
  3692 
       
  3693 		if (("" + replace_element.style.width).indexOf('%') != -1) {
       
  3694 			this.settings['width'] = replace_element.style.width;
       
  3695 			this.settings['area_width'] = "100%";
       
  3696 			this.settings['width_style'] = "100%";
       
  3697 		}
       
  3698 
       
  3699 		if (("" + replace_element.style.height).indexOf('%') != -1) {
       
  3700 			this.settings['height'] = replace_element.style.height;
       
  3701 			this.settings['area_height'] = "100%";
       
  3702 			this.settings['height_style'] = "100%";
       
  3703 		}
       
  3704 
       
  3705 		html = tinyMCE.applyTemplate(html);
       
  3706 
       
  3707 		this.settings['width'] = this.settings['old_width'];
       
  3708 		this.settings['height'] = this.settings['old_height'];
       
  3709 
       
  3710 		this.visualAid = this.settings['visual'];
       
  3711 		this.formTargetElementId = form_element_name;
       
  3712 
       
  3713 		// Get replace_element contents
       
  3714 		if (replace_element.nodeName == "TEXTAREA" || replace_element.nodeName == "INPUT")
       
  3715 			this.startContent = replace_element.value;
       
  3716 		else
       
  3717 			this.startContent = replace_element.innerHTML;
       
  3718 
       
  3719 		// If not text area or input
       
  3720 		if (replace_element.nodeName != "TEXTAREA" && replace_element.nodeName != "INPUT") {
       
  3721 			this.oldTargetElement = replace_element;
       
  3722 
       
  3723 			// Debug mode
       
  3724 			if (tinyMCE.settings['debug']) {
       
  3725 				hc = '<textarea wrap="off" id="' + form_element_name + '" name="' + form_element_name + '" cols="100" rows="15"></textarea>';
       
  3726 			} else {
       
  3727 				hc = '<input type="hidden" id="' + form_element_name + '" name="' + form_element_name + '" />';
       
  3728 				this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline');
       
  3729 				this.oldTargetElement.style.display = "none";
       
  3730 			}
       
  3731 
       
  3732 			html += '</span>';
       
  3733 
       
  3734 			if (tinyMCE.isGecko)
       
  3735 				html = hc + html;
       
  3736 			else
       
  3737 				html += hc;
       
  3738 
       
  3739 			// Output HTML and set editable
       
  3740 			if (tinyMCE.isGecko) {
       
  3741 				var rng = replace_element.ownerDocument.createRange();
       
  3742 				rng.setStartBefore(replace_element);
       
  3743 
       
  3744 				var fragment = rng.createContextualFragment(html);
       
  3745 				tinyMCE.insertAfter(fragment, replace_element);
       
  3746 			} else
       
  3747 				replace_element.insertAdjacentHTML("beforeBegin", html);
       
  3748 		} else {
       
  3749 			html += '</span>';
       
  3750 
       
  3751 			// Just hide the textarea element
       
  3752 			this.oldTargetElement = replace_element;
       
  3753 
       
  3754 			if (!tinyMCE.settings['debug']) {
       
  3755 				this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline');
       
  3756 				this.oldTargetElement.style.display = "none";
       
  3757 			}
       
  3758 
       
  3759 			// Output HTML and set editable
       
  3760 			if (tinyMCE.isGecko) {
       
  3761 				var rng = replace_element.ownerDocument.createRange();
       
  3762 				rng.setStartBefore(replace_element);
       
  3763 
       
  3764 				var fragment = rng.createContextualFragment(html);
       
  3765 				tinyMCE.insertAfter(fragment, replace_element);
       
  3766 			} else
       
  3767 				replace_element.insertAdjacentHTML("beforeBegin", html);
       
  3768 		}
       
  3769 
       
  3770 		// Setup iframe
       
  3771 		var dynamicIFrame = false;
       
  3772 		var tElm = targetDoc.getElementById(this.editorId);
       
  3773 
       
  3774 		if (!tinyMCE.isIE) {
       
  3775 			// Node case is preserved in XML strict mode
       
  3776 			if (tElm && (tElm.nodeName == "SPAN" || tElm.nodeName == "span")) {
       
  3777 				tElm = tinyMCE._createIFrame(tElm, targetDoc);
       
  3778 				dynamicIFrame = true;
       
  3779 			}
       
  3780 
       
  3781 			this.targetElement = tElm;
       
  3782 			this.iframeElement = tElm;
       
  3783 			this.contentDocument = tElm.contentDocument;
       
  3784 			this.contentWindow = tElm.contentWindow;
       
  3785 
       
  3786 			//this.getDoc().designMode = "on";
       
  3787 		} else {
       
  3788 			if (tElm && tElm.nodeName == "SPAN")
       
  3789 				tElm = tinyMCE._createIFrame(tElm, targetDoc, targetDoc.parentWindow);
       
  3790 			else
       
  3791 				tElm = targetDoc.frames[this.editorId];
       
  3792 
       
  3793 			this.targetElement = tElm;
       
  3794 			this.iframeElement = targetDoc.getElementById(this.editorId);
       
  3795 
       
  3796 			if (tinyMCE.isOpera) {
       
  3797 				this.contentDocument = this.iframeElement.contentDocument;
       
  3798 				this.contentWindow = this.iframeElement.contentWindow;
       
  3799 				dynamicIFrame = true;
       
  3800 			} else {
       
  3801 				this.contentDocument = tElm.window.document;
       
  3802 				this.contentWindow = tElm.window;
       
  3803 			}
       
  3804 
       
  3805 			this.getDoc().designMode = "on";
       
  3806 		}
       
  3807 
       
  3808 		// Setup base HTML
       
  3809 		var doc = this.contentDocument;
       
  3810 		if (dynamicIFrame) {
       
  3811 			var html = tinyMCE.getParam('doctype') + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + tinyMCE.settings['base_href'] + '" /><title>blank_page</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body class="mceContentBody"></body></html>';
       
  3812 
       
  3813 			try {
       
  3814 				if (!this.isHidden())
       
  3815 					this.getDoc().designMode = "on";
       
  3816 
       
  3817 				doc.open();
       
  3818         //alert('docwrite 3');
       
  3819 				doc.write(html);
       
  3820 				doc.close();
       
  3821 			} catch (e) {
       
  3822 				// Failed Mozilla 1.3
       
  3823 				this.getDoc().location.href = tinyMCE.baseURL + "/blank.htm";
       
  3824 			}
       
  3825 		}
       
  3826 
       
  3827 		// This timeout is needed in MSIE 5.5 for some odd reason
       
  3828 		// it seems that the document.frames isn't initialized yet?
       
  3829 		if (tinyMCE.isIE)
       
  3830 			window.setTimeout("tinyMCE.addEventHandlers(tinyMCE.instances[\"" + this.editorId + "\"]);", 1);
       
  3831 
       
  3832 		// Setup element references
       
  3833 		var parentElm = this.targetDoc.getElementById(this.editorId + '_parent');
       
  3834 		this.formElement = tinyMCE.isGecko ? parentElm.previousSibling : parentElm.nextSibling;
       
  3835 
       
  3836 		tinyMCE.setupContent(this.editorId, true);
       
  3837 
       
  3838 		return true;
       
  3839 	},
       
  3840 
       
  3841 	setBaseHREF : function(u) {
       
  3842 		var h, b, d, nl;
       
  3843 
       
  3844 		d = this.getDoc();
       
  3845 		nl = d.getElementsByTagName("base");
       
  3846 		b = nl.length > 0 ? nl[0] : null;
       
  3847 
       
  3848 		if (!b) {
       
  3849 			nl = d.getElementsByTagName("head");
       
  3850 			h = nl.length > 0 ? nl[0] : null;
       
  3851 
       
  3852 			b = d.createElement("base");
       
  3853 			b.setAttribute('href', u);
       
  3854 			h.appendChild(b);
       
  3855 		} else {
       
  3856 			if (u == "" || u == null)
       
  3857 				b.parentNode.removeChild(b);
       
  3858 			else
       
  3859 				b.setAttribute('href', u);
       
  3860 		}
       
  3861 	},
       
  3862 
       
  3863 	getHTML : function(r) {
       
  3864 		var h, d = this.getDoc(), b = this.getBody();
       
  3865 
       
  3866 		if (r)
       
  3867 			return b.innerHTML;
       
  3868 
       
  3869 		h = tinyMCE._cleanupHTML(this, d, this.settings, b, false, true, false, true);
       
  3870 
       
  3871 		if (tinyMCE.getParam("convert_fonts_to_spans"))
       
  3872 			tinyMCE.convertSpansToFonts(d);
       
  3873 
       
  3874 		return h;
       
  3875 	},
       
  3876 
       
  3877 	setHTML : function(h) {
       
  3878 		this.execCommand('mceSetContent', false, h);
       
  3879 		this.repaint();
       
  3880 	},
       
  3881 
       
  3882 	getFocusElement : function() {
       
  3883 		return this.selection.getFocusElement();
       
  3884 	},
       
  3885 
       
  3886 	getSel : function() {
       
  3887 		return this.selection.getSel();
       
  3888 	},
       
  3889 
       
  3890 	getRng : function() {
       
  3891 		return this.selection.getRng();
       
  3892 	},
       
  3893 
       
  3894 	triggerSave : function(skip_cleanup, skip_callback) {
       
  3895 		var e, nl = [], i, s;
       
  3896 
       
  3897 		this.switchSettings();
       
  3898 		s = tinyMCE.settings;
       
  3899 
       
  3900 		// Force hidden tabs visible while serializing
       
  3901 		if (tinyMCE.isRealIE) {
       
  3902 			e = this.iframeElement;
       
  3903 
       
  3904 			do {
       
  3905 				if (e.style && e.style.display == 'none') {
       
  3906 					e.style.display = 'block';
       
  3907 					nl[nl.length] = {elm : e, type : 'style'};
       
  3908 				}
       
  3909 
       
  3910 				if (e.style && s.hidden_tab_class.length > 0 && e.className.indexOf(s.hidden_tab_class) != -1) {
       
  3911 					e.className = s.display_tab_class;
       
  3912 					nl[nl.length] = {elm : e, type : 'class'};
       
  3913 				}
       
  3914 			} while ((e = e.parentNode) != null)
       
  3915 		}
       
  3916 
       
  3917 		tinyMCE.settings['preformatted'] = false;
       
  3918 
       
  3919 		// Default to false
       
  3920 		if (typeof(skip_cleanup) == "undefined")
       
  3921 			skip_cleanup = false;
       
  3922 
       
  3923 		// Default to false
       
  3924 		if (typeof(skip_callback) == "undefined")
       
  3925 			skip_callback = false;
       
  3926 
       
  3927 		tinyMCE._setHTML(this.getDoc(), this.getBody().innerHTML);
       
  3928 
       
  3929 		// Remove visual aids when cleanup is disabled
       
  3930 		if (this.settings['cleanup'] == false) {
       
  3931 			tinyMCE.handleVisualAid(this.getBody(), true, false, this);
       
  3932 			tinyMCE._setEventsEnabled(this.getBody(), true);
       
  3933 		}
       
  3934 
       
  3935 		tinyMCE._customCleanup(this, "submit_content_dom", this.contentWindow.document.body);
       
  3936 		var htm = skip_cleanup ? this.getBody().innerHTML : tinyMCE._cleanupHTML(this, this.getDoc(), this.settings, this.getBody(), tinyMCE.visualAid, true, true);
       
  3937 		htm = tinyMCE._customCleanup(this, "submit_content", htm);
       
  3938 
       
  3939 		if (!skip_callback && tinyMCE.settings['save_callback'] != "")
       
  3940 			var content = eval(tinyMCE.settings['save_callback'] + "(this.formTargetElementId,htm,this.getBody());");
       
  3941 
       
  3942 		// Use callback content if available
       
  3943 		if ((typeof(content) != "undefined") && content != null)
       
  3944 			htm = content;
       
  3945 
       
  3946 		// Replace some weird entities (Bug: #1056343)
       
  3947 		htm = tinyMCE.regexpReplace(htm, "&#40;", "(", "gi");
       
  3948 		htm = tinyMCE.regexpReplace(htm, "&#41;", ")", "gi");
       
  3949 		htm = tinyMCE.regexpReplace(htm, "&#59;", ";", "gi");
       
  3950 		htm = tinyMCE.regexpReplace(htm, "&#34;", "&quot;", "gi");
       
  3951 		htm = tinyMCE.regexpReplace(htm, "&#94;", "^", "gi");
       
  3952 
       
  3953 		if (this.formElement)
       
  3954 			this.formElement.value = htm;
       
  3955 
       
  3956 		if (tinyMCE.isSafari && this.formElement)
       
  3957 			this.formElement.innerText = htm;
       
  3958 
       
  3959 		// Hide them again (tabs in MSIE)
       
  3960 		for (i=0; i<nl.length; i++) {
       
  3961 			if (nl[i].type == 'style')
       
  3962 				nl[i].elm.style.display = 'none';
       
  3963 			else
       
  3964 				nl[i].elm.className = s.hidden_tab_class;
       
  3965 		}
       
  3966 	}
       
  3967 
       
  3968 	};
       
  3969 
       
  3970 /* file:jscripts/tiny_mce/classes/TinyMCE_Cleanup.class.js */
       
  3971 
       
  3972 TinyMCE_Engine.prototype.cleanupHTMLCode = function(s) {
       
  3973 	s = s.replace(new RegExp('<p \\/>', 'gi'), '<p>&nbsp;</p>');
       
  3974 	s = s.replace(new RegExp('<p>\\s*<\\/p>', 'gi'), '<p>&nbsp;</p>');
       
  3975 
       
  3976 	// Fix close BR elements
       
  3977 	s = s.replace(new RegExp('<br>\\s*<\\/br>', 'gi'), '<br />');
       
  3978 
       
  3979 	// Open closed tags like <b/> to <b></b>
       
  3980 	s = s.replace(new RegExp('<(h[1-6]|p|div|address|pre|form|table|li|ol|ul|td|b|font|em|strong|i|strike|u|span|a|ul|ol|li|blockquote)([a-z]*)([^\\\\|>]*)\\/>', 'gi'), '<$1$2$3></$1$2>');
       
  3981 
       
  3982 	// Remove trailing space <b > to <b>
       
  3983 	s = s.replace(new RegExp('\\s+></', 'gi'), '></');
       
  3984 
       
  3985 	// Close tags <img></img> to <img/>
       
  3986 	s = s.replace(new RegExp('<(img|br|hr)([^>]*)><\\/(img|br|hr)>', 'gi'), '<$1$2 />');
       
  3987 
       
  3988 	// Weird MSIE bug, <p><hr /></p> breaks runtime?
       
  3989 	if (tinyMCE.isIE)
       
  3990 		s = s.replace(new RegExp('<p><hr \\/><\\/p>', 'gi'), "<hr>");
       
  3991 
       
  3992 	// Weird tags will make IE error #bug: 1538495
       
  3993 	if (tinyMCE.isIE)
       
  3994 		s = s.replace(/<!(\s*)\/>/g, '');
       
  3995 
       
  3996 	// Convert relative anchors to absolute URLs ex: #something to file.htm#something
       
  3997 	// Removed: Since local document anchors should never be forced absolute example edit.php?id=something
       
  3998 	//if (tinyMCE.getParam('convert_urls'))
       
  3999 	//	s = s.replace(new RegExp('(href=\"{0,1})(\\s*#)', 'gi'), '$1' + tinyMCE.settings['document_base_url'] + "#");
       
  4000 
       
  4001 	return s;
       
  4002 };
       
  4003 
       
  4004 TinyMCE_Engine.prototype.parseStyle = function(str) {
       
  4005 	var ar = new Array();
       
  4006 
       
  4007 	if (str == null)
       
  4008 		return ar;
       
  4009 
       
  4010 	var st = str.split(';');
       
  4011 
       
  4012 	tinyMCE.clearArray(ar);
       
  4013 
       
  4014 	for (var i=0; i<st.length; i++) {
       
  4015 		if (st[i] == '')
       
  4016 			continue;
       
  4017 
       
  4018 		var re = new RegExp('^\\s*([^:]*):\\s*(.*)\\s*$');
       
  4019 		var pa = st[i].replace(re, '$1||$2').split('||');
       
  4020 //tinyMCE.debug(str, pa[0] + "=" + pa[1], st[i].replace(re, '$1||$2'));
       
  4021 		if (pa.length == 2)
       
  4022 			ar[pa[0].toLowerCase()] = pa[1];
       
  4023 	}
       
  4024 
       
  4025 	return ar;
       
  4026 };
       
  4027 
       
  4028 TinyMCE_Engine.prototype.compressStyle = function(ar, pr, sf, res) {
       
  4029 	var box = new Array();
       
  4030 
       
  4031 	box[0] = ar[pr + '-top' + sf];
       
  4032 	box[1] = ar[pr + '-left' + sf];
       
  4033 	box[2] = ar[pr + '-right' + sf];
       
  4034 	box[3] = ar[pr + '-bottom' + sf];
       
  4035 
       
  4036 	for (var i=0; i<box.length; i++) {
       
  4037 		if (box[i] == null)
       
  4038 			return;
       
  4039 
       
  4040 		for (var a=0; a<box.length; a++) {
       
  4041 			if (box[a] != box[i])
       
  4042 				return;
       
  4043 		}
       
  4044 	}
       
  4045 
       
  4046 	// They are all the same
       
  4047 	ar[res] = box[0];
       
  4048 	ar[pr + '-top' + sf] = null;
       
  4049 	ar[pr + '-left' + sf] = null;
       
  4050 	ar[pr + '-right' + sf] = null;
       
  4051 	ar[pr + '-bottom' + sf] = null;
       
  4052 };
       
  4053 
       
  4054 TinyMCE_Engine.prototype.serializeStyle = function(ar) {
       
  4055 	var str = "";
       
  4056 
       
  4057 	// Compress box
       
  4058 	tinyMCE.compressStyle(ar, "border", "", "border");
       
  4059 	tinyMCE.compressStyle(ar, "border", "-width", "border-width");
       
  4060 	tinyMCE.compressStyle(ar, "border", "-color", "border-color");
       
  4061 	tinyMCE.compressStyle(ar, "border", "-style", "border-style");
       
  4062 	tinyMCE.compressStyle(ar, "padding", "", "padding");
       
  4063 	tinyMCE.compressStyle(ar, "margin", "", "margin");
       
  4064 
       
  4065 	for (var key in ar) {
       
  4066 		var val = ar[key];
       
  4067 
       
  4068 		if (typeof(val) == 'function')
       
  4069 			continue;
       
  4070 
       
  4071 		if (key.indexOf('mso-') == 0)
       
  4072 			continue;
       
  4073 
       
  4074 		if (val != null && val != '') {
       
  4075 			val = '' + val; // Force string
       
  4076 
       
  4077 			// Fix style URL
       
  4078 			val = val.replace(new RegExp("url\\(\\'?([^\\']*)\\'?\\)", 'gi'), "url('$1')");
       
  4079 
       
  4080 			// Convert URL
       
  4081 			if (val.indexOf('url(') != -1 && tinyMCE.getParam('convert_urls')) {
       
  4082 				var m = new RegExp("url\\('(.*?)'\\)").exec(val);
       
  4083 
       
  4084 				if (m.length > 1)
       
  4085 					val = "url('" + eval(tinyMCE.getParam('urlconverter_callback') + "(m[1], null, true);") + "')";
       
  4086 			}
       
  4087 
       
  4088 			// Force HEX colors
       
  4089 			if (tinyMCE.getParam("force_hex_style_colors"))
       
  4090 				val = tinyMCE.convertRGBToHex(val, true);
       
  4091 
       
  4092 			val = val.replace(/\"/g, '\'');
       
  4093 
       
  4094 			if (val != "url('')")
       
  4095 				str += key.toLowerCase() + ": " + val + "; ";
       
  4096 		}
       
  4097 	}
       
  4098 
       
  4099 	if (new RegExp('; $').test(str))
       
  4100 		str = str.substring(0, str.length - 2);
       
  4101 
       
  4102 	return str;
       
  4103 };
       
  4104 
       
  4105 TinyMCE_Engine.prototype.convertRGBToHex = function(s, k) {
       
  4106 	if (s.toLowerCase().indexOf('rgb') != -1) {
       
  4107 		var re = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi");
       
  4108 		var rgb = s.replace(re, "$1,$2,$3,$4,$5").split(',');
       
  4109 		if (rgb.length == 5) {
       
  4110 			r = parseInt(rgb[1]).toString(16);
       
  4111 			g = parseInt(rgb[2]).toString(16);
       
  4112 			b = parseInt(rgb[3]).toString(16);
       
  4113 
       
  4114 			r = r.length == 1 ? '0' + r : r;
       
  4115 			g = g.length == 1 ? '0' + g : g;
       
  4116 			b = b.length == 1 ? '0' + b : b;
       
  4117 
       
  4118 			s = "#" + r + g + b;
       
  4119 
       
  4120 			if (k)
       
  4121 				s = rgb[0] + s + rgb[4];
       
  4122 		}
       
  4123 	}
       
  4124 
       
  4125 	return s;
       
  4126 };
       
  4127 
       
  4128 TinyMCE_Engine.prototype.convertHexToRGB = function(s) {
       
  4129 	if (s.indexOf('#') != -1) {
       
  4130 		s = s.replace(new RegExp('[^0-9A-F]', 'gi'), '');
       
  4131 		return "rgb(" + parseInt(s.substring(0, 2), 16) + "," + parseInt(s.substring(2, 4), 16) + "," + parseInt(s.substring(4, 6), 16) + ")";
       
  4132 	}
       
  4133 
       
  4134 	return s;
       
  4135 };
       
  4136 
       
  4137 TinyMCE_Engine.prototype.convertSpansToFonts = function(doc) {
       
  4138 	var sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');
       
  4139 
       
  4140 	/*var h = doc.body.innerHTML;
       
  4141 	h = h.replace(/<span/gi, '<font');
       
  4142 	h = h.replace(/<\/span/gi, '</font');
       
  4143 	tinyMCE.setInnerHTML(doc.body, h);*/
       
  4144 
       
  4145 	var s = tinyMCE.selectElements(doc, 'span,font');
       
  4146 	for (var i=0; i<s.length; i++) {
       
  4147 		var size = tinyMCE.trim(s[i].style.fontSize).toLowerCase();
       
  4148 		var fSize = 0;
       
  4149 
       
  4150 		for (var x=0; x<sizes.length; x++) {
       
  4151 			if (sizes[x] == size) {
       
  4152 				fSize = x + 1;
       
  4153 				break;
       
  4154 			}
       
  4155 		}
       
  4156 
       
  4157 		if (fSize > 0) {
       
  4158 			tinyMCE.setAttrib(s[i], 'size', fSize);
       
  4159 			s[i].style.fontSize = '';
       
  4160 		}
       
  4161 
       
  4162 		var fFace = s[i].style.fontFamily;
       
  4163 		if (fFace != null && fFace != "") {
       
  4164 			tinyMCE.setAttrib(s[i], 'face', fFace);
       
  4165 			s[i].style.fontFamily = '';
       
  4166 		}
       
  4167 
       
  4168 		var fColor = s[i].style.color;
       
  4169 		if (fColor != null && fColor != "") {
       
  4170 			tinyMCE.setAttrib(s[i], 'color', tinyMCE.convertRGBToHex(fColor));
       
  4171 			s[i].style.color = '';
       
  4172 		}
       
  4173 	}
       
  4174 };
       
  4175 
       
  4176 TinyMCE_Engine.prototype.convertFontsToSpans = function(doc) {
       
  4177 	var sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');
       
  4178 
       
  4179 /*	var h = doc.body.innerHTML;
       
  4180 	h = h.replace(/<font/gi, '<span');
       
  4181 	h = h.replace(/<\/font/gi, '</span');
       
  4182 	tinyMCE.setInnerHTML(doc.body, h);*/
       
  4183 
       
  4184 	var fsClasses = tinyMCE.getParam('font_size_classes');
       
  4185 	if (fsClasses != '')
       
  4186 		fsClasses = fsClasses.replace(/\s+/, '').split(',');
       
  4187 	else
       
  4188 		fsClasses = null;
       
  4189 
       
  4190 	var s = tinyMCE.selectElements(doc, 'span,font');
       
  4191 	for (var i=0; i<s.length; i++) {
       
  4192 		var fSize, fFace, fColor;
       
  4193 
       
  4194 		fSize = tinyMCE.getAttrib(s[i], 'size');
       
  4195 		fFace = tinyMCE.getAttrib(s[i], 'face');
       
  4196 		fColor = tinyMCE.getAttrib(s[i], 'color');
       
  4197 
       
  4198 		if (fSize != "") {
       
  4199 			fSize = parseInt(fSize);
       
  4200 
       
  4201 			if (fSize > 0 && fSize < 8) {
       
  4202 				if (fsClasses != null)
       
  4203 					tinyMCE.setAttrib(s[i], 'class', fsClasses[fSize-1]);
       
  4204 				else
       
  4205 					s[i].style.fontSize = sizes[fSize-1];
       
  4206 			}
       
  4207 
       
  4208 			s[i].removeAttribute('size');
       
  4209 		}
       
  4210 
       
  4211 		if (fFace != "") {
       
  4212 			s[i].style.fontFamily = fFace;
       
  4213 			s[i].removeAttribute('face');
       
  4214 		}
       
  4215 
       
  4216 		if (fColor != "") {
       
  4217 			s[i].style.color = fColor;
       
  4218 			s[i].removeAttribute('color');
       
  4219 		}
       
  4220 	}
       
  4221 };
       
  4222 
       
  4223 TinyMCE_Engine.prototype.cleanupAnchors = function(doc) {
       
  4224 	var i, cn, x, an = doc.getElementsByTagName("a");
       
  4225 
       
  4226 	// Loops backwards due to bug #1467987
       
  4227 	for (i=an.length-1; i>=0; i--) {
       
  4228 		if (tinyMCE.getAttrib(an[i], "name") != "" && tinyMCE.getAttrib(an[i], "href") == "") {
       
  4229 			cn = an[i].childNodes;
       
  4230 
       
  4231 			for (x=cn.length-1; x>=0; x--)
       
  4232 				tinyMCE.insertAfter(cn[x], an[i]);
       
  4233 		}
       
  4234 	}
       
  4235 };
       
  4236 
       
  4237 TinyMCE_Engine.prototype.getContent = function(editor_id) {
       
  4238 	if (typeof(editor_id) != "undefined")
       
  4239 		 tinyMCE.getInstanceById(editor_id).select();
       
  4240 
       
  4241 	if (tinyMCE.selectedInstance)
       
  4242 		return tinyMCE.selectedInstance.getHTML();
       
  4243 
       
  4244 	return null;
       
  4245 };
       
  4246 
       
  4247 TinyMCE_Engine.prototype._fixListElements = function(d) {
       
  4248 	var nl, x, a = ['ol', 'ul'], i, n, p, r = new RegExp('^(OL|UL)$'), np;
       
  4249 
       
  4250 	for (x=0; x<a.length; x++) {
       
  4251 		nl = d.getElementsByTagName(a[x]);
       
  4252 
       
  4253 		for (i=0; i<nl.length; i++) {
       
  4254 			n = nl[i];
       
  4255 			p = n.parentNode;
       
  4256 
       
  4257 			if (r.test(p.nodeName)) {
       
  4258 				np = tinyMCE.prevNode(n, 'LI');
       
  4259 
       
  4260 				if (!np) {
       
  4261 					np = d.createElement('li');
       
  4262 					np.innerHTML = '&nbsp;';
       
  4263 					np.appendChild(n);
       
  4264 					p.insertBefore(np, p.firstChild);
       
  4265 				} else
       
  4266 					np.appendChild(n);
       
  4267 			}
       
  4268 		}
       
  4269 	}
       
  4270 };
       
  4271 
       
  4272 TinyMCE_Engine.prototype._fixTables = function(d) {
       
  4273 	var nl, i, n, p, np, x, t;
       
  4274 
       
  4275 	nl = d.getElementsByTagName('table');
       
  4276 	for (i=0; i<nl.length; i++) {
       
  4277 		n = nl[i];
       
  4278 
       
  4279 		if ((p = tinyMCE.getParentElement(n, 'p,h1,h2,h3,h4,h5,h6')) != null) {
       
  4280 			np = p.cloneNode(false);
       
  4281 			np.removeAttribute('id');
       
  4282 
       
  4283 			t = n;
       
  4284 
       
  4285 			while ((n = n.nextSibling))
       
  4286 				np.appendChild(n);
       
  4287 
       
  4288 			tinyMCE.insertAfter(np, p);
       
  4289 			tinyMCE.insertAfter(t, p);
       
  4290 		}
       
  4291 	}
       
  4292 };
       
  4293 
       
  4294 TinyMCE_Engine.prototype._cleanupHTML = function(inst, doc, config, elm, visual, on_save, on_submit, inn) {
       
  4295 	var h, d, t1, t2, t3, t4, t5, c, s, nb;
       
  4296 
       
  4297 	if (!tinyMCE.getParam('cleanup'))
       
  4298 		return elm.innerHTML;
       
  4299 
       
  4300 	on_save = typeof(on_save) == 'undefined' ? false : on_save;
       
  4301 
       
  4302 	c = inst.cleanup;
       
  4303 	s = inst.settings;
       
  4304 	d = c.settings.debug;
       
  4305 
       
  4306 	if (d)
       
  4307 		t1 = new Date().getTime();
       
  4308 
       
  4309 	if (tinyMCE.getParam("convert_fonts_to_spans"))
       
  4310 		tinyMCE.convertFontsToSpans(doc);
       
  4311 
       
  4312 	if (tinyMCE.getParam("fix_list_elements"))
       
  4313 		tinyMCE._fixListElements(doc);
       
  4314 
       
  4315 	if (tinyMCE.getParam("fix_table_elements"))
       
  4316 		tinyMCE._fixTables(doc);
       
  4317 
       
  4318 	// Call custom cleanup code
       
  4319 	tinyMCE._customCleanup(inst, on_save ? "get_from_editor_dom" : "insert_to_editor_dom", doc.body);
       
  4320 
       
  4321 	if (d)
       
  4322 		t2 = new Date().getTime();
       
  4323 
       
  4324 	c.settings.on_save = on_save;
       
  4325 	//for (var i=0; i<100; i++)
       
  4326 
       
  4327 	c.idCount = 0;
       
  4328 	c.serializationId++;
       
  4329 	c.serializedNodes = new Array();
       
  4330 	c.sourceIndex = -1;
       
  4331 
       
  4332 	if (s.cleanup_serializer == "xml")
       
  4333 		h = c.serializeNodeAsXML(elm, inn);
       
  4334 	else
       
  4335 		h = c.serializeNodeAsHTML(elm, inn);
       
  4336 
       
  4337 	if (d)
       
  4338 		t3 = new Date().getTime();
       
  4339 
       
  4340 	// Post processing
       
  4341 	nb = tinyMCE.getParam('entity_encoding') == 'numeric' ? '&#160;' : '&nbsp;';
       
  4342 	h = h.replace(/<\/?(body|head|html)[^>]*>/gi, '');
       
  4343 	h = h.replace(new RegExp(' (rowspan="1"|colspan="1")', 'g'), '');
       
  4344 	h = h.replace(/<p><hr \/><\/p>/g, '<hr />');
       
  4345 	h = h.replace(/<p>(&nbsp;|&#160;)<\/p><hr \/><p>(&nbsp;|&#160;)<\/p>/g, '<hr />');
       
  4346 	h = h.replace(/<td>\s*<br \/>\s*<\/td>/g, '<td>' + nb + '</td>');
       
  4347 	h = h.replace(/<p>\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>');
       
  4348 	h = h.replace(/<br \/>$/, ''); // Remove last BR for Gecko
       
  4349 	h = h.replace(/<br \/><\/p>/g, '</p>'); // Remove last BR in P tags for Gecko
       
  4350 	h = h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*(&nbsp;|&#160;)\s*<\/p>/g, '<p>' + nb + '</p>');
       
  4351 	h = h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>');
       
  4352 	h = h.replace(/<p>\s*<br \/>\s*&nbsp;\s*<\/p>/g, '<p>' + nb + '</p>');
       
  4353 	h = h.replace(new RegExp('<a>(.*?)<\\/a>', 'g'), '$1');
       
  4354 	h = h.replace(/<p([^>]*)>\s*<\/p>/g, '<p$1>' + nb + '</p>');
       
  4355 
       
  4356 	// Clean body
       
  4357 	if (/^\s*(<br \/>|<p>&nbsp;<\/p>|<p>&#160;<\/p>|<p><\/p>)\s*$/.test(h))
       
  4358 		h = '';
       
  4359 
       
  4360 	// If preformatted
       
  4361 	if (s.preformatted) {
       
  4362 		h = h.replace(/^<pre>/, '');
       
  4363 		h = h.replace(/<\/pre>$/, '');
       
  4364 		h = '<pre>' + h + '</pre>';
       
  4365 	}
       
  4366 
       
  4367 	// Gecko specific processing
       
  4368 	if (tinyMCE.isGecko) {
       
  4369 		h = h.replace(/<o:p _moz-userdefined="" \/>/g, '');
       
  4370 		h = h.replace(/<td([^>]*)>\s*<br \/>\s*<\/td>/g, '<td$1>' + nb + '</td>');
       
  4371 	}
       
  4372 
       
  4373 	if (s.force_br_newlines)
       
  4374 		h = h.replace(/<p>(&nbsp;|&#160;)<\/p>/g, '<br />');
       
  4375 
       
  4376 	// Call custom cleanup code
       
  4377 	h = tinyMCE._customCleanup(inst, on_save ? "get_from_editor" : "insert_to_editor", h);
       
  4378 
       
  4379 	// Remove internal classes
       
  4380 	if (on_save) {
       
  4381 		h = h.replace(new RegExp(' ?(mceItem[a-zA-Z0-9]*|' + s.visual_table_class + ')', 'g'), '');
       
  4382 		h = h.replace(new RegExp(' ?class=""', 'g'), '');
       
  4383 	}
       
  4384 
       
  4385 	if (s.remove_linebreaks && !c.settings.indent)
       
  4386 		h = h.replace(/\n|\r/g, ' ');
       
  4387 
       
  4388 	if (d)
       
  4389 		t4 = new Date().getTime();
       
  4390 
       
  4391 	if (on_save && c.settings.indent)
       
  4392 		h = c.formatHTML(h);
       
  4393 
       
  4394 	// If encoding (not recommended option)
       
  4395 	if (on_submit && (s.encoding == "xml" || s.encoding == "html"))
       
  4396 		h = c.xmlEncode(h);
       
  4397 
       
  4398 	if (d)
       
  4399 		t5 = new Date().getTime();
       
  4400 
       
  4401 	if (c.settings.debug)
       
  4402 		tinyMCE.debug("Cleanup in ms: Pre=" + (t2-t1) + ", Serialize: " + (t3-t2) + ", Post: " + (t4-t3) + ", Format: " + (t5-t4) + ", Sum: " + (t5-t1) + ".");
       
  4403 
       
  4404 	return h;
       
  4405 };
       
  4406 
       
  4407 function TinyMCE_Cleanup() {
       
  4408 	this.isIE = (navigator.appName == "Microsoft Internet Explorer");
       
  4409 	this.rules = tinyMCE.clearArray(new Array());
       
  4410 
       
  4411 	// Default config
       
  4412 	this.settings = {
       
  4413 		indent_elements : 'head,table,tbody,thead,tfoot,form,tr,ul,ol,blockquote,object',
       
  4414 		newline_before_elements : 'h1,h2,h3,h4,h5,h6,pre,address,div,ul,ol,li,meta,option,area,title,link,base,script,td',
       
  4415 		newline_after_elements : 'br,hr,p,pre,address,div,ul,ol,meta,option,area,link,base,script',
       
  4416 		newline_before_after_elements : 'html,head,body,table,thead,tbody,tfoot,tr,form,ul,ol,blockquote,p,object,param,hr,div',
       
  4417 		indent_char : '\t',
       
  4418 		indent_levels : 1,
       
  4419 		entity_encoding : 'raw',
       
  4420 		valid_elements : '*[*]',
       
  4421 		entities : '',
       
  4422 		url_converter : '',
       
  4423 		invalid_elements : '',
       
  4424 		verify_html : false
       
  4425 	};
       
  4426 
       
  4427 	this.vElements = tinyMCE.clearArray(new Array());
       
  4428 	this.vElementsRe = '';
       
  4429 	this.closeElementsRe = /^(IMG|BR|HR|LINK|META|BASE|INPUT|AREA)$/;
       
  4430 	this.codeElementsRe = /^(SCRIPT|STYLE)$/;
       
  4431 	this.serializationId = 0;
       
  4432 	this.mceAttribs = {
       
  4433 		href : 'mce_href',
       
  4434 		src : 'mce_src',
       
  4435 		type : 'mce_type'
       
  4436 	};
       
  4437 }
       
  4438 
       
  4439 TinyMCE_Cleanup.prototype = {
       
  4440 	init : function(s) {
       
  4441 		var n, a, i, ir, or, st;
       
  4442 
       
  4443 		for (n in s)
       
  4444 			this.settings[n] = s[n];
       
  4445 
       
  4446 		// Setup code formating
       
  4447 		s = this.settings;
       
  4448 
       
  4449 		// Setup regexps
       
  4450 		this.inRe = this._arrayToRe(s.indent_elements.split(','), '', '^<(', ')[^>]*');
       
  4451 		this.ouRe = this._arrayToRe(s.indent_elements.split(','), '', '^<\\/(', ')[^>]*');
       
  4452 		this.nlBeforeRe = this._arrayToRe(s.newline_before_elements.split(','), 'gi', '<(',  ')([^>]*)>');
       
  4453 		this.nlAfterRe = this._arrayToRe(s.newline_after_elements.split(','), 'gi', '<(',  ')([^>]*)>');
       
  4454 		this.nlBeforeAfterRe = this._arrayToRe(s.newline_before_after_elements.split(','), 'gi', '<(\\/?)(', ')([^>]*)>');
       
  4455 		this.serializedNodes = [];
       
  4456 
       
  4457 		if (s.invalid_elements != '')
       
  4458 			this.iveRe = this._arrayToRe(s.invalid_elements.toUpperCase().split(','), 'g', '^(', ')$');
       
  4459 		else
       
  4460 			this.iveRe = null;
       
  4461 
       
  4462 		// Setup separator
       
  4463 		st = '';
       
  4464 		for (i=0; i<s.indent_levels; i++)
       
  4465 			st += s.indent_char;
       
  4466 
       
  4467 		this.inStr = st;
       
  4468 
       
  4469 		// If verify_html if false force *[*]
       
  4470 		if (!s.verify_html) {
       
  4471 			s.valid_elements = '*[*]';
       
  4472 			s.extended_valid_elements = '';
       
  4473 		}
       
  4474 
       
  4475 		this.fillStr = s.entity_encoding == "named" ? "&nbsp;" : "&#160;";
       
  4476 		this.idCount = 0;
       
  4477 		this.xmlEncodeRe = new RegExp('[\u007F-\uFFFF<>&"]', 'g');
       
  4478 		this.xmlEncodeAposRe = new RegExp('[\u007F-\uFFFF<>&"\']', 'g');
       
  4479 	},
       
  4480 
       
  4481 	addRuleStr : function(s) {
       
  4482 		var r = this.parseRuleStr(s);
       
  4483 		var n;
       
  4484 
       
  4485 		for (n in r) {
       
  4486 			if (r[n])
       
  4487 				this.rules[n] = r[n];
       
  4488 		}
       
  4489 
       
  4490 		this.vElements = tinyMCE.clearArray(new Array());
       
  4491 
       
  4492 		for (n in this.rules) {
       
  4493 			if (this.rules[n])
       
  4494 				this.vElements[this.vElements.length] = this.rules[n].tag;
       
  4495 		}
       
  4496 
       
  4497 		this.vElementsRe = this._arrayToRe(this.vElements, '');
       
  4498 	},
       
  4499 
       
  4500 	isValid : function(n) {
       
  4501 		this._setupRules(); // Will initialize cleanup rules
       
  4502 
       
  4503 		// Empty is true since it removes formatting
       
  4504 		if (!n)
       
  4505 			return true;
       
  4506 
       
  4507 		// Clean the name up a bit
       
  4508 		n = n.replace(/[^a-z0-9]+/gi, '').toUpperCase();
       
  4509 
       
  4510 		return !tinyMCE.getParam('cleanup') || this.vElementsRe.test(n);
       
  4511 	},
       
  4512 
       
  4513 	addChildRemoveRuleStr : function(s) {
       
  4514 		var x, y, p, i, t, tn, ta, cl, r;
       
  4515 
       
  4516 		if (!s)
       
  4517 			return;
       
  4518 
       
  4519 		ta = s.split(',');
       
  4520 		for (x=0; x<ta.length; x++) {
       
  4521 			s = ta[x];
       
  4522 
       
  4523 			// Split tag/children
       
  4524 			p = this.split(/\[|\]/, s);
       
  4525 			if (p == null || p.length < 1)
       
  4526 				t = s.toUpperCase();
       
  4527 			else
       
  4528 				t = p[0].toUpperCase();
       
  4529 
       
  4530 			// Handle all tag names
       
  4531 			tn = this.split('/', t);
       
  4532 			for (y=0; y<tn.length; y++) {
       
  4533 				r = "^(";
       
  4534 
       
  4535 				// Build regex
       
  4536 				cl = this.split(/\|/, p[1]);
       
  4537 				for (i=0; i<cl.length; i++) {
       
  4538 					if (cl[i] == '%istrict')
       
  4539 						r += tinyMCE.inlineStrict;
       
  4540 					else if (cl[i] == '%itrans')
       
  4541 						r += tinyMCE.inlineTransitional;
       
  4542 					else if (cl[i] == '%istrict_na')
       
  4543 						r += tinyMCE.inlineStrict.substring(2);
       
  4544 					else if (cl[i] == '%itrans_na')
       
  4545 						r += tinyMCE.inlineTransitional.substring(2);
       
  4546 					else if (cl[i] == '%btrans')
       
  4547 						r += tinyMCE.blockElms;
       
  4548 					else if (cl[i] == '%strict')
       
  4549 						r += tinyMCE.blockStrict;
       
  4550 					else
       
  4551 						r += (cl[i].charAt(0) != '#' ? cl[i].toUpperCase() : cl[i]);
       
  4552 
       
  4553 					r += (i != cl.length - 1 ? '|' : '');
       
  4554 				}
       
  4555 
       
  4556 				r += ')$';
       
  4557 //tinyMCE.debug(t + "=" + r);
       
  4558 				if (this.childRules == null)
       
  4559 					this.childRules = tinyMCE.clearArray(new Array());
       
  4560 
       
  4561 				this.childRules[tn[y]] = new RegExp(r);
       
  4562 
       
  4563 				if (p.length > 1)
       
  4564 					this.childRules[tn[y]].wrapTag = p[2];
       
  4565 			}
       
  4566 		}
       
  4567 	},
       
  4568 
       
  4569 	parseRuleStr : function(s) {
       
  4570 		var ta, p, r, a, i, x, px, t, tn, y, av, or = tinyMCE.clearArray(new Array()), dv;
       
  4571 
       
  4572 		if (s == null || s.length == 0)
       
  4573 			return or;
       
  4574 
       
  4575 		ta = s.split(',');
       
  4576 		for (x=0; x<ta.length; x++) {
       
  4577 			s = ta[x];
       
  4578 			if (s.length == 0)
       
  4579 				continue;
       
  4580 
       
  4581 			// Split tag/attrs
       
  4582 			p = this.split(/\[|\]/, s);
       
  4583 			if (p == null || p.length < 1)
       
  4584 				t = s.toUpperCase();
       
  4585 			else
       
  4586 				t = p[0].toUpperCase();
       
  4587 
       
  4588 			// Handle all tag names
       
  4589 			tn = this.split('/', t);
       
  4590 			for (y=0; y<tn.length; y++) {
       
  4591 				r = {};
       
  4592 
       
  4593 				r.tag = tn[y];
       
  4594 				r.forceAttribs = null;
       
  4595 				r.defaultAttribs = null;
       
  4596 				r.validAttribValues = null;
       
  4597 
       
  4598 				// Handle prefixes
       
  4599 				px = r.tag.charAt(0);
       
  4600 				r.forceOpen = px == '+';
       
  4601 				r.removeEmpty = px == '-';
       
  4602 				r.fill = px == '#';
       
  4603 				r.tag = r.tag.replace(/\+|-|#/g, '');
       
  4604 				r.oTagName = tn[0].replace(/\+|-|#/g, '').toLowerCase();
       
  4605 				r.isWild = new RegExp('\\*|\\?|\\+', 'g').test(r.tag);
       
  4606 				r.validRe = new RegExp(this._wildcardToRe('^' + r.tag + '$'));
       
  4607 
       
  4608 				// Setup valid attributes
       
  4609 				if (p.length > 1) {
       
  4610 					r.vAttribsRe = '^(';
       
  4611 					a = this.split(/\|/, p[1]);
       
  4612 
       
  4613 					for (i=0; i<a.length; i++) {
       
  4614 						t = a[i];
       
  4615 
       
  4616 						if (t.charAt(0) == '!') {
       
  4617 							a[i] = t = t.substring(1);
       
  4618 
       
  4619 							if (!r.reqAttribsRe)
       
  4620 								r.reqAttribsRe = '\\s+(' + t;
       
  4621 							else
       
  4622 								r.reqAttribsRe += '|' + t;
       
  4623 						}
       
  4624 
       
  4625 						av = new RegExp('(=|:|<)(.*?)$').exec(t);
       
  4626 						t = t.replace(new RegExp('(=|:|<).*?$'), '');
       
  4627 						if (av && av.length > 0) {
       
  4628 							if (av[0].charAt(0) == ':') {
       
  4629 								if (!r.forceAttribs)
       
  4630 									r.forceAttribs = tinyMCE.clearArray(new Array());
       
  4631 
       
  4632 								r.forceAttribs[t.toLowerCase()] = av[0].substring(1);
       
  4633 							} else if (av[0].charAt(0) == '=') {
       
  4634 								if (!r.defaultAttribs)
       
  4635 									r.defaultAttribs = tinyMCE.clearArray(new Array());
       
  4636 
       
  4637 								dv = av[0].substring(1);
       
  4638 
       
  4639 								r.defaultAttribs[t.toLowerCase()] = dv == "" ? "mce_empty" : dv;
       
  4640 							} else if (av[0].charAt(0) == '<') {
       
  4641 								if (!r.validAttribValues)
       
  4642 									r.validAttribValues = tinyMCE.clearArray(new Array());
       
  4643 
       
  4644 								r.validAttribValues[t.toLowerCase()] = this._arrayToRe(this.split('?', av[0].substring(1)), 'i');
       
  4645 							}
       
  4646 						}
       
  4647 
       
  4648 						r.vAttribsRe += '' + t.toLowerCase() + (i != a.length - 1 ? '|' : '');
       
  4649 
       
  4650 						a[i] = t.toLowerCase();
       
  4651 					}
       
  4652 
       
  4653 					if (r.reqAttribsRe)
       
  4654 						r.reqAttribsRe = new RegExp(r.reqAttribsRe + ')=\"', 'g');
       
  4655 
       
  4656 					r.vAttribsRe += ')$';
       
  4657 					r.vAttribsRe = this._wildcardToRe(r.vAttribsRe);
       
  4658 					r.vAttribsReIsWild = new RegExp('\\*|\\?|\\+', 'g').test(r.vAttribsRe);
       
  4659 					r.vAttribsRe = new RegExp(r.vAttribsRe);
       
  4660 					r.vAttribs = a.reverse();
       
  4661 
       
  4662 					//tinyMCE.debug(r.tag, r.oTagName, r.vAttribsRe, r.vAttribsReWC);
       
  4663 				} else {
       
  4664 					r.vAttribsRe = '';
       
  4665 					r.vAttribs = tinyMCE.clearArray(new Array());
       
  4666 					r.vAttribsReIsWild = false;
       
  4667 				}
       
  4668 
       
  4669 				or[r.tag] = r;
       
  4670 			}
       
  4671 		}
       
  4672 
       
  4673 		return or;
       
  4674 	},
       
  4675 
       
  4676 	serializeNodeAsXML : function(n) {
       
  4677 		var s, b;
       
  4678 
       
  4679 		if (!this.xmlDoc) {
       
  4680 			if (this.isIE) {
       
  4681 				try {this.xmlDoc = new ActiveXObject('MSXML2.DOMDocument');} catch (e) {}
       
  4682 
       
  4683 				if (!this.xmlDoc)
       
  4684 					try {this.xmlDoc = new ActiveXObject('Microsoft.XmlDom');} catch (e) {}
       
  4685 			} else
       
  4686 				this.xmlDoc = document.implementation.createDocument('', '', null);
       
  4687 
       
  4688 			if (!this.xmlDoc)
       
  4689 				alert("Error XML Parser could not be found.");
       
  4690 		}
       
  4691 
       
  4692 		if (this.xmlDoc.firstChild)
       
  4693 			this.xmlDoc.removeChild(this.xmlDoc.firstChild);
       
  4694 
       
  4695 		b = this.xmlDoc.createElement("html");
       
  4696 		b = this.xmlDoc.appendChild(b);
       
  4697 
       
  4698 		this._convertToXML(n, b);
       
  4699 
       
  4700 		if (this.isIE)
       
  4701 			return this.xmlDoc.xml;
       
  4702 		else
       
  4703 			return new XMLSerializer().serializeToString(this.xmlDoc);
       
  4704 	},
       
  4705 
       
  4706 	_convertToXML : function(n, xn) {
       
  4707 		var xd, el, i, l, cn, at, no, hc = false;
       
  4708 
       
  4709 		if (tinyMCE.isRealIE && this._isDuplicate(n))
       
  4710 			return;
       
  4711 
       
  4712 		xd = this.xmlDoc;
       
  4713 
       
  4714 		switch (n.nodeType) {
       
  4715 			case 1: // Element
       
  4716 				hc = n.hasChildNodes();
       
  4717 
       
  4718 				el = xd.createElement(n.nodeName.toLowerCase());
       
  4719 
       
  4720 				at = n.attributes;
       
  4721 				for (i=at.length-1; i>-1; i--) {
       
  4722 					no = at[i];
       
  4723 
       
  4724 					if (no.specified && no.nodeValue)
       
  4725 						el.setAttribute(no.nodeName.toLowerCase(), no.nodeValue);
       
  4726 				}
       
  4727 
       
  4728 				if (!hc && !this.closeElementsRe.test(n.nodeName))
       
  4729 					el.appendChild(xd.createTextNode(""));
       
  4730 
       
  4731 				xn = xn.appendChild(el);
       
  4732 				break;
       
  4733 
       
  4734 			case 3: // Text
       
  4735 				xn.appendChild(xd.createTextNode(n.nodeValue));
       
  4736 				return;
       
  4737 
       
  4738 			case 8: // Comment
       
  4739 				xn.appendChild(xd.createComment(n.nodeValue));
       
  4740 				return;
       
  4741 		}
       
  4742 
       
  4743 		if (hc) {
       
  4744 			cn = n.childNodes;
       
  4745 
       
  4746 			for (i=0, l=cn.length; i<l; i++)
       
  4747 				this._convertToXML(cn[i], xn);
       
  4748 		}
       
  4749 	},
       
  4750 
       
  4751 	serializeNodeAsHTML : function(n, inn) {
       
  4752 		var en, no, h = '', i, l, t, st, r, cn, va = false, f = false, at, hc, cr, nn;
       
  4753 
       
  4754 		this._setupRules(); // Will initialize cleanup rules
       
  4755 
       
  4756 		if (tinyMCE.isRealIE && this._isDuplicate(n))
       
  4757 			return '';
       
  4758 
       
  4759 		// Skip non valid child elements
       
  4760 		if (n.parentNode && this.childRules != null) {
       
  4761 			cr = this.childRules[n.parentNode.nodeName];
       
  4762 
       
  4763 			if (typeof(cr) != "undefined" && !cr.test(n.nodeName)) {
       
  4764 				st = true;
       
  4765 				t = null;
       
  4766 			}
       
  4767 		}
       
  4768 
       
  4769 		switch (n.nodeType) {
       
  4770 			case 1: // Element
       
  4771 				hc = n.hasChildNodes();
       
  4772 
       
  4773 				if (st)
       
  4774 					break;
       
  4775 
       
  4776 				// MSIE sometimes produces <//tag>
       
  4777 				if ((tinyMCE.isRealIE) && n.nodeName.indexOf('/') != -1)
       
  4778 					break;
       
  4779 
       
  4780 				nn = n.nodeName;
       
  4781 
       
  4782 				// Convert fonts to spans
       
  4783 				if (this.settings.convert_fonts_to_spans) {
       
  4784 					// On get content FONT -> SPAN
       
  4785 					if (this.settings.on_save && nn == 'FONT')
       
  4786 						nn = 'SPAN';
       
  4787 
       
  4788 					// On insert content SPAN -> FONT
       
  4789 					if (!this.settings.on_save && nn == 'SPAN')
       
  4790 						nn = 'FONT';
       
  4791 				}
       
  4792 
       
  4793 				if (this.vElementsRe.test(nn) && (!this.iveRe || !this.iveRe.test(nn)) && !inn) {
       
  4794 					va = true;
       
  4795 
       
  4796 					r = this.rules[nn];
       
  4797 					if (!r) {
       
  4798 						at = this.rules;
       
  4799 						for (no in at) {
       
  4800 							if (at[no] && at[no].validRe.test(nn)) {
       
  4801 								r = at[no];
       
  4802 								break;
       
  4803 							}
       
  4804 						}
       
  4805 					}
       
  4806 
       
  4807 					en = r.isWild ? nn.toLowerCase() : r.oTagName;
       
  4808 					f = r.fill;
       
  4809 
       
  4810 					if (r.removeEmpty && !hc)
       
  4811 						return "";
       
  4812 
       
  4813 					t = '<' + en;
       
  4814 
       
  4815 					if (r.vAttribsReIsWild) {
       
  4816 						// Serialize wildcard attributes
       
  4817 						at = n.attributes;
       
  4818 						for (i=at.length-1; i>-1; i--) {
       
  4819 							no = at[i];
       
  4820 							if (no.specified && r.vAttribsRe.test(no.nodeName))
       
  4821 								t += this._serializeAttribute(n, r, no.nodeName);
       
  4822 						}
       
  4823 					} else {
       
  4824 						// Serialize specific attributes
       
  4825 						for (i=r.vAttribs.length-1; i>-1; i--)
       
  4826 							t += this._serializeAttribute(n, r, r.vAttribs[i]);
       
  4827 					}
       
  4828 
       
  4829 					// Serialize mce_ atts
       
  4830 					if (!this.settings.on_save) {
       
  4831 						at = this.mceAttribs;
       
  4832 
       
  4833 						for (no in at) {
       
  4834 							if (at[no])
       
  4835 								t += this._serializeAttribute(n, r, at[no]);
       
  4836 						}
       
  4837 					}
       
  4838 
       
  4839 					// Check for required attribs
       
  4840 					if (r.reqAttribsRe && !t.match(r.reqAttribsRe))
       
  4841 						t = null;
       
  4842 
       
  4843 					// Close these
       
  4844 					if (t != null && this.closeElementsRe.test(nn))
       
  4845 						return t + ' />';
       
  4846 
       
  4847 					if (t != null)
       
  4848 						h += t + '>';
       
  4849 
       
  4850 					if (this.isIE && this.codeElementsRe.test(nn))
       
  4851 						h += n.innerHTML;
       
  4852 				}
       
  4853 			break;
       
  4854 
       
  4855 			case 3: // Text
       
  4856 				if (st)
       
  4857 					break;
       
  4858 
       
  4859 				if (n.parentNode && this.codeElementsRe.test(n.parentNode.nodeName))
       
  4860 					return this.isIE ? '' : n.nodeValue;
       
  4861 
       
  4862 				return this.xmlEncode(n.nodeValue);
       
  4863 
       
  4864 			case 8: // Comment
       
  4865 				if (st)
       
  4866 					break;
       
  4867 
       
  4868 				return "<!--" + this._trimComment(n.nodeValue) + "-->";
       
  4869 		}
       
  4870 
       
  4871 		if (hc) {
       
  4872 			cn = n.childNodes;
       
  4873 
       
  4874 			for (i=0, l=cn.length; i<l; i++)
       
  4875 				h += this.serializeNodeAsHTML(cn[i]);
       
  4876 		}
       
  4877 
       
  4878 		// Fill empty nodes
       
  4879 		if (f && !hc)
       
  4880 			h += this.fillStr;
       
  4881 
       
  4882 		// End element
       
  4883 		if (t != null && va)
       
  4884 			h += '</' + en + '>';
       
  4885 
       
  4886 		return h;
       
  4887 	},
       
  4888 
       
  4889 	_serializeAttribute : function(n, r, an) {
       
  4890 		var av = '', t, os = this.settings.on_save;
       
  4891 
       
  4892 		if (os && (an.indexOf('mce_') == 0 || an.indexOf('_moz') == 0))
       
  4893 			return '';
       
  4894 
       
  4895 		if (os && this.mceAttribs[an])
       
  4896 			av = this._getAttrib(n, this.mceAttribs[an]);
       
  4897 
       
  4898 		if (av.length == 0)
       
  4899 			av = this._getAttrib(n, an);
       
  4900 
       
  4901 		if (av.length == 0 && r.defaultAttribs && (t = r.defaultAttribs[an])) {
       
  4902 			av = t;
       
  4903 
       
  4904 			if (av == "mce_empty")
       
  4905 				return " " + an + '=""';
       
  4906 		}
       
  4907 
       
  4908 		if (r.forceAttribs && (t = r.forceAttribs[an]))
       
  4909 			av = t;
       
  4910 
       
  4911 		if (os && av.length != 0 && /^(src|href|longdesc)$/.test(an))
       
  4912 			av = this._urlConverter(this, n, av);
       
  4913 
       
  4914 		if (av.length != 0 && r.validAttribValues && r.validAttribValues[an] && !r.validAttribValues[an].test(av))
       
  4915 			return "";
       
  4916 
       
  4917 		if (av.length != 0 && av == "{$uid}")
       
  4918 			av = "uid_" + (this.idCount++);
       
  4919 
       
  4920 		if (av.length != 0) {
       
  4921 			if (an.indexOf('on') != 0)
       
  4922 				av = this.xmlEncode(av, 1);
       
  4923 
       
  4924 			return " " + an + "=" + '"' + av + '"';
       
  4925 		}
       
  4926 
       
  4927 		return "";
       
  4928 	},
       
  4929 
       
  4930 	formatHTML : function(h) {
       
  4931 		var s = this.settings, p = '', i = 0, li = 0, o = '', l;
       
  4932 
       
  4933 		// Replace BR in pre elements to \n
       
  4934 		h = h.replace(/<pre([^>]*)>(.*?)<\/pre>/gi, function (a, b, c) {
       
  4935 			c = c.replace(/<br\s*\/>/gi, '\n');
       
  4936 			return '<pre' + b + '>' + c + '</pre>';
       
  4937 		});
       
  4938 
       
  4939 		h = h.replace(/\r/g, ''); // Windows sux, isn't carriage return a thing of the past :)
       
  4940 		h = '\n' + h;
       
  4941 		h = h.replace(new RegExp('\\n\\s+', 'gi'), '\n'); // Remove previous formatting
       
  4942 		h = h.replace(this.nlBeforeRe, '\n<$1$2>');
       
  4943 		h = h.replace(this.nlAfterRe, '<$1$2>\n');
       
  4944 		h = h.replace(this.nlBeforeAfterRe, '\n<$1$2$3>\n');
       
  4945 		h += '\n';
       
  4946 
       
  4947 		//tinyMCE.debug(h);
       
  4948 
       
  4949 		while ((i = h.indexOf('\n', i + 1)) != -1) {
       
  4950 			if ((l = h.substring(li + 1, i)).length != 0) {
       
  4951 				if (this.ouRe.test(l) && p.length >= s.indent_levels)
       
  4952 					p = p.substring(s.indent_levels);
       
  4953 
       
  4954 				o += p + l + '\n';
       
  4955 	
       
  4956 				if (this.inRe.test(l))
       
  4957 					p += this.inStr;
       
  4958 			}
       
  4959 
       
  4960 			li = i;
       
  4961 		}
       
  4962 
       
  4963 		//tinyMCE.debug(h);
       
  4964 
       
  4965 		return o;
       
  4966 	},
       
  4967 
       
  4968 	xmlEncode : function(s, skip_apos) {
       
  4969 		var cl = this, re = !skip_apos ? this.xmlEncodeAposRe : this.xmlEncodeRe;
       
  4970 
       
  4971 		this._setupEntities(); // Will intialize lookup table
       
  4972 
       
  4973 		switch (this.settings.entity_encoding) {
       
  4974 			case "raw":
       
  4975 				return tinyMCE.xmlEncode(s, skip_apos);
       
  4976 
       
  4977 			case "named":
       
  4978 				return s.replace(re, function (c, b) {
       
  4979 					b = cl.entities[c.charCodeAt(0)];
       
  4980 
       
  4981 					return b ? '&' + b + ';' : c;
       
  4982 				});
       
  4983 
       
  4984 			case "numeric":
       
  4985 				return s.replace(re, function (c, b) {
       
  4986 					return b ? '&#' + c.charCodeAt(0) + ';' : c;
       
  4987 				});
       
  4988 		}
       
  4989 
       
  4990 		return s;
       
  4991 	},
       
  4992 
       
  4993 	split : function(re, s) {
       
  4994 		var c = s.split(re);
       
  4995 		var i, l, o = new Array();
       
  4996 
       
  4997 		for (i=0, l=c.length; i<l; i++) {
       
  4998 			if (c[i] != '')
       
  4999 				o[i] = c[i];
       
  5000 		}
       
  5001 
       
  5002 		return o;
       
  5003 	},
       
  5004 
       
  5005 	_trimComment : function(s) {
       
  5006 		// Remove mce_src, mce_href
       
  5007 		s = s.replace(new RegExp('\\smce_src=\"[^\"]*\"', 'gi'), "");
       
  5008 		s = s.replace(new RegExp('\\smce_href=\"[^\"]*\"', 'gi'), "");
       
  5009 
       
  5010 		return s;
       
  5011 	},
       
  5012 
       
  5013 	_getAttrib : function(e, n, d) {
       
  5014 		var v, ex, nn;
       
  5015 
       
  5016 		if (typeof(d) == "undefined")
       
  5017 			d = "";
       
  5018 
       
  5019 		if (!e || e.nodeType != 1)
       
  5020 			return d;
       
  5021 
       
  5022 		try {
       
  5023 			v = e.getAttribute(n, 0);
       
  5024 		} catch (ex) {
       
  5025 			// IE 7 may cast exception on invalid attributes
       
  5026 			v = e.getAttribute(n, 2);
       
  5027 		}
       
  5028 
       
  5029 		if (n == "class" && !v)
       
  5030 			v = e.className;
       
  5031 
       
  5032 		if (this.isIE) {
       
  5033 			if (n == "http-equiv")
       
  5034 				v = e.httpEquiv;
       
  5035 
       
  5036 			nn = e.nodeName;
       
  5037 
       
  5038 			// Skip the default values that IE returns
       
  5039 			if (nn == "FORM" && n == "enctype" && v == "application/x-www-form-urlencoded")
       
  5040 				v = "";
       
  5041 
       
  5042 			if (nn == "INPUT" && n == "size" && v == "20")
       
  5043 				v = "";
       
  5044 
       
  5045 			if (nn == "INPUT" && n == "maxlength" && v == "2147483647")
       
  5046 				v = "";
       
  5047 		}
       
  5048 
       
  5049 		if (n == 'style' && v) {
       
  5050 			if (!tinyMCE.isOpera)
       
  5051 				v = e.style.cssText;
       
  5052 
       
  5053 			v = tinyMCE.serializeStyle(tinyMCE.parseStyle(v));
       
  5054 		}
       
  5055 
       
  5056 		if (this.settings.on_save && n.indexOf('on') != -1 && this.settings.on_save && v && v != "")
       
  5057 			v = tinyMCE.cleanupEventStr(v);
       
  5058 
       
  5059 		return (v && v != "") ? '' + v : d;
       
  5060 	},
       
  5061 
       
  5062 	_urlConverter : function(c, n, v) {
       
  5063 		if (!c.settings.on_save)
       
  5064 			return tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, v);
       
  5065 		else if (tinyMCE.getParam('convert_urls')) {
       
  5066 			if (!this.urlConverter)
       
  5067 				this.urlConverter = eval(tinyMCE.settings.urlconverter_callback);
       
  5068 
       
  5069 			return this.urlConverter(v, n, true);
       
  5070 		}
       
  5071 
       
  5072 		return v;
       
  5073 	},
       
  5074 
       
  5075 	_arrayToRe : function(a, op, be, af) {
       
  5076 		var i, r;
       
  5077 
       
  5078 		op = typeof(op) == "undefined" ? "gi" : op;
       
  5079 		be = typeof(be) == "undefined" ? "^(" : be;
       
  5080 		af = typeof(af) == "undefined" ? ")$" : af;
       
  5081 
       
  5082 		r = be;
       
  5083 
       
  5084 		for (i=0; i<a.length; i++)
       
  5085 			r += this._wildcardToRe(a[i]) + (i != a.length-1 ? "|" : "");
       
  5086 
       
  5087 		r += af;
       
  5088 
       
  5089 		return new RegExp(r, op);
       
  5090 	},
       
  5091 
       
  5092 	_wildcardToRe : function(s) {
       
  5093 		s = s.replace(/\?/g, '(\\S?)');
       
  5094 		s = s.replace(/\+/g, '(\\S+)');
       
  5095 		s = s.replace(/\*/g, '(\\S*)');
       
  5096 
       
  5097 		return s;
       
  5098 	},
       
  5099 
       
  5100 	_setupEntities : function() {
       
  5101 		var n, a, i, s = this.settings;
       
  5102 
       
  5103 		// Setup entities
       
  5104 		if (!this.entitiesDone) {
       
  5105 			if (s.entity_encoding == "named") {
       
  5106 				n = tinyMCE.clearArray(new Array());
       
  5107 				a = this.split(',', s.entities);
       
  5108 				for (i=0; i<a.length; i+=2)
       
  5109 					n[a[i]] = a[i+1];
       
  5110 
       
  5111 				this.entities = n;
       
  5112 			}
       
  5113 
       
  5114 			this.entitiesDone = true;
       
  5115 		}
       
  5116 	},
       
  5117 
       
  5118 	_setupRules : function() {
       
  5119 		var s = this.settings;
       
  5120 
       
  5121 		// Setup default rule
       
  5122 		if (!this.rulesDone) {
       
  5123 			this.addRuleStr(s.valid_elements);
       
  5124 			this.addRuleStr(s.extended_valid_elements);
       
  5125 			this.addChildRemoveRuleStr(s.valid_child_elements);
       
  5126 
       
  5127 			this.rulesDone = true;
       
  5128 		}
       
  5129 	},
       
  5130 
       
  5131 	_isDuplicate : function(n) {
       
  5132 		var i;
       
  5133 
       
  5134 		if (!this.settings.fix_content_duplication)
       
  5135 			return false;
       
  5136 
       
  5137 		if (tinyMCE.isRealIE && n.nodeType == 1) {
       
  5138 			// Mark elements
       
  5139 			if (n.mce_serialized == this.serializationId)
       
  5140 				return true;
       
  5141 
       
  5142 			n.setAttribute('mce_serialized', this.serializationId);
       
  5143 		} else {
       
  5144 			// Search lookup table for text nodes  and comments
       
  5145 			for (i=0; i<this.serializedNodes.length; i++) {
       
  5146 				if (this.serializedNodes[i] == n)
       
  5147 					return true;
       
  5148 			}
       
  5149 
       
  5150 			this.serializedNodes[this.serializedNodes.length] = n;
       
  5151 		}
       
  5152 
       
  5153 		return false;
       
  5154 	}
       
  5155 
       
  5156 	};
       
  5157 
       
  5158 /* file:jscripts/tiny_mce/classes/TinyMCE_DOMUtils.class.js */
       
  5159 
       
  5160 TinyMCE_Engine.prototype.createTagHTML = function(tn, a, h) {
       
  5161 	var o = '', f = tinyMCE.xmlEncode;
       
  5162 
       
  5163 	o = '<' + tn;
       
  5164 
       
  5165 	if (a) {
       
  5166 		for (n in a) {
       
  5167 			if (typeof(a[n]) != 'function' && a[n] != null)
       
  5168 				o += ' ' + f(n) + '="' + f('' + a[n]) + '"';
       
  5169 		}
       
  5170 	}
       
  5171 
       
  5172 	o += !h ? ' />' : '>' + h + '</' + tn + '>';
       
  5173 
       
  5174 	return o;
       
  5175 };
       
  5176 
       
  5177 TinyMCE_Engine.prototype.createTag = function(d, tn, a, h) {
       
  5178 	var o = d.createElement(tn);
       
  5179 
       
  5180 	if (a) {
       
  5181 		for (n in a) {
       
  5182 			if (typeof(a[n]) != 'function' && a[n] != null)
       
  5183 				tinyMCE.setAttrib(o, n, a[n]);
       
  5184 		}
       
  5185 	}
       
  5186 
       
  5187 	if (h)
       
  5188 		o.innerHTML = h;
       
  5189 
       
  5190 	return o;
       
  5191 };
       
  5192 
       
  5193 TinyMCE_Engine.prototype.getElementByAttributeValue = function(n, e, a, v) {
       
  5194 	return (n = this.getElementsByAttributeValue(n, e, a, v)).length == 0 ? null : n[0];
       
  5195 };
       
  5196 
       
  5197 TinyMCE_Engine.prototype.getElementsByAttributeValue = function(n, e, a, v) {
       
  5198 	var i, nl = n.getElementsByTagName(e), o = new Array();
       
  5199 
       
  5200 	for (i=0; i<nl.length; i++) {
       
  5201 		if (tinyMCE.getAttrib(nl[i], a).indexOf(v) != -1)
       
  5202 			o[o.length] = nl[i];
       
  5203 	}
       
  5204 
       
  5205 	return o;
       
  5206 };
       
  5207 
       
  5208 TinyMCE_Engine.prototype.isBlockElement = function(n) {
       
  5209 	return n != null && n.nodeType == 1 && this.blockRegExp.test(n.nodeName);
       
  5210 };
       
  5211 
       
  5212 TinyMCE_Engine.prototype.getParentBlockElement = function(n, r) {
       
  5213 	return this.getParentNode(n, function(n) {
       
  5214 		return tinyMCE.isBlockElement(n);
       
  5215 	}, r);
       
  5216 
       
  5217 	return null;
       
  5218 };
       
  5219 
       
  5220 TinyMCE_Engine.prototype.insertAfter = function(n, r){
       
  5221 	if (r.nextSibling)
       
  5222 		r.parentNode.insertBefore(n, r.nextSibling);
       
  5223 	else
       
  5224 		r.parentNode.appendChild(n);
       
  5225 };
       
  5226 
       
  5227 TinyMCE_Engine.prototype.setInnerHTML = function(e, h) {
       
  5228 	var i, nl, n;
       
  5229 
       
  5230 	// Convert all strong/em to b/i in Gecko
       
  5231 	if (tinyMCE.isGecko) {
       
  5232 		h = h.replace(/<embed([^>]*)>/gi, '<tmpembed$1>');
       
  5233 		h = h.replace(/<em([^>]*)>/gi, '<i$1>');
       
  5234 		h = h.replace(/<tmpembed([^>]*)>/gi, '<embed$1>');
       
  5235 		h = h.replace(/<strong([^>]*)>/gi, '<b$1>');
       
  5236 		h = h.replace(/<\/strong>/gi, '</b>');
       
  5237 		h = h.replace(/<\/em>/gi, '</i>');
       
  5238 	}
       
  5239 
       
  5240 	if (tinyMCE.isRealIE) {
       
  5241 		// Since MSIE handles invalid HTML better that valid XHTML we
       
  5242 		// need to make some things invalid. <hr /> gets converted to <hr>.
       
  5243 		h = h.replace(/\s\/>/g, '>');
       
  5244 
       
  5245 		// Since MSIE auto generated emtpy P tags some times we must tell it to keep the real ones
       
  5246 		h = h.replace(/<p([^>]*)>\u00A0?<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
       
  5247 		h = h.replace(/<p([^>]*)>\s*&nbsp;\s*<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
       
  5248 		h = h.replace(/<p([^>]*)>\s+<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
       
  5249 
       
  5250 		// Remove first comment
       
  5251 		e.innerHTML = tinyMCE.uniqueTag + h;
       
  5252 		e.firstChild.removeNode(true);
       
  5253 
       
  5254 		// Remove weird auto generated empty paragraphs unless it's supposed to be there
       
  5255 		nl = e.getElementsByTagName("p");
       
  5256 		for (i=nl.length-1; i>=0; i--) {
       
  5257 			n = nl[i];
       
  5258 
       
  5259 			if (n.nodeName == 'P' && !n.hasChildNodes() && !n.mce_keep)
       
  5260 				n.parentNode.removeChild(n);
       
  5261 		}
       
  5262 	} else {
       
  5263 		h = this.fixGeckoBaseHREFBug(1, e, h);
       
  5264 		e.innerHTML = h;
       
  5265 		this.fixGeckoBaseHREFBug(2, e, h);
       
  5266 	}
       
  5267 };
       
  5268 
       
  5269 TinyMCE_Engine.prototype.getOuterHTML = function(e) {
       
  5270 	if (tinyMCE.isIE)
       
  5271 		return e.outerHTML;
       
  5272 
       
  5273 	var d = e.ownerDocument.createElement("body");
       
  5274 	d.appendChild(e.cloneNode(true));
       
  5275 	return d.innerHTML;
       
  5276 };
       
  5277 
       
  5278 TinyMCE_Engine.prototype.setOuterHTML = function(e, h, d) {
       
  5279 	var d = typeof(d) == "undefined" ? e.ownerDocument : d, i, nl, t;
       
  5280 
       
  5281 	if (tinyMCE.isIE && e.nodeType == 1)
       
  5282 		e.outerHTML = h;
       
  5283 	else {
       
  5284 		t = d.createElement("body");
       
  5285 		t.innerHTML = h;
       
  5286 
       
  5287 		for (i=0, nl=t.childNodes; i<nl.length; i++)
       
  5288 			e.parentNode.insertBefore(nl[i].cloneNode(true), e);
       
  5289 
       
  5290 		e.parentNode.removeChild(e);
       
  5291 	}
       
  5292 };
       
  5293 
       
  5294 TinyMCE_Engine.prototype._getElementById = function(id, d) {
       
  5295 	var e, i, j, f;
       
  5296 
       
  5297 	if (typeof(d) == "undefined")
       
  5298 		d = document;
       
  5299 
       
  5300 	e = d.getElementById(id);
       
  5301 	if (!e) {
       
  5302 		f = d.forms;
       
  5303 
       
  5304 		for (i=0; i<f.length; i++) {
       
  5305 			for (j=0; j<f[i].elements.length; j++) {
       
  5306 				if (f[i].elements[j].name == id) {
       
  5307 					e = f[i].elements[j];
       
  5308 					break;
       
  5309 				}
       
  5310 			}
       
  5311 		}
       
  5312 	}
       
  5313 
       
  5314 	return e;
       
  5315 };
       
  5316 
       
  5317 TinyMCE_Engine.prototype.getNodeTree = function(n, na, t, nn) {
       
  5318 	return this.selectNodes(n, function(n) {
       
  5319 		return (!t || n.nodeType == t) && (!nn || n.nodeName == nn);
       
  5320 	}, na ? na : new Array());
       
  5321 };
       
  5322 
       
  5323 TinyMCE_Engine.prototype.getParentElement = function(n, na, f, r) {
       
  5324 	var re = na ? new RegExp('^(' + na.toUpperCase().replace(/,/g, '|') + ')$') : 0, v;
       
  5325 
       
  5326 	// Compatiblity with old scripts where f param was a attribute string
       
  5327 	if (f && typeof(f) == 'string')
       
  5328 		return this.getParentElement(n, na, function(no) {return tinyMCE.getAttrib(no, f) != '';});
       
  5329 
       
  5330 	return this.getParentNode(n, function(n) {
       
  5331 		return ((n.nodeType == 1 && !re) || (re && re.test(n.nodeName))) && (!f || f(n));
       
  5332 	}, r);
       
  5333 };
       
  5334 
       
  5335 TinyMCE_Engine.prototype.getParentNode = function(n, f, r) {
       
  5336 	while (n) {
       
  5337 		if (n == r)
       
  5338 			return null;
       
  5339 
       
  5340 		if (f(n))
       
  5341 			return n;
       
  5342 
       
  5343 		n = n.parentNode;
       
  5344 	}
       
  5345 
       
  5346 	return null;
       
  5347 };
       
  5348 
       
  5349 TinyMCE_Engine.prototype.getAttrib = function(elm, name, dv) {
       
  5350 	var v;
       
  5351 
       
  5352 	if (typeof(dv) == "undefined")
       
  5353 		dv = "";
       
  5354 
       
  5355 	// Not a element
       
  5356 	if (!elm || elm.nodeType != 1)
       
  5357 		return dv;
       
  5358 
       
  5359 	try {
       
  5360 		v = elm.getAttribute(name, 0);
       
  5361 	} catch (ex) {
       
  5362 		// IE 7 may cast exception on invalid attributes
       
  5363 		v = elm.getAttribute(name, 2);
       
  5364 	}
       
  5365 
       
  5366 	// Try className for class attrib
       
  5367 	if (name == "class" && !v)
       
  5368 		v = elm.className;
       
  5369 
       
  5370 	// Workaround for a issue with Firefox 1.5rc2+
       
  5371 	if (tinyMCE.isGecko && name == "src" && elm.src != null && elm.src != "")
       
  5372 		v = elm.src;
       
  5373 
       
  5374 	// Workaround for a issue with Firefox 1.5rc2+
       
  5375 	if (tinyMCE.isGecko && name == "href" && elm.href != null && elm.href != "")
       
  5376 		v = elm.href;
       
  5377 
       
  5378 	if (name == "http-equiv" && tinyMCE.isIE)
       
  5379 		v = elm.httpEquiv;
       
  5380 
       
  5381 	if (name == "style" && !tinyMCE.isOpera)
       
  5382 		v = elm.style.cssText;
       
  5383 
       
  5384 	return (v && v != "") ? v : dv;
       
  5385 };
       
  5386 
       
  5387 TinyMCE_Engine.prototype.setAttrib = function(el, name, va, fix) {
       
  5388 	if (typeof(va) == "number" && va != null)
       
  5389 		va = "" + va;
       
  5390 
       
  5391 	if (fix) {
       
  5392 		if (va == null)
       
  5393 			va = "";
       
  5394 
       
  5395 		va = va.replace(/[^0-9%]/g, '');
       
  5396 	}
       
  5397 
       
  5398 	if (name == "style")
       
  5399 		el.style.cssText = va;
       
  5400 
       
  5401 	if (name == "class")
       
  5402 		el.className = va;
       
  5403 
       
  5404 	if (va != null && va != "" && va != -1)
       
  5405 		el.setAttribute(name, va);
       
  5406 	else
       
  5407 		el.removeAttribute(name);
       
  5408 };
       
  5409 
       
  5410 TinyMCE_Engine.prototype.setStyleAttrib = function(e, n, v) {
       
  5411 	e.style[n] = v;
       
  5412 
       
  5413 	// Style attrib deleted in IE
       
  5414 	if (tinyMCE.isIE && v == null || v == '') {
       
  5415 		v = tinyMCE.serializeStyle(tinyMCE.parseStyle(e.style.cssText));
       
  5416 		e.style.cssText = v;
       
  5417 		e.setAttribute("style", v);
       
  5418 	}
       
  5419 };
       
  5420 
       
  5421 TinyMCE_Engine.prototype.switchClass = function(ei, c) {
       
  5422 	var e;
       
  5423 
       
  5424 	if (tinyMCE.switchClassCache[ei])
       
  5425 		e = tinyMCE.switchClassCache[ei];
       
  5426 	else
       
  5427 		e = tinyMCE.switchClassCache[ei] = document.getElementById(ei);
       
  5428 
       
  5429 	if (e) {
       
  5430 		// Keep tile mode
       
  5431 		if (tinyMCE.settings.button_tile_map && e.className && e.className.indexOf('mceTiledButton') == 0)
       
  5432 			c = 'mceTiledButton ' + c;
       
  5433 
       
  5434 		e.className = c;
       
  5435 	}
       
  5436 };
       
  5437 
       
  5438 TinyMCE_Engine.prototype.getAbsPosition = function(n, cn) {
       
  5439 	var l = 0, t = 0;
       
  5440 
       
  5441 	while (n && n != cn) {
       
  5442 		l += n.offsetLeft;
       
  5443 		t += n.offsetTop;
       
  5444 		n = n.offsetParent;
       
  5445 	}
       
  5446 
       
  5447 	return {absLeft : l, absTop : t};
       
  5448 };
       
  5449 
       
  5450 TinyMCE_Engine.prototype.prevNode = function(e, n) {
       
  5451 	var a = n.split(','), i;
       
  5452 
       
  5453 	while ((e = e.previousSibling) != null) {
       
  5454 		for (i=0; i<a.length; i++) {
       
  5455 			if (e.nodeName == a[i])
       
  5456 				return e;
       
  5457 		}
       
  5458 	}
       
  5459 
       
  5460 	return null;
       
  5461 };
       
  5462 
       
  5463 TinyMCE_Engine.prototype.nextNode = function(e, n) {
       
  5464 	var a = n.split(','), i;
       
  5465 
       
  5466 	while ((e = e.nextSibling) != null) {
       
  5467 		for (i=0; i<a.length; i++) {
       
  5468 			if (e.nodeName == a[i])
       
  5469 				return e;
       
  5470 		}
       
  5471 	}
       
  5472 
       
  5473 	return null;
       
  5474 };
       
  5475 
       
  5476 TinyMCE_Engine.prototype.selectElements = function(n, na, f) {
       
  5477 	var i, a = [], nl, x;
       
  5478 
       
  5479 	for (x=0, na = na.split(','); x<na.length; x++)
       
  5480 		for (i=0, nl = n.getElementsByTagName(na[x]); i<nl.length; i++)
       
  5481 			(!f || f(nl[i])) && a.push(nl[i]);
       
  5482 
       
  5483 	return a;
       
  5484 };
       
  5485 
       
  5486 TinyMCE_Engine.prototype.selectNodes = function(n, f, a) {
       
  5487 	var i;
       
  5488 
       
  5489 	if (!a)
       
  5490 		a = new Array();
       
  5491 
       
  5492 	if (f(n))
       
  5493 		a[a.length] = n;
       
  5494 
       
  5495 	if (n.hasChildNodes()) {
       
  5496 		for (i=0; i<n.childNodes.length; i++)
       
  5497 			tinyMCE.selectNodes(n.childNodes[i], f, a);
       
  5498 	}
       
  5499 
       
  5500 	return a;
       
  5501 };
       
  5502 
       
  5503 TinyMCE_Engine.prototype.addCSSClass = function(e, c, b) {
       
  5504 	var o = this.removeCSSClass(e, c);
       
  5505 	return e.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c;
       
  5506 };
       
  5507 
       
  5508 TinyMCE_Engine.prototype.removeCSSClass = function(e, c) {
       
  5509 	c = e.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' ');
       
  5510 	return e.className = c != ' ' ? c : '';
       
  5511 };
       
  5512 
       
  5513 TinyMCE_Engine.prototype.hasCSSClass = function(n, c) {
       
  5514 	return new RegExp('\\b' + c + '\\b', 'g').test(n.className);
       
  5515 };
       
  5516 
       
  5517 TinyMCE_Engine.prototype.renameElement = function(e, n, d) {
       
  5518 	var ne, i, ar;
       
  5519 
       
  5520 	d = typeof(d) == "undefined" ? tinyMCE.selectedInstance.getDoc() : d;
       
  5521 
       
  5522 	if (e) {
       
  5523 		ne = d.createElement(n);
       
  5524 
       
  5525 		ar = e.attributes;
       
  5526 		for (i=ar.length-1; i>-1; i--) {
       
  5527 			if (ar[i].specified && ar[i].nodeValue)
       
  5528 				ne.setAttribute(ar[i].nodeName.toLowerCase(), ar[i].nodeValue);
       
  5529 		}
       
  5530 
       
  5531 		ar = e.childNodes;
       
  5532 		for (i=0; i<ar.length; i++)
       
  5533 			ne.appendChild(ar[i].cloneNode(true));
       
  5534 
       
  5535 		e.parentNode.replaceChild(ne, e);
       
  5536 	}
       
  5537 };
       
  5538 
       
  5539 TinyMCE_Engine.prototype.getViewPort = function(w) {
       
  5540 	var d = w.document, m = d.compatMode == 'CSS1Compat', b = d.body, de = d.documentElement;
       
  5541 
       
  5542 	return {
       
  5543 		left : w.pageXOffset || (m ? de.scrollLeft : b.scrollLeft),
       
  5544 		top : w.pageYOffset || (m ? de.scrollTop : b.scrollTop),
       
  5545 		width : w.innerWidth || (m ? de.clientWidth : b.clientWidth),
       
  5546 		height : w.innerHeight || (m ? de.clientHeight : b.clientHeight)
       
  5547 	};
       
  5548 };
       
  5549 
       
  5550 TinyMCE_Engine.prototype.getStyle = function(n, na, d) {
       
  5551 	if (!n)
       
  5552 		return false;
       
  5553 
       
  5554 	// Gecko
       
  5555 	if (tinyMCE.isGecko && n.ownerDocument.defaultView) {
       
  5556 		try {
       
  5557 			return n.ownerDocument.defaultView.getComputedStyle(n, null).getPropertyValue(na);
       
  5558 		} catch (n) {
       
  5559 			// Old safari might fail
       
  5560 			return null;
       
  5561 		}
       
  5562 	}
       
  5563 
       
  5564 	// Camelcase it, if needed
       
  5565 	na = na.replace(/-(\D)/g, function(a, b){
       
  5566 		return b.toUpperCase();
       
  5567 	});
       
  5568 
       
  5569 	// IE & Opera
       
  5570 	if (n.currentStyle)
       
  5571 		return n.currentStyle[na];
       
  5572 
       
  5573 	return false;
       
  5574 };
       
  5575 
       
  5576 /* file:jscripts/tiny_mce/classes/TinyMCE_URL.class.js */
       
  5577 
       
  5578 TinyMCE_Engine.prototype.parseURL = function(url_str) {
       
  5579 	var urlParts = new Array();
       
  5580 
       
  5581 	if (url_str) {
       
  5582 		var pos, lastPos;
       
  5583 
       
  5584 		// Parse protocol part
       
  5585 		pos = url_str.indexOf('://');
       
  5586 		if (pos != -1) {
       
  5587 			urlParts['protocol'] = url_str.substring(0, pos);
       
  5588 			lastPos = pos + 3;
       
  5589 		}
       
  5590 
       
  5591 		// Find port or path start
       
  5592 		for (var i=lastPos; i<url_str.length; i++) {
       
  5593 			var chr = url_str.charAt(i);
       
  5594 
       
  5595 			if (chr == ':')
       
  5596 				break;
       
  5597 
       
  5598 			if (chr == '/')
       
  5599 				break;
       
  5600 		}
       
  5601 		pos = i;
       
  5602 
       
  5603 		// Get host
       
  5604 		urlParts['host'] = url_str.substring(lastPos, pos);
       
  5605 
       
  5606 		// Get port
       
  5607 		urlParts['port'] = "";
       
  5608 		lastPos = pos;
       
  5609 		if (url_str.charAt(pos) == ':') {
       
  5610 			pos = url_str.indexOf('/', lastPos);
       
  5611 			urlParts['port'] = url_str.substring(lastPos+1, pos);
       
  5612 		}
       
  5613 
       
  5614 		// Get path
       
  5615 		lastPos = pos;
       
  5616 		pos = url_str.indexOf('?', lastPos);
       
  5617 
       
  5618 		if (pos == -1)
       
  5619 			pos = url_str.indexOf('#', lastPos);
       
  5620 
       
  5621 		if (pos == -1)
       
  5622 			pos = url_str.length;
       
  5623 
       
  5624 		urlParts['path'] = url_str.substring(lastPos, pos);
       
  5625 
       
  5626 		// Get query
       
  5627 		lastPos = pos;
       
  5628 		if (url_str.charAt(pos) == '?') {
       
  5629 			pos = url_str.indexOf('#');
       
  5630 			pos = (pos == -1) ? url_str.length : pos;
       
  5631 			urlParts['query'] = url_str.substring(lastPos+1, pos);
       
  5632 		}
       
  5633 
       
  5634 		// Get anchor
       
  5635 		lastPos = pos;
       
  5636 		if (url_str.charAt(pos) == '#') {
       
  5637 			pos = url_str.length;
       
  5638 			urlParts['anchor'] = url_str.substring(lastPos+1, pos);
       
  5639 		}
       
  5640 	}
       
  5641 
       
  5642 	return urlParts;
       
  5643 };
       
  5644 
       
  5645 TinyMCE_Engine.prototype.serializeURL = function(up) {
       
  5646 	var o = "";
       
  5647 
       
  5648 	if (up['protocol'])
       
  5649 		o += up['protocol'] + "://";
       
  5650 
       
  5651 	if (up['host'])
       
  5652 		o += up['host'];
       
  5653 
       
  5654 	if (up['port'])
       
  5655 		o += ":" + up['port'];
       
  5656 
       
  5657 	if (up['path'])
       
  5658 		o += up['path'];
       
  5659 
       
  5660 	if (up['query'])
       
  5661 		o += "?" + up['query'];
       
  5662 
       
  5663 	if (up['anchor'])
       
  5664 		o += "#" + up['anchor'];
       
  5665 
       
  5666 	return o;
       
  5667 };
       
  5668 
       
  5669 TinyMCE_Engine.prototype.convertAbsoluteURLToRelativeURL = function(base_url, url_to_relative) {
       
  5670 	var baseURL = this.parseURL(base_url);
       
  5671 	var targetURL = this.parseURL(url_to_relative);
       
  5672 	var strTok1;
       
  5673 	var strTok2;
       
  5674 	var breakPoint = 0;
       
  5675 	var outPath = "";
       
  5676 	var forceSlash = false;
       
  5677 
       
  5678 	if (targetURL.path == "")
       
  5679 		targetURL.path = "/";
       
  5680 	else
       
  5681 		forceSlash = true;
       
  5682 
       
  5683 	// Crop away last path part
       
  5684 	base_url = baseURL.path.substring(0, baseURL.path.lastIndexOf('/'));
       
  5685 	strTok1 = base_url.split('/');
       
  5686 	strTok2 = targetURL.path.split('/');
       
  5687 
       
  5688 	if (strTok1.length >= strTok2.length) {
       
  5689 		for (var i=0; i<strTok1.length; i++) {
       
  5690 			if (i >= strTok2.length || strTok1[i] != strTok2[i]) {
       
  5691 				breakPoint = i + 1;
       
  5692 				break;
       
  5693 			}
       
  5694 		}
       
  5695 	}
       
  5696 
       
  5697 	if (strTok1.length < strTok2.length) {
       
  5698 		for (var i=0; i<strTok2.length; i++) {
       
  5699 			if (i >= strTok1.length || strTok1[i] != strTok2[i]) {
       
  5700 				breakPoint = i + 1;
       
  5701 				break;
       
  5702 			}
       
  5703 		}
       
  5704 	}
       
  5705 
       
  5706 	if (breakPoint == 1)
       
  5707 		return targetURL.path;
       
  5708 
       
  5709 	for (var i=0; i<(strTok1.length-(breakPoint-1)); i++)
       
  5710 		outPath += "../";
       
  5711 
       
  5712 	for (var i=breakPoint-1; i<strTok2.length; i++) {
       
  5713 		if (i != (breakPoint-1))
       
  5714 			outPath += "/" + strTok2[i];
       
  5715 		else
       
  5716 			outPath += strTok2[i];
       
  5717 	}
       
  5718 
       
  5719 	targetURL.protocol = null;
       
  5720 	targetURL.host = null;
       
  5721 	targetURL.port = null;
       
  5722 	targetURL.path = outPath == "" && forceSlash ? "/" : outPath;
       
  5723 
       
  5724 	// Remove document prefix from local anchors
       
  5725 	var fileName = baseURL.path;
       
  5726 	var pos;
       
  5727 
       
  5728 	if ((pos = fileName.lastIndexOf('/')) != -1)
       
  5729 		fileName = fileName.substring(pos + 1);
       
  5730 
       
  5731 	// Is local anchor
       
  5732 	if (fileName == targetURL.path && targetURL.anchor != "")
       
  5733 		targetURL.path = "";
       
  5734 
       
  5735 	// If empty and not local anchor force filename or slash
       
  5736 	if (targetURL.path == "" && !targetURL.anchor)
       
  5737 		targetURL.path = fileName != "" ? fileName : "/";
       
  5738 
       
  5739 	return this.serializeURL(targetURL);
       
  5740 };
       
  5741 
       
  5742 TinyMCE_Engine.prototype.convertRelativeToAbsoluteURL = function(base_url, relative_url) {
       
  5743 	var baseURL = this.parseURL(base_url), baseURLParts, relURLParts;
       
  5744 	var relURL = this.parseURL(relative_url);
       
  5745 
       
  5746 	if (relative_url == "" || relative_url.indexOf('://') != -1 || /^(mailto:|javascript:|#|\/)/.test(relative_url))
       
  5747 		return relative_url;
       
  5748 
       
  5749 	// Split parts
       
  5750 	baseURLParts = baseURL['path'].split('/');
       
  5751 	relURLParts = relURL['path'].split('/');
       
  5752 
       
  5753 	// Remove empty chunks
       
  5754 	var newBaseURLParts = new Array();
       
  5755 	for (var i=baseURLParts.length-1; i>=0; i--) {
       
  5756 		if (baseURLParts[i].length == 0)
       
  5757 			continue;
       
  5758 
       
  5759 		newBaseURLParts[newBaseURLParts.length] = baseURLParts[i];
       
  5760 	}
       
  5761 	baseURLParts = newBaseURLParts.reverse();
       
  5762 
       
  5763 	// Merge relURLParts chunks
       
  5764 	var newRelURLParts = new Array();
       
  5765 	var numBack = 0;
       
  5766 	for (var i=relURLParts.length-1; i>=0; i--) {
       
  5767 		if (relURLParts[i].length == 0 || relURLParts[i] == ".")
       
  5768 			continue;
       
  5769 
       
  5770 		if (relURLParts[i] == '..') {
       
  5771 			numBack++;
       
  5772 			continue;
       
  5773 		}
       
  5774 
       
  5775 		if (numBack > 0) {
       
  5776 			numBack--;
       
  5777 			continue;
       
  5778 		}
       
  5779 
       
  5780 		newRelURLParts[newRelURLParts.length] = relURLParts[i];
       
  5781 	}
       
  5782 
       
  5783 	relURLParts = newRelURLParts.reverse();
       
  5784 
       
  5785 	// Remove end from absolute path
       
  5786 	var len = baseURLParts.length-numBack;
       
  5787 	var absPath = (len <= 0 ? "" : "/") + baseURLParts.slice(0, len).join('/') + "/" + relURLParts.join('/');
       
  5788 	var start = "", end = "";
       
  5789 
       
  5790 	// Build output URL
       
  5791 	relURL.protocol = baseURL.protocol;
       
  5792 	relURL.host = baseURL.host;
       
  5793 	relURL.port = baseURL.port;
       
  5794 
       
  5795 	// Re-add trailing slash if it's removed
       
  5796 	if (relURL.path.charAt(relURL.path.length-1) == "/")
       
  5797 		absPath += "/";
       
  5798 
       
  5799 	relURL.path = absPath;
       
  5800 
       
  5801 	return this.serializeURL(relURL);
       
  5802 };
       
  5803 
       
  5804 TinyMCE_Engine.prototype.convertURL = function(url, node, on_save) {
       
  5805 	var prot = document.location.protocol;
       
  5806 	var host = document.location.hostname;
       
  5807 	var port = document.location.port;
       
  5808 
       
  5809 	// Pass through file protocol
       
  5810 	if (prot == "file:")
       
  5811 		return url;
       
  5812 
       
  5813 	// Something is wrong, remove weirdness
       
  5814 	url = tinyMCE.regexpReplace(url, '(http|https):///', '/');
       
  5815 
       
  5816 	// Mailto link or anchor (Pass through)
       
  5817 	if (url.indexOf('mailto:') != -1 || url.indexOf('javascript:') != -1 || tinyMCE.regexpReplace(url,'[ \t\r\n\+]|%20','').charAt(0) == "#")
       
  5818 		return url;
       
  5819 
       
  5820 	// Fix relative/Mozilla
       
  5821 	if (!tinyMCE.isIE && !on_save && url.indexOf("://") == -1 && url.charAt(0) != '/')
       
  5822 		return tinyMCE.settings['base_href'] + url;
       
  5823 
       
  5824 	// Handle relative URLs
       
  5825 	if (on_save && tinyMCE.getParam('relative_urls')) {
       
  5826 		var curl = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], url);
       
  5827 		if (curl.charAt(0) == '/')
       
  5828 			curl = tinyMCE.settings['document_base_prefix'] + curl;
       
  5829 
       
  5830 		var urlParts = tinyMCE.parseURL(curl);
       
  5831 		var tmpUrlParts = tinyMCE.parseURL(tinyMCE.settings['document_base_url']);
       
  5832 
       
  5833 		// Force relative
       
  5834 		if (urlParts['host'] == tmpUrlParts['host'] && (urlParts['port'] == tmpUrlParts['port']))
       
  5835 			return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings['document_base_url'], curl);
       
  5836 	}
       
  5837 
       
  5838 	// Handle absolute URLs
       
  5839 	if (!tinyMCE.getParam('relative_urls')) {
       
  5840 		var urlParts = tinyMCE.parseURL(url);
       
  5841 		var baseUrlParts = tinyMCE.parseURL(tinyMCE.settings['base_href']);
       
  5842 
       
  5843 		// Force absolute URLs from relative URLs
       
  5844 		url = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], url);
       
  5845 
       
  5846 		// If anchor and path is the same page
       
  5847 		if (urlParts['anchor'] && urlParts['path'] == baseUrlParts['path'])
       
  5848 			return "#" + urlParts['anchor'];
       
  5849 	}
       
  5850 
       
  5851 	// Remove current domain
       
  5852 	if (tinyMCE.getParam('remove_script_host')) {
       
  5853 		var start = "", portPart = "";
       
  5854 
       
  5855 		if (port != "")
       
  5856 			portPart = ":" + port;
       
  5857 
       
  5858 		start = prot + "//" + host + portPart + "/";
       
  5859 
       
  5860 		if (url.indexOf(start) == 0)
       
  5861 			url = url.substring(start.length-1);
       
  5862 	}
       
  5863 
       
  5864 	return url;
       
  5865 };
       
  5866 
       
  5867 TinyMCE_Engine.prototype.convertAllRelativeURLs = function(body) {
       
  5868 	var i, elms, src, href, mhref, msrc;
       
  5869 
       
  5870 	// Convert all image URL:s to absolute URL
       
  5871 	elms = body.getElementsByTagName("img");
       
  5872 	for (i=0; i<elms.length; i++) {
       
  5873 		src = tinyMCE.getAttrib(elms[i], 'src');
       
  5874 
       
  5875 		msrc = tinyMCE.getAttrib(elms[i], 'mce_src');
       
  5876 		if (msrc != "")
       
  5877 			src = msrc;
       
  5878 
       
  5879 		if (src != "") {
       
  5880 			src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], src);
       
  5881 			elms[i].setAttribute("src", src);
       
  5882 		}
       
  5883 	}
       
  5884 
       
  5885 	// Convert all link URL:s to absolute URL
       
  5886 	elms = body.getElementsByTagName("a");
       
  5887 	for (i=0; i<elms.length; i++) {
       
  5888 		href = tinyMCE.getAttrib(elms[i], 'href');
       
  5889 
       
  5890 		mhref = tinyMCE.getAttrib(elms[i], 'mce_href');
       
  5891 		if (mhref != "")
       
  5892 			href = mhref;
       
  5893 
       
  5894 		if (href && href != "") {
       
  5895 			href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], href);
       
  5896 			elms[i].setAttribute("href", href);
       
  5897 		}
       
  5898 	}
       
  5899 };
       
  5900 
       
  5901 /* file:jscripts/tiny_mce/classes/TinyMCE_Array.class.js */
       
  5902 
       
  5903 TinyMCE_Engine.prototype.clearArray = function(a) {
       
  5904 	var n;
       
  5905 
       
  5906 	for (n in a)
       
  5907 		a[n] = null;
       
  5908 
       
  5909 	return a;
       
  5910 };
       
  5911 
       
  5912 TinyMCE_Engine.prototype.explode = function(d, s) {
       
  5913 	var ar = s.split(d), oar = new Array(), i;
       
  5914 
       
  5915 	for (i = 0; i<ar.length; i++) {
       
  5916 		if (ar[i] != "")
       
  5917 			oar[oar.length] = ar[i];
       
  5918 	}
       
  5919 
       
  5920 	return oar;
       
  5921 };
       
  5922 
       
  5923 /* file:jscripts/tiny_mce/classes/TinyMCE_Event.class.js */
       
  5924 
       
  5925 TinyMCE_Engine.prototype._setEventsEnabled = function(node, state) {
       
  5926 	var evs, x, y, elms, i, event;
       
  5927 	var events = ['onfocus','onblur','onclick','ondblclick',
       
  5928 				'onmousedown','onmouseup','onmouseover','onmousemove',
       
  5929 				'onmouseout','onkeypress','onkeydown','onkeydown','onkeyup'];
       
  5930 
       
  5931 	evs = tinyMCE.settings['event_elements'].split(',');
       
  5932 	for (y=0; y<evs.length; y++){
       
  5933 		elms = node.getElementsByTagName(evs[y]);
       
  5934 		for (i=0; i<elms.length; i++) {
       
  5935 			event = "";
       
  5936 
       
  5937 			for (x=0; x<events.length; x++) {
       
  5938 				if ((event = tinyMCE.getAttrib(elms[i], events[x])) != '') {
       
  5939 					event = tinyMCE.cleanupEventStr("" + event);
       
  5940 
       
  5941 					if (!state)
       
  5942 						event = "return true;" + event;
       
  5943 					else
       
  5944 						event = event.replace(/^return true;/gi, '');
       
  5945 
       
  5946 					elms[i].removeAttribute(events[x]);
       
  5947 					elms[i].setAttribute(events[x], event);
       
  5948 				}
       
  5949 			}
       
  5950 		}
       
  5951 	}
       
  5952 };
       
  5953 
       
  5954 TinyMCE_Engine.prototype._eventPatch = function(editor_id) {
       
  5955 	var n, inst, win, e;
       
  5956 
       
  5957 	// Remove odd, error
       
  5958 	if (typeof(tinyMCE) == "undefined")
       
  5959 		return true;
       
  5960 
       
  5961 	try {
       
  5962 		// Try selected instance first
       
  5963 		if (tinyMCE.selectedInstance) {
       
  5964 			win = tinyMCE.selectedInstance.getWin();
       
  5965 
       
  5966 			if (win && win.event) {
       
  5967 				e = win.event;
       
  5968 
       
  5969 				if (!e.target)
       
  5970 					e.target = e.srcElement;
       
  5971 
       
  5972 				TinyMCE_Engine.prototype.handleEvent(e);
       
  5973 				return;
       
  5974 			}
       
  5975 		}
       
  5976 
       
  5977 		// Search for it
       
  5978 		for (n in tinyMCE.instances) {
       
  5979 			inst = tinyMCE.instances[n];
       
  5980 
       
  5981 			if (!tinyMCE.isInstance(inst))
       
  5982 				continue;
       
  5983 
       
  5984 			inst.select();
       
  5985 			win = inst.getWin();
       
  5986 
       
  5987 			if (win && win.event) {
       
  5988 				e = win.event;
       
  5989 
       
  5990 				if (!e.target)
       
  5991 					e.target = e.srcElement;
       
  5992 
       
  5993 				TinyMCE_Engine.prototype.handleEvent(e);
       
  5994 				return;
       
  5995 			}
       
  5996 		}
       
  5997 	} catch (ex) {
       
  5998 		// Ignore error if iframe is pointing to external URL
       
  5999 	}
       
  6000 };
       
  6001 
       
  6002 TinyMCE_Engine.prototype.findEvent = function(e) {
       
  6003 	var n, inst;
       
  6004 
       
  6005 	if (e)
       
  6006 		return e;
       
  6007 
       
  6008 	for (n in tinyMCE.instances) {
       
  6009 		inst = tinyMCE.instances[n];
       
  6010 
       
  6011 		if (tinyMCE.isInstance(inst) && inst.getWin().event)
       
  6012 			return inst.getWin().event;
       
  6013 	}
       
  6014 
       
  6015 	return null;
       
  6016 };
       
  6017 
       
  6018 TinyMCE_Engine.prototype.unloadHandler = function() {
       
  6019 	tinyMCE.triggerSave(true, true);
       
  6020 };
       
  6021 
       
  6022 TinyMCE_Engine.prototype.addEventHandlers = function(inst) {
       
  6023 	this.setEventHandlers(inst, 1);
       
  6024 };
       
  6025 
       
  6026 TinyMCE_Engine.prototype.setEventHandlers = function(inst, s) {
       
  6027 	var doc = inst.getDoc(), ie, ot, i, f = s ? tinyMCE.addEvent : tinyMCE.removeEvent;
       
  6028 
       
  6029 	ie = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'controlselect', 'dblclick'];
       
  6030 	ot = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'focus', 'blur', 'dragdrop'];
       
  6031 
       
  6032 	inst.switchSettings();
       
  6033 
       
  6034 	if (tinyMCE.isIE) {
       
  6035 		for (i=0; i<ie.length; i++)
       
  6036 			f(doc, ie[i], TinyMCE_Engine.prototype._eventPatch);
       
  6037 	} else {
       
  6038 		for (i=0; i<ot.length; i++)
       
  6039 			f(doc, ot[i], tinyMCE.handleEvent);
       
  6040 
       
  6041 		// Force designmode
       
  6042 		try {
       
  6043 			doc.designMode = "On";
       
  6044 		} catch (e) {
       
  6045 			// Ignore
       
  6046 		}
       
  6047 	}
       
  6048 };
       
  6049 
       
  6050 TinyMCE_Engine.prototype.onMouseMove = function() {
       
  6051 	var inst, lh;
       
  6052 
       
  6053 	// Fix for IE7 bug where it's not restoring hover on anchors correctly
       
  6054 	if (tinyMCE.lastHover) {
       
  6055 		lh = tinyMCE.lastHover;
       
  6056 
       
  6057 		// Call out on menus and refresh class on normal buttons
       
  6058 		if (lh.className.indexOf('mceMenu') != -1)
       
  6059 			tinyMCE._menuButtonEvent('out', lh);
       
  6060 		else
       
  6061 			lh.className = lh.className;
       
  6062 
       
  6063 		tinyMCE.lastHover = null;
       
  6064 	}
       
  6065 
       
  6066 	if (!tinyMCE.hasMouseMoved) {
       
  6067 		inst = tinyMCE.selectedInstance;
       
  6068 
       
  6069 		// Workaround for bug #1437457 (Odd MSIE bug)
       
  6070 		if (inst.isFocused) {
       
  6071 			inst.undoBookmark = inst.selection.getBookmark();
       
  6072 			tinyMCE.hasMouseMoved = true;
       
  6073 		}
       
  6074 	}
       
  6075 
       
  6076 //	tinyMCE.cancelEvent(inst.getWin().event);
       
  6077 //	return false;
       
  6078 };
       
  6079 
       
  6080 TinyMCE_Engine.prototype.cancelEvent = function(e) {
       
  6081 	if (!e)
       
  6082 		return false;
       
  6083 
       
  6084 	if (tinyMCE.isIE) {
       
  6085 		e.returnValue = false;
       
  6086 		e.cancelBubble = true;
       
  6087 	} else {
       
  6088 		e.preventDefault();
       
  6089 		e.stopPropagation && e.stopPropagation();
       
  6090 	}
       
  6091 
       
  6092 	return false;
       
  6093 };
       
  6094 
       
  6095 TinyMCE_Engine.prototype.addEvent = function(o, n, h) {
       
  6096 	// Add cleanup for all non unload events
       
  6097 	if (n != 'unload') {
       
  6098 		function clean() {
       
  6099 			var ex;
       
  6100 
       
  6101 			try {
       
  6102 				tinyMCE.removeEvent(o, n, h);
       
  6103 				tinyMCE.removeEvent(window, 'unload', clean);
       
  6104 				o = n = h = null;
       
  6105 			} catch (ex) {
       
  6106 				// IE may produce access denied exception on unload
       
  6107 			}
       
  6108 		}
       
  6109 
       
  6110 		// Add memory cleaner
       
  6111 		tinyMCE.addEvent(window, 'unload', clean);
       
  6112 	}
       
  6113 
       
  6114 	if (o.attachEvent)
       
  6115 		o.attachEvent("on" + n, h);
       
  6116 	else
       
  6117 		o.addEventListener(n, h, false);
       
  6118 };
       
  6119 
       
  6120 TinyMCE_Engine.prototype.removeEvent = function(o, n, h) {
       
  6121 	if (o.detachEvent)
       
  6122 		o.detachEvent("on" + n, h);
       
  6123 	else
       
  6124 		o.removeEventListener(n, h, false);
       
  6125 };
       
  6126 
       
  6127 TinyMCE_Engine.prototype.addSelectAccessibility = function(e, s, w) {
       
  6128 	// Add event handlers 
       
  6129 	if (!s._isAccessible) {
       
  6130 		s.onkeydown = tinyMCE.accessibleEventHandler;
       
  6131 		s.onblur = tinyMCE.accessibleEventHandler;
       
  6132 		s._isAccessible = true;
       
  6133 		s._win = w;
       
  6134 	}
       
  6135 
       
  6136 	return false;
       
  6137 };
       
  6138 
       
  6139 TinyMCE_Engine.prototype.accessibleEventHandler = function(e) {
       
  6140 	var win = this._win;
       
  6141 	e = tinyMCE.isIE ? win.event : e;
       
  6142 	var elm = tinyMCE.isIE ? e.srcElement : e.target;
       
  6143 
       
  6144 	// Unpiggyback onchange on blur
       
  6145 	if (e.type == "blur") {
       
  6146 		if (elm.oldonchange) {
       
  6147 			elm.onchange = elm.oldonchange;
       
  6148 			elm.oldonchange = null;
       
  6149 		}
       
  6150 
       
  6151 		return true;
       
  6152 	}
       
  6153 
       
  6154 	// Piggyback onchange
       
  6155 	if (elm.nodeName == "SELECT" && !elm.oldonchange) {
       
  6156 		elm.oldonchange = elm.onchange;
       
  6157 		elm.onchange = null;
       
  6158 	}
       
  6159 
       
  6160 	// Execute onchange and remove piggyback
       
  6161 	if (e.keyCode == 13 || e.keyCode == 32) {
       
  6162 		elm.onchange = elm.oldonchange;
       
  6163 		elm.onchange();
       
  6164 		elm.oldonchange = null;
       
  6165 
       
  6166 		tinyMCE.cancelEvent(e);
       
  6167 		return false;
       
  6168 	}
       
  6169 
       
  6170 	return true;
       
  6171 };
       
  6172 
       
  6173 TinyMCE_Engine.prototype._resetIframeHeight = function() {
       
  6174 	var ife;
       
  6175 
       
  6176 	if (tinyMCE.isRealIE) {
       
  6177 		ife = tinyMCE.selectedInstance.iframeElement;
       
  6178 
       
  6179 /*		if (ife._oldWidth) {
       
  6180 			ife.style.width = ife._oldWidth;
       
  6181 			ife.width = ife._oldWidth;
       
  6182 		}*/
       
  6183 
       
  6184 		if (ife._oldHeight) {
       
  6185 			ife.style.height = ife._oldHeight;
       
  6186 			ife.height = ife._oldHeight;
       
  6187 		}
       
  6188 	}
       
  6189 };
       
  6190 
       
  6191 /* file:jscripts/tiny_mce/classes/TinyMCE_Selection.class.js */
       
  6192 
       
  6193 function TinyMCE_Selection(inst) {
       
  6194 	this.instance = inst;
       
  6195 };
       
  6196 
       
  6197 TinyMCE_Selection.prototype = {
       
  6198 	getSelectedHTML : function() {
       
  6199 		var inst = this.instance;
       
  6200 		var e, r = this.getRng(), h;
       
  6201 
       
  6202 		if (!r)
       
  6203 			return null;
       
  6204 
       
  6205 		e = document.createElement("body");
       
  6206 
       
  6207 		if (r.cloneContents)
       
  6208 			e.appendChild(r.cloneContents());
       
  6209 		else if (typeof(r.item) != 'undefined' || typeof(r.htmlText) != 'undefined')
       
  6210 			e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;
       
  6211 		else
       
  6212 			e.innerHTML = r.toString(); // Failed, use text for now
       
  6213 
       
  6214 		h = tinyMCE._cleanupHTML(inst, inst.contentDocument, inst.settings, e, e, false, true, false);
       
  6215 
       
  6216 		// When editing always use fonts internaly
       
  6217 		//if (tinyMCE.getParam("convert_fonts_to_spans"))
       
  6218 		//	tinyMCE.convertSpansToFonts(inst.getDoc());
       
  6219 
       
  6220 		return h;
       
  6221 	},
       
  6222 
       
  6223 	getSelectedText : function() {
       
  6224 		var inst = this.instance;
       
  6225 		var d, r, s, t;
       
  6226 
       
  6227 		if (tinyMCE.isIE) {
       
  6228 			d = inst.getDoc();
       
  6229 
       
  6230 			if (d.selection.type == "Text") {
       
  6231 				r = d.selection.createRange();
       
  6232 				t = r.text;
       
  6233 			} else
       
  6234 				t = '';
       
  6235 		} else {
       
  6236 			s = this.getSel();
       
  6237 
       
  6238 			if (s && s.toString)
       
  6239 				t = s.toString();
       
  6240 			else
       
  6241 				t = '';
       
  6242 		}
       
  6243 
       
  6244 		return t;
       
  6245 	},
       
  6246 
       
  6247 	getBookmark : function(simple) {
       
  6248 		var inst = this.instance;
       
  6249 		var rng = this.getRng();
       
  6250 		var doc = inst.getDoc(), b = inst.getBody();
       
  6251 		var sp, le, s, e, nl, i, si, ei, w;
       
  6252 		var trng, sx, sy, xx = -999999999, vp = inst.getViewPort();
       
  6253 
       
  6254 		sx = vp.left;
       
  6255 		sy = vp.top;
       
  6256 
       
  6257 		if (tinyMCE.isSafari || tinyMCE.isOpera || simple)
       
  6258 			return {rng : rng, scrollX : sx, scrollY : sy};
       
  6259 
       
  6260 		if (tinyMCE.isIE) {
       
  6261 			if (rng.item) {
       
  6262 				e = rng.item(0);
       
  6263 
       
  6264 				nl = b.getElementsByTagName(e.nodeName);
       
  6265 				for (i=0; i<nl.length; i++) {
       
  6266 					if (e == nl[i]) {
       
  6267 						sp = i;
       
  6268 						break;
       
  6269 					}
       
  6270 				}
       
  6271 
       
  6272 				return {
       
  6273 					tag : e.nodeName,
       
  6274 					index : sp,
       
  6275 					scrollX : sx,
       
  6276 					scrollY : sy
       
  6277 				};
       
  6278 			} else {
       
  6279 				trng = doc.body.createTextRange();
       
  6280 				trng.moveToElementText(inst.getBody());
       
  6281 				trng.collapse(true);
       
  6282 				bp = Math.abs(trng.move('character', xx));
       
  6283 
       
  6284 				trng = rng.duplicate();
       
  6285 				trng.collapse(true);
       
  6286 				sp = Math.abs(trng.move('character', xx));
       
  6287 
       
  6288 				trng = rng.duplicate();
       
  6289 				trng.collapse(false);
       
  6290 				le = Math.abs(trng.move('character', xx)) - sp;
       
  6291 
       
  6292 				return {
       
  6293 					start : sp - bp,
       
  6294 					length : le,
       
  6295 					scrollX : sx,
       
  6296 					scrollY : sy
       
  6297 				};
       
  6298 			}
       
  6299 		}
       
  6300 
       
  6301 		if (tinyMCE.isGecko) {
       
  6302 			s = this.getSel();
       
  6303 			e = this.getFocusElement();
       
  6304 
       
  6305 			if (!s)
       
  6306 				return null;
       
  6307 
       
  6308 			if (e && e.nodeName == 'IMG') {
       
  6309 				/*nl = b.getElementsByTagName('IMG');
       
  6310 				for (i=0; i<nl.length; i++) {
       
  6311 					if (e == nl[i]) {
       
  6312 						sp = i;
       
  6313 						break;
       
  6314 					}
       
  6315 				}*/
       
  6316 
       
  6317 				return {
       
  6318 					start : -1,
       
  6319 					end : -1,
       
  6320 					index : sp,
       
  6321 					scrollX : sx,
       
  6322 					scrollY : sy
       
  6323 				};
       
  6324 			}
       
  6325 
       
  6326 			// Caret or selection
       
  6327 			if (s.anchorNode == s.focusNode && s.anchorOffset == s.focusOffset) {
       
  6328 				e = this._getPosText(b, s.anchorNode, s.focusNode);
       
  6329 
       
  6330 				if (!e)
       
  6331 					return {scrollX : sx, scrollY : sy};
       
  6332 
       
  6333 				return {
       
  6334 					start : e.start + s.anchorOffset,
       
  6335 					end : e.end + s.focusOffset,
       
  6336 					scrollX : sx,
       
  6337 					scrollY : sy
       
  6338 				};
       
  6339 			} else {
       
  6340 				e = this._getPosText(b, rng.startContainer, rng.endContainer);
       
  6341 
       
  6342 				if (!e)
       
  6343 					return {scrollX : sx, scrollY : sy};
       
  6344 
       
  6345 				return {
       
  6346 					start : e.start + rng.startOffset,
       
  6347 					end : e.end + rng.endOffset,
       
  6348 					scrollX : sx,
       
  6349 					scrollY : sy
       
  6350 				};
       
  6351 			}
       
  6352 		}
       
  6353 
       
  6354 		return null;
       
  6355 	},
       
  6356 
       
  6357 	moveToBookmark : function(bookmark) {
       
  6358 		var inst = this.instance;
       
  6359 		var rng, nl, i, ex, b = inst.getBody(), sd;
       
  6360 		var doc = inst.getDoc();
       
  6361 		var win = inst.getWin();
       
  6362 		var sel = this.getSel();
       
  6363 
       
  6364 		if (!bookmark)
       
  6365 			return false;
       
  6366 
       
  6367 		if (tinyMCE.isSafari) {
       
  6368 			sel.setBaseAndExtent(bookmark.rng.startContainer, bookmark.rng.startOffset, bookmark.rng.endContainer, bookmark.rng.endOffset);
       
  6369 			return true;
       
  6370 		}
       
  6371 
       
  6372 		if (tinyMCE.isRealIE) {
       
  6373 			if (bookmark.rng) {
       
  6374 				try {
       
  6375 					bookmark.rng.select();
       
  6376 				} catch (ex) {
       
  6377 					// Ignore
       
  6378 				}
       
  6379 
       
  6380 				return true;
       
  6381 			}
       
  6382 
       
  6383 			win.focus();
       
  6384 
       
  6385 			if (bookmark.tag) {
       
  6386 				rng = b.createControlRange();
       
  6387 
       
  6388 				nl = b.getElementsByTagName(bookmark.tag);
       
  6389 
       
  6390 				if (nl.length > bookmark.index) {
       
  6391 					try {
       
  6392 						rng.addElement(nl[bookmark.index]);
       
  6393 					} catch (ex) {
       
  6394 						// Might be thrown if the node no longer exists
       
  6395 					}
       
  6396 				}
       
  6397 			} else {
       
  6398 				// Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs
       
  6399 				try {
       
  6400 					// Incorrect bookmark
       
  6401 					if (bookmark.start < 0)
       
  6402 						return true;
       
  6403 
       
  6404 					rng = inst.getSel().createRange();
       
  6405 					rng.moveToElementText(inst.getBody());
       
  6406 					rng.collapse(true);
       
  6407 					rng.moveStart('character', bookmark.start);
       
  6408 					rng.moveEnd('character', bookmark.length);
       
  6409 				} catch (ex) {
       
  6410 					return true;
       
  6411 				}
       
  6412 			}
       
  6413 
       
  6414 			rng.select();
       
  6415 
       
  6416 			win.scrollTo(bookmark.scrollX, bookmark.scrollY);
       
  6417 			return true;
       
  6418 		}
       
  6419 
       
  6420 		if (tinyMCE.isGecko || tinyMCE.isOpera) {
       
  6421 			if (!sel)
       
  6422 				return false;
       
  6423 
       
  6424 			if (bookmark.rng) {
       
  6425 				sel.removeAllRanges();
       
  6426 				sel.addRange(bookmark.rng);
       
  6427 			}
       
  6428 
       
  6429 			if (bookmark.start != -1 && bookmark.end != -1) {
       
  6430 				try {
       
  6431 					sd = this._getTextPos(b, bookmark.start, bookmark.end);
       
  6432 					rng = doc.createRange();
       
  6433 					rng.setStart(sd.startNode, sd.startOffset);
       
  6434 					rng.setEnd(sd.endNode, sd.endOffset);
       
  6435 					sel.removeAllRanges();
       
  6436 					sel.addRange(rng);
       
  6437 					win.focus();
       
  6438 				} catch (ex) {
       
  6439 					// Ignore
       
  6440 				}
       
  6441 			}
       
  6442 
       
  6443 			/*
       
  6444 			if (typeof(bookmark.index) != 'undefined') {
       
  6445 				tinyMCE.selectElements(b, 'IMG', function (n) {
       
  6446 					if (bookmark.index-- == 0) {
       
  6447 						// Select image in Gecko here
       
  6448 					}
       
  6449 
       
  6450 					return false;
       
  6451 				});
       
  6452 			}
       
  6453 			*/
       
  6454 
       
  6455 			win.scrollTo(bookmark.scrollX, bookmark.scrollY);
       
  6456 			return true;
       
  6457 		}
       
  6458 
       
  6459 		return false;
       
  6460 	},
       
  6461 
       
  6462 	_getPosText : function(r, sn, en) {
       
  6463 		var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
       
  6464 
       
  6465 		while ((n = w.nextNode()) != null) {
       
  6466 			if (n == sn)
       
  6467 				d.start = p;
       
  6468 
       
  6469 			if (n == en) {
       
  6470 				d.end = p;
       
  6471 				return d;
       
  6472 			}
       
  6473 
       
  6474 			p += n.nodeValue ? n.nodeValue.length : 0;
       
  6475 		}
       
  6476 
       
  6477 		return null;
       
  6478 	},
       
  6479 
       
  6480 	_getTextPos : function(r, sp, ep) {
       
  6481 		var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
       
  6482 
       
  6483 		while ((n = w.nextNode()) != null) {
       
  6484 			p += n.nodeValue ? n.nodeValue.length : 0;
       
  6485 
       
  6486 			if (p >= sp && !d.startNode) {
       
  6487 				d.startNode = n;
       
  6488 				d.startOffset = sp - (p - n.nodeValue.length);
       
  6489 			}
       
  6490 
       
  6491 			if (p >= ep) {
       
  6492 				d.endNode = n;
       
  6493 				d.endOffset = ep - (p - n.nodeValue.length);
       
  6494 
       
  6495 				return d;
       
  6496 			}
       
  6497 		}
       
  6498 
       
  6499 		return null;
       
  6500 	},
       
  6501 
       
  6502 	selectNode : function(node, collapse, select_text_node, to_start) {
       
  6503 		var inst = this.instance, sel, rng, nodes;
       
  6504 
       
  6505 		if (!node)
       
  6506 			return;
       
  6507 
       
  6508 		if (typeof(collapse) == "undefined")
       
  6509 			collapse = true;
       
  6510 
       
  6511 		if (typeof(select_text_node) == "undefined")
       
  6512 			select_text_node = false;
       
  6513 
       
  6514 		if (typeof(to_start) == "undefined")
       
  6515 			to_start = true;
       
  6516 
       
  6517 		if (inst.settings.auto_resize)
       
  6518 			inst.resizeToContent();
       
  6519 
       
  6520 		if (tinyMCE.isRealIE) {
       
  6521 			rng = inst.getDoc().body.createTextRange();
       
  6522 
       
  6523 			try {
       
  6524 				rng.moveToElementText(node);
       
  6525 
       
  6526 				if (collapse)
       
  6527 					rng.collapse(to_start);
       
  6528 
       
  6529 				rng.select();
       
  6530 			} catch (e) {
       
  6531 				// Throws illigal agrument in MSIE some times
       
  6532 			}
       
  6533 		} else {
       
  6534 			sel = this.getSel();
       
  6535 
       
  6536 			if (!sel)
       
  6537 				return;
       
  6538 
       
  6539 			if (tinyMCE.isSafari) {
       
  6540 				sel.setBaseAndExtent(node, 0, node, node.innerText.length);
       
  6541 
       
  6542 				if (collapse) {
       
  6543 					if (to_start)
       
  6544 						sel.collapseToStart();
       
  6545 					else
       
  6546 						sel.collapseToEnd();
       
  6547 				}
       
  6548 
       
  6549 				this.scrollToNode(node);
       
  6550 
       
  6551 				return;
       
  6552 			}
       
  6553 
       
  6554 			rng = inst.getDoc().createRange();
       
  6555 
       
  6556 			if (select_text_node) {
       
  6557 				// Find first textnode in tree
       
  6558 				nodes = tinyMCE.getNodeTree(node, new Array(), 3);
       
  6559 				if (nodes.length > 0)
       
  6560 					rng.selectNodeContents(nodes[0]);
       
  6561 				else
       
  6562 					rng.selectNodeContents(node);
       
  6563 			} else
       
  6564 				rng.selectNode(node);
       
  6565 
       
  6566 			if (collapse) {
       
  6567 				// Special treatment of textnode collapse
       
  6568 				if (!to_start && node.nodeType == 3) {
       
  6569 					rng.setStart(node, node.nodeValue.length);
       
  6570 					rng.setEnd(node, node.nodeValue.length);
       
  6571 				} else
       
  6572 					rng.collapse(to_start);
       
  6573 			}
       
  6574 
       
  6575 			sel.removeAllRanges();
       
  6576 			sel.addRange(rng);
       
  6577 		}
       
  6578 
       
  6579 		this.scrollToNode(node);
       
  6580 
       
  6581 		// Set selected element
       
  6582 		tinyMCE.selectedElement = null;
       
  6583 		if (node.nodeType == 1)
       
  6584 			tinyMCE.selectedElement = node;
       
  6585 	},
       
  6586 
       
  6587 	scrollToNode : function(node) {
       
  6588 		var inst = this.instance, w = inst.getWin(), vp = inst.getViewPort(), pos = tinyMCE.getAbsPosition(node), cvp, p, cwin;
       
  6589 
       
  6590 		// Only scroll if out of visible area
       
  6591 		if (pos.absLeft < vp.left || pos.absLeft > vp.left + vp.width || pos.absTop < vp.top || pos.absTop > vp.top + (vp.height-25))
       
  6592 			w.scrollTo(pos.absLeft, pos.absTop - vp.height + 25);
       
  6593 
       
  6594 		// Scroll container window
       
  6595 		if (inst.settings.auto_resize) {
       
  6596 			cwin = inst.getContainerWin();
       
  6597 			cvp = tinyMCE.getViewPort(cwin);
       
  6598 			p = this.getAbsPosition(node);
       
  6599 
       
  6600 			if (p.absLeft < cvp.left || p.absLeft > cvp.left + cvp.width || p.absTop < cvp.top || p.absTop > cvp.top + cvp.height)
       
  6601 				cwin.scrollTo(p.absLeft, p.absTop - cvp.height + 25);
       
  6602 		}
       
  6603 	},
       
  6604 
       
  6605 	getAbsPosition : function(n) {
       
  6606 		var pos = tinyMCE.getAbsPosition(n), ipos = tinyMCE.getAbsPosition(this.instance.iframeElement);
       
  6607 
       
  6608 		return {
       
  6609 			absLeft : ipos.absLeft + pos.absLeft,
       
  6610 			absTop : ipos.absTop + pos.absTop
       
  6611 		};
       
  6612 	},
       
  6613 
       
  6614 	getSel : function() {
       
  6615 		var inst = this.instance;
       
  6616 
       
  6617 		if (tinyMCE.isRealIE)
       
  6618 			return inst.getDoc().selection;
       
  6619 
       
  6620 		return inst.contentWindow.getSelection();
       
  6621 	},
       
  6622 
       
  6623 	getRng : function() {
       
  6624 		var s = this.getSel();
       
  6625 
       
  6626 		if (s == null)
       
  6627 			return null;
       
  6628 
       
  6629 		if (tinyMCE.isRealIE)
       
  6630 			return s.createRange();
       
  6631 
       
  6632 		if (tinyMCE.isSafari && !s.getRangeAt)
       
  6633 			return '' + window.getSelection();
       
  6634 
       
  6635 		if (s.rangeCount > 0)
       
  6636 			return s.getRangeAt(0);
       
  6637 
       
  6638 		return null;
       
  6639 	},
       
  6640 
       
  6641 	isCollapsed : function() {
       
  6642 		var r = this.getRng();
       
  6643 
       
  6644 		if (r.item)
       
  6645 			return false;
       
  6646 
       
  6647 		return r.boundingWidth == 0 || this.getSel().isCollapsed;
       
  6648 	},
       
  6649 
       
  6650 	collapse : function(b) {
       
  6651 		var r = this.getRng(), s = this.getSel();
       
  6652 
       
  6653 		if (r.select) {
       
  6654 			r.collapse(b);
       
  6655 			r.select();
       
  6656 		} else {
       
  6657 			if (b)
       
  6658 				s.collapseToStart();
       
  6659 			else
       
  6660 				s.collapseToEnd();
       
  6661 		}
       
  6662 	},
       
  6663 
       
  6664 	getFocusElement : function() {
       
  6665 		var inst = this.instance, doc, rng, sel, elm;
       
  6666 
       
  6667 		if (tinyMCE.isRealIE) {
       
  6668 			doc = inst.getDoc();
       
  6669 			rng = doc.selection.createRange();
       
  6670 
       
  6671 	//		if (rng.collapse)
       
  6672 	//			rng.collapse(true);
       
  6673 
       
  6674 			elm = rng.item ? rng.item(0) : rng.parentElement();
       
  6675 		} else {
       
  6676 			if (!tinyMCE.isSafari && inst.isHidden())
       
  6677 				return inst.getBody();
       
  6678 
       
  6679 			sel = this.getSel();
       
  6680 			rng = this.getRng();
       
  6681 
       
  6682 			if (!sel || !rng)
       
  6683 				return null;
       
  6684 
       
  6685 			elm = rng.commonAncestorContainer;
       
  6686 			//elm = (sel && sel.anchorNode) ? sel.anchorNode : null;
       
  6687 
       
  6688 			// Handle selection a image or other control like element such as anchors
       
  6689 			if (!rng.collapsed) {
       
  6690 				// Is selection small
       
  6691 				if (rng.startContainer == rng.endContainer) {
       
  6692 					if (rng.startOffset - rng.endOffset < 2) {
       
  6693 						if (rng.startContainer.hasChildNodes())
       
  6694 							elm = rng.startContainer.childNodes[rng.startOffset];
       
  6695 					}
       
  6696 				}
       
  6697 			}
       
  6698 
       
  6699 			// Get the element parent of the node
       
  6700 			elm = tinyMCE.getParentElement(elm);
       
  6701 
       
  6702 			//if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img")
       
  6703 			//	elm = tinyMCE.selectedElement;
       
  6704 		}
       
  6705 
       
  6706 		return elm;
       
  6707 	}
       
  6708 
       
  6709 	};
       
  6710 
       
  6711 /* file:jscripts/tiny_mce/classes/TinyMCE_UndoRedo.class.js */
       
  6712 
       
  6713 function TinyMCE_UndoRedo(inst) {
       
  6714 	this.instance = inst;
       
  6715 	this.undoLevels = new Array();
       
  6716 	this.undoIndex = 0;
       
  6717 	this.typingUndoIndex = -1;
       
  6718 	this.undoRedo = true;
       
  6719 };
       
  6720 
       
  6721 TinyMCE_UndoRedo.prototype = {
       
  6722 	add : function(l) {
       
  6723 		var b, customUndoLevels, newHTML, inst = this.instance, i, ul, ur;
       
  6724 
       
  6725 		if (l) {
       
  6726 			this.undoLevels[this.undoLevels.length] = l;
       
  6727 			return true;
       
  6728 		}
       
  6729 
       
  6730 		if (this.typingUndoIndex != -1) {
       
  6731 			this.undoIndex = this.typingUndoIndex;
       
  6732 
       
  6733 			if (tinyMCE.typingUndoIndex != -1)
       
  6734 				tinyMCE.undoIndex = tinyMCE.typingUndoIndex;
       
  6735 		}
       
  6736 
       
  6737 		newHTML = tinyMCE.trim(inst.getBody().innerHTML);
       
  6738 		if (this.undoLevels[this.undoIndex] && newHTML != this.undoLevels[this.undoIndex].content) {
       
  6739 			//tinyMCE.debug(newHTML, this.undoLevels[this.undoIndex].content);
       
  6740 
       
  6741 			tinyMCE.dispatchCallback(inst, 'onchange_callback', 'onChange', inst);
       
  6742 
       
  6743 			// Time to compress
       
  6744 			customUndoLevels = tinyMCE.settings['custom_undo_redo_levels'];
       
  6745 			if (customUndoLevels != -1 && this.undoLevels.length > customUndoLevels) {
       
  6746 				for (i=0; i<this.undoLevels.length-1; i++)
       
  6747 					this.undoLevels[i] = this.undoLevels[i+1];
       
  6748 
       
  6749 				this.undoLevels.length--;
       
  6750 				this.undoIndex--;
       
  6751 
       
  6752 				// Todo: Implement global undo/redo logic here
       
  6753 			}
       
  6754 
       
  6755 			b = inst.undoBookmark;
       
  6756 
       
  6757 			if (!b)
       
  6758 				b = inst.selection.getBookmark();
       
  6759 
       
  6760 			this.undoIndex++;
       
  6761 			this.undoLevels[this.undoIndex] = {
       
  6762 				content : newHTML,
       
  6763 				bookmark : b
       
  6764 			};
       
  6765 
       
  6766 			// Remove all above from global undo/redo
       
  6767 			ul = tinyMCE.undoLevels;
       
  6768 			for (i=tinyMCE.undoIndex + 1; i<ul.length; i++) {
       
  6769 				ur = ul[i].undoRedo;
       
  6770 
       
  6771 				if (ur.undoIndex == ur.undoLevels.length -1)
       
  6772 					ur.undoIndex--;
       
  6773 
       
  6774 				ur.undoLevels.length--;
       
  6775 			}
       
  6776 
       
  6777 			// Add global undo level
       
  6778 			tinyMCE.undoLevels[tinyMCE.undoIndex++] = inst;
       
  6779 			tinyMCE.undoLevels.length = tinyMCE.undoIndex;
       
  6780 
       
  6781 			this.undoLevels.length = this.undoIndex + 1;
       
  6782 
       
  6783 			return true;
       
  6784 		}
       
  6785 
       
  6786 		return false;
       
  6787 	},
       
  6788 
       
  6789 	undo : function() {
       
  6790 		var inst = this.instance;
       
  6791 
       
  6792 		// Do undo
       
  6793 		if (this.undoIndex > 0) {
       
  6794 			this.undoIndex--;
       
  6795 
       
  6796 			tinyMCE.setInnerHTML(inst.getBody(), this.undoLevels[this.undoIndex].content);
       
  6797 			inst.repaint();
       
  6798 
       
  6799 			if (inst.settings.custom_undo_redo_restore_selection)
       
  6800 				inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark);
       
  6801 		}
       
  6802 	},
       
  6803 
       
  6804 	redo : function() {
       
  6805 		var inst = this.instance;
       
  6806 
       
  6807 		tinyMCE.execCommand("mceEndTyping");
       
  6808 
       
  6809 		if (this.undoIndex < (this.undoLevels.length-1)) {
       
  6810 			this.undoIndex++;
       
  6811 
       
  6812 			tinyMCE.setInnerHTML(inst.getBody(), this.undoLevels[this.undoIndex].content);
       
  6813 			inst.repaint();
       
  6814 
       
  6815 			if (inst.settings.custom_undo_redo_restore_selection)
       
  6816 				inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark);
       
  6817 		}
       
  6818 
       
  6819 		tinyMCE.triggerNodeChange();
       
  6820 	}
       
  6821 
       
  6822 	};
       
  6823 
       
  6824 /* file:jscripts/tiny_mce/classes/TinyMCE_ForceParagraphs.class.js */
       
  6825 
       
  6826 var TinyMCE_ForceParagraphs = {
       
  6827 	_insertPara : function(inst, e) {
       
  6828 		var doc = inst.getDoc(), sel = inst.getSel(), body = inst.getBody(), win = inst.contentWindow, rng = sel.getRangeAt(0);
       
  6829 		var rootElm = doc.documentElement, blockName = "P", startNode, endNode, startBlock, endBlock;
       
  6830 		var rngBefore, rngAfter, direct, startNode, startOffset, endNode, endOffset, b = tinyMCE.isOpera ? inst.selection.getBookmark() : null;
       
  6831 		var paraBefore, paraAfter, startChop, endChop, contents;
       
  6832 
       
  6833 		function isEmpty(para) {
       
  6834 			function isEmptyHTML(html) {
       
  6835 				return html.replace(new RegExp('[ \t\r\n]+', 'g'), '').toLowerCase() == "";
       
  6836 			}
       
  6837 
       
  6838 			// Check for images
       
  6839 			if (para.getElementsByTagName("img").length > 0)
       
  6840 				return false;
       
  6841 
       
  6842 			// Check for tables
       
  6843 			if (para.getElementsByTagName("table").length > 0)
       
  6844 				return false;
       
  6845 
       
  6846 			// Check for HRs
       
  6847 			if (para.getElementsByTagName("hr").length > 0)
       
  6848 				return false;
       
  6849 
       
  6850 			// Check all textnodes
       
  6851 			var nodes = tinyMCE.getNodeTree(para, new Array(), 3);
       
  6852 			for (var i=0; i<nodes.length; i++) {
       
  6853 				if (!isEmptyHTML(nodes[i].nodeValue))
       
  6854 					return false;
       
  6855 			}
       
  6856 
       
  6857 			// No images, no tables, no hrs, no text content then it's empty
       
  6858 			return true;
       
  6859 		}
       
  6860 
       
  6861 	//	tinyMCE.debug(body.innerHTML);
       
  6862 
       
  6863 	//	debug(e.target, sel.anchorNode.nodeName, sel.focusNode.nodeName, rng.startContainer, rng.endContainer, rng.commonAncestorContainer, sel.anchorOffset, sel.focusOffset, rng.toString());
       
  6864 
       
  6865 		// Setup before range
       
  6866 		rngBefore = doc.createRange();
       
  6867 		rngBefore.setStart(sel.anchorNode, sel.anchorOffset);
       
  6868 		rngBefore.collapse(true);
       
  6869 
       
  6870 		// Setup after range
       
  6871 		rngAfter = doc.createRange();
       
  6872 		rngAfter.setStart(sel.focusNode, sel.focusOffset);
       
  6873 		rngAfter.collapse(true);
       
  6874 
       
  6875 		// Setup start/end points
       
  6876 		direct = rngBefore.compareBoundaryPoints(rngBefore.START_TO_END, rngAfter) < 0;
       
  6877 		startNode = direct ? sel.anchorNode : sel.focusNode;
       
  6878 		startOffset = direct ? sel.anchorOffset : sel.focusOffset;
       
  6879 		endNode = direct ? sel.focusNode : sel.anchorNode;
       
  6880 		endOffset = direct ? sel.focusOffset : sel.anchorOffset;
       
  6881 
       
  6882 		startNode = startNode.nodeName == "BODY" ? startNode.firstChild : startNode;
       
  6883 		endNode = endNode.nodeName == "BODY" ? endNode.firstChild : endNode;
       
  6884 
       
  6885 		// Get block elements
       
  6886 		startBlock = inst.getParentBlockElement(startNode);
       
  6887 		endBlock = inst.getParentBlockElement(endNode);
       
  6888 
       
  6889 		// If absolute force paragraph generation within
       
  6890 		if (startBlock && new RegExp('absolute|relative|static', 'gi').test(startBlock.style.position))
       
  6891 			startBlock = null;
       
  6892 
       
  6893 		if (endBlock && new RegExp('absolute|relative|static', 'gi').test(endBlock.style.position))
       
  6894 			endBlock = null;
       
  6895 
       
  6896 		// Use current block name
       
  6897 		if (startBlock != null) {
       
  6898 			blockName = startBlock.nodeName;
       
  6899 
       
  6900 			// Use P instead
       
  6901 			if (blockName == "TD" || blockName == "TABLE" || (blockName == "DIV" && new RegExp('left|right', 'gi').test(startBlock.style.cssFloat)))
       
  6902 				blockName = "P";
       
  6903 		}
       
  6904 
       
  6905 		// Within a list use normal behaviour
       
  6906 		if (tinyMCE.getParentElement(startBlock, "OL,UL", null, body) != null)
       
  6907 			return false;
       
  6908 
       
  6909 		// Within a table create new paragraphs
       
  6910 		if ((startBlock != null && startBlock.nodeName == "TABLE") || (endBlock != null && endBlock.nodeName == "TABLE"))
       
  6911 			startBlock = endBlock = null;
       
  6912 
       
  6913 		// Setup new paragraphs
       
  6914 		paraBefore = (startBlock != null && startBlock.nodeName == blockName) ? startBlock.cloneNode(false) : doc.createElement(blockName);
       
  6915 		paraAfter = (endBlock != null && endBlock.nodeName == blockName) ? endBlock.cloneNode(false) : doc.createElement(blockName);
       
  6916 
       
  6917 		// Is header, then force paragraph under
       
  6918 		if (/^(H[1-6])$/.test(blockName))
       
  6919 			paraAfter = doc.createElement("p");
       
  6920 
       
  6921 		// Setup chop nodes
       
  6922 		startChop = startNode;
       
  6923 		endChop = endNode;
       
  6924 
       
  6925 		// Get startChop node
       
  6926 		node = startChop;
       
  6927 		do {
       
  6928 			if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node))
       
  6929 				break;
       
  6930 
       
  6931 			startChop = node;
       
  6932 		} while ((node = node.previousSibling ? node.previousSibling : node.parentNode));
       
  6933 
       
  6934 		// Get endChop node
       
  6935 		node = endChop;
       
  6936 		do {
       
  6937 			if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node))
       
  6938 				break;
       
  6939 
       
  6940 			endChop = node;
       
  6941 		} while ((node = node.nextSibling ? node.nextSibling : node.parentNode));
       
  6942 
       
  6943 		// Fix when only a image is within the TD
       
  6944 		if (startChop.nodeName == "TD")
       
  6945 			startChop = startChop.firstChild;
       
  6946 
       
  6947 		if (endChop.nodeName == "TD")
       
  6948 			endChop = endChop.lastChild;
       
  6949 
       
  6950 		// If not in a block element
       
  6951 		if (startBlock == null) {
       
  6952 			// Delete selection
       
  6953 			rng.deleteContents();
       
  6954 
       
  6955 			if (!tinyMCE.isSafari)
       
  6956 				sel.removeAllRanges();
       
  6957 
       
  6958 			if (startChop != rootElm && endChop != rootElm) {
       
  6959 				// Insert paragraph before
       
  6960 				rngBefore = rng.cloneRange();
       
  6961 
       
  6962 				if (startChop == body)
       
  6963 					rngBefore.setStart(startChop, 0);
       
  6964 				else
       
  6965 					rngBefore.setStartBefore(startChop);
       
  6966 
       
  6967 				paraBefore.appendChild(rngBefore.cloneContents());
       
  6968 
       
  6969 				// Insert paragraph after
       
  6970 				if (endChop.parentNode.nodeName == blockName)
       
  6971 					endChop = endChop.parentNode;
       
  6972 
       
  6973 				// If not after image
       
  6974 				//if (rng.startContainer.nodeName != "BODY" && rng.endContainer.nodeName != "BODY")
       
  6975 					rng.setEndAfter(endChop);
       
  6976 
       
  6977 				if (endChop.nodeName != "#text" && endChop.nodeName != "BODY")
       
  6978 					rngBefore.setEndAfter(endChop);
       
  6979 
       
  6980 				contents = rng.cloneContents();
       
  6981 				if (contents.firstChild && (contents.firstChild.nodeName == blockName || contents.firstChild.nodeName == "BODY"))
       
  6982 					paraAfter.innerHTML = contents.firstChild.innerHTML;
       
  6983 				else
       
  6984 					paraAfter.appendChild(contents);
       
  6985 
       
  6986 				// Check if it's a empty paragraph
       
  6987 				if (isEmpty(paraBefore))
       
  6988 					paraBefore.innerHTML = "&nbsp;";
       
  6989 
       
  6990 				// Check if it's a empty paragraph
       
  6991 				if (isEmpty(paraAfter))
       
  6992 					paraAfter.innerHTML = "&nbsp;";
       
  6993 
       
  6994 				// Delete old contents
       
  6995 				rng.deleteContents();
       
  6996 				rngAfter.deleteContents();
       
  6997 				rngBefore.deleteContents();
       
  6998 
       
  6999 				// Insert new paragraphs
       
  7000 				if (tinyMCE.isOpera) {
       
  7001 					paraBefore.normalize();
       
  7002 					rngBefore.insertNode(paraBefore);
       
  7003 					paraAfter.normalize();
       
  7004 					rngBefore.insertNode(paraAfter);
       
  7005 				} else {
       
  7006 					paraAfter.normalize();
       
  7007 					rngBefore.insertNode(paraAfter);
       
  7008 					paraBefore.normalize();
       
  7009 					rngBefore.insertNode(paraBefore);
       
  7010 				}
       
  7011 
       
  7012 				//tinyMCE.debug("1: ", paraBefore.innerHTML, paraAfter.innerHTML);
       
  7013 			} else {
       
  7014 				body.innerHTML = "<" + blockName + ">&nbsp;</" + blockName + "><" + blockName + ">&nbsp;</" + blockName + ">";
       
  7015 				paraAfter = body.childNodes[1];
       
  7016 			}
       
  7017 
       
  7018 			inst.selection.moveToBookmark(b);
       
  7019 			inst.selection.selectNode(paraAfter, true, true);
       
  7020 
       
  7021 			return true;
       
  7022 		}
       
  7023 
       
  7024 		// Place first part within new paragraph
       
  7025 		if (startChop.nodeName == blockName)
       
  7026 			rngBefore.setStart(startChop, 0);
       
  7027 		else
       
  7028 			rngBefore.setStartBefore(startChop);
       
  7029 
       
  7030 		rngBefore.setEnd(startNode, startOffset);
       
  7031 		paraBefore.appendChild(rngBefore.cloneContents());
       
  7032 
       
  7033 		// Place secound part within new paragraph
       
  7034 		rngAfter.setEndAfter(endChop);
       
  7035 		rngAfter.setStart(endNode, endOffset);
       
  7036 		contents = rngAfter.cloneContents();
       
  7037 
       
  7038 		if (contents.firstChild && contents.firstChild.nodeName == blockName) {
       
  7039 	/*		var nodes = contents.firstChild.childNodes;
       
  7040 			for (var i=0; i<nodes.length; i++) {
       
  7041 				//tinyMCE.debug(nodes[i].nodeName);
       
  7042 				if (nodes[i].nodeName != "BODY")
       
  7043 					paraAfter.appendChild(nodes[i]);
       
  7044 			}
       
  7045 	*/
       
  7046 			paraAfter.innerHTML = contents.firstChild.innerHTML;
       
  7047 		} else
       
  7048 			paraAfter.appendChild(contents);
       
  7049 
       
  7050 		// Check if it's a empty paragraph
       
  7051 		if (isEmpty(paraBefore))
       
  7052 			paraBefore.innerHTML = "&nbsp;";
       
  7053 
       
  7054 		// Check if it's a empty paragraph
       
  7055 		if (isEmpty(paraAfter))
       
  7056 			paraAfter.innerHTML = "&nbsp;";
       
  7057 
       
  7058 		// Create a range around everything
       
  7059 		rng = doc.createRange();
       
  7060 
       
  7061 		if (!startChop.previousSibling && startChop.parentNode.nodeName.toUpperCase() == blockName) {
       
  7062 			rng.setStartBefore(startChop.parentNode);
       
  7063 		} else {
       
  7064 			if (rngBefore.startContainer.nodeName.toUpperCase() == blockName && rngBefore.startOffset == 0)
       
  7065 				rng.setStartBefore(rngBefore.startContainer);
       
  7066 			else
       
  7067 				rng.setStart(rngBefore.startContainer, rngBefore.startOffset);
       
  7068 		}
       
  7069 
       
  7070 		if (!endChop.nextSibling && endChop.parentNode.nodeName.toUpperCase() == blockName)
       
  7071 			rng.setEndAfter(endChop.parentNode);
       
  7072 		else
       
  7073 			rng.setEnd(rngAfter.endContainer, rngAfter.endOffset);
       
  7074 
       
  7075 		// Delete all contents and insert new paragraphs
       
  7076 		rng.deleteContents();
       
  7077 
       
  7078 		if (tinyMCE.isOpera) {
       
  7079 			rng.insertNode(paraBefore);
       
  7080 			rng.insertNode(paraAfter);
       
  7081 		} else {
       
  7082 			rng.insertNode(paraAfter);
       
  7083 			rng.insertNode(paraBefore);
       
  7084 		}
       
  7085 
       
  7086 		//tinyMCE.debug("2", paraBefore.innerHTML, paraAfter.innerHTML);
       
  7087 
       
  7088 		// Normalize
       
  7089 		paraAfter.normalize();
       
  7090 		paraBefore.normalize();
       
  7091 
       
  7092 		inst.selection.moveToBookmark(b);
       
  7093 		inst.selection.selectNode(paraAfter, true, true);
       
  7094 
       
  7095 		return true;
       
  7096 	},
       
  7097 
       
  7098 	_handleBackSpace : function(inst) {
       
  7099 		var r = inst.getRng(), sn = r.startContainer, nv, s = false;
       
  7100 
       
  7101 		// Added body check for bug #1527787
       
  7102 		if (sn && sn.nextSibling && sn.nextSibling.nodeName == "BR" && sn.parentNode.nodeName != "BODY") {
       
  7103 			nv = sn.nodeValue;
       
  7104 
       
  7105 			// Handle if a backspace is pressed after a space character #bug 1466054 removed since fix for #1527787
       
  7106 			/*if (nv != null && nv.length >= r.startOffset && nv.charAt(r.startOffset - 1) == ' ')
       
  7107 				s = true;*/
       
  7108 
       
  7109 			// Only remove BRs if we are at the end of line #bug 1464152
       
  7110 			if (nv != null && r.startOffset == nv.length)
       
  7111 				sn.nextSibling.parentNode.removeChild(sn.nextSibling);
       
  7112 		}
       
  7113 
       
  7114 		if (inst.settings.auto_resize)
       
  7115 			inst.resizeToContent();
       
  7116 
       
  7117 		return s;
       
  7118 	}
       
  7119 
       
  7120 	};
       
  7121 
       
  7122 /* file:jscripts/tiny_mce/classes/TinyMCE_Layer.class.js */
       
  7123 
       
  7124 function TinyMCE_Layer(id, bm) {
       
  7125 	this.id = id;
       
  7126 	this.blockerElement = null;
       
  7127 	this.events = false;
       
  7128 	this.element = null;
       
  7129 	this.blockMode = typeof(bm) != 'undefined' ? bm : true;
       
  7130 	this.doc = document;
       
  7131 };
       
  7132 
       
  7133 TinyMCE_Layer.prototype = {
       
  7134 	moveRelativeTo : function(re, p) {
       
  7135 		var rep = this.getAbsPosition(re);
       
  7136 		var w = parseInt(re.offsetWidth);
       
  7137 		var h = parseInt(re.offsetHeight);
       
  7138 		var e = this.getElement();
       
  7139 		var ew = parseInt(e.offsetWidth);
       
  7140 		var eh = parseInt(e.offsetHeight);
       
  7141 		var x, y;
       
  7142 
       
  7143 		switch (p) {
       
  7144 			case "tl":
       
  7145 				x = rep.absLeft;
       
  7146 				y = rep.absTop;
       
  7147 				break;
       
  7148 
       
  7149 			case "tr":
       
  7150 				x = rep.absLeft + w;
       
  7151 				y = rep.absTop;
       
  7152 				break;
       
  7153 
       
  7154 			case "bl":
       
  7155 				x = rep.absLeft;
       
  7156 				y = rep.absTop + h;
       
  7157 				break;
       
  7158 
       
  7159 			case "br":
       
  7160 				x = rep.absLeft + w;
       
  7161 				y = rep.absTop + h;
       
  7162 				break;
       
  7163 
       
  7164 			case "cc":
       
  7165 				x = rep.absLeft + (w / 2) - (ew / 2);
       
  7166 				y = rep.absTop + (h / 2) - (eh / 2);
       
  7167 				break;
       
  7168 		}
       
  7169 
       
  7170 		this.moveTo(x, y);
       
  7171 	},
       
  7172 
       
  7173 	moveBy : function(x, y) {
       
  7174 		var e = this.getElement();
       
  7175 		this.moveTo(parseInt(e.style.left) + x, parseInt(e.style.top) + y);
       
  7176 	},
       
  7177 
       
  7178 	moveTo : function(x, y) {
       
  7179 		var e = this.getElement();
       
  7180 
       
  7181 		e.style.left = x + "px";
       
  7182 		e.style.top = y + "px";
       
  7183 
       
  7184 		this.updateBlocker();
       
  7185 	},
       
  7186 
       
  7187 	resizeBy : function(w, h) {
       
  7188 		var e = this.getElement();
       
  7189 		this.resizeTo(parseInt(e.style.width) + w, parseInt(e.style.height) + h);
       
  7190 	},
       
  7191 
       
  7192 	resizeTo : function(w, h) {
       
  7193 		var e = this.getElement();
       
  7194 
       
  7195 		if (w != null)
       
  7196 			e.style.width = w + "px";
       
  7197 
       
  7198 		if (h != null)
       
  7199 			e.style.height = h + "px";
       
  7200 
       
  7201 		this.updateBlocker();
       
  7202 	},
       
  7203 
       
  7204 	show : function() {
       
  7205 		var el = this.getElement();
       
  7206 
       
  7207 		if (el) {
       
  7208 			el.style.display = 'block';
       
  7209 			this.updateBlocker();
       
  7210 		}
       
  7211 	},
       
  7212 
       
  7213 	hide : function() {
       
  7214 		var el = this.getElement();
       
  7215 
       
  7216 		if (el) {
       
  7217 			el.style.display = 'none';
       
  7218 			this.updateBlocker();
       
  7219 		}
       
  7220 	},
       
  7221 
       
  7222 	isVisible : function() {
       
  7223 		return this.getElement().style.display == 'block';
       
  7224 	},
       
  7225 
       
  7226 	getElement : function() {
       
  7227 		if (!this.element)
       
  7228 			this.element = this.doc.getElementById(this.id);
       
  7229 
       
  7230 		return this.element;
       
  7231 	},
       
  7232 
       
  7233 	setBlockMode : function(s) {
       
  7234 		this.blockMode = s;
       
  7235 	},
       
  7236 
       
  7237 	updateBlocker : function() {
       
  7238 		var e, b, x, y, w, h;
       
  7239 
       
  7240 		b = this.getBlocker();
       
  7241 		if (b) {
       
  7242 			if (this.blockMode) {
       
  7243 				e = this.getElement();
       
  7244 				x = this.parseInt(e.style.left);
       
  7245 				y = this.parseInt(e.style.top);
       
  7246 				w = this.parseInt(e.offsetWidth);
       
  7247 				h = this.parseInt(e.offsetHeight);
       
  7248 
       
  7249 				b.style.left = x + 'px';
       
  7250 				b.style.top = y + 'px';
       
  7251 				b.style.width = w + 'px';
       
  7252 				b.style.height = h + 'px';
       
  7253 				b.style.display = e.style.display;
       
  7254 			} else
       
  7255 				b.style.display = 'none';
       
  7256 		}
       
  7257 	},
       
  7258 
       
  7259 	getBlocker : function() {
       
  7260 		var d, b;
       
  7261 
       
  7262 		if (!this.blockerElement && this.blockMode) {
       
  7263 			d = this.doc;
       
  7264 			b = d.getElementById(this.id + "_blocker");
       
  7265 
       
  7266 			if (!b) {
       
  7267 				b = d.createElement("iframe");
       
  7268 
       
  7269 				b.setAttribute('id', this.id + "_blocker");
       
  7270 				b.style.cssText = 'display: none; position: absolute; left: 0; top: 0';
       
  7271 				b.src = 'javascript:false;';
       
  7272 				b.frameBorder = '0';
       
  7273 				b.scrolling = 'no';
       
  7274 	
       
  7275 				d.body.appendChild(b);
       
  7276 			}
       
  7277 
       
  7278 			this.blockerElement = b;
       
  7279 		}
       
  7280 
       
  7281 		return this.blockerElement;
       
  7282 	},
       
  7283 
       
  7284 	getAbsPosition : function(n) {
       
  7285 		var p = {absLeft : 0, absTop : 0};
       
  7286 
       
  7287 		while (n) {
       
  7288 			p.absLeft += n.offsetLeft;
       
  7289 			p.absTop += n.offsetTop;
       
  7290 			n = n.offsetParent;
       
  7291 		}
       
  7292 
       
  7293 		return p;
       
  7294 	},
       
  7295 
       
  7296 	create : function(n, c, p, h) {
       
  7297 		var d = this.doc, e = d.createElement(n);
       
  7298 
       
  7299 		e.setAttribute('id', this.id);
       
  7300 
       
  7301 		if (c)
       
  7302 			e.className = c;
       
  7303 
       
  7304 		if (!p)
       
  7305 			p = d.body;
       
  7306 
       
  7307 		if (h)
       
  7308 			e.innerHTML = h;
       
  7309 
       
  7310 		p.appendChild(e);
       
  7311 
       
  7312 		return this.element = e;
       
  7313 	},
       
  7314 
       
  7315 	exists : function() {
       
  7316 		return this.doc.getElementById(this.id) != null;
       
  7317 	},
       
  7318 
       
  7319 	parseInt : function(s) {
       
  7320 		if (s == null || s == '')
       
  7321 			return 0;
       
  7322 
       
  7323 		return parseInt(s);
       
  7324 	},
       
  7325 
       
  7326 	remove : function() {
       
  7327 		var e = this.getElement(), b = this.getBlocker();
       
  7328 
       
  7329 		if (e)
       
  7330 			e.parentNode.removeChild(e);
       
  7331 
       
  7332 		if (b)
       
  7333 			b.parentNode.removeChild(b);
       
  7334 	}
       
  7335 
       
  7336 	};
       
  7337 
       
  7338 /* file:jscripts/tiny_mce/classes/TinyMCE_Menu.class.js */
       
  7339 
       
  7340 function TinyMCE_Menu() {
       
  7341 	var id;
       
  7342 
       
  7343 	if (typeof(tinyMCE.menuCounter) == "undefined")
       
  7344 		tinyMCE.menuCounter = 0;
       
  7345 
       
  7346 	id = "mc_menu_" + tinyMCE.menuCounter++;
       
  7347 
       
  7348 	TinyMCE_Layer.call(this, id, true);
       
  7349 
       
  7350 	this.id = id;
       
  7351 	this.items = new Array();
       
  7352 	this.needsUpdate = true;
       
  7353 };
       
  7354 
       
  7355 TinyMCE_Menu.prototype = tinyMCE.extend(TinyMCE_Layer.prototype, {
       
  7356 	init : function(s) {
       
  7357 		var n;
       
  7358 
       
  7359 		// Default params
       
  7360 		this.settings = {
       
  7361 			separator_class : 'mceMenuSeparator',
       
  7362 			title_class : 'mceMenuTitle',
       
  7363 			disabled_class : 'mceMenuDisabled',
       
  7364 			menu_class : 'mceMenu',
       
  7365 			drop_menu : true
       
  7366 		};
       
  7367 
       
  7368 		for (n in s)
       
  7369 			this.settings[n] = s[n];
       
  7370 
       
  7371 		this.create('div', this.settings.menu_class);
       
  7372 	},
       
  7373 
       
  7374 	clear : function() {
       
  7375 		this.items = new Array();
       
  7376 	},
       
  7377 
       
  7378 	addTitle : function(t) {
       
  7379 		this.add({type : 'title', text : t});
       
  7380 	},
       
  7381 
       
  7382 	addDisabled : function(t) {
       
  7383 		this.add({type : 'disabled', text : t});
       
  7384 	},
       
  7385 
       
  7386 	addSeparator : function() {
       
  7387 		this.add({type : 'separator'});
       
  7388 	},
       
  7389 
       
  7390 	addItem : function(t, js) {
       
  7391 		this.add({text : t, js : js});
       
  7392 	},
       
  7393 
       
  7394 	add : function(mi) {
       
  7395 		this.items[this.items.length] = mi;
       
  7396 		this.needsUpdate = true;
       
  7397 	},
       
  7398 
       
  7399 	update : function() {
       
  7400 		var e = this.getElement(), h = '', i, t, m = this.items, s = this.settings;
       
  7401 
       
  7402 		if (this.settings.drop_menu)
       
  7403 			h += '<span class="mceMenuLine"></span>';
       
  7404 
       
  7405 		h += '<table border="0" cellpadding="0" cellspacing="0">';
       
  7406 
       
  7407 		for (i=0; i<m.length; i++) {
       
  7408 			t = tinyMCE.xmlEncode(m[i].text);
       
  7409 			c = m[i].class_name ? ' class="' + m[i].class_name + '"' : '';
       
  7410 
       
  7411 			switch (m[i].type) {
       
  7412 				case 'separator':
       
  7413 					h += '<tr class="' + s.separator_class + '"><td>';
       
  7414 					break;
       
  7415 
       
  7416 				case 'title':
       
  7417 					h += '<tr class="' + s.title_class + '"><td><span' + c +'>' + t + '</span>';
       
  7418 					break;
       
  7419 
       
  7420 				case 'disabled':
       
  7421 					h += '<tr class="' + s.disabled_class + '"><td><span' + c +'>' + t + '</span>';
       
  7422 					break;
       
  7423 
       
  7424 				default:
       
  7425 					h += '<tr><td><a href="' + tinyMCE.xmlEncode(m[i].js) + '" onmousedown="' + tinyMCE.xmlEncode(m[i].js) + ';return tinyMCE.cancelEvent(event);" onclick="return tinyMCE.cancelEvent(event);" onmouseup="return tinyMCE.cancelEvent(event);"><span' + c +'>' + t + '</span></a>';
       
  7426 			}
       
  7427 
       
  7428 			h += '</td></tr>';
       
  7429 		}
       
  7430 
       
  7431 		h += '</table>';
       
  7432 
       
  7433 		e.innerHTML = h;
       
  7434 
       
  7435 		this.needsUpdate = false;
       
  7436 		this.updateBlocker();
       
  7437 	},
       
  7438 
       
  7439 	show : function() {
       
  7440 		var nl, i;
       
  7441 
       
  7442 		if (tinyMCE.lastMenu == this)
       
  7443 			return;
       
  7444 
       
  7445 		if (this.needsUpdate)
       
  7446 			this.update();
       
  7447 
       
  7448 		if (tinyMCE.lastMenu && tinyMCE.lastMenu != this)
       
  7449 			tinyMCE.lastMenu.hide();
       
  7450 
       
  7451 		TinyMCE_Layer.prototype.show.call(this);
       
  7452 
       
  7453 		if (!tinyMCE.isOpera) {
       
  7454 			// Accessibility stuff
       
  7455 /*			nl = this.getElement().getElementsByTagName("a");
       
  7456 			if (nl.length > 0)
       
  7457 				nl[0].focus();*/
       
  7458 		}
       
  7459 
       
  7460 		tinyMCE.lastMenu = this;
       
  7461 	}
       
  7462 
       
  7463 	});
       
  7464 
       
  7465 /* file:jscripts/tiny_mce/classes/TinyMCE_Compatibility.class.js */
       
  7466 
       
  7467 if (!Function.prototype.call) {
       
  7468 	Function.prototype.call = function() {
       
  7469 		var a = arguments, s = a[0], i, as = '', r, o;
       
  7470 
       
  7471 		for (i=1; i<a.length; i++)
       
  7472 			as += (i > 1 ? ',' : '') + 'a[' + i + ']';
       
  7473 
       
  7474 		o = s._fu;
       
  7475 		s._fu = this;
       
  7476 		r = eval('s._fu(' + as + ')');
       
  7477 		s._fu = o;
       
  7478 
       
  7479 		return r;
       
  7480 	};
       
  7481 };
       
  7482 
       
  7483 /* file:jscripts/tiny_mce/classes/TinyMCE_Debug.class.js */
       
  7484 
       
  7485 TinyMCE_Engine.prototype.debug = function() {
       
  7486 	var m = "", a, i, l = tinyMCE.log.length;
       
  7487 
       
  7488 	for (i=0, a = this.debug.arguments; i<a.length; i++) {
       
  7489 		m += a[i];
       
  7490 
       
  7491 		if (i<a.length-1)
       
  7492 			m += ', ';
       
  7493 	}
       
  7494 
       
  7495 	if (l < 1000)
       
  7496 		tinyMCE.log[l] = "[debug] " + m;
       
  7497 };
       
  7498