app/tiny_mce/tiny_mce_src.js
changeset 154 d2377425d3f2
parent 126 6186c115a210
equal deleted inserted replaced
153:79d52c2d50a2 154:d2377425d3f2
       
     1 
       
     2 /* file:jscripts/tiny_mce/classes/tinymce.js */
       
     3 
       
     4 var tinymce = {
       
     5 	majorVersion : '3',
       
     6 	minorVersion : '1.1',
       
     7 	releaseDate : '2008-08-18',
       
     8 
       
     9 	_init : function() {
       
    10 		var t = this, d = document, w = window, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
       
    11 
       
    12 		// Browser checks
       
    13 		t.isOpera = w.opera && opera.buildNumber;
       
    14 		t.isWebKit = /WebKit/.test(ua);
       
    15 		t.isOldWebKit = t.isWebKit && !w.getSelection().getRangeAt;
       
    16 		t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);
       
    17 		t.isIE6 = t.isIE && /MSIE [56]/.test(ua);
       
    18 		t.isGecko = !t.isWebKit && /Gecko/.test(ua);
       
    19 		t.isMac = ua.indexOf('Mac') != -1;
       
    20 
       
    21 		// TinyMCE .NET webcontrol might be setting the values for TinyMCE
       
    22 		if (w.tinyMCEPreInit) {
       
    23 			t.suffix = tinyMCEPreInit.suffix;
       
    24 			t.baseURL = tinyMCEPreInit.base;
       
    25 			t.query = tinyMCEPreInit.query;
       
    26 			return;
       
    27 		}
       
    28 
       
    29 		// Get suffix and base
       
    30 		t.suffix = '';
       
    31 
       
    32 		// If base element found, add that infront of baseURL
       
    33 		nl = d.getElementsByTagName('base');
       
    34 		for (i=0; i<nl.length; i++) {
       
    35 			if (v = nl[i].href) {
       
    36 				// Host only value like http://site.com or http://site.com:8008
       
    37 				if (/^https?:\/\/[^\/]+$/.test(v))
       
    38 					v += '/';
       
    39 
       
    40 				base = v ? v.match(/.*\//)[0] : ''; // Get only directory
       
    41 			}
       
    42 		}
       
    43 
       
    44 		function getBase(n) {
       
    45 			if (n.src && /tiny_mce(|_dev|_src|_gzip|_jquery|_prototype).js/.test(n.src)) {
       
    46 				if (/_(src|dev)\.js/g.test(n.src))
       
    47 					t.suffix = '_src';
       
    48 
       
    49 				if ((p = n.src.indexOf('?')) != -1)
       
    50 					t.query = n.src.substring(p + 1);
       
    51 
       
    52 				t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));
       
    53 
       
    54 				// If path to script is relative and a base href was found add that one infront
       
    55 				if (base && t.baseURL.indexOf('://') == -1)
       
    56 					t.baseURL = base + t.baseURL;
       
    57 
       
    58 				return t.baseURL;
       
    59 			}
       
    60 
       
    61 			return null;
       
    62 		};
       
    63 
       
    64 		// Check document
       
    65 		nl = d.getElementsByTagName('script');
       
    66 		for (i=0; i<nl.length; i++) {
       
    67 			if (getBase(nl[i]))
       
    68 				return;
       
    69 		}
       
    70 
       
    71 		// Check head
       
    72 		n = d.getElementsByTagName('head')[0];
       
    73 		if (n) {
       
    74 			nl = n.getElementsByTagName('script');
       
    75 			for (i=0; i<nl.length; i++) {
       
    76 				if (getBase(nl[i]))
       
    77 					return;
       
    78 			}
       
    79 		}
       
    80 
       
    81 		return;
       
    82 	},
       
    83 
       
    84 	is : function(o, t) {
       
    85 		var n = typeof(o);
       
    86 
       
    87 		if (!t)
       
    88 			return n != 'undefined';
       
    89 
       
    90 		if (t == 'array' && (o instanceof Array))
       
    91 			return true;
       
    92 
       
    93 		return n == t;
       
    94 	},
       
    95 
       
    96 	// #if !jquery
       
    97 
       
    98 	each : function(o, cb, s) {
       
    99 		var n, l;
       
   100 
       
   101 		if (!o)
       
   102 			return 0;
       
   103 
       
   104 		s = s || o;
       
   105 
       
   106 		if (typeof(o.length) != 'undefined') {
       
   107 			// Indexed arrays, needed for Safari
       
   108 			for (n=0, l = o.length; n<l; n++) {
       
   109 				if (cb.call(s, o[n], n, o) === false)
       
   110 					return 0;
       
   111 			}
       
   112 		} else {
       
   113 			// Hashtables
       
   114 			for (n in o) {
       
   115 				if (o.hasOwnProperty(n)) {
       
   116 					if (cb.call(s, o[n], n, o) === false)
       
   117 						return 0;
       
   118 				}
       
   119 			}
       
   120 		}
       
   121 
       
   122 		return 1;
       
   123 	},
       
   124 
       
   125 	map : function(a, f) {
       
   126 		var o = [];
       
   127 
       
   128 		tinymce.each(a, function(v) {
       
   129 			o.push(f(v));
       
   130 		});
       
   131 
       
   132 		return o;
       
   133 	},
       
   134 
       
   135 	grep : function(a, f) {
       
   136 		var o = [];
       
   137 
       
   138 		tinymce.each(a, function(v) {
       
   139 			if (!f || f(v))
       
   140 				o.push(v);
       
   141 		});
       
   142 
       
   143 		return o;
       
   144 	},
       
   145 
       
   146 	inArray : function(a, v) {
       
   147 		var i, l;
       
   148 
       
   149 		if (a) {
       
   150 			for (i = 0, l = a.length; i < l; i++) {
       
   151 				if (a[i] === v)
       
   152 					return i;
       
   153 			}
       
   154 		}
       
   155 
       
   156 		return -1;
       
   157 	},
       
   158 
       
   159 	extend : function(o, e) {
       
   160 		var i, a = arguments;
       
   161 
       
   162 		for (i=1; i<a.length; i++) {
       
   163 			e = a[i];
       
   164 
       
   165 			tinymce.each(e, function(v, n) {
       
   166 				if (typeof(v) !== 'undefined')
       
   167 					o[n] = v;
       
   168 			});
       
   169 		}
       
   170 
       
   171 		return o;
       
   172 	},
       
   173 
       
   174 	trim : function(s) {
       
   175 		return (s ? '' + s : '').replace(/^\s*|\s*$/g, '');
       
   176 	},
       
   177 
       
   178 	// #endif
       
   179 
       
   180 	create : function(s, p) {
       
   181 		var t = this, sp, ns, cn, scn, c, de = 0;
       
   182 
       
   183 		// Parse : <prefix> <class>:<super class>
       
   184 		s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
       
   185 		cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
       
   186 
       
   187 		// Create namespace for new class
       
   188 		ns = t.createNS(s[3].replace(/\.\w+$/, ''));
       
   189 
       
   190 		// Class already exists
       
   191 		if (ns[cn])
       
   192 			return;
       
   193 
       
   194 		// Make pure static class
       
   195 		if (s[2] == 'static') {
       
   196 			ns[cn] = p;
       
   197 
       
   198 			if (this.onCreate)
       
   199 				this.onCreate(s[2], s[3], ns[cn]);
       
   200 
       
   201 			return;
       
   202 		}
       
   203 
       
   204 		// Create default constructor
       
   205 		if (!p[cn]) {
       
   206 			p[cn] = function() {};
       
   207 			de = 1;
       
   208 		}
       
   209 
       
   210 		// Add constructor and methods
       
   211 		ns[cn] = p[cn];
       
   212 		t.extend(ns[cn].prototype, p);
       
   213 
       
   214 		// Extend
       
   215 		if (s[5]) {
       
   216 			sp = t.resolve(s[5]).prototype;
       
   217 			scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
       
   218 
       
   219 			// Extend constructor
       
   220 			c = ns[cn];
       
   221 			if (de) {
       
   222 				// Add passthrough constructor
       
   223 				ns[cn] = function() {
       
   224 					return sp[scn].apply(this, arguments);
       
   225 				};
       
   226 			} else {
       
   227 				// Add inherit constructor
       
   228 				ns[cn] = function() {
       
   229 					this.parent = sp[scn];
       
   230 					return c.apply(this, arguments);
       
   231 				};
       
   232 			}
       
   233 			ns[cn].prototype[cn] = ns[cn];
       
   234 
       
   235 			// Add super methods
       
   236 			t.each(sp, function(f, n) {
       
   237 				ns[cn].prototype[n] = sp[n];
       
   238 			});
       
   239 
       
   240 			// Add overridden methods
       
   241 			t.each(p, function(f, n) {
       
   242 				// Extend methods if needed
       
   243 				if (sp[n]) {
       
   244 					ns[cn].prototype[n] = function() {
       
   245 						this.parent = sp[n];
       
   246 						return f.apply(this, arguments);
       
   247 					};
       
   248 				} else {
       
   249 					if (n != cn)
       
   250 						ns[cn].prototype[n] = f;
       
   251 				}
       
   252 			});
       
   253 		}
       
   254 
       
   255 		// Add static methods
       
   256 		t.each(p['static'], function(f, n) {
       
   257 			ns[cn][n] = f;
       
   258 		});
       
   259 
       
   260 		if (this.onCreate)
       
   261 			this.onCreate(s[2], s[3], ns[cn].prototype);
       
   262 	},
       
   263 
       
   264 	walk : function(o, f, n, s) {
       
   265 		s = s || this;
       
   266 
       
   267 		if (o) {
       
   268 			if (n)
       
   269 				o = o[n];
       
   270 
       
   271 			tinymce.each(o, function(o, i) {
       
   272 				if (f.call(s, o, i, n) === false)
       
   273 					return false;
       
   274 
       
   275 				tinymce.walk(o, f, n, s);
       
   276 			});
       
   277 		}
       
   278 	},
       
   279 
       
   280 	createNS : function(n, o) {
       
   281 		var i, v;
       
   282 
       
   283 		o = o || window;
       
   284 
       
   285 		n = n.split('.');
       
   286 		for (i=0; i<n.length; i++) {
       
   287 			v = n[i];
       
   288 
       
   289 			if (!o[v])
       
   290 				o[v] = {};
       
   291 
       
   292 			o = o[v];
       
   293 		}
       
   294 
       
   295 		return o;
       
   296 	},
       
   297 
       
   298 	resolve : function(n, o) {
       
   299 		var i, l;
       
   300 
       
   301 		o = o || window;
       
   302 
       
   303 		n = n.split('.');
       
   304 		for (i=0, l = n.length; i<l; i++) {
       
   305 			o = o[n[i]];
       
   306 
       
   307 			if (!o)
       
   308 				break;
       
   309 		}
       
   310 
       
   311 		return o;
       
   312 	},
       
   313 
       
   314 	addUnload : function(f, s) {
       
   315 		var t = this, w = window;
       
   316 
       
   317 		f = {func : f, scope : s || this};
       
   318 
       
   319 		if (!t.unloads) {
       
   320 			function unload() {
       
   321 				var li = t.unloads, o, n;
       
   322 
       
   323 				if (li) {
       
   324 					// Call unload handlers
       
   325 					for (n in li) {
       
   326 						o = li[n];
       
   327 
       
   328 						if (o && o.func)
       
   329 							o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy
       
   330 					}
       
   331 
       
   332 					// Detach unload function
       
   333 					if (w.detachEvent) {
       
   334 						w.detachEvent('onbeforeunload', fakeUnload);
       
   335 						w.detachEvent('onunload', unload);
       
   336 					} else if (w.removeEventListener)
       
   337 						w.removeEventListener('unload', unload, false);
       
   338 
       
   339 					// Destroy references
       
   340 					t.unloads = o = li = w = unload = null;
       
   341 
       
   342 					// Run garbarge collector on IE
       
   343 					if (window.CollectGarbage)
       
   344 						window.CollectGarbage();
       
   345 				}
       
   346 			};
       
   347 
       
   348 			function fakeUnload() {
       
   349 				var d = document;
       
   350 
       
   351 				// Is there things still loading, then do some magic
       
   352 				if (d.readyState == 'interactive') {
       
   353 					function stop() {
       
   354 						// Prevent memory leak
       
   355 						d.detachEvent('onstop', stop);
       
   356 
       
   357 						// Call unload handler
       
   358 						unload();
       
   359 
       
   360 						d = null;
       
   361 					};
       
   362 
       
   363 					// Fire unload when the currently loading page is stopped
       
   364 					d.attachEvent('onstop', stop);
       
   365 
       
   366 					// Remove onstop listener after a while to prevent the unload function
       
   367 					// to execute if the user presses cancel in an onbeforeunload
       
   368 					// confirm dialog and then presses the browser stop button
       
   369 					window.setTimeout(function() {
       
   370 						d.detachEvent('onstop', stop);
       
   371 					}, 0);
       
   372 				}
       
   373 			};
       
   374 
       
   375 			// Attach unload handler
       
   376 			if (w.attachEvent) {
       
   377 				w.attachEvent('onunload', unload);
       
   378 				w.attachEvent('onbeforeunload', fakeUnload);
       
   379 			} else if (w.addEventListener)
       
   380 				w.addEventListener('unload', unload, false);
       
   381 
       
   382 			// Setup initial unload handler array
       
   383 			t.unloads = [f];
       
   384 		} else
       
   385 			t.unloads.push(f);
       
   386 
       
   387 		return f;
       
   388 	},
       
   389 
       
   390 	removeUnload : function(f) {
       
   391 		var u = this.unloads, r = null;
       
   392 
       
   393 		tinymce.each(u, function(o, i) {
       
   394 			if (o && o.func == f) {
       
   395 				u.splice(i, 1);
       
   396 				r = f;
       
   397 				return false;
       
   398 			}
       
   399 		});
       
   400 
       
   401 		return r;
       
   402 	},
       
   403 
       
   404 	explode : function(s, d) {
       
   405 		return s ? tinymce.map(s.split(d || ','), tinymce.trim) : s;
       
   406 	},
       
   407 
       
   408 	_addVer : function(u) {
       
   409 		var v;
       
   410 
       
   411 		if (!this.query)
       
   412 			return u;
       
   413 
       
   414 		v = (u.indexOf('?') == -1 ? '?' : '&') + this.query;
       
   415 
       
   416 		if (u.indexOf('#') == -1)
       
   417 			return u + v;
       
   418 
       
   419 		return u.replace('#', v + '#');
       
   420 	}
       
   421 
       
   422 	};
       
   423 
       
   424 // Required for GZip AJAX loading
       
   425 window.tinymce = tinymce;
       
   426 
       
   427 // Initialize the API
       
   428 tinymce._init();
       
   429 
       
   430 /* file:jscripts/tiny_mce/classes/adapter/jquery/adapter.js */
       
   431 
       
   432 
       
   433 /* file:jscripts/tiny_mce/classes/adapter/prototype/adapter.js */
       
   434 
       
   435 
       
   436 /* file:jscripts/tiny_mce/classes/util/Dispatcher.js */
       
   437 
       
   438 tinymce.create('tinymce.util.Dispatcher', {
       
   439 	scope : null,
       
   440 	listeners : null,
       
   441 
       
   442 	Dispatcher : function(s) {
       
   443 		this.scope = s || this;
       
   444 		this.listeners = [];
       
   445 	},
       
   446 
       
   447 	add : function(cb, s) {
       
   448 		this.listeners.push({cb : cb, scope : s || this.scope});
       
   449 
       
   450 		return cb;
       
   451 	},
       
   452 
       
   453 	addToTop : function(cb, s) {
       
   454 		this.listeners.unshift({cb : cb, scope : s || this.scope});
       
   455 
       
   456 		return cb;
       
   457 	},
       
   458 
       
   459 	remove : function(cb) {
       
   460 		var l = this.listeners, o = null;
       
   461 
       
   462 		tinymce.each(l, function(c, i) {
       
   463 			if (cb == c.cb) {
       
   464 				o = cb;
       
   465 				l.splice(i, 1);
       
   466 				return false;
       
   467 			}
       
   468 		});
       
   469 
       
   470 		return o;
       
   471 	},
       
   472 
       
   473 	dispatch : function() {
       
   474 		var s, a = arguments, i, li = this.listeners, c;
       
   475 
       
   476 		// Needs to be a real loop since the listener count might change while looping
       
   477 		// And this is also more efficient
       
   478 		for (i = 0; i<li.length; i++) {
       
   479 			c = li[i];
       
   480 			s = c.cb.apply(c.scope, a);
       
   481 
       
   482 			if (s === false)
       
   483 				break;
       
   484 		}
       
   485 
       
   486 		return s;
       
   487 	}
       
   488 
       
   489 	});
       
   490 
       
   491 /* file:jscripts/tiny_mce/classes/util/URI.js */
       
   492 
       
   493 (function() {
       
   494 	var each = tinymce.each;
       
   495 
       
   496 	tinymce.create('tinymce.util.URI', {
       
   497 		URI : function(u, s) {
       
   498 			var t = this, o, a, b;
       
   499 
       
   500 			// Default settings
       
   501 			s = t.settings = s || {};
       
   502 
       
   503 			// Strange app protocol or local anchor
       
   504 			if (/^(mailto|news|javascript|about):/i.test(u) || /^\s*#/.test(u)) {
       
   505 				t.source = u;
       
   506 				return;
       
   507 			}
       
   508 
       
   509 			// Absolute path with no host, fake host and protocol
       
   510 			if (u.indexOf('/') === 0 && u.indexOf('//') !== 0)
       
   511 				u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u;
       
   512 
       
   513 			// Relative path
       
   514 			if (u.indexOf('://') === -1 && u.indexOf('//') !== 0)
       
   515 				u = (s.base_uri.protocol || 'http') + '://mce_host' + t.toAbsPath(s.base_uri.path, u);
       
   516 
       
   517 			// Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
       
   518 			u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something
       
   519 			u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);
       
   520 			each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) {
       
   521 				var s = u[i];
       
   522 
       
   523 				// Zope 3 workaround, they use @@something
       
   524 				if (s)
       
   525 					s = s.replace(/\(mce_at\)/g, '@@');
       
   526 
       
   527 				t[v] = s;
       
   528 			});
       
   529 
       
   530 			if (b = s.base_uri) {
       
   531 				if (!t.protocol)
       
   532 					t.protocol = b.protocol;
       
   533 
       
   534 				if (!t.userInfo)
       
   535 					t.userInfo = b.userInfo;
       
   536 
       
   537 				if (!t.port && t.host == 'mce_host')
       
   538 					t.port = b.port;
       
   539 
       
   540 				if (!t.host || t.host == 'mce_host')
       
   541 					t.host = b.host;
       
   542 
       
   543 				t.source = '';
       
   544 			}
       
   545 
       
   546 			//t.path = t.path || '/';
       
   547 		},
       
   548 
       
   549 		setPath : function(p) {
       
   550 			var t = this;
       
   551 
       
   552 			p = /^(.*?)\/?(\w+)?$/.exec(p);
       
   553 
       
   554 			// Update path parts
       
   555 			t.path = p[0];
       
   556 			t.directory = p[1];
       
   557 			t.file = p[2];
       
   558 
       
   559 			// Rebuild source
       
   560 			t.source = '';
       
   561 			t.getURI();
       
   562 		},
       
   563 
       
   564 		toRelative : function(u) {
       
   565 			var t = this, o;
       
   566 
       
   567 			u = new tinymce.util.URI(u, {base_uri : t});
       
   568 
       
   569 			// Not on same domain/port or protocol
       
   570 			if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol)
       
   571 				return u.getURI();
       
   572 
       
   573 			o = t.toRelPath(t.path, u.path);
       
   574 
       
   575 			// Add query
       
   576 			if (u.query)
       
   577 				o += '?' + u.query;
       
   578 
       
   579 			// Add anchor
       
   580 			if (u.anchor)
       
   581 				o += '#' + u.anchor;
       
   582 
       
   583 			return o;
       
   584 		},
       
   585 	
       
   586 		toAbsolute : function(u, nh) {
       
   587 			var u = new tinymce.util.URI(u, {base_uri : this});
       
   588 
       
   589 			return u.getURI(this.host == u.host ? nh : 0);
       
   590 		},
       
   591 
       
   592 		toRelPath : function(base, path) {
       
   593 			var items, bp = 0, out = '', i;
       
   594 
       
   595 			// Split the paths
       
   596 			base = base.substring(0, base.lastIndexOf('/'));
       
   597 			base = base.split('/');
       
   598 			items = path.split('/');
       
   599 
       
   600 			if (base.length >= items.length) {
       
   601 				for (i = 0; i < base.length; i++) {
       
   602 					if (i >= items.length || base[i] != items[i]) {
       
   603 						bp = i + 1;
       
   604 						break;
       
   605 					}
       
   606 				}
       
   607 			}
       
   608 
       
   609 			if (base.length < items.length) {
       
   610 				for (i = 0; i < items.length; i++) {
       
   611 					if (i >= base.length || base[i] != items[i]) {
       
   612 						bp = i + 1;
       
   613 						break;
       
   614 					}
       
   615 				}
       
   616 			}
       
   617 
       
   618 			if (bp == 1)
       
   619 				return path;
       
   620 
       
   621 			for (i = 0; i < base.length - (bp - 1); i++)
       
   622 				out += "../";
       
   623 
       
   624 			for (i = bp - 1; i < items.length; i++) {
       
   625 				if (i != bp - 1)
       
   626 					out += "/" + items[i];
       
   627 				else
       
   628 					out += items[i];
       
   629 			}
       
   630 
       
   631 			return out;
       
   632 		},
       
   633 
       
   634 		toAbsPath : function(base, path) {
       
   635 			var i, nb = 0, o = [];
       
   636 
       
   637 			// Split paths
       
   638 			base = base.split('/');
       
   639 			path = path.split('/');
       
   640 
       
   641 			// Remove empty chunks
       
   642 			each(base, function(k) {
       
   643 				if (k)
       
   644 					o.push(k);
       
   645 			});
       
   646 
       
   647 			base = o;
       
   648 
       
   649 			// Merge relURLParts chunks
       
   650 			for (i = path.length - 1, o = []; i >= 0; i--) {
       
   651 				// Ignore empty or .
       
   652 				if (path[i].length == 0 || path[i] == ".")
       
   653 					continue;
       
   654 
       
   655 				// Is parent
       
   656 				if (path[i] == '..') {
       
   657 					nb++;
       
   658 					continue;
       
   659 				}
       
   660 
       
   661 				// Move up
       
   662 				if (nb > 0) {
       
   663 					nb--;
       
   664 					continue;
       
   665 				}
       
   666 
       
   667 				o.push(path[i]);
       
   668 			}
       
   669 
       
   670 			i = base.length - nb;
       
   671 
       
   672 			// If /a/b/c or /
       
   673 			if (i <= 0)
       
   674 				return '/' + o.reverse().join('/');
       
   675 
       
   676 			return '/' + base.slice(0, i).join('/') + '/' + o.reverse().join('/');
       
   677 		},
       
   678 
       
   679 		getURI : function(nh) {
       
   680 			var s, t = this;
       
   681 
       
   682 			// Rebuild source
       
   683 			if (!t.source || nh) {
       
   684 				s = '';
       
   685 
       
   686 				if (!nh) {
       
   687 					if (t.protocol)
       
   688 						s += t.protocol + '://';
       
   689 
       
   690 					if (t.userInfo)
       
   691 						s += t.userInfo + '@';
       
   692 
       
   693 					if (t.host)
       
   694 						s += t.host;
       
   695 
       
   696 					if (t.port)
       
   697 						s += ':' + t.port;
       
   698 				}
       
   699 
       
   700 				if (t.path)
       
   701 					s += t.path;
       
   702 
       
   703 				if (t.query)
       
   704 					s += '?' + t.query;
       
   705 
       
   706 				if (t.anchor)
       
   707 					s += '#' + t.anchor;
       
   708 
       
   709 				t.source = s;
       
   710 			}
       
   711 
       
   712 			return t.source;
       
   713 		}
       
   714 
       
   715 		});
       
   716 })();
       
   717 
       
   718 /* file:jscripts/tiny_mce/classes/util/Cookie.js */
       
   719 
       
   720 (function() {
       
   721 	var each = tinymce.each;
       
   722 
       
   723 	tinymce.create('static tinymce.util.Cookie', {
       
   724 		getHash : function(n) {
       
   725 			var v = this.get(n), h;
       
   726 
       
   727 			if (v) {
       
   728 				each(v.split('&'), function(v) {
       
   729 					v = v.split('=');
       
   730 					h = h || {};
       
   731 					h[unescape(v[0])] = unescape(v[1]);
       
   732 				});
       
   733 			}
       
   734 
       
   735 			return h;
       
   736 		},
       
   737 
       
   738 		setHash : function(n, v, e, p, d, s) {
       
   739 			var o = '';
       
   740 
       
   741 			each(v, function(v, k) {
       
   742 				o += (!o ? '' : '&') + escape(k) + '=' + escape(v);
       
   743 			});
       
   744 
       
   745 			this.set(n, o, e, p, d, s);
       
   746 		},
       
   747 
       
   748 		get : function(n) {
       
   749 			var c = document.cookie, e, p = n + "=", b;
       
   750 
       
   751 			// Strict mode
       
   752 			if (!c)
       
   753 				return;
       
   754 
       
   755 			b = c.indexOf("; " + p);
       
   756 
       
   757 			if (b == -1) {
       
   758 				b = c.indexOf(p);
       
   759 
       
   760 				if (b != 0)
       
   761 					return null;
       
   762 			} else
       
   763 				b += 2;
       
   764 
       
   765 			e = c.indexOf(";", b);
       
   766 
       
   767 			if (e == -1)
       
   768 				e = c.length;
       
   769 
       
   770 			return unescape(c.substring(b + p.length, e));
       
   771 		},
       
   772 
       
   773 		set : function(n, v, e, p, d, s) {
       
   774 			document.cookie = n + "=" + escape(v) +
       
   775 				((e) ? "; expires=" + e.toGMTString() : "") +
       
   776 				((p) ? "; path=" + escape(p) : "") +
       
   777 				((d) ? "; domain=" + d : "") +
       
   778 				((s) ? "; secure" : "");
       
   779 		},
       
   780 
       
   781 		remove : function(n, p) {
       
   782 			var d = new Date();
       
   783 
       
   784 			d.setTime(d.getTime() - 1000);
       
   785 
       
   786 			this.set(n, '', d, p, d);
       
   787 		}
       
   788 
       
   789 		});
       
   790 })();
       
   791 
       
   792 /* file:jscripts/tiny_mce/classes/util/JSON.js */
       
   793 
       
   794 tinymce.create('static tinymce.util.JSON', {
       
   795 	serialize : function(o) {
       
   796 		var i, v, s = tinymce.util.JSON.serialize, t;
       
   797 
       
   798 		if (o == null)
       
   799 			return 'null';
       
   800 
       
   801 		t = typeof o;
       
   802 
       
   803 		if (t == 'string') {
       
   804 			v = '\bb\tt\nn\ff\rr\""\'\'\\\\';
       
   805 
       
   806 			return '"' + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'])/g, function(a, b) {
       
   807 				i = v.indexOf(b);
       
   808 
       
   809 				if (i + 1)
       
   810 					return '\\' + v.charAt(i + 1);
       
   811 
       
   812 				a = b.charCodeAt().toString(16);
       
   813 
       
   814 				return '\\u' + '0000'.substring(a.length) + a;
       
   815 			}) + '"';
       
   816 		}
       
   817 
       
   818 		if (t == 'object') {
       
   819 			if (o instanceof Array) {
       
   820 					for (i=0, v = '['; i<o.length; i++)
       
   821 						v += (i > 0 ? ',' : '') + s(o[i]);
       
   822 
       
   823 					return v + ']';
       
   824 				}
       
   825 
       
   826 				v = '{';
       
   827 
       
   828 				for (i in o)
       
   829 					v += typeof o[i] != 'function' ? (v.length > 1 ? ',"' : '"') + i + '":' + s(o[i]) : '';
       
   830 
       
   831 				return v + '}';
       
   832 		}
       
   833 
       
   834 		return '' + o;
       
   835 	},
       
   836 
       
   837 	parse : function(s) {
       
   838 		try {
       
   839 			return eval('(' + s + ')');
       
   840 		} catch (ex) {
       
   841 			// Ignore
       
   842 		}
       
   843 	}
       
   844 
       
   845 	});
       
   846 
       
   847 /* file:jscripts/tiny_mce/classes/util/XHR.js */
       
   848 
       
   849 tinymce.create('static tinymce.util.XHR', {
       
   850 	send : function(o) {
       
   851 		var x, t, w = window, c = 0;
       
   852 
       
   853 		// Default settings
       
   854 		o.scope = o.scope || this;
       
   855 		o.success_scope = o.success_scope || o.scope;
       
   856 		o.error_scope = o.error_scope || o.scope;
       
   857 		o.async = o.async === false ? false : true;
       
   858 		o.data = o.data || '';
       
   859 
       
   860 		function get(s) {
       
   861 			x = 0;
       
   862 
       
   863 			try {
       
   864 				x = new ActiveXObject(s);
       
   865 			} catch (ex) {
       
   866 			}
       
   867 
       
   868 			return x;
       
   869 		};
       
   870 
       
   871 		x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP');
       
   872 
       
   873 		if (x) {
       
   874 			if (x.overrideMimeType)
       
   875 				x.overrideMimeType(o.content_type);
       
   876 
       
   877 			x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async);
       
   878 
       
   879 			if (o.content_type)
       
   880 				x.setRequestHeader('Content-Type', o.content_type);
       
   881 
       
   882 			x.send(o.data);
       
   883 
       
   884 			function ready() {
       
   885 				if (!o.async || x.readyState == 4 || c++ > 10000) {
       
   886 					if (o.success && c < 10000 && x.status == 200)
       
   887 						o.success.call(o.success_scope, '' + x.responseText, x, o);
       
   888 					else if (o.error)
       
   889 						o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);
       
   890 
       
   891 					x = null;
       
   892 				} else
       
   893 					w.setTimeout(ready, 10);
       
   894 			};
       
   895 
       
   896 			// Syncronous request
       
   897 			if (!o.async)
       
   898 				return ready();
       
   899 
       
   900 			// Wait for response, onReadyStateChange can not be used since it leaks memory in IE
       
   901 			t = w.setTimeout(ready, 10);
       
   902 		}
       
   903 
       
   904 		}
       
   905 });
       
   906 
       
   907 /* file:jscripts/tiny_mce/classes/util/JSONRequest.js */
       
   908 
       
   909 (function() {
       
   910 	var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR;
       
   911 
       
   912 	tinymce.create('tinymce.util.JSONRequest', {
       
   913 		JSONRequest : function(s) {
       
   914 			this.settings = extend({
       
   915 			}, s);
       
   916 			this.count = 0;
       
   917 		},
       
   918 
       
   919 		send : function(o) {
       
   920 			var ecb = o.error, scb = o.success;
       
   921 
       
   922 			o = extend(this.settings, o);
       
   923 
       
   924 			o.success = function(c, x) {
       
   925 				c = JSON.parse(c);
       
   926 
       
   927 				if (typeof(c) == 'undefined') {
       
   928 					c = {
       
   929 						error : 'JSON Parse error.'
       
   930 					};
       
   931 				}
       
   932 
       
   933 				if (c.error)
       
   934 					ecb.call(o.error_scope || o.scope, c.error, x);
       
   935 				else
       
   936 					scb.call(o.success_scope || o.scope, c.result);
       
   937 			};
       
   938 
       
   939 			o.error = function(ty, x) {
       
   940 				ecb.call(o.error_scope || o.scope, ty, x);
       
   941 			};
       
   942 
       
   943 			o.data = JSON.serialize({
       
   944 				id : o.id || 'c' + (this.count++),
       
   945 				method : o.method,
       
   946 				params : o.params
       
   947 			});
       
   948 
       
   949 			// JSON content type for Ruby on rails. Bug: #1883287
       
   950 			o.content_type = 'application/json';
       
   951 
       
   952 			XHR.send(o);
       
   953 		},
       
   954 
       
   955 		'static' : {
       
   956 			sendRPC : function(o) {
       
   957 				return new tinymce.util.JSONRequest().send(o);
       
   958 			}
       
   959 		}
       
   960 
       
   961 		});
       
   962 }());
       
   963 /* file:jscripts/tiny_mce/classes/dom/DOMUtils.js */
       
   964 
       
   965 (function() {
       
   966 	// Shorten names
       
   967 	var each = tinymce.each, is = tinymce.is;
       
   968 	var isWebKit = tinymce.isWebKit, isIE = tinymce.isIE;
       
   969 
       
   970 	tinymce.create('tinymce.dom.DOMUtils', {
       
   971 		doc : null,
       
   972 		root : null,
       
   973 		files : null,
       
   974 		listeners : {},
       
   975 		pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/,
       
   976 		cache : {},
       
   977 		idPattern : /^#[\w]+$/,
       
   978 		elmPattern : /^[\w_*]+$/,
       
   979 		elmClassPattern : /^([\w_]*)\.([\w_]+)$/,
       
   980 		props : {
       
   981 			"for" : "htmlFor",
       
   982 			"class" : "className",
       
   983 			className : "className",
       
   984 			checked : "checked",
       
   985 			disabled : "disabled",
       
   986 			maxlength : "maxLength",
       
   987 			readonly : "readOnly",
       
   988 			selected : "selected",
       
   989 			value : "value"
       
   990 		},
       
   991 
       
   992 		DOMUtils : function(d, s) {
       
   993 			var t = this;
       
   994 
       
   995 			t.doc = d;
       
   996 			t.win = window;
       
   997 			t.files = {};
       
   998 			t.cssFlicker = false;
       
   999 			t.counter = 0;
       
  1000 			t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat"; 
       
  1001 			t.stdMode = d.documentMode === 8;
       
  1002 
       
  1003 			this.settings = s = tinymce.extend({
       
  1004 				keep_values : false,
       
  1005 				hex_colors : 1,
       
  1006 				process_html : 1
       
  1007 			}, s);
       
  1008 
       
  1009 			// Fix IE6SP2 flicker and check it failed for pre SP2
       
  1010 			if (tinymce.isIE6) {
       
  1011 				try {
       
  1012 					d.execCommand('BackgroundImageCache', false, true);
       
  1013 				} catch (e) {
       
  1014 					t.cssFlicker = true;
       
  1015 				}
       
  1016 			}
       
  1017 
       
  1018 			tinymce.addUnload(t.destroy, t);
       
  1019 		},
       
  1020 
       
  1021 		getRoot : function() {
       
  1022 			var t = this, s = t.settings;
       
  1023 
       
  1024 			return (s && t.get(s.root_element)) || t.doc.body;
       
  1025 		},
       
  1026 
       
  1027 		getViewPort : function(w) {
       
  1028 			var d, b;
       
  1029 
       
  1030 			w = !w ? this.win : w;
       
  1031 			d = w.document;
       
  1032 			b = this.boxModel ? d.documentElement : d.body;
       
  1033 
       
  1034 			// Returns viewport size excluding scrollbars
       
  1035 			return {
       
  1036 				x : w.pageXOffset || b.scrollLeft,
       
  1037 				y : w.pageYOffset || b.scrollTop,
       
  1038 				w : w.innerWidth || b.clientWidth,
       
  1039 				h : w.innerHeight || b.clientHeight
       
  1040 			};
       
  1041 		},
       
  1042 
       
  1043 		getRect : function(e) {
       
  1044 			var p, t = this, sr;
       
  1045 
       
  1046 			e = t.get(e);
       
  1047 			p = t.getPos(e);
       
  1048 			sr = t.getSize(e);
       
  1049 
       
  1050 			return {
       
  1051 				x : p.x,
       
  1052 				y : p.y,
       
  1053 				w : sr.w,
       
  1054 				h : sr.h
       
  1055 			};
       
  1056 		},
       
  1057 
       
  1058 		getSize : function(e) {
       
  1059 			var t = this, w, h;
       
  1060 
       
  1061 			e = t.get(e);
       
  1062 			w = t.getStyle(e, 'width');
       
  1063 			h = t.getStyle(e, 'height');
       
  1064 
       
  1065 			// Non pixel value, then force offset/clientWidth
       
  1066 			if (w.indexOf('px') === -1)
       
  1067 				w = 0;
       
  1068 
       
  1069 			// Non pixel value, then force offset/clientWidth
       
  1070 			if (h.indexOf('px') === -1)
       
  1071 				h = 0;
       
  1072 
       
  1073 			return {
       
  1074 				w : parseInt(w) || e.offsetWidth || e.clientWidth,
       
  1075 				h : parseInt(h) || e.offsetHeight || e.clientHeight
       
  1076 			};
       
  1077 		},
       
  1078 
       
  1079 		getParent : function(n, f, r) {
       
  1080 			var na, se = this.settings;
       
  1081 
       
  1082 			n = this.get(n);
       
  1083 
       
  1084 			if (se.strict_root)
       
  1085 				r = r || this.getRoot();
       
  1086 
       
  1087 			// Wrap node name as func
       
  1088 			if (is(f, 'string')) {
       
  1089 				na = f.toUpperCase();
       
  1090 
       
  1091 				f = function(n) {
       
  1092 					var s = false;
       
  1093 
       
  1094 					// Any element
       
  1095 					if (n.nodeType == 1 && na === '*') {
       
  1096 						s = true;
       
  1097 						return false;
       
  1098 					}
       
  1099 
       
  1100 					each(na.split(','), function(v) {
       
  1101 						if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName.toUpperCase() == v)) {
       
  1102 							s = true;
       
  1103 							return false; // Break loop
       
  1104 						}
       
  1105 					});
       
  1106 
       
  1107 					return s;
       
  1108 				};
       
  1109 			}
       
  1110 
       
  1111 			while (n) {
       
  1112 				if (n == r)
       
  1113 					return null;
       
  1114 
       
  1115 				if (f(n))
       
  1116 					return n;
       
  1117 
       
  1118 				n = n.parentNode;
       
  1119 			}
       
  1120 
       
  1121 			return null;
       
  1122 		},
       
  1123 
       
  1124 		get : function(e) {
       
  1125 			var n;
       
  1126 
       
  1127 			if (e && this.doc && typeof(e) == 'string') {
       
  1128 				n = e;
       
  1129 				e = this.doc.getElementById(e);
       
  1130 
       
  1131 				// IE and Opera returns meta elements when they match the specified input ID, but getElementsByName seems to do the trick
       
  1132 				if (e && e.id !== n)
       
  1133 					return this.doc.getElementsByName(n)[1];
       
  1134 			}
       
  1135 
       
  1136 			return e;
       
  1137 		},
       
  1138 
       
  1139 		// #if !jquery
       
  1140 
       
  1141 		select : function(pa, s) {
       
  1142 			var t = this, cs, c, pl, o = [], x, i, l, n;
       
  1143 
       
  1144 			s = t.get(s) || t.doc;
       
  1145 
       
  1146 			// Look for native support and use that if it's found
       
  1147 			if (s.querySelectorAll) {
       
  1148 				// Element scope then use temp id
       
  1149 				// We need to do this to be compatible with other implementations
       
  1150 				// See bug report: http://bugs.webkit.org/show_bug.cgi?id=17461
       
  1151 				if (s != t.doc) {
       
  1152 					i = s.id;
       
  1153 					s.id = '_mc_tmp';
       
  1154 					pa = '#_mc_tmp ' + pa;
       
  1155 				}
       
  1156 
       
  1157 				// Select elements
       
  1158 				l = tinymce.grep(s.querySelectorAll(pa));
       
  1159 
       
  1160 				// Restore old id
       
  1161 				s.id = i;
       
  1162 
       
  1163 				return l;
       
  1164 			}
       
  1165 
       
  1166 			if (t.settings.strict) {
       
  1167 				function get(s, n) {
       
  1168 					return s.getElementsByTagName(n.toLowerCase());
       
  1169 				};
       
  1170 			} else {
       
  1171 				function get(s, n) {
       
  1172 					return s.getElementsByTagName(n);
       
  1173 				};
       
  1174 			}
       
  1175 
       
  1176 			// Simple element pattern. For example: "p" or "*"
       
  1177 			if (t.elmPattern.test(pa)) {
       
  1178 				x = get(s, pa);
       
  1179 
       
  1180 				for (i = 0, l = x.length; i<l; i++)
       
  1181 					o.push(x[i]);
       
  1182 
       
  1183 				return o;
       
  1184 			}
       
  1185 
       
  1186 			// Simple class pattern. For example: "p.class" or ".class"
       
  1187 			if (t.elmClassPattern.test(pa)) {
       
  1188 				pl = t.elmClassPattern.exec(pa);
       
  1189 				x = get(s, pl[1] || '*');
       
  1190 				c = ' ' + pl[2] + ' ';
       
  1191 
       
  1192 				for (i = 0, l = x.length; i<l; i++) {
       
  1193 					n = x[i];
       
  1194 
       
  1195 					if (n.className && (' ' + n.className + ' ').indexOf(c) !== -1)
       
  1196 						o.push(n);
       
  1197 				}
       
  1198 
       
  1199 				return o;
       
  1200 			}
       
  1201 
       
  1202 			function collect(n) {
       
  1203 				if (!n.mce_save) {
       
  1204 					n.mce_save = 1;
       
  1205 					o.push(n);
       
  1206 				}
       
  1207 			};
       
  1208 
       
  1209 			function collectIE(n) {
       
  1210 				if (!n.getAttribute('mce_save')) {
       
  1211 					n.setAttribute('mce_save', '1');
       
  1212 					o.push(n);
       
  1213 				}
       
  1214 			};
       
  1215 
       
  1216 			function find(n, f, r) {
       
  1217 				var i, l, nl = get(r, n);
       
  1218 
       
  1219 				for (i = 0, l = nl.length; i < l; i++)
       
  1220 					f(nl[i]);
       
  1221 			};
       
  1222 
       
  1223 			each(pa.split(','), function(v, i) {
       
  1224 				v = tinymce.trim(v);
       
  1225 
       
  1226 				// Simple element pattern, most common in TinyMCE
       
  1227 				if (t.elmPattern.test(v)) {
       
  1228 					each(get(s, v), function(n) {
       
  1229 						collect(n);
       
  1230 					});
       
  1231 
       
  1232 					return;
       
  1233 				}
       
  1234 
       
  1235 				// Simple element pattern with class, fairly common in TinyMCE
       
  1236 				if (t.elmClassPattern.test(v)) {
       
  1237 					x = t.elmClassPattern.exec(v);
       
  1238 
       
  1239 					each(get(s, x[1]), function(n) {
       
  1240 						if (t.hasClass(n, x[2]))
       
  1241 							collect(n);
       
  1242 					});
       
  1243 
       
  1244 					return;
       
  1245 				}
       
  1246 
       
  1247 				if (!(cs = t.cache[pa])) {
       
  1248 					cs = 'x=(function(cf, s) {';
       
  1249 					pl = v.split(' ');
       
  1250 
       
  1251 					each(pl, function(v) {
       
  1252 						var p = /^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@([\w\\]+)([\^\$\*!]?=)([\w\\]+)\])?(?:\:([\w\\]+))?/i.exec(v);
       
  1253 
       
  1254 						// Find elements
       
  1255 						p[1] = p[1] || '*';
       
  1256 						cs += 'find("' + p[1] + '", function(n) {';
       
  1257 
       
  1258 						// Check id
       
  1259 						if (p[2])
       
  1260 							cs += 'if (n.id !== "' + p[2] + '") return;';
       
  1261 
       
  1262 						// Check classes
       
  1263 						if (p[3]) {
       
  1264 							cs += 'var c = " " + n.className + " ";';
       
  1265 							cs += 'if (';
       
  1266 							c = '';
       
  1267 							each(p[3].split('.'), function(v) {
       
  1268 								if (v)
       
  1269 									c += (c ? '||' : '') + 'c.indexOf(" ' + v + ' ") === -1';
       
  1270 							});
       
  1271 							cs += c + ') return;';
       
  1272 						}
       
  1273 					});
       
  1274 
       
  1275 					cs += 'cf(n);';
       
  1276 
       
  1277 					for (i = pl.length - 1; i >= 0; i--)
       
  1278 						cs += '}, ' + (i ? 'n' : 's') + ');';
       
  1279 
       
  1280 					cs += '})';
       
  1281 
       
  1282 					// Compile CSS pattern function
       
  1283 					t.cache[pa] = cs = eval(cs);
       
  1284 				}
       
  1285 
       
  1286 				// Run selector function
       
  1287 				cs(isIE ? collectIE : collect, s);
       
  1288 			});
       
  1289 
       
  1290 			// Cleanup
       
  1291 			each(o, function(n) {
       
  1292 				if (isIE)
       
  1293 					n.removeAttribute('mce_save');
       
  1294 				else
       
  1295 					delete n.mce_save;
       
  1296 			});
       
  1297 
       
  1298 			return o;
       
  1299 		},
       
  1300 
       
  1301 		// #endif
       
  1302 
       
  1303 		add : function(p, n, a, h, c) {
       
  1304 			var t = this;
       
  1305 
       
  1306 			return this.run(p, function(p) {
       
  1307 				var e, k;
       
  1308 
       
  1309 				e = is(n, 'string') ? t.doc.createElement(n) : n;
       
  1310 
       
  1311 				if (a) {
       
  1312 					for (k in a) {
       
  1313 						if (a.hasOwnProperty(k) && !is(a[k], 'object'))
       
  1314 							t.setAttrib(e, k, '' + a[k]);
       
  1315 					}
       
  1316 
       
  1317 					if (a.style && !is(a.style, 'string')) {
       
  1318 						each(a.style, function(v, n) {
       
  1319 							t.setStyle(e, n, v);
       
  1320 						});
       
  1321 					}
       
  1322 				}
       
  1323 
       
  1324 				if (h) {
       
  1325 					if (h.nodeType)
       
  1326 						e.appendChild(h);
       
  1327 					else
       
  1328 						t.setHTML(e, h);
       
  1329 				}
       
  1330 
       
  1331 				return !c ? p.appendChild(e) : e;
       
  1332 			});
       
  1333 		},
       
  1334 
       
  1335 		create : function(n, a, h) {
       
  1336 			return this.add(this.doc.createElement(n), n, a, h, 1);
       
  1337 		},
       
  1338 
       
  1339 		createHTML : function(n, a, h) {
       
  1340 			var o = '', t = this, k;
       
  1341 
       
  1342 			o += '<' + n;
       
  1343 
       
  1344 			for (k in a) {
       
  1345 				if (a.hasOwnProperty(k))
       
  1346 					o += ' ' + k + '="' + t.encode(a[k]) + '"';
       
  1347 			}
       
  1348 
       
  1349 			if (tinymce.is(h))
       
  1350 				return o + '>' + h + '</' + n + '>';
       
  1351 
       
  1352 			return o + ' />';
       
  1353 		},
       
  1354 
       
  1355 		remove : function(n, k) {
       
  1356 			return this.run(n, function(n) {
       
  1357 				var p, g;
       
  1358 
       
  1359 				p = n.parentNode;
       
  1360 
       
  1361 				if (!p)
       
  1362 					return null;
       
  1363 
       
  1364 				if (k) {
       
  1365 					each (n.childNodes, function(c) {
       
  1366 						p.insertBefore(c.cloneNode(true), n);
       
  1367 					});
       
  1368 				}
       
  1369 
       
  1370 				// Fix IE psuedo leak
       
  1371 		/*		if (isIE) {
       
  1372 					p = n.cloneNode(true);
       
  1373 					n.outerHTML = '';
       
  1374 
       
  1375 					return p;
       
  1376 				}*/
       
  1377 
       
  1378 				return p.removeChild(n);
       
  1379 			});
       
  1380 		},
       
  1381 
       
  1382 		// #if !jquery
       
  1383 
       
  1384 		setStyle : function(n, na, v) {
       
  1385 			var t = this;
       
  1386 
       
  1387 			return t.run(n, function(e) {
       
  1388 				var s, i;
       
  1389 
       
  1390 				s = e.style;
       
  1391 
       
  1392 				// Camelcase it, if needed
       
  1393 				na = na.replace(/-(\D)/g, function(a, b){
       
  1394 					return b.toUpperCase();
       
  1395 				});
       
  1396 
       
  1397 				// Default px suffix on these
       
  1398 				if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v)))
       
  1399 					v += 'px';
       
  1400 
       
  1401 				switch (na) {
       
  1402 					case 'opacity':
       
  1403 						// IE specific opacity
       
  1404 						if (isIE) {
       
  1405 							s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")";
       
  1406 
       
  1407 							if (!n.currentStyle || !n.currentStyle.hasLayout)
       
  1408 								s.display = 'inline-block';
       
  1409 						}
       
  1410 
       
  1411 						// Fix for older browsers
       
  1412 						s[na] = s['-moz-opacity'] = s['-khtml-opacity'] = v || '';
       
  1413 						break;
       
  1414 
       
  1415 					case 'float':
       
  1416 						isIE ? s.styleFloat = v : s.cssFloat = v;
       
  1417 						break;
       
  1418 					
       
  1419 					default:
       
  1420 						s[na] = v || '';
       
  1421 				}
       
  1422 
       
  1423 				// Force update of the style data
       
  1424 				if (t.settings.update_styles)
       
  1425 					t.setAttrib(e, 'mce_style');
       
  1426 			});
       
  1427 		},
       
  1428 
       
  1429 		getStyle : function(n, na, c) {
       
  1430 			n = this.get(n);
       
  1431 
       
  1432 			if (!n)
       
  1433 				return false;
       
  1434 
       
  1435 			// Gecko
       
  1436 			if (this.doc.defaultView && c) {
       
  1437 				// Remove camelcase
       
  1438 				na = na.replace(/[A-Z]/g, function(a){
       
  1439 					return '-' + a;
       
  1440 				});
       
  1441 
       
  1442 				try {
       
  1443 					return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na);
       
  1444 				} catch (ex) {
       
  1445 					// Old safari might fail
       
  1446 					return null;
       
  1447 				}
       
  1448 			}
       
  1449 
       
  1450 			// Camelcase it, if needed
       
  1451 			na = na.replace(/-(\D)/g, function(a, b){
       
  1452 				return b.toUpperCase();
       
  1453 			});
       
  1454 
       
  1455 			if (na == 'float')
       
  1456 				na = isIE ? 'styleFloat' : 'cssFloat';
       
  1457 
       
  1458 			// IE & Opera
       
  1459 			if (n.currentStyle && c)
       
  1460 				return n.currentStyle[na];
       
  1461 
       
  1462 			return n.style[na];
       
  1463 		},
       
  1464 
       
  1465 		setStyles : function(e, o) {
       
  1466 			var t = this, s = t.settings, ol;
       
  1467 
       
  1468 			ol = s.update_styles;
       
  1469 			s.update_styles = 0;
       
  1470 
       
  1471 			each(o, function(v, n) {
       
  1472 				t.setStyle(e, n, v);
       
  1473 			});
       
  1474 
       
  1475 			// Update style info
       
  1476 			s.update_styles = ol;
       
  1477 			if (s.update_styles)
       
  1478 				t.setAttrib(e, s.cssText);
       
  1479 		},
       
  1480 
       
  1481 		setAttrib : function(e, n, v) {
       
  1482 			var t = this;
       
  1483 
       
  1484 			// Whats the point
       
  1485 			if (!e || !n)
       
  1486 				return;
       
  1487 
       
  1488 			// Strict XML mode
       
  1489 			if (t.settings.strict)
       
  1490 				n = n.toLowerCase();
       
  1491 
       
  1492 			return this.run(e, function(e) {
       
  1493 				var s = t.settings;
       
  1494 
       
  1495 				switch (n) {
       
  1496 					case "style":
       
  1497 						// No mce_style for elements with these since they might get resized by the user
       
  1498 						if (s.keep_values) {
       
  1499 							if (v && !t._isRes(v))
       
  1500 								e.setAttribute('mce_style', v, 2);
       
  1501 							else
       
  1502 								e.removeAttribute('mce_style', 2);
       
  1503 						}
       
  1504 
       
  1505 						e.style.cssText = v;
       
  1506 						break;
       
  1507 
       
  1508 					case "class":
       
  1509 						e.className = v || ''; // Fix IE null bug
       
  1510 						break;
       
  1511 
       
  1512 					case "src":
       
  1513 					case "href":
       
  1514 						if (s.keep_values) {
       
  1515 							if (s.url_converter)
       
  1516 								v = s.url_converter.call(s.url_converter_scope || t, v, n, e);
       
  1517 
       
  1518 							t.setAttrib(e, 'mce_' + n, v, 2);
       
  1519 						}
       
  1520 
       
  1521 						break;
       
  1522 					
       
  1523 					case "shape":
       
  1524 						e.setAttribute('mce_style', v);
       
  1525 						break;
       
  1526 				}
       
  1527 
       
  1528 				if (is(v) && v !== null && v.length !== 0)
       
  1529 					e.setAttribute(n, '' + v, 2);
       
  1530 				else
       
  1531 					e.removeAttribute(n, 2);
       
  1532 			});
       
  1533 		},
       
  1534 
       
  1535 		setAttribs : function(e, o) {
       
  1536 			var t = this;
       
  1537 
       
  1538 			return this.run(e, function(e) {
       
  1539 				each(o, function(v, n) {
       
  1540 					t.setAttrib(e, n, v);
       
  1541 				});
       
  1542 			});
       
  1543 		},
       
  1544 
       
  1545 		// #endif
       
  1546 
       
  1547 		getAttrib : function(e, n, dv) {
       
  1548 			var v, t = this;
       
  1549 
       
  1550 			e = t.get(e);
       
  1551 
       
  1552 			if (!e || e.nodeType !== 1)
       
  1553 				return false;
       
  1554 
       
  1555 			if (!is(dv))
       
  1556 				dv = '';
       
  1557 
       
  1558 			// Try the mce variant for these
       
  1559 			if (/^(src|href|style|coords|shape)$/.test(n)) {
       
  1560 				v = e.getAttribute("mce_" + n);
       
  1561 
       
  1562 				if (v)
       
  1563 					return v;
       
  1564 			}
       
  1565 
       
  1566 			if (isIE && t.props[n]) {
       
  1567 				v = e[t.props[n]];
       
  1568 				v = v && v.nodeValue ? v.nodeValue : v;
       
  1569 			}
       
  1570 
       
  1571 			if (!v)
       
  1572 				v = e.getAttribute(n, 2);
       
  1573 
       
  1574 			if (n === 'style') {
       
  1575 				v = v || e.style.cssText;
       
  1576 
       
  1577 				if (v) {
       
  1578 					v = t.serializeStyle(t.parseStyle(v));
       
  1579 
       
  1580 					if (t.settings.keep_values && !t._isRes(v))
       
  1581 						e.setAttribute('mce_style', v);
       
  1582 				}
       
  1583 			}
       
  1584 
       
  1585 			// Remove Apple and WebKit stuff
       
  1586 			if (isWebKit && n === "class" && v)
       
  1587 				v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, '');
       
  1588 
       
  1589 			// Handle IE issues
       
  1590 			if (isIE) {
       
  1591 				switch (n) {
       
  1592 					case 'rowspan':
       
  1593 					case 'colspan':
       
  1594 						// IE returns 1 as default value
       
  1595 						if (v === 1)
       
  1596 							v = '';
       
  1597 
       
  1598 						break;
       
  1599 
       
  1600 					case 'size':
       
  1601 						// IE returns +0 as default value for size
       
  1602 						if (v === '+0' || v === 20)
       
  1603 							v = '';
       
  1604 
       
  1605 						break;
       
  1606 
       
  1607 					case 'width':
       
  1608 					case 'height':
       
  1609 					case 'vspace':
       
  1610 						if (v === 0)
       
  1611 							v = '';
       
  1612 
       
  1613 						break;
       
  1614 
       
  1615 					case 'hspace':
       
  1616 						// IE returns -1 as default value
       
  1617 						if (v === -1)
       
  1618 							v = '';
       
  1619 
       
  1620 						break;
       
  1621 
       
  1622 					case 'maxlength':
       
  1623 					case 'tabindex':
       
  1624 						// IE returns default value
       
  1625 						if (v === 32768 || v === 2147483647)
       
  1626 							v = '';
       
  1627 
       
  1628 						break;
       
  1629 
       
  1630 					case 'compact':
       
  1631 					case 'noshade':
       
  1632 						if (v === 65535)
       
  1633 							return n;
       
  1634 
       
  1635 						return dv;
       
  1636 
       
  1637 					case 'shape':
       
  1638 						v = v.toLowerCase();
       
  1639 						break;
       
  1640 
       
  1641 					default:
       
  1642 						// IE has odd anonymous function for event attributes
       
  1643 						if (n.indexOf('on') === 0 && v)
       
  1644 							v = ('' + v).replace(/^function\s+anonymous\(\)\s+\{\s+(.*)\s+\}$/, '$1');
       
  1645 				}
       
  1646 			}
       
  1647 
       
  1648 			return (v !== undefined && v !== null && v !== '') ? '' + v : dv;
       
  1649 		},
       
  1650 
       
  1651 		getPos : function(n) {
       
  1652 			var t = this, x = 0, y = 0, e, d = t.doc, r;
       
  1653 
       
  1654 			n = t.get(n);
       
  1655 
       
  1656 			// Use getBoundingClientRect on IE, Opera has it but it's not perfect
       
  1657 			if (n && isIE) {
       
  1658 				n = n.getBoundingClientRect();
       
  1659 				e = t.boxModel ? d.documentElement : d.body;
       
  1660 				x = t.getStyle(t.select('html')[0], 'borderWidth'); // Remove border
       
  1661 				x = (x == 'medium' || t.boxModel && !t.isIE6) && 2 || x;
       
  1662 				n.top += t.win.self != t.win.top ? 2 : 0; // IE adds some strange extra cord if used in a frameset
       
  1663 
       
  1664 				return {x : n.left + e.scrollLeft - x, y : n.top + e.scrollTop - x};
       
  1665 			}
       
  1666 
       
  1667 			r = n;
       
  1668 			while (r) {
       
  1669 				x += r.offsetLeft || 0;
       
  1670 				y += r.offsetTop || 0;
       
  1671 				r = r.offsetParent;
       
  1672 			}
       
  1673 
       
  1674 			r = n;
       
  1675 			while (r) {
       
  1676 				// Opera 9.25 bug fix, fixed in 9.50
       
  1677 				if (!/^table-row|inline.*/i.test(t.getStyle(r, "display", 1))) {
       
  1678 					x -= r.scrollLeft || 0;
       
  1679 					y -= r.scrollTop || 0;
       
  1680 				}
       
  1681 
       
  1682 				r = r.parentNode;
       
  1683 
       
  1684 				if (r == d.body)
       
  1685 					break;
       
  1686 			}
       
  1687 
       
  1688 			return {x : x, y : y};
       
  1689 		},
       
  1690 
       
  1691 		parseStyle : function(st) {
       
  1692 			var t = this, s = t.settings, o = {};
       
  1693 
       
  1694 			if (!st)
       
  1695 				return o;
       
  1696 
       
  1697 			function compress(p, s, ot) {
       
  1698 				var t, r, b, l;
       
  1699 
       
  1700 				// Get values and check it it needs compressing
       
  1701 				t = o[p + '-top' + s];
       
  1702 				if (!t)
       
  1703 					return;
       
  1704 
       
  1705 				r = o[p + '-right' + s];
       
  1706 				if (t != r)
       
  1707 					return;
       
  1708 
       
  1709 				b = o[p + '-bottom' + s];
       
  1710 				if (r != b)
       
  1711 					return;
       
  1712 
       
  1713 				l = o[p + '-left' + s];
       
  1714 				if (b != l)
       
  1715 					return;
       
  1716 
       
  1717 				// Compress
       
  1718 				o[ot] = l;
       
  1719 				delete o[p + '-top' + s];
       
  1720 				delete o[p + '-right' + s];
       
  1721 				delete o[p + '-bottom' + s];
       
  1722 				delete o[p + '-left' + s];
       
  1723 			};
       
  1724 
       
  1725 			function compress2(ta, a, b, c) {
       
  1726 				var t;
       
  1727 
       
  1728 				t = o[a];
       
  1729 				if (!t)
       
  1730 					return;
       
  1731 
       
  1732 				t = o[b];
       
  1733 				if (!t)
       
  1734 					return;
       
  1735 
       
  1736 				t = o[c];
       
  1737 				if (!t)
       
  1738 					return;
       
  1739 
       
  1740 				// Compress
       
  1741 				o[ta] = o[a] + ' ' + o[b] + ' ' + o[c];
       
  1742 				delete o[a];
       
  1743 				delete o[b];
       
  1744 				delete o[c];
       
  1745 			};
       
  1746 
       
  1747 			st = st.replace(/&(#?[a-z0-9]+);/g, '&$1_MCE_SEMI_'); // Protect entities
       
  1748 
       
  1749 			each(st.split(';'), function(v) {
       
  1750 				var sv, ur = [];
       
  1751 
       
  1752 				if (v) {
       
  1753 					v = v.replace(/_MCE_SEMI_/g, ';'); // Restore entities
       
  1754 					v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});
       
  1755 					v = v.split(':');
       
  1756 					sv = tinymce.trim(v[1]);
       
  1757 					sv = sv.replace(/url\(([^\)]+)\)/g, function(a, b) {return ur[parseInt(b) - 1];});
       
  1758 
       
  1759 					sv = sv.replace(/rgb\([^\)]+\)/g, function(v) {
       
  1760 						return t.toHex(v);
       
  1761 					});
       
  1762 
       
  1763 					if (s.url_converter) {
       
  1764 						sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {
       
  1765 							return 'url(' + s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null) + ')';
       
  1766 						});
       
  1767 					}
       
  1768 
       
  1769 					o[tinymce.trim(v[0]).toLowerCase()] = sv;
       
  1770 				}
       
  1771 			});
       
  1772 
       
  1773 			compress("border", "", "border");
       
  1774 			compress("border", "-width", "border-width");
       
  1775 			compress("border", "-color", "border-color");
       
  1776 			compress("border", "-style", "border-style");
       
  1777 			compress("padding", "", "padding");
       
  1778 			compress("margin", "", "margin");
       
  1779 			compress2('border', 'border-width', 'border-style', 'border-color');
       
  1780 
       
  1781 			if (isIE) {
       
  1782 				// Remove pointless border
       
  1783 				if (o.border == 'medium none')
       
  1784 					o.border = '';
       
  1785 			}
       
  1786 
       
  1787 			return o;
       
  1788 		},
       
  1789 
       
  1790 		serializeStyle : function(o) {
       
  1791 			var s = '';
       
  1792 
       
  1793 			each(o, function(v, k) {
       
  1794 				if (k && v) {
       
  1795 					if (tinymce.isGecko && k.indexOf('-moz-') === 0)
       
  1796 						return;
       
  1797 
       
  1798 					switch (k) {
       
  1799 						case 'color':
       
  1800 						case 'background-color':
       
  1801 							v = v.toLowerCase();
       
  1802 							break;
       
  1803 					}
       
  1804 
       
  1805 					s += (s ? ' ' : '') + k + ': ' + v + ';';
       
  1806 				}
       
  1807 			});
       
  1808 
       
  1809 			return s;
       
  1810 		},
       
  1811 
       
  1812 		loadCSS : function(u) {
       
  1813 			var t = this, d = t.doc;
       
  1814 
       
  1815 			if (!u)
       
  1816 				u = '';
       
  1817 
       
  1818 			each(u.split(','), function(u) {
       
  1819 				if (t.files[u])
       
  1820 					return;
       
  1821 
       
  1822 				t.files[u] = true;
       
  1823 				t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : tinymce._addVer(u)});
       
  1824 			});
       
  1825 		},
       
  1826 
       
  1827 		// #if !jquery
       
  1828 
       
  1829 		addClass : function(e, c) {
       
  1830 			return this.run(e, function(e) {
       
  1831 				var o;
       
  1832 
       
  1833 				if (!c)
       
  1834 					return 0;
       
  1835 
       
  1836 				if (this.hasClass(e, c))
       
  1837 					return e.className;
       
  1838 
       
  1839 				o = this.removeClass(e, c);
       
  1840 
       
  1841 				return e.className = (o != '' ? (o + ' ') : '') + c;
       
  1842 			});
       
  1843 		},
       
  1844 
       
  1845 		removeClass : function(e, c) {
       
  1846 			var t = this, re;
       
  1847 
       
  1848 			return t.run(e, function(e) {
       
  1849 				var v;
       
  1850 
       
  1851 				if (t.hasClass(e, c)) {
       
  1852 					if (!re)
       
  1853 						re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g");
       
  1854 
       
  1855 					v = e.className.replace(re, ' ');
       
  1856 
       
  1857 					return e.className = tinymce.trim(v != ' ' ? v : '');
       
  1858 				}
       
  1859 
       
  1860 				return e.className;
       
  1861 			});
       
  1862 		},
       
  1863 
       
  1864 		hasClass : function(n, c) {
       
  1865 			n = this.get(n);
       
  1866 
       
  1867 			if (!n || !c)
       
  1868 				return false;
       
  1869 
       
  1870 			return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1;
       
  1871 		},
       
  1872 
       
  1873 		show : function(e) {
       
  1874 			return this.setStyle(e, 'display', 'block');
       
  1875 		},
       
  1876 
       
  1877 		hide : function(e) {
       
  1878 			return this.setStyle(e, 'display', 'none');
       
  1879 		},
       
  1880 
       
  1881 		isHidden : function(e) {
       
  1882 			e = this.get(e);
       
  1883 
       
  1884 			return e.style.display == 'none' || this.getStyle(e, 'display') == 'none';
       
  1885 		},
       
  1886 
       
  1887 		// #endif
       
  1888 
       
  1889 		uniqueId : function(p) {
       
  1890 			return (!p ? 'mce_' : p) + (this.counter++);
       
  1891 		},
       
  1892 
       
  1893 		setHTML : function(e, h) {
       
  1894 			var t = this;
       
  1895 
       
  1896 			return this.run(e, function(e) {
       
  1897 				var x, i, nl, n, p, x;
       
  1898 
       
  1899 				h = t.processHTML(h);
       
  1900 
       
  1901 				if (isIE) {
       
  1902 					function set() {
       
  1903 						try {
       
  1904 							// IE will remove comments from the beginning
       
  1905 							// unless you padd the contents with something
       
  1906 							e.innerHTML = '<br />' + h;
       
  1907 							e.removeChild(e.firstChild);
       
  1908 						} catch (ex) {
       
  1909 							// IE sometimes produces an unknown runtime error on innerHTML if it's an block element within a block element for example a div inside a p
       
  1910 							// This seems to fix this problem
       
  1911 
       
  1912 							// Remove all child nodes
       
  1913 							while (e.firstChild)
       
  1914 								e.firstChild.removeNode();
       
  1915 
       
  1916 							// Create new div with HTML contents and a BR infront to keep comments
       
  1917 							x = t.create('div');
       
  1918 							x.innerHTML = '<br />' + h;
       
  1919 
       
  1920 							// Add all children from div to target
       
  1921 							each (x.childNodes, function(n, i) {
       
  1922 								// Skip br element
       
  1923 								if (i)
       
  1924 									e.appendChild(n);
       
  1925 							});
       
  1926 						}
       
  1927 					};
       
  1928 
       
  1929 					// IE has a serious bug when it comes to paragraphs it can produce an invalid
       
  1930 					// DOM tree if contents like this <p><ul><li>Item 1</li></ul></p> is inserted
       
  1931 					// It seems to be that IE doesn't like a root block element placed inside another root block element
       
  1932 					if (t.settings.fix_ie_paragraphs)
       
  1933 						h = h.replace(/<p><\/p>|<p([^>]+)><\/p>|<p[^\/+]\/>/gi, '<p$1 mce_keep="true">&nbsp;</p>');
       
  1934 
       
  1935 					set();
       
  1936 
       
  1937 					if (t.settings.fix_ie_paragraphs) {
       
  1938 						// Check for odd paragraphs this is a sign of a broken DOM
       
  1939 						nl = e.getElementsByTagName("p");
       
  1940 						for (i = nl.length - 1, x = 0; i >= 0; i--) {
       
  1941 							n = nl[i];
       
  1942 
       
  1943 							if (!n.hasChildNodes()) {
       
  1944 								if (!n.mce_keep) {
       
  1945 									x = 1; // Is broken
       
  1946 									break;
       
  1947 								}
       
  1948 
       
  1949 								n.removeAttribute('mce_keep');
       
  1950 							}
       
  1951 						}
       
  1952 					}
       
  1953 
       
  1954 					// Time to fix the madness IE left us
       
  1955 					if (x) {
       
  1956 						// So if we replace the p elements with divs and mark them and then replace them back to paragraphs
       
  1957 						// after we use innerHTML we can fix the DOM tree
       
  1958 						h = h.replace(/<p([^>]+)>|<p>/g, '<div$1 mce_tmp="1">');
       
  1959 						h = h.replace(/<\/p>/g, '</div>');
       
  1960 
       
  1961 						// Set the new HTML with DIVs
       
  1962 						set();
       
  1963 
       
  1964 						// Replace all DIV elements with he mce_tmp attibute back to paragraphs
       
  1965 						// This is needed since IE has a annoying bug see above for details
       
  1966 						// This is a slow process but it has to be done. :(
       
  1967 						if (t.settings.fix_ie_paragraphs) {
       
  1968 							nl = e.getElementsByTagName("DIV");
       
  1969 							for (i = nl.length - 1; i >= 0; i--) {
       
  1970 								n = nl[i];
       
  1971 
       
  1972 								// Is it a temp div
       
  1973 								if (n.mce_tmp) {
       
  1974 									// Create new paragraph
       
  1975 									p = t.doc.createElement('p');
       
  1976 
       
  1977 									// Copy all attributes
       
  1978 									n.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi, function(a, b) {
       
  1979 										var v;
       
  1980 
       
  1981 										if (b !== 'mce_tmp') {
       
  1982 											v = n.getAttribute(b);
       
  1983 
       
  1984 											if (!v && b === 'class')
       
  1985 												v = n.className;
       
  1986 
       
  1987 											p.setAttribute(b, v);
       
  1988 										}
       
  1989 									});
       
  1990 
       
  1991 									// Append all children to new paragraph
       
  1992 									for (x = 0; x<n.childNodes.length; x++)
       
  1993 										p.appendChild(n.childNodes[x].cloneNode(true));
       
  1994 
       
  1995 									// Replace div with new paragraph
       
  1996 									n.swapNode(p);
       
  1997 								}
       
  1998 							}
       
  1999 						}
       
  2000 					}
       
  2001 				} else
       
  2002 					e.innerHTML = h;
       
  2003 
       
  2004 				return h;
       
  2005 			});
       
  2006 		},
       
  2007 
       
  2008 		processHTML : function(h) {
       
  2009 			var t = this, s = t.settings;
       
  2010 
       
  2011 			if (!s.process_html)
       
  2012 				return h;
       
  2013 
       
  2014 			// Convert strong and em to b and i in FF since it can't handle them
       
  2015 			if (tinymce.isGecko) {
       
  2016 				h = h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi, '<$1b$2>');
       
  2017 				h = h.replace(/<(\/?)em>|<em( [^>]+)>/gi, '<$1i$2>');
       
  2018 			} else if (isIE)
       
  2019 				h = h.replace(/&apos;/g, '&#39;'); // IE can't handle apos
       
  2020 
       
  2021 			// Fix some issues
       
  2022 			h = h.replace(/<a( )([^>]+)\/>|<a\/>/gi, '<a$1$2></a>'); // Force open
       
  2023 
       
  2024 			// Store away src and href in mce_src and mce_href since browsers mess them up
       
  2025 			if (s.keep_values) {
       
  2026 				h = h.replace(/<!\[CDATA\[([\s\S]+)\]\]>/g, '<!--[CDATA[$1]]-->');
       
  2027 
       
  2028 				// Wrap scripts and styles in comments for serialization purposes
       
  2029 				if (/<script|style/.test(h)) {
       
  2030 					function trim(s) {
       
  2031 						// Remove prefix and suffix code for element
       
  2032 						s = s.replace(/^[\r\n]*|[\r\n]*$/g, '');
       
  2033 						s = s.replace(/^\s*(\/\/\s*<!--|\/\/\s*<\[CDATA\[|<!--|<\[CDATA\[)[\r\n]*/g, '');
       
  2034 						s = s.replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->)\s*$/g, '');
       
  2035 
       
  2036 						return s;
       
  2037 					};
       
  2038 
       
  2039 					// Preserve script elements
       
  2040 					h = h.replace(/<script([^>]+|)>([\s\S]*?)<\/script>/g, function(v, a, b) {
       
  2041 						// Remove prefix and suffix code for script element
       
  2042 						b = trim(b);
       
  2043 
       
  2044 						// Force type attribute
       
  2045 						if (!a)
       
  2046 							a = ' type="text/javascript"';
       
  2047 
       
  2048 						// Wrap contents in a comment
       
  2049 						if (b)
       
  2050 							b = '<!--\n' + b + '\n// -->';
       
  2051 
       
  2052 						// Output fake element
       
  2053 						return '<mce:script' + a + '>' + b + '</mce:script>';
       
  2054 					});
       
  2055 
       
  2056 					// Preserve style elements
       
  2057 					h = h.replace(/<style([^>]+|)>([\s\S]*?)<\/style>/g, function(v, a, b) {
       
  2058 						b = trim(b);
       
  2059 						return '<mce:style' + a + '><!--\n' + b + '\n--></mce:style><style' + a + ' mce_bogus="1">' + b + '</style>';
       
  2060 					});
       
  2061 				}
       
  2062 
       
  2063 				// Process all tags with src, href or style
       
  2064 				h = h.replace(/<([\w:]+) [^>]*(src|href|style|shape|coords)[^>]*>/gi, function(a, n) {
       
  2065 					function handle(m, b, c) {
       
  2066 						var u = c;
       
  2067 
       
  2068 						// Tag already got a mce_ version
       
  2069 						if (a.indexOf('mce_' + b) != -1)
       
  2070 							return m;
       
  2071 
       
  2072 						if (b == 'style') {
       
  2073 							// Why did I need this one?
       
  2074 							//if (isIE)
       
  2075 							//	u = t.serializeStyle(t.parseStyle(u));
       
  2076 
       
  2077 							// No mce_style for elements with these since they might get resized by the user
       
  2078 							if (t._isRes(c))
       
  2079 								return m;
       
  2080 
       
  2081 							if (s.hex_colors) {
       
  2082 								u = u.replace(/rgb\([^\)]+\)/g, function(v) {
       
  2083 									return t.toHex(v);
       
  2084 								});
       
  2085 							}
       
  2086 
       
  2087 							if (s.url_converter) {
       
  2088 								u = u.replace(/url\([\'\"]?([^\)\'\"]+)\)/g, function(x, c) {
       
  2089 									return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n)) + ')';
       
  2090 								});
       
  2091 							}
       
  2092 						} else if (b != 'coords' && b != 'shape') {
       
  2093 							if (s.url_converter)
       
  2094 								u = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n));
       
  2095 						}
       
  2096 
       
  2097 						return ' ' + b + '="' + c + '" mce_' + b + '="' + u + '"';
       
  2098 					};
       
  2099 
       
  2100 					a = a.replace(/ (src|href|style|coords|shape)=[\"]([^\"]+)[\"]/gi, handle); // W3C
       
  2101 					a = a.replace(/ (src|href|style|coords|shape)=[\']([^\']+)[\']/gi, handle); // W3C
       
  2102 
       
  2103 					return a.replace(/ (src|href|style|coords|shape)=([^\s\"\'>]+)/gi, handle); // IE
       
  2104 				});
       
  2105 			}
       
  2106 
       
  2107 			return h;
       
  2108 		},
       
  2109 
       
  2110 		getOuterHTML : function(e) {
       
  2111 			var d;
       
  2112 
       
  2113 			e = this.get(e);
       
  2114 
       
  2115 			if (!e)
       
  2116 				return null;
       
  2117 
       
  2118 			if (isIE)
       
  2119 				return e.outerHTML;
       
  2120 
       
  2121 			d = (e.ownerDocument || this.doc).createElement("body");
       
  2122 			d.appendChild(e.cloneNode(true));
       
  2123 
       
  2124 			return d.innerHTML;
       
  2125 		},
       
  2126 
       
  2127 		setOuterHTML : function(e, h, d) {
       
  2128 			var t = this;
       
  2129 
       
  2130 			return this.run(e, function(e) {
       
  2131 				var n, tp;
       
  2132 
       
  2133 				e = t.get(e);
       
  2134 				d = d || e.ownerDocument || t.doc;
       
  2135 
       
  2136 				if (isIE && e.nodeType == 1)
       
  2137 					e.outerHTML = h;
       
  2138 				else {
       
  2139 					tp = d.createElement("body");
       
  2140 					tp.innerHTML = h;
       
  2141 
       
  2142 					n = tp.lastChild;
       
  2143 					while (n) {
       
  2144 						t.insertAfter(n.cloneNode(true), e);
       
  2145 						n = n.previousSibling;
       
  2146 					}
       
  2147 
       
  2148 					t.remove(e);
       
  2149 				}
       
  2150 			});
       
  2151 		},
       
  2152 
       
  2153 		decode : function(s) {
       
  2154 			var e;
       
  2155 
       
  2156 			// Look for entities to decode
       
  2157 			if (/&[^;]+;/.test(s)) {
       
  2158 				// Decode the entities using a div element not super efficient but less code
       
  2159 				e = this.doc.createElement("div");
       
  2160 				e.innerHTML = s;
       
  2161 
       
  2162 				return !e.firstChild ? s : e.firstChild.nodeValue;
       
  2163 			}
       
  2164 
       
  2165 			return s;
       
  2166 		},
       
  2167 
       
  2168 		encode : function(s) {
       
  2169 			return s ? ('' + s).replace(/[<>&\"]/g, function (c, b) {
       
  2170 				switch (c) {
       
  2171 					case '&':
       
  2172 						return '&amp;';
       
  2173 
       
  2174 					case '"':
       
  2175 						return '&quot;';
       
  2176 
       
  2177 					case '<':
       
  2178 						return '&lt;';
       
  2179 
       
  2180 					case '>':
       
  2181 						return '&gt;';
       
  2182 				}
       
  2183 
       
  2184 				return c;
       
  2185 			}) : s;
       
  2186 		},
       
  2187 
       
  2188 		// #if !jquery
       
  2189 
       
  2190 		insertAfter : function(n, r) {
       
  2191 			var t = this;
       
  2192 
       
  2193 			r = t.get(r);
       
  2194 
       
  2195 			return this.run(n, function(n) {
       
  2196 				var p, ns;
       
  2197 
       
  2198 				p = r.parentNode;
       
  2199 				ns = r.nextSibling;
       
  2200 
       
  2201 				if (ns)
       
  2202 					p.insertBefore(n, ns);
       
  2203 				else
       
  2204 					p.appendChild(n);
       
  2205 
       
  2206 				return n;
       
  2207 			});
       
  2208 		},
       
  2209 
       
  2210 		// #endif
       
  2211 
       
  2212 		isBlock : function(n) {
       
  2213 			if (n.nodeType && n.nodeType !== 1)
       
  2214 				return false;
       
  2215 
       
  2216 			n = n.nodeName || n;
       
  2217 
       
  2218 			return /^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n);
       
  2219 		},
       
  2220 
       
  2221 		// #if !jquery
       
  2222 
       
  2223 		replace : function(n, o, k) {
       
  2224 			if (is(o, 'array'))
       
  2225 				n = n.cloneNode(true);
       
  2226 
       
  2227 			return this.run(o, function(o) {
       
  2228 				if (k) {
       
  2229 					each(o.childNodes, function(c) {
       
  2230 						n.appendChild(c.cloneNode(true));
       
  2231 					});
       
  2232 				}
       
  2233 
       
  2234 				// Fix IE psuedo leak for elements since replacing elements if fairly common
       
  2235 				// Will break parentNode for some unknown reason
       
  2236 	/*			if (isIE && o.nodeType === 1) {
       
  2237 					o.parentNode.insertBefore(n, o);
       
  2238 					o.outerHTML = '';
       
  2239 					return n;
       
  2240 				}*/
       
  2241 
       
  2242 				return o.parentNode.replaceChild(n, o);
       
  2243 			});
       
  2244 		},
       
  2245 
       
  2246 		// #endif
       
  2247 
       
  2248 		toHex : function(s) {
       
  2249 			var c = /^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s);
       
  2250 
       
  2251 			function hex(s) {
       
  2252 				s = parseInt(s).toString(16);
       
  2253 
       
  2254 				return s.length > 1 ? s : '0' + s; // 0 -> 00
       
  2255 			};
       
  2256 
       
  2257 			if (c) {
       
  2258 				s = '#' + hex(c[1]) + hex(c[2]) + hex(c[3]);
       
  2259 
       
  2260 				return s;
       
  2261 			}
       
  2262 
       
  2263 			return s;
       
  2264 		},
       
  2265 
       
  2266 		getClasses : function() {
       
  2267 			var t = this, cl = [], i, lo = {}, f = t.settings.class_filter, ov;
       
  2268 
       
  2269 			if (t.classes)
       
  2270 				return t.classes;
       
  2271 
       
  2272 			function addClasses(s) {
       
  2273 				// IE style imports
       
  2274 				each(s.imports, function(r) {
       
  2275 					addClasses(r);
       
  2276 				});
       
  2277 
       
  2278 				each(s.cssRules || s.rules, function(r) {
       
  2279 					// Real type or fake it on IE
       
  2280 					switch (r.type || 1) {
       
  2281 						// Rule
       
  2282 						case 1:
       
  2283 							if (r.selectorText) {
       
  2284 								each(r.selectorText.split(','), function(v) {
       
  2285 									v = v.replace(/^\s*|\s*$|^\s\./g, "");
       
  2286 
       
  2287 									// Is internal or it doesn't contain a class
       
  2288 									if (/\.mce/.test(v) || !/\.[\w\-]+$/.test(v))
       
  2289 										return;
       
  2290 
       
  2291 									// Remove everything but class name
       
  2292 									ov = v;
       
  2293 									v = v.replace(/.*\.([a-z0-9_\-]+).*/i, '$1');
       
  2294 
       
  2295 									// Filter classes
       
  2296 									if (f && !(v = f(v, ov)))
       
  2297 										return;
       
  2298 
       
  2299 									if (!lo[v]) {
       
  2300 										cl.push({'class' : v});
       
  2301 										lo[v] = 1;
       
  2302 									}
       
  2303 								});
       
  2304 							}
       
  2305 							break;
       
  2306 
       
  2307 						// Import
       
  2308 						case 3:
       
  2309 							addClasses(r.styleSheet);
       
  2310 							break;
       
  2311 					}
       
  2312 				});
       
  2313 			};
       
  2314 
       
  2315 			try {
       
  2316 				each(t.doc.styleSheets, addClasses);
       
  2317 			} catch (ex) {
       
  2318 				// Ignore
       
  2319 			}
       
  2320 
       
  2321 			if (cl.length > 0)
       
  2322 				t.classes = cl;
       
  2323 
       
  2324 			return cl;
       
  2325 		},
       
  2326 
       
  2327 		run : function(e, f, s) {
       
  2328 			var t = this, o;
       
  2329 
       
  2330 			if (t.doc && typeof(e) === 'string')
       
  2331 				e = t.doc.getElementById(e);
       
  2332 
       
  2333 			if (!e)
       
  2334 				return false;
       
  2335 
       
  2336 			s = s || this;
       
  2337 			if (!e.nodeType && (e.length || e.length === 0)) {
       
  2338 				o = [];
       
  2339 
       
  2340 				each(e, function(e, i) {
       
  2341 					if (e) {
       
  2342 						if (typeof(e) == 'string')
       
  2343 							e = t.doc.getElementById(e);
       
  2344 
       
  2345 						o.push(f.call(s, e, i));
       
  2346 					}
       
  2347 				});
       
  2348 
       
  2349 				return o;
       
  2350 			}
       
  2351 
       
  2352 			return f.call(s, e);
       
  2353 		},
       
  2354 
       
  2355 		getAttribs : function(n) {
       
  2356 			var o;
       
  2357 
       
  2358 			n = this.get(n);
       
  2359 
       
  2360 			if (!n)
       
  2361 				return [];
       
  2362 
       
  2363 			if (isIE) {
       
  2364 				o = [];
       
  2365 
       
  2366 				// Object will throw exception in IE
       
  2367 				if (n.nodeName == 'OBJECT')
       
  2368 					return n.attributes;
       
  2369 
       
  2370 				// It's crazy that this is faster in IE but it's because it returns all attributes all the time
       
  2371 				n.cloneNode(false).outerHTML.replace(/([a-z0-9\:\-_]+)=/gi, function(a, b) {
       
  2372 					o.push({specified : 1, nodeName : b});
       
  2373 				});
       
  2374 
       
  2375 				return o;
       
  2376 			}
       
  2377 
       
  2378 			return n.attributes;
       
  2379 		},
       
  2380 
       
  2381 		destroy : function(s) {
       
  2382 			var t = this;
       
  2383 
       
  2384 			t.win = t.doc = t.root = null;
       
  2385 
       
  2386 			// Manual destroy then remove unload handler
       
  2387 			if (!s)
       
  2388 				tinymce.removeUnload(t.destroy);
       
  2389 		},
       
  2390 
       
  2391 		_isRes : function(c) {
       
  2392 			// Is live resizble element
       
  2393 			return /^(top|left|bottom|right|width|height)/i.test(c) || /;\s*(top|left|bottom|right|width|height)/i.test(c);
       
  2394 		}
       
  2395 
       
  2396 		/*
       
  2397 		walk : function(n, f, s) {
       
  2398 			var d = this.doc, w;
       
  2399 
       
  2400 			if (d.createTreeWalker) {
       
  2401 				w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
       
  2402 
       
  2403 				while ((n = w.nextNode()) != null)
       
  2404 					f.call(s || this, n);
       
  2405 			} else
       
  2406 				tinymce.walk(n, f, 'childNodes', s);
       
  2407 		}
       
  2408 		*/
       
  2409 
       
  2410 		/*
       
  2411 		toRGB : function(s) {
       
  2412 			var c = /^\s*?#([0-9A-F]{2})([0-9A-F]{1,2})([0-9A-F]{2})?\s*?$/.exec(s);
       
  2413 
       
  2414 			if (c) {
       
  2415 				// #FFF -> #FFFFFF
       
  2416 				if (!is(c[3]))
       
  2417 					c[3] = c[2] = c[1];
       
  2418 
       
  2419 				return "rgb(" + parseInt(c[1], 16) + "," + parseInt(c[2], 16) + "," + parseInt(c[3], 16) + ")";
       
  2420 			}
       
  2421 
       
  2422 			return s;
       
  2423 		}
       
  2424 		*/
       
  2425 
       
  2426 		});
       
  2427 
       
  2428 	// Setup page DOM
       
  2429 	tinymce.DOM = new tinymce.dom.DOMUtils(document, {process_html : 0});
       
  2430 })();
       
  2431 
       
  2432 /* file:jscripts/tiny_mce/classes/dom/Event.js */
       
  2433 
       
  2434 (function() {
       
  2435 	// Shorten names
       
  2436 	var each = tinymce.each, DOM = tinymce.DOM, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, Event;
       
  2437 
       
  2438 	tinymce.create('static tinymce.dom.Event', {
       
  2439 		inits : [],
       
  2440 		events : [],
       
  2441 
       
  2442 		// #if !jquery
       
  2443 
       
  2444 		add : function(o, n, f, s) {
       
  2445 			var cb, t = this, el = t.events, r;
       
  2446 
       
  2447 			// Handle array
       
  2448 			if (o && o instanceof Array) {
       
  2449 				r = [];
       
  2450 
       
  2451 				each(o, function(o) {
       
  2452 					o = DOM.get(o);
       
  2453 					r.push(t.add(o, n, f, s));
       
  2454 				});
       
  2455 
       
  2456 				return r;
       
  2457 			}
       
  2458 
       
  2459 			o = DOM.get(o);
       
  2460 
       
  2461 			if (!o)
       
  2462 				return;
       
  2463 
       
  2464 			// Setup event callback
       
  2465 			cb = function(e) {
       
  2466 				e = e || window.event;
       
  2467 
       
  2468 				// Patch in target in IE it's W3C valid
       
  2469 				if (e && !e.target && isIE)
       
  2470 					e.target = e.srcElement;
       
  2471 
       
  2472 				if (!s)
       
  2473 					return f(e);
       
  2474 
       
  2475 				return f.call(s, e);
       
  2476 			};
       
  2477 
       
  2478 			if (n == 'unload') {
       
  2479 				tinymce.unloads.unshift({func : cb});
       
  2480 				return cb;
       
  2481 			}
       
  2482 
       
  2483 			if (n == 'init') {
       
  2484 				if (t.domLoaded)
       
  2485 					cb();
       
  2486 				else
       
  2487 					t.inits.push(cb);
       
  2488 
       
  2489 				return cb;
       
  2490 			}
       
  2491 
       
  2492 			// Store away listener reference
       
  2493 			el.push({
       
  2494 				obj : o,
       
  2495 				name : n,
       
  2496 				func : f,
       
  2497 				cfunc : cb,
       
  2498 				scope : s
       
  2499 			});
       
  2500 
       
  2501 			t._add(o, n, cb);
       
  2502 
       
  2503 			return f;
       
  2504 		},
       
  2505 
       
  2506 		remove : function(o, n, f) {
       
  2507 			var t = this, a = t.events, s = false, r;
       
  2508 
       
  2509 			// Handle array
       
  2510 			if (o && o instanceof Array) {
       
  2511 				r = [];
       
  2512 
       
  2513 				each(o, function(o) {
       
  2514 					o = DOM.get(o);
       
  2515 					r.push(t.remove(o, n, f));
       
  2516 				});
       
  2517 
       
  2518 				return r;
       
  2519 			}
       
  2520 
       
  2521 			o = DOM.get(o);
       
  2522 
       
  2523 			each(a, function(e, i) {
       
  2524 				if (e.obj == o && e.name == n && (!f || (e.func == f || e.cfunc == f))) {
       
  2525 					a.splice(i, 1);
       
  2526 					t._remove(o, n, e.cfunc);
       
  2527 					s = true;
       
  2528 					return false;
       
  2529 				}
       
  2530 			});
       
  2531 
       
  2532 			return s;
       
  2533 		},
       
  2534 
       
  2535 		clear : function(o) {
       
  2536 			var t = this, a = t.events, i, e;
       
  2537 
       
  2538 			if (o) {
       
  2539 				o = DOM.get(o);
       
  2540 
       
  2541 				for (i = a.length - 1; i >= 0; i--) {
       
  2542 					e = a[i];
       
  2543 
       
  2544 					if (e.obj === o) {
       
  2545 						t._remove(e.obj, e.name, e.cfunc);
       
  2546 						e.obj = e.cfunc = null;
       
  2547 						a.splice(i, 1);
       
  2548 					}
       
  2549 				}
       
  2550 			}
       
  2551 		},
       
  2552 
       
  2553 		// #endif
       
  2554 
       
  2555 		cancel : function(e) {
       
  2556 			if (!e)
       
  2557 				return false;
       
  2558 
       
  2559 			this.stop(e);
       
  2560 			return this.prevent(e);
       
  2561 		},
       
  2562 
       
  2563 		stop : function(e) {
       
  2564 			if (e.stopPropagation)
       
  2565 				e.stopPropagation();
       
  2566 			else
       
  2567 				e.cancelBubble = true;
       
  2568 
       
  2569 			return false;
       
  2570 		},
       
  2571 
       
  2572 		prevent : function(e) {
       
  2573 			if (e.preventDefault)
       
  2574 				e.preventDefault();
       
  2575 			else
       
  2576 				e.returnValue = false;
       
  2577 
       
  2578 			return false;
       
  2579 		},
       
  2580 
       
  2581 		_unload : function() {
       
  2582 			var t = Event;
       
  2583 
       
  2584 			each(t.events, function(e, i) {
       
  2585 				t._remove(e.obj, e.name, e.cfunc);
       
  2586 				e.obj = e.cfunc = null;
       
  2587 			});
       
  2588 
       
  2589 			t.events = [];
       
  2590 			t = null;
       
  2591 		},
       
  2592 
       
  2593 		_add : function(o, n, f) {
       
  2594 			if (o.attachEvent)
       
  2595 				o.attachEvent('on' + n, f);
       
  2596 			else if (o.addEventListener)
       
  2597 				o.addEventListener(n, f, false);
       
  2598 			else
       
  2599 				o['on' + n] = f;
       
  2600 		},
       
  2601 
       
  2602 		_remove : function(o, n, f) {
       
  2603 			if (o) {
       
  2604 				try {
       
  2605 					if (o.detachEvent)
       
  2606 						o.detachEvent('on' + n, f);
       
  2607 					else if (o.removeEventListener)
       
  2608 						o.removeEventListener(n, f, false);
       
  2609 					else
       
  2610 						o['on' + n] = null;
       
  2611 				} catch (ex) {
       
  2612 					// Might fail with permission denined on IE so we just ignore that
       
  2613 				}
       
  2614 			}
       
  2615 		},
       
  2616 
       
  2617 		_pageInit : function() {
       
  2618 			var e = Event;
       
  2619 
       
  2620 			e._remove(window, 'DOMContentLoaded', e._pageInit);
       
  2621 			e.domLoaded = true;
       
  2622 
       
  2623 			each(e.inits, function(c) {
       
  2624 				c();
       
  2625 			});
       
  2626 
       
  2627 			e.inits = [];
       
  2628 		},
       
  2629 
       
  2630 		_wait : function() {
       
  2631 			var t;
       
  2632 
       
  2633 			// No need since the document is already loaded
       
  2634 			if (window.tinyMCE_GZ && tinyMCE_GZ.loaded) {
       
  2635 				Event.domLoaded = 1;
       
  2636 				return;
       
  2637 			}
       
  2638 
       
  2639 			if (isIE && document.location.protocol != 'https:') {
       
  2640 				// Fake DOMContentLoaded on IE
       
  2641 				document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');
       
  2642 				DOM.get("__ie_onload").onreadystatechange = function() {
       
  2643 					if (this.readyState == "complete") {
       
  2644 						Event._pageInit();
       
  2645 						DOM.get("__ie_onload").onreadystatechange = null; // Prevent leak
       
  2646 					}
       
  2647 				};
       
  2648 			} else {
       
  2649 				Event._add(window, 'DOMContentLoaded', Event._pageInit, Event);
       
  2650 
       
  2651 				if (isIE || isWebKit) {
       
  2652 					t = setInterval(function() {
       
  2653 						if (/loaded|complete/.test(document.readyState)) {
       
  2654 							clearInterval(t);
       
  2655 							Event._pageInit();
       
  2656 						}
       
  2657 					}, 10);
       
  2658 				}
       
  2659 			}
       
  2660 		}
       
  2661 
       
  2662 		});
       
  2663 
       
  2664 	// Shorten name
       
  2665 	Event = tinymce.dom.Event;
       
  2666 
       
  2667 	// Dispatch DOM content loaded event for IE and Safari
       
  2668 	Event._wait();
       
  2669 	tinymce.addUnload(Event._unload);
       
  2670 })();
       
  2671 
       
  2672 /* file:jscripts/tiny_mce/classes/dom/Element.js */
       
  2673 
       
  2674 (function() {
       
  2675 	var each = tinymce.each;
       
  2676 
       
  2677 	tinymce.create('tinymce.dom.Element', {
       
  2678 		Element : function(id, s) {
       
  2679 			var t = this, dom, el;
       
  2680 
       
  2681 			s = s || {};
       
  2682 			t.id = id;
       
  2683 			t.dom = dom = s.dom || tinymce.DOM;
       
  2684 			t.settings = s;
       
  2685 
       
  2686 			// Only IE leaks DOM references, this is a lot faster
       
  2687 			if (!tinymce.isIE)
       
  2688 				el = t.dom.get(t.id);
       
  2689 
       
  2690 			each([
       
  2691 				'getPos',
       
  2692 				'getRect',
       
  2693 				'getParent',
       
  2694 				'add',
       
  2695 				'setStyle',
       
  2696 				'getStyle',
       
  2697 				'setStyles',
       
  2698 				'setAttrib',
       
  2699 				'setAttribs',
       
  2700 				'getAttrib',
       
  2701 				'addClass',
       
  2702 				'removeClass',
       
  2703 				'hasClass',
       
  2704 				'getOuterHTML',
       
  2705 				'setOuterHTML',
       
  2706 				'remove',
       
  2707 				'show',
       
  2708 				'hide',
       
  2709 				'isHidden',
       
  2710 				'setHTML',
       
  2711 				'get'
       
  2712 			], function(k) {
       
  2713 				t[k] = function() {
       
  2714 					var a = arguments, o;
       
  2715 
       
  2716 					// Opera fails
       
  2717 					if (tinymce.isOpera) {
       
  2718 						a = [id];
       
  2719 
       
  2720 						each(arguments, function(v) {
       
  2721 							a.push(v);
       
  2722 						});
       
  2723 					} else
       
  2724 						Array.prototype.unshift.call(a, el || id);
       
  2725 
       
  2726 					o = dom[k].apply(dom, a);
       
  2727 					t.update(k);
       
  2728 
       
  2729 					return o;
       
  2730 				};
       
  2731 			});
       
  2732 		},
       
  2733 
       
  2734 		on : function(n, f, s) {
       
  2735 			return tinymce.dom.Event.add(this.id, n, f, s);
       
  2736 		},
       
  2737 
       
  2738 		getXY : function() {
       
  2739 			return {
       
  2740 				x : parseInt(this.getStyle('left')),
       
  2741 				y : parseInt(this.getStyle('top'))
       
  2742 			};
       
  2743 		},
       
  2744 
       
  2745 		getSize : function() {
       
  2746 			var n = this.dom.get(this.id);
       
  2747 
       
  2748 			return {
       
  2749 				w : parseInt(this.getStyle('width') || n.clientWidth),
       
  2750 				h : parseInt(this.getStyle('height') || n.clientHeight)
       
  2751 			};
       
  2752 		},
       
  2753 
       
  2754 		moveTo : function(x, y) {
       
  2755 			this.setStyles({left : x, top : y});
       
  2756 		},
       
  2757 
       
  2758 		moveBy : function(x, y) {
       
  2759 			var p = this.getXY();
       
  2760 
       
  2761 			this.moveTo(p.x + x, p.y + y);
       
  2762 		},
       
  2763 
       
  2764 		resizeTo : function(w, h) {
       
  2765 			this.setStyles({width : w, height : h});
       
  2766 		},
       
  2767 
       
  2768 		resizeBy : function(w, h) {
       
  2769 			var s = this.getSize();
       
  2770 
       
  2771 			this.resizeTo(s.w + w, s.h + h);
       
  2772 		},
       
  2773 
       
  2774 		update : function(k) {
       
  2775 			var t = this, b, dom = t.dom;
       
  2776 
       
  2777 			if (tinymce.isIE6 && t.settings.blocker) {
       
  2778 				k = k || '';
       
  2779 
       
  2780 				// Ignore getters
       
  2781 				if (k.indexOf('get') === 0 || k.indexOf('has') === 0 || k.indexOf('is') === 0)
       
  2782 					return;
       
  2783 
       
  2784 				// Remove blocker on remove
       
  2785 				if (k == 'remove') {
       
  2786 					dom.remove(t.blocker);
       
  2787 					return;
       
  2788 				}
       
  2789 
       
  2790 				if (!t.blocker) {
       
  2791 					t.blocker = dom.uniqueId();
       
  2792 					b = dom.add(t.settings.container || dom.getRoot(), 'iframe', {id : t.blocker, style : 'position:absolute;', frameBorder : 0, src : 'javascript:""'});
       
  2793 					dom.setStyle(b, 'opacity', 0);
       
  2794 				} else
       
  2795 					b = dom.get(t.blocker);
       
  2796 
       
  2797 				dom.setStyle(b, 'left', t.getStyle('left', 1));
       
  2798 				dom.setStyle(b, 'top', t.getStyle('top', 1));
       
  2799 				dom.setStyle(b, 'width', t.getStyle('width', 1));
       
  2800 				dom.setStyle(b, 'height', t.getStyle('height', 1));
       
  2801 				dom.setStyle(b, 'display', t.getStyle('display', 1));
       
  2802 				dom.setStyle(b, 'zIndex', parseInt(t.getStyle('zIndex', 1) || 0) - 1);
       
  2803 			}
       
  2804 		}
       
  2805 
       
  2806 		});
       
  2807 })();
       
  2808 
       
  2809 /* file:jscripts/tiny_mce/classes/dom/Selection.js */
       
  2810 
       
  2811 (function() {
       
  2812 	function trimNl(s) {
       
  2813 		return s.replace(/[\n\r]+/g, '');
       
  2814 	};
       
  2815 
       
  2816 	// Shorten names
       
  2817 	var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each;
       
  2818 
       
  2819 	tinymce.create('tinymce.dom.Selection', {
       
  2820 		Selection : function(dom, win, serializer) {
       
  2821 			var t = this;
       
  2822 
       
  2823 			t.dom = dom;
       
  2824 			t.win = win;
       
  2825 			t.serializer = serializer;
       
  2826 
       
  2827 			// Prevent leaks
       
  2828 			tinymce.addUnload(t.destroy, t);
       
  2829 		},
       
  2830 
       
  2831 		getContent : function(s) {
       
  2832 			var t = this, r = t.getRng(), e = t.dom.create("body"), se = t.getSel(), wb, wa, n;
       
  2833 
       
  2834 			s = s || {};
       
  2835 			wb = wa = '';
       
  2836 			s.get = true;
       
  2837 			s.format = s.format || 'html';
       
  2838 
       
  2839 			if (s.format == 'text')
       
  2840 				return t.isCollapsed() ? '' : (r.text || (se.toString ? se.toString() : ''));
       
  2841 
       
  2842 			if (r.cloneContents) {
       
  2843 				n = r.cloneContents();
       
  2844 
       
  2845 				if (n)
       
  2846 					e.appendChild(n);
       
  2847 			} else if (is(r.item) || is(r.htmlText))
       
  2848 				e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;
       
  2849 			else
       
  2850 				e.innerHTML = r.toString();
       
  2851 
       
  2852 			// Keep whitespace before and after
       
  2853 			if (/^\s/.test(e.innerHTML))
       
  2854 				wb = ' ';
       
  2855 
       
  2856 			if (/\s+$/.test(e.innerHTML))
       
  2857 				wa = ' ';
       
  2858 
       
  2859 			s.getInner = true;
       
  2860 
       
  2861 			return t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa;
       
  2862 		},
       
  2863 
       
  2864 		setContent : function(h, s) {
       
  2865 			var t = this, r = t.getRng(), c, d = t.win.document;
       
  2866 
       
  2867 			s = s || {format : 'html'};
       
  2868 			s.set = true;
       
  2869 			h = t.dom.processHTML(h);
       
  2870 
       
  2871 			if (r.insertNode) {
       
  2872 				// Make caret marker since insertNode places the caret in the beginning of text after insert
       
  2873 				h += '<span id="__caret">_</span>';
       
  2874 
       
  2875 				// Delete and insert new node
       
  2876 				r.deleteContents();
       
  2877 				r.insertNode(t.getRng().createContextualFragment(h));
       
  2878 
       
  2879 				// Move to caret marker
       
  2880 				c = t.dom.get('__caret');
       
  2881 
       
  2882 				// Make sure we wrap it compleatly, Opera fails with a simple select call
       
  2883 				r = d.createRange();
       
  2884 				r.setStartBefore(c);
       
  2885 				r.setEndAfter(c);
       
  2886 				t.setRng(r);
       
  2887 
       
  2888 				// Delete the marker, and hopefully the caret gets placed in the right location
       
  2889 				d.execCommand('Delete', false, null);
       
  2890 
       
  2891 				// In case it's still there
       
  2892 				t.dom.remove('__caret');
       
  2893 			} else {
       
  2894 				if (r.item) {
       
  2895 					// Delete content and get caret text selection
       
  2896 					d.execCommand('Delete', false, null);
       
  2897 					r = t.getRng();
       
  2898 				}
       
  2899 
       
  2900 				r.pasteHTML(h);
       
  2901 			}
       
  2902 		},
       
  2903 
       
  2904 		getStart : function() {
       
  2905 			var t = this, r = t.getRng(), e;
       
  2906 
       
  2907 			if (isIE) {
       
  2908 				if (r.item)
       
  2909 					return r.item(0);
       
  2910 
       
  2911 				r = r.duplicate();
       
  2912 				r.collapse(1);
       
  2913 				e = r.parentElement();
       
  2914 
       
  2915 				if (e && e.nodeName == 'BODY')
       
  2916 					return e.firstChild;
       
  2917 
       
  2918 				return e;
       
  2919 			} else {
       
  2920 				e = r.startContainer;
       
  2921 
       
  2922 				if (e.nodeName == 'BODY')
       
  2923 					return e.firstChild;
       
  2924 
       
  2925 				return t.dom.getParent(e, function(n) {return n.nodeType == 1;});
       
  2926 			}
       
  2927 		},
       
  2928 
       
  2929 		getEnd : function() {
       
  2930 			var t = this, r = t.getRng(), e;
       
  2931 
       
  2932 			if (isIE) {
       
  2933 				if (r.item)
       
  2934 					return r.item(0);
       
  2935 
       
  2936 				r = r.duplicate();
       
  2937 				r.collapse(0);
       
  2938 				e = r.parentElement();
       
  2939 
       
  2940 				if (e && e.nodeName == 'BODY')
       
  2941 					return e.lastChild;
       
  2942 
       
  2943 				return e;
       
  2944 			} else {
       
  2945 				e = r.endContainer;
       
  2946 
       
  2947 				if (e.nodeName == 'BODY')
       
  2948 					return e.lastChild;
       
  2949 
       
  2950 				return t.dom.getParent(e, function(n) {return n.nodeType == 1;});
       
  2951 			}
       
  2952 		},
       
  2953 
       
  2954 		getBookmark : function(si) {
       
  2955 			var t = this, r = t.getRng(), tr, sx, sy, vp = t.dom.getViewPort(t.win), e, sp, bp, le, c = -0xFFFFFF, s, ro = t.dom.getRoot(), wb = 0, wa = 0, nv;
       
  2956 			sx = vp.x;
       
  2957 			sy = vp.y;
       
  2958 
       
  2959 			// Simple bookmark fast but not as persistent
       
  2960 			if (si == 'simple')
       
  2961 				return {rng : r, scrollX : sx, scrollY : sy};
       
  2962 
       
  2963 			// Handle IE
       
  2964 			if (isIE) {
       
  2965 				// Control selection
       
  2966 				if (r.item) {
       
  2967 					e = r.item(0);
       
  2968 
       
  2969 					each(t.dom.select(e.nodeName), function(n, i) {
       
  2970 						if (e == n) {
       
  2971 							sp = i;
       
  2972 							return false;
       
  2973 						}
       
  2974 					});
       
  2975 
       
  2976 					return {
       
  2977 						tag : e.nodeName,
       
  2978 						index : sp,
       
  2979 						scrollX : sx,
       
  2980 						scrollY : sy
       
  2981 					};
       
  2982 				}
       
  2983 
       
  2984 				// Text selection
       
  2985 				tr = t.dom.doc.body.createTextRange();
       
  2986 				tr.moveToElementText(ro);
       
  2987 				tr.collapse(true);
       
  2988 				bp = Math.abs(tr.move('character', c));
       
  2989 
       
  2990 				tr = r.duplicate();
       
  2991 				tr.collapse(true);
       
  2992 				sp = Math.abs(tr.move('character', c));
       
  2993 
       
  2994 				tr = r.duplicate();
       
  2995 				tr.collapse(false);
       
  2996 				le = Math.abs(tr.move('character', c)) - sp;
       
  2997 
       
  2998 				return {
       
  2999 					start : sp - bp,
       
  3000 					length : le,
       
  3001 					scrollX : sx,
       
  3002 					scrollY : sy
       
  3003 				};
       
  3004 			}
       
  3005 
       
  3006 			// Handle W3C
       
  3007 			e = t.getNode();
       
  3008 			s = t.getSel();
       
  3009 
       
  3010 			if (!s)
       
  3011 				return null;
       
  3012 
       
  3013 			// Image selection
       
  3014 			if (e && e.nodeName == 'IMG') {
       
  3015 				return {
       
  3016 					scrollX : sx,
       
  3017 					scrollY : sy
       
  3018 				};
       
  3019 			}
       
  3020 
       
  3021 			// Text selection
       
  3022 
       
  3023 			function getPos(r, sn, en) {
       
  3024 				var w = t.dom.doc.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
       
  3025 
       
  3026 				while ((n = w.nextNode()) != null) {
       
  3027 					if (n == sn)
       
  3028 						d.start = p;
       
  3029 
       
  3030 					if (n == en) {
       
  3031 						d.end = p;
       
  3032 						return d;
       
  3033 					}
       
  3034 
       
  3035 					p += trimNl(n.nodeValue || '').length;
       
  3036 				}
       
  3037 
       
  3038 				return null;
       
  3039 			};
       
  3040 
       
  3041 			// Caret or selection
       
  3042 			if (s.anchorNode == s.focusNode && s.anchorOffset == s.focusOffset) {
       
  3043 				e = getPos(ro, s.anchorNode, s.focusNode);
       
  3044 
       
  3045 				if (!e)
       
  3046 					return {scrollX : sx, scrollY : sy};
       
  3047 
       
  3048 				// Count whitespace before
       
  3049 				trimNl(s.anchorNode.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});
       
  3050 
       
  3051 				return {
       
  3052 					start : Math.max(e.start + s.anchorOffset - wb, 0),
       
  3053 					end : Math.max(e.end + s.focusOffset - wb, 0),
       
  3054 					scrollX : sx,
       
  3055 					scrollY : sy,
       
  3056 					beg : s.anchorOffset - wb == 0
       
  3057 				};
       
  3058 			} else {
       
  3059 				e = getPos(ro, r.startContainer, r.endContainer);
       
  3060 
       
  3061 				// Count whitespace before start and end container
       
  3062 				//(r.startContainer.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});
       
  3063 				//(r.endContainer.nodeValue || '').replace(/^\s+/, function(a) {wa = a.length;});
       
  3064 
       
  3065 				if (!e)
       
  3066 					return {scrollX : sx, scrollY : sy};
       
  3067 
       
  3068 				return {
       
  3069 					start : Math.max(e.start + r.startOffset - wb, 0),
       
  3070 					end : Math.max(e.end + r.endOffset - wa, 0),
       
  3071 					scrollX : sx,
       
  3072 					scrollY : sy,
       
  3073 					beg : r.startOffset - wb == 0
       
  3074 				};
       
  3075 			}
       
  3076 		},
       
  3077 
       
  3078 		moveToBookmark : function(b) {
       
  3079 			var t = this, r = t.getRng(), s = t.getSel(), ro = t.dom.getRoot(), sd, nvl, nv;
       
  3080 
       
  3081 			function getPos(r, sp, ep) {
       
  3082 				var w = t.dom.doc.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {}, o, v, wa, wb;
       
  3083 
       
  3084 				while ((n = w.nextNode()) != null) {
       
  3085 					wa = wb = 0;
       
  3086 
       
  3087 					nv = n.nodeValue || '';
       
  3088 					//nv.replace(/^\s+[^\s]/, function(a) {wb = a.length - 1;});
       
  3089 					//nv.replace(/[^\s]\s+$/, function(a) {wa = a.length - 1;});
       
  3090 
       
  3091 					nvl = trimNl(nv).length;
       
  3092 					p += nvl;
       
  3093 
       
  3094 					if (p >= sp && !d.startNode) {
       
  3095 						o = sp - (p - nvl);
       
  3096 
       
  3097 						// Fix for odd quirk in FF
       
  3098 						if (b.beg && o >= nvl)
       
  3099 							continue;
       
  3100 
       
  3101 						d.startNode = n;
       
  3102 						d.startOffset = o + wb;
       
  3103 					}
       
  3104 
       
  3105 					if (p >= ep) {
       
  3106 						d.endNode = n;
       
  3107 						d.endOffset = ep - (p - nvl) + wb;
       
  3108 						return d;
       
  3109 					}
       
  3110 				}
       
  3111 
       
  3112 				return null;
       
  3113 			};
       
  3114 
       
  3115 			if (!b)
       
  3116 				return false;
       
  3117 
       
  3118 			t.win.scrollTo(b.scrollX, b.scrollY);
       
  3119 
       
  3120 			// Handle explorer
       
  3121 			if (isIE) {
       
  3122 				// Handle simple
       
  3123 				if (r = b.rng) {
       
  3124 					try {
       
  3125 						r.select();
       
  3126 					} catch (ex) {
       
  3127 						// Ignore
       
  3128 					}
       
  3129 
       
  3130 					return true;
       
  3131 				}
       
  3132 
       
  3133 				t.win.focus();
       
  3134 
       
  3135 				// Handle control bookmark
       
  3136 				if (b.tag) {
       
  3137 					r = ro.createControlRange();
       
  3138 
       
  3139 					each(t.dom.select(b.tag), function(n, i) {
       
  3140 						if (i == b.index)
       
  3141 							r.addElement(n);
       
  3142 					});
       
  3143 				} else {
       
  3144 					// Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs
       
  3145 					try {
       
  3146 						// Incorrect bookmark
       
  3147 						if (b.start < 0)
       
  3148 							return true;
       
  3149 
       
  3150 						r = s.createRange();
       
  3151 						r.moveToElementText(ro);
       
  3152 						r.collapse(true);
       
  3153 						r.moveStart('character', b.start);
       
  3154 						r.moveEnd('character', b.length);
       
  3155 					} catch (ex2) {
       
  3156 						return true;
       
  3157 					}
       
  3158 				}
       
  3159 
       
  3160 				try {
       
  3161 					r.select();
       
  3162 				} catch (ex) {
       
  3163 					// Needed for some odd IE bug #1843306
       
  3164 				}
       
  3165 
       
  3166 				return true;
       
  3167 			}
       
  3168 
       
  3169 			// Handle W3C
       
  3170 			if (!s)
       
  3171 				return false;
       
  3172 
       
  3173 			// Handle simple
       
  3174 			if (b.rng) {
       
  3175 				s.removeAllRanges();
       
  3176 				s.addRange(b.rng);
       
  3177 			} else {
       
  3178 				if (is(b.start) && is(b.end)) {
       
  3179 					try {
       
  3180 						sd = getPos(ro, b.start, b.end);
       
  3181 
       
  3182 						if (sd) {
       
  3183 							r = t.dom.doc.createRange();
       
  3184 							r.setStart(sd.startNode, sd.startOffset);
       
  3185 							r.setEnd(sd.endNode, sd.endOffset);
       
  3186 							s.removeAllRanges();
       
  3187 							s.addRange(r);
       
  3188 						}
       
  3189 
       
  3190 						if (!tinymce.isOpera)
       
  3191 							t.win.focus();
       
  3192 					} catch (ex) {
       
  3193 						// Ignore
       
  3194 					}
       
  3195 				}
       
  3196 			}
       
  3197 		},
       
  3198 
       
  3199 		select : function(n, c) {
       
  3200 			var t = this, r = t.getRng(), s = t.getSel(), b, fn, ln, d = t.win.document;
       
  3201 
       
  3202 			function first(n) {
       
  3203 				return n ? d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() : null;
       
  3204 			};
       
  3205 
       
  3206 			function last(n) {
       
  3207 				var c, o, w;
       
  3208 
       
  3209 				if (!n)
       
  3210 					return null;
       
  3211 
       
  3212 				w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
       
  3213 				while (c = w.nextNode())
       
  3214 					o = c;
       
  3215 
       
  3216 				return o;
       
  3217 			};
       
  3218 
       
  3219 			if (isIE) {
       
  3220 				try {
       
  3221 					b = d.body;
       
  3222 
       
  3223 					if (/^(IMG|TABLE)$/.test(n.nodeName)) {
       
  3224 						r = b.createControlRange();
       
  3225 						r.addElement(n);
       
  3226 					} else {
       
  3227 						r = b.createTextRange();
       
  3228 						r.moveToElementText(n);
       
  3229 					}
       
  3230 
       
  3231 					r.select();
       
  3232 				} catch (ex) {
       
  3233 					// Throws illigal agrument in IE some times
       
  3234 				}
       
  3235 			} else {
       
  3236 				if (c) {
       
  3237 					fn = first(n);
       
  3238 					ln = last(n);
       
  3239 
       
  3240 					if (fn && ln) {
       
  3241 						//console.debug(fn, ln);
       
  3242 						r = d.createRange();
       
  3243 						r.setStart(fn, 0);
       
  3244 						r.setEnd(ln, ln.nodeValue.length);
       
  3245 					} else
       
  3246 						r.selectNode(n);
       
  3247 				} else
       
  3248 					r.selectNode(n);
       
  3249 
       
  3250 				t.setRng(r);
       
  3251 			}
       
  3252 
       
  3253 			return n;
       
  3254 		},
       
  3255 
       
  3256 		isCollapsed : function() {
       
  3257 			var t = this, r = t.getRng(), s = t.getSel();
       
  3258 
       
  3259 			if (!r || r.item)
       
  3260 				return false;
       
  3261 
       
  3262 			return !s || r.boundingWidth == 0 || r.collapsed;
       
  3263 		},
       
  3264 
       
  3265 		collapse : function(b) {
       
  3266 			var t = this, r = t.getRng(), n;
       
  3267 
       
  3268 			// Control range on IE
       
  3269 			if (r.item) {
       
  3270 				n = r.item(0);
       
  3271 				r = this.win.document.body.createTextRange();
       
  3272 				r.moveToElementText(n);
       
  3273 			}
       
  3274 
       
  3275 			r.collapse(!!b);
       
  3276 			t.setRng(r);
       
  3277 		},
       
  3278 
       
  3279 		getSel : function() {
       
  3280 			var t = this, w = this.win;
       
  3281 
       
  3282 			return w.getSelection ? w.getSelection() : w.document.selection;
       
  3283 		},
       
  3284 
       
  3285 		getRng : function() {
       
  3286 			var t = this, s = t.getSel(), r;
       
  3287 
       
  3288 			try {
       
  3289 				if (s)
       
  3290 					r = s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : t.win.document.createRange());
       
  3291 			} catch (ex) {
       
  3292 				// IE throws unspecified error here if TinyMCE is placed in a frame/iframe
       
  3293 			}
       
  3294 
       
  3295 			// No range found then create an empty one
       
  3296 			// This can occur when the editor is placed in a hidden container element on Gecko
       
  3297 			// Or on IE when there was an exception
       
  3298 			if (!r)
       
  3299 				r = isIE ? t.win.document.body.createTextRange() : t.win.document.createRange();
       
  3300 
       
  3301 			return r;
       
  3302 		},
       
  3303 
       
  3304 		setRng : function(r) {
       
  3305 			var s;
       
  3306 
       
  3307 			if (!isIE) {
       
  3308 				s = this.getSel();
       
  3309 
       
  3310 				if (s) {
       
  3311 					s.removeAllRanges();
       
  3312 					s.addRange(r);
       
  3313 				}
       
  3314 			} else {
       
  3315 				try {
       
  3316 					r.select();
       
  3317 				} catch (ex) {
       
  3318 					// Needed for some odd IE bug #1843306
       
  3319 				}
       
  3320 			}
       
  3321 		},
       
  3322 
       
  3323 		setNode : function(n) {
       
  3324 			var t = this;
       
  3325 
       
  3326 			t.setContent(t.dom.getOuterHTML(n));
       
  3327 
       
  3328 			return n;
       
  3329 		},
       
  3330 
       
  3331 		getNode : function() {
       
  3332 			var t = this, r = t.getRng(), s = t.getSel(), e;
       
  3333 
       
  3334 			if (!isIE) {
       
  3335 				// Range maybe lost after the editor is made visible again
       
  3336 				if (!r)
       
  3337 					return t.dom.getRoot();
       
  3338 
       
  3339 				e = r.commonAncestorContainer;
       
  3340 
       
  3341 				// Handle selection a image or other control like element such as anchors
       
  3342 				if (!r.collapsed) {
       
  3343 					// If the anchor node is a element instead of a text node then return this element
       
  3344 					if (tinymce.isWebKit && s.anchorNode && s.anchorNode.nodeType == 1) 
       
  3345 						return s.anchorNode.childNodes[s.anchorOffset]; 
       
  3346 
       
  3347 					if (r.startContainer == r.endContainer) {
       
  3348 						if (r.startOffset - r.endOffset < 2) {
       
  3349 							if (r.startContainer.hasChildNodes())
       
  3350 								e = r.startContainer.childNodes[r.startOffset];
       
  3351 						}
       
  3352 					}
       
  3353 				}
       
  3354 
       
  3355 				return t.dom.getParent(e, function(n) {
       
  3356 					return n.nodeType == 1;
       
  3357 				});
       
  3358 			}
       
  3359 
       
  3360 			return r.item ? r.item(0) : r.parentElement();
       
  3361 		},
       
  3362 
       
  3363 		destroy : function(s) {
       
  3364 			var t = this;
       
  3365 
       
  3366 			t.win = null;
       
  3367 
       
  3368 			// Manual destroy then remove unload handler
       
  3369 			if (!s)
       
  3370 				tinymce.removeUnload(t.destroy);
       
  3371 		}
       
  3372 
       
  3373 		});
       
  3374 })();
       
  3375 
       
  3376 /* file:jscripts/tiny_mce/classes/dom/XMLWriter.js */
       
  3377 
       
  3378 (function() {
       
  3379 	tinymce.create('tinymce.dom.XMLWriter', {
       
  3380 		node : null,
       
  3381 
       
  3382 		XMLWriter : function(s) {
       
  3383 			// Get XML document
       
  3384 			function getXML() {
       
  3385 				var i = document.implementation;
       
  3386 
       
  3387 				if (!i || !i.createDocument) {
       
  3388 					// Try IE objects
       
  3389 					try {return new ActiveXObject('MSXML2.DOMDocument');} catch (ex) {}
       
  3390 					try {return new ActiveXObject('Microsoft.XmlDom');} catch (ex) {}
       
  3391 				} else
       
  3392 					return i.createDocument('', '', null);
       
  3393 			};
       
  3394 
       
  3395 			this.doc = getXML();
       
  3396 			
       
  3397 			// Since Opera and WebKit doesn't escape > into &gt; we need to do it our self to normalize the output for all browsers
       
  3398 			this.valid = tinymce.isOpera || tinymce.isWebKit;
       
  3399 
       
  3400 			this.reset();
       
  3401 		},
       
  3402 
       
  3403 		reset : function() {
       
  3404 			var t = this, d = t.doc;
       
  3405 
       
  3406 			if (d.firstChild)
       
  3407 				d.removeChild(d.firstChild);
       
  3408 
       
  3409 			t.node = d.appendChild(d.createElement("html"));
       
  3410 		},
       
  3411 
       
  3412 		writeStartElement : function(n) {
       
  3413 			var t = this;
       
  3414 
       
  3415 			t.node = t.node.appendChild(t.doc.createElement(n));
       
  3416 		},
       
  3417 
       
  3418 		writeAttribute : function(n, v) {
       
  3419 			if (this.valid)
       
  3420 				v = v.replace(/>/g, '%MCGT%');
       
  3421 
       
  3422 			this.node.setAttribute(n, v);
       
  3423 		},
       
  3424 
       
  3425 		writeEndElement : function() {
       
  3426 			this.node = this.node.parentNode;
       
  3427 		},
       
  3428 
       
  3429 		writeFullEndElement : function() {
       
  3430 			var t = this, n = t.node;
       
  3431 
       
  3432 			n.appendChild(t.doc.createTextNode(""));
       
  3433 			t.node = n.parentNode;
       
  3434 		},
       
  3435 
       
  3436 		writeText : function(v) {
       
  3437 			if (this.valid)
       
  3438 				v = v.replace(/>/g, '%MCGT%');
       
  3439 
       
  3440 			this.node.appendChild(this.doc.createTextNode(v));
       
  3441 		},
       
  3442 
       
  3443 		writeCDATA : function(v) {
       
  3444 			this.node.appendChild(this.doc.createCDATA(v));
       
  3445 		},
       
  3446 
       
  3447 		writeComment : function(v) {
       
  3448 			this.node.appendChild(this.doc.createComment(v.replace(/\-\-/g, ' ')));
       
  3449 		},
       
  3450 
       
  3451 		getContent : function() {
       
  3452 			var h;
       
  3453 
       
  3454 			h = this.doc.xml || new XMLSerializer().serializeToString(this.doc);
       
  3455 			h = h.replace(/<\?[^?]+\?>|<html>|<\/html>|<html\/>|<!DOCTYPE[^>]+>/g, '');
       
  3456 			h = h.replace(/ ?\/>/g, ' />');
       
  3457 
       
  3458 			if (this.valid)
       
  3459 				h = h.replace(/\%MCGT%/g, '&gt;');
       
  3460 
       
  3461 			return h;
       
  3462 		}
       
  3463 
       
  3464 		});
       
  3465 })();
       
  3466 
       
  3467 /* file:jscripts/tiny_mce/classes/dom/StringWriter.js */
       
  3468 
       
  3469 (function() {
       
  3470 	tinymce.create('tinymce.dom.StringWriter', {
       
  3471 		str : null,
       
  3472 		tags : null,
       
  3473 		count : 0,
       
  3474 		settings : null,
       
  3475 		indent : null,
       
  3476 
       
  3477 		StringWriter : function(s) {
       
  3478 			this.settings = tinymce.extend({
       
  3479 				indent_char : ' ',
       
  3480 				indentation : 1
       
  3481 			}, s);
       
  3482 
       
  3483 			this.reset();
       
  3484 		},
       
  3485 
       
  3486 		reset : function() {
       
  3487 			this.indent = '';
       
  3488 			this.str = "";
       
  3489 			this.tags = [];
       
  3490 			this.count = 0;
       
  3491 		},
       
  3492 
       
  3493 		writeStartElement : function(n) {
       
  3494 			this._writeAttributesEnd();
       
  3495 			this.writeRaw('<' + n);
       
  3496 			this.tags.push(n);
       
  3497 			this.inAttr = true;
       
  3498 			this.count++;
       
  3499 			this.elementCount = this.count;
       
  3500 		},
       
  3501 
       
  3502 		writeAttribute : function(n, v) {
       
  3503 			var t = this;
       
  3504 
       
  3505 			t.writeRaw(" " + t.encode(n) + '="' + t.encode(v) + '"');
       
  3506 		},
       
  3507 
       
  3508 		writeEndElement : function() {
       
  3509 			var n;
       
  3510 
       
  3511 			if (this.tags.length > 0) {
       
  3512 				n = this.tags.pop();
       
  3513 
       
  3514 				if (this._writeAttributesEnd(1))
       
  3515 					this.writeRaw('</' + n + '>');
       
  3516 
       
  3517 				if (this.settings.indentation > 0)
       
  3518 					this.writeRaw('\n');
       
  3519 			}
       
  3520 		},
       
  3521 
       
  3522 		writeFullEndElement : function() {
       
  3523 			if (this.tags.length > 0) {
       
  3524 				this._writeAttributesEnd();
       
  3525 				this.writeRaw('</' + this.tags.pop() + '>');
       
  3526 
       
  3527 				if (this.settings.indentation > 0)
       
  3528 					this.writeRaw('\n');
       
  3529 			}
       
  3530 		},
       
  3531 
       
  3532 		writeText : function(v) {
       
  3533 			this._writeAttributesEnd();
       
  3534 			this.writeRaw(this.encode(v));
       
  3535 			this.count++;
       
  3536 		},
       
  3537 
       
  3538 		writeCDATA : function(v) {
       
  3539 			this._writeAttributesEnd();
       
  3540 			this.writeRaw('<![CDATA[' + v + ']]>');
       
  3541 			this.count++;
       
  3542 		},
       
  3543 
       
  3544 		writeComment : function(v) {
       
  3545 			this._writeAttributesEnd();
       
  3546 			this.writeRaw('<!-- ' + v + '-->');
       
  3547 			this.count++;
       
  3548 		},
       
  3549 
       
  3550 		writeRaw : function(v) {
       
  3551 			this.str += v;
       
  3552 		},
       
  3553 
       
  3554 		encode : function(s) {
       
  3555 			return s.replace(/[<>&"]/g, function(v) {
       
  3556 				switch (v) {
       
  3557 					case '<':
       
  3558 						return '&lt;';
       
  3559 
       
  3560 					case '>':
       
  3561 						return '&gt;';
       
  3562 
       
  3563 					case '&':
       
  3564 						return '&amp;';
       
  3565 
       
  3566 					case '"':
       
  3567 						return '&quot;';
       
  3568 				}
       
  3569 
       
  3570 				return v;
       
  3571 			});
       
  3572 		},
       
  3573 
       
  3574 		getContent : function() {
       
  3575 			return this.str;
       
  3576 		},
       
  3577 
       
  3578 		_writeAttributesEnd : function(s) {
       
  3579 			if (!this.inAttr)
       
  3580 				return;
       
  3581 
       
  3582 			this.inAttr = false;
       
  3583 
       
  3584 			if (s && this.elementCount == this.count) {
       
  3585 				this.writeRaw(' />');
       
  3586 				return false;
       
  3587 			}
       
  3588 
       
  3589 			this.writeRaw('>');
       
  3590 
       
  3591 			return true;
       
  3592 		}
       
  3593 
       
  3594 		});
       
  3595 })();
       
  3596 
       
  3597 /* file:jscripts/tiny_mce/classes/dom/Serializer.js */
       
  3598 
       
  3599 (function() {
       
  3600 	// Shorten names
       
  3601 	var extend = tinymce.extend, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, isIE = tinymce.isIE, isGecko = tinymce.isGecko;
       
  3602 
       
  3603 	// Returns only attribites that have values not all attributes in IE
       
  3604 	function getIEAtts(n) {
       
  3605 		var o = [];
       
  3606 
       
  3607 		// Object will throw exception in IE
       
  3608 		if (n.nodeName == 'OBJECT')
       
  3609 			return n.attributes;
       
  3610 
       
  3611 		n.cloneNode(false).outerHTML.replace(/([a-z0-9\:\-_]+)=/gi, function(a, b) {
       
  3612 			o.push({specified : 1, nodeName : b});
       
  3613 		});
       
  3614 
       
  3615 		return o;
       
  3616 	};
       
  3617 
       
  3618 	function wildcardToRE(s) {
       
  3619 		return s.replace(/([?+*])/g, '.$1');
       
  3620 	};
       
  3621 
       
  3622 	tinymce.create('tinymce.dom.Serializer', {
       
  3623 		Serializer : function(s) {
       
  3624 			var t = this;
       
  3625 
       
  3626 			t.key = 0;
       
  3627 			t.onPreProcess = new Dispatcher(t);
       
  3628 			t.onPostProcess = new Dispatcher(t);
       
  3629 
       
  3630 			if (tinymce.relaxedDomain && tinymce.isGecko) {
       
  3631 				// Gecko has a bug where we can't create a new XML document if domain relaxing is used
       
  3632 				t.writer = new tinymce.dom.StringWriter();
       
  3633 			} else {
       
  3634 				try {
       
  3635 					t.writer = new tinymce.dom.XMLWriter();
       
  3636 				} catch (ex) {
       
  3637 					// IE might throw exception if ActiveX is disabled so we then switch to the slightly slower StringWriter
       
  3638 					t.writer = new tinymce.dom.StringWriter();
       
  3639 				}
       
  3640 			}
       
  3641 
       
  3642 			// Default settings
       
  3643 			t.settings = s = extend({
       
  3644 				dom : tinymce.DOM,
       
  3645 				valid_nodes : 0,
       
  3646 				node_filter : 0,
       
  3647 				attr_filter : 0,
       
  3648 				invalid_attrs : /^(mce_|_moz_)/,
       
  3649 				closed : /(br|hr|input|meta|img|link|param)/,
       
  3650 				entity_encoding : 'named',
       
  3651 				entities : '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,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',
       
  3652 				valid_elements : '*[*]',
       
  3653 				extended_valid_elements : 0,
       
  3654 				valid_child_elements : 0,
       
  3655 				invalid_elements : 0,
       
  3656 				fix_table_elements : 0,
       
  3657 				fix_list_elements : true,
       
  3658 				fix_content_duplication : true,
       
  3659 				convert_fonts_to_spans : false,
       
  3660 				font_size_classes : 0,
       
  3661 				font_size_style_values : 0,
       
  3662 				apply_source_formatting : 0,
       
  3663 				indent_mode : 'simple',
       
  3664 				indent_char : '\t',
       
  3665 				indent_levels : 1,
       
  3666 				remove_linebreaks : 1,
       
  3667 				remove_redundant_brs : 1
       
  3668 			}, s);
       
  3669 
       
  3670 			t.dom = s.dom;
       
  3671 
       
  3672 			if (s.remove_redundant_brs) {
       
  3673 				t.onPostProcess.add(function(se, o) {
       
  3674 					// Remove BR elements at end of list elements since they get rendered in IE
       
  3675 					o.content = o.content.replace(/<br \/>(\s*<\/li>)/g, '$1');
       
  3676 				});
       
  3677 			}
       
  3678 
       
  3679 			if (s.fix_list_elements) {
       
  3680 				t.onPreProcess.add(function(se, o) {
       
  3681 					var nl, x, a = ['ol', 'ul'], i, n, p, r = /^(OL|UL)$/, np;
       
  3682 
       
  3683 					function prevNode(e, n) {
       
  3684 						var a = n.split(','), i;
       
  3685 
       
  3686 						while ((e = e.previousSibling) != null) {
       
  3687 							for (i=0; i<a.length; i++) {
       
  3688 								if (e.nodeName == a[i])
       
  3689 									return e;
       
  3690 							}
       
  3691 						}
       
  3692 
       
  3693 						return null;
       
  3694 					};
       
  3695 
       
  3696 					for (x=0; x<a.length; x++) {
       
  3697 						nl = t.dom.select(a[x], o.node);
       
  3698 
       
  3699 						for (i=0; i<nl.length; i++) {
       
  3700 							n = nl[i];
       
  3701 							p = n.parentNode;
       
  3702 
       
  3703 							if (r.test(p.nodeName)) {
       
  3704 								np = prevNode(n, 'LI');
       
  3705 
       
  3706 								if (!np) {
       
  3707 									np = t.dom.create('li');
       
  3708 									np.innerHTML = '&nbsp;';
       
  3709 									np.appendChild(n);
       
  3710 									p.insertBefore(np, p.firstChild);
       
  3711 								} else
       
  3712 									np.appendChild(n);
       
  3713 							}
       
  3714 						}
       
  3715 					}
       
  3716 				});
       
  3717 			}
       
  3718 
       
  3719 			if (s.fix_table_elements) {
       
  3720 				t.onPreProcess.add(function(se, o) {
       
  3721 					each(t.dom.select('table', o.node), function(e) {
       
  3722 						var pa = t.dom.getParent(e, 'H1,H2,H3,H4,H5,H6,P'), pa2, n, tm, pl = [], i, ns;
       
  3723 
       
  3724 						if (pa) {
       
  3725 							pa2 = pa.cloneNode(false);
       
  3726 
       
  3727 							pl.push(e);
       
  3728 							for (n = e; n = n.parentNode;) {
       
  3729 								pl.push(n);
       
  3730 
       
  3731 								if (n == pa)
       
  3732 									break;
       
  3733 							}
       
  3734 
       
  3735 							tm = pa2;
       
  3736 							for (i = pl.length - 1; i >= 0; i--) {
       
  3737 								if (i == pl.length - 1) {
       
  3738 									while (ns = pl[i - 1].nextSibling)
       
  3739 										tm.appendChild(ns.parentNode.removeChild(ns));
       
  3740 								} else {
       
  3741 									n = pl[i].cloneNode(false);
       
  3742 
       
  3743 									if (i != 0) {
       
  3744 										while (ns = pl[i - 1].nextSibling)
       
  3745 											n.appendChild(ns.parentNode.removeChild(ns));
       
  3746 									}
       
  3747 
       
  3748 									tm = tm.appendChild(n);
       
  3749 								}
       
  3750 							}
       
  3751 
       
  3752 							e = t.dom.insertAfter(e.parentNode.removeChild(e), pa);
       
  3753 							t.dom.insertAfter(e, pa);
       
  3754 							t.dom.insertAfter(pa2, e);
       
  3755 						}
       
  3756 					});
       
  3757 				});
       
  3758 			}
       
  3759 		},
       
  3760 
       
  3761 		setEntities : function(s) {
       
  3762 			var t = this, a, i, l = {}, re = '', v;
       
  3763 
       
  3764 			// No need to setup more than once
       
  3765 			if (t.entityLookup)
       
  3766 				return;
       
  3767 
       
  3768 			// Build regex and lookup array
       
  3769 			a = s.split(',');
       
  3770 			for (i = 0; i < a.length; i += 2) {
       
  3771 				v = a[i];
       
  3772 
       
  3773 				// Don't add default &amp; &quot; etc.
       
  3774 				if (v == 34 || v == 38 || v == 60 || v == 62)
       
  3775 					continue;
       
  3776 
       
  3777 				l[String.fromCharCode(a[i])] = a[i + 1];
       
  3778 
       
  3779 				v = parseInt(a[i]).toString(16);
       
  3780 				re += '\\u' + '0000'.substring(v.length) + v;
       
  3781 			}
       
  3782 
       
  3783 			if (!re) {
       
  3784 				t.settings.entity_encoding = 'raw';
       
  3785 				return;
       
  3786 			}
       
  3787 
       
  3788 			t.entitiesRE = new RegExp('[' + re + ']', 'g');
       
  3789 			t.entityLookup = l;
       
  3790 		},
       
  3791 
       
  3792 		setValidChildRules : function(s) {
       
  3793 			this.childRules = null;
       
  3794 			this.addValidChildRules(s);
       
  3795 		},
       
  3796 
       
  3797 		addValidChildRules : function(s) {
       
  3798 			var t = this, inst, intr, bloc;
       
  3799 
       
  3800 			if (!s)
       
  3801 				return;
       
  3802 
       
  3803 			inst = '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';
       
  3804 			intr = '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';
       
  3805 			bloc = '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';
       
  3806 
       
  3807 			each(s.split(','), function(s) {
       
  3808 				var p = s.split(/\[|\]/), re;
       
  3809 
       
  3810 				s = '';
       
  3811 				each(p[1].split('|'), function(v) {
       
  3812 					if (s)
       
  3813 						s += '|';
       
  3814 
       
  3815 					switch (v) {
       
  3816 						case '%itrans':
       
  3817 							v = intr;
       
  3818 							break;
       
  3819 
       
  3820 						case '%itrans_na':
       
  3821 							v = intr.substring(2);
       
  3822 							break;
       
  3823 
       
  3824 						case '%istrict':
       
  3825 							v = inst;
       
  3826 							break;
       
  3827 
       
  3828 						case '%istrict_na':
       
  3829 							v = inst.substring(2);
       
  3830 							break;
       
  3831 
       
  3832 						case '%btrans':
       
  3833 							v = bloc;
       
  3834 							break;
       
  3835 
       
  3836 						case '%bstrict':
       
  3837 							v = bloc;
       
  3838 							break;
       
  3839 					}
       
  3840 
       
  3841 					s += v;
       
  3842 				});
       
  3843 				re = new RegExp('^(' + s.toLowerCase() + ')$', 'i');
       
  3844 
       
  3845 				each(p[0].split('/'), function(s) {
       
  3846 					t.childRules = t.childRules || {};
       
  3847 					t.childRules[s] = re;
       
  3848 				});
       
  3849 			});
       
  3850 
       
  3851 			// Build regex
       
  3852 			s = '';
       
  3853 			each(t.childRules, function(v, k) {
       
  3854 				if (s)
       
  3855 					s += '|';
       
  3856 
       
  3857 				s += k;
       
  3858 			});
       
  3859 
       
  3860 			t.parentElementsRE = new RegExp('^(' + s.toLowerCase() + ')$', 'i');
       
  3861 
       
  3862 			/*console.debug(t.parentElementsRE.toString());
       
  3863 			each(t.childRules, function(v) {
       
  3864 				console.debug(v.toString());
       
  3865 			});*/
       
  3866 		},
       
  3867 
       
  3868 		setRules : function(s) {
       
  3869 			var t = this;
       
  3870 
       
  3871 			t._setup();
       
  3872 			t.rules = {};
       
  3873 			t.wildRules = [];
       
  3874 			t.validElements = {};
       
  3875 
       
  3876 			return t.addRules(s);
       
  3877 		},
       
  3878 
       
  3879 		addRules : function(s) {
       
  3880 			var t = this, dr;
       
  3881 
       
  3882 			if (!s)
       
  3883 				return;
       
  3884 
       
  3885 			t._setup();
       
  3886 
       
  3887 			each(s.split(','), function(s) {
       
  3888 				var p = s.split(/\[|\]/), tn = p[0].split('/'), ra, at, wat, va = [];
       
  3889 
       
  3890 				// Extend with default rules
       
  3891 				if (dr)
       
  3892 					at = tinymce.extend([], dr.attribs);
       
  3893 
       
  3894 				// Parse attributes
       
  3895 				if (p.length > 1) {
       
  3896 					each(p[1].split('|'), function(s) {
       
  3897 						var ar = {}, i;
       
  3898 
       
  3899 						at = at || [];
       
  3900 
       
  3901 						// Parse attribute rule
       
  3902 						s = s.replace(/::/g, '~');
       
  3903 						s = /^([!\-])?([\w*.?~_\-]+|)([=:<])?(.+)?$/.exec(s);
       
  3904 						s[2] = s[2].replace(/~/g, ':');
       
  3905 
       
  3906 						// Add required attributes
       
  3907 						if (s[1] == '!') {
       
  3908 							ra = ra || [];
       
  3909 							ra.push(s[2]);
       
  3910 						}
       
  3911 
       
  3912 						// Remove inherited attributes
       
  3913 						if (s[1] == '-') {
       
  3914 							for (i = 0; i <at.length; i++) {
       
  3915 								if (at[i].name == s[2]) {
       
  3916 									at.splice(i, 1);
       
  3917 									return;
       
  3918 								}
       
  3919 							}
       
  3920 						}
       
  3921 
       
  3922 						switch (s[3]) {
       
  3923 							// Add default attrib values
       
  3924 							case '=':
       
  3925 								ar.defaultVal = s[4] || '';
       
  3926 								break;
       
  3927 
       
  3928 							// Add forced attrib values
       
  3929 							case ':':
       
  3930 								ar.forcedVal = s[4];
       
  3931 								break;
       
  3932 
       
  3933 							// Add validation values
       
  3934 							case '<':
       
  3935 								ar.validVals = s[4].split('?');
       
  3936 								break;
       
  3937 						}
       
  3938 
       
  3939 						if (/[*.?]/.test(s[2])) {
       
  3940 							wat = wat || [];
       
  3941 							ar.nameRE = new RegExp('^' + wildcardToRE(s[2]) + '$');
       
  3942 							wat.push(ar);
       
  3943 						} else {
       
  3944 							ar.name = s[2];
       
  3945 							at.push(ar);
       
  3946 						}
       
  3947 
       
  3948 						va.push(s[2]);
       
  3949 					});
       
  3950 				}
       
  3951 
       
  3952 				// Handle element names
       
  3953 				each(tn, function(s, i) {
       
  3954 					var pr = s.charAt(0), x = 1, ru = {};
       
  3955 
       
  3956 					// Extend with default rule data
       
  3957 					if (dr) {
       
  3958 						if (dr.noEmpty)
       
  3959 							ru.noEmpty = dr.noEmpty;
       
  3960 
       
  3961 						if (dr.fullEnd)
       
  3962 							ru.fullEnd = dr.fullEnd;
       
  3963 
       
  3964 						if (dr.padd)
       
  3965 							ru.padd = dr.padd;
       
  3966 					}
       
  3967 
       
  3968 					// Handle prefixes
       
  3969 					switch (pr) {
       
  3970 						case '-':
       
  3971 							ru.noEmpty = true;
       
  3972 							break;
       
  3973 
       
  3974 						case '+':
       
  3975 							ru.fullEnd = true;
       
  3976 							break;
       
  3977 
       
  3978 						case '#':
       
  3979 							ru.padd = true;
       
  3980 							break;
       
  3981 
       
  3982 						default:
       
  3983 							x = 0;
       
  3984 					}
       
  3985 
       
  3986 					tn[i] = s = s.substring(x);
       
  3987 					t.validElements[s] = 1;
       
  3988 
       
  3989 					// Add element name or element regex
       
  3990 					if (/[*.?]/.test(tn[0])) {
       
  3991 						ru.nameRE = new RegExp('^' + wildcardToRE(tn[0]) + '$');
       
  3992 						t.wildRules = t.wildRules || {};
       
  3993 						t.wildRules.push(ru);
       
  3994 					} else {
       
  3995 						ru.name = tn[0];
       
  3996 
       
  3997 						// Store away default rule
       
  3998 						if (tn[0] == '@')
       
  3999 							dr = ru;
       
  4000 
       
  4001 						t.rules[s] = ru;
       
  4002 					}
       
  4003 
       
  4004 					ru.attribs = at;
       
  4005 
       
  4006 					if (ra)
       
  4007 						ru.requiredAttribs = ra;
       
  4008 
       
  4009 					if (wat) {
       
  4010 						// Build valid attributes regexp
       
  4011 						s = '';
       
  4012 						each(va, function(v) {
       
  4013 							if (s)
       
  4014 								s += '|';
       
  4015 
       
  4016 							s += '(' + wildcardToRE(v) + ')';
       
  4017 						});
       
  4018 						ru.validAttribsRE = new RegExp('^' + s.toLowerCase() + '$');
       
  4019 						ru.wildAttribs = wat;
       
  4020 					}
       
  4021 				});
       
  4022 			});
       
  4023 
       
  4024 			// Build valid elements regexp
       
  4025 			s = '';
       
  4026 			each(t.validElements, function(v, k) {
       
  4027 				if (s)
       
  4028 					s += '|';
       
  4029 
       
  4030 				if (k != '@')
       
  4031 					s += k;
       
  4032 			});
       
  4033 			t.validElementsRE = new RegExp('^(' + wildcardToRE(s.toLowerCase()) + ')$');
       
  4034 
       
  4035 			//console.debug(t.validElementsRE.toString());
       
  4036 			//console.dir(t.rules);
       
  4037 			//console.dir(t.wildRules);
       
  4038 		},
       
  4039 
       
  4040 		findRule : function(n) {
       
  4041 			var t = this, rl = t.rules, i, r;
       
  4042 
       
  4043 			t._setup();
       
  4044 
       
  4045 			// Exact match
       
  4046 			r = rl[n];
       
  4047 			if (r)
       
  4048 				return r;
       
  4049 
       
  4050 			// Try wildcards
       
  4051 			rl = t.wildRules;
       
  4052 			for (i = 0; i < rl.length; i++) {
       
  4053 				if (rl[i].nameRE.test(n))
       
  4054 					return rl[i];
       
  4055 			}
       
  4056 
       
  4057 			return null;
       
  4058 		},
       
  4059 
       
  4060 		findAttribRule : function(ru, n) {
       
  4061 			var i, wa = ru.wildAttribs;
       
  4062 
       
  4063 			for (i = 0; i < wa.length; i++) {
       
  4064 				if (wa[i].nameRE.test(n))
       
  4065 					return wa[i];
       
  4066 			}
       
  4067 
       
  4068 			return null;
       
  4069 		},
       
  4070 
       
  4071 		serialize : function(n, o) {
       
  4072 			var h, t = this;
       
  4073 
       
  4074 			t._setup();
       
  4075 			o = o || {};
       
  4076 			o.format = o.format || 'html';
       
  4077 			t.processObj = o;
       
  4078 			n = n.cloneNode(true);
       
  4079 			t.key = '' + (parseInt(t.key) + 1);
       
  4080 
       
  4081 			// Pre process
       
  4082 			if (!o.no_events) {
       
  4083 				o.node = n;
       
  4084 				t.onPreProcess.dispatch(t, o);
       
  4085 			}
       
  4086 
       
  4087 			// Serialize HTML DOM into a string
       
  4088 			t.writer.reset();
       
  4089 			t._serializeNode(n, o.getInner);
       
  4090 
       
  4091 			// Post process
       
  4092 			o.content = t.writer.getContent();
       
  4093 
       
  4094 			if (!o.no_events)
       
  4095 				t.onPostProcess.dispatch(t, o);
       
  4096 
       
  4097 			t._postProcess(o);
       
  4098 			o.node = null;
       
  4099 
       
  4100 			return tinymce.trim(o.content);
       
  4101 		},
       
  4102 
       
  4103 		// Internal functions
       
  4104 
       
  4105 		_postProcess : function(o) {
       
  4106 			var t = this, s = t.settings, h = o.content, sc = [], p;
       
  4107 
       
  4108 			if (o.format == 'html') {
       
  4109 				// Protect some elements
       
  4110 				p = t._protect({
       
  4111 					content : h,
       
  4112 					patterns : [
       
  4113 						{pattern : /(<script[^>]*>)(.*?)(<\/script>)/g},
       
  4114 						{pattern : /(<style[^>]*>)(.*?)(<\/style>)/g},
       
  4115 						{pattern : /(<pre[^>]*>)(.*?)(<\/pre>)/g, encode : 1},
       
  4116 						{pattern : /(<!--\[CDATA\[)(.*?)(\]\]-->)/g}
       
  4117 					]
       
  4118 				});
       
  4119 
       
  4120 				h = p.content;
       
  4121 
       
  4122 				// Entity encode
       
  4123 				if (s.entity_encoding !== 'raw')
       
  4124 					h = t._encode(h);
       
  4125 
       
  4126 				// Use BR instead of &nbsp; padded P elements inside editor and use <p>&nbsp;</p> outside editor
       
  4127 /*				if (o.set)
       
  4128 					h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p><br /></p>');
       
  4129 				else
       
  4130 					h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p>$1</p>');*/
       
  4131 
       
  4132 				// Since Gecko and Safari keeps whitespace in the DOM we need to
       
  4133 				// remove it inorder to match other browsers. But I think Gecko and Safari is right.
       
  4134 				// This process is only done when getting contents out from the editor.
       
  4135 				if (!o.set) {
       
  4136 					// We need to replace paragraph whitespace with an nbsp before indentation to keep the \u00a0 char
       
  4137 					h = h.replace(/<p>\s+<\/p>|<p([^>]+)>\s+<\/p>/g, s.entity_encoding == 'numeric' ? '<p$1>&#160;</p>' : '<p$1>&nbsp;</p>');
       
  4138 
       
  4139 					if (s.remove_linebreaks) {
       
  4140 						h = h.replace(/\r?\n|\r/g, ' ');
       
  4141 						h = h.replace(/(<[^>]+>)\s+/g, '$1 ');
       
  4142 						h = h.replace(/\s+(<\/[^>]+>)/g, ' $1');
       
  4143 						h = h.replace(/<(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object) ([^>]+)>\s+/g, '<$1 $2>'); // Trim block start
       
  4144 						h = h.replace(/<(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>\s+/g, '<$1>'); // Trim block start
       
  4145 						h = h.replace(/\s+<\/(p|h[1-6]|blockquote|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>/g, '</$1>'); // Trim block end
       
  4146 					}
       
  4147 
       
  4148 					// Simple indentation
       
  4149 					if (s.apply_source_formatting && s.indent_mode == 'simple') {
       
  4150 						// Add line breaks before and after block elements
       
  4151 						h = h.replace(/<(\/?)(ul|hr|table|meta|link|tbody|tr|object|body|head|html|map)(|[^>]+)>\s*/g, '\n<$1$2$3>\n');
       
  4152 						h = h.replace(/\s*<(p|h[1-6]|blockquote|div|title|style|pre|script|td|li|area)(|[^>]+)>/g, '\n<$1$2>');
       
  4153 						h = h.replace(/<\/(p|h[1-6]|blockquote|div|title|style|pre|script|td|li)>\s*/g, '</$1>\n');
       
  4154 						h = h.replace(/\n\n/g, '\n');
       
  4155 					}
       
  4156 				}
       
  4157 
       
  4158 				h = t._unprotect(h, p);
       
  4159 
       
  4160 				// Restore CDATA sections
       
  4161 				h = h.replace(/<!--\[CDATA\[([\s\S]+)\]\]-->/g, '<![CDATA[$1]]>');
       
  4162 
       
  4163 				// Restore the \u00a0 character if raw mode is enabled
       
  4164 				if (s.entity_encoding == 'raw')
       
  4165 					h = h.replace(/<p>&nbsp;<\/p>|<p([^>]+)>&nbsp;<\/p>/g, '<p$1>\u00a0</p>');
       
  4166 			}
       
  4167 
       
  4168 			o.content = h;
       
  4169 		},
       
  4170 
       
  4171 		_serializeNode : function(n, inn) {
       
  4172 			var t = this, s = t.settings, w = t.writer, hc, el, cn, i, l, a, at, no, v, nn, ru, ar, iv;
       
  4173 
       
  4174 			if (!s.node_filter || s.node_filter(n)) {
       
  4175 				switch (n.nodeType) {
       
  4176 					case 1: // Element
       
  4177 						if (n.hasAttribute ? n.hasAttribute('mce_bogus') : n.getAttribute('mce_bogus'))
       
  4178 							return;
       
  4179 
       
  4180 						iv = false;
       
  4181 						hc = n.hasChildNodes();
       
  4182 						nn = n.getAttribute('mce_name') || n.nodeName.toLowerCase();
       
  4183 
       
  4184 						// Add correct prefix on IE
       
  4185 						if (isIE) {
       
  4186 							if (n.scopeName !== 'HTML' && n.scopeName !== 'html')
       
  4187 								nn = n.scopeName + ':' + nn;
       
  4188 						}
       
  4189 
       
  4190 						// Remove mce prefix on IE needed for the abbr element
       
  4191 						if (nn.indexOf('mce:') === 0)
       
  4192 							nn = nn.substring(4);
       
  4193 
       
  4194 						// Check if valid
       
  4195 						if (!t.validElementsRE.test(nn) || (t.invalidElementsRE && t.invalidElementsRE.test(nn)) || inn) {
       
  4196 							iv = true;
       
  4197 							break;
       
  4198 						}
       
  4199 
       
  4200 						if (isIE) {
       
  4201 							// Fix IE content duplication (DOM can have multiple copies of the same node)
       
  4202 							if (s.fix_content_duplication) {
       
  4203 								if (n.mce_serialized == t.key)
       
  4204 									return;
       
  4205 
       
  4206 								n.mce_serialized = t.key;
       
  4207 							}
       
  4208 
       
  4209 							// IE sometimes adds a / infront of the node name
       
  4210 							if (nn.charAt(0) == '/')
       
  4211 								nn = nn.substring(1);
       
  4212 						} else if (isGecko) {
       
  4213 							// Ignore br elements
       
  4214 							if (n.nodeName === 'BR' && n.getAttribute('type') == '_moz')
       
  4215 								return;
       
  4216 						}
       
  4217 
       
  4218 						// Check if valid child
       
  4219 						if (t.childRules) {
       
  4220 							if (t.parentElementsRE.test(t.elementName)) {
       
  4221 								if (!t.childRules[t.elementName].test(nn)) {
       
  4222 									iv = true;
       
  4223 									break;
       
  4224 								}
       
  4225 							}
       
  4226 
       
  4227 							t.elementName = nn;
       
  4228 						}
       
  4229 
       
  4230 						ru = t.findRule(nn);
       
  4231 						nn = ru.name || nn;
       
  4232 
       
  4233 						// Skip empty nodes or empty node name in IE
       
  4234 						if ((!hc && ru.noEmpty) || (isIE && !nn)) {
       
  4235 							iv = true;
       
  4236 							break;
       
  4237 						}
       
  4238 
       
  4239 						// Check required
       
  4240 						if (ru.requiredAttribs) {
       
  4241 							a = ru.requiredAttribs;
       
  4242 
       
  4243 							for (i = a.length - 1; i >= 0; i--) {
       
  4244 								if (this.dom.getAttrib(n, a[i]) !== '')
       
  4245 									break;
       
  4246 							}
       
  4247 
       
  4248 							// None of the required was there
       
  4249 							if (i == -1) {
       
  4250 								iv = true;
       
  4251 								break;
       
  4252 							}
       
  4253 						}
       
  4254 
       
  4255 						w.writeStartElement(nn);
       
  4256 
       
  4257 						// Add ordered attributes
       
  4258 						if (ru.attribs) {
       
  4259 							for (i=0, at = ru.attribs, l = at.length; i<l; i++) {
       
  4260 								a = at[i];
       
  4261 								v = t._getAttrib(n, a);
       
  4262 
       
  4263 								if (v !== null)
       
  4264 									w.writeAttribute(a.name, v);
       
  4265 							}
       
  4266 						}
       
  4267 
       
  4268 						// Add wild attributes
       
  4269 						if (ru.validAttribsRE) {
       
  4270 							at = isIE ? getIEAtts(n) : n.attributes;
       
  4271 							for (i=at.length-1; i>-1; i--) {
       
  4272 								no = at[i];
       
  4273 
       
  4274 								if (no.specified) {
       
  4275 									a = no.nodeName.toLowerCase();
       
  4276 
       
  4277 									if (s.invalid_attrs.test(a) || !ru.validAttribsRE.test(a))
       
  4278 										continue;
       
  4279 
       
  4280 									ar = t.findAttribRule(ru, a);
       
  4281 									v = t._getAttrib(n, ar, a);
       
  4282 
       
  4283 									if (v !== null)
       
  4284 										w.writeAttribute(a, v);
       
  4285 								}
       
  4286 							}
       
  4287 						}
       
  4288 
       
  4289 						// Padd empty nodes with a &nbsp;
       
  4290 						if (!hc && ru.padd)
       
  4291 							w.writeText('\u00a0');
       
  4292 
       
  4293 						break;
       
  4294 
       
  4295 					case 3: // Text
       
  4296 						// Check if valid child
       
  4297 						if (t.childRules && t.parentElementsRE.test(t.elementName)) {
       
  4298 							if (!t.childRules[t.elementName].test(n.nodeName))
       
  4299 								return;
       
  4300 						}
       
  4301 
       
  4302 						return w.writeText(n.nodeValue);
       
  4303 
       
  4304 					case 4: // CDATA
       
  4305 						return w.writeCDATA(n.nodeValue);
       
  4306 
       
  4307 					case 8: // Comment
       
  4308 						return w.writeComment(n.nodeValue);
       
  4309 				}
       
  4310 			} else if (n.nodeType == 1)
       
  4311 				hc = n.hasChildNodes();
       
  4312 
       
  4313 			if (hc) {
       
  4314 				cn = n.firstChild;
       
  4315 
       
  4316 				while (cn) {
       
  4317 					t._serializeNode(cn);
       
  4318 					t.elementName = nn;
       
  4319 					cn = cn.nextSibling;
       
  4320 				}
       
  4321 			}
       
  4322 
       
  4323 			// Write element end
       
  4324 			if (!iv) {
       
  4325 				if (hc || !s.closed.test(nn))
       
  4326 					w.writeFullEndElement();
       
  4327 				else
       
  4328 					w.writeEndElement();
       
  4329 			}
       
  4330 		},
       
  4331 
       
  4332 		_protect : function(o) {
       
  4333 			var t = this;
       
  4334 
       
  4335 			o.items = o.items || [];
       
  4336 
       
  4337 			function enc(s) {
       
  4338 				return s.replace(/[\r\n\\]/g, function(c) {
       
  4339 					if (c === '\n')
       
  4340 						return '\\n';
       
  4341 					else if (c === '\\')
       
  4342 						return '\\\\';
       
  4343 
       
  4344 					return '\\r';
       
  4345 				});
       
  4346 			};
       
  4347 
       
  4348 			function dec(s) {
       
  4349 				return s.replace(/\\[\\rn]/g, function(c) {
       
  4350 					if (c === '\\n')
       
  4351 						return '\n';
       
  4352 					else if (c === '\\\\')
       
  4353 						return '\\';
       
  4354 
       
  4355 					return '\r';
       
  4356 				});
       
  4357 			};
       
  4358 
       
  4359 			each(o.patterns, function(p) {
       
  4360 				o.content = dec(enc(o.content).replace(p.pattern, function(x, a, b, c) {
       
  4361 					b = dec(b);
       
  4362 
       
  4363 					if (p.encode)
       
  4364 						b = t._encode(b);
       
  4365 
       
  4366 					o.items.push(b);
       
  4367 					return a + '<!--mce:' + (o.items.length - 1) + '-->' + c;
       
  4368 				}));
       
  4369 			});
       
  4370 
       
  4371 			return o;
       
  4372 		},
       
  4373 
       
  4374 		_unprotect : function(h, o) {
       
  4375 			h = h.replace(/\<!--mce:([0-9]+)--\>/g, function(a, b) {
       
  4376 				return o.items[parseInt(b)];
       
  4377 			});
       
  4378 
       
  4379 			o.items = [];
       
  4380 
       
  4381 			return h;
       
  4382 		},
       
  4383 
       
  4384 		_encode : function(h) {
       
  4385 			var t = this, s = t.settings, l;
       
  4386 
       
  4387 			// Entity encode
       
  4388 			if (s.entity_encoding !== 'raw') {
       
  4389 				if (s.entity_encoding.indexOf('named') != -1) {
       
  4390 					t.setEntities(s.entities);
       
  4391 					l = t.entityLookup;
       
  4392 
       
  4393 					h = h.replace(t.entitiesRE, function(a) {
       
  4394 						var v;
       
  4395 
       
  4396 						if (v = l[a])
       
  4397 							a = '&' + v + ';';
       
  4398 
       
  4399 						return a;
       
  4400 					});
       
  4401 				}
       
  4402 
       
  4403 				if (s.entity_encoding.indexOf('numeric') != -1) {
       
  4404 					h = h.replace(/[\u007E-\uFFFF]/g, function(a) {
       
  4405 						return '&#' + a.charCodeAt(0) + ';';
       
  4406 					});
       
  4407 				}
       
  4408 			}
       
  4409 
       
  4410 			return h;
       
  4411 		},
       
  4412 
       
  4413 		_setup : function() {
       
  4414 			var t = this, s = this.settings;
       
  4415 
       
  4416 			if (t.done)
       
  4417 				return;
       
  4418 
       
  4419 			t.done = 1;
       
  4420 
       
  4421 			t.setRules(s.valid_elements);
       
  4422 			t.addRules(s.extended_valid_elements);
       
  4423 			t.addValidChildRules(s.valid_child_elements);
       
  4424 
       
  4425 			if (s.invalid_elements)
       
  4426 				t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(/,/g, '|').toLowerCase()) + ')$');
       
  4427 
       
  4428 			if (s.attrib_value_filter)
       
  4429 				t.attribValueFilter = s.attribValueFilter;
       
  4430 		},
       
  4431 
       
  4432 		_getAttrib : function(n, a, na) {
       
  4433 			var i, v;
       
  4434 
       
  4435 			na = na || a.name;
       
  4436 
       
  4437 			if (a.forcedVal && (v = a.forcedVal)) {
       
  4438 				if (v === '{$uid}')
       
  4439 					return this.dom.uniqueId();
       
  4440 
       
  4441 				return v;
       
  4442 			}
       
  4443 
       
  4444 			v = this.dom.getAttrib(n, na);
       
  4445 
       
  4446 			switch (na) {
       
  4447 				case 'rowspan':
       
  4448 				case 'colspan':
       
  4449 					// Whats the point? Remove usless attribute value
       
  4450 					if (v == '1')
       
  4451 						v = '';
       
  4452 
       
  4453 					break;
       
  4454 			}
       
  4455 
       
  4456 			if (this.attribValueFilter)
       
  4457 				v = this.attribValueFilter(na, v, n);
       
  4458 
       
  4459 			if (a.validVals) {
       
  4460 				for (i = a.validVals.length - 1; i >= 0; i--) {
       
  4461 					if (v == a.validVals[i])
       
  4462 						break;
       
  4463 				}
       
  4464 
       
  4465 				if (i == -1)
       
  4466 					return null;
       
  4467 			}
       
  4468 
       
  4469 			if (v === '' && typeof(a.defaultVal) != 'undefined') {
       
  4470 				v = a.defaultVal;
       
  4471 
       
  4472 				if (v === '{$uid}')
       
  4473 					return this.dom.uniqueId();
       
  4474 
       
  4475 				return v;
       
  4476 			} else {
       
  4477 				// Remove internal mceItemXX classes when content is extracted from editor
       
  4478 				if (na == 'class' && this.processObj.get)
       
  4479 					v = v.replace(/\s?mceItem\w+\s?/g, '');
       
  4480 			}
       
  4481 
       
  4482 			if (v === '')
       
  4483 				return null;
       
  4484 
       
  4485 
       
  4486 			return v;
       
  4487 		}
       
  4488 
       
  4489 		});
       
  4490 })();
       
  4491 
       
  4492 /* file:jscripts/tiny_mce/classes/dom/ScriptLoader.js */
       
  4493 
       
  4494 (function() {
       
  4495 	var each = tinymce.each;
       
  4496 
       
  4497 	tinymce.create('tinymce.dom.ScriptLoader', {
       
  4498 		ScriptLoader : function(s) {
       
  4499 			this.settings = s || {};
       
  4500 			this.queue = [];
       
  4501 			this.lookup = {};
       
  4502 		},
       
  4503 
       
  4504 		isDone : function(u) {
       
  4505 			return this.lookup[u] ? this.lookup[u].state == 2 : 0;
       
  4506 		},
       
  4507 
       
  4508 		markDone : function(u) {
       
  4509 			this.lookup[u] = {state : 2, url : u};
       
  4510 		},
       
  4511 
       
  4512 		add : function(u, cb, s, pr) {
       
  4513 			var t = this, lo = t.lookup, o;
       
  4514 
       
  4515 			if (o = lo[u]) {
       
  4516 				// Is loaded fire callback
       
  4517 				if (cb && o.state == 2)
       
  4518 					cb.call(s || this);
       
  4519 
       
  4520 				return o;
       
  4521 			}
       
  4522 
       
  4523 			o = {state : 0, url : u, func : cb, scope : s || this};
       
  4524 
       
  4525 			if (pr)
       
  4526 				t.queue.unshift(o);
       
  4527 			else
       
  4528 				t.queue.push(o);
       
  4529 
       
  4530 			lo[u] = o;
       
  4531 
       
  4532 			return o;
       
  4533 		},
       
  4534 
       
  4535 		load : function(u, cb, s) {
       
  4536 			var t = this, o;
       
  4537 
       
  4538 			if (o = t.lookup[u]) {
       
  4539 				// Is loaded fire callback
       
  4540 				if (cb && o.state == 2)
       
  4541 					cb.call(s || t);
       
  4542 
       
  4543 				return o;
       
  4544 			}
       
  4545 
       
  4546 			function loadScript(u) {
       
  4547 				if (tinymce.dom.Event.domLoaded || t.settings.strict_mode) {
       
  4548 					tinymce.util.XHR.send({
       
  4549 						url : tinymce._addVer(u),
       
  4550 						error : t.settings.error,
       
  4551 						async : false,
       
  4552 						success : function(co) {
       
  4553 							t.eval(co);
       
  4554 						}
       
  4555 					});
       
  4556 				} else
       
  4557 					document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"></script>');
       
  4558 			};
       
  4559 
       
  4560 			if (!tinymce.is(u, 'string')) {
       
  4561 				each(u, function(u) {
       
  4562 					loadScript(u);
       
  4563 				});
       
  4564 
       
  4565 				if (cb)
       
  4566 					cb.call(s || t);
       
  4567 			} else {
       
  4568 				loadScript(u);
       
  4569 
       
  4570 				if (cb)
       
  4571 					cb.call(s || t);
       
  4572 			}
       
  4573 		},
       
  4574 
       
  4575 		loadQueue : function(cb, s) {
       
  4576 			var t = this;
       
  4577 
       
  4578 			if (!t.queueLoading) {
       
  4579 				t.queueLoading = 1;
       
  4580 				t.queueCallbacks = [];
       
  4581 
       
  4582 				t.loadScripts(t.queue, function() {
       
  4583 					t.queueLoading = 0;
       
  4584 
       
  4585 					if (cb)
       
  4586 						cb.call(s || t);
       
  4587 
       
  4588 					each(t.queueCallbacks, function(o) {
       
  4589 						o.func.call(o.scope);
       
  4590 					});
       
  4591 				});
       
  4592 			} else if (cb)
       
  4593 				t.queueCallbacks.push({func : cb, scope : s || t});
       
  4594 		},
       
  4595 
       
  4596 		eval : function(co) {
       
  4597 			var w = window;
       
  4598 
       
  4599 			// Evaluate script
       
  4600 			if (!w.execScript) {
       
  4601 				try {
       
  4602 					eval.call(w, co);
       
  4603 				} catch (ex) {
       
  4604 					eval(co, w); // Firefox 3.0a8
       
  4605 				}
       
  4606 			} else
       
  4607 				w.execScript(co); // IE
       
  4608 		},
       
  4609 
       
  4610 		loadScripts : function(sc, cb, s) {
       
  4611 			var t = this, lo = t.lookup;
       
  4612 
       
  4613 			function done(o) {
       
  4614 				o.state = 2; // Has been loaded
       
  4615 
       
  4616 				// Run callback
       
  4617 				if (o.func)
       
  4618 					o.func.call(o.scope || t);
       
  4619 			};
       
  4620 
       
  4621 			function allDone() {
       
  4622 				var l;
       
  4623 
       
  4624 				// Check if all files are loaded
       
  4625 				l = sc.length;
       
  4626 				each(sc, function(o) {
       
  4627 					o = lo[o.url];
       
  4628 
       
  4629 					if (o.state === 2) {// It has finished loading
       
  4630 						done(o);
       
  4631 						l--;
       
  4632 					} else
       
  4633 						load(o);
       
  4634 				});
       
  4635 
       
  4636 				// They are all loaded
       
  4637 				if (l === 0 && cb) {
       
  4638 					cb.call(s || t);
       
  4639 					cb = 0;
       
  4640 				}
       
  4641 			};
       
  4642 
       
  4643 			function load(o) {
       
  4644 				if (o.state > 0)
       
  4645 					return;
       
  4646 
       
  4647 				o.state = 1; // Is loading
       
  4648 
       
  4649 				tinymce.util.XHR.send({
       
  4650 					url : o.url,
       
  4651 					error : t.settings.error,
       
  4652 					success : function(co) {
       
  4653 						t.eval(co);
       
  4654 						done(o);
       
  4655 						allDone();
       
  4656 					}
       
  4657 				});
       
  4658 			};
       
  4659 
       
  4660 			each(sc, function(o) {
       
  4661 				var u = o.url;
       
  4662 
       
  4663 				// Add to queue if needed
       
  4664 				if (!lo[u]) {
       
  4665 					lo[u] = o;
       
  4666 					t.queue.push(o);
       
  4667 				} else
       
  4668 					o = lo[u];
       
  4669 
       
  4670 				// Is already loading or has been loaded
       
  4671 				if (o.state > 0)
       
  4672 					return;
       
  4673 
       
  4674 				if (!tinymce.dom.Event.domLoaded && !t.settings.strict_mode) {
       
  4675 					var ix, ol = '';
       
  4676 
       
  4677 					// Add onload events
       
  4678 					if (cb || o.func) {
       
  4679 						o.state = 1; // Is loading
       
  4680 
       
  4681 						ix = tinymce.dom.ScriptLoader._addOnLoad(function() {
       
  4682 							done(o);
       
  4683 							allDone();
       
  4684 						});
       
  4685 
       
  4686 						if (tinymce.isIE)
       
  4687 							ol = ' onreadystatechange="';
       
  4688 						else
       
  4689 							ol = ' onload="';
       
  4690 
       
  4691 						ol += 'tinymce.dom.ScriptLoader._onLoad(this,\'' + u + '\',' + ix + ');"';
       
  4692 					}
       
  4693 
       
  4694 					document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"' + ol + '></script>');
       
  4695 
       
  4696 					if (!o.func)
       
  4697 						done(o);
       
  4698 				} else
       
  4699 					load(o);
       
  4700 			});
       
  4701 
       
  4702 			allDone();
       
  4703 		},
       
  4704 
       
  4705 		// Static methods
       
  4706 		'static' : {
       
  4707 			_addOnLoad : function(f) {
       
  4708 				var t = this;
       
  4709 
       
  4710 				t._funcs = t._funcs || [];
       
  4711 				t._funcs.push(f);
       
  4712 
       
  4713 				return t._funcs.length - 1;
       
  4714 			},
       
  4715 
       
  4716 			_onLoad : function(e, u, ix) {
       
  4717 				if (!tinymce.isIE || e.readyState == 'complete')
       
  4718 					this._funcs[ix].call(this);
       
  4719 			}
       
  4720 		}
       
  4721 
       
  4722 		});
       
  4723 
       
  4724 	// Global script loader
       
  4725 	tinymce.ScriptLoader = new tinymce.dom.ScriptLoader();
       
  4726 })();
       
  4727 
       
  4728 /* file:jscripts/tiny_mce/classes/ui/Control.js */
       
  4729 
       
  4730 (function() {
       
  4731 	// Shorten class names
       
  4732 	var DOM = tinymce.DOM, is = tinymce.is;
       
  4733 
       
  4734 	tinymce.create('tinymce.ui.Control', {
       
  4735 		Control : function(id, s) {
       
  4736 			this.id = id;
       
  4737 			this.settings = s = s || {};
       
  4738 			this.rendered = false;
       
  4739 			this.onRender = new tinymce.util.Dispatcher(this);
       
  4740 			this.classPrefix = '';
       
  4741 			this.scope = s.scope || this;
       
  4742 			this.disabled = 0;
       
  4743 			this.active = 0;
       
  4744 		},
       
  4745 
       
  4746 		setDisabled : function(s) {
       
  4747 			var e;
       
  4748 
       
  4749 			if (s != this.disabled) {
       
  4750 				e = DOM.get(this.id);
       
  4751 
       
  4752 				// Add accessibility title for unavailable actions
       
  4753 				if (e && this.settings.unavailable_prefix) {
       
  4754 					if (s) {
       
  4755 						this.prevTitle = e.title;
       
  4756 						e.title = this.settings.unavailable_prefix + ": " + e.title;
       
  4757 					} else
       
  4758 						e.title = this.prevTitle;
       
  4759 				}
       
  4760 
       
  4761 				this.setState('Disabled', s);
       
  4762 				this.setState('Enabled', !s);
       
  4763 				this.disabled = s;
       
  4764 			}
       
  4765 		},
       
  4766 
       
  4767 		isDisabled : function() {
       
  4768 			return this.disabled;
       
  4769 		},
       
  4770 
       
  4771 		setActive : function(s) {
       
  4772 			if (s != this.active) {
       
  4773 				this.setState('Active', s);
       
  4774 				this.active = s;
       
  4775 			}
       
  4776 		},
       
  4777 
       
  4778 		isActive : function() {
       
  4779 			return this.active;
       
  4780 		},
       
  4781 
       
  4782 		setState : function(c, s) {
       
  4783 			var n = DOM.get(this.id);
       
  4784 
       
  4785 			c = this.classPrefix + c;
       
  4786 
       
  4787 			if (s)
       
  4788 				DOM.addClass(n, c);
       
  4789 			else
       
  4790 				DOM.removeClass(n, c);
       
  4791 		},
       
  4792 
       
  4793 		isRendered : function() {
       
  4794 			return this.rendered;
       
  4795 		},
       
  4796 
       
  4797 		renderHTML : function() {
       
  4798 		},
       
  4799 
       
  4800 		renderTo : function(n) {
       
  4801 			DOM.setHTML(n, this.renderHTML());
       
  4802 		},
       
  4803 
       
  4804 		postRender : function() {
       
  4805 			var t = this, b;
       
  4806 
       
  4807 			// Set pending states
       
  4808 			if (is(t.disabled)) {
       
  4809 				b = t.disabled;
       
  4810 				t.disabled = -1;
       
  4811 				t.setDisabled(b);
       
  4812 			}
       
  4813 
       
  4814 			if (is(t.active)) {
       
  4815 				b = t.active;
       
  4816 				t.active = -1;
       
  4817 				t.setActive(b);
       
  4818 			}
       
  4819 		},
       
  4820 
       
  4821 		remove : function() {
       
  4822 			DOM.remove(this.id);
       
  4823 			this.destroy();
       
  4824 		},
       
  4825 
       
  4826 		destroy : function() {
       
  4827 			tinymce.dom.Event.clear(this.id);
       
  4828 		}
       
  4829 
       
  4830 		});
       
  4831 })();
       
  4832 /* file:jscripts/tiny_mce/classes/ui/Container.js */
       
  4833 
       
  4834 tinymce.create('tinymce.ui.Container:tinymce.ui.Control', {
       
  4835 	Container : function(id, s) {
       
  4836 		this.parent(id, s);
       
  4837 		this.controls = [];
       
  4838 		this.lookup = {};
       
  4839 	},
       
  4840 
       
  4841 	add : function(c) {
       
  4842 		this.lookup[c.id] = c;
       
  4843 		this.controls.push(c);
       
  4844 
       
  4845 		return c;
       
  4846 	},
       
  4847 
       
  4848 	get : function(n) {
       
  4849 		return this.lookup[n];
       
  4850 	}
       
  4851 
       
  4852 	});
       
  4853 
       
  4854 
       
  4855 /* file:jscripts/tiny_mce/classes/ui/Separator.js */
       
  4856 
       
  4857 tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
       
  4858 	Separator : function(id, s) {
       
  4859 		this.parent(id, s);
       
  4860 		this.classPrefix = 'mceSeparator';
       
  4861 	},
       
  4862 
       
  4863 	renderHTML : function() {
       
  4864 		return tinymce.DOM.createHTML('span', {'class' : this.classPrefix});
       
  4865 	}
       
  4866 
       
  4867 	});
       
  4868 
       
  4869 /* file:jscripts/tiny_mce/classes/ui/MenuItem.js */
       
  4870 
       
  4871 (function() {
       
  4872 	var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
       
  4873 
       
  4874 	tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', {
       
  4875 		MenuItem : function(id, s) {
       
  4876 			this.parent(id, s);
       
  4877 			this.classPrefix = 'mceMenuItem';
       
  4878 		},
       
  4879 
       
  4880 		setSelected : function(s) {
       
  4881 			this.setState('Selected', s);
       
  4882 			this.selected = s;
       
  4883 		},
       
  4884 
       
  4885 		isSelected : function() {
       
  4886 			return this.selected;
       
  4887 		},
       
  4888 
       
  4889 		postRender : function() {
       
  4890 			var t = this;
       
  4891 			
       
  4892 			t.parent();
       
  4893 
       
  4894 			// Set pending state
       
  4895 			if (is(t.selected))
       
  4896 				t.setSelected(t.selected);
       
  4897 		}
       
  4898 
       
  4899 		});
       
  4900 })();
       
  4901 
       
  4902 /* file:jscripts/tiny_mce/classes/ui/Menu.js */
       
  4903 
       
  4904 (function() {
       
  4905 	var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
       
  4906 
       
  4907 	tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', {
       
  4908 		Menu : function(id, s) {
       
  4909 			var t = this;
       
  4910 
       
  4911 			t.parent(id, s);
       
  4912 			t.items = {};
       
  4913 			t.collapsed = false;
       
  4914 			t.menuCount = 0;
       
  4915 			t.onAddItem = new tinymce.util.Dispatcher(this);
       
  4916 		},
       
  4917 
       
  4918 		expand : function(d) {
       
  4919 			var t = this;
       
  4920 
       
  4921 			if (d) {
       
  4922 				walk(t, function(o) {
       
  4923 					if (o.expand)
       
  4924 						o.expand();
       
  4925 				}, 'items', t);
       
  4926 			}
       
  4927 
       
  4928 			t.collapsed = false;
       
  4929 		},
       
  4930 
       
  4931 		collapse : function(d) {
       
  4932 			var t = this;
       
  4933 
       
  4934 			if (d) {
       
  4935 				walk(t, function(o) {
       
  4936 					if (o.collapse)
       
  4937 						o.collapse();
       
  4938 				}, 'items', t);
       
  4939 			}
       
  4940 
       
  4941 			t.collapsed = true;
       
  4942 		},
       
  4943 
       
  4944 		isCollapsed : function() {
       
  4945 			return this.collapsed;
       
  4946 		},
       
  4947 
       
  4948 		add : function(o) {
       
  4949 			if (!o.settings)
       
  4950 				o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o);
       
  4951 
       
  4952 			this.onAddItem.dispatch(this, o);
       
  4953 
       
  4954 			return this.items[o.id] = o;
       
  4955 		},
       
  4956 
       
  4957 		addSeparator : function() {
       
  4958 			return this.add({separator : true});
       
  4959 		},
       
  4960 
       
  4961 		addMenu : function(o) {
       
  4962 			if (!o.collapse)
       
  4963 				o = this.createMenu(o);
       
  4964 
       
  4965 			this.menuCount++;
       
  4966 
       
  4967 			return this.add(o);
       
  4968 		},
       
  4969 
       
  4970 		hasMenus : function() {
       
  4971 			return this.menuCount !== 0;
       
  4972 		},
       
  4973 
       
  4974 		remove : function(o) {
       
  4975 			delete this.items[o.id];
       
  4976 		},
       
  4977 
       
  4978 		removeAll : function() {
       
  4979 			var t = this;
       
  4980 
       
  4981 			walk(t, function(o) {
       
  4982 				if (o.removeAll)
       
  4983 					o.removeAll();
       
  4984 				else
       
  4985 					o.remove();
       
  4986 
       
  4987 				o.destroy();
       
  4988 			}, 'items', t);
       
  4989 
       
  4990 			t.items = {};
       
  4991 		},
       
  4992 
       
  4993 		createMenu : function(o) {
       
  4994 			var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o);
       
  4995 
       
  4996 			m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem);
       
  4997 
       
  4998 			return m;
       
  4999 		}
       
  5000 
       
  5001 		});
       
  5002 })();
       
  5003 /* file:jscripts/tiny_mce/classes/ui/DropMenu.js */
       
  5004 
       
  5005 (function() {
       
  5006 	var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element;
       
  5007 
       
  5008 	tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', {
       
  5009 		DropMenu : function(id, s) {
       
  5010 			s = s || {};
       
  5011 			s.container = s.container || DOM.doc.body;
       
  5012 			s.offset_x = s.offset_x || 0;
       
  5013 			s.offset_y = s.offset_y || 0;
       
  5014 			s.vp_offset_x = s.vp_offset_x || 0;
       
  5015 			s.vp_offset_y = s.vp_offset_y || 0;
       
  5016 
       
  5017 			if (is(s.icons) && !s.icons)
       
  5018 				s['class'] += ' mceNoIcons';
       
  5019 
       
  5020 			this.parent(id, s);
       
  5021 			this.onShowMenu = new tinymce.util.Dispatcher(this);
       
  5022 			this.onHideMenu = new tinymce.util.Dispatcher(this);
       
  5023 			this.classPrefix = 'mceMenu';
       
  5024 		},
       
  5025 
       
  5026 		createMenu : function(s) {
       
  5027 			var t = this, cs = t.settings, m;
       
  5028 
       
  5029 			s.container = s.container || cs.container;
       
  5030 			s.parent = t;
       
  5031 			s.constrain = s.constrain || cs.constrain;
       
  5032 			s['class'] = s['class'] || cs['class'];
       
  5033 			s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x;
       
  5034 			s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y;
       
  5035 			m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s);
       
  5036 
       
  5037 			m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem);
       
  5038 
       
  5039 			return m;
       
  5040 		},
       
  5041 
       
  5042 		update : function() {
       
  5043 			var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th;
       
  5044 
       
  5045 			tw = s.max_width ? Math.min(tb.clientWidth, s.max_width) : tb.clientWidth;
       
  5046 			th = s.max_height ? Math.min(tb.clientHeight, s.max_height) : tb.clientHeight;
       
  5047 
       
  5048 			if (!DOM.boxModel)
       
  5049 				t.element.setStyles({width : tw + 2, height : th + 2});
       
  5050 			else
       
  5051 				t.element.setStyles({width : tw, height : th});
       
  5052 
       
  5053 			if (s.max_width)
       
  5054 				DOM.setStyle(co, 'width', tw);
       
  5055 
       
  5056 			if (s.max_height) {
       
  5057 				DOM.setStyle(co, 'height', th);
       
  5058 
       
  5059 				if (tb.clientHeight < s.max_height)
       
  5060 					DOM.setStyle(co, 'overflow', 'hidden');
       
  5061 			}
       
  5062 		},
       
  5063 
       
  5064 		showMenu : function(x, y, px) {
       
  5065 			var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb, cp = t.classPrefix;
       
  5066 
       
  5067 			t.collapse(1);
       
  5068 
       
  5069 			if (t.isMenuVisible)
       
  5070 				return;
       
  5071 
       
  5072 			if (!t.rendered) {
       
  5073 				co = DOM.add(t.settings.container, t.renderNode());
       
  5074 
       
  5075 				each(t.items, function(o) {
       
  5076 					o.postRender();
       
  5077 				});
       
  5078 
       
  5079 				t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
       
  5080 			} else
       
  5081 				co = DOM.get('menu_' + t.id);
       
  5082 
       
  5083 			// Move layer out of sight unless it's Opera since it scrolls to top of page due to an bug
       
  5084 			if (!tinymce.isOpera)
       
  5085 				DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF});
       
  5086 
       
  5087 			DOM.show(co);
       
  5088 			t.update();
       
  5089 
       
  5090 			x += s.offset_x || 0;
       
  5091 			y += s.offset_y || 0;
       
  5092 			vp.w -= 4;
       
  5093 			vp.h -= 4;
       
  5094 
       
  5095 			// Move inside viewport if not submenu
       
  5096 			if (s.constrain) {
       
  5097 				w = co.clientWidth - ot;
       
  5098 				h = co.clientHeight - ot;
       
  5099 				mx = vp.x + vp.w;
       
  5100 				my = vp.y + vp.h;
       
  5101 
       
  5102 				if ((x + s.vp_offset_x + w) > mx)
       
  5103 					x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w);
       
  5104 
       
  5105 				if ((y + s.vp_offset_y + h) > my)
       
  5106 					y = Math.max(0, (my - s.vp_offset_y) - h);
       
  5107 			}
       
  5108 
       
  5109 			DOM.setStyles(co, {left : x , top : y});
       
  5110 			t.element.update();
       
  5111 
       
  5112 			t.isMenuVisible = 1;
       
  5113 			t.mouseClickFunc = Event.add(co, 'click', function(e) {
       
  5114 				var m;
       
  5115 
       
  5116 				e = e.target;
       
  5117 
       
  5118 				if (e && (e = DOM.getParent(e, 'TR')) && !DOM.hasClass(e, cp + 'ItemSub')) {
       
  5119 					m = t.items[e.id];
       
  5120 
       
  5121 					if (m.isDisabled())
       
  5122 						return;
       
  5123 
       
  5124 					dm = t;
       
  5125 
       
  5126 					while (dm) {
       
  5127 						if (dm.hideMenu)
       
  5128 							dm.hideMenu();
       
  5129 
       
  5130 						dm = dm.settings.parent;
       
  5131 					}
       
  5132 
       
  5133 					if (m.settings.onclick)
       
  5134 						m.settings.onclick(e);
       
  5135 
       
  5136 					return Event.cancel(e); // Cancel to fix onbeforeunload problem
       
  5137 				}
       
  5138 			});
       
  5139 
       
  5140 			if (t.hasMenus()) {
       
  5141 				t.mouseOverFunc = Event.add(co, 'mouseover', function(e) {
       
  5142 					var m, r, mi;
       
  5143 
       
  5144 					e = e.target;
       
  5145 					if (e && (e = DOM.getParent(e, 'TR'))) {
       
  5146 						m = t.items[e.id];
       
  5147 
       
  5148 						if (t.lastMenu)
       
  5149 							t.lastMenu.collapse(1);
       
  5150 
       
  5151 						if (m.isDisabled())
       
  5152 							return;
       
  5153 
       
  5154 						if (e && DOM.hasClass(e, cp + 'ItemSub')) {
       
  5155 							//p = DOM.getPos(s.container);
       
  5156 							r = DOM.getRect(e);
       
  5157 							m.showMenu((r.x + r.w - ot), r.y - ot, r.x);
       
  5158 							t.lastMenu = m;
       
  5159 							DOM.addClass(DOM.get(m.id).firstChild, cp + 'ItemActive');
       
  5160 						}
       
  5161 					}
       
  5162 				});
       
  5163 			}
       
  5164 
       
  5165 			t.onShowMenu.dispatch(t);
       
  5166 
       
  5167 			if (s.keyboard_focus) {
       
  5168 				Event.add(co, 'keydown', t._keyHandler, t);
       
  5169 				DOM.select('a', 'menu_' + t.id)[0].focus(); // Select first link
       
  5170 				t._focusIdx = 0;
       
  5171 			}
       
  5172 		},
       
  5173 
       
  5174 		hideMenu : function(c) {
       
  5175 			var t = this, co = DOM.get('menu_' + t.id), e;
       
  5176 
       
  5177 			if (!t.isMenuVisible)
       
  5178 				return;
       
  5179 
       
  5180 			Event.remove(co, 'mouseover', t.mouseOverFunc);
       
  5181 			Event.remove(co, 'click', t.mouseClickFunc);
       
  5182 			Event.remove(co, 'keydown', t._keyHandler);
       
  5183 			DOM.hide(co);
       
  5184 			t.isMenuVisible = 0;
       
  5185 
       
  5186 			if (!c)
       
  5187 				t.collapse(1);
       
  5188 
       
  5189 			if (t.element)
       
  5190 				t.element.hide();
       
  5191 
       
  5192 			if (e = DOM.get(t.id))
       
  5193 				DOM.removeClass(e.firstChild, t.classPrefix + 'ItemActive');
       
  5194 
       
  5195 			t.onHideMenu.dispatch(t);
       
  5196 		},
       
  5197 
       
  5198 		add : function(o) {
       
  5199 			var t = this, co;
       
  5200 
       
  5201 			o = t.parent(o);
       
  5202 
       
  5203 			if (t.isRendered && (co = DOM.get('menu_' + t.id)))
       
  5204 				t._add(DOM.select('tbody', co)[0], o);
       
  5205 
       
  5206 			return o;
       
  5207 		},
       
  5208 
       
  5209 		collapse : function(d) {
       
  5210 			this.parent(d);
       
  5211 			this.hideMenu(1);
       
  5212 		},
       
  5213 
       
  5214 		remove : function(o) {
       
  5215 			DOM.remove(o.id);
       
  5216 			this.destroy();
       
  5217 
       
  5218 			return this.parent(o);
       
  5219 		},
       
  5220 
       
  5221 		destroy : function() {
       
  5222 			var t = this, co = DOM.get('menu_' + t.id);
       
  5223 
       
  5224 			Event.remove(co, 'mouseover', t.mouseOverFunc);
       
  5225 			Event.remove(co, 'click', t.mouseClickFunc);
       
  5226 
       
  5227 			if (t.element)
       
  5228 				t.element.remove();
       
  5229 
       
  5230 			DOM.remove(co);
       
  5231 		},
       
  5232 
       
  5233 		renderNode : function() {
       
  5234 			var t = this, s = t.settings, n, tb, co, w;
       
  5235 
       
  5236 			w = DOM.create('div', {id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:200000'});
       
  5237 			co = DOM.add(w, 'div', {id : 'menu_' + t.id + '_co', 'class' : t.classPrefix + (s['class'] ? ' ' + s['class'] : '')});
       
  5238 			t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
       
  5239 
       
  5240 			if (s.menu_line)
       
  5241 				DOM.add(co, 'span', {'class' : t.classPrefix + 'Line'});
       
  5242 
       
  5243 //			n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'});
       
  5244 			n = DOM.add(co, 'table', {id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0});
       
  5245 			tb = DOM.add(n, 'tbody');
       
  5246 
       
  5247 			each(t.items, function(o) {
       
  5248 				t._add(tb, o);
       
  5249 			});
       
  5250 
       
  5251 			t.rendered = true;
       
  5252 
       
  5253 			return w;
       
  5254 		},
       
  5255 
       
  5256 		// Internal functions
       
  5257 
       
  5258 		_keyHandler : function(e) {
       
  5259 			var t = this, kc = e.keyCode;
       
  5260 
       
  5261 			function focus(d) {
       
  5262 				var i = t._focusIdx + d, e = DOM.select('a', 'menu_' + t.id)[i];
       
  5263 
       
  5264 				if (e) {
       
  5265 					t._focusIdx = i;
       
  5266 					e.focus();
       
  5267 				}
       
  5268 			};
       
  5269 
       
  5270 			switch (kc) {
       
  5271 				case 38:
       
  5272 					focus(-1); // Select first link
       
  5273 					return;
       
  5274 
       
  5275 				case 40:
       
  5276 					focus(1);
       
  5277 					return;
       
  5278 
       
  5279 				case 13:
       
  5280 					return;
       
  5281 
       
  5282 				case 27:
       
  5283 					return this.hideMenu();
       
  5284 			}
       
  5285 		},
       
  5286 
       
  5287 		_add : function(tb, o) {
       
  5288 			var n, s = o.settings, a, ro, it, cp = this.classPrefix;
       
  5289 
       
  5290 			if (s.separator) {
       
  5291 				ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'ItemSeparator'});
       
  5292 				DOM.add(ro, 'td', {'class' : cp + 'ItemSeparator'});
       
  5293 
       
  5294 				if (n = ro.previousSibling)
       
  5295 					DOM.addClass(n, 'mceLast');
       
  5296 
       
  5297 				return;
       
  5298 			}
       
  5299 
       
  5300 			n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : cp + 'Item ' + cp + 'ItemEnabled'});
       
  5301 			n = it = DOM.add(n, 'td');
       
  5302 			n = a = DOM.add(n, 'a', {href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'});
       
  5303 
       
  5304 			DOM.addClass(it, s['class']);
       
  5305 //			n = DOM.add(n, 'span', {'class' : 'item'});
       
  5306 			DOM.add(n, 'span', {'class' : 'mceIcon' + (s.icon ? ' mce_' + s.icon : '')});
       
  5307 			n = DOM.add(n, s.element || 'span', {'class' : 'mceText', title : o.settings.title}, o.settings.title);
       
  5308 
       
  5309 			if (o.settings.style)
       
  5310 				DOM.setAttrib(n, 'style', o.settings.style);
       
  5311 
       
  5312 			if (tb.childNodes.length == 1)
       
  5313 				DOM.addClass(ro, 'mceFirst');
       
  5314 
       
  5315 			if ((n = ro.previousSibling) && DOM.hasClass(n, cp + 'ItemSeparator'))
       
  5316 				DOM.addClass(ro, 'mceFirst');
       
  5317 
       
  5318 			if (o.collapse)
       
  5319 				DOM.addClass(ro, cp + 'ItemSub');
       
  5320 
       
  5321 			if (n = ro.previousSibling)
       
  5322 				DOM.removeClass(n, 'mceLast');
       
  5323 
       
  5324 			DOM.addClass(ro, 'mceLast');
       
  5325 		}
       
  5326 
       
  5327 		});
       
  5328 })();
       
  5329 /* file:jscripts/tiny_mce/classes/ui/Button.js */
       
  5330 
       
  5331 (function() {
       
  5332 	var DOM = tinymce.DOM;
       
  5333 
       
  5334 	tinymce.create('tinymce.ui.Button:tinymce.ui.Control', {
       
  5335 		Button : function(id, s) {
       
  5336 			this.parent(id, s);
       
  5337 			this.classPrefix = 'mceButton';
       
  5338 		},
       
  5339 
       
  5340 		renderHTML : function() {
       
  5341 			var cp = this.classPrefix, s = this.settings, h, l;
       
  5342 
       
  5343 			l = DOM.encode(s.label || '');
       
  5344 			h = '<a id="' + this.id + '" href="javascript:;" class="' + cp + ' ' + cp + 'Enabled ' + s['class'] + (l ? ' ' + cp + 'Labeled' : '') +'" onmousedown="return false;" onclick="return false;" title="' + DOM.encode(s.title) + '">';
       
  5345 
       
  5346 			if (s.image)
       
  5347 				h += '<img class="mceIcon" src="' + s.image + '" />' + l + '</a>';
       
  5348 			else
       
  5349 				h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '') + '</a>';
       
  5350 
       
  5351 			return h;
       
  5352 		},
       
  5353 
       
  5354 		postRender : function() {
       
  5355 			var t = this, s = t.settings;
       
  5356 
       
  5357 			tinymce.dom.Event.add(t.id, 'click', function(e) {
       
  5358 				if (!t.isDisabled())
       
  5359 					return s.onclick.call(s.scope, e);
       
  5360 			});
       
  5361 		}
       
  5362 
       
  5363 		});
       
  5364 })();
       
  5365 
       
  5366 /* file:jscripts/tiny_mce/classes/ui/ListBox.js */
       
  5367 
       
  5368 (function() {
       
  5369 	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
       
  5370 
       
  5371 	tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', {
       
  5372 		ListBox : function(id, s) {
       
  5373 			var t = this;
       
  5374 
       
  5375 			t.parent(id, s);
       
  5376 			t.items = [];
       
  5377 			t.onChange = new Dispatcher(t);
       
  5378 			t.onPostRender = new Dispatcher(t);
       
  5379 			t.onAdd = new Dispatcher(t);
       
  5380 			t.onRenderMenu = new tinymce.util.Dispatcher(this);
       
  5381 			t.classPrefix = 'mceListBox';
       
  5382 		},
       
  5383 
       
  5384 		select : function(v) {
       
  5385 			var t = this, e, fv;
       
  5386 
       
  5387 			// Do we need to do something?
       
  5388 			if (v != t.selectedValue) {
       
  5389 				e = DOM.get(t.id + '_text');
       
  5390 				t.selectedValue = v;
       
  5391 
       
  5392 				// Find item
       
  5393 				each(t.items, function(o) {
       
  5394 					if (o.value == v) {
       
  5395 						DOM.setHTML(e, DOM.encode(o.title));
       
  5396 						fv = 1;
       
  5397 						return false;
       
  5398 					}
       
  5399 				});
       
  5400 
       
  5401 				// If no item was found then present title
       
  5402 				if (!fv) {
       
  5403 					DOM.setHTML(e, DOM.encode(t.settings.title));
       
  5404 					DOM.addClass(e, 'mceTitle');
       
  5405 					e = 0;
       
  5406 					return;
       
  5407 				} else
       
  5408 					DOM.removeClass(e, 'mceTitle');
       
  5409 			}
       
  5410 
       
  5411 			e = 0;
       
  5412 		},
       
  5413 
       
  5414 		add : function(n, v, o) {
       
  5415 			var t = this;
       
  5416 
       
  5417 			o = o || {};
       
  5418 			o = tinymce.extend(o, {
       
  5419 				title : n,
       
  5420 				value : v
       
  5421 			});
       
  5422 
       
  5423 			t.items.push(o);
       
  5424 			t.onAdd.dispatch(t, o);
       
  5425 		},
       
  5426 
       
  5427 		getLength : function() {
       
  5428 			return this.items.length;
       
  5429 		},
       
  5430 
       
  5431 		renderHTML : function() {
       
  5432 			var h = '', t = this, s = t.settings, cp = t.classPrefix;
       
  5433 
       
  5434 			h = '<table id="' + t.id + '" cellpadding="0" cellspacing="0" class="' + cp + ' ' + cp + 'Enabled' + (s['class'] ? (' ' + s['class']) : '') + '"><tbody><tr>';
       
  5435 			h += '<td>' + DOM.createHTML('a', {id : t.id + '_text', href : 'javascript:;', 'class' : 'mceText', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + '</td>';
       
  5436 			h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', tabindex : -1, href : 'javascript:;', 'class' : 'mceOpen', onclick : "return false;", onmousedown : 'return false;'}, '<span></span>') + '</td>';
       
  5437 			h += '</tr></tbody></table>';
       
  5438 
       
  5439 			return h;
       
  5440 		},
       
  5441 
       
  5442 		showMenu : function() {
       
  5443 			var t = this, p1, p2, e = DOM.get(this.id), m;
       
  5444 
       
  5445 			if (t.isDisabled() || t.items.length == 0)
       
  5446 				return;
       
  5447 
       
  5448 			if (t.menu && t.menu.isMenuVisible)
       
  5449 				return t.hideMenu();
       
  5450 
       
  5451 			if (!t.isMenuRendered) {
       
  5452 				t.renderMenu();
       
  5453 				t.isMenuRendered = true;
       
  5454 			}
       
  5455 
       
  5456 			p1 = DOM.getPos(this.settings.menu_container);
       
  5457 			p2 = DOM.getPos(e);
       
  5458 
       
  5459 			m = t.menu;
       
  5460 			m.settings.offset_x = p2.x;
       
  5461 			m.settings.offset_y = p2.y;
       
  5462 			m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus
       
  5463 
       
  5464 			// Select in menu
       
  5465 			if (t.oldID)
       
  5466 				m.items[t.oldID].setSelected(0);
       
  5467 
       
  5468 			each(t.items, function(o) {
       
  5469 				if (o.value === t.selectedValue) {
       
  5470 					m.items[o.id].setSelected(1);
       
  5471 					t.oldID = o.id;
       
  5472 				}
       
  5473 			});
       
  5474 
       
  5475 			m.showMenu(0, e.clientHeight);
       
  5476 
       
  5477 			Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
       
  5478 			DOM.addClass(t.id, t.classPrefix + 'Selected');
       
  5479 
       
  5480 			//DOM.get(t.id + '_text').focus();
       
  5481 		},
       
  5482 
       
  5483 		hideMenu : function(e) {
       
  5484 			var t = this;
       
  5485 
       
  5486 			// Prevent double toogles by canceling the mouse click event to the button
       
  5487 			if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open'))
       
  5488 				return;
       
  5489 
       
  5490 			if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
       
  5491 				DOM.removeClass(t.id, t.classPrefix + 'Selected');
       
  5492 				Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
       
  5493 
       
  5494 				if (t.menu)
       
  5495 					t.menu.hideMenu();
       
  5496 			}
       
  5497 		},
       
  5498 
       
  5499 		renderMenu : function() {
       
  5500 			var t = this, m;
       
  5501 
       
  5502 			m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
       
  5503 				menu_line : 1,
       
  5504 				'class' : t.classPrefix + 'Menu mceNoIcons',
       
  5505 				max_width : 150,
       
  5506 				max_height : 150
       
  5507 			});
       
  5508 
       
  5509 			m.onHideMenu.add(t.hideMenu, t);
       
  5510 
       
  5511 			m.add({
       
  5512 				title : t.settings.title,
       
  5513 				'class' : 'mceMenuItemTitle',
       
  5514 				onclick : function() {
       
  5515 					if (t.settings.onselect('') !== false)
       
  5516 						t.select(''); // Must be runned after
       
  5517 				}
       
  5518 			});
       
  5519 
       
  5520 			each(t.items, function(o) {
       
  5521 				o.id = DOM.uniqueId();
       
  5522 				o.onclick = function() {
       
  5523 					if (t.settings.onselect(o.value) !== false)
       
  5524 						t.select(o.value); // Must be runned after
       
  5525 				};
       
  5526 
       
  5527 				m.add(o);
       
  5528 			});
       
  5529 
       
  5530 			t.onRenderMenu.dispatch(t, m);
       
  5531 			t.menu = m;
       
  5532 		},
       
  5533 
       
  5534 		postRender : function() {
       
  5535 			var t = this, cp = t.classPrefix;
       
  5536 
       
  5537 			Event.add(t.id, 'click', t.showMenu, t);
       
  5538 			Event.add(t.id + '_text', 'focus', function(e) {
       
  5539 				if (!t._focused) {
       
  5540 					t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) {
       
  5541 						var idx = -1, v, kc = e.keyCode;
       
  5542 
       
  5543 						// Find current index
       
  5544 						each(t.items, function(v, i) {
       
  5545 							if (t.selectedValue == v.value)
       
  5546 								idx = i;
       
  5547 						});
       
  5548 
       
  5549 						// Move up/down
       
  5550 						if (kc == 38)
       
  5551 							v = t.items[idx - 1];
       
  5552 						else if (kc == 40)
       
  5553 							v = t.items[idx + 1];
       
  5554 						else if (kc == 13) {
       
  5555 							// Fake select on enter
       
  5556 							v = t.selectedValue;
       
  5557 							t.selectedValue = null; // Needs to be null to fake change
       
  5558 							t.settings.onselect(v);
       
  5559 							return Event.cancel(e);
       
  5560 						}
       
  5561 
       
  5562 						if (v) {
       
  5563 							t.hideMenu();
       
  5564 							t.select(v.value);
       
  5565 						}
       
  5566 					});
       
  5567 				}
       
  5568 
       
  5569 				t._focused = 1;
       
  5570 			});
       
  5571 			Event.add(t.id + '_text', 'blur', function() {Event.remove(t.id + '_text', 'keydown', t.keyDownHandler); t._focused = 0;});
       
  5572 
       
  5573 			// Old IE doesn't have hover on all elements
       
  5574 			if (tinymce.isIE6 || !DOM.boxModel) {
       
  5575 				Event.add(t.id, 'mouseover', function() {
       
  5576 					if (!DOM.hasClass(t.id, cp + 'Disabled'))
       
  5577 						DOM.addClass(t.id, cp + 'Hover');
       
  5578 				});
       
  5579 
       
  5580 				Event.add(t.id, 'mouseout', function() {
       
  5581 					if (!DOM.hasClass(t.id, cp + 'Disabled'))
       
  5582 						DOM.removeClass(t.id, cp + 'Hover');
       
  5583 				});
       
  5584 			}
       
  5585 
       
  5586 			t.onPostRender.dispatch(t, DOM.get(t.id));
       
  5587 		},
       
  5588 
       
  5589 		destroy : function() {
       
  5590 			this.parent();
       
  5591 
       
  5592 			Event.clear(this.id + '_text');
       
  5593 		}
       
  5594 
       
  5595 		});
       
  5596 })();
       
  5597 /* file:jscripts/tiny_mce/classes/ui/NativeListBox.js */
       
  5598 
       
  5599 (function() {
       
  5600 	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
       
  5601 
       
  5602 	tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', {
       
  5603 		NativeListBox : function(id, s) {
       
  5604 			this.parent(id, s);
       
  5605 			this.classPrefix = 'mceNativeListBox';
       
  5606 		},
       
  5607 
       
  5608 		setDisabled : function(s) {
       
  5609 			DOM.get(this.id).disabled = s;
       
  5610 		},
       
  5611 
       
  5612 		isDisabled : function() {
       
  5613 			return DOM.get(this.id).disabled;
       
  5614 		},
       
  5615 
       
  5616 		select : function(v) {
       
  5617 			var e = DOM.get(this.id), ol = e.options;
       
  5618 
       
  5619 			v = '' + (v || '');
       
  5620 
       
  5621 			e.selectedIndex = 0;
       
  5622 			each(ol, function(o, i) {
       
  5623 				if (o.value == v) {
       
  5624 					e.selectedIndex = i;
       
  5625 					return false;
       
  5626 				}
       
  5627 			});
       
  5628 		},
       
  5629 
       
  5630 		add : function(n, v, a) {
       
  5631 			var o, t = this;
       
  5632 
       
  5633 			a = a || {};
       
  5634 			a.value = v;
       
  5635 
       
  5636 			if (t.isRendered())
       
  5637 				DOM.add(DOM.get(this.id), 'option', a, n);
       
  5638 
       
  5639 			o = {
       
  5640 				title : n,
       
  5641 				value : v,
       
  5642 				attribs : a
       
  5643 			};
       
  5644 
       
  5645 			t.items.push(o);
       
  5646 			t.onAdd.dispatch(t, o);
       
  5647 		},
       
  5648 
       
  5649 		getLength : function() {
       
  5650 			return DOM.get(this.id).options.length - 1;
       
  5651 		},
       
  5652 
       
  5653 		renderHTML : function() {
       
  5654 			var h, t = this;
       
  5655 
       
  5656 			h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --');
       
  5657 
       
  5658 			each(t.items, function(it) {
       
  5659 				h += DOM.createHTML('option', {value : it.value}, it.title);
       
  5660 			});
       
  5661 
       
  5662 			h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox'}, h);
       
  5663 
       
  5664 			return h;
       
  5665 		},
       
  5666 
       
  5667 		postRender : function() {
       
  5668 			var t = this, ch;
       
  5669 
       
  5670 			t.rendered = true;
       
  5671 
       
  5672 			function onChange(e) {
       
  5673 				var v = e.target.options[e.target.selectedIndex].value;
       
  5674 
       
  5675 				t.onChange.dispatch(t, v);
       
  5676 
       
  5677 				if (t.settings.onselect)
       
  5678 					t.settings.onselect(v);
       
  5679 			};
       
  5680 
       
  5681 			Event.add(t.id, 'change', onChange);
       
  5682 
       
  5683 			// Accessibility keyhandler
       
  5684 			Event.add(t.id, 'keydown', function(e) {
       
  5685 				var bf;
       
  5686 
       
  5687 				Event.remove(t.id, 'change', ch);
       
  5688 
       
  5689 				bf = Event.add(t.id, 'blur', function() {
       
  5690 					Event.add(t.id, 'change', onChange);
       
  5691 					Event.remove(t.id, 'blur', bf);
       
  5692 				});
       
  5693 
       
  5694 				if (e.keyCode == 13 || e.keyCode == 32) {
       
  5695 					onChange(e);
       
  5696 					return Event.cancel(e);
       
  5697 				}
       
  5698 			});
       
  5699 
       
  5700 			t.onPostRender.dispatch(t, DOM.get(t.id));
       
  5701 		}
       
  5702 
       
  5703 		});
       
  5704 })();
       
  5705 /* file:jscripts/tiny_mce/classes/ui/MenuButton.js */
       
  5706 
       
  5707 (function() {
       
  5708 	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
       
  5709 
       
  5710 	tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', {
       
  5711 		MenuButton : function(id, s) {
       
  5712 			this.parent(id, s);
       
  5713 			this.onRenderMenu = new tinymce.util.Dispatcher(this);
       
  5714 			s.menu_container = s.menu_container || DOM.doc.body;
       
  5715 		},
       
  5716 
       
  5717 		showMenu : function() {
       
  5718 			var t = this, p1, p2, e = DOM.get(t.id), m;
       
  5719 
       
  5720 			if (t.isDisabled())
       
  5721 				return;
       
  5722 
       
  5723 			if (!t.isMenuRendered) {
       
  5724 				t.renderMenu();
       
  5725 				t.isMenuRendered = true;
       
  5726 			}
       
  5727 
       
  5728 			if (t.isMenuVisible)
       
  5729 				return t.hideMenu();
       
  5730 
       
  5731 			p1 = DOM.getPos(t.settings.menu_container);
       
  5732 			p2 = DOM.getPos(e);
       
  5733 
       
  5734 			m = t.menu;
       
  5735 			m.settings.offset_x = p2.x;
       
  5736 			m.settings.offset_y = p2.y;
       
  5737 			m.settings.vp_offset_x = p2.x;
       
  5738 			m.settings.vp_offset_y = p2.y;
       
  5739 			m.settings.keyboard_focus = t._focused;
       
  5740 			m.showMenu(0, e.clientHeight);
       
  5741 
       
  5742 			Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
       
  5743 			t.setState('Selected', 1);
       
  5744 
       
  5745 			t.isMenuVisible = 1;
       
  5746 		},
       
  5747 
       
  5748 		renderMenu : function() {
       
  5749 			var t = this, m;
       
  5750 
       
  5751 			m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
       
  5752 				menu_line : 1,
       
  5753 				'class' : this.classPrefix + 'Menu',
       
  5754 				icons : t.settings.icons
       
  5755 			});
       
  5756 
       
  5757 			m.onHideMenu.add(t.hideMenu, t);
       
  5758 
       
  5759 			t.onRenderMenu.dispatch(t, m);
       
  5760 			t.menu = m;
       
  5761 		},
       
  5762 
       
  5763 		hideMenu : function(e) {
       
  5764 			var t = this;
       
  5765 
       
  5766 			// Prevent double toogles by canceling the mouse click event to the button
       
  5767 			if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';}))
       
  5768 				return;
       
  5769 
       
  5770 			if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
       
  5771 				t.setState('Selected', 0);
       
  5772 				Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
       
  5773 				if (t.menu)
       
  5774 					t.menu.hideMenu();
       
  5775 			}
       
  5776 
       
  5777 			t.isMenuVisible = 0;
       
  5778 		},
       
  5779 
       
  5780 		postRender : function() {
       
  5781 			var t = this, s = t.settings;
       
  5782 
       
  5783 			Event.add(t.id, 'click', function() {
       
  5784 				if (!t.isDisabled()) {
       
  5785 					if (s.onclick)
       
  5786 						s.onclick(t.value);
       
  5787 
       
  5788 					t.showMenu();
       
  5789 				}
       
  5790 			});
       
  5791 		}
       
  5792 
       
  5793 		});
       
  5794 })();
       
  5795 
       
  5796 /* file:jscripts/tiny_mce/classes/ui/SplitButton.js */
       
  5797 
       
  5798 (function() {
       
  5799 	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
       
  5800 
       
  5801 	tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', {
       
  5802 		SplitButton : function(id, s) {
       
  5803 			this.parent(id, s);
       
  5804 			this.classPrefix = 'mceSplitButton';
       
  5805 		},
       
  5806 
       
  5807 		renderHTML : function() {
       
  5808 			var h, t = this, s = t.settings, h1;
       
  5809 
       
  5810 			h = '<tbody><tr>';
       
  5811 
       
  5812 			if (s.image)
       
  5813 				h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'mceAction ' + s['class']});
       
  5814 			else
       
  5815 				h1 = DOM.createHTML('span', {'class' : 'mceAction ' + s['class']}, '');
       
  5816 
       
  5817 			h += '<td>' + DOM.createHTML('a', {id : t.id + '_action', href : 'javascript:;', 'class' : 'mceAction ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
       
  5818 	
       
  5819 			h1 = DOM.createHTML('span', {'class' : 'mceOpen ' + s['class']});
       
  5820 			h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'mceOpen ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
       
  5821 
       
  5822 			h += '</tr></tbody>';
       
  5823 
       
  5824 			return DOM.createHTML('table', {id : t.id, 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', onmousedown : 'return false;', title : s.title}, h);
       
  5825 		},
       
  5826 
       
  5827 		postRender : function() {
       
  5828 			var t = this, s = t.settings;
       
  5829 
       
  5830 			if (s.onclick) {
       
  5831 				Event.add(t.id + '_action', 'click', function() {
       
  5832 					if (!t.isDisabled())
       
  5833 						s.onclick(t.value);
       
  5834 				});
       
  5835 			}
       
  5836 
       
  5837 			Event.add(t.id + '_open', 'click', t.showMenu, t);
       
  5838 			Event.add(t.id + '_open', 'focus', function() {t._focused = 1;});
       
  5839 			Event.add(t.id + '_open', 'blur', function() {t._focused = 0;});
       
  5840 
       
  5841 			// Old IE doesn't have hover on all elements
       
  5842 			if (tinymce.isIE6 || !DOM.boxModel) {
       
  5843 				Event.add(t.id, 'mouseover', function() {
       
  5844 					if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
       
  5845 						DOM.addClass(t.id, 'mceSplitButtonHover');
       
  5846 				});
       
  5847 
       
  5848 				Event.add(t.id, 'mouseout', function() {
       
  5849 					if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
       
  5850 						DOM.removeClass(t.id, 'mceSplitButtonHover');
       
  5851 				});
       
  5852 			}
       
  5853 		},
       
  5854 
       
  5855 		destroy : function() {
       
  5856 			this.parent();
       
  5857 
       
  5858 			Event.clear(this.id + '_action');
       
  5859 			Event.clear(this.id + '_open');
       
  5860 		}
       
  5861 
       
  5862 		});
       
  5863 })();
       
  5864 
       
  5865 /* file:jscripts/tiny_mce/classes/ui/ColorSplitButton.js */
       
  5866 
       
  5867 (function() {
       
  5868 	var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each;
       
  5869 
       
  5870 	tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', {
       
  5871 		ColorSplitButton : function(id, s) {
       
  5872 			var t = this;
       
  5873 
       
  5874 			t.parent(id, s);
       
  5875 
       
  5876 			t.settings = s = tinymce.extend({
       
  5877 				colors : '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF',
       
  5878 				grid_width : 8,
       
  5879 				default_color : '#888888'
       
  5880 			}, t.settings);
       
  5881 
       
  5882 			t.onShowMenu = new tinymce.util.Dispatcher(t);
       
  5883 			t.onHideMenu = new tinymce.util.Dispatcher(t);
       
  5884 
       
  5885 			t.value = s.default_color;
       
  5886 		},
       
  5887 
       
  5888 		showMenu : function() {
       
  5889 			var t = this, r, p, e, p2;
       
  5890 
       
  5891 			if (t.isDisabled())
       
  5892 				return;
       
  5893 
       
  5894 			if (!t.isMenuRendered) {
       
  5895 				t.renderMenu();
       
  5896 				t.isMenuRendered = true;
       
  5897 			}
       
  5898 
       
  5899 			if (t.isMenuVisible)
       
  5900 				return t.hideMenu();
       
  5901 
       
  5902 			e = DOM.get(t.id);
       
  5903 			DOM.show(t.id + '_menu');
       
  5904 			DOM.addClass(e, 'mceSplitButtonSelected');
       
  5905 			p2 = DOM.getPos(e);
       
  5906 			DOM.setStyles(t.id + '_menu', {
       
  5907 				left : p2.x,
       
  5908 				top : p2.y + e.clientHeight,
       
  5909 				zIndex : 200000
       
  5910 			});
       
  5911 			e = 0;
       
  5912 
       
  5913 			Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
       
  5914 
       
  5915 			if (t._focused) {
       
  5916 				t._keyHandler = Event.add(t.id + '_menu', 'keydown', function(e) {
       
  5917 					if (e.keyCode == 27)
       
  5918 						t.hideMenu();
       
  5919 				});
       
  5920 
       
  5921 				DOM.select('a', t.id + '_menu')[0].focus(); // Select first link
       
  5922 			}
       
  5923 
       
  5924 			t.onShowMenu.dispatch(t);
       
  5925 
       
  5926 			t.isMenuVisible = 1;
       
  5927 		},
       
  5928 
       
  5929 		hideMenu : function(e) {
       
  5930 			var t = this;
       
  5931 
       
  5932 			// Prevent double toogles by canceling the mouse click event to the button
       
  5933 			if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))
       
  5934 				return;
       
  5935 
       
  5936 			if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceSplitButtonMenu');})) {
       
  5937 				DOM.removeClass(t.id, 'mceSplitButtonSelected');
       
  5938 				Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
       
  5939 				Event.remove(t.id + '_menu', 'keydown', t._keyHandler);
       
  5940 				DOM.hide(t.id + '_menu');
       
  5941 			}
       
  5942 
       
  5943 			t.onHideMenu.dispatch(t);
       
  5944 
       
  5945 			t.isMenuVisible = 0;
       
  5946 		},
       
  5947 
       
  5948 		renderMenu : function() {
       
  5949 			var t = this, m, i = 0, s = t.settings, n, tb, tr, w;
       
  5950 
       
  5951 			w = DOM.add(s.menu_container, 'div', {id : t.id + '_menu', 'class' : s['menu_class'] + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'});
       
  5952 			m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'});
       
  5953 			DOM.add(m, 'span', {'class' : 'mceMenuLine'});
       
  5954 
       
  5955 			n = DOM.add(m, 'table', {'class' : 'mceColorSplitMenu'});
       
  5956 			tb = DOM.add(n, 'tbody');
       
  5957 
       
  5958 			// Generate color grid
       
  5959 			i = 0;
       
  5960 			each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) {
       
  5961 				c = c.replace(/^#/, '');
       
  5962 
       
  5963 				if (!i--) {
       
  5964 					tr = DOM.add(tb, 'tr');
       
  5965 					i = s.grid_width - 1;
       
  5966 				}
       
  5967 
       
  5968 				n = DOM.add(tr, 'td');
       
  5969 
       
  5970 				n = DOM.add(n, 'a', {
       
  5971 					href : 'javascript:;',
       
  5972 					style : {
       
  5973 						backgroundColor : '#' + c
       
  5974 					},
       
  5975 					mce_color : '#' + c
       
  5976 				});
       
  5977 			});
       
  5978 
       
  5979 			if (s.more_colors_func) {
       
  5980 				n = DOM.add(tb, 'tr');
       
  5981 				n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'mceMoreColors'});
       
  5982 				n = DOM.add(n, 'a', {id : t.id + '_more', href : 'javascript:;', onclick : 'return false;', 'class' : 'mceMoreColors'}, s.more_colors_title);
       
  5983 
       
  5984 				Event.add(n, 'click', function(e) {
       
  5985 					s.more_colors_func.call(s.more_colors_scope || this);
       
  5986 					return Event.cancel(e); // Cancel to fix onbeforeunload problem
       
  5987 				});
       
  5988 			}
       
  5989 
       
  5990 			DOM.addClass(m, 'mceColorSplitMenu');
       
  5991 
       
  5992 			Event.add(t.id + '_menu', 'click', function(e) {
       
  5993 				var c;
       
  5994 
       
  5995 				e = e.target;
       
  5996 
       
  5997 				if (e.nodeName == 'A' && (c = e.getAttribute('mce_color')))
       
  5998 					t.setColor(c);
       
  5999 
       
  6000 				return Event.cancel(e); // Prevent IE auto save warning
       
  6001 			});
       
  6002 
       
  6003 			return w;
       
  6004 		},
       
  6005 
       
  6006 		setColor : function(c) {
       
  6007 			var t = this;
       
  6008 
       
  6009 			DOM.setStyle(t.id + '_preview', 'backgroundColor', c);
       
  6010 
       
  6011 			t.value = c;
       
  6012 			t.hideMenu();
       
  6013 			t.settings.onselect(c);
       
  6014 		},
       
  6015 
       
  6016 		postRender : function() {
       
  6017 			var t = this, id = t.id;
       
  6018 
       
  6019 			t.parent();
       
  6020 			DOM.add(id + '_action', 'div', {id : id + '_preview', 'class' : 'mceColorPreview'});
       
  6021 		},
       
  6022 
       
  6023 		destroy : function() {
       
  6024 			this.parent();
       
  6025 
       
  6026 			Event.clear(this.id + '_menu');
       
  6027 			Event.clear(this.id + '_more');
       
  6028 			DOM.remove(this.id + '_menu');
       
  6029 		}
       
  6030 
       
  6031 		});
       
  6032 })();
       
  6033 
       
  6034 /* file:jscripts/tiny_mce/classes/ui/Toolbar.js */
       
  6035 
       
  6036 tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
       
  6037 	renderHTML : function() {
       
  6038 		var t = this, h = '', c, co, dom = tinymce.DOM, s = t.settings, i, pr, nx, cl;
       
  6039 
       
  6040 		cl = t.controls;
       
  6041 		for (i=0; i<cl.length; i++) {
       
  6042 			// Get current control, prev control, next control and if the control is a list box or not
       
  6043 			co = cl[i];
       
  6044 			pr = cl[i - 1];
       
  6045 			nx = cl[i + 1];
       
  6046 
       
  6047 			// Add toolbar start
       
  6048 			if (i === 0) {
       
  6049 				c = 'mceToolbarStart';
       
  6050 
       
  6051 				if (co.Button)
       
  6052 					c += ' mceToolbarStartButton';
       
  6053 				else if (co.SplitButton)
       
  6054 					c += ' mceToolbarStartSplitButton';
       
  6055 				else if (co.ListBox)
       
  6056 					c += ' mceToolbarStartListBox';
       
  6057 
       
  6058 				h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));
       
  6059 			}
       
  6060 
       
  6061 			// Add toolbar end before list box and after the previous button
       
  6062 			// This is to fix the o2k7 editor skins
       
  6063 			if (pr && co.ListBox) {
       
  6064 				if (pr.Button || pr.SplitButton)
       
  6065 					h += dom.createHTML('td', {'class' : 'mceToolbarEnd'}, dom.createHTML('span', null, '<!-- IE -->'));
       
  6066 			}
       
  6067 
       
  6068 			// Render control HTML
       
  6069 
       
  6070 			// IE 8 quick fix, needed to propertly generate a hit area for anchors
       
  6071 			if (dom.stdMode)
       
  6072 				h += '<td style="position: relative">' + co.renderHTML() + '</td>';
       
  6073 			else
       
  6074 				h += '<td>' + co.renderHTML() + '</td>';
       
  6075 
       
  6076 			// Add toolbar start after list box and before the next button
       
  6077 			// This is to fix the o2k7 editor skins
       
  6078 			if (nx && co.ListBox) {
       
  6079 				if (nx.Button || nx.SplitButton)
       
  6080 					h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '<!-- IE -->'));
       
  6081 			}
       
  6082 		}
       
  6083 
       
  6084 		c = 'mceToolbarEnd';
       
  6085 
       
  6086 		if (co.Button)
       
  6087 			c += ' mceToolbarEndButton';
       
  6088 		else if (co.SplitButton)
       
  6089 			c += ' mceToolbarEndSplitButton';
       
  6090 		else if (co.ListBox)
       
  6091 			c += ' mceToolbarEndListBox';
       
  6092 
       
  6093 		h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));
       
  6094 
       
  6095 		return dom.createHTML('table', {id : t.id, 'class' : 'mceToolbar' + (s['class'] ? ' ' + s['class'] : ''), cellpadding : '0', cellspacing : '0', align : t.settings.align || ''}, '<tbody><tr>' + h + '</tr></tbody>');
       
  6096 	}
       
  6097 
       
  6098 	});
       
  6099 
       
  6100 /* file:jscripts/tiny_mce/classes/AddOnManager.js */
       
  6101 
       
  6102 (function() {
       
  6103 	var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each;
       
  6104 
       
  6105 	tinymce.create('tinymce.AddOnManager', {
       
  6106 		items : [],
       
  6107 		urls : {},
       
  6108 		lookup : {},
       
  6109 		onAdd : new Dispatcher(this),
       
  6110 
       
  6111 		get : function(n) {
       
  6112 			return this.lookup[n];
       
  6113 		},
       
  6114 
       
  6115 		requireLangPack : function(n) {
       
  6116 			var u, s = tinymce.EditorManager.settings;
       
  6117 
       
  6118 			if (s && s.language) {
       
  6119 				u = this.urls[n] + '/langs/' + s.language + '.js';
       
  6120 
       
  6121 				if (!tinymce.dom.Event.domLoaded && !s.strict_mode)
       
  6122 					tinymce.ScriptLoader.load(u);
       
  6123 				else
       
  6124 					tinymce.ScriptLoader.add(u);
       
  6125 			}
       
  6126 		},
       
  6127 
       
  6128 		add : function(id, o) {
       
  6129 			this.items.push(o);
       
  6130 			this.lookup[id] = o;
       
  6131 			this.onAdd.dispatch(this, id, o);
       
  6132 
       
  6133 			return o;
       
  6134 		},
       
  6135 
       
  6136 		load : function(n, u, cb, s) {
       
  6137 			var t = this;
       
  6138 
       
  6139 			if (t.urls[n])
       
  6140 				return;
       
  6141 
       
  6142 			if (u.indexOf('/') != 0 && u.indexOf('://') == -1)
       
  6143 				u = tinymce.baseURL + '/' +  u;
       
  6144 
       
  6145 			t.urls[n] = u.substring(0, u.lastIndexOf('/'));
       
  6146 			tinymce.ScriptLoader.add(u, cb, s);
       
  6147 		}
       
  6148 
       
  6149 		});
       
  6150 
       
  6151 	// Create plugin and theme managers
       
  6152 	tinymce.PluginManager = new tinymce.AddOnManager();
       
  6153 	tinymce.ThemeManager = new tinymce.AddOnManager();
       
  6154 }());
       
  6155 /* file:jscripts/tiny_mce/classes/EditorManager.js */
       
  6156 
       
  6157 (function() {
       
  6158 	// Shorten names
       
  6159 	var each = tinymce.each, extend = tinymce.extend, DOM = tinymce.DOM, Event = tinymce.dom.Event, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, explode = tinymce.explode;
       
  6160 
       
  6161 	tinymce.create('static tinymce.EditorManager', {
       
  6162 		editors : {},
       
  6163 		i18n : {},
       
  6164 		activeEditor : null,
       
  6165 
       
  6166 		preInit : function() {
       
  6167 			var t = this, lo = window.location;
       
  6168 
       
  6169 			// Setup some URLs where the editor API is located and where the document is
       
  6170 			tinymce.documentBaseURL = lo.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
       
  6171 			if (!/[\/\\]$/.test(tinymce.documentBaseURL))
       
  6172 				tinymce.documentBaseURL += '/';
       
  6173 
       
  6174 			tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);
       
  6175 			tinymce.EditorManager.baseURI = new tinymce.util.URI(tinymce.baseURL);
       
  6176 
       
  6177 			// User already specified a document.domain value
       
  6178 			if (document.domain && lo.hostname != document.domain)
       
  6179 				tinymce.relaxedDomain = document.domain;
       
  6180 
       
  6181 			// Setup document domain if tinymce is loaded from other domain
       
  6182 			if (!tinymce.relaxedDomain && tinymce.EditorManager.baseURI.host != lo.hostname && lo.hostname)
       
  6183 				document.domain = tinymce.relaxedDomain = lo.hostname.replace(/.*\.(.+\..+)$/, '$1');
       
  6184 
       
  6185 			// Add before unload listener
       
  6186 			// This was required since IE was leaking memory if you added and removed beforeunload listeners
       
  6187 			// with attachEvent/detatchEvent so this only adds one listener and instances can the attach to the onBeforeUnload event
       
  6188 			t.onBeforeUnload = new tinymce.util.Dispatcher(t);
       
  6189 
       
  6190 			// Must be on window or IE will leak if the editor is placed in frame or iframe
       
  6191 			Event.add(window, 'beforeunload', function(e) {
       
  6192 				t.onBeforeUnload.dispatch(t, e);
       
  6193 			});
       
  6194 		},
       
  6195 
       
  6196 		init : function(s) {
       
  6197 			var t = this, pl, sl = tinymce.ScriptLoader, c, e, el = [], ed;
       
  6198 
       
  6199 			function execCallback(se, n, s) {
       
  6200 				var f = se[n];
       
  6201 
       
  6202 				if (!f)
       
  6203 					return;
       
  6204 
       
  6205 				if (tinymce.is(f, 'string')) {
       
  6206 					s = f.replace(/\.\w+$/, '');
       
  6207 					s = s ? tinymce.resolve(s) : 0;
       
  6208 					f = tinymce.resolve(f);
       
  6209 				}
       
  6210 
       
  6211 				return f.apply(s || this, Array.prototype.slice.call(arguments, 2));
       
  6212 			};
       
  6213 
       
  6214 			s = extend({
       
  6215 				theme : "simple",
       
  6216 				language : "en",
       
  6217 				strict_loading_mode : document.contentType == 'application/xhtml+xml'
       
  6218 			}, s);
       
  6219 
       
  6220 			t.settings = s;
       
  6221 
       
  6222 			// If page not loaded and strict mode isn't enabled then load them
       
  6223 			if (!Event.domLoaded && !s.strict_loading_mode) {
       
  6224 				// Load language
       
  6225 				if (s.language)
       
  6226 					sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');
       
  6227 
       
  6228 				// Load theme
       
  6229 				if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])
       
  6230 					ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');
       
  6231 
       
  6232 				// Load plugins
       
  6233 				if (s.plugins) {
       
  6234 					pl = explode(s.plugins);
       
  6235 
       
  6236 					// Load compat2x first
       
  6237 					if (tinymce.inArray(pl, 'compat2x') != -1)
       
  6238 						PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');
       
  6239 
       
  6240 					// Load rest if plugins
       
  6241 					each(pl, function(v) {
       
  6242 						if (v && v.charAt(0) != '-' && !PluginManager.urls[v]) {
       
  6243 							// Skip safari plugin for other browsers
       
  6244 							if (!tinymce.isWebKit && v == 'safari')
       
  6245 								return;
       
  6246 
       
  6247 							PluginManager.load(v, 'plugins/' + v + '/editor_plugin' + tinymce.suffix + '.js');
       
  6248 						}
       
  6249 					});
       
  6250 				}
       
  6251 
       
  6252 				sl.loadQueue();
       
  6253 			}
       
  6254 
       
  6255 			// Legacy call
       
  6256 			Event.add(document, 'init', function() {
       
  6257 				var l, co;
       
  6258 
       
  6259 				execCallback(s, 'onpageload');
       
  6260 
       
  6261 				// Verify that it's a valid browser
       
  6262 				if (s.browsers) {
       
  6263 					l = false;
       
  6264 
       
  6265 					each(explode(s.browsers), function(v) {
       
  6266 						switch (v) {
       
  6267 							case 'ie':
       
  6268 							case 'msie':
       
  6269 								if (tinymce.isIE)
       
  6270 									l = true;
       
  6271 								break;
       
  6272 
       
  6273 							case 'gecko':
       
  6274 								if (tinymce.isGecko)
       
  6275 									l = true;
       
  6276 								break;
       
  6277 
       
  6278 							case 'safari':
       
  6279 							case 'webkit':
       
  6280 								if (tinymce.isWebKit)
       
  6281 									l = true;
       
  6282 								break;
       
  6283 
       
  6284 							case 'opera':
       
  6285 								if (tinymce.isOpera)
       
  6286 									l = true;
       
  6287 
       
  6288 								break;
       
  6289 						}
       
  6290 					});
       
  6291 
       
  6292 					// Not a valid one
       
  6293 					if (!l)
       
  6294 						return;
       
  6295 				}
       
  6296 
       
  6297 				switch (s.mode) {
       
  6298 					case "exact":
       
  6299 						l = s.elements || '';
       
  6300 
       
  6301 						if(l.length > 0) {
       
  6302 							each(explode(l), function(v) {
       
  6303 								if (DOM.get(v)) {
       
  6304 									ed = new tinymce.Editor(v, s);
       
  6305 									el.push(ed);
       
  6306 									ed.render(1);
       
  6307 								} else {
       
  6308 									c = 0;
       
  6309 
       
  6310 									each(document.forms, function(f) {
       
  6311 										each(f.elements, function(e) {
       
  6312 											if (e.name === v) {
       
  6313 												v = 'mce_editor_' + c;
       
  6314 												DOM.setAttrib(e, 'id', v);
       
  6315 
       
  6316 												ed = new tinymce.Editor(v, s);
       
  6317 												el.push(ed);
       
  6318 												ed.render(1);
       
  6319 											}
       
  6320 										});
       
  6321 									});
       
  6322 								}
       
  6323 							});
       
  6324 						}
       
  6325 						break;
       
  6326 
       
  6327 					case "textareas":
       
  6328 					case "specific_textareas":
       
  6329 						function hasClass(n, c) {
       
  6330 							return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c);
       
  6331 						};
       
  6332 
       
  6333 						each(DOM.select('textarea'), function(v) {
       
  6334 							if (s.editor_deselector && hasClass(v, s.editor_deselector))
       
  6335 								return;
       
  6336 
       
  6337 							if (!s.editor_selector || hasClass(v, s.editor_selector)) {
       
  6338 								// Can we use the name
       
  6339 								e = DOM.get(v.name);
       
  6340 								if (!v.id && !e)
       
  6341 									v.id = v.name;
       
  6342 
       
  6343 								// Generate unique name if missing or already exists
       
  6344 								if (!v.id || t.get(v.id))
       
  6345 									v.id = DOM.uniqueId();
       
  6346 
       
  6347 								ed = new tinymce.Editor(v.id, s);
       
  6348 								el.push(ed);
       
  6349 								ed.render(1);
       
  6350 							}
       
  6351 						});
       
  6352 						break;
       
  6353 				}
       
  6354 
       
  6355 				// Call onInit when all editors are initialized
       
  6356 				if (s.oninit) {
       
  6357 					l = co = 0;
       
  6358 
       
  6359 					each (el, function(ed) {
       
  6360 						co++;
       
  6361 
       
  6362 						if (!ed.initialized) {
       
  6363 							// Wait for it
       
  6364 							ed.onInit.add(function() {
       
  6365 								l++;
       
  6366 
       
  6367 								// All done
       
  6368 								if (l == co)
       
  6369 									execCallback(s, 'oninit');
       
  6370 							});
       
  6371 						} else
       
  6372 							l++;
       
  6373 
       
  6374 						// All done
       
  6375 						if (l == co)
       
  6376 							execCallback(s, 'oninit');					
       
  6377 					});
       
  6378 				}
       
  6379 			});
       
  6380 		},
       
  6381 
       
  6382 		get : function(id) {
       
  6383 			return this.editors[id];
       
  6384 		},
       
  6385 
       
  6386 		getInstanceById : function(id) {
       
  6387 			return this.get(id);
       
  6388 		},
       
  6389 
       
  6390 		add : function(e) {
       
  6391 			this.editors[e.id] = e;
       
  6392 			this._setActive(e);
       
  6393 
       
  6394 			return e;
       
  6395 		},
       
  6396 
       
  6397 		remove : function(e) {
       
  6398 			var t = this;
       
  6399 
       
  6400 			// Not in the collection
       
  6401 			if (!t.editors[e.id])
       
  6402 				return null;
       
  6403 
       
  6404 			delete t.editors[e.id];
       
  6405 
       
  6406 			// Select another editor since the active one was removed
       
  6407 			if (t.activeEditor == e) {
       
  6408 				each(t.editors, function(e) {
       
  6409 					t._setActive(e);
       
  6410 					return false; // Break
       
  6411 				});
       
  6412 			}
       
  6413 
       
  6414 			e.destroy();
       
  6415 
       
  6416 			return e;
       
  6417 		},
       
  6418 
       
  6419 		execCommand : function(c, u, v) {
       
  6420 			var t = this, ed = t.get(v), w;
       
  6421 
       
  6422 			// Manager commands
       
  6423 			switch (c) {
       
  6424 				case "mceFocus":
       
  6425 					ed.focus();
       
  6426 					return true;
       
  6427 
       
  6428 				case "mceAddEditor":
       
  6429 				case "mceAddControl":
       
  6430 					if (!t.get(v))
       
  6431 						new tinymce.Editor(v, t.settings).render();
       
  6432 
       
  6433 					return true;
       
  6434 
       
  6435 				case "mceAddFrameControl":
       
  6436 					w = v.window;
       
  6437 
       
  6438 					// Add tinyMCE global instance and tinymce namespace to specified window
       
  6439 					w.tinyMCE = tinyMCE;
       
  6440 					w.tinymce = tinymce;
       
  6441 
       
  6442 					tinymce.DOM.doc = w.document;
       
  6443 					tinymce.DOM.win = w;
       
  6444 
       
  6445 					ed = new tinymce.Editor(v.element_id, v);
       
  6446 					ed.render();
       
  6447 
       
  6448 					// Fix IE memory leaks
       
  6449 					if (tinymce.isIE) {
       
  6450 						function clr() {
       
  6451 							ed.destroy();
       
  6452 							w.detachEvent('onunload', clr);
       
  6453 							w = w.tinyMCE = w.tinymce = null; // IE leak
       
  6454 						};
       
  6455 
       
  6456 						w.attachEvent('onunload', clr);
       
  6457 					}
       
  6458 
       
  6459 					v.page_window = null;
       
  6460 
       
  6461 					return true;
       
  6462 
       
  6463 				case "mceRemoveEditor":
       
  6464 				case "mceRemoveControl":
       
  6465 					ed.remove();
       
  6466 					return true;
       
  6467 
       
  6468 				case 'mceToggleEditor':
       
  6469 					if (!ed) {
       
  6470 						t.execCommand('mceAddControl', 0, v);
       
  6471 						return true;
       
  6472 					}
       
  6473 
       
  6474 					if (ed.isHidden())
       
  6475 						ed.show();
       
  6476 					else
       
  6477 						ed.hide();
       
  6478 
       
  6479 					return true;
       
  6480 			}
       
  6481 
       
  6482 			// Run command on active editor
       
  6483 			if (t.activeEditor)
       
  6484 				return t.activeEditor.execCommand(c, u, v);
       
  6485 
       
  6486 			return false;
       
  6487 		},
       
  6488 
       
  6489 		execInstanceCommand : function(id, c, u, v) {
       
  6490 			var ed = this.get(id);
       
  6491 
       
  6492 			if (ed)
       
  6493 				return ed.execCommand(c, u, v);
       
  6494 
       
  6495 			return false;
       
  6496 		},
       
  6497 
       
  6498 		triggerSave : function() {
       
  6499 			each(this.editors, function(e) {
       
  6500 				e.save();
       
  6501 			});
       
  6502 		},
       
  6503 
       
  6504 		addI18n : function(p, o) {
       
  6505 			var lo, i18n = this.i18n;
       
  6506 
       
  6507 			if (!tinymce.is(p, 'string')) {
       
  6508 				each(p, function(o, lc) {
       
  6509 					each(o, function(o, g) {
       
  6510 						each(o, function(o, k) {
       
  6511 							if (g === 'common')
       
  6512 								i18n[lc + '.' + k] = o;
       
  6513 							else
       
  6514 								i18n[lc + '.' + g + '.' + k] = o;
       
  6515 						});
       
  6516 					});
       
  6517 				});
       
  6518 			} else {
       
  6519 				each(o, function(o, k) {
       
  6520 					i18n[p + '.' + k] = o;
       
  6521 				});
       
  6522 			}
       
  6523 		},
       
  6524 
       
  6525 		// Private methods
       
  6526 
       
  6527 		_setActive : function(e) {
       
  6528 			this.selectedInstance = this.activeEditor = e;
       
  6529 		}
       
  6530 
       
  6531 		});
       
  6532 
       
  6533 	tinymce.EditorManager.preInit();
       
  6534 })();
       
  6535 
       
  6536 // Short for editor manager window.tinyMCE is needed when TinyMCE gets loaded though a XHR call
       
  6537 var tinyMCE = window.tinyMCE = tinymce.EditorManager;
       
  6538 
       
  6539 /* file:jscripts/tiny_mce/classes/Editor.js */
       
  6540 
       
  6541 (function() {
       
  6542 	var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, Dispatcher = tinymce.util.Dispatcher;
       
  6543 	var each = tinymce.each, isGecko = tinymce.isGecko, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit;
       
  6544 	var is = tinymce.is, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, EditorManager = tinymce.EditorManager;
       
  6545 	var inArray = tinymce.inArray, grep = tinymce.grep, explode = tinymce.explode;
       
  6546 
       
  6547 	tinymce.create('tinymce.Editor', {
       
  6548 		Editor : function(id, s) {
       
  6549 			var t = this;
       
  6550 
       
  6551 			t.id = t.editorId = id;
       
  6552 			t.execCommands = {};
       
  6553 			t.queryStateCommands = {};
       
  6554 			t.queryValueCommands = {};
       
  6555 			t.plugins = {};
       
  6556 
       
  6557 			// Add events to the editor
       
  6558 			each([
       
  6559 				'onPreInit',
       
  6560 				'onBeforeRenderUI',
       
  6561 				'onPostRender',
       
  6562 				'onInit',
       
  6563 				'onRemove',
       
  6564 				'onActivate',
       
  6565 				'onDeactivate',
       
  6566 				'onClick',
       
  6567 				'onEvent',
       
  6568 				'onMouseUp',
       
  6569 				'onMouseDown',
       
  6570 				'onDblClick',
       
  6571 				'onKeyDown',
       
  6572 				'onKeyUp',
       
  6573 				'onKeyPress',
       
  6574 				'onContextMenu',
       
  6575 				'onSubmit',
       
  6576 				'onReset',
       
  6577 				'onPaste',
       
  6578 				'onPreProcess',
       
  6579 				'onPostProcess',
       
  6580 				'onBeforeSetContent',
       
  6581 				'onBeforeGetContent',
       
  6582 				'onSetContent',
       
  6583 				'onGetContent',
       
  6584 				'onLoadContent',
       
  6585 				'onSaveContent',
       
  6586 				'onNodeChange',
       
  6587 				'onChange',
       
  6588 				'onBeforeExecCommand',
       
  6589 				'onExecCommand',
       
  6590 				'onUndo',
       
  6591 				'onRedo',
       
  6592 				'onVisualAid',
       
  6593 				'onSetProgressState'
       
  6594 			], function(e) {
       
  6595 				t[e] = new Dispatcher(t);
       
  6596 			});
       
  6597 
       
  6598 			// Default editor config
       
  6599 			t.settings = s = extend({
       
  6600 				id : id,
       
  6601 				language : 'en',
       
  6602 				docs_language : 'en',
       
  6603 				theme : 'simple',
       
  6604 				skin : 'default',
       
  6605 				delta_width : 0,
       
  6606 				delta_height : 0,
       
  6607 				popup_css : '',
       
  6608 				plugins : '',
       
  6609 				document_base_url : tinymce.documentBaseURL,
       
  6610 				add_form_submit_trigger : 1,
       
  6611 				submit_patch : 1,
       
  6612 				add_unload_trigger : 1,
       
  6613 				convert_urls : 1,
       
  6614 				relative_urls : 1,
       
  6615 				remove_script_host : 1,
       
  6616 				table_inline_editing : 0,
       
  6617 				object_resizing : 1,
       
  6618 				cleanup : 1,
       
  6619 				accessibility_focus : 1,
       
  6620 				custom_shortcuts : 1,
       
  6621 				custom_undo_redo_keyboard_shortcuts : 1,
       
  6622 				custom_undo_redo_restore_selection : 1,
       
  6623 				custom_undo_redo : 1,
       
  6624 				doctype : '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">',
       
  6625 				visual_table_class : 'mceItemTable',
       
  6626 				visual : 1,
       
  6627 				inline_styles : true,
       
  6628 				convert_fonts_to_spans : true,
       
  6629 				font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large',
       
  6630 				apply_source_formatting : 1,
       
  6631 				directionality : 'ltr',
       
  6632 				forced_root_block : 'p',
       
  6633 				valid_elements : '@[id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong/b,em/i,strike,u,#p[align],-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote[cite],-table[border=0|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-code,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value],embed[type|width|height|src|*],script[src|type],map[name],area[shape|coords|href|alt|target],bdo,button,col[align|char|charoff|span|valign|width],colgroup[align|char|charoff|span|valign|width],dfn,fieldset,form[action|accept|accept-charset|enctype|method],input[accept|alt|checked|disabled|maxlength|name|readonly|size|src|type|value|tabindex|accesskey],kbd,label[for],legend,noscript,optgroup[label|disabled],option[disabled|label|selected|value],q[cite],samp,select[disabled|multiple|name|size],small,textarea[cols|rows|disabled|name|readonly],tt,var,big',
       
  6634 				hidden_input : 1,
       
  6635 				padd_empty_editor : 1,
       
  6636 				render_ui : 1,
       
  6637 				init_theme : 1,
       
  6638 				force_p_newlines : 1,
       
  6639 				indentation : '30px'
       
  6640 			}, s);
       
  6641 
       
  6642 			// Setup URIs
       
  6643 			t.documentBaseURI = new tinymce.util.URI(s.document_base_url || tinymce.documentBaseURL, {
       
  6644 				base_uri : tinyMCE.baseURI
       
  6645 			});
       
  6646 			t.baseURI = EditorManager.baseURI;
       
  6647 
       
  6648 			// Call setup
       
  6649 			t.execCallback('setup', t);
       
  6650 		},
       
  6651 
       
  6652 		render : function(nst) {
       
  6653 			var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader;
       
  6654 
       
  6655 			// Page is not loaded yet, wait for it
       
  6656 			if (!Event.domLoaded) {
       
  6657 				Event.add(document, 'init', function() {
       
  6658 					t.render();
       
  6659 				});
       
  6660 				return;
       
  6661 			}
       
  6662 
       
  6663 			// Force strict loading mode if render us called by user and not internally
       
  6664 			if (!nst) {
       
  6665 				s.strict_loading_mode = 1;
       
  6666 				tinyMCE.settings = s;
       
  6667 			}
       
  6668 
       
  6669 			// Element not found, then skip initialization
       
  6670 			if (!t.getElement())
       
  6671 				return;
       
  6672 
       
  6673 			if (s.strict_loading_mode) {
       
  6674 				sl.settings.strict_mode = s.strict_loading_mode;
       
  6675 				tinymce.DOM.settings.strict = 1;
       
  6676 			}
       
  6677 
       
  6678 			// Add hidden input for non input elements inside form elements
       
  6679 			if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form'))
       
  6680 				DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id);
       
  6681 
       
  6682 			t.windowManager = new tinymce.WindowManager(t);
       
  6683 
       
  6684 			if (s.encoding == 'xml') {
       
  6685 				t.onGetContent.add(function(ed, o) {
       
  6686 					if (o.save)
       
  6687 						o.content = DOM.encode(o.content);
       
  6688 				});
       
  6689 			}
       
  6690 
       
  6691 			if (s.add_form_submit_trigger) {
       
  6692 				t.onSubmit.addToTop(function() {
       
  6693 					if (t.initialized) {
       
  6694 						t.save();
       
  6695 						t.isNotDirty = 1;
       
  6696 					}
       
  6697 				});
       
  6698 			}
       
  6699 
       
  6700 			if (s.add_unload_trigger && !s.ask) {
       
  6701 				t._beforeUnload = tinyMCE.onBeforeUnload.add(function() {
       
  6702 					if (t.initialized && !t.destroyed && !t.isHidden())
       
  6703 						t.save({format : 'raw', no_events : true});
       
  6704 				});
       
  6705 			}
       
  6706 
       
  6707 			tinymce.addUnload(t.destroy, t);
       
  6708 
       
  6709 			if (s.submit_patch) {
       
  6710 				t.onBeforeRenderUI.add(function() {
       
  6711 					var n = t.getElement().form;
       
  6712 
       
  6713 					if (!n)
       
  6714 						return;
       
  6715 
       
  6716 					// Already patched
       
  6717 					if (n._mceOldSubmit)
       
  6718 						return;
       
  6719 
       
  6720 					// Check page uses id="submit" or name="submit" for it's submit button
       
  6721 					if (!n.submit.nodeType && !n.submit.length) {
       
  6722 						t.formElement = n;
       
  6723 						n._mceOldSubmit = n.submit;
       
  6724 						n.submit = function() {
       
  6725 							// Save all instances
       
  6726 							EditorManager.triggerSave();
       
  6727 							t.isNotDirty = 1;
       
  6728 
       
  6729 							return this._mceOldSubmit(this);
       
  6730 						};
       
  6731 					}
       
  6732 
       
  6733 					n = null;
       
  6734 				});
       
  6735 			}
       
  6736 
       
  6737 			// Load scripts
       
  6738 			function loadScripts() {
       
  6739 				if (s.language)
       
  6740 					sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');
       
  6741 
       
  6742 				if (s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])
       
  6743 					ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');
       
  6744 
       
  6745 				each(explode(s.plugins), function(p) {
       
  6746 					if (p && p.charAt(0) != '-' && !PluginManager.urls[p]) {
       
  6747 						// Skip safari plugin for other browsers
       
  6748 						if (!isWebKit && p == 'safari')
       
  6749 							return;
       
  6750 
       
  6751 						PluginManager.load(p, 'plugins/' + p + '/editor_plugin' + tinymce.suffix + '.js');
       
  6752 					}
       
  6753 				});
       
  6754 
       
  6755 				// Init when que is loaded
       
  6756 				sl.loadQueue(function() {
       
  6757 					if (s.ask) {
       
  6758 						function ask() {
       
  6759 							// Yield for awhile to avoid focus bug on FF 3 when cancel is pressed
       
  6760 							window.setTimeout(function() {
       
  6761 								Event.remove(t.id, 'focus', ask);
       
  6762 
       
  6763 								t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {
       
  6764 									if (s)
       
  6765 										t.init();
       
  6766 								});
       
  6767 							}, 0);
       
  6768 						};
       
  6769 
       
  6770 						Event.add(t.id, 'focus', ask);
       
  6771 						return;
       
  6772 					}
       
  6773 
       
  6774 					if (!t.removed)
       
  6775 						t.init();
       
  6776 				});
       
  6777 			};
       
  6778 
       
  6779 			// Load compat2x first
       
  6780 			if (s.plugins.indexOf('compat2x') != -1) {
       
  6781 				PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');
       
  6782 				sl.loadQueue(loadScripts);
       
  6783 			} else
       
  6784 				loadScripts();
       
  6785 		},
       
  6786 
       
  6787 		init : function() {
       
  6788 			var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti, u, bi, bc, re;
       
  6789 
       
  6790 			EditorManager.add(t);
       
  6791 
       
  6792 			// Create theme
       
  6793 			s.theme = s.theme.replace(/-/, '');
       
  6794 			o = ThemeManager.get(s.theme);
       
  6795 			t.theme = new o();
       
  6796 
       
  6797 			if (t.theme.init && s.init_theme)
       
  6798 				t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, ''));
       
  6799 
       
  6800 			// Create all plugins
       
  6801 			each(explode(s.plugins.replace(/\-/g, '')), function(p) {
       
  6802 				var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po;
       
  6803 
       
  6804 				if (c) {
       
  6805 					po = new c(t, u);
       
  6806 
       
  6807 					t.plugins[p] = po;
       
  6808 
       
  6809 					if (po.init)
       
  6810 						po.init(t, u);
       
  6811 				}
       
  6812 			});
       
  6813 
       
  6814 			// Setup popup CSS path(s)
       
  6815 			if (s.popup_css)
       
  6816 				s.popup_css = t.documentBaseURI.toAbsolute(s.popup_css);
       
  6817 			else
       
  6818 				s.popup_css = t.baseURI.toAbsolute("themes/" + s.theme + "/skins/" + s.skin + "/dialog.css");
       
  6819 
       
  6820 			if (s.popup_css_add)
       
  6821 				s.popup_css += ',' + t.documentBaseURI.toAbsolute(s.popup_css_add);
       
  6822 
       
  6823 			// Setup control factory
       
  6824 			t.controlManager = new tinymce.ControlManager(t);
       
  6825 			t.undoManager = new tinymce.UndoManager(t);
       
  6826 
       
  6827 			// Pass through
       
  6828 			t.undoManager.onAdd.add(function(um, l) {
       
  6829 				if (!l.initial)
       
  6830 					return t.onChange.dispatch(t, l, um);
       
  6831 			});
       
  6832 
       
  6833 			t.undoManager.onUndo.add(function(um, l) {
       
  6834 				return t.onUndo.dispatch(t, l, um);
       
  6835 			});
       
  6836 
       
  6837 			t.undoManager.onRedo.add(function(um, l) {
       
  6838 				return t.onRedo.dispatch(t, l, um);
       
  6839 			});
       
  6840 
       
  6841 			if (s.custom_undo_redo) {
       
  6842 				t.onExecCommand.add(function(ed, cmd, ui, val, a) {
       
  6843 					if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint' && (!a || !a.skip_undo))
       
  6844 						t.undoManager.add();
       
  6845 				});
       
  6846 			}
       
  6847 
       
  6848 			t.onExecCommand.add(function(ed, c) {
       
  6849 				// Don't refresh the select lists until caret move
       
  6850 				if (!/^(FontName|FontSize)$/.test(c))
       
  6851 					t.nodeChanged();
       
  6852 			});
       
  6853 
       
  6854 			// Remove ghost selections on images and tables in Gecko
       
  6855 			if (isGecko) {
       
  6856 				function repaint(a, o) {
       
  6857 					if (!o || !o.initial)
       
  6858 						t.execCommand('mceRepaint');
       
  6859 				};
       
  6860 
       
  6861 				t.onUndo.add(repaint);
       
  6862 				t.onRedo.add(repaint);
       
  6863 				t.onSetContent.add(repaint);
       
  6864 			}
       
  6865 
       
  6866 			// Enables users to override the control factory
       
  6867 			t.onBeforeRenderUI.dispatch(t, t.controlManager);
       
  6868 
       
  6869 			// Measure box
       
  6870 			if (s.render_ui) {
       
  6871 				w = s.width || e.style.width || e.offsetWidth;
       
  6872 				h = s.height || e.style.height || e.offsetHeight;
       
  6873 				t.orgDisplay = e.style.display;
       
  6874 				re = /^[0-9\.]+(|px)$/i;
       
  6875 
       
  6876 				if (re.test('' + w))
       
  6877 					w = Math.max(parseInt(w) + (o.deltaWidth || 0), 100);
       
  6878 
       
  6879 				if (re.test('' + h))
       
  6880 					h = Math.max(parseInt(h) + (o.deltaHeight || 0), 100);
       
  6881 
       
  6882 				// Render UI
       
  6883 				o = t.theme.renderUI({
       
  6884 					targetNode : e,
       
  6885 					width : w,
       
  6886 					height : h,
       
  6887 					deltaWidth : s.delta_width,
       
  6888 					deltaHeight : s.delta_height
       
  6889 				});
       
  6890 
       
  6891 				t.editorContainer = o.editorContainer;
       
  6892 			}
       
  6893 
       
  6894 			
       
  6895 			// Resize editor
       
  6896 			DOM.setStyles(o.sizeContainer || o.editorContainer, {
       
  6897 				width : w,
       
  6898 				height : h
       
  6899 			});
       
  6900 
       
  6901 			h = (o.iframeHeight || h) + ((h + '').indexOf('%') == -1 ? (o.deltaHeight || 0) : '');
       
  6902 			if (h < 100)
       
  6903 				h = 100;
       
  6904 
       
  6905 			t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '" />';
       
  6906 			t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
       
  6907 
       
  6908 			if (tinymce.relaxedDomain)
       
  6909 				t.iframeHTML += '<script type="text/javascript">document.domain = "' + tinymce.relaxedDomain + '";</script>';
       
  6910 
       
  6911 			bi = s.body_id || 'tinymce';
       
  6912 			if (bi.indexOf('=') != -1) {
       
  6913 				bi = t.getParam('body_id', '', 'hash');
       
  6914 				bi = bi[t.id] || bi;
       
  6915 			}
       
  6916 
       
  6917 			bc = s.body_class || '';
       
  6918 			if (bc.indexOf('=') != -1) {
       
  6919 				bc = t.getParam('body_class', '', 'hash');
       
  6920 				bc = bc[t.id] || '';
       
  6921 			}
       
  6922 
       
  6923 			t.iframeHTML += '</head><body id="' + bi + '" class="mceContentBody ' + bc + '"></body></html>';
       
  6924 
       
  6925 			// Domain relaxing enabled, then set document domain
       
  6926 			if (tinymce.relaxedDomain) {
       
  6927 				// We need to write the contents here in IE since multiple writes messes up refresh button and back button
       
  6928 				if (isIE || (tinymce.isOpera && parseFloat(opera.version()) >= 9.5))
       
  6929 					u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";var ed = window.parent.tinyMCE.get("' + t.id + '");document.write(ed.iframeHTML);document.close();ed.setupIframe();})()';
       
  6930 				else if (tinymce.isOpera)
       
  6931 					u = 'javascript:(function(){document.open();document.domain="' + document.domain + '";document.close();ed.setupIframe();})()';					
       
  6932 			}
       
  6933 
       
  6934 			// Create iframe
       
  6935 			n = DOM.add(o.iframeContainer, 'iframe', {
       
  6936 				id : t.id + "_ifr",
       
  6937 				src : u || 'javascript:""', // Workaround for HTTPS warning in IE6/7
       
  6938 				frameBorder : '0',
       
  6939 				style : {
       
  6940 					width : '100%',
       
  6941 					height : h
       
  6942 				}
       
  6943 			});
       
  6944 
       
  6945 			t.contentAreaContainer = o.iframeContainer;
       
  6946 			DOM.get(o.editorContainer).style.display = t.orgDisplay;
       
  6947 			DOM.get(t.id).style.display = 'none';
       
  6948 
       
  6949 			// Safari 2.x requires us to wait for the load event and load a real HTML doc
       
  6950 			if (tinymce.isOldWebKit) {
       
  6951 				Event.add(n, 'load', t.setupIframe, t);
       
  6952 				n.src = tinymce.baseURL + '/plugins/safari/blank.htm';
       
  6953 			} else {
       
  6954 				if (!isIE || !tinymce.relaxedDomain)
       
  6955 					t.setupIframe();
       
  6956 
       
  6957 				e = n = o = null; // Cleanup
       
  6958 			}
       
  6959 		},
       
  6960 
       
  6961 		setupIframe : function() {
       
  6962 			var t = this, s = t.settings, e = DOM.get(t.id), d = t.getDoc(), h, b;
       
  6963 
       
  6964 			// Setup iframe body
       
  6965 			if (!isIE || !tinymce.relaxedDomain) {
       
  6966 				d.open();
       
  6967 				d.write(t.iframeHTML);
       
  6968 				d.close();
       
  6969 			}
       
  6970 
       
  6971 			// Design mode needs to be added here Ctrl+A will fail otherwise
       
  6972 			if (!isIE) {
       
  6973 				try {
       
  6974 					if (!s.readonly)
       
  6975 						d.designMode = 'On';
       
  6976 				} catch (ex) {
       
  6977 					// Will fail on Gecko if the editor is placed in an hidden container element
       
  6978 					// The design mode will be set ones the editor is focused
       
  6979 				}
       
  6980 			}
       
  6981 
       
  6982 			// IE needs to use contentEditable or it will display non secure items for HTTPS
       
  6983 			if (isIE) {
       
  6984 				// It will not steal focus if we hide it while setting contentEditable
       
  6985 				b = t.getBody();
       
  6986 				DOM.hide(b);
       
  6987 
       
  6988 				if (!s.readonly)
       
  6989 					b.contentEditable = true;
       
  6990 
       
  6991 				DOM.show(b);
       
  6992 			}
       
  6993 
       
  6994 			// Setup objects
       
  6995 			t.dom = new tinymce.DOM.DOMUtils(t.getDoc(), {
       
  6996 				keep_values : true,
       
  6997 				url_converter : t.convertURL,
       
  6998 				url_converter_scope : t,
       
  6999 				hex_colors : s.force_hex_style_colors,
       
  7000 				class_filter : s.class_filter,
       
  7001 				update_styles : 1,
       
  7002 				fix_ie_paragraphs : 1
       
  7003 			});
       
  7004 
       
  7005 			t.serializer = new tinymce.dom.Serializer({
       
  7006 				entity_encoding : s.entity_encoding,
       
  7007 				entities : s.entities,
       
  7008 				valid_elements : s.verify_html === false ? '*[*]' : s.valid_elements,
       
  7009 				extended_valid_elements : s.extended_valid_elements,
       
  7010 				valid_child_elements : s.valid_child_elements,
       
  7011 				invalid_elements : s.invalid_elements,
       
  7012 				fix_table_elements : s.fix_table_elements,
       
  7013 				fix_list_elements : s.fix_list_elements,
       
  7014 				fix_content_duplication : s.fix_content_duplication,
       
  7015 				convert_fonts_to_spans : s.convert_fonts_to_spans,
       
  7016 				font_size_classes  : s.font_size_classes,
       
  7017 				font_size_style_values : s.font_size_style_values,
       
  7018 				apply_source_formatting : s.apply_source_formatting,
       
  7019 				remove_linebreaks : s.remove_linebreaks,
       
  7020 				dom : t.dom
       
  7021 			});
       
  7022 
       
  7023 			t.selection = new tinymce.dom.Selection(t.dom, t.getWin(), t.serializer);
       
  7024 			t.forceBlocks = new tinymce.ForceBlocks(t, {
       
  7025 				forced_root_block : s.forced_root_block
       
  7026 			});
       
  7027 			t.editorCommands = new tinymce.EditorCommands(t);
       
  7028 
       
  7029 			// Pass through
       
  7030 			t.serializer.onPreProcess.add(function(se, o) {
       
  7031 				return t.onPreProcess.dispatch(t, o, se);
       
  7032 			});
       
  7033 
       
  7034 			t.serializer.onPostProcess.add(function(se, o) {
       
  7035 				return t.onPostProcess.dispatch(t, o, se);
       
  7036 			});
       
  7037 
       
  7038 			t.onPreInit.dispatch(t);
       
  7039 
       
  7040 			if (!s.gecko_spellcheck)
       
  7041 				t.getBody().spellcheck = 0;
       
  7042 
       
  7043 			if (!s.readonly)
       
  7044 				t._addEvents();
       
  7045 
       
  7046 			t.controlManager.onPostRender.dispatch(t, t.controlManager);
       
  7047 			t.onPostRender.dispatch(t);
       
  7048 
       
  7049 			if (s.directionality)
       
  7050 				t.getBody().dir = s.directionality;
       
  7051 
       
  7052 			if (s.nowrap)
       
  7053 				t.getBody().style.whiteSpace = "nowrap";
       
  7054 
       
  7055 			if (s.auto_resize)
       
  7056 				t.onNodeChange.add(t.resizeToContent, t);
       
  7057 
       
  7058 			if (s.custom_elements) {
       
  7059 				function handleCustom(ed, o) {
       
  7060 					each(explode(s.custom_elements), function(v) {
       
  7061 						var n;
       
  7062 
       
  7063 						if (v.indexOf('~') === 0) {
       
  7064 							v = v.substring(1);
       
  7065 							n = 'span';
       
  7066 						} else
       
  7067 							n = 'div';
       
  7068 
       
  7069 						o.content = o.content.replace(new RegExp('<(' + v + ')([^>]*)>', 'g'), '<' + n + ' mce_name="$1"$2>');
       
  7070 						o.content = o.content.replace(new RegExp('</(' + v + ')>', 'g'), '</' + n + '>');
       
  7071 					});
       
  7072 				};
       
  7073 
       
  7074 				t.onBeforeSetContent.add(handleCustom);
       
  7075 				t.onPostProcess.add(function(ed, o) {
       
  7076 					if (o.set)
       
  7077 						handleCustom(ed, o)
       
  7078 				});
       
  7079 			}
       
  7080 
       
  7081 			if (s.handle_node_change_callback) {
       
  7082 				t.onNodeChange.add(function(ed, cm, n) {
       
  7083 					t.execCallback('handle_node_change_callback', t.id, n, -1, -1, true, t.selection.isCollapsed());
       
  7084 				});
       
  7085 			}
       
  7086 
       
  7087 			if (s.save_callback) {
       
  7088 				t.onSaveContent.add(function(ed, o) {
       
  7089 					var h = t.execCallback('save_callback', t.id, o.content, t.getBody());
       
  7090 
       
  7091 					if (h)
       
  7092 						o.content = h;
       
  7093 				});
       
  7094 			}
       
  7095 
       
  7096 			if (s.onchange_callback) {
       
  7097 				t.onChange.add(function(ed, l) {
       
  7098 					t.execCallback('onchange_callback', t, l);
       
  7099 				});
       
  7100 			}
       
  7101 
       
  7102 			if (s.convert_newlines_to_brs) {
       
  7103 				t.onBeforeSetContent.add(function(ed, o) {
       
  7104 					if (o.initial)
       
  7105 						o.content = o.content.replace(/\r?\n/g, '<br />');
       
  7106 				});
       
  7107 			}
       
  7108 
       
  7109 			if (s.fix_nesting && isIE) {
       
  7110 				t.onBeforeSetContent.add(function(ed, o) {
       
  7111 					o.content = t._fixNesting(o.content);
       
  7112 				});
       
  7113 			}
       
  7114 
       
  7115 			if (s.preformatted) {
       
  7116 				t.onPostProcess.add(function(ed, o) {
       
  7117 					o.content = o.content.replace(/^\s*<pre.*?>/, '');
       
  7118 					o.content = o.content.replace(/<\/pre>\s*$/, '');
       
  7119 
       
  7120 					if (o.set)
       
  7121 						o.content = '<pre class="mceItemHidden">' + o.content + '</pre>';
       
  7122 				});
       
  7123 			}
       
  7124 
       
  7125 			if (s.verify_css_classes) {
       
  7126 				t.serializer.attribValueFilter = function(n, v) {
       
  7127 					var s, cl;
       
  7128 
       
  7129 					if (n == 'class') {
       
  7130 						// Build regexp for classes
       
  7131 						if (!t.classesRE) {
       
  7132 							cl = t.dom.getClasses();
       
  7133 
       
  7134 							if (cl.length > 0) {
       
  7135 								s = '';
       
  7136 
       
  7137 								each (cl, function(o) {
       
  7138 									s += (s ? '|' : '') + o['class'];
       
  7139 								});
       
  7140 
       
  7141 								t.classesRE = new RegExp('(' + s + ')', 'gi');
       
  7142 							}
       
  7143 						}
       
  7144 
       
  7145 						return !t.classesRE || /(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(v) || t.classesRE.test(v) ? v : '';
       
  7146 					}
       
  7147 
       
  7148 					return v;
       
  7149 				};
       
  7150 			}
       
  7151 
       
  7152 			if (s.convert_fonts_to_spans)
       
  7153 				t._convertFonts();
       
  7154 
       
  7155 			if (s.inline_styles)
       
  7156 				t._convertInlineElements();
       
  7157 
       
  7158 			if (s.cleanup_callback) {
       
  7159 				t.onBeforeSetContent.add(function(ed, o) {
       
  7160 					o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);
       
  7161 				});
       
  7162 
       
  7163 				t.onPreProcess.add(function(ed, o) {
       
  7164 					if (o.set)
       
  7165 						t.execCallback('cleanup_callback', 'insert_to_editor_dom', o.node, o);
       
  7166 
       
  7167 					if (o.get)
       
  7168 						t.execCallback('cleanup_callback', 'get_from_editor_dom', o.node, o);
       
  7169 				});
       
  7170 
       
  7171 				t.onPostProcess.add(function(ed, o) {
       
  7172 					if (o.set)
       
  7173 						o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);
       
  7174 
       
  7175 					if (o.get)						
       
  7176 						o.content = t.execCallback('cleanup_callback', 'get_from_editor', o.content, o);
       
  7177 				});
       
  7178 			}
       
  7179 
       
  7180 			if (s.save_callback) {
       
  7181 				t.onGetContent.add(function(ed, o) {
       
  7182 					if (o.save)
       
  7183 						o.content = t.execCallback('save_callback', t.id, o.content, t.getBody());
       
  7184 				});
       
  7185 			}
       
  7186 
       
  7187 			if (s.handle_event_callback) {
       
  7188 				t.onEvent.add(function(ed, e, o) {
       
  7189 					if (t.execCallback('handle_event_callback', e, ed, o) === false)
       
  7190 						Event.cancel(e);
       
  7191 				});
       
  7192 			}
       
  7193 
       
  7194 			t.onSetContent.add(function() {
       
  7195 				// Safari needs some time, it will crash the browser when a link is created otherwise
       
  7196 				// I think this crash issue is resolved in the latest 3.0.4
       
  7197 				//window.setTimeout(function() {
       
  7198 					t.addVisual(t.getBody());
       
  7199 				//}, 1);
       
  7200 			});
       
  7201 
       
  7202 			// Remove empty contents
       
  7203 			if (s.padd_empty_editor) {
       
  7204 				t.onPostProcess.add(function(ed, o) {
       
  7205 					o.content = o.content.replace(/^(<p>(&nbsp;|&#160;|\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, '');
       
  7206 				});
       
  7207 			}
       
  7208 
       
  7209 			if (isGecko && !s.readonly) {
       
  7210 				try {
       
  7211 					// Design mode must be set here once again to fix a bug where
       
  7212 					// Ctrl+A/Delete/Backspace didn't work if the editor was added using mceAddControl then removed then added again
       
  7213 					d.designMode = 'Off';
       
  7214 					d.designMode = 'On';
       
  7215 				} catch (ex) {
       
  7216 					// Will fail on Gecko if the editor is placed in an hidden container element
       
  7217 					// The design mode will be set ones the editor is focused
       
  7218 				}
       
  7219 			}
       
  7220 
       
  7221 			// A small timeout was needed since firefox will remove. Bug: #1838304
       
  7222 			setTimeout(function () {
       
  7223 				if (t.removed)
       
  7224 					return;
       
  7225 
       
  7226 				t.load({initial : true, format : (s.cleanup_on_startup ? 'html' : 'raw')});
       
  7227 				t.startContent = t.getContent({format : 'raw'});
       
  7228 				t.undoManager.add({initial : true});
       
  7229 				t.initialized = true;
       
  7230 
       
  7231 				t.onInit.dispatch(t);
       
  7232 				t.execCallback('setupcontent_callback', t.id, t.getBody(), t.getDoc());
       
  7233 				t.execCallback('init_instance_callback', t);
       
  7234 				t.focus(true);
       
  7235 				t.nodeChanged({initial : 1});
       
  7236 
       
  7237 				// Load specified content CSS last
       
  7238 				if (s.content_css) {
       
  7239 					tinymce.each(explode(s.content_css), function(u) {
       
  7240 						t.dom.loadCSS(t.documentBaseURI.toAbsolute(u));
       
  7241 					});
       
  7242 				}
       
  7243 
       
  7244 				// Handle auto focus
       
  7245 				if (s.auto_focus) {
       
  7246 					setTimeout(function () {
       
  7247 						var ed = EditorManager.get(s.auto_focus);
       
  7248 
       
  7249 						ed.selection.select(ed.getBody(), 1);
       
  7250 						ed.selection.collapse(1);
       
  7251 						ed.getWin().focus();
       
  7252 					}, 100);
       
  7253 				}
       
  7254 			}, 1);
       
  7255 	
       
  7256 			e = null;
       
  7257 		},
       
  7258 
       
  7259 		
       
  7260 		focus : function(sf) {
       
  7261 			var oed, t = this, ce = t.settings.content_editable;
       
  7262 
       
  7263 			if (!sf) {
       
  7264 				// Is not content editable or the selection is outside the area in IE
       
  7265 				// the IE statement is needed to avoid bluring if element selections inside layers since
       
  7266 				// the layer is like it's own document in IE
       
  7267 				if (!ce && (!isIE || t.selection.getNode().ownerDocument != t.getDoc()))
       
  7268 					t.getWin().focus();
       
  7269 
       
  7270 							}
       
  7271 
       
  7272 			if (EditorManager.activeEditor != t) {
       
  7273 				if ((oed = EditorManager.activeEditor) != null)
       
  7274 					oed.onDeactivate.dispatch(oed, t);
       
  7275 
       
  7276 				t.onActivate.dispatch(t, oed);
       
  7277 			}
       
  7278 
       
  7279 			EditorManager._setActive(t);
       
  7280 		},
       
  7281 
       
  7282 		execCallback : function(n) {
       
  7283 			var t = this, f = t.settings[n], s;
       
  7284 
       
  7285 			if (!f)
       
  7286 				return;
       
  7287 
       
  7288 			// Look through lookup
       
  7289 			if (t.callbackLookup && (s = t.callbackLookup[n])) {
       
  7290 				f = s.func;
       
  7291 				s = s.scope;
       
  7292 			}
       
  7293 
       
  7294 			if (is(f, 'string')) {
       
  7295 				s = f.replace(/\.\w+$/, '');
       
  7296 				s = s ? tinymce.resolve(s) : 0;
       
  7297 				f = tinymce.resolve(f);
       
  7298 				t.callbackLookup = t.callbackLookup || {};
       
  7299 				t.callbackLookup[n] = {func : f, scope : s};
       
  7300 			}
       
  7301 
       
  7302 			return f.apply(s || t, Array.prototype.slice.call(arguments, 1));
       
  7303 		},
       
  7304 
       
  7305 		translate : function(s) {
       
  7306 			var c = this.settings.language || 'en', i18n = EditorManager.i18n;
       
  7307 
       
  7308 			if (!s)
       
  7309 				return '';
       
  7310 
       
  7311 			return i18n[c + '.' + s] || s.replace(/{\#([^}]+)\}/g, function(a, b) {
       
  7312 				return i18n[c + '.' + b] || '{#' + b + '}';
       
  7313 			});
       
  7314 		},
       
  7315 
       
  7316 		getLang : function(n, dv) {
       
  7317 			return EditorManager.i18n[(this.settings.language || 'en') + '.' + n] || (is(dv) ? dv : '{#' + n + '}');
       
  7318 		},
       
  7319 
       
  7320 		getParam : function(n, dv, ty) {
       
  7321 			var tr = tinymce.trim, v = is(this.settings[n]) ? this.settings[n] : dv, o;
       
  7322 
       
  7323 			if (ty === 'hash') {
       
  7324 				o = {};
       
  7325 
       
  7326 				if (is(v, 'string')) {
       
  7327 					each(v.indexOf('=') > 0 ? v.split(/[;,](?![^=;,]*(?:[;,]|$))/) : v.split(','), function(v) {
       
  7328 						v = v.split('=');
       
  7329 
       
  7330 						if (v.length > 1)
       
  7331 							o[tr(v[0])] = tr(v[1]);
       
  7332 						else
       
  7333 							o[tr(v[0])] = tr(v);
       
  7334 					});
       
  7335 				} else
       
  7336 					o = v;
       
  7337 
       
  7338 				return o;
       
  7339 			}
       
  7340 
       
  7341 			return v;
       
  7342 		},
       
  7343 
       
  7344 		nodeChanged : function(o) {
       
  7345 			var t = this, s = t.selection, n = s.getNode() || t.getBody();
       
  7346 
       
  7347 			// Fix for bug #1896577 it seems that this can not be fired while the editor is loading
       
  7348 			if (t.initialized) {
       
  7349 				t.onNodeChange.dispatch(
       
  7350 					t,
       
  7351 					o ? o.controlManager || t.controlManager : t.controlManager,
       
  7352 					isIE && n.ownerDocument != t.getDoc() ? t.getBody() : n, // Fix for IE initial state
       
  7353 					s.isCollapsed(),
       
  7354 					o
       
  7355 				);
       
  7356 			}
       
  7357 		},
       
  7358 
       
  7359 		addButton : function(n, s) {
       
  7360 			var t = this;
       
  7361 
       
  7362 			t.buttons = t.buttons || {};
       
  7363 			t.buttons[n] = s;
       
  7364 		},
       
  7365 
       
  7366 		addCommand : function(n, f, s) {
       
  7367 			this.execCommands[n] = {func : f, scope : s || this};
       
  7368 		},
       
  7369 
       
  7370 		addQueryStateHandler : function(n, f, s) {
       
  7371 			this.queryStateCommands[n] = {func : f, scope : s || this};
       
  7372 		},
       
  7373 
       
  7374 		addQueryValueHandler : function(n, f, s) {
       
  7375 			this.queryValueCommands[n] = {func : f, scope : s || this};
       
  7376 		},
       
  7377 
       
  7378 		addShortcut : function(pa, desc, cmd_func, sc) {
       
  7379 			var t = this, c;
       
  7380 
       
  7381 			if (!t.settings.custom_shortcuts)
       
  7382 				return false;
       
  7383 
       
  7384 			t.shortcuts = t.shortcuts || {};
       
  7385 
       
  7386 			if (is(cmd_func, 'string')) {
       
  7387 				c = cmd_func;
       
  7388 
       
  7389 				cmd_func = function() {
       
  7390 					t.execCommand(c, false, null);
       
  7391 				};
       
  7392 			}
       
  7393 
       
  7394 			if (is(cmd_func, 'object')) {
       
  7395 				c = cmd_func;
       
  7396 
       
  7397 				cmd_func = function() {
       
  7398 					t.execCommand(c[0], c[1], c[2]);
       
  7399 				};
       
  7400 			}
       
  7401 
       
  7402 			each(explode(pa), function(pa) {
       
  7403 				var o = {
       
  7404 					func : cmd_func,
       
  7405 					scope : sc || this,
       
  7406 					desc : desc,
       
  7407 					alt : false,
       
  7408 					ctrl : false,
       
  7409 					shift : false
       
  7410 				};
       
  7411 
       
  7412 				each(explode(pa, '+'), function(v) {
       
  7413 					switch (v) {
       
  7414 						case 'alt':
       
  7415 						case 'ctrl':
       
  7416 						case 'shift':
       
  7417 							o[v] = true;
       
  7418 							break;
       
  7419 
       
  7420 						default:
       
  7421 							o.charCode = v.charCodeAt(0);
       
  7422 							o.keyCode = v.toUpperCase().charCodeAt(0);
       
  7423 					}
       
  7424 				});
       
  7425 
       
  7426 				t.shortcuts[(o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode] = o;
       
  7427 			});
       
  7428 
       
  7429 			return true;
       
  7430 		},
       
  7431 
       
  7432 		execCommand : function(cmd, ui, val, a) {
       
  7433 			var t = this, s = 0, o, st;
       
  7434 
       
  7435 			if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus))
       
  7436 				t.focus();
       
  7437 
       
  7438 			o = {};
       
  7439 			t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o);
       
  7440 			if (o.terminate)
       
  7441 				return false;
       
  7442 
       
  7443 			// Command callback
       
  7444 			if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) {
       
  7445 				t.onExecCommand.dispatch(t, cmd, ui, val, a);
       
  7446 				return true;
       
  7447 			}
       
  7448 
       
  7449 			// Registred commands
       
  7450 			if (o = t.execCommands[cmd]) {
       
  7451 				st = o.func.call(o.scope, ui, val);
       
  7452 
       
  7453 				// Fall through on true
       
  7454 				if (st !== true) {
       
  7455 					t.onExecCommand.dispatch(t, cmd, ui, val, a);
       
  7456 					return st;
       
  7457 				}
       
  7458 			}
       
  7459 
       
  7460 			// Plugin commands
       
  7461 			each(t.plugins, function(p) {
       
  7462 				if (p.execCommand && p.execCommand(cmd, ui, val)) {
       
  7463 					t.onExecCommand.dispatch(t, cmd, ui, val, a);
       
  7464 					s = 1;
       
  7465 					return false;
       
  7466 				}
       
  7467 			});
       
  7468 
       
  7469 			if (s)
       
  7470 				return true;
       
  7471 
       
  7472 			// Theme commands
       
  7473 			if (t.theme.execCommand && t.theme.execCommand(cmd, ui, val)) {
       
  7474 				t.onExecCommand.dispatch(t, cmd, ui, val, a);
       
  7475 				return true;
       
  7476 			}
       
  7477 
       
  7478 			// Editor commands
       
  7479 			if (t.editorCommands.execCommand(cmd, ui, val)) {
       
  7480 				t.onExecCommand.dispatch(t, cmd, ui, val, a);
       
  7481 				return true;
       
  7482 			}
       
  7483 
       
  7484 			// Browser commands
       
  7485 			t.getDoc().execCommand(cmd, ui, val);
       
  7486 			t.onExecCommand.dispatch(t, cmd, ui, val, a);
       
  7487 		},
       
  7488 
       
  7489 		queryCommandState : function(c) {
       
  7490 			var t = this, o, s;
       
  7491 
       
  7492 			// Is hidden then return undefined
       
  7493 			if (t._isHidden())
       
  7494 				return;
       
  7495 
       
  7496 			// Registred commands
       
  7497 			if (o = t.queryStateCommands[c]) {
       
  7498 				s = o.func.call(o.scope);
       
  7499 
       
  7500 				// Fall though on true
       
  7501 				if (s !== true)
       
  7502 					return s;
       
  7503 			}
       
  7504 
       
  7505 			// Registred commands
       
  7506 			o = t.editorCommands.queryCommandState(c);
       
  7507 			if (o !== -1)
       
  7508 				return o;
       
  7509 
       
  7510 			// Browser commands
       
  7511 			try {
       
  7512 				return this.getDoc().queryCommandState(c);
       
  7513 			} catch (ex) {
       
  7514 				// Fails sometimes see bug: 1896577
       
  7515 			}
       
  7516 		},
       
  7517 
       
  7518 		queryCommandValue : function(c) {
       
  7519 			var t = this, o, s;
       
  7520 
       
  7521 			// Is hidden then return undefined
       
  7522 			if (t._isHidden())
       
  7523 				return;
       
  7524 
       
  7525 			// Registred commands
       
  7526 			if (o = t.queryValueCommands[c]) {
       
  7527 				s = o.func.call(o.scope);
       
  7528 
       
  7529 				// Fall though on true
       
  7530 				if (s !== true)
       
  7531 					return s;
       
  7532 			}
       
  7533 
       
  7534 			// Registred commands
       
  7535 			o = t.editorCommands.queryCommandValue(c);
       
  7536 			if (is(o))
       
  7537 				return o;
       
  7538 
       
  7539 			// Browser commands
       
  7540 			try {
       
  7541 				return this.getDoc().queryCommandValue(c);
       
  7542 			} catch (ex) {
       
  7543 				// Fails sometimes see bug: 1896577
       
  7544 			}
       
  7545 		},
       
  7546 
       
  7547 		show : function() {
       
  7548 			var t = this;
       
  7549 
       
  7550 			DOM.show(t.getContainer());
       
  7551 			DOM.hide(t.id);
       
  7552 			t.load();
       
  7553 		},
       
  7554 
       
  7555 		hide : function() {
       
  7556 			var t = this, d = t.getDoc();
       
  7557 
       
  7558 			// Fixed bug where IE has a blinking cursor left from the editor
       
  7559 			if (isIE && d)
       
  7560 				d.execCommand('SelectAll');
       
  7561 
       
  7562 			// We must save before we hide so Safari doesn't crash
       
  7563 			t.save();
       
  7564 			DOM.hide(t.getContainer());
       
  7565 			DOM.setStyle(t.id, 'display', t.orgDisplay);
       
  7566 		},
       
  7567 
       
  7568 		isHidden : function() {
       
  7569 			return !DOM.isHidden(this.id);
       
  7570 		},
       
  7571 
       
  7572 		setProgressState : function(b, ti, o) {
       
  7573 			this.onSetProgressState.dispatch(this, b, ti, o);
       
  7574 
       
  7575 			return b;
       
  7576 		},
       
  7577 
       
  7578 		resizeToContent : function() {
       
  7579 			var t = this;
       
  7580 
       
  7581 			DOM.setStyle(t.id + "_ifr", 'height', t.getBody().scrollHeight);
       
  7582 		},
       
  7583 
       
  7584 		load : function(o) {
       
  7585 			var t = this, e = t.getElement(), h;
       
  7586 
       
  7587 			o = o || {};
       
  7588 			o.load = true;
       
  7589 
       
  7590 			h = t.setContent(is(e.value) ? e.value : e.innerHTML, o);
       
  7591 			o.element = e;
       
  7592 
       
  7593 			if (!o.no_events)
       
  7594 				t.onLoadContent.dispatch(t, o);
       
  7595 
       
  7596 			o.element = e = null;
       
  7597 
       
  7598 			return h;
       
  7599 		},
       
  7600 
       
  7601 		save : function(o) {
       
  7602 			var t = this, e = t.getElement(), h, f;
       
  7603 
       
  7604 			if (!t.initialized)
       
  7605 				return;
       
  7606 
       
  7607 			o = o || {};
       
  7608 			o.save = true;
       
  7609 
       
  7610 			// Add undo level will trigger onchange event
       
  7611 			if (!o.no_events) {
       
  7612 				t.undoManager.typing = 0;
       
  7613 				t.undoManager.add();
       
  7614 			}
       
  7615 
       
  7616 			o.element = e;
       
  7617 			h = o.content = t.getContent(o);
       
  7618 
       
  7619 			if (!o.no_events)
       
  7620 				t.onSaveContent.dispatch(t, o);
       
  7621 
       
  7622 			h = o.content;
       
  7623 
       
  7624 			if (!/TEXTAREA|INPUT/i.test(e.nodeName)) {
       
  7625 				e.innerHTML = h;
       
  7626 
       
  7627 				// Update hidden form element
       
  7628 				if (f = DOM.getParent(t.id, 'form')) {
       
  7629 					each(f.elements, function(e) {
       
  7630 						if (e.name == t.id) {
       
  7631 							e.value = h;
       
  7632 							return false;
       
  7633 						}
       
  7634 					});
       
  7635 				}
       
  7636 			} else
       
  7637 				e.value = h;
       
  7638 
       
  7639 			o.element = e = null;
       
  7640 
       
  7641 			return h;
       
  7642 		},
       
  7643 
       
  7644 		setContent : function(h, o) {
       
  7645 			var t = this;
       
  7646 
       
  7647 			o = o || {};
       
  7648 			o.format = o.format || 'html';
       
  7649 			o.set = true;
       
  7650 			o.content = h;
       
  7651 
       
  7652 			if (!o.no_events)
       
  7653 				t.onBeforeSetContent.dispatch(t, o);
       
  7654 
       
  7655 			// Padd empty content in Gecko and Safari. Commands will otherwise fail on the content
       
  7656 			// It will also be impossible to place the caret in the editor unless there is a BR element present
       
  7657 			if (!tinymce.isIE && (h.length === 0 || /^\s+$/.test(h))) {
       
  7658 				o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />');
       
  7659 				o.format = 'raw';
       
  7660 			}
       
  7661 
       
  7662 			o.content = t.dom.setHTML(t.getBody(), tinymce.trim(o.content));
       
  7663 
       
  7664 			if (o.format != 'raw' && t.settings.cleanup) {
       
  7665 				o.getInner = true;
       
  7666 				o.content = t.dom.setHTML(t.getBody(), t.serializer.serialize(t.getBody(), o));
       
  7667 			}
       
  7668 
       
  7669 			if (!o.no_events)
       
  7670 				t.onSetContent.dispatch(t, o);
       
  7671 
       
  7672 			return o.content;
       
  7673 		},
       
  7674 
       
  7675 		getContent : function(o) {
       
  7676 			var t = this, h;
       
  7677 
       
  7678 			o = o || {};
       
  7679 			o.format = o.format || 'html';
       
  7680 			o.get = true;
       
  7681 
       
  7682 			if (!o.no_events)
       
  7683 				t.onBeforeGetContent.dispatch(t, o);
       
  7684 
       
  7685 			if (o.format != 'raw' && t.settings.cleanup) {
       
  7686 				o.getInner = true;
       
  7687 				h = t.serializer.serialize(t.getBody(), o);
       
  7688 			} else
       
  7689 				h = t.getBody().innerHTML;
       
  7690 
       
  7691 			h = h.replace(/^\s*|\s*$/g, '');
       
  7692 			o.content = h;
       
  7693 
       
  7694 			if (!o.no_events)
       
  7695 				t.onGetContent.dispatch(t, o);
       
  7696 
       
  7697 			return o.content;
       
  7698 		},
       
  7699 
       
  7700 		isDirty : function() {
       
  7701 			var t = this;
       
  7702 
       
  7703 			return tinymce.trim(t.startContent) != tinymce.trim(t.getContent({format : 'raw', no_events : 1})) && !t.isNotDirty;
       
  7704 		},
       
  7705 
       
  7706 		getContainer : function() {
       
  7707 			var t = this;
       
  7708 
       
  7709 			if (!t.container)
       
  7710 				t.container = DOM.get(t.editorContainer || t.id + '_parent');
       
  7711 
       
  7712 			return t.container;
       
  7713 		},
       
  7714 
       
  7715 		getContentAreaContainer : function() {
       
  7716 			return this.contentAreaContainer;
       
  7717 		},
       
  7718 
       
  7719 		getElement : function() {
       
  7720 			return DOM.get(this.settings.content_element || this.id);
       
  7721 		},
       
  7722 
       
  7723 		getWin : function() {
       
  7724 			var t = this, e;
       
  7725 
       
  7726 			if (!t.contentWindow) {
       
  7727 				e = DOM.get(t.id + "_ifr");
       
  7728 
       
  7729 				if (e)
       
  7730 					t.contentWindow = e.contentWindow;
       
  7731 			}
       
  7732 
       
  7733 			return t.contentWindow;
       
  7734 		},
       
  7735 
       
  7736 		getDoc : function() {
       
  7737 			var t = this, w;
       
  7738 
       
  7739 			if (!t.contentDocument) {
       
  7740 				w = t.getWin();
       
  7741 
       
  7742 				if (w)
       
  7743 					t.contentDocument = w.document;
       
  7744 			}
       
  7745 
       
  7746 			return t.contentDocument;
       
  7747 		},
       
  7748 
       
  7749 		getBody : function() {
       
  7750 			return this.bodyElement || this.getDoc().body;
       
  7751 		},
       
  7752 
       
  7753 		convertURL : function(u, n, e) {
       
  7754 			var t = this, s = t.settings;
       
  7755 
       
  7756 			// Use callback instead
       
  7757 			if (s.urlconverter_callback)
       
  7758 				return t.execCallback('urlconverter_callback', u, e, true, n);
       
  7759 
       
  7760 			// Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs
       
  7761 			if (!s.convert_urls || (e && e.nodeName == 'LINK') || u.indexOf('file:') === 0)
       
  7762 				return u;
       
  7763 
       
  7764 			// Convert to relative
       
  7765 			if (s.relative_urls)
       
  7766 				return t.documentBaseURI.toRelative(u);
       
  7767 
       
  7768 			// Convert to absolute
       
  7769 			u = t.documentBaseURI.toAbsolute(u, s.remove_script_host);
       
  7770 
       
  7771 			return u;
       
  7772 		},
       
  7773 
       
  7774 		addVisual : function(e) {
       
  7775 			var t = this, s = t.settings;
       
  7776 
       
  7777 			e = e || t.getBody();
       
  7778 
       
  7779 			if (!is(t.hasVisual))
       
  7780 				t.hasVisual = s.visual;
       
  7781 
       
  7782 			each(t.dom.select('table,a', e), function(e) {
       
  7783 				var v;
       
  7784 
       
  7785 				switch (e.nodeName) {
       
  7786 					case 'TABLE':
       
  7787 						v = t.dom.getAttrib(e, 'border');
       
  7788 
       
  7789 						if (!v || v == '0') {
       
  7790 							if (t.hasVisual)
       
  7791 								t.dom.addClass(e, s.visual_table_class);
       
  7792 							else
       
  7793 								t.dom.removeClass(e, s.visual_table_class);
       
  7794 						}
       
  7795 
       
  7796 						return;
       
  7797 
       
  7798 					case 'A':
       
  7799 						v = t.dom.getAttrib(e, 'name');
       
  7800 
       
  7801 						if (v) {
       
  7802 							if (t.hasVisual)
       
  7803 								t.dom.addClass(e, 'mceItemAnchor');
       
  7804 							else
       
  7805 								t.dom.removeClass(e, 'mceItemAnchor');
       
  7806 						}
       
  7807 
       
  7808 						return;
       
  7809 				}
       
  7810 			});
       
  7811 
       
  7812 			t.onVisualAid.dispatch(t, e, t.hasVisual);
       
  7813 		},
       
  7814 
       
  7815 		remove : function() {
       
  7816 			var t = this, e = t.getContainer();
       
  7817 
       
  7818 			t.removed = 1; // Cancels post remove event execution
       
  7819 			t.hide();
       
  7820 
       
  7821 			t.execCallback('remove_instance_callback', t);
       
  7822 			t.onRemove.dispatch(t);
       
  7823 
       
  7824 			// Clear all execCommand listeners this is required to avoid errors if the editor was removed inside another command
       
  7825 			t.onExecCommand.listeners = [];
       
  7826 
       
  7827 			EditorManager.remove(t);
       
  7828 			DOM.remove(e);
       
  7829 		},
       
  7830 
       
  7831 		destroy : function(s) {
       
  7832 			var t = this;
       
  7833 
       
  7834 			// One time is enough
       
  7835 			if (t.destroyed)
       
  7836 				return;
       
  7837 
       
  7838 			if (!s) {
       
  7839 				tinymce.removeUnload(t.destroy);
       
  7840 				tinyMCE.onBeforeUnload.remove(t._beforeUnload);
       
  7841 
       
  7842 				// Manual destroy
       
  7843 				if (t.theme.destroy)
       
  7844 					t.theme.destroy();
       
  7845 
       
  7846 				// Destroy controls, selection and dom
       
  7847 				t.controlManager.destroy();
       
  7848 				t.selection.destroy();
       
  7849 				t.dom.destroy();
       
  7850 
       
  7851 				// Remove all events
       
  7852 
       
  7853 				// Don't clear the window or document if content editable
       
  7854 				// is enabled since other instances might still be present
       
  7855 				if (!t.settings.content_editable) {
       
  7856 					Event.clear(t.getWin());
       
  7857 					Event.clear(t.getDoc());
       
  7858 				}
       
  7859 
       
  7860 				Event.clear(t.getBody());
       
  7861 				Event.clear(t.formElement);
       
  7862 			}
       
  7863 
       
  7864 			if (t.formElement) {
       
  7865 				t.formElement.submit = t.formElement._mceOldSubmit;
       
  7866 				t.formElement._mceOldSubmit = null;
       
  7867 			}
       
  7868 
       
  7869 			t.contentAreaContainer = t.formElement = t.container = t.settings.content_element = t.bodyElement = t.contentDocument = t.contentWindow = null;
       
  7870 
       
  7871 			if (t.selection)
       
  7872 				t.selection = t.selection.win = t.selection.dom = t.selection.dom.doc = null;
       
  7873 
       
  7874 			t.destroyed = 1;
       
  7875 		},
       
  7876 
       
  7877 		// Internal functions
       
  7878 
       
  7879 		_addEvents : function() {
       
  7880 			// 'focus', 'blur', 'dblclick', 'beforedeactivate', submit, reset
       
  7881 			var t = this, i, s = t.settings, lo = {
       
  7882 				mouseup : 'onMouseUp',
       
  7883 				mousedown : 'onMouseDown',
       
  7884 				click : 'onClick',
       
  7885 				keyup : 'onKeyUp',
       
  7886 				keydown : 'onKeyDown',
       
  7887 				keypress : 'onKeyPress',
       
  7888 				submit : 'onSubmit',
       
  7889 				reset : 'onReset',
       
  7890 				contextmenu : 'onContextMenu',
       
  7891 				dblclick : 'onDblClick',
       
  7892 				paste : 'onPaste' // Doesn't work in all browsers yet
       
  7893 			};
       
  7894 
       
  7895 			function eventHandler(e, o) {
       
  7896 				var ty = e.type;
       
  7897 
       
  7898 				// Don't fire events when it's removed
       
  7899 				if (t.removed)
       
  7900 					return;
       
  7901 
       
  7902 				// Generic event handler
       
  7903 				if (t.onEvent.dispatch(t, e, o) !== false) {
       
  7904 					// Specific event handler
       
  7905 					t[lo[e.fakeType || e.type]].dispatch(t, e, o);
       
  7906 				}
       
  7907 			};
       
  7908 
       
  7909 			// Add DOM events
       
  7910 			each(lo, function(v, k) {
       
  7911 				switch (k) {
       
  7912 					case 'contextmenu':
       
  7913 						if (tinymce.isOpera) {
       
  7914 							// Fake contextmenu on Opera
       
  7915 							Event.add(t.getBody(), 'mousedown', function(e) {
       
  7916 								if (e.ctrlKey) {
       
  7917 									e.fakeType = 'contextmenu';
       
  7918 									eventHandler(e);
       
  7919 								}
       
  7920 							});
       
  7921 						} else
       
  7922 							Event.add(t.getBody(), k, eventHandler);
       
  7923 						break;
       
  7924 
       
  7925 					case 'paste':
       
  7926 						Event.add(t.getBody(), k, function(e) {
       
  7927 							var tx, h, el, r;
       
  7928 
       
  7929 							// Get plain text data
       
  7930 							if (e.clipboardData)
       
  7931 								tx = e.clipboardData.getData('text/plain');
       
  7932 							else if (tinymce.isIE)
       
  7933 								tx = t.getWin().clipboardData.getData('Text');
       
  7934 
       
  7935 							// Get HTML data
       
  7936 							/*if (tinymce.isIE) {
       
  7937 								el = DOM.add(DOM.doc.body, 'div', {style : 'visibility:hidden;overflow:hidden;position:absolute;width:1px;height:1px'});
       
  7938 								r = DOM.doc.body.createTextRange();
       
  7939 								r.moveToElementText(el);
       
  7940 								r.execCommand('Paste');
       
  7941 								h = el.innerHTML;
       
  7942 								DOM.remove(el);
       
  7943 							}*/
       
  7944 
       
  7945 							eventHandler(e, {text : tx, html : h});
       
  7946 						});
       
  7947 						break;
       
  7948 
       
  7949 					case 'submit':
       
  7950 					case 'reset':
       
  7951 						Event.add(t.getElement().form || DOM.getParent(t.id, 'form'), k, eventHandler);
       
  7952 						break;
       
  7953 
       
  7954 					default:
       
  7955 						Event.add(s.content_editable ? t.getBody() : t.getDoc(), k, eventHandler);
       
  7956 				}
       
  7957 			});
       
  7958 
       
  7959 			Event.add(s.content_editable ? t.getBody() : (isGecko ? t.getDoc() : t.getWin()), 'focus', function(e) {
       
  7960 				t.focus(true);
       
  7961 			});
       
  7962 
       
  7963 			
       
  7964 			// Fixes bug where a specified document_base_uri could result in broken images
       
  7965 			// This will also fix drag drop of images in Gecko
       
  7966 			if (tinymce.isGecko) {
       
  7967 				// Convert all images to absolute URLs
       
  7968 /*				t.onSetContent.add(function(ed, o) {
       
  7969 					each(ed.dom.select('img'), function(e) {
       
  7970 						var v;
       
  7971 
       
  7972 						if (v = e.getAttribute('mce_src'))
       
  7973 							e.src = t.documentBaseURI.toAbsolute(v);
       
  7974 					})
       
  7975 				});*/
       
  7976 
       
  7977 				Event.add(t.getDoc(), 'DOMNodeInserted', function(e) {
       
  7978 					var v;
       
  7979 
       
  7980 					e = e.target;
       
  7981 
       
  7982 					if (e.nodeType === 1 && e.nodeName === 'IMG' && (v = e.getAttribute('mce_src')))
       
  7983 						e.src = t.documentBaseURI.toAbsolute(v);
       
  7984 				});
       
  7985 			}
       
  7986 
       
  7987 			// Set various midas options in Gecko
       
  7988 			if (isGecko) {
       
  7989 				function setOpts() {
       
  7990 					var t = this, d = t.getDoc(), s = t.settings;
       
  7991 
       
  7992 					if (isGecko && !s.readonly) {
       
  7993 						if (t._isHidden()) {
       
  7994 							try {
       
  7995 								if (!s.content_editable)
       
  7996 									d.designMode = 'On';
       
  7997 							} catch (ex) {
       
  7998 								// Fails if it's hidden
       
  7999 							}
       
  8000 						}
       
  8001 
       
  8002 						try {
       
  8003 							// Try new Gecko method
       
  8004 							d.execCommand("styleWithCSS", 0, false);
       
  8005 						} catch (ex) {
       
  8006 							// Use old method
       
  8007 							if (!t._isHidden())
       
  8008 								try {d.execCommand("useCSS", 0, true);} catch (ex) {}
       
  8009 						}
       
  8010 
       
  8011 						if (!s.table_inline_editing)
       
  8012 							try {d.execCommand('enableInlineTableEditing', false, false);} catch (ex) {}
       
  8013 
       
  8014 						if (!s.object_resizing)
       
  8015 							try {d.execCommand('enableObjectResizing', false, false);} catch (ex) {}
       
  8016 					}
       
  8017 				};
       
  8018 
       
  8019 				t.onBeforeExecCommand.add(setOpts);
       
  8020 				t.onMouseDown.add(setOpts);
       
  8021 			}
       
  8022 
       
  8023 			// Add node change handlers
       
  8024 			t.onMouseUp.add(t.nodeChanged);
       
  8025 			t.onClick.add(t.nodeChanged);
       
  8026 			t.onKeyUp.add(function(ed, e) {
       
  8027 				var c = e.keyCode;
       
  8028 
       
  8029 				if ((c >= 33 && c <= 36) || (c >= 37 && c <= 40) || c == 13 || c == 45 || c == 46 || c == 8 || (tinymce.isMac && c >= 91 && c <= 93) || e.ctrlKey)
       
  8030 					t.nodeChanged();
       
  8031 			});
       
  8032 
       
  8033 			// Add reset handler
       
  8034 			t.onReset.add(function() {
       
  8035 				t.setContent(t.startContent, {format : 'raw'});
       
  8036 			});
       
  8037 
       
  8038 			if (t.getParam('tab_focus')) {
       
  8039 				function tabCancel(ed, e) {
       
  8040 					if (e.keyCode === 9)
       
  8041 						return Event.cancel(e);
       
  8042 				};
       
  8043 
       
  8044 				function tabHandler(ed, e) {
       
  8045 					var x, i, f, el, v;
       
  8046 
       
  8047 					function find(d) {
       
  8048 						f = DOM.getParent(ed.id, 'form');
       
  8049 						el = f.elements;
       
  8050 
       
  8051 						if (f) {
       
  8052 							each(el, function(e, i) {
       
  8053 								if (e.id == ed.id) {
       
  8054 									x = i;
       
  8055 									return false;
       
  8056 								}
       
  8057 							});
       
  8058 
       
  8059 							if (d > 0) {
       
  8060 								for (i = x + 1; i < el.length; i++) {
       
  8061 									if (el[i].type != 'hidden')
       
  8062 										return el[i];
       
  8063 								}
       
  8064 							} else {
       
  8065 								for (i = x - 1; i >= 0; i--) {
       
  8066 									if (el[i].type != 'hidden')
       
  8067 										return el[i];
       
  8068 								}
       
  8069 							}
       
  8070 						}
       
  8071 
       
  8072 						return null;
       
  8073 					};
       
  8074 
       
  8075 					if (e.keyCode === 9) {
       
  8076 						v = explode(ed.getParam('tab_focus'));
       
  8077 
       
  8078 						if (v.length == 1) {
       
  8079 							v[1] = v[0];
       
  8080 							v[0] = ':prev';
       
  8081 						}
       
  8082 
       
  8083 						// Find element to focus
       
  8084 						if (e.shiftKey) {
       
  8085 							if (v[0] == ':prev')
       
  8086 								el = find(-1);
       
  8087 							else
       
  8088 								el = DOM.get(v[0]);
       
  8089 						} else {
       
  8090 							if (v[1] == ':next')
       
  8091 								el = find(1);
       
  8092 							else
       
  8093 								el = DOM.get(v[1]);
       
  8094 						}
       
  8095 
       
  8096 						if (el) {
       
  8097 							if (ed = EditorManager.get(el.id || el.name))
       
  8098 								ed.focus();
       
  8099 							else
       
  8100 								window.setTimeout(function() {window.focus();el.focus();}, 10);
       
  8101 
       
  8102 							return Event.cancel(e);
       
  8103 						}
       
  8104 					}
       
  8105 				};
       
  8106 
       
  8107 				t.onKeyUp.add(tabCancel);
       
  8108 
       
  8109 				if (isGecko) {
       
  8110 					t.onKeyPress.add(tabHandler);
       
  8111 					t.onKeyDown.add(tabCancel);
       
  8112 				} else
       
  8113 					t.onKeyDown.add(tabHandler);
       
  8114 			}
       
  8115 
       
  8116 			// Add shortcuts
       
  8117 			if (s.custom_shortcuts) {
       
  8118 				if (s.custom_undo_redo_keyboard_shortcuts) {
       
  8119 					t.addShortcut('ctrl+z', t.getLang('undo_desc'), 'Undo');
       
  8120 					t.addShortcut('ctrl+y', t.getLang('redo_desc'), 'Redo');
       
  8121 				}
       
  8122 
       
  8123 				// Add default shortcuts for gecko
       
  8124 				if (isGecko) {
       
  8125 					t.addShortcut('ctrl+b', t.getLang('bold_desc'), 'Bold');
       
  8126 					t.addShortcut('ctrl+i', t.getLang('italic_desc'), 'Italic');
       
  8127 					t.addShortcut('ctrl+u', t.getLang('underline_desc'), 'Underline');
       
  8128 				}
       
  8129 
       
  8130 				// BlockFormat shortcuts keys
       
  8131 				for (i=1; i<=6; i++)
       
  8132 					t.addShortcut('ctrl+' + i, '', ['FormatBlock', false, '<h' + i + '>']);
       
  8133 
       
  8134 				t.addShortcut('ctrl+7', '', ['FormatBlock', false, '<p>']);
       
  8135 				t.addShortcut('ctrl+8', '', ['FormatBlock', false, '<div>']);
       
  8136 				t.addShortcut('ctrl+9', '', ['FormatBlock', false, '<address>']);
       
  8137 
       
  8138 				function find(e) {
       
  8139 					var v = null;
       
  8140 
       
  8141 					if (!e.altKey && !e.ctrlKey && !e.metaKey)
       
  8142 						return v;
       
  8143 
       
  8144 					each(t.shortcuts, function(o) {
       
  8145 						if (o.ctrl != e.ctrlKey && (!tinymce.isMac || o.ctrl == e.metaKey))
       
  8146 							return;
       
  8147 
       
  8148 						if (o.alt != e.altKey)
       
  8149 							return;
       
  8150 
       
  8151 						if (o.shift != e.shiftKey)
       
  8152 							return;
       
  8153 
       
  8154 						if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) {
       
  8155 							v = o;
       
  8156 							return false;
       
  8157 						}
       
  8158 					});
       
  8159 
       
  8160 					return v;
       
  8161 				};
       
  8162 
       
  8163 				t.onKeyUp.add(function(ed, e) {
       
  8164 					var o = find(e);
       
  8165 
       
  8166 					if (o)
       
  8167 						return Event.cancel(e);
       
  8168 				});
       
  8169 
       
  8170 				t.onKeyPress.add(function(ed, e) {
       
  8171 					var o = find(e);
       
  8172 
       
  8173 					if (o)
       
  8174 						return Event.cancel(e);
       
  8175 				});
       
  8176 
       
  8177 				t.onKeyDown.add(function(ed, e) {
       
  8178 					var o = find(e);
       
  8179 
       
  8180 					if (o) {
       
  8181 						o.func.call(o.scope);
       
  8182 						return Event.cancel(e);
       
  8183 					}
       
  8184 				});
       
  8185 			}
       
  8186 
       
  8187 			if (tinymce.isIE) {
       
  8188 				// Fix so resize will only update the width and height attributes not the styles of an image
       
  8189 				// It will also block mceItemNoResize items
       
  8190 				Event.add(t.getDoc(), 'controlselect', function(e) {
       
  8191 					var re = t.resizeInfo, cb;
       
  8192 
       
  8193 					e = e.target;
       
  8194 
       
  8195 					// Don't do this action for non image elements
       
  8196 					if (e.nodeName !== 'IMG')
       
  8197 						return;
       
  8198 
       
  8199 					if (re)
       
  8200 						Event.remove(re.node, re.ev, re.cb);
       
  8201 
       
  8202 					if (!t.dom.hasClass(e, 'mceItemNoResize')) {
       
  8203 						ev = 'resizeend';
       
  8204 						cb = Event.add(e, ev, function(e) {
       
  8205 							var v;
       
  8206 
       
  8207 							e = e.target;
       
  8208 
       
  8209 							if (v = t.dom.getStyle(e, 'width')) {
       
  8210 								t.dom.setAttrib(e, 'width', v.replace(/[^0-9%]+/g, ''));
       
  8211 								t.dom.setStyle(e, 'width', '');
       
  8212 							}
       
  8213 
       
  8214 							if (v = t.dom.getStyle(e, 'height')) {
       
  8215 								t.dom.setAttrib(e, 'height', v.replace(/[^0-9%]+/g, ''));
       
  8216 								t.dom.setStyle(e, 'height', '');
       
  8217 							}
       
  8218 						});
       
  8219 					} else {
       
  8220 						ev = 'resizestart';
       
  8221 						cb = Event.add(e, 'resizestart', Event.cancel, Event);
       
  8222 					}
       
  8223 
       
  8224 					re = t.resizeInfo = {
       
  8225 						node : e,
       
  8226 						ev : ev,
       
  8227 						cb : cb
       
  8228 					};
       
  8229 				});
       
  8230 
       
  8231 				t.onKeyDown.add(function(ed, e) {
       
  8232 					switch (e.keyCode) {
       
  8233 						case 8:
       
  8234 							// Fix IE control + backspace browser bug
       
  8235 							if (t.selection.getRng().item) {
       
  8236 								t.selection.getRng().item(0).removeNode();
       
  8237 								return Event.cancel(e);
       
  8238 							}
       
  8239 					}
       
  8240 				});
       
  8241 			}
       
  8242 
       
  8243 			if (tinymce.isOpera) {
       
  8244 				t.onClick.add(function(ed, e) {
       
  8245 					Event.prevent(e);
       
  8246 				});
       
  8247 			}
       
  8248 
       
  8249 			// Add custom undo/redo handlers
       
  8250 			if (s.custom_undo_redo) {
       
  8251 				function addUndo() {
       
  8252 					t.undoManager.typing = 0;
       
  8253 					t.undoManager.add();
       
  8254 				};
       
  8255 
       
  8256 				// Add undo level on editor blur
       
  8257 				if (tinymce.isIE) {
       
  8258 					Event.add(t.getWin(), 'blur', function(e) {
       
  8259 						var n;
       
  8260 
       
  8261 						// Check added for fullscreen bug
       
  8262 						if (t.selection) {
       
  8263 							n = t.selection.getNode();
       
  8264 
       
  8265 							// Add undo level is selection was lost to another document
       
  8266 							if (!t.removed && n.ownerDocument && n.ownerDocument != t.getDoc())
       
  8267 								addUndo();
       
  8268 						}
       
  8269 					});
       
  8270 				} else {
       
  8271 					Event.add(t.getDoc(), 'blur', function() {
       
  8272 						if (t.selection && !t.removed)
       
  8273 							addUndo();
       
  8274 					});
       
  8275 				}
       
  8276 
       
  8277 				t.onMouseDown.add(addUndo);
       
  8278 
       
  8279 				t.onKeyUp.add(function(ed, e) {
       
  8280 					if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.ctrlKey) {
       
  8281 						t.undoManager.typing = 0;
       
  8282 						t.undoManager.add();
       
  8283 					}
       
  8284 				});
       
  8285 
       
  8286 				t.onKeyDown.add(function(ed, e) {
       
  8287 					// Is caracter positon keys
       
  8288 					if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) {
       
  8289 						if (t.undoManager.typing) {
       
  8290 							t.undoManager.add();
       
  8291 							t.undoManager.typing = 0;
       
  8292 						}
       
  8293 
       
  8294 						return;
       
  8295 					}
       
  8296 
       
  8297 					if (!t.undoManager.typing) {
       
  8298 						t.undoManager.add();
       
  8299 						t.undoManager.typing = 1;
       
  8300 					}
       
  8301 				});
       
  8302 			}
       
  8303 		},
       
  8304 
       
  8305 		_convertInlineElements : function() {
       
  8306 			var t = this, s = t.settings, dom = t.dom, v, e, na, st, sp;
       
  8307 
       
  8308 			function convert(ed, o) {
       
  8309 				if (!s.inline_styles)
       
  8310 					return;
       
  8311 
       
  8312 				if (o.get) {
       
  8313 					each(t.dom.select('table,u,strike', o.node), function(n) {
       
  8314 						switch (n.nodeName) {
       
  8315 							case 'TABLE':
       
  8316 								if (v = dom.getAttrib(n, 'height')) {
       
  8317 									dom.setStyle(n, 'height', v);
       
  8318 									dom.setAttrib(n, 'height', '');
       
  8319 								}
       
  8320 								break;
       
  8321 
       
  8322 							case 'U':
       
  8323 							case 'STRIKE':
       
  8324 								//sp = dom.create('span', {style : dom.getAttrib(n, 'style')});
       
  8325 								n.style.textDecoration = n.nodeName == 'U' ? 'underline' : 'line-through';
       
  8326 								dom.setAttrib(n, 'mce_style', '');
       
  8327 								dom.setAttrib(n, 'mce_name', 'span');
       
  8328 								break;
       
  8329 						}
       
  8330 					});
       
  8331 				} else if (o.set) {
       
  8332 					each(t.dom.select('table,span', o.node).reverse(), function(n) {
       
  8333 						if (n.nodeName == 'TABLE') {
       
  8334 							if (v = dom.getStyle(n, 'height'))
       
  8335 								dom.setAttrib(n, 'height', v.replace(/[^0-9%]+/g, ''));
       
  8336 						} else {
       
  8337 							// Convert spans to elements
       
  8338 							if (n.style.textDecoration == 'underline')
       
  8339 								na = 'u';
       
  8340 							else if (n.style.textDecoration == 'line-through')
       
  8341 								na = 'strike';
       
  8342 							else
       
  8343 								na = '';
       
  8344 
       
  8345 							if (na) {
       
  8346 								n.style.textDecoration = '';
       
  8347 								dom.setAttrib(n, 'mce_style', '');
       
  8348 
       
  8349 								e = dom.create(na, {
       
  8350 									style : dom.getAttrib(n, 'style')
       
  8351 								});
       
  8352 
       
  8353 								dom.replace(e, n, 1);
       
  8354 							}
       
  8355 						}
       
  8356 					});
       
  8357 				}
       
  8358 			};
       
  8359 
       
  8360 			t.onPreProcess.add(convert);
       
  8361 
       
  8362 			if (!s.cleanup_on_startup) {
       
  8363 				t.onSetContent.add(function(ed, o) {
       
  8364 					if (o.initial)
       
  8365 						convert(t, {node : t.getBody(), set : 1});
       
  8366 				});
       
  8367 			}
       
  8368 		},
       
  8369 
       
  8370 		_convertFonts : function() {
       
  8371 			var t = this, s = t.settings, dom = t.dom, fz, fzn, sl, cl;
       
  8372 
       
  8373 			// No need
       
  8374 			if (!s.inline_styles)
       
  8375 				return;
       
  8376 
       
  8377 			// Font pt values and font size names
       
  8378 			fz = [8, 10, 12, 14, 18, 24, 36];
       
  8379 			fzn = ['xx-small', 'x-small','small','medium','large','x-large', 'xx-large'];
       
  8380 
       
  8381 			if (sl = s.font_size_style_values)
       
  8382 				sl = explode(sl);
       
  8383 
       
  8384 			if (cl = s.font_size_classes)
       
  8385 				cl = explode(cl);
       
  8386 
       
  8387 			function convertToFonts(no) {
       
  8388 				var n, f, nl, x, i, v, st;
       
  8389 
       
  8390 				// Convert spans to fonts on non WebKit browsers
       
  8391 				if (tinymce.isWebKit || !s.inline_styles)
       
  8392 					return;
       
  8393 
       
  8394 				nl = t.dom.select('span', no);
       
  8395 				for (x = nl.length - 1; x >= 0; x--) {
       
  8396 					n = nl[x];
       
  8397 
       
  8398 					f = dom.create('font', {
       
  8399 						color : dom.toHex(dom.getStyle(n, 'color')),
       
  8400 						face : dom.getStyle(n, 'fontFamily'),
       
  8401 						style : dom.getAttrib(n, 'style'),
       
  8402 						'class' : dom.getAttrib(n, 'class')
       
  8403 					});
       
  8404 
       
  8405 					// Clear color and font family
       
  8406 					st = f.style;
       
  8407 					if (st.color || st.fontFamily) {
       
  8408 						st.color = st.fontFamily = '';
       
  8409 						dom.setAttrib(f, 'mce_style', ''); // Remove cached style data
       
  8410 					}
       
  8411 
       
  8412 					if (sl) {
       
  8413 						i = inArray(sl, dom.getStyle(n, 'fontSize'));
       
  8414 
       
  8415 						if (i != -1) {
       
  8416 							dom.setAttrib(f, 'size', '' + (i + 1 || 1));
       
  8417 							//f.style.fontSize = '';
       
  8418 						}
       
  8419 					} else if (cl) {
       
  8420 						i = inArray(cl, dom.getAttrib(n, 'class'));
       
  8421 						v = dom.getStyle(n, 'fontSize');
       
  8422 
       
  8423 						if (i == -1 && v.indexOf('pt') > 0)
       
  8424 							i = inArray(fz, parseInt(v));
       
  8425 
       
  8426 						if (i == -1)
       
  8427 							i = inArray(fzn, v);
       
  8428 
       
  8429 						if (i != -1) {
       
  8430 							dom.setAttrib(f, 'size', '' + (i + 1 || 1));
       
  8431 							f.style.fontSize = '';
       
  8432 						}
       
  8433 					}
       
  8434 
       
  8435 					if (f.color || f.face || f.size) {
       
  8436 						f.style.fontFamily = '';
       
  8437 						dom.setAttrib(f, 'mce_style', '');
       
  8438 						dom.replace(f, n, 1);
       
  8439 					}
       
  8440 
       
  8441 					f = n = null;
       
  8442 				}
       
  8443 			};
       
  8444 
       
  8445 			// Run on setup
       
  8446 			t.onSetContent.add(function(ed, o) {
       
  8447 				convertToFonts(ed.getBody());
       
  8448 			});
       
  8449 
       
  8450 			// Run on cleanup
       
  8451 			t.onPreProcess.add(function(ed, o) {
       
  8452 				var n, sp, nl, x;
       
  8453 
       
  8454 				// Keep unit tests happy
       
  8455 				if (!s.inline_styles)
       
  8456 					return;
       
  8457 
       
  8458 				if (o.get) {
       
  8459 					nl = t.dom.select('font', o.node);
       
  8460 					for (x = nl.length - 1; x >= 0; x--) {
       
  8461 						n = nl[x];
       
  8462 
       
  8463 						sp = dom.create('span', {
       
  8464 							style : dom.getAttrib(n, 'style'),
       
  8465 							'class' : dom.getAttrib(n, 'class')
       
  8466 						});
       
  8467 
       
  8468 						dom.setStyles(sp, {
       
  8469 							fontFamily : dom.getAttrib(n, 'face'),
       
  8470 							color : dom.getAttrib(n, 'color'),
       
  8471 							backgroundColor : n.style.backgroundColor
       
  8472 						});
       
  8473 
       
  8474 						if (n.size) {
       
  8475 							if (sl)
       
  8476 								dom.setStyle(sp, 'fontSize', sl[parseInt(n.size) - 1]);
       
  8477 							else
       
  8478 								dom.setAttrib(sp, 'class', cl[parseInt(n.size) - 1]);
       
  8479 						}
       
  8480 
       
  8481 						dom.setAttrib(sp, 'mce_style', '');
       
  8482 						dom.replace(sp, n, 1);
       
  8483 					}
       
  8484 				}
       
  8485 			});
       
  8486 		},
       
  8487 
       
  8488 		_isHidden : function() {
       
  8489 			var s;
       
  8490 
       
  8491 			if (!isGecko)
       
  8492 				return 0;
       
  8493 
       
  8494 			// Weird, wheres that cursor selection?
       
  8495 			s = this.selection.getSel();
       
  8496 			return (!s || !s.rangeCount || s.rangeCount == 0);
       
  8497 		},
       
  8498 
       
  8499 		// Fix for bug #1867292
       
  8500 		_fixNesting : function(s) {
       
  8501 			var d = [], i;
       
  8502 
       
  8503 			s = s.replace(/<(\/)?([^\s>]+)[^>]*?>/g, function(a, b, c) {
       
  8504 				var e;
       
  8505 
       
  8506 				// Handle end element
       
  8507 				if (b === '/') {
       
  8508 					if (!d.length)
       
  8509 						return '';
       
  8510 
       
  8511 					if (c !== d[d.length - 1].tag) {
       
  8512 						for (i=d.length - 1; i>=0; i--) {
       
  8513 							if (d[i].tag === c) {
       
  8514 								d[i].close = 1;
       
  8515 								break;
       
  8516 							}
       
  8517 						}
       
  8518 
       
  8519 						return '';
       
  8520 					} else {
       
  8521 						d.pop();
       
  8522 
       
  8523 						if (d.length && d[d.length - 1].close) {
       
  8524 							a = a + '</' + d[d.length - 1].tag + '>';
       
  8525 							d.pop();
       
  8526 						}
       
  8527 					}
       
  8528 				} else {
       
  8529 					// Ignore these
       
  8530 					if (/^(br|hr|input|meta|img|link|param)$/i.test(c))
       
  8531 						return a;
       
  8532 
       
  8533 					// Ignore closed ones
       
  8534 					if (/\/>$/.test(a))
       
  8535 						return a;
       
  8536 
       
  8537 					d.push({tag : c}); // Push start element
       
  8538 				}
       
  8539 
       
  8540 				return a;
       
  8541 			});
       
  8542 
       
  8543 			// End all open tags
       
  8544 			for (i=d.length - 1; i>=0; i--)
       
  8545 				s += '</' + d[i].tag + '>';
       
  8546 
       
  8547 			return s;
       
  8548 		}
       
  8549 
       
  8550 		});
       
  8551 })();
       
  8552 
       
  8553 /* file:jscripts/tiny_mce/classes/EditorCommands.js */
       
  8554 
       
  8555 (function() {
       
  8556 	var each = tinymce.each, isIE = tinymce.isIE, isGecko = tinymce.isGecko, isOpera = tinymce.isOpera, isWebKit = tinymce.isWebKit;
       
  8557 
       
  8558 	tinymce.create('tinymce.EditorCommands', {
       
  8559 		EditorCommands : function(ed) {
       
  8560 			this.editor = ed;
       
  8561 		},
       
  8562 
       
  8563 		execCommand : function(cmd, ui, val) {
       
  8564 			var t = this, ed = t.editor, f;
       
  8565 
       
  8566 			switch (cmd) {
       
  8567 				case 'Cut':
       
  8568 				case 'Copy':
       
  8569 				case 'Paste':
       
  8570 					try {
       
  8571 						ed.getDoc().execCommand(cmd, ui, val);
       
  8572 					} catch (ex) {
       
  8573 						if (isGecko) {
       
  8574 							ed.windowManager.confirm(ed.getLang('clipboard_msg'), function(s) {
       
  8575 								if (s)
       
  8576 									window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal');
       
  8577 							});
       
  8578 						} else
       
  8579 							ed.windowManager.alert(ed.getLang('clipboard_no_support'));
       
  8580 					}
       
  8581 
       
  8582 					return true;
       
  8583 
       
  8584 				// Ignore these
       
  8585 				case 'mceResetDesignMode':
       
  8586 				case 'mceBeginUndoLevel':
       
  8587 					return true;
       
  8588 
       
  8589 				// Ignore these
       
  8590 				case 'unlink':
       
  8591 					t.UnLink();
       
  8592 					return true;
       
  8593 
       
  8594 				// Bundle these together
       
  8595 				case 'JustifyLeft':
       
  8596 				case 'JustifyCenter':
       
  8597 				case 'JustifyRight':
       
  8598 				case 'JustifyFull':
       
  8599 					t.mceJustify(cmd, cmd.substring(7).toLowerCase());
       
  8600 					return true;
       
  8601 
       
  8602 				case 'mceEndUndoLevel':
       
  8603 				case 'mceAddUndoLevel':
       
  8604 					ed.undoManager.add();
       
  8605 					return true;
       
  8606 
       
  8607 				default:
       
  8608 					f = this[cmd];
       
  8609 
       
  8610 					if (f) {
       
  8611 						f.call(this, ui, val);
       
  8612 						return true;
       
  8613 					}
       
  8614 			}
       
  8615 
       
  8616 			return false;
       
  8617 		},
       
  8618 
       
  8619 		Indent : function() {
       
  8620 			var ed = this.editor, d = ed.dom, s = ed.selection, e, iv, iu;
       
  8621 
       
  8622 			// Setup indent level
       
  8623 			iv = ed.settings.indentation;
       
  8624 			iu = /[a-z%]+$/i.exec(iv);
       
  8625 			iv = parseInt(iv);
       
  8626 
       
  8627 			if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {
       
  8628 				each(this._getSelectedBlocks(), function(e) {
       
  8629 					d.setStyle(e, 'paddingLeft', (parseInt(e.style.paddingLeft || 0) + iv) + iu);
       
  8630 				});
       
  8631 
       
  8632 				return;
       
  8633 			}
       
  8634 
       
  8635 			ed.getDoc().execCommand('Indent', false, null);
       
  8636 
       
  8637 			if (isIE) {
       
  8638 				d.getParent(s.getNode(), function(n) {
       
  8639 					if (n.nodeName == 'BLOCKQUOTE') {
       
  8640 						n.dir = n.style.cssText = '';
       
  8641 					}
       
  8642 				});
       
  8643 			}
       
  8644 		},
       
  8645 
       
  8646 		Outdent : function() {
       
  8647 			var ed = this.editor, d = ed.dom, s = ed.selection, e, v, iv, iu;
       
  8648 
       
  8649 			// Setup indent level
       
  8650 			iv = ed.settings.indentation;
       
  8651 			iu = /[a-z%]+$/i.exec(iv);
       
  8652 			iv = parseInt(iv);
       
  8653 
       
  8654 			if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {
       
  8655 				each(this._getSelectedBlocks(), function(e) {
       
  8656 					v = Math.max(0, parseInt(e.style.paddingLeft || 0) - iv);
       
  8657 					d.setStyle(e, 'paddingLeft', v ? v + iu : '');
       
  8658 				});
       
  8659 
       
  8660 				return;
       
  8661 			}
       
  8662 
       
  8663 			ed.getDoc().execCommand('Outdent', false, null);
       
  8664 		},
       
  8665 
       
  8666 		mceSetAttribute : function(u, v) {
       
  8667 			var ed = this.editor, d = ed.dom, e;
       
  8668 
       
  8669 			if (e = d.getParent(ed.selection.getNode(), d.isBlock))
       
  8670 				d.setAttrib(e, v.name, v.value);
       
  8671 		},
       
  8672 
       
  8673 		mceSetContent : function(u, v) {
       
  8674 			this.editor.setContent(v);
       
  8675 		},
       
  8676 
       
  8677 		mceToggleVisualAid : function() {
       
  8678 			var ed = this.editor;
       
  8679 
       
  8680 			ed.hasVisual = !ed.hasVisual;
       
  8681 			ed.addVisual();
       
  8682 		},
       
  8683 
       
  8684 		mceReplaceContent : function(u, v) {
       
  8685 			var s = this.editor.selection;
       
  8686 
       
  8687 			s.setContent(v.replace(/\{\$selection\}/g, s.getContent({format : 'text'})));
       
  8688 		},
       
  8689 
       
  8690 		mceInsertLink : function(u, v) {
       
  8691 			var ed = this.editor, s = ed.selection, e = ed.dom.getParent(s.getNode(), 'A');
       
  8692 
       
  8693 			if (tinymce.is(v, 'string'))
       
  8694 				v = {href : v};
       
  8695 
       
  8696 			function set(e) {
       
  8697 				each(v, function(v, k) {
       
  8698 					ed.dom.setAttrib(e, k, v);
       
  8699 				});
       
  8700 			};
       
  8701 
       
  8702 			if (!e) {
       
  8703 				ed.execCommand('CreateLink', false, 'javascript:mctmp(0);');
       
  8704 				each(ed.dom.select('a'), function(e) {
       
  8705 					if (e.href == 'javascript:mctmp(0);')
       
  8706 						set(e);
       
  8707 				});
       
  8708 			} else {
       
  8709 				if (v.href)
       
  8710 					set(e);
       
  8711 				else
       
  8712 					ed.dom.remove(e, 1);
       
  8713 			}
       
  8714 		},
       
  8715 
       
  8716 		UnLink : function() {
       
  8717 			var ed = this.editor, s = ed.selection;
       
  8718 
       
  8719 			if (s.isCollapsed())
       
  8720 				s.select(s.getNode());
       
  8721 
       
  8722 			ed.getDoc().execCommand('unlink', false, null);
       
  8723 			s.collapse(0);
       
  8724 		},
       
  8725 
       
  8726 		FontName : function(u, v) {
       
  8727 			var t = this, ed = t.editor, s = ed.selection, e;
       
  8728 
       
  8729 			if (!v) {
       
  8730 				if (s.isCollapsed())
       
  8731 					s.select(s.getNode());
       
  8732 
       
  8733 				t.RemoveFormat();
       
  8734 			} else
       
  8735 				ed.getDoc().execCommand('FontName', false, v);
       
  8736 		},
       
  8737 
       
  8738 		FontSize : function(u, v) {
       
  8739 			var ed = this.editor, s = ed.settings, fz = tinymce.explode(s.font_size_style_values), fzc = tinymce.explode(s.font_size_classes), h, bm;
       
  8740 
       
  8741 			// Remove style sizes
       
  8742 			each(ed.dom.select('font'), function(e) {
       
  8743 				e.style.fontSize = '';
       
  8744 			});
       
  8745 
       
  8746 			// Let the browser add new size it will remove unneded ones in some browsers
       
  8747 			ed.getDoc().execCommand('FontSize', false, v);
       
  8748 
       
  8749 			// Add style values
       
  8750 			if (s.inline_styles) {
       
  8751 				each(ed.dom.select('font'), function(e) {
       
  8752 					// Try remove redundant font elements
       
  8753 					if (e.parentNode.nodeName == 'FONT' && e.size == e.parentNode.size) {
       
  8754 						if (!bm)
       
  8755 							bm = ed.selection.getBookmark();
       
  8756 
       
  8757 						ed.dom.remove(e, 1);
       
  8758 						return;
       
  8759 					}
       
  8760 
       
  8761 					// Setup font size based on font size value
       
  8762 					if (v = e.size) {
       
  8763 						if (fzc && fzc.length > 0)
       
  8764 							ed.dom.setAttrib(e, 'class', fzc[parseInt(v) - 1]);
       
  8765 						else
       
  8766 							ed.dom.setStyle(e, 'fontSize', fz[parseInt(v) - 1]);
       
  8767 					}
       
  8768 				});
       
  8769 			}
       
  8770 
       
  8771 			ed.selection.moveToBookmark(bm);
       
  8772 		},
       
  8773 
       
  8774 		queryCommandValue : function(c) {
       
  8775 			var f = this['queryValue' + c];
       
  8776 
       
  8777 			if (f)
       
  8778 				return f.call(this, c);
       
  8779 
       
  8780 			return false;
       
  8781 		},
       
  8782 
       
  8783 		queryCommandState : function(cmd) {
       
  8784 			var f;
       
  8785 
       
  8786 			switch (cmd) {
       
  8787 				// Bundle these together
       
  8788 				case 'JustifyLeft':
       
  8789 				case 'JustifyCenter':
       
  8790 				case 'JustifyRight':
       
  8791 				case 'JustifyFull':
       
  8792 					return this.queryStateJustify(cmd, cmd.substring(7).toLowerCase());
       
  8793 
       
  8794 				default:
       
  8795 					if (f = this['queryState' + cmd])
       
  8796 						return f.call(this, cmd);
       
  8797 			}
       
  8798 
       
  8799 			return -1;
       
  8800 		},
       
  8801 
       
  8802 		_queryState : function(c) {
       
  8803 			try {
       
  8804 				return this.editor.getDoc().queryCommandState(c);
       
  8805 			} catch (ex) {
       
  8806 				// Ignore exception
       
  8807 			}
       
  8808 		},
       
  8809 
       
  8810 		_queryVal : function(c) {
       
  8811 			try {
       
  8812 				return this.editor.getDoc().queryCommandValue(c);
       
  8813 			} catch (ex) {
       
  8814 				// Ignore exception
       
  8815 			}
       
  8816 		},
       
  8817 
       
  8818 		queryValueFontSize : function() {
       
  8819 			var ed = this.editor, v = 0, p;
       
  8820 
       
  8821 			if (isOpera || isWebKit) {
       
  8822 				if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))
       
  8823 					v = p.size;
       
  8824 
       
  8825 				return v;
       
  8826 			}
       
  8827 
       
  8828 			return this._queryVal('FontSize');
       
  8829 		},
       
  8830 
       
  8831 		queryValueFontName : function() {
       
  8832 			var ed = this.editor, v = 0, p;
       
  8833 
       
  8834 			if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))
       
  8835 				v = p.face;
       
  8836 
       
  8837 			if (!v)
       
  8838 				v = this._queryVal('FontName');
       
  8839 
       
  8840 			return v;
       
  8841 		},
       
  8842 
       
  8843 		mceJustify : function(c, v) {
       
  8844 			var ed = this.editor, se = ed.selection, n = se.getNode(), nn = n.nodeName, bl, nb, dom = ed.dom, rm;
       
  8845 
       
  8846 			if (ed.settings.inline_styles && this.queryStateJustify(c, v))
       
  8847 				rm = 1;
       
  8848 
       
  8849 			bl = dom.getParent(n, ed.dom.isBlock);
       
  8850 
       
  8851 			if (nn == 'IMG') {
       
  8852 				if (v == 'full')
       
  8853 					return;
       
  8854 
       
  8855 				if (rm) {
       
  8856 					if (v == 'center')
       
  8857 						dom.setStyle(bl || n.parentNode, 'textAlign', '');
       
  8858 
       
  8859 					dom.setStyle(n, 'float', '');
       
  8860 					this.mceRepaint();
       
  8861 					return;
       
  8862 				}
       
  8863 
       
  8864 				if (v == 'center') {
       
  8865 					// Do not change table elements
       
  8866 					if (bl && /^(TD|TH)$/.test(bl.nodeName))
       
  8867 						bl = 0;
       
  8868 
       
  8869 					if (!bl || bl.childNodes.length > 1) {
       
  8870 						nb = dom.create('p');
       
  8871 						nb.appendChild(n.cloneNode(false));
       
  8872 
       
  8873 						if (bl)
       
  8874 							dom.insertAfter(nb, bl);
       
  8875 						else
       
  8876 							dom.insertAfter(nb, n);
       
  8877 
       
  8878 						dom.remove(n);
       
  8879 						n = nb.firstChild;
       
  8880 						bl = nb;
       
  8881 					}
       
  8882 
       
  8883 					dom.setStyle(bl, 'textAlign', v);
       
  8884 					dom.setStyle(n, 'float', '');
       
  8885 				} else {
       
  8886 					dom.setStyle(n, 'float', v);
       
  8887 					dom.setStyle(bl || n.parentNode, 'textAlign', '');
       
  8888 				}
       
  8889 
       
  8890 				this.mceRepaint();
       
  8891 				return;
       
  8892 			}
       
  8893 
       
  8894 			// Handle the alignment outselfs, less quirks in all browsers
       
  8895 			if (ed.settings.inline_styles && ed.settings.forced_root_block) {
       
  8896 				if (rm)
       
  8897 					v = '';
       
  8898 
       
  8899 				each(this._getSelectedBlocks(dom.getParent(se.getStart(), dom.isBlock), dom.getParent(se.getEnd(), dom.isBlock)), function(e) {
       
  8900 					dom.setAttrib(e, 'align', '');
       
  8901 					dom.setStyle(e, 'textAlign', v == 'full' ? 'justify' : v);
       
  8902 				});
       
  8903 
       
  8904 				return;
       
  8905 			} else if (!rm)
       
  8906 				ed.getDoc().execCommand(c, false, null);
       
  8907 
       
  8908 			if (ed.settings.inline_styles) {
       
  8909 				if (rm) {
       
  8910 					dom.getParent(ed.selection.getNode(), function(n) {
       
  8911 						if (n.style && n.style.textAlign)
       
  8912 							dom.setStyle(n, 'textAlign', '');
       
  8913 					});
       
  8914 
       
  8915 					return;
       
  8916 				}
       
  8917 
       
  8918 				each(dom.select('*'), function(n) {
       
  8919 					var v = n.align;
       
  8920 
       
  8921 					if (v) {
       
  8922 						if (v == 'full')
       
  8923 							v = 'justify';
       
  8924 
       
  8925 						dom.setStyle(n, 'textAlign', v);
       
  8926 						dom.setAttrib(n, 'align', '');
       
  8927 					}
       
  8928 				});
       
  8929 			}
       
  8930 		},
       
  8931 
       
  8932 		mceSetCSSClass : function(u, v) {
       
  8933 			this.mceSetStyleInfo(0, {command : 'setattrib', name : 'class', value : v});
       
  8934 		},
       
  8935 
       
  8936 		getSelectedElement : function() {
       
  8937 			var t = this, ed = t.editor, dom = ed.dom, se = ed.selection, r = se.getRng(), r1, r2, sc, ec, so, eo, e, sp, ep, re;
       
  8938 
       
  8939 			if (se.isCollapsed() || r.item)
       
  8940 				return se.getNode();
       
  8941 
       
  8942 			// Setup regexp
       
  8943 			re = ed.settings.merge_styles_invalid_parents;
       
  8944 			if (tinymce.is(re, 'string'))
       
  8945 				re = new RegExp(re, 'i');
       
  8946 
       
  8947 			if (isIE) {
       
  8948 				r1 = r.duplicate();
       
  8949 				r1.collapse(true);
       
  8950 				sc = r1.parentElement();
       
  8951 
       
  8952 				r2 = r.duplicate();
       
  8953 				r2.collapse(false);
       
  8954 				ec = r2.parentElement();
       
  8955 
       
  8956 				if (sc != ec) {
       
  8957 					r1.move('character', 1);
       
  8958 					sc = r1.parentElement();
       
  8959 				}
       
  8960 
       
  8961 				if (sc == ec) {
       
  8962 					r1 = r.duplicate();
       
  8963 					r1.moveToElementText(sc);
       
  8964 
       
  8965 					if (r1.compareEndPoints('StartToStart', r) == 0 && r1.compareEndPoints('EndToEnd', r) == 0)
       
  8966 						return re && re.test(sc.nodeName) ? null : sc;
       
  8967 				}
       
  8968 			} else {
       
  8969 				function getParent(n) {
       
  8970 					return dom.getParent(n, function(n) {return n.nodeType == 1;});
       
  8971 				};
       
  8972 
       
  8973 				sc = r.startContainer;
       
  8974 				ec = r.endContainer;
       
  8975 				so = r.startOffset;
       
  8976 				eo = r.endOffset;
       
  8977 
       
  8978 				if (!r.collapsed) {
       
  8979 					if (sc == ec) {
       
  8980 						if (so - eo < 2) {
       
  8981 							if (sc.hasChildNodes()) {
       
  8982 								sp = sc.childNodes[so];
       
  8983 								return re && re.test(sp.nodeName) ? null : sp;
       
  8984 							}
       
  8985 						}
       
  8986 					}
       
  8987 				}
       
  8988 
       
  8989 				if (sc.nodeType != 3 || ec.nodeType != 3)
       
  8990 					return null;
       
  8991 
       
  8992 				if (so == 0) {
       
  8993 					sp = getParent(sc);
       
  8994 
       
  8995 					if (sp && sp.firstChild != sc)
       
  8996 						sp = null;
       
  8997 				}
       
  8998 
       
  8999 				if (so == sc.nodeValue.length) {
       
  9000 					e = sc.nextSibling;
       
  9001 
       
  9002 					if (e && e.nodeType == 1)
       
  9003 						sp = sc.nextSibling;
       
  9004 				}
       
  9005 
       
  9006 				if (eo == 0) {
       
  9007 					e = ec.previousSibling;
       
  9008 
       
  9009 					if (e && e.nodeType == 1)
       
  9010 						ep = e;
       
  9011 				}
       
  9012 
       
  9013 				if (eo == ec.nodeValue.length) {
       
  9014 					ep = getParent(ec);
       
  9015 
       
  9016 					if (ep && ep.lastChild != ec)
       
  9017 						ep = null;
       
  9018 				}
       
  9019 
       
  9020 				// Same element
       
  9021 				if (sp == ep)
       
  9022 					return re && sp && re.test(sp.nodeName) ? null : sp;
       
  9023 			}
       
  9024 
       
  9025 			return null;
       
  9026 		},
       
  9027 
       
  9028 		InsertHorizontalRule : function() {
       
  9029 			// Fix for Gecko <hr size="1" /> issue and IE bug rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");
       
  9030 			if (isGecko || isIE)
       
  9031 				this.editor.selection.setContent('<hr />');
       
  9032 			else
       
  9033 				this.editor.getDoc().execCommand('InsertHorizontalRule', false, '');
       
  9034 		},
       
  9035 
       
  9036 		RemoveFormat : function() {
       
  9037 			var t = this, ed = t.editor, s = ed.selection, b;
       
  9038 
       
  9039 			// Safari breaks tables
       
  9040 			if (isWebKit)
       
  9041 				s.setContent(s.getContent({format : 'raw'}).replace(/(<(span|b|i|strong|em|strike) [^>]+>|<(span|b|i|strong|em|strike)>|<\/(span|b|i|strong|em|strike)>|)/g, ''), {format : 'raw'});
       
  9042 			else
       
  9043 				ed.getDoc().execCommand('RemoveFormat', false, null);
       
  9044 
       
  9045 			t.mceSetStyleInfo(0, {command : 'removeformat'});
       
  9046 			ed.addVisual();
       
  9047 		},
       
  9048 
       
  9049 		mceSetStyleInfo : function(u, v) {
       
  9050 			var t = this, ed = t.editor, d = ed.getDoc(), dom = ed.dom, e, b, s = ed.selection, nn = v.wrapper || 'span', b = s.getBookmark(), re;
       
  9051 
       
  9052 			function set(n, e) {
       
  9053 				if (n.nodeType == 1) {
       
  9054 					switch (v.command) {
       
  9055 						case 'setattrib':
       
  9056 							return dom.setAttrib(n, v.name, v.value);
       
  9057 
       
  9058 						case 'setstyle':
       
  9059 							return dom.setStyle(n, v.name, v.value);
       
  9060 
       
  9061 						case 'removeformat':
       
  9062 							return dom.setAttrib(n, 'class', '');
       
  9063 					}
       
  9064 				}
       
  9065 			};
       
  9066 
       
  9067 			// Setup regexp
       
  9068 			re = ed.settings.merge_styles_invalid_parents;
       
  9069 			if (tinymce.is(re, 'string'))
       
  9070 				re = new RegExp(re, 'i');
       
  9071 
       
  9072 			// Set style info on selected element
       
  9073 			if ((e = t.getSelectedElement()) && !ed.settings.force_span_wrappers)
       
  9074 				set(e, 1);
       
  9075 			else {
       
  9076 				// Generate wrappers and set styles on them
       
  9077 				d.execCommand('FontName', false, '__');
       
  9078 				each(isWebKit ? dom.select('span') : dom.select('font'), function(n) {
       
  9079 					var sp, e;
       
  9080 
       
  9081 					if (dom.getAttrib(n, 'face') == '__' || n.style.fontFamily === '__') {
       
  9082 						sp = dom.create(nn, {mce_new : '1'});
       
  9083 
       
  9084 						set(sp);
       
  9085 
       
  9086 						each (n.childNodes, function(n) {
       
  9087 							sp.appendChild(n.cloneNode(true));
       
  9088 						});
       
  9089 
       
  9090 						dom.replace(sp, n);
       
  9091 					}
       
  9092 				});
       
  9093 			}
       
  9094 
       
  9095 			// Remove wrappers inside new ones
       
  9096 			each(dom.select(nn).reverse(), function(n) {
       
  9097 				var p = n.parentNode;
       
  9098 
       
  9099 				// Check if it's an old span in a new wrapper
       
  9100 				if (!dom.getAttrib(n, 'mce_new')) {
       
  9101 					// Find new wrapper
       
  9102 					p = dom.getParent(n, function(n) {
       
  9103 						return n.nodeType == 1 && dom.getAttrib(n, 'mce_new');
       
  9104 					});
       
  9105 
       
  9106 					if (p)
       
  9107 						dom.remove(n, 1);
       
  9108 				}
       
  9109 			});
       
  9110 
       
  9111 			// Merge wrappers with parent wrappers
       
  9112 			each(dom.select(nn).reverse(), function(n) {
       
  9113 				var p = n.parentNode;
       
  9114 
       
  9115 				if (!p || !dom.getAttrib(n, 'mce_new'))
       
  9116 					return;
       
  9117 
       
  9118 				if (ed.settings.force_span_wrappers && p.nodeName != 'SPAN')
       
  9119 					return;
       
  9120 
       
  9121 				// Has parent of the same type and only child
       
  9122 				if (p.nodeName == nn.toUpperCase() && p.childNodes.length == 1)
       
  9123 					return dom.remove(p, 1);
       
  9124 
       
  9125 				// Has parent that is more suitable to have the class and only child
       
  9126 				if (n.nodeType == 1 && (!re || !re.test(p.nodeName)) && p.childNodes.length == 1) {
       
  9127 					set(p); // Set style info on parent instead
       
  9128 					dom.setAttrib(n, 'class', '');
       
  9129 				}
       
  9130 			});
       
  9131 
       
  9132 			// Remove empty wrappers
       
  9133 			each(dom.select(nn).reverse(), function(n) {
       
  9134 				if (dom.getAttrib(n, 'mce_new') || (dom.getAttribs(n).length <= 1 && n.className === '')) {
       
  9135 					if (!dom.getAttrib(n, 'class') && !dom.getAttrib(n, 'style'))
       
  9136 						return dom.remove(n, 1);
       
  9137 
       
  9138 					dom.setAttrib(n, 'mce_new', ''); // Remove mce_new marker
       
  9139 				}
       
  9140 			});
       
  9141 
       
  9142 			s.moveToBookmark(b);
       
  9143 		},
       
  9144 
       
  9145 		queryStateJustify : function(c, v) {
       
  9146 			var ed = this.editor, n = ed.selection.getNode(), dom = ed.dom;
       
  9147 
       
  9148 			if (n && n.nodeName == 'IMG') {
       
  9149 				if (dom.getStyle(n, 'float') == v)
       
  9150 					return 1;
       
  9151 
       
  9152 				return n.parentNode.style.textAlign == v;
       
  9153 			}
       
  9154 
       
  9155 			n = dom.getParent(ed.selection.getStart(), function(n) {
       
  9156 				return n.nodeType == 1 && n.style.textAlign;
       
  9157 			});
       
  9158 
       
  9159 			if (v == 'full')
       
  9160 				v = 'justify';
       
  9161 
       
  9162 			if (ed.settings.inline_styles)
       
  9163 				return (n && n.style.textAlign == v);
       
  9164 
       
  9165 			return this._queryState(c);
       
  9166 		},
       
  9167 
       
  9168 		HiliteColor : function(ui, val) {
       
  9169 			var t = this, ed = t.editor, d = ed.getDoc();
       
  9170 
       
  9171 			function set(s) {
       
  9172 				if (!isGecko)
       
  9173 					return;
       
  9174 
       
  9175 				try {
       
  9176 					// Try new Gecko method
       
  9177 					d.execCommand("styleWithCSS", 0, s);
       
  9178 				} catch (ex) {
       
  9179 					// Use old
       
  9180 					d.execCommand("useCSS", 0, !s);
       
  9181 				}
       
  9182 			};
       
  9183 
       
  9184 			if (isGecko || isOpera) {
       
  9185 				set(true);
       
  9186 				d.execCommand('hilitecolor', false, val);
       
  9187 				set(false);
       
  9188 			} else
       
  9189 				d.execCommand('BackColor', false, val);
       
  9190 		},
       
  9191 
       
  9192 		Undo : function() {
       
  9193 			var ed = this.editor;
       
  9194 
       
  9195 			if (ed.settings.custom_undo_redo) {
       
  9196 				ed.undoManager.undo();
       
  9197 				ed.nodeChanged();
       
  9198 			} else
       
  9199 				ed.getDoc().execCommand('Undo', false, null);
       
  9200 		},
       
  9201 
       
  9202 		Redo : function() {
       
  9203 			var ed = this.editor;
       
  9204 
       
  9205 			if (ed.settings.custom_undo_redo) {
       
  9206 				ed.undoManager.redo();
       
  9207 				ed.nodeChanged();
       
  9208 			} else
       
  9209 				ed.getDoc().execCommand('Redo', false, null);
       
  9210 		},
       
  9211 
       
  9212 		FormatBlock : function(ui, val) {
       
  9213 			var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, bl, nb, b;
       
  9214 
       
  9215 			function isBlock(n) {
       
  9216 				return /^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(n.nodeName);
       
  9217 			};
       
  9218 
       
  9219 			bl = dom.getParent(s.getNode(), function(n) {
       
  9220 				return isBlock(n);
       
  9221 			});
       
  9222 
       
  9223 			// IE has an issue where it removes the parent div if you change format on the paragrah in <div><p>Content</p></div>
       
  9224 			// FF and Opera doesn't change parent DIV elements if you switch format
       
  9225 			if (bl) {
       
  9226 				if ((isIE && isBlock(bl.parentNode)) || bl.nodeName == 'DIV') {
       
  9227 					// Rename block element
       
  9228 					nb = ed.dom.create(val);
       
  9229 
       
  9230 					each(dom.getAttribs(bl), function(v) {
       
  9231 						dom.setAttrib(nb, v.nodeName, dom.getAttrib(bl, v.nodeName));
       
  9232 					});
       
  9233 
       
  9234 					b = s.getBookmark();
       
  9235 					dom.replace(nb, bl, 1);
       
  9236 					s.moveToBookmark(b);
       
  9237 					ed.nodeChanged();
       
  9238 					return;
       
  9239 				}
       
  9240 			}
       
  9241 
       
  9242 			val = ed.settings.forced_root_block ? (val || '<p>') : val;
       
  9243 
       
  9244 			if (val.indexOf('<') == -1)
       
  9245 				val = '<' + val + '>';
       
  9246 
       
  9247 			if (tinymce.isGecko)
       
  9248 				val = val.replace(/<(div|blockquote|code|dt|dd|dl|samp)>/gi, '$1');
       
  9249 
       
  9250 			ed.getDoc().execCommand('FormatBlock', false, val);
       
  9251 		},
       
  9252 
       
  9253 		mceCleanup : function() {
       
  9254 			var ed = this.editor, s = ed.selection, b = s.getBookmark();
       
  9255 			ed.setContent(ed.getContent());
       
  9256 			s.moveToBookmark(b);
       
  9257 		},
       
  9258 
       
  9259 		mceRemoveNode : function(ui, val) {
       
  9260 			var ed = this.editor, s = ed.selection, b, n = val || s.getNode();
       
  9261 
       
  9262 			// Make sure that the body node isn't removed
       
  9263 			if (n == ed.getBody())
       
  9264 				return;
       
  9265 
       
  9266 			b = s.getBookmark();
       
  9267 			ed.dom.remove(n, 1);
       
  9268 			s.moveToBookmark(b);
       
  9269 			ed.nodeChanged();
       
  9270 		},
       
  9271 
       
  9272 		mceSelectNodeDepth : function(ui, val) {
       
  9273 			var ed = this.editor, s = ed.selection, c = 0;
       
  9274 
       
  9275 			ed.dom.getParent(s.getNode(), function(n) {
       
  9276 				if (n.nodeType == 1 && c++ == val) {
       
  9277 					s.select(n);
       
  9278 					ed.nodeChanged();
       
  9279 					return false;
       
  9280 				}
       
  9281 			}, ed.getBody());
       
  9282 		},
       
  9283 
       
  9284 		mceSelectNode : function(u, v) {
       
  9285 			this.editor.selection.select(v);
       
  9286 		},
       
  9287 
       
  9288 		mceInsertContent : function(ui, val) {
       
  9289 			this.editor.selection.setContent(val);
       
  9290 		},
       
  9291 
       
  9292 		mceInsertRawHTML : function(ui, val) {
       
  9293 			var ed = this.editor;
       
  9294 
       
  9295 			ed.selection.setContent('tiny_mce_marker');
       
  9296 			ed.setContent(ed.getContent().replace(/tiny_mce_marker/g, val));
       
  9297 		},
       
  9298 
       
  9299 		mceRepaint : function() {
       
  9300 			var s, b, e = this.editor;
       
  9301 
       
  9302 			if (tinymce.isGecko) {
       
  9303 				try {
       
  9304 					s = e.selection;
       
  9305 					b = s.getBookmark(true);
       
  9306 
       
  9307 					if (s.getSel())
       
  9308 						s.getSel().selectAllChildren(e.getBody());
       
  9309 
       
  9310 					s.collapse(true);
       
  9311 					s.moveToBookmark(b);
       
  9312 				} catch (ex) {
       
  9313 					// Ignore
       
  9314 				}
       
  9315 			}
       
  9316 		},
       
  9317 
       
  9318 		queryStateUnderline : function() {
       
  9319 			var ed = this.editor, n = ed.selection.getNode();
       
  9320 
       
  9321 			if (n && n.nodeName == 'A')
       
  9322 				return false;
       
  9323 
       
  9324 			return this._queryState('Underline');
       
  9325 		},
       
  9326 
       
  9327 		queryStateOutdent : function() {
       
  9328 			var ed = this.editor, n;
       
  9329 
       
  9330 			if (ed.settings.inline_styles) {
       
  9331 				if ((n = ed.dom.getParent(ed.selection.getStart(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)
       
  9332 					return true;
       
  9333 
       
  9334 				if ((n = ed.dom.getParent(ed.selection.getEnd(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)
       
  9335 					return true;
       
  9336 			} else
       
  9337 				return !!ed.dom.getParent(ed.selection.getNode(), 'BLOCKQUOTE');
       
  9338 
       
  9339 			return this.queryStateInsertUnorderedList() || this.queryStateInsertOrderedList();
       
  9340 		},
       
  9341 
       
  9342 		queryStateInsertUnorderedList : function() {
       
  9343 			return this.editor.dom.getParent(this.editor.selection.getNode(), 'UL');
       
  9344 		},
       
  9345 
       
  9346 		queryStateInsertOrderedList : function() {
       
  9347 			return this.editor.dom.getParent(this.editor.selection.getNode(), 'OL');
       
  9348 		},
       
  9349 
       
  9350 		queryStatemceBlockQuote : function() {
       
  9351 			return !!this.editor.dom.getParent(this.editor.selection.getStart(), function(n) {return n.nodeName === 'BLOCKQUOTE';});
       
  9352 		},
       
  9353 
       
  9354 		mceBlockQuote : function() {
       
  9355 			var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, sb, eb, n, bm, bq, r, bq2, i, nl;
       
  9356 
       
  9357 			function getBQ(e) {
       
  9358 				return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});
       
  9359 			};
       
  9360 
       
  9361 			// Get start/end block
       
  9362 			sb = dom.getParent(s.getStart(), dom.isBlock);
       
  9363 			eb = dom.getParent(s.getEnd(), dom.isBlock);
       
  9364 
       
  9365 			// Remove blockquote(s)
       
  9366 			if (bq = getBQ(sb)) {
       
  9367 				if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))
       
  9368 					bm = s.getBookmark();
       
  9369 
       
  9370 				// Move all elements after the end block into new bq
       
  9371 				if (getBQ(eb)) {
       
  9372 					bq2 = bq.cloneNode(false);
       
  9373 
       
  9374 					while (n = eb.nextSibling)
       
  9375 						bq2.appendChild(n.parentNode.removeChild(n));
       
  9376 				}
       
  9377 
       
  9378 				// Add new bq after
       
  9379 				if (bq2)
       
  9380 					dom.insertAfter(bq2, bq);
       
  9381 
       
  9382 				// Move all selected blocks after the current bq
       
  9383 				nl = t._getSelectedBlocks(sb, eb);
       
  9384 				for (i = nl.length - 1; i >= 0; i--) {
       
  9385 					dom.insertAfter(nl[i], bq);
       
  9386 				}
       
  9387 
       
  9388 				// Empty bq, then remove it
       
  9389 				if (/^\s*$/.test(bq.innerHTML))
       
  9390 					dom.remove(bq, 1); // Keep children so boomark restoration works correctly
       
  9391 
       
  9392 				// Empty bq, then remote it
       
  9393 				if (bq2 && /^\s*$/.test(bq2.innerHTML))
       
  9394 					dom.remove(bq2, 1); // Keep children so boomark restoration works correctly
       
  9395 
       
  9396 				if (!bm) {
       
  9397 					// Move caret inside empty block element
       
  9398 					if (!isIE) {
       
  9399 						r = ed.getDoc().createRange();
       
  9400 						r.setStart(sb, 0);
       
  9401 						r.setEnd(sb, 0);
       
  9402 						s.setRng(r);
       
  9403 					} else {
       
  9404 						s.select(sb);
       
  9405 						s.collapse(0);
       
  9406 
       
  9407 						// IE misses the empty block some times element so we must move back the caret
       
  9408 						if (dom.getParent(s.getStart(), dom.isBlock) != sb) {
       
  9409 							r = s.getRng();
       
  9410 							r.move('character', -1);
       
  9411 							r.select();
       
  9412 						}
       
  9413 					}
       
  9414 				} else
       
  9415 					t.editor.selection.moveToBookmark(bm);
       
  9416 
       
  9417 				return;
       
  9418 			}
       
  9419 
       
  9420 			// Since IE can start with a totally empty document we need to add the first bq and paragraph
       
  9421 			if (isIE && !sb && !eb) {
       
  9422 				t.editor.getDoc().execCommand('Indent');
       
  9423 				n = getBQ(s.getNode());
       
  9424 				n.style.margin = n.dir = ''; // IE adds margin and dir to bq
       
  9425 				return;
       
  9426 			}
       
  9427 
       
  9428 			if (!sb || !eb)
       
  9429 				return;
       
  9430 
       
  9431 			// If empty paragraph node then do not use bookmark
       
  9432 			if (sb != eb || sb.childNodes.length > 1 || (sb.childNodes.length == 1 && sb.firstChild.nodeName != 'BR'))
       
  9433 				bm = s.getBookmark();
       
  9434 
       
  9435 			// Move selected block elements into a bq
       
  9436 			each(t._getSelectedBlocks(getBQ(s.getStart()), getBQ(s.getEnd())), function(e) {
       
  9437 				// Found existing BQ add to this one
       
  9438 				if (e.nodeName == 'BLOCKQUOTE' && !bq) {
       
  9439 					bq = e;
       
  9440 					return;
       
  9441 				}
       
  9442 
       
  9443 				// No BQ found, create one
       
  9444 				if (!bq) {
       
  9445 					bq = dom.create('blockquote');
       
  9446 					e.parentNode.insertBefore(bq, e);
       
  9447 				}
       
  9448 
       
  9449 				// Add children from existing BQ
       
  9450 				if (e.nodeName == 'BLOCKQUOTE' && bq) {
       
  9451 					n = e.firstChild;
       
  9452 
       
  9453 					while (n) {
       
  9454 						bq.appendChild(n.cloneNode(true));
       
  9455 						n = n.nextSibling;
       
  9456 					}
       
  9457 
       
  9458 					dom.remove(e);
       
  9459 					return;
       
  9460 				}
       
  9461 
       
  9462 				// Add non BQ element to BQ
       
  9463 				bq.appendChild(dom.remove(e));
       
  9464 			});
       
  9465 
       
  9466 			if (!bm) {
       
  9467 				// Move caret inside empty block element
       
  9468 				if (!isIE) {
       
  9469 					r = ed.getDoc().createRange();
       
  9470 					r.setStart(sb, 0);
       
  9471 					r.setEnd(sb, 0);
       
  9472 					s.setRng(r);
       
  9473 				} else {
       
  9474 					s.select(sb);
       
  9475 					s.collapse(1);
       
  9476 				}
       
  9477 			} else
       
  9478 				s.moveToBookmark(bm);
       
  9479 		},
       
  9480 /*
       
  9481 		_mceBlockQuote : function() {
       
  9482 			var t = this, s = t.editor.selection, b = s.getBookmark(), bq, dom = t.editor.dom;
       
  9483 
       
  9484 			function findBQ(e) {
       
  9485 				return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});
       
  9486 			};
       
  9487 
       
  9488 			// Remove blockquote(s)
       
  9489 			if (findBQ(s.getStart())) {
       
  9490 				each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {
       
  9491 					// Found BQ lets remove it
       
  9492 					if (e.nodeName == 'BLOCKQUOTE')
       
  9493 						dom.remove(e, 1);
       
  9494 				});
       
  9495 
       
  9496 				t.editor.selection.moveToBookmark(b);
       
  9497 				return;
       
  9498 			}
       
  9499 
       
  9500 			each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {
       
  9501 				var n;
       
  9502 
       
  9503 				// Found existing BQ add to this one
       
  9504 				if (e.nodeName == 'BLOCKQUOTE' && !bq) {
       
  9505 					bq = e;
       
  9506 					return;
       
  9507 				}
       
  9508 
       
  9509 				// No BQ found, create one
       
  9510 				if (!bq) {
       
  9511 					bq = dom.create('blockquote');
       
  9512 					e.parentNode.insertBefore(bq, e);
       
  9513 				}
       
  9514 
       
  9515 				// Add children from existing BQ
       
  9516 				if (e.nodeName == 'BLOCKQUOTE' && bq) {
       
  9517 					n = e.firstChild;
       
  9518 
       
  9519 					while (n) {
       
  9520 						bq.appendChild(n.cloneNode(true));
       
  9521 						n = n.nextSibling;
       
  9522 					}
       
  9523 
       
  9524 					dom.remove(e);
       
  9525 
       
  9526 					return;
       
  9527 				}
       
  9528 
       
  9529 				// Add non BQ element to BQ
       
  9530 				bq.appendChild(dom.remove(e));
       
  9531 			});
       
  9532 
       
  9533 			t.editor.selection.moveToBookmark(b);
       
  9534 		},
       
  9535 */
       
  9536 		_getSelectedBlocks : function(st, en) {
       
  9537 			var ed = this.editor, dom = ed.dom, s = ed.selection, sb, eb, n, bl = [];
       
  9538 
       
  9539 			sb = dom.getParent(st || s.getStart(), dom.isBlock);
       
  9540 			eb = dom.getParent(en || s.getEnd(), dom.isBlock);
       
  9541 
       
  9542 			if (sb)
       
  9543 				bl.push(sb);
       
  9544 
       
  9545 			if (sb && eb && sb != eb) {
       
  9546 				n = sb;
       
  9547 
       
  9548 				while ((n = n.nextSibling) && n != eb) {
       
  9549 					if (dom.isBlock(n))
       
  9550 						bl.push(n);
       
  9551 				}
       
  9552 			}
       
  9553 
       
  9554 			if (eb && sb != eb)
       
  9555 				bl.push(eb);
       
  9556 
       
  9557 			return bl;
       
  9558 		}
       
  9559 	});
       
  9560 })();
       
  9561 
       
  9562 
       
  9563 /* file:jscripts/tiny_mce/classes/UndoManager.js */
       
  9564 
       
  9565 tinymce.create('tinymce.UndoManager', {
       
  9566 	index : 0,
       
  9567 	data : null,
       
  9568 	typing : 0,
       
  9569 
       
  9570 	UndoManager : function(ed) {
       
  9571 		var t = this, Dispatcher = tinymce.util.Dispatcher;
       
  9572 
       
  9573 		t.editor = ed;
       
  9574 		t.data = [];
       
  9575 		t.onAdd = new Dispatcher(this);
       
  9576 		t.onUndo = new Dispatcher(this);
       
  9577 		t.onRedo = new Dispatcher(this);
       
  9578 	},
       
  9579 
       
  9580 	add : function(l) {
       
  9581 		var t = this, i, ed = t.editor, b, s = ed.settings, la;
       
  9582 
       
  9583 		l = l || {};
       
  9584 		l.content = l.content || ed.getContent({format : 'raw', no_events : 1});
       
  9585 
       
  9586 		// Add undo level if needed
       
  9587 		l.content = l.content.replace(/^\s*|\s*$/g, '');
       
  9588 		la = t.data[t.index > 0 && (t.index == 0 || t.index == t.data.length) ? t.index - 1 : t.index];
       
  9589 		if (!l.initial && la && l.content == la.content)
       
  9590 			return null;
       
  9591 
       
  9592 		// Time to compress
       
  9593 		if (s.custom_undo_redo_levels) {
       
  9594 			if (t.data.length > s.custom_undo_redo_levels) {
       
  9595 				for (i = 0; i < t.data.length - 1; i++)
       
  9596 					t.data[i] = t.data[i + 1];
       
  9597 
       
  9598 				t.data.length--;
       
  9599 				t.index = t.data.length;
       
  9600 			}
       
  9601 		}
       
  9602 
       
  9603 		if (s.custom_undo_redo_restore_selection && !l.initial)
       
  9604 			l.bookmark = b = l.bookmark || ed.selection.getBookmark();
       
  9605 
       
  9606 		if (t.index < t.data.length)
       
  9607 			t.index++;
       
  9608 
       
  9609 		// Only initial marked undo levels should be allowed as first item
       
  9610 		// This to workaround a bug with Firefox and the blur event
       
  9611 		if (t.data.length === 0 && !l.initial)
       
  9612 			return null;
       
  9613 
       
  9614 		// Add level
       
  9615 		t.data.length = t.index + 1;
       
  9616 		t.data[t.index++] = l;
       
  9617 
       
  9618 		if (l.initial)
       
  9619 			t.index = 0;
       
  9620 
       
  9621 		// Set initial bookmark use first real undo level
       
  9622 		if (t.data.length == 2 && t.data[0].initial)
       
  9623 			t.data[0].bookmark = b;
       
  9624 
       
  9625 		t.onAdd.dispatch(t, l);
       
  9626 		ed.isNotDirty = 0;
       
  9627 
       
  9628 		//console.dir(t.data);
       
  9629 
       
  9630 		return l;
       
  9631 	},
       
  9632 
       
  9633 	undo : function() {
       
  9634 		var t = this, ed = t.editor, l = l, i;
       
  9635 
       
  9636 		if (t.typing) {
       
  9637 			t.add();
       
  9638 			t.typing = 0;
       
  9639 		}
       
  9640 
       
  9641 		if (t.index > 0) {
       
  9642 			// If undo on last index then take snapshot
       
  9643 			if (t.index == t.data.length && t.index > 1) {
       
  9644 				i = t.index;
       
  9645 				t.typing = 0;
       
  9646 
       
  9647 				if (!t.add())
       
  9648 					t.index = i;
       
  9649 
       
  9650 				--t.index;
       
  9651 			}
       
  9652 
       
  9653 			l = t.data[--t.index];
       
  9654 			ed.setContent(l.content, {format : 'raw'});
       
  9655 			ed.selection.moveToBookmark(l.bookmark);
       
  9656 
       
  9657 			t.onUndo.dispatch(t, l);
       
  9658 		}
       
  9659 
       
  9660 		return l;
       
  9661 	},
       
  9662 
       
  9663 	redo : function() {
       
  9664 		var t = this, ed = t.editor, l = null;
       
  9665 
       
  9666 		if (t.index < t.data.length - 1) {
       
  9667 			l = t.data[++t.index];
       
  9668 			ed.setContent(l.content, {format : 'raw'});
       
  9669 			ed.selection.moveToBookmark(l.bookmark);
       
  9670 
       
  9671 			t.onRedo.dispatch(t, l);
       
  9672 		}
       
  9673 
       
  9674 		return l;
       
  9675 	},
       
  9676 
       
  9677 	clear : function() {
       
  9678 		var t = this;
       
  9679 
       
  9680 		t.data = [];
       
  9681 		t.index = 0;
       
  9682 		t.typing = 0;
       
  9683 		t.add({initial : true});
       
  9684 	},
       
  9685 
       
  9686 	hasUndo : function() {
       
  9687 		return this.index != 0 || this.typing;
       
  9688 	},
       
  9689 
       
  9690 	hasRedo : function() {
       
  9691 		return this.index < this.data.length - 1;
       
  9692 	}
       
  9693 
       
  9694 	});
       
  9695 /* file:jscripts/tiny_mce/classes/ForceBlocks.js */
       
  9696 
       
  9697 (function() {
       
  9698 	// Shorten names
       
  9699 	var Event, isIE, isGecko, isOpera, each, extend;
       
  9700 
       
  9701 	Event = tinymce.dom.Event;
       
  9702 	isIE = tinymce.isIE;
       
  9703 	isGecko = tinymce.isGecko;
       
  9704 	isOpera = tinymce.isOpera;
       
  9705 	each = tinymce.each;
       
  9706 	extend = tinymce.extend;
       
  9707 
       
  9708 	tinymce.create('tinymce.ForceBlocks', {
       
  9709 		ForceBlocks : function(ed) {
       
  9710 			var t = this, s = ed.settings, elm;
       
  9711 
       
  9712 			t.editor = ed;
       
  9713 			t.dom = ed.dom;
       
  9714 			elm = (s.forced_root_block || 'p').toLowerCase();
       
  9715 			s.element = elm.toUpperCase();
       
  9716 
       
  9717 			ed.onPreInit.add(t.setup, t);
       
  9718 
       
  9719 			t.reOpera = new RegExp('(\\u00a0|&#160;|&nbsp;)<\/' + elm + '>', 'gi');
       
  9720 			t.rePadd = new RegExp('<p( )([^>]+)><\\\/p>|<p( )([^>]+)\\\/>|<p( )([^>]+)>\\s+<\\\/p>|<p><\\\/p>|<p\\\/>|<p>\\s+<\\\/p>'.replace(/p/g, elm), 'gi');
       
  9721 			t.reNbsp2BR1 = new RegExp('<p( )([^>]+)>[\\s\\u00a0]+<\\\/p>|<p>[\\s\\u00a0]+<\\\/p>'.replace(/p/g, elm), 'gi');
       
  9722 			t.reNbsp2BR2 = new RegExp('<p( )([^>]+)>(&nbsp;|&#160;)<\\\/p>|<p>(&nbsp;|&#160;)<\\\/p>'.replace(/p/g, elm), 'gi');
       
  9723 			t.reBR2Nbsp = new RegExp('<p( )([^>]+)>\\s*<br \\\/>\\s*<\\\/p>|<p>\\s*<br \\\/>\\s*<\\\/p>'.replace(/p/g, elm), 'gi');
       
  9724 			t.reTrailBr = new RegExp('\\s*<br \\/>\\s*<\\\/p>'.replace(/p/g, elm), 'gi');
       
  9725 
       
  9726 			function padd(ed, o) {
       
  9727 				if (isOpera)
       
  9728 					o.content = o.content.replace(t.reOpera, '</' + elm + '>');
       
  9729 
       
  9730 				o.content = o.content.replace(t.rePadd, '<' + elm + '$1$2$3$4$5$6>\u00a0</' + elm + '>');
       
  9731 
       
  9732 				if (!isIE && !isOpera && o.set) {
       
  9733 					// Use &nbsp; instead of BR in padded paragraphs
       
  9734 					o.content = o.content.replace(t.reNbsp2BR1, '<' + elm + '$1$2><br /></' + elm + '>');
       
  9735 					o.content = o.content.replace(t.reNbsp2BR2, '<' + elm + '$1$2><br /></' + elm + '>');
       
  9736 				} else {
       
  9737 					o.content = o.content.replace(t.reBR2Nbsp, '<' + elm + '$1$2>\u00a0</' + elm + '>');
       
  9738 					o.content = o.content.replace(t.reTrailBr, '</' + elm + '>');
       
  9739 				}
       
  9740 			};
       
  9741 
       
  9742 			ed.onBeforeSetContent.add(padd);
       
  9743 			ed.onPostProcess.add(padd);
       
  9744 
       
  9745 			if (s.forced_root_block) {
       
  9746 				ed.onInit.add(t.forceRoots, t);
       
  9747 				ed.onSetContent.add(t.forceRoots, t);
       
  9748 				ed.onBeforeGetContent.add(t.forceRoots, t);
       
  9749 			}
       
  9750 		},
       
  9751 
       
  9752 		setup : function() {
       
  9753 			var t = this, ed = t.editor, s = ed.settings;
       
  9754 
       
  9755 			// Force root blocks when typing and when getting output
       
  9756 			if (s.forced_root_block) {
       
  9757 				ed.onKeyUp.add(t.forceRoots, t);
       
  9758 				ed.onPreProcess.add(t.forceRoots, t);
       
  9759 			}
       
  9760 
       
  9761 			if (s.force_br_newlines) {
       
  9762 				// Force IE to produce BRs on enter
       
  9763 				if (isIE) {
       
  9764 					ed.onKeyPress.add(function(ed, e) {
       
  9765 						var n, s = ed.selection;
       
  9766 
       
  9767 						if (e.keyCode == 13 && s.getNode().nodeName != 'LI') {
       
  9768 							s.setContent('<br id="__" /> ', {format : 'raw'});
       
  9769 							n = ed.dom.get('__');
       
  9770 							n.removeAttribute('id');
       
  9771 							s.select(n);
       
  9772 							s.collapse();
       
  9773 							return Event.cancel(e);
       
  9774 						}
       
  9775 					});
       
  9776 				}
       
  9777 
       
  9778 				return;
       
  9779 			}
       
  9780 
       
  9781 			if (!isIE && s.force_p_newlines) {
       
  9782 /*				ed.onPreProcess.add(function(ed, o) {
       
  9783 					each(ed.dom.select('br', o.node), function(n) {
       
  9784 						var p = n.parentNode;
       
  9785 
       
  9786 						// Replace <p><br /></p> with <p>&nbsp;</p>
       
  9787 						if (p && p.nodeName == 'p' && (p.childNodes.length == 1 || p.lastChild == n)) {
       
  9788 							p.replaceChild(ed.getDoc().createTextNode('\u00a0'), n);
       
  9789 						}
       
  9790 					});
       
  9791 				});*/
       
  9792 
       
  9793 				ed.onKeyPress.add(function(ed, e) {
       
  9794 					if (e.keyCode == 13 && !e.shiftKey) {
       
  9795 						if (!t.insertPara(e))
       
  9796 							Event.cancel(e);
       
  9797 					}
       
  9798 				});
       
  9799 
       
  9800 				if (isGecko) {
       
  9801 					ed.onKeyDown.add(function(ed, e) {
       
  9802 						if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey)
       
  9803 							t.backspaceDelete(e, e.keyCode == 8);
       
  9804 					});
       
  9805 				}
       
  9806 			}
       
  9807 
       
  9808 			function ren(rn, na) {
       
  9809 				var ne = ed.dom.create(na);
       
  9810 
       
  9811 				each(rn.attributes, function(a) {
       
  9812 					if (a.specified && a.nodeValue)
       
  9813 						ne.setAttribute(a.nodeName.toLowerCase(), a.nodeValue);
       
  9814 				});
       
  9815 
       
  9816 				each(rn.childNodes, function(n) {
       
  9817 					ne.appendChild(n.cloneNode(true));
       
  9818 				});
       
  9819 
       
  9820 				rn.parentNode.replaceChild(ne, rn);
       
  9821 
       
  9822 				return ne;
       
  9823 			};
       
  9824 
       
  9825 			// Replaces IE:s auto generated paragraphs with the specified element name
       
  9826 			if (isIE && s.element != 'P') {
       
  9827 				ed.onKeyPress.add(function(ed, e) {
       
  9828 					t.lastElm = ed.selection.getNode().nodeName;
       
  9829 				});
       
  9830 
       
  9831 				ed.onKeyUp.add(function(ed, e) {
       
  9832 					var bl, sel = ed.selection, n = sel.getNode(), b = ed.getBody();
       
  9833 
       
  9834 					if (b.childNodes.length === 1 && n.nodeName == 'P') {
       
  9835 						n = ren(n, s.element);
       
  9836 						sel.select(n);
       
  9837 						sel.collapse();
       
  9838 						ed.nodeChanged();
       
  9839 					} else if (e.keyCode == 13 && !e.shiftKey && t.lastElm != 'P') {
       
  9840 						bl = ed.dom.getParent(n, 'P');
       
  9841 
       
  9842 						if (bl) {
       
  9843 							ren(bl, s.element);
       
  9844 							ed.nodeChanged();
       
  9845 						}
       
  9846 					}
       
  9847 				});
       
  9848 			}
       
  9849 		},
       
  9850 
       
  9851 		find : function(n, t, s) {
       
  9852 			var ed = this.editor, w = ed.getDoc().createTreeWalker(n, 4, null, false), c = -1;
       
  9853 
       
  9854 			while (n = w.nextNode()) {
       
  9855 				c++;
       
  9856 
       
  9857 				// Index by node
       
  9858 				if (t == 0 && n == s)
       
  9859 					return c;
       
  9860 
       
  9861 				// Node by index
       
  9862 				if (t == 1 && c == s)
       
  9863 					return n;
       
  9864 			}
       
  9865 
       
  9866 			return -1;
       
  9867 		},
       
  9868 
       
  9869 		forceRoots : function(ed, e) {
       
  9870 			var t = this, ed = t.editor, b = ed.getBody(), d = ed.getDoc(), se = ed.selection, s = se.getSel(), r = se.getRng(), si = -2, ei, so, eo, tr, c = -0xFFFFFF;
       
  9871 			var nx, bl, bp, sp, le, nl = b.childNodes, i;
       
  9872 
       
  9873 			// Fix for bug #1863847
       
  9874 			if (e && e.keyCode == 13)
       
  9875 				return true;
       
  9876 
       
  9877 			// Wrap non blocks into blocks
       
  9878 			for (i = nl.length - 1; i >= 0; i--) {
       
  9879 				nx = nl[i];
       
  9880 
       
  9881 				// Is text or non block element
       
  9882 				if (nx.nodeType == 3 || (!t.dom.isBlock(nx) && nx.nodeType != 8)) {
       
  9883 					if (!bl) {
       
  9884 						// Create new block but ignore whitespace
       
  9885 						if (nx.nodeType != 3 || /[^\s]/g.test(nx.nodeValue)) {
       
  9886 							// Store selection
       
  9887 							if (si == -2 && r) {
       
  9888 								if (!isIE) {
       
  9889 									// If element is inside body, might not be the case in contentEdiable mode
       
  9890 									if (ed.dom.getParent(r.startContainer, function(e) {return e === b;})) {
       
  9891 										so = r.startOffset;
       
  9892 										eo = r.endOffset;
       
  9893 										si = t.find(b, 0, r.startContainer);
       
  9894 										ei = t.find(b, 0, r.endContainer);
       
  9895 									}
       
  9896 								} else {
       
  9897 									tr = d.body.createTextRange();
       
  9898 									tr.moveToElementText(b);
       
  9899 									tr.collapse(1);
       
  9900 									bp = tr.move('character', c) * -1;
       
  9901 
       
  9902 									tr = r.duplicate();
       
  9903 									tr.collapse(1);
       
  9904 									sp = tr.move('character', c) * -1;
       
  9905 
       
  9906 									tr = r.duplicate();
       
  9907 									tr.collapse(0);
       
  9908 									le = (tr.move('character', c) * -1) - sp;
       
  9909 
       
  9910 									si = sp - bp;
       
  9911 									ei = le;
       
  9912 								}
       
  9913 							}
       
  9914 
       
  9915 							bl = ed.dom.create(ed.settings.forced_root_block);
       
  9916 							bl.appendChild(nx.cloneNode(1));
       
  9917 							nx.parentNode.replaceChild(bl, nx);
       
  9918 						}
       
  9919 					} else {
       
  9920 						if (bl.hasChildNodes())
       
  9921 							bl.insertBefore(nx, bl.firstChild);
       
  9922 						else
       
  9923 							bl.appendChild(nx);
       
  9924 					}
       
  9925 				} else
       
  9926 					bl = null; // Time to create new block
       
  9927 			}
       
  9928 
       
  9929 			// Restore selection
       
  9930 			if (si != -2) {
       
  9931 				if (!isIE) {
       
  9932 					bl = b.getElementsByTagName(ed.settings.element)[0];
       
  9933 					r = d.createRange();
       
  9934 
       
  9935 					// Select last location or generated block
       
  9936 					if (si != -1)
       
  9937 						r.setStart(t.find(b, 1, si), so);
       
  9938 					else
       
  9939 						r.setStart(bl, 0);
       
  9940 
       
  9941 					// Select last location or generated block
       
  9942 					if (ei != -1)
       
  9943 						r.setEnd(t.find(b, 1, ei), eo);
       
  9944 					else
       
  9945 						r.setEnd(bl, 0);
       
  9946 
       
  9947 					if (s) {
       
  9948 						s.removeAllRanges();
       
  9949 						s.addRange(r);
       
  9950 					}
       
  9951 				} else {
       
  9952 					try {
       
  9953 						r = s.createRange();
       
  9954 						r.moveToElementText(b);
       
  9955 						r.collapse(1);
       
  9956 						r.moveStart('character', si);
       
  9957 						r.moveEnd('character', ei);
       
  9958 						r.select();
       
  9959 					} catch (ex) {
       
  9960 						// Ignore
       
  9961 					}
       
  9962 				}
       
  9963 			}
       
  9964 		},
       
  9965 
       
  9966 		getParentBlock : function(n) {
       
  9967 			var d = this.dom;
       
  9968 
       
  9969 			return d.getParent(n, d.isBlock);
       
  9970 		},
       
  9971 
       
  9972 		insertPara : function(e) {
       
  9973 			var t = this, ed = t.editor, dom = ed.dom, d = ed.getDoc(), se = ed.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body;
       
  9974 			var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n, vp = dom.getViewPort(ed.getWin()), y, ch;
       
  9975 
       
  9976 			function isEmpty(n) {
       
  9977 				n = n.innerHTML;
       
  9978 				n = n.replace(/<(img|hr|table)/gi, '-'); // Keep these convert them to - chars
       
  9979 				n = n.replace(/<[^>]+>/g, ''); // Remove all tags
       
  9980 
       
  9981 				return n.replace(/[ \t\r\n]+/g, '') == '';
       
  9982 			};
       
  9983 
       
  9984 			// If root blocks are forced then use Operas default behavior since it's really good
       
  9985 // Removed due to bug: #1853816
       
  9986 //			if (se.forced_root_block && isOpera)
       
  9987 //				return true;
       
  9988 
       
  9989 			// Setup before range
       
  9990 			rb = d.createRange();
       
  9991 
       
  9992 			// If is before the first block element and in body, then move it into first block element
       
  9993 			rb.setStart(s.anchorNode, s.anchorOffset);
       
  9994 			rb.collapse(true);
       
  9995 
       
  9996 			// Setup after range
       
  9997 			ra = d.createRange();
       
  9998 
       
  9999 			// If is before the first block element and in body, then move it into first block element
       
 10000 			ra.setStart(s.focusNode, s.focusOffset);
       
 10001 			ra.collapse(true);
       
 10002 
       
 10003 			// Setup start/end points
       
 10004 			dir = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0;
       
 10005 			sn = dir ? s.anchorNode : s.focusNode;
       
 10006 			so = dir ? s.anchorOffset : s.focusOffset;
       
 10007 			en = dir ? s.focusNode : s.anchorNode;
       
 10008 			eo = dir ? s.focusOffset : s.anchorOffset;
       
 10009 
       
 10010 			// If selection is in empty table cell
       
 10011 			if (sn === en && /^(TD|TH)$/.test(sn.nodeName)) {
       
 10012 				dom.remove(sn.firstChild); // Remove BR
       
 10013 
       
 10014 				// Create two new block elements
       
 10015 				ed.dom.add(sn, se.element, null, '<br />');
       
 10016 				aft = ed.dom.add(sn, se.element, null, '<br />');
       
 10017 
       
 10018 				// Move caret into the last one
       
 10019 				r = d.createRange();
       
 10020 				r.selectNodeContents(aft);
       
 10021 				r.collapse(1);
       
 10022 				ed.selection.setRng(r);
       
 10023 
       
 10024 				return false;
       
 10025 			}
       
 10026 
       
 10027 			// If the caret is in an invalid location in FF we need to move it into the first block
       
 10028 			if (sn == b && en == b && b.firstChild && ed.dom.isBlock(b.firstChild)) {
       
 10029 				sn = en = sn.firstChild;
       
 10030 				so = eo = 0;
       
 10031 				rb = d.createRange();
       
 10032 				rb.setStart(sn, 0);
       
 10033 				ra = d.createRange();
       
 10034 				ra.setStart(en, 0);
       
 10035 			}
       
 10036 
       
 10037 			// Never use body as start or end node
       
 10038 			sn = sn.nodeName == "HTML" ? d.body : sn; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes
       
 10039 			sn = sn.nodeName == "BODY" ? sn.firstChild : sn;
       
 10040 			en = en.nodeName == "HTML" ? d.body : en; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes
       
 10041 			en = en.nodeName == "BODY" ? en.firstChild : en;
       
 10042 
       
 10043 			// Get start and end blocks
       
 10044 			sb = t.getParentBlock(sn);
       
 10045 			eb = t.getParentBlock(en);
       
 10046 			bn = sb ? sb.nodeName : se.element; // Get block name to create
       
 10047 
       
 10048 			// Return inside list use default browser behavior
       
 10049 			if (t.dom.getParent(sb, function(n) { return /OL|UL|PRE/.test(n.nodeName); }))
       
 10050 				return true;
       
 10051 
       
 10052 			// If caption or absolute layers then always generate new blocks within
       
 10053 			if (sb && (sb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(sb.style.position))) {
       
 10054 				bn = se.element;
       
 10055 				sb = null;
       
 10056 			}
       
 10057 
       
 10058 			// If caption or absolute layers then always generate new blocks within
       
 10059 			if (eb && (eb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(eb.style.position))) {
       
 10060 				bn = se.element;
       
 10061 				eb = null;
       
 10062 			}
       
 10063 
       
 10064 			// Use P instead
       
 10065 			if (/(TD|TABLE|TH|CAPTION)/.test(bn) || (sb && bn == "DIV" && /left|right/gi.test(sb.style.cssFloat))) {
       
 10066 				bn = se.element;
       
 10067 				sb = eb = null;
       
 10068 			}
       
 10069 
       
 10070 			// Setup new before and after blocks
       
 10071 			bef = (sb && sb.nodeName == bn) ? sb.cloneNode(0) : ed.dom.create(bn);
       
 10072 			aft = (eb && eb.nodeName == bn) ? eb.cloneNode(0) : ed.dom.create(bn);
       
 10073 
       
 10074 			// Remove id from after clone
       
 10075 			aft.removeAttribute('id');
       
 10076 
       
 10077 			// Is header and cursor is at the end, then force paragraph under
       
 10078 			if (/^(H[1-6])$/.test(bn) && sn.nodeValue && so == sn.nodeValue.length)
       
 10079 				aft = ed.dom.create(se.element);
       
 10080 
       
 10081 			// Find start chop node
       
 10082 			n = sc = sn;
       
 10083 			do {
       
 10084 				if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))
       
 10085 					break;
       
 10086 
       
 10087 				sc = n;
       
 10088 			} while ((n = n.previousSibling ? n.previousSibling : n.parentNode));
       
 10089 
       
 10090 			// Find end chop node
       
 10091 			n = ec = en;
       
 10092 			do {
       
 10093 				if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))
       
 10094 					break;
       
 10095 
       
 10096 				ec = n;
       
 10097 			} while ((n = n.nextSibling ? n.nextSibling : n.parentNode));
       
 10098 
       
 10099 			// Place first chop part into before block element
       
 10100 			if (sc.nodeName == bn)
       
 10101 				rb.setStart(sc, 0);
       
 10102 			else
       
 10103 				rb.setStartBefore(sc);
       
 10104 
       
 10105 			rb.setEnd(sn, so);
       
 10106 			bef.appendChild(rb.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari
       
 10107 
       
 10108 			// Place secnd chop part within new block element
       
 10109 			try {
       
 10110 				ra.setEndAfter(ec);
       
 10111 			} catch(ex) {
       
 10112 				//console.debug(s.focusNode, s.focusOffset);
       
 10113 			}
       
 10114 
       
 10115 			ra.setStart(en, eo);
       
 10116 			aft.appendChild(ra.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari
       
 10117 
       
 10118 			// Create range around everything
       
 10119 			r = d.createRange();
       
 10120 			if (!sc.previousSibling && sc.parentNode.nodeName == bn) {
       
 10121 				r.setStartBefore(sc.parentNode);
       
 10122 			} else {
       
 10123 				if (rb.startContainer.nodeName == bn && rb.startOffset == 0)
       
 10124 					r.setStartBefore(rb.startContainer);
       
 10125 				else
       
 10126 					r.setStart(rb.startContainer, rb.startOffset);
       
 10127 			}
       
 10128 
       
 10129 			if (!ec.nextSibling && ec.parentNode.nodeName == bn)
       
 10130 				r.setEndAfter(ec.parentNode);
       
 10131 			else
       
 10132 				r.setEnd(ra.endContainer, ra.endOffset);
       
 10133 
       
 10134 			// Delete and replace it with new block elements
       
 10135 			r.deleteContents();
       
 10136 
       
 10137 			if (isOpera)
       
 10138 				ed.getWin().scrollTo(0, vp.y);
       
 10139 
       
 10140 			// Never wrap blocks in blocks
       
 10141 			if (bef.firstChild && bef.firstChild.nodeName == bn)
       
 10142 				bef.innerHTML = bef.firstChild.innerHTML;
       
 10143 
       
 10144 			if (aft.firstChild && aft.firstChild.nodeName == bn)
       
 10145 				aft.innerHTML = aft.firstChild.innerHTML;
       
 10146 
       
 10147 			// Padd empty blocks
       
 10148 			if (isEmpty(bef))
       
 10149 				bef.innerHTML = '<br />';
       
 10150 
       
 10151 			if (isEmpty(aft))
       
 10152 				aft.innerHTML = isOpera ? '&nbsp;' : '<br />'; // Extra space for Opera so that the caret can move there
       
 10153 
       
 10154 			// Opera needs this one backwards for older versions
       
 10155 			if (isOpera && parseFloat(opera.version()) < 9.5) {
       
 10156 				r.insertNode(bef);
       
 10157 				r.insertNode(aft);
       
 10158 			} else {
       
 10159 				r.insertNode(aft);
       
 10160 				r.insertNode(bef);
       
 10161 			}
       
 10162 
       
 10163 			// Normalize
       
 10164 			aft.normalize();
       
 10165 			bef.normalize();
       
 10166 
       
 10167 			function first(n) {
       
 10168 				return d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() || n;
       
 10169 			};
       
 10170 
       
 10171 			// Move cursor and scroll into view
       
 10172 			r = d.createRange();
       
 10173 			r.selectNodeContents(isGecko ? first(aft) : aft);
       
 10174 			r.collapse(1);
       
 10175 			s.removeAllRanges();
       
 10176 			s.addRange(r);
       
 10177 
       
 10178 			// scrollIntoView seems to scroll the parent window in most browsers now including FF 3.0b4 so it's time to stop using it and do it our selfs
       
 10179 			y = ed.dom.getPos(aft).y;
       
 10180 			ch = aft.clientHeight;
       
 10181 
       
 10182 			// Is element within viewport
       
 10183 			if (y < vp.y || y + ch > vp.y + vp.h) {
       
 10184 				ed.getWin().scrollTo(0, y < vp.y ? y : y - vp.h + 25); // Needs to be hardcoded to roughly one line of text if a huge text block is broken into two blocks
       
 10185 				//console.debug('SCROLL!', 'vp.y: ' + vp.y, 'y' + y, 'vp.h' + vp.h, 'clientHeight' + aft.clientHeight, 'yyy: ' + (y < vp.y ? y : y - vp.h + aft.clientHeight));
       
 10186 			}
       
 10187 
       
 10188 			return false;
       
 10189 		},
       
 10190 
       
 10191 		backspaceDelete : function(e, bs) {
       
 10192 			var t = this, ed = t.editor, b = ed.getBody(), n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n, w, tn;
       
 10193 
       
 10194 			// The caret sometimes gets stuck in Gecko if you delete empty paragraphs
       
 10195 			// This workaround removes the element by hand and moves the caret to the previous element
       
 10196 			if (sc && ed.dom.isBlock(sc) && !/^(TD|TH)$/.test(sc.nodeName) && bs) {
       
 10197 				if (sc.childNodes.length == 0 || (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR')) {
       
 10198 					// Find previous block element
       
 10199 					n = sc;
       
 10200 					while ((n = n.previousSibling) && !ed.dom.isBlock(n)) ;
       
 10201 
       
 10202 					if (n) {
       
 10203 						if (sc != b.firstChild) {
       
 10204 							// Find last text node
       
 10205 							w = ed.dom.doc.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
       
 10206 							while (tn = w.nextNode())
       
 10207 								n = tn;
       
 10208 
       
 10209 							// Place caret at the end of last text node
       
 10210 							r = ed.getDoc().createRange();
       
 10211 							r.setStart(n, n.nodeValue ? n.nodeValue.length : 0);
       
 10212 							r.setEnd(n, n.nodeValue ? n.nodeValue.length : 0);
       
 10213 							se.setRng(r);
       
 10214 
       
 10215 							// Remove the target container
       
 10216 							ed.dom.remove(sc);
       
 10217 						}
       
 10218 
       
 10219 						return Event.cancel(e);
       
 10220 					}
       
 10221 				}
       
 10222 			}
       
 10223 
       
 10224 			// Gecko generates BR elements here and there, we don't like those so lets remove them
       
 10225 			function handler(e) {
       
 10226 				var pr;
       
 10227 
       
 10228 				e = e.target;
       
 10229 
       
 10230 				// A new BR was created in a block element, remove it
       
 10231 				if (e && e.parentNode && e.nodeName == 'BR' && (n = t.getParentBlock(e))) {
       
 10232 					pr = e.previousSibling;
       
 10233 
       
 10234 					Event.remove(b, 'DOMNodeInserted', handler);
       
 10235 
       
 10236 					// Is there whitespace at the end of the node before then we might need the pesky BR
       
 10237 					// to place the caret at a correct location see bug: #2013943
       
 10238 					if (pr && pr.nodeType == 3 && /\s+$/.test(pr.nodeValue))
       
 10239 						return;
       
 10240 
       
 10241 					// Only remove BR elements that got inserted in the middle of the text
       
 10242 					if (e.previousSibling || e.nextSibling)
       
 10243 						ed.dom.remove(e);
       
 10244 				}
       
 10245 			};
       
 10246 
       
 10247 			// Listen for new nodes
       
 10248 			Event._add(b, 'DOMNodeInserted', handler);
       
 10249 
       
 10250 			// Remove listener
       
 10251 			window.setTimeout(function() {
       
 10252 				Event._remove(b, 'DOMNodeInserted', handler);
       
 10253 			}, 1);
       
 10254 		}
       
 10255 	});
       
 10256 })();
       
 10257 
       
 10258 /* file:jscripts/tiny_mce/classes/ControlManager.js */
       
 10259 
       
 10260 (function() {
       
 10261 	// Shorten names
       
 10262 	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, extend = tinymce.extend;
       
 10263 
       
 10264 	tinymce.create('tinymce.ControlManager', {
       
 10265 		ControlManager : function(ed, s) {
       
 10266 			var t = this, i;
       
 10267 
       
 10268 			s = s || {};
       
 10269 			t.editor = ed;
       
 10270 			t.controls = {};
       
 10271 			t.onAdd = new tinymce.util.Dispatcher(t);
       
 10272 			t.onPostRender = new tinymce.util.Dispatcher(t);
       
 10273 			t.prefix = s.prefix || ed.id + '_';
       
 10274 			t._cls = {};
       
 10275 
       
 10276 			t.onPostRender.add(function() {
       
 10277 				each(t.controls, function(c) {
       
 10278 					c.postRender();
       
 10279 				});
       
 10280 			});
       
 10281 		},
       
 10282 
       
 10283 		get : function(id) {
       
 10284 			return this.controls[this.prefix + id] || this.controls[id];
       
 10285 		},
       
 10286 
       
 10287 		setActive : function(id, s) {
       
 10288 			var c = null;
       
 10289 
       
 10290 			if (c = this.get(id))
       
 10291 				c.setActive(s);
       
 10292 
       
 10293 			return c;
       
 10294 		},
       
 10295 
       
 10296 		setDisabled : function(id, s) {
       
 10297 			var c = null;
       
 10298 
       
 10299 			if (c = this.get(id))
       
 10300 				c.setDisabled(s);
       
 10301 
       
 10302 			return c;
       
 10303 		},
       
 10304 
       
 10305 		add : function(c) {
       
 10306 			var t = this;
       
 10307 
       
 10308 			if (c) {
       
 10309 				t.controls[c.id] = c;
       
 10310 				t.onAdd.dispatch(c, t);
       
 10311 			}
       
 10312 
       
 10313 			return c;
       
 10314 		},
       
 10315 
       
 10316 		createControl : function(n) {
       
 10317 			var c, t = this, ed = t.editor;
       
 10318 
       
 10319 			each(ed.plugins, function(p) {
       
 10320 				if (p.createControl) {
       
 10321 					c = p.createControl(n, t);
       
 10322 
       
 10323 					if (c)
       
 10324 						return false;
       
 10325 				}
       
 10326 			});
       
 10327 
       
 10328 			switch (n) {
       
 10329 				case "|":
       
 10330 				case "separator":
       
 10331 					return t.createSeparator();
       
 10332 			}
       
 10333 
       
 10334 			if (!c && ed.buttons && (c = ed.buttons[n]))
       
 10335 				return t.createButton(n, c);
       
 10336 
       
 10337 			return t.add(c);
       
 10338 		},
       
 10339 
       
 10340 		createDropMenu : function(id, s, cc) {
       
 10341 			var t = this, ed = t.editor, c, bm, v, cls;
       
 10342 
       
 10343 			s = extend({
       
 10344 				'class' : 'mceDropDown',
       
 10345 				constrain : ed.settings.constrain_menus
       
 10346 			}, s);
       
 10347 
       
 10348 			s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin';
       
 10349 			if (v = ed.getParam('skin_variant'))
       
 10350 				s['class'] += ' ' + ed.getParam('skin') + 'Skin' + v.substring(0, 1).toUpperCase() + v.substring(1);
       
 10351 
       
 10352 			id = t.prefix + id;
       
 10353 			cls = cc || t._cls.dropmenu || tinymce.ui.DropMenu;
       
 10354 			c = t.controls[id] = new cls(id, s);
       
 10355 			c.onAddItem.add(function(c, o) {
       
 10356 				var s = o.settings;
       
 10357 
       
 10358 				s.title = ed.getLang(s.title, s.title);
       
 10359 
       
 10360 				if (!s.onclick) {
       
 10361 					s.onclick = function(v) {
       
 10362 						ed.execCommand(s.cmd, s.ui || false, s.value);
       
 10363 					};
       
 10364 				}
       
 10365 			});
       
 10366 
       
 10367 			ed.onRemove.add(function() {
       
 10368 				c.destroy();
       
 10369 			});
       
 10370 
       
 10371 			// Fix for bug #1897785, #1898007
       
 10372 			if (tinymce.isIE) {
       
 10373 				c.onShowMenu.add(function() {
       
 10374 					bm = ed.selection.getBookmark(1);
       
 10375 				});
       
 10376 
       
 10377 				c.onHideMenu.add(function() {
       
 10378 					if (bm)
       
 10379 						ed.selection.moveToBookmark(bm);
       
 10380 				});
       
 10381 			}
       
 10382 
       
 10383 			return t.add(c);
       
 10384 		},
       
 10385 
       
 10386 		createListBox : function(id, s, cc) {
       
 10387 			var t = this, ed = t.editor, cmd, c, cls;
       
 10388 
       
 10389 			if (t.get(id))
       
 10390 				return null;
       
 10391 
       
 10392 			s.title = ed.translate(s.title);
       
 10393 			s.scope = s.scope || ed;
       
 10394 
       
 10395 			if (!s.onselect) {
       
 10396 				s.onselect = function(v) {
       
 10397 					ed.execCommand(s.cmd, s.ui || false, v || s.value);
       
 10398 				};
       
 10399 			}
       
 10400 
       
 10401 			s = extend({
       
 10402 				title : s.title,
       
 10403 				'class' : 'mce_' + id,
       
 10404 				scope : s.scope,
       
 10405 				control_manager : t
       
 10406 			}, s);
       
 10407 
       
 10408 			id = t.prefix + id;
       
 10409 
       
 10410 			if (ed.settings.use_native_selects)
       
 10411 				c = new tinymce.ui.NativeListBox(id, s);
       
 10412 			else {
       
 10413 				cls = cc || t._cls.listbox || tinymce.ui.ListBox;
       
 10414 				c = new cls(id, s);
       
 10415 			}
       
 10416 
       
 10417 			t.controls[id] = c;
       
 10418 
       
 10419 			// Fix focus problem in Safari
       
 10420 			if (tinymce.isWebKit) {
       
 10421 				c.onPostRender.add(function(c, n) {
       
 10422 					// Store bookmark on mousedown
       
 10423 					Event.add(n, 'mousedown', function() {
       
 10424 						ed.bookmark = ed.selection.getBookmark('simple');
       
 10425 					});
       
 10426 
       
 10427 					// Restore on focus, since it might be lost
       
 10428 					Event.add(n, 'focus', function() {
       
 10429 						ed.selection.moveToBookmark(ed.bookmark);
       
 10430 						ed.bookmark = null;
       
 10431 					});
       
 10432 				});
       
 10433 			}
       
 10434 
       
 10435 			if (c.hideMenu)
       
 10436 				ed.onMouseDown.add(c.hideMenu, c);
       
 10437 
       
 10438 			return t.add(c);
       
 10439 		},
       
 10440 
       
 10441 		createButton : function(id, s, cc) {
       
 10442 			var t = this, ed = t.editor, o, c, cls;
       
 10443 
       
 10444 			if (t.get(id))
       
 10445 				return null;
       
 10446 
       
 10447 			s.title = ed.translate(s.title);
       
 10448 			s.label = ed.translate(s.label);
       
 10449 			s.scope = s.scope || ed;
       
 10450 
       
 10451 			if (!s.onclick && !s.menu_button) {
       
 10452 				s.onclick = function() {
       
 10453 					ed.execCommand(s.cmd, s.ui || false, s.value);
       
 10454 				};
       
 10455 			}
       
 10456 
       
 10457 			s = extend({
       
 10458 				title : s.title,
       
 10459 				'class' : 'mce_' + id,
       
 10460 				unavailable_prefix : ed.getLang('unavailable', ''),
       
 10461 				scope : s.scope,
       
 10462 				control_manager : t
       
 10463 			}, s);
       
 10464 
       
 10465 			id = t.prefix + id;
       
 10466 
       
 10467 			if (s.menu_button) {
       
 10468 				cls = cc || t._cls.menubutton || tinymce.ui.MenuButton;
       
 10469 				c = new cls(id, s);
       
 10470 				ed.onMouseDown.add(c.hideMenu, c);
       
 10471 			} else {
       
 10472 				cls = t._cls.button || tinymce.ui.Button;
       
 10473 				c = new cls(id, s);
       
 10474 			}
       
 10475 
       
 10476 			return t.add(c);
       
 10477 		},
       
 10478 
       
 10479 		createMenuButton : function(id, s) {
       
 10480 			s = s || {};
       
 10481 			s.menu_button = 1;
       
 10482 
       
 10483 			return this.createButton(id, s);
       
 10484 		},
       
 10485 
       
 10486 		createSplitButton : function(id, s, cc) {
       
 10487 			var t = this, ed = t.editor, cmd, c, cls;
       
 10488 
       
 10489 			if (t.get(id))
       
 10490 				return null;
       
 10491 
       
 10492 			s.title = ed.translate(s.title);
       
 10493 			s.scope = s.scope || ed;
       
 10494 
       
 10495 			if (!s.onclick) {
       
 10496 				s.onclick = function(v) {
       
 10497 					ed.execCommand(s.cmd, s.ui || false, v || s.value);
       
 10498 				};
       
 10499 			}
       
 10500 
       
 10501 			if (!s.onselect) {
       
 10502 				s.onselect = function(v) {
       
 10503 					ed.execCommand(s.cmd, s.ui || false, v || s.value);
       
 10504 				};
       
 10505 			}
       
 10506 
       
 10507 			s = extend({
       
 10508 				title : s.title,
       
 10509 				'class' : 'mce_' + id,
       
 10510 				scope : s.scope,
       
 10511 				control_manager : t
       
 10512 			}, s);
       
 10513 
       
 10514 			id = t.prefix + id;
       
 10515 			cls = cc || t._cls.splitbutton || tinymce.ui.SplitButton;
       
 10516 			c = t.add(new cls(id, s));
       
 10517 			ed.onMouseDown.add(c.hideMenu, c);
       
 10518 
       
 10519 			return c;
       
 10520 		},
       
 10521 
       
 10522 		createColorSplitButton : function(id, s, cc) {
       
 10523 			var t = this, ed = t.editor, cmd, c, cls, bm;
       
 10524 
       
 10525 			if (t.get(id))
       
 10526 				return null;
       
 10527 
       
 10528 			s.title = ed.translate(s.title);
       
 10529 			s.scope = s.scope || ed;
       
 10530 
       
 10531 			if (!s.onclick) {
       
 10532 				s.onclick = function(v) {
       
 10533 					ed.execCommand(s.cmd, s.ui || false, v || s.value);
       
 10534 				};
       
 10535 			}
       
 10536 
       
 10537 			if (!s.onselect) {
       
 10538 				s.onselect = function(v) {
       
 10539 					ed.execCommand(s.cmd, s.ui || false, v || s.value);
       
 10540 				};
       
 10541 			}
       
 10542 
       
 10543 			s = extend({
       
 10544 				title : s.title,
       
 10545 				'class' : 'mce_' + id,
       
 10546 				'menu_class' : ed.getParam('skin') + 'Skin',
       
 10547 				scope : s.scope,
       
 10548 				more_colors_title : ed.getLang('more_colors')
       
 10549 			}, s);
       
 10550 
       
 10551 			id = t.prefix + id;
       
 10552 			cls = cc || t._cls.colorsplitbutton || tinymce.ui.ColorSplitButton;
       
 10553 			c = new cls(id, s);
       
 10554 			ed.onMouseDown.add(c.hideMenu, c);
       
 10555 
       
 10556 			// Remove the menu element when the editor is removed
       
 10557 			ed.onRemove.add(function() {
       
 10558 				c.destroy();
       
 10559 			});
       
 10560 
       
 10561 			// Fix for bug #1897785, #1898007
       
 10562 			if (tinymce.isIE) {
       
 10563 				c.onShowMenu.add(function() {
       
 10564 					bm = ed.selection.getBookmark(1);
       
 10565 				});
       
 10566 
       
 10567 				c.onHideMenu.add(function() {
       
 10568 					if (bm) {
       
 10569 						ed.selection.moveToBookmark(bm);
       
 10570 						bm = 0;
       
 10571 					}
       
 10572 				});
       
 10573 			}
       
 10574 
       
 10575 			return t.add(c);
       
 10576 		},
       
 10577 
       
 10578 		createToolbar : function(id, s, cc) {
       
 10579 			var c, t = this, cls;
       
 10580 
       
 10581 			id = t.prefix + id;
       
 10582 			cls = cc || t._cls.toolbar || tinymce.ui.Toolbar;
       
 10583 			c = new cls(id, s);
       
 10584 
       
 10585 			if (t.get(id))
       
 10586 				return null;
       
 10587 
       
 10588 			return t.add(c);
       
 10589 		},
       
 10590 
       
 10591 		createSeparator : function(cc) {
       
 10592 			var cls = cc || this._cls.separator || tinymce.ui.Separator;
       
 10593 
       
 10594 			return new cls();
       
 10595 		},
       
 10596 
       
 10597 		setControlType : function(n, c) {
       
 10598 			return this._cls[n.toLowerCase()] = c;
       
 10599 		},
       
 10600 
       
 10601 		destroy : function() {
       
 10602 			each(this.controls, function(c) {
       
 10603 				c.destroy();
       
 10604 			});
       
 10605 
       
 10606 			this.controls = null;
       
 10607 		}
       
 10608 
       
 10609 		});
       
 10610 })();
       
 10611 
       
 10612 /* file:jscripts/tiny_mce/classes/WindowManager.js */
       
 10613 
       
 10614 (function() {
       
 10615 	var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isIE = tinymce.isIE, isOpera = tinymce.isOpera;
       
 10616 
       
 10617 	tinymce.create('tinymce.WindowManager', {
       
 10618 		WindowManager : function(ed) {
       
 10619 			var t = this;
       
 10620 
       
 10621 			t.editor = ed;
       
 10622 			t.onOpen = new Dispatcher(t);
       
 10623 			t.onClose = new Dispatcher(t);
       
 10624 			t.params = {};
       
 10625 			t.features = {};
       
 10626 		},
       
 10627 
       
 10628 		open : function(s, p) {
       
 10629 			var t = this, f = '', x, y, mo = t.editor.settings.dialog_type == 'modal', w, sw, sh, vp = tinymce.DOM.getViewPort(), u;
       
 10630 
       
 10631 			// Default some options
       
 10632 			s = s || {};
       
 10633 			p = p || {};
       
 10634 			sw = isOpera ? vp.w : screen.width; // Opera uses windows inside the Opera window
       
 10635 			sh = isOpera ? vp.h : screen.height;
       
 10636 			s.name = s.name || 'mc_' + new Date().getTime();
       
 10637 			s.width = parseInt(s.width || 320);
       
 10638 			s.height = parseInt(s.height || 240);
       
 10639 			s.resizable = true;
       
 10640 			s.left = s.left || parseInt(sw / 2.0) - (s.width / 2.0);
       
 10641 			s.top = s.top || parseInt(sh / 2.0) - (s.height / 2.0);
       
 10642 			p.inline = false;
       
 10643 			p.mce_width = s.width;
       
 10644 			p.mce_height = s.height;
       
 10645 			p.mce_auto_focus = s.auto_focus;
       
 10646 
       
 10647 			if (mo) {
       
 10648 				if (isIE) {
       
 10649 					s.center = true;
       
 10650 					s.help = false;
       
 10651 					s.dialogWidth = s.width + 'px';
       
 10652 					s.dialogHeight = s.height + 'px';
       
 10653 					s.scroll = s.scrollbars || false;
       
 10654 				}
       
 10655 			}
       
 10656 
       
 10657 			// Build features string
       
 10658 			each(s, function(v, k) {
       
 10659 				if (tinymce.is(v, 'boolean'))
       
 10660 					v = v ? 'yes' : 'no';
       
 10661 
       
 10662 				if (!/^(name|url)$/.test(k)) {
       
 10663 					if (isIE && mo)
       
 10664 						f += (f ? ';' : '') + k + ':' + v;
       
 10665 					else
       
 10666 						f += (f ? ',' : '') + k + '=' + v;
       
 10667 				}
       
 10668 			});
       
 10669 
       
 10670 			t.features = s;
       
 10671 			t.params = p;
       
 10672 			t.onOpen.dispatch(t, s, p);
       
 10673 
       
 10674 			u = s.url || s.file;
       
 10675 			if (tinymce.relaxedDomain)
       
 10676 				u += (u.indexOf('?') == -1 ? '?' : '&') + 'mce_rdomain=' + tinymce.relaxedDomain;
       
 10677 
       
 10678 			u = tinymce._addVer(u);
       
 10679 
       
 10680 			try {
       
 10681 				if (isIE && mo) {
       
 10682 					w = 1;
       
 10683 					window.showModalDialog(u, window, f);
       
 10684 				} else
       
 10685 					w = window.open(u, s.name, f);
       
 10686 			} catch (ex) {
       
 10687 				// Ignore
       
 10688 			}
       
 10689 
       
 10690 			if (!w)
       
 10691 				alert(t.editor.getLang('popup_blocked'));
       
 10692 		},
       
 10693 
       
 10694 		close : function(w) {
       
 10695 			w.close();
       
 10696 			this.onClose.dispatch(this);
       
 10697 		},
       
 10698 
       
 10699 		createInstance : function(cl, a, b, c, d, e) {
       
 10700 			var f = tinymce.resolve(cl);
       
 10701 
       
 10702 			return new f(a, b, c, d, e);
       
 10703 		},
       
 10704 
       
 10705 		confirm : function(t, cb, s, w) {
       
 10706 			w = w || window;
       
 10707 
       
 10708 			cb.call(s || this, w.confirm(this._decode(this.editor.getLang(t, t))));
       
 10709 		},
       
 10710 
       
 10711 		alert : function(tx, cb, s, w) {
       
 10712 			var t = this;
       
 10713 
       
 10714 			w = w || window;
       
 10715 			w.alert(t._decode(t.editor.getLang(tx, tx)));
       
 10716 
       
 10717 			if (cb)
       
 10718 				cb.call(s || t);
       
 10719 		},
       
 10720 
       
 10721 		// Internal functions
       
 10722 
       
 10723 		_decode : function(s) {
       
 10724 			return tinymce.DOM.decode(s).replace(/\\n/g, '\n');
       
 10725 		}
       
 10726 
       
 10727 		});
       
 10728 }());