PageRenderTime 102ms CodeModel.GetById 12ms app.highlight 75ms RepoModel.GetById 1ms app.codeStats 0ms

/BlogEngine/BlogEngine.NET/editors/tiny_mce_3_4_3_1/tiny_mce_src.js

#
JavaScript | 2488 lines | 2193 code | 222 blank | 73 comment | 196 complexity | 2c6c96b9d0b46ee7053301c941d3da97 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1(function(win) {
   2	var whiteSpaceRe = /^\s*|\s*$/g,
   3		undefined, isRegExpBroken = 'B'.replace(/A(.)|B/, '$1') === '$1';
   4
   5	var tinymce = {
   6		majorVersion : '3',
   7
   8		minorVersion : '4.3.1',
   9
  10		releaseDate : '2011-06-16',
  11
  12		_init : function() {
  13			var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
  14
  15			t.isOpera = win.opera && opera.buildNumber;
  16
  17			t.isWebKit = /WebKit/.test(ua);
  18
  19			t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);
  20
  21			t.isIE6 = t.isIE && /MSIE [56]/.test(ua);
  22
  23			t.isGecko = !t.isWebKit && /Gecko/.test(ua);
  24
  25			t.isMac = ua.indexOf('Mac') != -1;
  26
  27			t.isAir = /adobeair/i.test(ua);
  28
  29			t.isIDevice = /(iPad|iPhone)/.test(ua);
  30			
  31			t.isIOS5 = t.isIDevice && ua.match(/AppleWebKit\/(\d*)/)[1]>=534;
  32
  33			// TinyMCE .NET webcontrol might be setting the values for TinyMCE
  34			if (win.tinyMCEPreInit) {
  35				t.suffix = tinyMCEPreInit.suffix;
  36				t.baseURL = tinyMCEPreInit.base;
  37				t.query = tinyMCEPreInit.query;
  38				return;
  39			}
  40
  41			// Get suffix and base
  42			t.suffix = '';
  43
  44			// If base element found, add that infront of baseURL
  45			nl = d.getElementsByTagName('base');
  46			for (i=0; i<nl.length; i++) {
  47				if (v = nl[i].href) {
  48					// Host only value like http://site.com or http://site.com:8008
  49					if (/^https?:\/\/[^\/]+$/.test(v))
  50						v += '/';
  51
  52					base = v ? v.match(/.*\//)[0] : ''; // Get only directory
  53				}
  54			}
  55
  56			function getBase(n) {
  57				if (n.src && /tiny_mce(|_gzip|_jquery|_prototype|_full)(_dev|_src)?.js/.test(n.src)) {
  58					if (/_(src|dev)\.js/g.test(n.src))
  59						t.suffix = '_src';
  60
  61					if ((p = n.src.indexOf('?')) != -1)
  62						t.query = n.src.substring(p + 1);
  63
  64					t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));
  65
  66					// If path to script is relative and a base href was found add that one infront
  67					// the src property will always be an absolute one on non IE browsers and IE 8
  68					// so this logic will basically only be executed on older IE versions
  69					if (base && t.baseURL.indexOf('://') == -1 && t.baseURL.indexOf('/') !== 0)
  70						t.baseURL = base + t.baseURL;
  71
  72					return t.baseURL;
  73				}
  74
  75				return null;
  76			};
  77
  78			// Check document
  79			nl = d.getElementsByTagName('script');
  80			for (i=0; i<nl.length; i++) {
  81				if (getBase(nl[i]))
  82					return;
  83			}
  84
  85			// Check head
  86			n = d.getElementsByTagName('head')[0];
  87			if (n) {
  88				nl = n.getElementsByTagName('script');
  89				for (i=0; i<nl.length; i++) {
  90					if (getBase(nl[i]))
  91						return;
  92				}
  93			}
  94
  95			return;
  96		},
  97
  98		is : function(o, t) {
  99			if (!t)
 100				return o !== undefined;
 101
 102			if (t == 'array' && (o.hasOwnProperty && o instanceof Array))
 103				return true;
 104
 105			return typeof(o) == t;
 106		},
 107
 108		makeMap : function(items, delim, map) {
 109			var i;
 110
 111			items = items || [];
 112			delim = delim || ',';
 113
 114			if (typeof(items) == "string")
 115				items = items.split(delim);
 116
 117			map = map || {};
 118
 119			i = items.length;
 120			while (i--)
 121				map[items[i]] = {};
 122
 123			return map;
 124		},
 125
 126		each : function(o, cb, s) {
 127			var n, l;
 128
 129			if (!o)
 130				return 0;
 131
 132			s = s || o;
 133
 134			if (o.length !== undefined) {
 135				// Indexed arrays, needed for Safari
 136				for (n=0, l = o.length; n < l; n++) {
 137					if (cb.call(s, o[n], n, o) === false)
 138						return 0;
 139				}
 140			} else {
 141				// Hashtables
 142				for (n in o) {
 143					if (o.hasOwnProperty(n)) {
 144						if (cb.call(s, o[n], n, o) === false)
 145							return 0;
 146					}
 147				}
 148			}
 149
 150			return 1;
 151		},
 152
 153
 154		map : function(a, f) {
 155			var o = [];
 156
 157			tinymce.each(a, function(v) {
 158				o.push(f(v));
 159			});
 160
 161			return o;
 162		},
 163
 164		grep : function(a, f) {
 165			var o = [];
 166
 167			tinymce.each(a, function(v) {
 168				if (!f || f(v))
 169					o.push(v);
 170			});
 171
 172			return o;
 173		},
 174
 175		inArray : function(a, v) {
 176			var i, l;
 177
 178			if (a) {
 179				for (i = 0, l = a.length; i < l; i++) {
 180					if (a[i] === v)
 181						return i;
 182				}
 183			}
 184
 185			return -1;
 186		},
 187
 188		extend : function(o, e) {
 189			var i, l, a = arguments;
 190
 191			for (i = 1, l = a.length; i < l; i++) {
 192				e = a[i];
 193
 194				tinymce.each(e, function(v, n) {
 195					if (v !== undefined)
 196						o[n] = v;
 197				});
 198			}
 199
 200			return o;
 201		},
 202
 203
 204		trim : function(s) {
 205			return (s ? '' + s : '').replace(whiteSpaceRe, '');
 206		},
 207
 208		create : function(s, p, root) {
 209			var t = this, sp, ns, cn, scn, c, de = 0;
 210
 211			// Parse : <prefix> <class>:<super class>
 212			s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
 213			cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
 214
 215			// Create namespace for new class
 216			ns = t.createNS(s[3].replace(/\.\w+$/, ''), root);
 217
 218			// Class already exists
 219			if (ns[cn])
 220				return;
 221
 222			// Make pure static class
 223			if (s[2] == 'static') {
 224				ns[cn] = p;
 225
 226				if (this.onCreate)
 227					this.onCreate(s[2], s[3], ns[cn]);
 228
 229				return;
 230			}
 231
 232			// Create default constructor
 233			if (!p[cn]) {
 234				p[cn] = function() {};
 235				de = 1;
 236			}
 237
 238			// Add constructor and methods
 239			ns[cn] = p[cn];
 240			t.extend(ns[cn].prototype, p);
 241
 242			// Extend
 243			if (s[5]) {
 244				sp = t.resolve(s[5]).prototype;
 245				scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
 246
 247				// Extend constructor
 248				c = ns[cn];
 249				if (de) {
 250					// Add passthrough constructor
 251					ns[cn] = function() {
 252						return sp[scn].apply(this, arguments);
 253					};
 254				} else {
 255					// Add inherit constructor
 256					ns[cn] = function() {
 257						this.parent = sp[scn];
 258						return c.apply(this, arguments);
 259					};
 260				}
 261				ns[cn].prototype[cn] = ns[cn];
 262
 263				// Add super methods
 264				t.each(sp, function(f, n) {
 265					ns[cn].prototype[n] = sp[n];
 266				});
 267
 268				// Add overridden methods
 269				t.each(p, function(f, n) {
 270					// Extend methods if needed
 271					if (sp[n]) {
 272						ns[cn].prototype[n] = function() {
 273							this.parent = sp[n];
 274							return f.apply(this, arguments);
 275						};
 276					} else {
 277						if (n != cn)
 278							ns[cn].prototype[n] = f;
 279					}
 280				});
 281			}
 282
 283			// Add static methods
 284			t.each(p['static'], function(f, n) {
 285				ns[cn][n] = f;
 286			});
 287
 288			if (this.onCreate)
 289				this.onCreate(s[2], s[3], ns[cn].prototype);
 290		},
 291
 292		walk : function(o, f, n, s) {
 293			s = s || this;
 294
 295			if (o) {
 296				if (n)
 297					o = o[n];
 298
 299				tinymce.each(o, function(o, i) {
 300					if (f.call(s, o, i, n) === false)
 301						return false;
 302
 303					tinymce.walk(o, f, n, s);
 304				});
 305			}
 306		},
 307
 308		createNS : function(n, o) {
 309			var i, v;
 310
 311			o = o || win;
 312
 313			n = n.split('.');
 314			for (i=0; i<n.length; i++) {
 315				v = n[i];
 316
 317				if (!o[v])
 318					o[v] = {};
 319
 320				o = o[v];
 321			}
 322
 323			return o;
 324		},
 325
 326		resolve : function(n, o) {
 327			var i, l;
 328
 329			o = o || win;
 330
 331			n = n.split('.');
 332			for (i = 0, l = n.length; i < l; i++) {
 333				o = o[n[i]];
 334
 335				if (!o)
 336					break;
 337			}
 338
 339			return o;
 340		},
 341
 342		addUnload : function(f, s) {
 343			var t = this;
 344
 345			f = {func : f, scope : s || this};
 346
 347			if (!t.unloads) {
 348				function unload() {
 349					var li = t.unloads, o, n;
 350
 351					if (li) {
 352						// Call unload handlers
 353						for (n in li) {
 354							o = li[n];
 355
 356							if (o && o.func)
 357								o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy
 358						}
 359
 360						// Detach unload function
 361						if (win.detachEvent) {
 362							win.detachEvent('onbeforeunload', fakeUnload);
 363							win.detachEvent('onunload', unload);
 364						} else if (win.removeEventListener)
 365							win.removeEventListener('unload', unload, false);
 366
 367						// Destroy references
 368						t.unloads = o = li = w = unload = 0;
 369
 370						// Run garbarge collector on IE
 371						if (win.CollectGarbage)
 372							CollectGarbage();
 373					}
 374				};
 375
 376				function fakeUnload() {
 377					var d = document;
 378
 379					// Is there things still loading, then do some magic
 380					if (d.readyState == 'interactive') {
 381						function stop() {
 382							// Prevent memory leak
 383							d.detachEvent('onstop', stop);
 384
 385							// Call unload handler
 386							if (unload)
 387								unload();
 388
 389							d = 0;
 390						};
 391
 392						// Fire unload when the currently loading page is stopped
 393						if (d)
 394							d.attachEvent('onstop', stop);
 395
 396						// Remove onstop listener after a while to prevent the unload function
 397						// to execute if the user presses cancel in an onbeforeunload
 398						// confirm dialog and then presses the browser stop button
 399						win.setTimeout(function() {
 400							if (d)
 401								d.detachEvent('onstop', stop);
 402						}, 0);
 403					}
 404				};
 405
 406				// Attach unload handler
 407				if (win.attachEvent) {
 408					win.attachEvent('onunload', unload);
 409					win.attachEvent('onbeforeunload', fakeUnload);
 410				} else if (win.addEventListener)
 411					win.addEventListener('unload', unload, false);
 412
 413				// Setup initial unload handler array
 414				t.unloads = [f];
 415			} else
 416				t.unloads.push(f);
 417
 418			return f;
 419		},
 420
 421		removeUnload : function(f) {
 422			var u = this.unloads, r = null;
 423
 424			tinymce.each(u, function(o, i) {
 425				if (o && o.func == f) {
 426					u.splice(i, 1);
 427					r = f;
 428					return false;
 429				}
 430			});
 431
 432			return r;
 433		},
 434
 435		explode : function(s, d) {
 436			return s ? tinymce.map(s.split(d || ','), tinymce.trim) : s;
 437		},
 438
 439		_addVer : function(u) {
 440			var v;
 441
 442			if (!this.query)
 443				return u;
 444
 445			v = (u.indexOf('?') == -1 ? '?' : '&') + this.query;
 446
 447			if (u.indexOf('#') == -1)
 448				return u + v;
 449
 450			return u.replace('#', v + '#');
 451		},
 452
 453		// Fix function for IE 9 where regexps isn't working correctly
 454		// Todo: remove me once MS fixes the bug
 455		_replace : function(find, replace, str) {
 456			// On IE9 we have to fake $x replacement
 457			if (isRegExpBroken) {
 458				return str.replace(find, function() {
 459					var val = replace, args = arguments, i;
 460
 461					for (i = 0; i < args.length - 2; i++) {
 462						if (args[i] === undefined) {
 463							val = val.replace(new RegExp('\\$' + i, 'g'), '');
 464						} else {
 465							val = val.replace(new RegExp('\\$' + i, 'g'), args[i]);
 466						}
 467					}
 468
 469					return val;
 470				});
 471			}
 472
 473			return str.replace(find, replace);
 474		}
 475
 476		};
 477
 478	// Initialize the API
 479	tinymce._init();
 480
 481	// Expose tinymce namespace to the global namespace (window)
 482	win.tinymce = win.tinyMCE = tinymce;
 483
 484	// Describe the different namespaces
 485
 486	})(window);
 487
 488
 489
 490tinymce.create('tinymce.util.Dispatcher', {
 491	scope : null,
 492	listeners : null,
 493
 494	Dispatcher : function(s) {
 495		this.scope = s || this;
 496		this.listeners = [];
 497	},
 498
 499	add : function(cb, s) {
 500		this.listeners.push({cb : cb, scope : s || this.scope});
 501
 502		return cb;
 503	},
 504
 505	addToTop : function(cb, s) {
 506		this.listeners.unshift({cb : cb, scope : s || this.scope});
 507
 508		return cb;
 509	},
 510
 511	remove : function(cb) {
 512		var l = this.listeners, o = null;
 513
 514		tinymce.each(l, function(c, i) {
 515			if (cb == c.cb) {
 516				o = cb;
 517				l.splice(i, 1);
 518				return false;
 519			}
 520		});
 521
 522		return o;
 523	},
 524
 525	dispatch : function() {
 526		var s, a = arguments, i, li = this.listeners, c;
 527
 528		// Needs to be a real loop since the listener count might change while looping
 529		// And this is also more efficient
 530		for (i = 0; i<li.length; i++) {
 531			c = li[i];
 532			s = c.cb.apply(c.scope, a);
 533
 534			if (s === false)
 535				break;
 536		}
 537
 538		return s;
 539	}
 540
 541	});
 542
 543(function() {
 544	var each = tinymce.each;
 545
 546	tinymce.create('tinymce.util.URI', {
 547		URI : function(u, s) {
 548			var t = this, o, a, b, base_url;
 549
 550			// Trim whitespace
 551			u = tinymce.trim(u);
 552
 553			// Default settings
 554			s = t.settings = s || {};
 555
 556			// Strange app protocol or local anchor
 557			if (/^(mailto|tel|news|javascript|about|data):/i.test(u) || /^\s*#/.test(u)) {
 558				t.source = u;
 559				return;
 560			}
 561
 562			// Absolute path with no host, fake host and protocol
 563			if (u.indexOf('/') === 0 && u.indexOf('//') !== 0)
 564				u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u;
 565
 566			// Relative path http:// or protocol relative //path
 567			if (!/^[\w-]*:?\/\//.test(u)) {
 568				base_url = s.base_uri ? s.base_uri.path : new tinymce.util.URI(location.href).directory;
 569				u = ((s.base_uri && s.base_uri.protocol) || 'http') + '://mce_host' + t.toAbsPath(base_url, u);
 570			}
 571
 572			// Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
 573			u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something
 574			u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);
 575			each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) {
 576				var s = u[i];
 577
 578				// Zope 3 workaround, they use @@something
 579				if (s)
 580					s = s.replace(/\(mce_at\)/g, '@@');
 581
 582				t[v] = s;
 583			});
 584
 585			if (b = s.base_uri) {
 586				if (!t.protocol)
 587					t.protocol = b.protocol;
 588
 589				if (!t.userInfo)
 590					t.userInfo = b.userInfo;
 591
 592				if (!t.port && t.host == 'mce_host')
 593					t.port = b.port;
 594
 595				if (!t.host || t.host == 'mce_host')
 596					t.host = b.host;
 597
 598				t.source = '';
 599			}
 600
 601			//t.path = t.path || '/';
 602		},
 603
 604		setPath : function(p) {
 605			var t = this;
 606
 607			p = /^(.*?)\/?(\w+)?$/.exec(p);
 608
 609			// Update path parts
 610			t.path = p[0];
 611			t.directory = p[1];
 612			t.file = p[2];
 613
 614			// Rebuild source
 615			t.source = '';
 616			t.getURI();
 617		},
 618
 619		toRelative : function(u) {
 620			var t = this, o;
 621
 622			if (u === "./")
 623				return u;
 624
 625			u = new tinymce.util.URI(u, {base_uri : t});
 626
 627			// Not on same domain/port or protocol
 628			if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol)
 629				return u.getURI();
 630
 631			o = t.toRelPath(t.path, u.path);
 632
 633			// Add query
 634			if (u.query)
 635				o += '?' + u.query;
 636
 637			// Add anchor
 638			if (u.anchor)
 639				o += '#' + u.anchor;
 640
 641			return o;
 642		},
 643	
 644		toAbsolute : function(u, nh) {
 645			var u = new tinymce.util.URI(u, {base_uri : this});
 646
 647			return u.getURI(this.host == u.host && this.protocol == u.protocol ? nh : 0);
 648		},
 649
 650		toRelPath : function(base, path) {
 651			var items, bp = 0, out = '', i, l;
 652
 653			// Split the paths
 654			base = base.substring(0, base.lastIndexOf('/'));
 655			base = base.split('/');
 656			items = path.split('/');
 657
 658			if (base.length >= items.length) {
 659				for (i = 0, l = base.length; i < l; i++) {
 660					if (i >= items.length || base[i] != items[i]) {
 661						bp = i + 1;
 662						break;
 663					}
 664				}
 665			}
 666
 667			if (base.length < items.length) {
 668				for (i = 0, l = items.length; i < l; i++) {
 669					if (i >= base.length || base[i] != items[i]) {
 670						bp = i + 1;
 671						break;
 672					}
 673				}
 674			}
 675
 676			if (bp == 1)
 677				return path;
 678
 679			for (i = 0, l = base.length - (bp - 1); i < l; i++)
 680				out += "../";
 681
 682			for (i = bp - 1, l = items.length; i < l; i++) {
 683				if (i != bp - 1)
 684					out += "/" + items[i];
 685				else
 686					out += items[i];
 687			}
 688
 689			return out;
 690		},
 691
 692		toAbsPath : function(base, path) {
 693			var i, nb = 0, o = [], tr, outPath;
 694
 695			// Split paths
 696			tr = /\/$/.test(path) ? '/' : '';
 697			base = base.split('/');
 698			path = path.split('/');
 699
 700			// Remove empty chunks
 701			each(base, function(k) {
 702				if (k)
 703					o.push(k);
 704			});
 705
 706			base = o;
 707
 708			// Merge relURLParts chunks
 709			for (i = path.length - 1, o = []; i >= 0; i--) {
 710				// Ignore empty or .
 711				if (path[i].length == 0 || path[i] == ".")
 712					continue;
 713
 714				// Is parent
 715				if (path[i] == '..') {
 716					nb++;
 717					continue;
 718				}
 719
 720				// Move up
 721				if (nb > 0) {
 722					nb--;
 723					continue;
 724				}
 725
 726				o.push(path[i]);
 727			}
 728
 729			i = base.length - nb;
 730
 731			// If /a/b/c or /
 732			if (i <= 0)
 733				outPath = o.reverse().join('/');
 734			else
 735				outPath = base.slice(0, i).join('/') + '/' + o.reverse().join('/');
 736
 737			// Add front / if it's needed
 738			if (outPath.indexOf('/') !== 0)
 739				outPath = '/' + outPath;
 740
 741			// Add traling / if it's needed
 742			if (tr && outPath.lastIndexOf('/') !== outPath.length - 1)
 743				outPath += tr;
 744
 745			return outPath;
 746		},
 747
 748		getURI : function(nh) {
 749			var s, t = this;
 750
 751			// Rebuild source
 752			if (!t.source || nh) {
 753				s = '';
 754
 755				if (!nh) {
 756					if (t.protocol)
 757						s += t.protocol + '://';
 758
 759					if (t.userInfo)
 760						s += t.userInfo + '@';
 761
 762					if (t.host)
 763						s += t.host;
 764
 765					if (t.port)
 766						s += ':' + t.port;
 767				}
 768
 769				if (t.path)
 770					s += t.path;
 771
 772				if (t.query)
 773					s += '?' + t.query;
 774
 775				if (t.anchor)
 776					s += '#' + t.anchor;
 777
 778				t.source = s;
 779			}
 780
 781			return t.source;
 782		}
 783	});
 784})();
 785
 786(function() {
 787	var each = tinymce.each;
 788
 789	tinymce.create('static tinymce.util.Cookie', {
 790		getHash : function(n) {
 791			var v = this.get(n), h;
 792
 793			if (v) {
 794				each(v.split('&'), function(v) {
 795					v = v.split('=');
 796					h = h || {};
 797					h[unescape(v[0])] = unescape(v[1]);
 798				});
 799			}
 800
 801			return h;
 802		},
 803
 804		setHash : function(n, v, e, p, d, s) {
 805			var o = '';
 806
 807			each(v, function(v, k) {
 808				o += (!o ? '' : '&') + escape(k) + '=' + escape(v);
 809			});
 810
 811			this.set(n, o, e, p, d, s);
 812		},
 813
 814		get : function(n) {
 815			var c = document.cookie, e, p = n + "=", b;
 816
 817			// Strict mode
 818			if (!c)
 819				return;
 820
 821			b = c.indexOf("; " + p);
 822
 823			if (b == -1) {
 824				b = c.indexOf(p);
 825
 826				if (b != 0)
 827					return null;
 828			} else
 829				b += 2;
 830
 831			e = c.indexOf(";", b);
 832
 833			if (e == -1)
 834				e = c.length;
 835
 836			return unescape(c.substring(b + p.length, e));
 837		},
 838
 839		set : function(n, v, e, p, d, s) {
 840			document.cookie = n + "=" + escape(v) +
 841				((e) ? "; expires=" + e.toGMTString() : "") +
 842				((p) ? "; path=" + escape(p) : "") +
 843				((d) ? "; domain=" + d : "") +
 844				((s) ? "; secure" : "");
 845		},
 846
 847		remove : function(n, p) {
 848			var d = new Date();
 849
 850			d.setTime(d.getTime() - 1000);
 851
 852			this.set(n, '', d, p, d);
 853		}
 854	});
 855})();
 856
 857(function() {
 858	function serialize(o, quote) {
 859		var i, v, t;
 860
 861		quote = quote || '"';
 862
 863		if (o == null)
 864			return 'null';
 865
 866		t = typeof o;
 867
 868		if (t == 'string') {
 869			v = '\bb\tt\nn\ff\rr\""\'\'\\\\';
 870
 871			return quote + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g, function(a, b) {
 872				// Make sure single quotes never get encoded inside double quotes for JSON compatibility
 873				if (quote === '"' && a === "'")
 874					return a;
 875
 876				i = v.indexOf(b);
 877
 878				if (i + 1)
 879					return '\\' + v.charAt(i + 1);
 880
 881				a = b.charCodeAt().toString(16);
 882
 883				return '\\u' + '0000'.substring(a.length) + a;
 884			}) + quote;
 885		}
 886
 887		if (t == 'object') {
 888			if (o.hasOwnProperty && o instanceof Array) {
 889					for (i=0, v = '['; i<o.length; i++)
 890						v += (i > 0 ? ',' : '') + serialize(o[i], quote);
 891
 892					return v + ']';
 893				}
 894
 895				v = '{';
 896
 897				for (i in o)
 898					v += typeof o[i] != 'function' ? (v.length > 1 ? ',' + quote : quote) + i + quote +':' + serialize(o[i], quote) : '';
 899
 900				return v + '}';
 901		}
 902
 903		return '' + o;
 904	};
 905
 906	tinymce.util.JSON = {
 907		serialize: serialize,
 908
 909		parse: function(s) {
 910			try {
 911				return eval('(' + s + ')');
 912			} catch (ex) {
 913				// Ignore
 914			}
 915		}
 916
 917		};
 918})();
 919tinymce.create('static tinymce.util.XHR', {
 920	send : function(o) {
 921		var x, t, w = window, c = 0;
 922
 923		// Default settings
 924		o.scope = o.scope || this;
 925		o.success_scope = o.success_scope || o.scope;
 926		o.error_scope = o.error_scope || o.scope;
 927		o.async = o.async === false ? false : true;
 928		o.data = o.data || '';
 929
 930		function get(s) {
 931			x = 0;
 932
 933			try {
 934				x = new ActiveXObject(s);
 935			} catch (ex) {
 936			}
 937
 938			return x;
 939		};
 940
 941		x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP');
 942
 943		if (x) {
 944			if (x.overrideMimeType)
 945				x.overrideMimeType(o.content_type);
 946
 947			x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async);
 948
 949			if (o.content_type)
 950				x.setRequestHeader('Content-Type', o.content_type);
 951
 952			x.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
 953
 954			x.send(o.data);
 955
 956			function ready() {
 957				if (!o.async || x.readyState == 4 || c++ > 10000) {
 958					if (o.success && c < 10000 && x.status == 200)
 959						o.success.call(o.success_scope, '' + x.responseText, x, o);
 960					else if (o.error)
 961						o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);
 962
 963					x = null;
 964				} else
 965					w.setTimeout(ready, 10);
 966			};
 967
 968			// Syncronous request
 969			if (!o.async)
 970				return ready();
 971
 972			// Wait for response, onReadyStateChange can not be used since it leaks memory in IE
 973			t = w.setTimeout(ready, 10);
 974		}
 975	}
 976});
 977
 978(function() {
 979	var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR;
 980
 981	tinymce.create('tinymce.util.JSONRequest', {
 982		JSONRequest : function(s) {
 983			this.settings = extend({
 984			}, s);
 985			this.count = 0;
 986		},
 987
 988		send : function(o) {
 989			var ecb = o.error, scb = o.success;
 990
 991			o = extend(this.settings, o);
 992
 993			o.success = function(c, x) {
 994				c = JSON.parse(c);
 995
 996				if (typeof(c) == 'undefined') {
 997					c = {
 998						error : 'JSON Parse error.'
 999					};
1000				}
1001
1002				if (c.error)
1003					ecb.call(o.error_scope || o.scope, c.error, x);
1004				else
1005					scb.call(o.success_scope || o.scope, c.result);
1006			};
1007
1008			o.error = function(ty, x) {
1009				if (ecb)
1010					ecb.call(o.error_scope || o.scope, ty, x);
1011			};
1012
1013			o.data = JSON.serialize({
1014				id : o.id || 'c' + (this.count++),
1015				method : o.method,
1016				params : o.params
1017			});
1018
1019			// JSON content type for Ruby on rails. Bug: #1883287
1020			o.content_type = 'application/json';
1021
1022			XHR.send(o);
1023		},
1024
1025		'static' : {
1026			sendRPC : function(o) {
1027				return new tinymce.util.JSONRequest().send(o);
1028			}
1029		}
1030	});
1031}());
1032(function(tinymce) {
1033	var namedEntities, baseEntities, reverseEntities,
1034		attrsCharsRegExp = /[&<>\"\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
1035		textCharsRegExp = /[<>&\u007E-\uD7FF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
1036		rawCharsRegExp = /[<>&\"\']/g,
1037		entityRegExp = /&(#x|#)?([\w]+);/g,
1038		asciiMap = {
1039				128 : "\u20AC", 130 : "\u201A", 131 : "\u0192", 132 : "\u201E", 133 : "\u2026", 134 : "\u2020",
1040				135 : "\u2021", 136 : "\u02C6", 137 : "\u2030", 138 : "\u0160", 139 : "\u2039", 140 : "\u0152",
1041				142 : "\u017D", 145 : "\u2018", 146 : "\u2019", 147 : "\u201C", 148 : "\u201D", 149 : "\u2022",
1042				150 : "\u2013", 151 : "\u2014", 152 : "\u02DC", 153 : "\u2122", 154 : "\u0161", 155 : "\u203A",
1043				156 : "\u0153", 158 : "\u017E", 159 : "\u0178"
1044		};
1045
1046	// Raw entities
1047	baseEntities = {
1048		'"' : '&quot;',
1049		"'" : '&#39;',
1050		'<' : '&lt;',
1051		'>' : '&gt;',
1052		'&' : '&amp;'
1053	};
1054
1055	// Reverse lookup table for raw entities
1056	reverseEntities = {
1057		'&lt;' : '<',
1058		'&gt;' : '>',
1059		'&amp;' : '&',
1060		'&quot;' : '"',
1061		'&apos;' : "'"
1062	};
1063
1064	// Decodes text by using the browser
1065	function nativeDecode(text) {
1066		var elm;
1067
1068		elm = document.createElement("div");
1069		elm.innerHTML = text;
1070
1071		return elm.textContent || elm.innerText || text;
1072	};
1073
1074	// Build a two way lookup table for the entities
1075	function buildEntitiesLookup(items, radix) {
1076		var i, chr, entity, lookup = {};
1077
1078		if (items) {
1079			items = items.split(',');
1080			radix = radix || 10;
1081
1082			// Build entities lookup table
1083			for (i = 0; i < items.length; i += 2) {
1084				chr = String.fromCharCode(parseInt(items[i], radix));
1085
1086				// Only add non base entities
1087				if (!baseEntities[chr]) {
1088					entity = '&' + items[i + 1] + ';';
1089					lookup[chr] = entity;
1090					lookup[entity] = chr;
1091				}
1092			}
1093
1094			return lookup;
1095		}
1096	};
1097
1098	// Unpack entities lookup where the numbers are in radix 32 to reduce the size
1099	namedEntities = buildEntitiesLookup(
1100		'50,nbsp,51,iexcl,52,cent,53,pound,54,curren,55,yen,56,brvbar,57,sect,58,uml,59,copy,' +
1101		'5a,ordf,5b,laquo,5c,not,5d,shy,5e,reg,5f,macr,5g,deg,5h,plusmn,5i,sup2,5j,sup3,5k,acute,' +
1102		'5l,micro,5m,para,5n,middot,5o,cedil,5p,sup1,5q,ordm,5r,raquo,5s,frac14,5t,frac12,5u,frac34,' +
1103		'5v,iquest,60,Agrave,61,Aacute,62,Acirc,63,Atilde,64,Auml,65,Aring,66,AElig,67,Ccedil,' +
1104		'68,Egrave,69,Eacute,6a,Ecirc,6b,Euml,6c,Igrave,6d,Iacute,6e,Icirc,6f,Iuml,6g,ETH,6h,Ntilde,' +
1105		'6i,Ograve,6j,Oacute,6k,Ocirc,6l,Otilde,6m,Ouml,6n,times,6o,Oslash,6p,Ugrave,6q,Uacute,' +
1106		'6r,Ucirc,6s,Uuml,6t,Yacute,6u,THORN,6v,szlig,70,agrave,71,aacute,72,acirc,73,atilde,74,auml,' +
1107		'75,aring,76,aelig,77,ccedil,78,egrave,79,eacute,7a,ecirc,7b,euml,7c,igrave,7d,iacute,7e,icirc,' +
1108		'7f,iuml,7g,eth,7h,ntilde,7i,ograve,7j,oacute,7k,ocirc,7l,otilde,7m,ouml,7n,divide,7o,oslash,' +
1109		'7p,ugrave,7q,uacute,7r,ucirc,7s,uuml,7t,yacute,7u,thorn,7v,yuml,ci,fnof,sh,Alpha,si,Beta,' +
1110		'sj,Gamma,sk,Delta,sl,Epsilon,sm,Zeta,sn,Eta,so,Theta,sp,Iota,sq,Kappa,sr,Lambda,ss,Mu,' +
1111		'st,Nu,su,Xi,sv,Omicron,t0,Pi,t1,Rho,t3,Sigma,t4,Tau,t5,Upsilon,t6,Phi,t7,Chi,t8,Psi,' +
1112		't9,Omega,th,alpha,ti,beta,tj,gamma,tk,delta,tl,epsilon,tm,zeta,tn,eta,to,theta,tp,iota,' +
1113		'tq,kappa,tr,lambda,ts,mu,tt,nu,tu,xi,tv,omicron,u0,pi,u1,rho,u2,sigmaf,u3,sigma,u4,tau,' +
1114		'u5,upsilon,u6,phi,u7,chi,u8,psi,u9,omega,uh,thetasym,ui,upsih,um,piv,812,bull,816,hellip,' +
1115		'81i,prime,81j,Prime,81u,oline,824,frasl,88o,weierp,88h,image,88s,real,892,trade,89l,alefsym,' +
1116		'8cg,larr,8ch,uarr,8ci,rarr,8cj,darr,8ck,harr,8dl,crarr,8eg,lArr,8eh,uArr,8ei,rArr,8ej,dArr,' +
1117		'8ek,hArr,8g0,forall,8g2,part,8g3,exist,8g5,empty,8g7,nabla,8g8,isin,8g9,notin,8gb,ni,8gf,prod,' +
1118		'8gh,sum,8gi,minus,8gn,lowast,8gq,radic,8gt,prop,8gu,infin,8h0,ang,8h7,and,8h8,or,8h9,cap,8ha,cup,' +
1119		'8hb,int,8hk,there4,8hs,sim,8i5,cong,8i8,asymp,8j0,ne,8j1,equiv,8j4,le,8j5,ge,8k2,sub,8k3,sup,8k4,' +
1120		'nsub,8k6,sube,8k7,supe,8kl,oplus,8kn,otimes,8l5,perp,8m5,sdot,8o8,lceil,8o9,rceil,8oa,lfloor,8ob,' +
1121		'rfloor,8p9,lang,8pa,rang,9ea,loz,9j0,spades,9j3,clubs,9j5,hearts,9j6,diams,ai,OElig,aj,oelig,b0,' +
1122		'Scaron,b1,scaron,bo,Yuml,m6,circ,ms,tilde,802,ensp,803,emsp,809,thinsp,80c,zwnj,80d,zwj,80e,lrm,' +
1123		'80f,rlm,80j,ndash,80k,mdash,80o,lsquo,80p,rsquo,80q,sbquo,80s,ldquo,80t,rdquo,80u,bdquo,810,dagger,' +
1124		'811,Dagger,81g,permil,81p,lsaquo,81q,rsaquo,85c,euro'
1125	, 32);
1126
1127	tinymce.html = tinymce.html || {};
1128
1129	tinymce.html.Entities = {
1130		encodeRaw : function(text, attr) {
1131			return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
1132				return baseEntities[chr] || chr;
1133			});
1134		},
1135
1136		encodeAllRaw : function(text) {
1137			return ('' + text).replace(rawCharsRegExp, function(chr) {
1138				return baseEntities[chr] || chr;
1139			});
1140		},
1141
1142		encodeNumeric : function(text, attr) {
1143			return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
1144				// Multi byte sequence convert it to a single entity
1145				if (chr.length > 1)
1146					return '&#' + (((chr.charCodeAt(0) - 0xD800) * 0x400) + (chr.charCodeAt(1) - 0xDC00) + 0x10000) + ';';
1147
1148				return baseEntities[chr] || '&#' + chr.charCodeAt(0) + ';';
1149			});
1150		},
1151
1152		encodeNamed : function(text, attr, entities) {
1153			entities = entities || namedEntities;
1154
1155			return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
1156				return baseEntities[chr] || entities[chr] || chr;
1157			});
1158		},
1159
1160		getEncodeFunc : function(name, entities) {
1161			var Entities = tinymce.html.Entities;
1162
1163			entities = buildEntitiesLookup(entities) || namedEntities;
1164
1165			function encodeNamedAndNumeric(text, attr) {
1166				return text.replace(attr ? attrsCharsRegExp : textCharsRegExp, function(chr) {
1167					return baseEntities[chr] || entities[chr] || '&#' + chr.charCodeAt(0) + ';' || chr;
1168				});
1169			};
1170
1171			function encodeCustomNamed(text, attr) {
1172				return Entities.encodeNamed(text, attr, entities);
1173			};
1174
1175			// Replace + with , to be compatible with previous TinyMCE versions
1176			name = tinymce.makeMap(name.replace(/\+/g, ','));
1177
1178			// Named and numeric encoder
1179			if (name.named && name.numeric)
1180				return encodeNamedAndNumeric;
1181
1182			// Named encoder
1183			if (name.named) {
1184				// Custom names
1185				if (entities)
1186					return encodeCustomNamed;
1187
1188				return Entities.encodeNamed;
1189			}
1190
1191			// Numeric
1192			if (name.numeric)
1193				return Entities.encodeNumeric;
1194
1195			// Raw encoder
1196			return Entities.encodeRaw;
1197		},
1198
1199		decode : function(text) {
1200			return text.replace(entityRegExp, function(all, numeric, value) {
1201				if (numeric) {
1202					value = parseInt(value, numeric.length === 2 ? 16 : 10);
1203
1204					// Support upper UTF
1205					if (value > 0xFFFF) {
1206						value -= 0x10000;
1207
1208						return String.fromCharCode(0xD800 + (value >> 10), 0xDC00 + (value & 0x3FF));
1209					} else
1210						return asciiMap[value] || String.fromCharCode(value);
1211				}
1212
1213				return reverseEntities[all] || namedEntities[all] || nativeDecode(all);
1214			});
1215		}
1216	};
1217})(tinymce);
1218
1219tinymce.html.Styles = function(settings, schema) {
1220	var rgbRegExp = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/gi,
1221		urlOrStrRegExp = /(?:url(?:(?:\(\s*\"([^\"]+)\"\s*\))|(?:\(\s*\'([^\']+)\'\s*\))|(?:\(\s*([^)\s]+)\s*\))))|(?:\'([^\']+)\')|(?:\"([^\"]+)\")/gi,
1222		styleRegExp = /\s*([^:]+):\s*([^;]+);?/g,
1223		trimRightRegExp = /\s+$/,
1224		urlColorRegExp = /rgb/,
1225		undef, i, encodingLookup = {}, encodingItems;
1226
1227	settings = settings || {};
1228
1229	encodingItems = '\\" \\\' \\; \\: ; : \uFEFF'.split(' ');
1230	for (i = 0; i < encodingItems.length; i++) {
1231		encodingLookup[encodingItems[i]] = '\uFEFF' + i;
1232		encodingLookup['\uFEFF' + i] = encodingItems[i];
1233	}
1234
1235	function toHex(match, r, g, b) {
1236		function hex(val) {
1237			val = parseInt(val).toString(16);
1238
1239			return val.length > 1 ? val : '0' + val; // 0 -> 00
1240		};
1241
1242		return '#' + hex(r) + hex(g) + hex(b);
1243	};
1244
1245	return {
1246		toHex : function(color) {
1247			return color.replace(rgbRegExp, toHex);
1248		},
1249
1250		parse : function(css) {
1251			var styles = {}, matches, name, value, isEncoded, urlConverter = settings.url_converter, urlConverterScope = settings.url_converter_scope || this;
1252
1253			function compress(prefix, suffix) {
1254				var top, right, bottom, left;
1255
1256				// Get values and check it it needs compressing
1257				top = styles[prefix + '-top' + suffix];
1258				if (!top)
1259					return;
1260
1261				right = styles[prefix + '-right' + suffix];
1262				if (top != right)
1263					return;
1264
1265				bottom = styles[prefix + '-bottom' + suffix];
1266				if (right != bottom)
1267					return;
1268
1269				left = styles[prefix + '-left' + suffix];
1270				if (bottom != left)
1271					return;
1272
1273				// Compress
1274				styles[prefix + suffix] = left;
1275				delete styles[prefix + '-top' + suffix];
1276				delete styles[prefix + '-right' + suffix];
1277				delete styles[prefix + '-bottom' + suffix];
1278				delete styles[prefix + '-left' + suffix];
1279			};
1280
1281			function canCompress(key) {
1282				var value = styles[key], i;
1283
1284				if (!value || value.indexOf(' ') < 0)
1285					return;
1286
1287				value = value.split(' ');
1288				i = value.length;
1289				while (i--) {
1290					if (value[i] !== value[0])
1291						return false;
1292				}
1293
1294				styles[key] = value[0];
1295
1296				return true;
1297			};
1298
1299			function compress2(target, a, b, c) {
1300				if (!canCompress(a))
1301					return;
1302
1303				if (!canCompress(b))
1304					return;
1305
1306				if (!canCompress(c))
1307					return;
1308
1309				// Compress
1310				styles[target] = styles[a] + ' ' + styles[b] + ' ' + styles[c];
1311				delete styles[a];
1312				delete styles[b];
1313				delete styles[c];
1314			};
1315
1316			// Encodes the specified string by replacing all \" \' ; : with _<num>
1317			function encode(str) {
1318				isEncoded = true;
1319
1320				return encodingLookup[str];
1321			};
1322
1323			// Decodes the specified string by replacing all _<num> with it's original value \" \' etc
1324			// It will also decode the \" \' if keep_slashes is set to fale or omitted
1325			function decode(str, keep_slashes) {
1326				if (isEncoded) {
1327					str = str.replace(/\uFEFF[0-9]/g, function(str) {
1328						return encodingLookup[str];
1329					});
1330				}
1331
1332				if (!keep_slashes)
1333					str = str.replace(/\\([\'\";:])/g, "$1");
1334
1335				return str;
1336			}
1337
1338			if (css) {
1339				// Encode \" \' % and ; and : inside strings so they don't interfere with the style parsing
1340				css = css.replace(/\\[\"\';:\uFEFF]/g, encode).replace(/\"[^\"]+\"|\'[^\']+\'/g, function(str) {
1341					return str.replace(/[;:]/g, encode);
1342				});
1343
1344				// Parse styles
1345				while (matches = styleRegExp.exec(css)) {
1346					name = matches[1].replace(trimRightRegExp, '').toLowerCase();
1347					value = matches[2].replace(trimRightRegExp, '');
1348
1349					if (name && value.length > 0) {
1350						// Opera will produce 700 instead of bold in their style values
1351						if (name === 'font-weight' && value === '700')
1352							value = 'bold';
1353						else if (name === 'color' || name === 'background-color') // Lowercase colors like RED
1354							value = value.toLowerCase();		
1355
1356						// Convert RGB colors to HEX
1357						value = value.replace(rgbRegExp, toHex);
1358
1359						// Convert URLs and force them into url('value') format
1360						value = value.replace(urlOrStrRegExp, function(match, url, url2, url3, str, str2) {
1361							str = str || str2;
1362
1363							if (str) {
1364								str = decode(str);
1365
1366								// Force strings into single quote format
1367								return "'" + str.replace(/\'/g, "\\'") + "'";
1368							}
1369
1370							url = decode(url || url2 || url3);
1371
1372							// Convert the URL to relative/absolute depending on config
1373							if (urlConverter)
1374								url = urlConverter.call(urlConverterScope, url, 'style');
1375
1376							// Output new URL format
1377							return "url('" + url.replace(/\'/g, "\\'") + "')";
1378						});
1379
1380						styles[name] = isEncoded ? decode(value, true) : value;
1381					}
1382
1383					styleRegExp.lastIndex = matches.index + matches[0].length;
1384				}
1385
1386				// Compress the styles to reduce it's size for example IE will expand styles
1387				compress("border", "");
1388				compress("border", "-width");
1389				compress("border", "-color");
1390				compress("border", "-style");
1391				compress("padding", "");
1392				compress("margin", "");
1393				compress2('border', 'border-width', 'border-style', 'border-color');
1394
1395				// Remove pointless border, IE produces these
1396				if (styles.border === 'medium none')
1397					delete styles.border;
1398			}
1399
1400			return styles;
1401		},
1402
1403		serialize : function(styles, element_name) {
1404			var css = '', name, value;
1405
1406			function serializeStyles(name) {
1407				var styleList, i, l, value;
1408
1409				styleList = schema.styles[name];
1410				if (styleList) {
1411					for (i = 0, l = styleList.length; i < l; i++) {
1412						name = styleList[i];
1413						value = styles[name];
1414
1415						if (value !== undef && value.length > 0)
1416							css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
1417					}
1418				}
1419			};
1420
1421			// Serialize styles according to schema
1422			if (element_name && schema && schema.styles) {
1423				// Serialize global styles and element specific styles
1424				serializeStyles('*');
1425				serializeStyles(element_name);
1426			} else {
1427				// Output the styles in the order they are inside the object
1428				for (name in styles) {
1429					value = styles[name];
1430
1431					if (value !== undef && value.length > 0)
1432						css += (css.length > 0 ? ' ' : '') + name + ': ' + value + ';';
1433				}
1434			}
1435
1436			return css;
1437		}
1438	};
1439};
1440
1441(function(tinymce) {
1442	var transitional = {}, boolAttrMap, blockElementsMap, shortEndedElementsMap, nonEmptyElementsMap, customElementsMap = {},
1443		whiteSpaceElementsMap, selfClosingElementsMap, makeMap = tinymce.makeMap, each = tinymce.each;
1444
1445	function split(str, delim) {
1446		return str.split(delim || ',');
1447	};
1448
1449	function unpack(lookup, data) {
1450		var key, elements = {};
1451
1452		function replace(value) {
1453			return value.replace(/[A-Z]+/g, function(key) {
1454				return replace(lookup[key]);
1455			});
1456		};
1457
1458		// Unpack lookup
1459		for (key in lookup) {
1460			if (lookup.hasOwnProperty(key))
1461				lookup[key] = replace(lookup[key]);
1462		}
1463
1464		// Unpack and parse data into object map
1465		replace(data).replace(/#/g, '#text').replace(/(\w+)\[([^\]]+)\]\[([^\]]*)\]/g, function(str, name, attributes, children) {
1466			attributes = split(attributes, '|');
1467
1468			elements[name] = {
1469				attributes : makeMap(attributes),
1470				attributesOrder : attributes,
1471				children : makeMap(children, '|', {'#comment' : {}})
1472			}
1473		});
1474
1475		return elements;
1476	};
1477
1478	// Build a lookup table for block elements both lowercase and uppercase
1479	blockElementsMap = 'h1,h2,h3,h4,h5,h6,hr,p,div,address,pre,form,table,tbody,thead,tfoot,' + 
1480						'th,tr,td,li,ol,ul,caption,blockquote,center,dl,dt,dd,dir,fieldset,' + 
1481						'noscript,menu,isindex,samp,header,footer,article,section,hgroup';
1482	blockElementsMap = makeMap(blockElementsMap, ',', makeMap(blockElementsMap.toUpperCase()));
1483
1484	// This is the XHTML 1.0 transitional elements with it's attributes and children packed to reduce it's size
1485	transitional = unpack({
1486		Z : 'H|K|N|O|P',
1487		Y : 'X|form|R|Q',
1488		ZG : 'E|span|width|align|char|charoff|valign',
1489		X : 'p|T|div|U|W|isindex|fieldset|table',
1490		ZF : 'E|align|char|charoff|valign',
1491		W : 'pre|hr|blockquote|address|center|noframes',
1492		ZE : 'abbr|axis|headers|scope|rowspan|colspan|align|char|charoff|valign|nowrap|bgcolor|width|height',
1493		ZD : '[E][S]',
1494		U : 'ul|ol|dl|menu|dir',
1495		ZC : 'p|Y|div|U|W|table|br|span|bdo|object|applet|img|map|K|N|Q',
1496		T : 'h1|h2|h3|h4|h5|h6',
1497		ZB : 'X|S|Q',
1498		S : 'R|P',
1499		ZA : 'a|G|J|M|O|P',
1500		R : 'a|H|K|N|O',
1501		Q : 'noscript|P',
1502		P : 'ins|del|script',
1503		O : 'input|select|textarea|label|button',
1504		N : 'M|L',
1505		M : 'em|strong|dfn|code|q|samp|kbd|var|cite|abbr|acronym',
1506		L : 'sub|sup',
1507		K : 'J|I',
1508		J : 'tt|i|b|u|s|strike',
1509		I : 'big|small|font|basefont',
1510		H : 'G|F',
1511		G : 'br|span|bdo',
1512		F : 'object|applet|img|map|iframe',
1513		E : 'A|B|C',
1514		D : 'accesskey|tabindex|onfocus|onblur',
1515		C : 'onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup',
1516		B : 'lang|xml:lang|dir',
1517		A : 'id|class|style|title'
1518	}, 'script[id|charset|type|language|src|defer|xml:space][]' + 
1519		'style[B|id|type|media|title|xml:space][]' + 
1520		'object[E|declare|classid|codebase|data|type|codetype|archive|standby|width|height|usemap|name|tabindex|align|border|hspace|vspace][#|param|Y]' + 
1521		'param[id|name|value|valuetype|type][]' + 
1522		'p[E|align][#|S]' + 
1523		'a[E|D|charset|type|name|href|hreflang|rel|rev|shape|coords|target][#|Z]' + 
1524		'br[A|clear][]' + 
1525		'span[E][#|S]' + 
1526		'bdo[A|C|B][#|S]' + 
1527		'applet[A|codebase|archive|code|object|alt|name|width|height|align|hspace|vspace][#|param|Y]' + 
1528		'h1[E|align][#|S]' + 
1529		'img[E|src|alt|name|longdesc|width|height|usemap|ismap|align|border|hspace|vspace][]' + 
1530		'map[B|C|A|name][X|form|Q|area]' + 
1531		'h2[E|align][#|S]' + 
1532		'iframe[A|longdesc|name|src|frameborder|marginwidth|marginheight|scrolling|align|width|height][#|Y]' + 
1533		'h3[E|align][#|S]' + 
1534		'tt[E][#|S]' + 
1535		'i[E][#|S]' + 
1536		'b[E][#|S]' + 
1537		'u[E][#|S]' + 
1538		's[E][#|S]' + 
1539		'strike[E][#|S]' + 
1540		'big[E][#|S]' + 
1541		'small[E][#|S]' + 
1542		'font[A|B|size|color|face][#|S]' + 
1543		'basefont[id|size|color|face][]' + 
1544		'em[E][#|S]' + 
1545		'strong[E][#|S]' + 
1546		'dfn[E][#|S]' + 
1547		'code[E][#|S]' + 
1548		'q[E|cite][#|S]' + 
1549		'samp[E][#|S]' + 
1550		'kbd[E][#|S]' + 
1551		'var[E][#|S]' + 
1552		'cite[E][#|S]' + 
1553		'abbr[E][#|S]' + 
1554		'acronym[E][#|S]' + 
1555		'sub[E][#|S]' + 
1556		'sup[E][#|S]' + 
1557		'input[E|D|type|name|value|checked|disabled|readonly|size|maxlength|src|alt|usemap|onselect|onchange|accept|align][]' + 
1558		'select[E|name|size|multiple|disabled|tabindex|onfocus|onblur|onchange][optgroup|option]' + 
1559		'optgroup[E|disabled|label][option]' + 
1560		'option[E|selected|disabled|label|value][]' + 
1561		'textarea[E|D|name|rows|cols|disabled|readonly|onselect|onchange][]' + 
1562		'label[E|for|accesskey|onfocus|onblur][#|S]' + 
1563		'button[E|D|name|value|type|disabled][#|p|T|div|U|W|table|G|object|applet|img|map|K|N|Q]' + 
1564		'h4[E|align][#|S]' + 
1565		'ins[E|cite|datetime][#|Y]' + 
1566		'h5[E|align][#|S]' + 
1567		'del[E|cite|datetime][#|Y]' + 
1568		'h6[E|align][#|S]' + 
1569		'div[E|align][#|Y]' + 
1570		'ul[E|type|compact][li]' + 
1571		'li[E|type|value][#|Y]' + 
1572		'ol[E|type|compact|start][li]' + 
1573		'dl[E|compact][dt|dd]' + 
1574		'dt[E][#|S]' + 
1575		'dd[E][#|Y]' + 
1576		'menu[E|compact][li]' + 
1577		'dir[E|compact][li]' + 
1578		'pre[E|width|xml:space][#|ZA]' + 
1579		'hr[E|align|noshade|size|width][]' + 
1580		'blockquote[E|cite][#|Y]' + 
1581		'address[E][#|S|p]' + 
1582		'center[E][#|Y]' + 
1583		'noframes[E][#|Y]' + 
1584		'isindex[A|B|prompt][]' + 
1585		'fieldset[E][#|legend|Y]' + 
1586		'legend[E|accesskey|align][#|S]' + 
1587		'table[E|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor][caption|col|colgroup|thead|tfoot|tbody|tr]' + 
1588		'caption[E|align][#|S]' + 
1589		'col[ZG][]' + 
1590		'colgroup[ZG][col]' + 
1591		'thead[ZF][tr]' + 
1592		'tr[ZF|bgcolor][th|td]' + 
1593		'th[E|ZE][#|Y]' + 
1594		'form[E|action|method|name|enctype|onsubmit|onreset|accept|accept-charset|target][#|X|R|Q]' + 
1595		'noscript[E][#|Y]' + 
1596		'td[E|ZE][#|Y]' + 
1597		'tfoot[ZF][tr]' + 
1598		'tbody[ZF][tr]' + 
1599		'area[E|D|shape|coords|href|nohref|alt|target][]' + 
1600		'base[id|href|target][]' + 
1601		'body[E|onload|onunload|background|bgcolor|text|link|vlink|alink][#|Y]'
1602	);
1603
1604	boolAttrMap = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected,preload,autoplay,loop,controls');
1605	shortEndedElementsMap = makeMap('area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed,source');
1606	nonEmptyElementsMap = tinymce.extend(makeMap('td,th,iframe,video,object'), shortEndedElementsMap);
1607	whiteSpaceElementsMap = makeMap('pre,script,style');
1608	selfClosingElementsMap = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
1609
1610	tinymce.html.Schema = function(settings) {
1611		var self = this, elements = {}, children = {}, patternElements = [], validStyles;
1612
1613		settings = settings || {};
1614
1615		// Allow all elements and attributes if verify_html is set to false
1616		if (settings.verify_html === false)
1617			settings.valid_elements = '*[*]';
1618
1619		// Build styles list
1620		if (settings.valid_styles) {
1621			validStyles = {};
1622
1623			// Convert styles into a rule list
1624			each(settings.valid_styles, function(value, key) {
1625				validStyles[key] = tinymce.explode(value);
1626			});
1627		}
1628
1629		// Converts a wildcard expression string to a regexp for example *a will become /.*a/.
1630		function patternToRegExp(str) {
1631			return new RegExp('^' + str.replace(/([?+*])/g, '.$1') + '$');
1632		};
1633
1634		// Parses the specified valid_elements string and adds to the current rules
1635		// This function is a bit hard to read since it's heavily optimized for speed
1636		function addValidElements(valid_elements) {
1637			var ei, el, ai, al, yl, matches, element, attr, attrData, elementName, attrName, attrType, attributes, attributesOrder,
1638				prefix, outputName, globalAttributes, globalAttributesOrder, transElement, key, childKey, value,
1639				elementRuleRegExp = /^([#+-])?([^\[\/]+)(?:\/([^\[]+))?(?:\[([^\]]+)\])?$/,
1640				attrRuleRegExp = /^([!\-])?(\w+::\w+|[^=:<]+)?(?:([=:<])(.*))?$/,
1641				hasPatternsRegExp = /[*?+]/;
1642
1643			if (valid_elements) {
1644				// Split valid elements into an array with rules
1645				valid_elements = split(valid_elements);
1646
1647				if (elements['@']) {
1648					globalAttributes = elements['@'].attributes;
1649					globalAttributesOrder = elements['@'].attributesOrder;
1650				}
1651
1652				// Loop all rules
1653				for (ei = 0, el = valid_elements.length; ei < el; ei++) {
1654					// Parse element rule
1655					matches = elementRuleRegExp.exec(valid_elements[ei]);
1656					if (matches) {
1657						// Setup local names for matches
1658						prefix = matches[1];
1659						elementName = matches[2];
1660						outputName = matches[3];
1661						attrData = matches[4];
1662
1663						// Create new attributes and attributesOrder
1664						attributes = {};
1665						attributesOrder = [];
1666
1667						// Create the new element
1668						element = {
1669							attributes : attributes,
1670							attributesOrder : attributesOrder
1671						};
1672
1673						// Padd empty elements prefix
1674						if (prefix === '#')
1675							element.paddEmpty = true;
1676
1677						// Remove empty elements prefix
1678						if (prefix === '-')
1679							element.removeEmpty = true;
1680
1681						// Copy attributes from global rule into current rule
1682						if (globalAttributes) {
1683							for (key in globalAttributes)
1684								attributes[key] = globalAttributes[key];
1685
1686							attributesOrder.push.apply(attributesOrder, globalAttributesOrder);
1687						}
1688
1689						// Attributes defined
1690						if (attrData) {
1691							attrData = split(attrData, '|');
1692							for (ai = 0, al = attrData.length; ai < al; ai++) {
1693								matches = attrRuleRegExp.exec(attrData[ai]);
1694								if (matches) {
1695									attr = {};
1696									attrType = matches[1];
1697									attrName = matches[2].replace(/::/g, ':');
1698									prefix = matches[3];
1699									value = matches[4];
1700
1701									// Required
1702									if (attrType === '!') {
1703										element.attributesRequired = element.attributesRequired || [];
1704										element.attributesRequired.push(attrName);
1705										attr.required = true;
1706									}
1707
1708									// Denied from global
1709									if (attrType === '-') {
1710										delete attributes[attrName];
1711										attributesOrder.splice(tinymce.inArray(attributesOrder, attrName), 1);
1712										continue;
1713									}
1714
1715									// Default value
1716									if (prefix) {
1717										// Default value
1718										if (prefix === '=') {
1719											element.attributesDefault = element.attributesDefault || [];
1720											element.attributesDefault.push({name: attrName, value: value});
1721											attr.defaultValue = value;
1722										}
1723
1724										// Forced value
1725										if (prefix === ':') {
1726											element.attributesForced = element.attributesForced || [];
1727											element.attributesForced.push({name: attrName, value: value});
1728											attr.forcedValue = value;
1729										}
1730
1731										// Required values
1732										if (prefix === '<')
1733											attr.validValues = makeMap(value, '?');
1734									}
1735
1736									// Check for attribute patterns
1737									if (hasPatternsRegExp.test(attrName)) {
1738										element.attributePatterns = element.attributePatterns || [];
1739										attr.pattern = patternToRegExp(attrName);
1740										element.attributePatterns.push(attr);
1741									} else {
1742										// Add attribute to order list if it doesn't already exist
1743										if (!attributes[attrName])
1744											attributesOrder.push(attrName);
1745
1746										attributes[attrName] = attr;
1747									}
1748								}
1749							}
1750						}
1751
1752						// Global rule, store away these for later usage
1753						if (!globalAttributes && elementName == '@') {
1754							globalAttributes = attributes;
1755							globalAttributesOrder = attributesOrder;
1756						}
1757
1758						// Handle substitute elements such as b/strong
1759						if (outputName) {
1760							element.outputName = elementName;
1761							elements[outputName] = element;
1762						}
1763
1764						// Add pattern or exact element
1765						if (hasPatternsRegExp.test(elementName)) {
1766							element.pattern = patternToRegExp(elementName);
1767							patternElements.push(element);
1768						} else
1769							elements[elementName] = element;
1770					}
1771				}
1772			}
1773		};
1774
1775		function setValidElements(valid_elements) {
1776			elements = {};
1777			patternElements = [];
1778
1779			addValidElements(valid_elements);
1780
1781			each(transitional, function(element, name) {
1782				children[name] = element.children;
1783			});
1784		};
1785
1786		// Adds custom non HTML elements to the schema
1787		function addCustomElements(custom_elements) {
1788			var customElementRegExp = /^(~)?(.+)$/;
1789
1790			if (custom_elements) {
1791				each(split(custom_elements), function(rule) {
1792					var matches = customElementRegExp.exec(rule),
1793						inline = matches[1] === '~',
1794						cloneName = inline ? 'span' : 'div',
1795						name = matches[2];
1796
1797					children[name] = children[cloneName];
1798					customElementsMap[name] = cloneName;
1799
1800					// If it's not marked as inline then add it to valid block elements
1801					if (!inline)
1802						blockElementsMap[name] = {};
1803
1804					// Add custom elements at span/div positions
1805					each(children, function(element, child) {
1806						if (element[cloneName])
1807							element[name] = element[cloneName];
1808					});
1809				});
1810			}
1811		};
1812
1813		// Adds valid children to the schema object
1814		function addValidChildren(valid_children) {
1815			var childRuleRegExp = /^([+\-]?)(\w+)\[([^\]]+)\]$/;
1816
1817			if (valid_children) {
1818				each(split(valid_children), function(rule) {
1819					var matches = childRuleRegExp.exec(rule), parent, prefix;
1820
1821					if (matches) {
1822						prefix = matches[1];
1823
1824						// Add/remove items from default
1825						if (prefix)
1826							parent = children[matches[2]];
1827						else
1828							parent = children[matches[2]] = {'#comment' : {}};
1829
1830						parent = children[matches[2]];
1831
1832						each(split(matches[3], '|'), function(child) {
1833							if (prefix === '-')
1834								delete parent[child];
1835							else
1836								parent[child] = {};
1837						});
1838					}
1839				});
1840			}
1841		}
1842
1843		if (!settings.valid_elements) {
1844			// No valid elements defined then clone the elements from the transitional spec
1845			each(transitional, function(element, name) {
1846				elements[name] = {
1847					attributes : element.attributes,
1848					attributesOrder : element.attributesOrder
1849				};
1850
1851				children[name] = element.children;
1852			});
1853
1854			// Switch these
1855			each(split('strong/b,em/i'), function(item) {
1856				item = split(item, '/');
1857				elements[item[1]].outputName = item[0];
1858			});
1859
1860			// Add default alt attribute for images
1861			elements.img.attributesDefault = [{name: 'alt', value: ''}];
1862
1863			// Remove these if they are empty by default
1864			each(split('ol,ul,sub,sup,blockquote,span,font,a,table,tbody,tr'), function(name) {
1865				elements[name].removeEmpty = true;
1866			});
1867
1868			// Padd these by default
1869			each(split('p,h1,h2,h3,h4,h5,h6,th,td,pre,div,address,caption'), function(name) {
1870				elements[name].paddEmpty = true;
1871			});
1872		} else
1873			setValidElements(settings.valid_elements);
1874
1875		addCustomElements(settings.custom_elements);
1876		

Large files files are truncated, but you can click here to view the full file