Subversion Repositories Sites.tela-botanica.org

Rev

Details | Last modification | View Log | RSS feed

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