includes/clientside/tinymce/tiny_mce_src.js
changeset 588 20484deb89cd
parent 543 dffcbfbc4e59
child 778 57ce13805b6f
equal deleted inserted replaced
587:705ed7162315 588:20484deb89cd
     1 
     1 
     2 /* file:jscripts/tiny_mce/classes/tinymce.js */
     2 /* file:jscripts/tiny_mce/classes/tinymce.js */
     3 
     3 
     4 var tinymce = {
     4 var tinymce = {
     5 	majorVersion : '3',
     5 	majorVersion : '3',
     6 	minorVersion : '0.8',
     6 	minorVersion : '1.0.1',
     7 	releaseDate : '2008-04-30',
     7 	releaseDate : '2008-06-18',
     8 
     8 
     9 	_init : function() {
     9 	_init : function() {
    10 		var t = this, d = document, w = window, na = navigator, ua = na.userAgent, i, nl, n, base, p;
    10 		var t = this, d = document, w = window, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;
    11 
    11 
    12 		// Browser checks
    12 		// Browser checks
    13 		t.isOpera = w.opera && opera.buildNumber;
    13 		t.isOpera = w.opera && opera.buildNumber;
    14 		t.isWebKit = /WebKit/.test(ua);
    14 		t.isWebKit = /WebKit/.test(ua);
    15 		t.isOldWebKit = t.isWebKit && !w.getSelection().getRangeAt;
    15 		t.isOldWebKit = t.isWebKit && !w.getSelection().getRangeAt;
    30 		t.suffix = '';
    30 		t.suffix = '';
    31 
    31 
    32 		// If base element found, add that infront of baseURL
    32 		// If base element found, add that infront of baseURL
    33 		nl = d.getElementsByTagName('base');
    33 		nl = d.getElementsByTagName('base');
    34 		for (i=0; i<nl.length; i++) {
    34 		for (i=0; i<nl.length; i++) {
    35 			if (nl[i].href)
    35 			if (v = nl[i].href) {
    36 				base = 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 			}
    37 		}
    42 		}
    38 
    43 
    39 		function getBase(n) {
    44 		function getBase(n) {
    40 			if (n.src && /tiny_mce(|_dev|_src|_gzip|_jquery|_prototype).js/.test(n.src)) {
    45 			if (n.src && /tiny_mce(|_dev|_src|_gzip|_jquery|_prototype).js/.test(n.src)) {
    41 				if (/_(src|dev)\.js/g.test(n.src))
    46 				if (/_(src|dev)\.js/g.test(n.src))
   874 			if (o.content_type)
   879 			if (o.content_type)
   875 				x.setRequestHeader('Content-Type', o.content_type);
   880 				x.setRequestHeader('Content-Type', o.content_type);
   876 
   881 
   877 			x.send(o.data);
   882 			x.send(o.data);
   878 
   883 
   879 			// Wait for response, onReadyStateChange can not be used since it leaks memory in IE
   884 			function ready() {
   880 			t = w.setInterval(function() {
   885 				if (!o.async || x.readyState == 4 || c++ > 10000) {
   881 				if (x.readyState == 4 || c++ > 10000) {
       
   882 					w.clearInterval(t);
       
   883 
       
   884 					if (o.success && c < 10000 && x.status == 200)
   886 					if (o.success && c < 10000 && x.status == 200)
   885 						o.success.call(o.success_scope, '' + x.responseText, x, o);
   887 						o.success.call(o.success_scope, '' + x.responseText, x, o);
   886 					else if (o.error)
   888 					else if (o.error)
   887 						o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);
   889 						o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);
   888 
   890 
   889 					x = null;
   891 					x = null;
   890 				}
   892 				} else
   891 			}, 10);
   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);
   892 		}
   902 		}
   893 
   903 
   894 		}
   904 		}
   895 });
   905 });
   896 
   906 
  1063 						s = true;
  1073 						s = true;
  1064 						return false;
  1074 						return false;
  1065 					}
  1075 					}
  1066 
  1076 
  1067 					each(na.split(','), function(v) {
  1077 					each(na.split(','), function(v) {
  1068 						if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName == v)) {
  1078 						if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName.toUpperCase() == v)) {
  1069 							s = true;
  1079 							s = true;
  1070 							return false; // Break loop
  1080 							return false; // Break loop
  1071 						}
  1081 						}
  1072 					});
  1082 					});
  1073 
  1083 
  1480 
  1490 
  1481 							t.setAttrib(e, 'mce_' + n, v, 2);
  1491 							t.setAttrib(e, 'mce_' + n, v, 2);
  1482 						}
  1492 						}
  1483 
  1493 
  1484 						break;
  1494 						break;
       
  1495 					
       
  1496 					case "shape":
       
  1497 						e.setAttribute('mce_style', v);
       
  1498 						break;
  1485 				}
  1499 				}
  1486 
  1500 
  1487 				if (is(v) && v !== null && v.length !== 0)
  1501 				if (is(v) && v !== null && v.length !== 0)
  1488 					e.setAttribute(n, '' + v, 2);
  1502 					e.setAttribute(n, '' + v, 2);
  1489 				else
  1503 				else
  1513 
  1527 
  1514 			if (!is(dv))
  1528 			if (!is(dv))
  1515 				dv = "";
  1529 				dv = "";
  1516 
  1530 
  1517 			// Try the mce variant for these
  1531 			// Try the mce variant for these
  1518 			if (/^(src|href|style|coords)$/.test(n)) {
  1532 			if (/^(src|href|style|coords|shape)$/.test(n)) {
  1519 				v = e.getAttribute("mce_" + n);
  1533 				v = e.getAttribute("mce_" + n);
  1520 
  1534 
  1521 				if (v)
  1535 				if (v)
  1522 					return v;
  1536 					return v;
  1523 			}
  1537 			}
  1584 							v = '';
  1598 							v = '';
  1585 
  1599 
  1586 						break;
  1600 						break;
  1587 
  1601 
  1588 					case 'tabindex':
  1602 					case 'tabindex':
  1589 						// IE returns 32768 as default value
  1603 						// IE returns default value
  1590 						if (v === 32768)
  1604 						if (v === 32768)
       
  1605 							v = '';
       
  1606 
       
  1607 						break;
       
  1608 
       
  1609 					case 'maxlength':
       
  1610 						// IE returns  default value
       
  1611 						if (v === 2147483647)
  1591 							v = '';
  1612 							v = '';
  1592 
  1613 
  1593 						break;
  1614 						break;
  1594 
  1615 
  1595 					case 'shape':
  1616 					case 'shape':
  1700 				delete o[a];
  1721 				delete o[a];
  1701 				delete o[b];
  1722 				delete o[b];
  1702 				delete o[c];
  1723 				delete o[c];
  1703 			};
  1724 			};
  1704 
  1725 
       
  1726 			st = st.replace(/&(#?[a-z0-9]+);/g, '&$1_MCE_SEMI_'); // Protect entities
       
  1727 
  1705 			each(st.split(';'), function(v) {
  1728 			each(st.split(';'), function(v) {
  1706 				var sv, ur = [];
  1729 				var sv, ur = [];
  1707 
  1730 
  1708 				if (v) {
  1731 				if (v) {
       
  1732 					v = v.replace(/_MCE_SEMI_/g, ';'); // Restore entities
  1709 					v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});
  1733 					v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});
  1710 					v = v.split(':');
  1734 					v = v.split(':');
  1711 					sv = tinymce.trim(v[1]);
  1735 					sv = tinymce.trim(v[1]);
  1712 					sv = sv.replace(/url\(([^\)]+)\)/g, function(a, b) {return ur[parseInt(b) - 1];});
  1736 					sv = sv.replace(/url\(([^\)]+)\)/g, function(a, b) {return ur[parseInt(b) - 1];});
  1713 
  1737 
  1715 						return t.toHex(v);
  1739 						return t.toHex(v);
  1716 					});
  1740 					});
  1717 
  1741 
  1718 					if (s.url_converter) {
  1742 					if (s.url_converter) {
  1719 						sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {
  1743 						sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {
  1720 							return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null)) + ')';
  1744 							return 'url(' + s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null) + ')';
  1721 						});
  1745 						});
  1722 					}
  1746 					}
  1723 
  1747 
  1724 					o[tinymce.trim(v[0]).toLowerCase()] = sv;
  1748 					o[tinymce.trim(v[0]).toLowerCase()] = sv;
  1725 				}
  1749 				}
  1745 		serializeStyle : function(o) {
  1769 		serializeStyle : function(o) {
  1746 			var s = '';
  1770 			var s = '';
  1747 
  1771 
  1748 			each(o, function(v, k) {
  1772 			each(o, function(v, k) {
  1749 				if (k && v) {
  1773 				if (k && v) {
       
  1774 					if (tinymce.isGecko && k.indexOf('-moz-') === 0)
       
  1775 						return;
       
  1776 
  1750 					switch (k) {
  1777 					switch (k) {
  1751 						case 'color':
  1778 						case 'color':
  1752 						case 'background-color':
  1779 						case 'background-color':
  1753 							v = v.toLowerCase();
  1780 							v = v.toLowerCase();
  1754 							break;
  1781 							break;
  1973 			// Fix some issues
  2000 			// Fix some issues
  1974 			h = h.replace(/<a( )([^>]+)\/>|<a\/>/gi, '<a$1$2></a>'); // Force open
  2001 			h = h.replace(/<a( )([^>]+)\/>|<a\/>/gi, '<a$1$2></a>'); // Force open
  1975 
  2002 
  1976 			// Store away src and href in mce_src and mce_href since browsers mess them up
  2003 			// Store away src and href in mce_src and mce_href since browsers mess them up
  1977 			if (s.keep_values) {
  2004 			if (s.keep_values) {
  1978 				// Wrap scripts in comments for serialization purposes
  2005 				// Wrap scripts and styles in comments for serialization purposes
  1979 				if (h.indexOf('<script') !== -1) {
  2006 				if (/<script|style/.test(h)) {
  1980 					h = h.replace(/<script>/g, '<script type="text/javascript">');
  2007 					function trim(s) {
  1981 					h = h.replace(/<script(|[^>]+)>(\s*<!--|\/\/\s*<\[CDATA\[)?[\r\n]*/g, '<mce:script$1><!--\n');
  2008 						// Remove prefix and suffix code for element
  1982 					h = h.replace(/\s*(\/\/\s*-->|\/\/\s*]]>)?<\/script>/g, '\n// --></mce:script>');
  2009 						s = s.replace(/^[\r\n]*|[\r\n]*$/g, '');
  1983 					h = h.replace(/<mce:script(|[^>]+)><!--\n\/\/ --><\/mce:script>/g, '<mce:script$1></mce:script>');
  2010 						s = s.replace(/^\s*(\/\/\s*<!--|\/\/\s*<\[CDATA\[|<!--|<\[CDATA\[)[\r\n]*/g, '');
       
  2011 						s = s.replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->)\s*$/g, '');
       
  2012 
       
  2013 						return s;
       
  2014 					};
       
  2015 
       
  2016 					// Preserve script elements
       
  2017 					h = h.replace(/<script([^>]+|)>([\s\S]*?)<\/script>/g, function(v, a, b) {
       
  2018 						// Remove prefix and suffix code for script element
       
  2019 						b = trim(b);
       
  2020 
       
  2021 						// Force type attribute
       
  2022 						if (!a)
       
  2023 							a = ' type="text/javascript"';
       
  2024 
       
  2025 						// Wrap contents in a comment
       
  2026 						if (b)
       
  2027 							b = '<!--\n' + b + '\n// -->';
       
  2028 
       
  2029 						// Output fake element
       
  2030 						return '<mce:script' + a + '>' + b + '</mce:script>';
       
  2031 					});
       
  2032 
       
  2033 					// Preserve style elements
       
  2034 					h = h.replace(/<style([^>]+|)>([\s\S]*?)<\/style>/g, function(v, a, b) {
       
  2035 						b = trim(b);
       
  2036 						return '<mce:style' + a + '><!--\n' + b + '\n--></mce:style><style' + a + ' mce_bogus="1">' + b + '</style>';
       
  2037 					});
  1984 				}
  2038 				}
  1985 
  2039 
  1986 				// Process all tags with src, href or style
  2040 				// Process all tags with src, href or style
  1987 				h = h.replace(/<([\w:]+) [^>]*(src|href|style|coords)[^>]*>/gi, function(a, n) {
  2041 				h = h.replace(/<([\w:]+) [^>]*(src|href|style|shape|coords)[^>]*>/gi, function(a, n) {
  1988 					function handle(m, b, c) {
  2042 					function handle(m, b, c) {
  1989 						var u = c;
  2043 						var u = c;
  1990 
  2044 
  1991 						// Tag already got a mce_ version
  2045 						// Tag already got a mce_ version
  1992 						if (a.indexOf('mce_' + b) != -1)
  2046 						if (a.indexOf('mce_' + b) != -1)
  2010 							if (s.url_converter) {
  2064 							if (s.url_converter) {
  2011 								u = u.replace(/url\([\'\"]?([^\)\'\"]+)\)/g, function(x, c) {
  2065 								u = u.replace(/url\([\'\"]?([^\)\'\"]+)\)/g, function(x, c) {
  2012 									return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n)) + ')';
  2066 									return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n)) + ')';
  2013 								});
  2067 								});
  2014 							}
  2068 							}
  2015 						} else if (b != 'coords') {
  2069 						} else if (b != 'coords' && b != 'shape') {
  2016 							if (s.url_converter)
  2070 							if (s.url_converter)
  2017 								u = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n));
  2071 								u = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n));
  2018 						}
  2072 						}
  2019 
  2073 
  2020 						return ' ' + b + '="' + c + '" mce_' + b + '="' + u + '"';
  2074 						return ' ' + b + '="' + c + '" mce_' + b + '="' + u + '"';
  2021 					};
  2075 					};
  2022 
  2076 
  2023 					a = a.replace(/ (src|href|style|coords)=[\"]([^\"]+)[\"]/gi, handle); // W3C
  2077 					a = a.replace(/ (src|href|style|coords|shape)=[\"]([^\"]+)[\"]/gi, handle); // W3C
  2024 					a = a.replace(/ (src|href|style|coords)=[\']([^\']+)[\']/gi, handle); // W3C
  2078 					a = a.replace(/ (src|href|style|coords|shape)=[\']([^\']+)[\']/gi, handle); // W3C
  2025 
  2079 
  2026 					return a.replace(/ (src|href|style|coords)=([^\s\"\'>]+)/gi, handle); // IE
  2080 					return a.replace(/ (src|href|style|coords|shape)=([^\s\"\'>]+)/gi, handle); // IE
  2027 				});
  2081 				});
  2028 			}
  2082 			}
  2029 
  2083 
  2030 			return h;
  2084 			return h;
  2031 		},
  2085 		},
  2136 			if (n.nodeType && n.nodeType !== 1)
  2190 			if (n.nodeType && n.nodeType !== 1)
  2137 				return false;
  2191 				return false;
  2138 
  2192 
  2139 			n = n.nodeName || n;
  2193 			n = n.nodeName || n;
  2140 
  2194 
  2141 			return /^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n);
  2195 			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);
  2142 		},
  2196 		},
  2143 
  2197 
  2144 		// #if !jquery
  2198 		// #if !jquery
  2145 
  2199 
  2146 		replace : function(n, o, k) {
  2200 		replace : function(n, o, k) {
  2311 				tinymce.removeUnload(t.destroy);
  2365 				tinymce.removeUnload(t.destroy);
  2312 		},
  2366 		},
  2313 
  2367 
  2314 		_isRes : function(c) {
  2368 		_isRes : function(c) {
  2315 			// Is live resizble element
  2369 			// Is live resizble element
  2316 
  2370 			return /^(top|left|bottom|right|width|height)/i.test(c) || /;\s*(top|left|bottom|right|width|height)/i.test(c);
  2317 			return /^(top|left|bottom|right|width|height)/i.test(c) || /^[;\s](top|left|bottom|right|width|height)/i.test(c);
       
  2318 		}
  2371 		}
  2319 
  2372 
  2320 		/*
  2373 		/*
  2321 		walk : function(n, f, s) {
  2374 		walk : function(n, f, s) {
  2322 			var d = this.doc, w;
  2375 			var d = this.doc, w;
  2553 
  2606 
  2554 		_wait : function() {
  2607 		_wait : function() {
  2555 			var t;
  2608 			var t;
  2556 
  2609 
  2557 			// No need since the document is already loaded
  2610 			// No need since the document is already loaded
  2558 			if (window.tinyMCE_GZ && tinyMCE_GZ.loaded)
  2611 			if (window.tinyMCE_GZ && tinyMCE_GZ.loaded) {
       
  2612 				Event.domLoaded = 1;
  2559 				return;
  2613 				return;
       
  2614 			}
  2560 
  2615 
  2561 			if (isIE && document.location.protocol != 'https:') {
  2616 			if (isIE && document.location.protocol != 'https:') {
  2562 				// Fake DOMContentLoaded on IE
  2617 				// Fake DOMContentLoaded on IE
  2563 				document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');
  2618 				document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');
  2564 				DOM.get("__ie_onload").onreadystatechange = function() {
  2619 				DOM.get("__ie_onload").onreadystatechange = function() {
  2782 
  2837 
  2783 			return t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa;
  2838 			return t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa;
  2784 		},
  2839 		},
  2785 
  2840 
  2786 		setContent : function(h, s) {
  2841 		setContent : function(h, s) {
  2787 			var t = this, r = t.getRng(), d;
  2842 			var t = this, r = t.getRng(), d = t.win.document;
  2788 
  2843 
  2789 			s = s || {format : 'html'};
  2844 			s = s || {format : 'html'};
  2790 			s.set = true;
  2845 			s.set = true;
  2791 			h = t.dom.processHTML(h);
  2846 			h = t.dom.processHTML(h);
  2792 
  2847 
  2793 			if (r.insertNode) {
  2848 			if (r.insertNode) {
  2794 				d = t.win.document;
       
  2795 
       
  2796 				// Gecko has a bug where if you insert &nbsp; using InsertHTML it will insert a space instead
  2849 				// Gecko has a bug where if you insert &nbsp; using InsertHTML it will insert a space instead
  2797 				// So we simply check if the input is HTML or text and then insert text using the insertNode method
  2850 				// So we simply check if the input is HTML or text and then insert text using the insertNode method
  2798 				if (tinymce.isGecko && h.indexOf('<') == -1) {
  2851 				if (tinymce.isGecko && h.indexOf('<') == -1) {
  2799 					r.deleteContents();
  2852 					r.deleteContents();
  2800 					r.insertNode(t.getRng().createContextualFragment(h + '<span id="__caret">_</span>'));
  2853 					r.insertNode(t.getRng().createContextualFragment(h + '<span id="__caret">_</span>'));
  2812 					// Use old school method
  2865 					// Use old school method
  2813 					r.deleteContents();
  2866 					r.deleteContents();
  2814 					r.insertNode(t.getRng().createContextualFragment(h));
  2867 					r.insertNode(t.getRng().createContextualFragment(h));
  2815 				}
  2868 				}
  2816 			} else {
  2869 			} else {
  2817 				if (r.item)
  2870 				if (r.item) {
  2818 					r.item(0).outerHTML = h;
  2871 					// Delete content and get caret text selection
  2819 				else
  2872 					d.execCommand('Delete', false, null);
  2820 					r.pasteHTML(h);
  2873 					r = t.getRng();
       
  2874 				}
       
  2875 
       
  2876 				r.pasteHTML(h);
  2821 			}
  2877 			}
  2822 		},
  2878 		},
  2823 
  2879 
  2824 		getStart : function() {
  2880 		getStart : function() {
  2825 			var t = this, r = t.getRng(), e;
  2881 			var t = this, r = t.getRng(), e;
  2950 					if (n == en) {
  3006 					if (n == en) {
  2951 						d.end = p;
  3007 						d.end = p;
  2952 						return d;
  3008 						return d;
  2953 					}
  3009 					}
  2954 
  3010 
  2955 					p += (n.nodeValue || '').length;
  3011 					p += trimNl(n.nodeValue || '').length;
  2956 				}
  3012 				}
  2957 
  3013 
  2958 				return null;
  3014 				return null;
  2959 			};
  3015 			};
  2960 
  3016 
  4325 			t.setRules(s.valid_elements);
  4381 			t.setRules(s.valid_elements);
  4326 			t.addRules(s.extended_valid_elements);
  4382 			t.addRules(s.extended_valid_elements);
  4327 			t.addValidChildRules(s.valid_child_elements);
  4383 			t.addValidChildRules(s.valid_child_elements);
  4328 
  4384 
  4329 			if (s.invalid_elements)
  4385 			if (s.invalid_elements)
  4330 				t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(',', '|').toLowerCase()) + ')$');
  4386 				t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(/,/g, '|').toLowerCase()) + ')$');
  4331 
  4387 
  4332 			if (s.attrib_value_filter)
  4388 			if (s.attrib_value_filter)
  4333 				t.attribValueFilter = s.attribValueFilter;
  4389 				t.attribValueFilter = s.attribValueFilter;
  4334 		},
  4390 		},
  4335 
  4391 
  4923 
  4979 
  4924 			this.parent(id, s);
  4980 			this.parent(id, s);
  4925 			this.onShowMenu = new tinymce.util.Dispatcher(this);
  4981 			this.onShowMenu = new tinymce.util.Dispatcher(this);
  4926 			this.onHideMenu = new tinymce.util.Dispatcher(this);
  4982 			this.onHideMenu = new tinymce.util.Dispatcher(this);
  4927 			this.classPrefix = 'mceMenu';
  4983 			this.classPrefix = 'mceMenu';
  4928 
       
  4929 			// Fix for odd IE bug: #1903622 (Frames selection)
       
  4930 			this.fixIE = tinymce.isIE && (DOM.win.top != DOM.win);
       
  4931 		},
  4984 		},
  4932 
  4985 
  4933 		createMenu : function(s) {
  4986 		createMenu : function(s) {
  4934 			var t = this, cs = t.settings, m;
  4987 			var t = this, cs = t.settings, m;
  4935 
  4988 
  5015 
  5068 
  5016 			DOM.setStyles(co, {left : x , top : y});
  5069 			DOM.setStyles(co, {left : x , top : y});
  5017 			t.element.update();
  5070 			t.element.update();
  5018 
  5071 
  5019 			t.isMenuVisible = 1;
  5072 			t.isMenuVisible = 1;
  5020 			t.mouseClickFunc = Event.add(co, t.fixIE ? 'mousedown' : 'click', function(e) {
  5073 			t.mouseClickFunc = Event.add(co, 'click', function(e) {
  5021 				var m;
  5074 				var m;
  5022 
  5075 
  5023 				e = e.target;
  5076 				e = e.target;
  5024 
  5077 
  5025 				if (e && (e = DOM.getParent(e, 'TR')) && !DOM.hasClass(e, cp + 'ItemSub')) {
  5078 				if (e && (e = DOM.getParent(e, 'TR')) && !DOM.hasClass(e, cp + 'ItemSub')) {
  5028 					if (m.isDisabled())
  5081 					if (m.isDisabled())
  5029 						return;
  5082 						return;
  5030 
  5083 
  5031 					dm = t;
  5084 					dm = t;
  5032 
  5085 
  5033 					// Wait a while to fix IE bug where it looses the selection if the user clicks on a menu
  5086 					while (dm) {
  5034 					// item when the editor is placed within an frame or iframe
  5087 						if (dm.hideMenu)
  5035 					DOM.win.setTimeout(function() {
  5088 							dm.hideMenu();
  5036 						while (dm) {
  5089 
  5037 							if (dm.hideMenu)
  5090 						dm = dm.settings.parent;
  5038 								dm.hideMenu();
  5091 					}
  5039 
  5092 
  5040 							dm = dm.settings.parent;
  5093 					if (m.settings.onclick)
  5041 						}
  5094 						m.settings.onclick(e);
  5042 					}, 0);
       
  5043 
       
  5044 					// Yield on IE to prevent loosing image focus when context menu is used
       
  5045 					window.setTimeout(function() {
       
  5046 						if (m.settings.onclick)
       
  5047 							m.settings.onclick(e);
       
  5048 					}, 0);
       
  5049 
  5095 
  5050 					return Event.cancel(e); // Cancel to fix onbeforeunload problem
  5096 					return Event.cancel(e); // Cancel to fix onbeforeunload problem
  5051 				}
  5097 				}
  5052 			});
  5098 			});
  5053 
  5099 
  5079 			t.onShowMenu.dispatch(t);
  5125 			t.onShowMenu.dispatch(t);
  5080 
  5126 
  5081 			if (s.keyboard_focus) {
  5127 			if (s.keyboard_focus) {
  5082 				Event.add(co, 'keydown', t._keyHandler, t);
  5128 				Event.add(co, 'keydown', t._keyHandler, t);
  5083 				DOM.select('a', 'menu_' + t.id)[0].focus(); // Select first link
  5129 				DOM.select('a', 'menu_' + t.id)[0].focus(); // Select first link
       
  5130 				t._focusIdx = 0;
  5084 			}
  5131 			}
  5085 		},
  5132 		},
  5086 
  5133 
  5087 		hideMenu : function(c) {
  5134 		hideMenu : function(c) {
  5088 			var t = this, co = DOM.get('menu_' + t.id), e;
  5135 			var t = this, co = DOM.get('menu_' + t.id), e;
  5089 
  5136 
  5090 			if (!t.isMenuVisible)
  5137 			if (!t.isMenuVisible)
  5091 				return;
  5138 				return;
  5092 
  5139 
  5093 			Event.remove(co, 'mouseover', t.mouseOverFunc);
  5140 			Event.remove(co, 'mouseover', t.mouseOverFunc);
  5094 			Event.remove(co, t.fixIE ? 'mousedown' : 'click', t.mouseClickFunc);
  5141 			Event.remove(co, 'click', t.mouseClickFunc);
  5095 			Event.remove(co, 'keydown', t._keyHandler);
  5142 			Event.remove(co, 'keydown', t._keyHandler);
  5096 			DOM.hide(co);
  5143 			DOM.hide(co);
  5097 			t.isMenuVisible = 0;
  5144 			t.isMenuVisible = 0;
  5098 
  5145 
  5099 			if (!c)
  5146 			if (!c)
  5167 		},
  5214 		},
  5168 
  5215 
  5169 		// Internal functions
  5216 		// Internal functions
  5170 
  5217 
  5171 		_keyHandler : function(e) {
  5218 		_keyHandler : function(e) {
  5172 			// Accessibility feature
  5219 			var t = this, kc = e.keyCode;
  5173 			if (e.keyCode == 27)
  5220 
  5174 				this.hideMenu();
  5221 			function focus(d) {
       
  5222 				var i = t._focusIdx + d, e = DOM.select('a', 'menu_' + t.id)[i];
       
  5223 
       
  5224 				if (e) {
       
  5225 					t._focusIdx = i;
       
  5226 					e.focus();
       
  5227 				}
       
  5228 			};
       
  5229 
       
  5230 			switch (kc) {
       
  5231 				case 38:
       
  5232 					focus(-1); // Select first link
       
  5233 					return;
       
  5234 
       
  5235 				case 40:
       
  5236 					focus(1);
       
  5237 					return;
       
  5238 
       
  5239 				case 13:
       
  5240 					return;
       
  5241 
       
  5242 				case 27:
       
  5243 					return this.hideMenu();
       
  5244 			}
  5175 		},
  5245 		},
  5176 
  5246 
  5177 		_add : function(tb, o) {
  5247 		_add : function(tb, o) {
  5178 			var n, s = o.settings, a, ro, it, cp = this.classPrefix;
  5248 			var n, s = o.settings, a, ro, it, cp = this.classPrefix;
  5179 
  5249 
  5347 			p2 = DOM.getPos(e);
  5417 			p2 = DOM.getPos(e);
  5348 
  5418 
  5349 			m = t.menu;
  5419 			m = t.menu;
  5350 			m.settings.offset_x = p2.x;
  5420 			m.settings.offset_x = p2.x;
  5351 			m.settings.offset_y = p2.y;
  5421 			m.settings.offset_y = p2.y;
  5352 			m.settings.keyboard_focus = t._focused;
  5422 			m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus
  5353 
  5423 
  5354 			// Select in menu
  5424 			// Select in menu
  5355 			if (t.oldID)
  5425 			if (t.oldID)
  5356 				m.items[t.oldID].setSelected(0);
  5426 				m.items[t.oldID].setSelected(0);
  5357 
  5427 
  5364 
  5434 
  5365 			m.showMenu(0, e.clientHeight);
  5435 			m.showMenu(0, e.clientHeight);
  5366 
  5436 
  5367 			Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
  5437 			Event.add(DOM.doc, 'mousedown', t.hideMenu, t);
  5368 			DOM.addClass(t.id, t.classPrefix + 'Selected');
  5438 			DOM.addClass(t.id, t.classPrefix + 'Selected');
       
  5439 
       
  5440 			//DOM.get(t.id + '_text').focus();
  5369 		},
  5441 		},
  5370 
  5442 
  5371 		hideMenu : function(e) {
  5443 		hideMenu : function(e) {
  5372 			var t = this;
  5444 			var t = this;
  5373 
  5445 
  5396 
  5468 
  5397 			m.onHideMenu.add(t.hideMenu, t);
  5469 			m.onHideMenu.add(t.hideMenu, t);
  5398 
  5470 
  5399 			m.add({
  5471 			m.add({
  5400 				title : t.settings.title,
  5472 				title : t.settings.title,
  5401 				'class' : 'mceMenuItemTitle'
  5473 				'class' : 'mceMenuItemTitle',
  5402 			}).setDisabled(1);
  5474 				onclick : function() {
       
  5475 					if (t.settings.onselect('') !== false)
       
  5476 						t.select(''); // Must be runned after
       
  5477 				}
       
  5478 			});
  5403 
  5479 
  5404 			each(t.items, function(o) {
  5480 			each(t.items, function(o) {
  5405 				o.id = DOM.uniqueId();
  5481 				o.id = DOM.uniqueId();
  5406 				o.onclick = function() {
  5482 				o.onclick = function() {
  5407 					if (t.settings.onselect(o.value) !== false)
  5483 					if (t.settings.onselect(o.value) !== false)
  5417 
  5493 
  5418 		postRender : function() {
  5494 		postRender : function() {
  5419 			var t = this, cp = t.classPrefix;
  5495 			var t = this, cp = t.classPrefix;
  5420 
  5496 
  5421 			Event.add(t.id, 'click', t.showMenu, t);
  5497 			Event.add(t.id, 'click', t.showMenu, t);
  5422 			Event.add(t.id + '_text', 'focus', function() {t._focused = 1;});
  5498 			Event.add(t.id + '_text', 'focus', function(e) {
  5423 			Event.add(t.id + '_text', 'blur', function() {t._focused = 0;});
  5499 				if (!t._focused) {
       
  5500 					t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) {
       
  5501 						var idx = -1, v, kc = e.keyCode;
       
  5502 
       
  5503 						// Find current index
       
  5504 						each(t.items, function(v, i) {
       
  5505 							if (t.selectedValue == v.value)
       
  5506 								idx = i;
       
  5507 						});
       
  5508 
       
  5509 						// Move up/down
       
  5510 						if (kc == 38)
       
  5511 							v = t.items[idx - 1];
       
  5512 						else if (kc == 40)
       
  5513 							v = t.items[idx + 1];
       
  5514 						else if (kc == 13) {
       
  5515 							// Fake select on enter
       
  5516 							v = t.selectedValue;
       
  5517 							t.selectedValue = null; // Needs to be null to fake change
       
  5518 							t.settings.onselect(v);
       
  5519 							return Event.cancel(e);
       
  5520 						}
       
  5521 
       
  5522 						if (v) {
       
  5523 							t.hideMenu();
       
  5524 							t.select(v.value);
       
  5525 						}
       
  5526 					});
       
  5527 				}
       
  5528 
       
  5529 				t._focused = 1;
       
  5530 			});
       
  5531 			Event.add(t.id + '_text', 'blur', function() {Event.remove(t.id + '_text', 'keydown', t.keyDownHandler); t._focused = 0;});
  5424 
  5532 
  5425 			// Old IE doesn't have hover on all elements
  5533 			// Old IE doesn't have hover on all elements
  5426 			if (tinymce.isIE6 || !DOM.boxModel) {
  5534 			if (tinymce.isIE6 || !DOM.boxModel) {
  5427 				Event.add(t.id, 'mouseover', function() {
  5535 				Event.add(t.id, 'mouseover', function() {
  5428 					if (!DOM.hasClass(t.id, cp + 'Disabled'))
  5536 					if (!DOM.hasClass(t.id, cp + 'Disabled'))
  5728 			t.settings = s = tinymce.extend({
  5836 			t.settings = s = tinymce.extend({
  5729 				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',
  5837 				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',
  5730 				grid_width : 8,
  5838 				grid_width : 8,
  5731 				default_color : '#888888'
  5839 				default_color : '#888888'
  5732 			}, t.settings);
  5840 			}, t.settings);
       
  5841 
       
  5842 			t.onShowMenu = new tinymce.util.Dispatcher(t);
       
  5843 			t.onHideMenu = new tinymce.util.Dispatcher(t);
  5733 
  5844 
  5734 			t.value = s.default_color;
  5845 			t.value = s.default_color;
  5735 		},
  5846 		},
  5736 
  5847 
  5737 		showMenu : function() {
  5848 		showMenu : function() {
  5768 				});
  5879 				});
  5769 
  5880 
  5770 				DOM.select('a', t.id + '_menu')[0].focus(); // Select first link
  5881 				DOM.select('a', t.id + '_menu')[0].focus(); // Select first link
  5771 			}
  5882 			}
  5772 
  5883 
       
  5884 			t.onShowMenu.dispatch(t);
       
  5885 
  5773 			t.isMenuVisible = 1;
  5886 			t.isMenuVisible = 1;
  5774 		},
  5887 		},
  5775 
  5888 
  5776 		hideMenu : function(e) {
  5889 		hideMenu : function(e) {
  5777 			var t = this;
  5890 			var t = this;
  5784 				DOM.removeClass(t.id, 'mceSplitButtonSelected');
  5897 				DOM.removeClass(t.id, 'mceSplitButtonSelected');
  5785 				Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
  5898 				Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);
  5786 				Event.remove(t.id + '_menu', 'keydown', t._keyHandler);
  5899 				Event.remove(t.id + '_menu', 'keydown', t._keyHandler);
  5787 				DOM.hide(t.id + '_menu');
  5900 				DOM.hide(t.id + '_menu');
  5788 			}
  5901 			}
       
  5902 
       
  5903 			t.onHideMenu.dispatch(t);
  5789 
  5904 
  5790 			t.isMenuVisible = 0;
  5905 			t.isMenuVisible = 0;
  5791 		},
  5906 		},
  5792 
  5907 
  5793 		renderMenu : function() {
  5908 		renderMenu : function() {
  6465 				convert_fonts_to_spans : true,
  6580 				convert_fonts_to_spans : true,
  6466 				font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large',
  6581 				font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large',
  6467 				apply_source_formatting : 1,
  6582 				apply_source_formatting : 1,
  6468 				directionality : 'ltr',
  6583 				directionality : 'ltr',
  6469 				forced_root_block : 'p',
  6584 				forced_root_block : 'p',
  6470 				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,-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|_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],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',
  6585 				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],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',
  6471 				hidden_input : 1,
  6586 				hidden_input : 1,
  6472 				padd_empty_editor : 1,
  6587 				padd_empty_editor : 1,
  6473 				render_ui : 1,
  6588 				render_ui : 1,
  6474 				init_theme : 1,
  6589 				init_theme : 1,
  6475 				force_p_newlines : 1,
  6590 				force_p_newlines : 1,
  6518 
  6633 
  6519 			t.windowManager = new tinymce.WindowManager(t);
  6634 			t.windowManager = new tinymce.WindowManager(t);
  6520 
  6635 
  6521 			if (s.encoding == 'xml') {
  6636 			if (s.encoding == 'xml') {
  6522 				t.onGetContent.add(function(ed, o) {
  6637 				t.onGetContent.add(function(ed, o) {
  6523 					if (o.get)
  6638 					if (o.save)
  6524 						o.content = DOM.encode(o.content);
  6639 						o.content = DOM.encode(o.content);
  6525 				});
  6640 				});
  6526 			}
  6641 			}
  6527 
  6642 
  6528 			if (s.add_form_submit_trigger) {
  6643 			if (s.add_form_submit_trigger) {
  6532 						t.isNotDirty = 1;
  6647 						t.isNotDirty = 1;
  6533 					}
  6648 					}
  6534 				});
  6649 				});
  6535 			}
  6650 			}
  6536 
  6651 
  6537 			if (s.add_unload_trigger) {
  6652 			if (s.add_unload_trigger && !s.ask) {
  6538 				t._beforeUnload = tinyMCE.onBeforeUnload.add(function() {
  6653 				t._beforeUnload = tinyMCE.onBeforeUnload.add(function() {
  6539 					if (t.initialized && !t.destroyed && !t.isHidden())
  6654 					if (t.initialized && !t.destroyed && !t.isHidden())
  6540 						t.save({format : 'raw', no_events : true});
  6655 						t.save({format : 'raw', no_events : true});
  6541 				});
  6656 				});
  6542 			}
  6657 			}
  6591 
  6706 
  6592 				// Init when que is loaded
  6707 				// Init when que is loaded
  6593 				sl.loadQueue(function() {
  6708 				sl.loadQueue(function() {
  6594 					if (s.ask) {
  6709 					if (s.ask) {
  6595 						function ask() {
  6710 						function ask() {
  6596 							t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {
  6711 							// Yield for awhile to avoid focus bug on FF 3 when cancel is pressed
  6597 								if (s)
  6712 							window.setTimeout(function() {
  6598 									t.init();
  6713 								Event.remove(t.id, 'focus', ask);
  6599 								else
  6714 
  6600 									Event.remove(t.id, 'focus', ask);
  6715 								t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {
  6601 							});
  6716 									if (s)
       
  6717 										t.init();
       
  6718 								});
       
  6719 							}, 0);
  6602 						};
  6720 						};
  6603 
  6721 
  6604 						Event.add(t.id, 'focus', ask);
  6722 						Event.add(t.id, 'focus', ask);
  6605 						return;
  6723 						return;
  6606 					}
  6724 					}
  6734 
  6852 
  6735 			h = (o.iframeHeight || h) + ((h + '').indexOf('%') == -1 ? (o.deltaHeight || 0) : '');
  6853 			h = (o.iframeHeight || h) + ((h + '').indexOf('%') == -1 ? (o.deltaHeight || 0) : '');
  6736 			if (h < 100)
  6854 			if (h < 100)
  6737 				h = 100;
  6855 				h = 100;
  6738 
  6856 
  6739 			t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '"></base>';
  6857 			t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '" />';
  6740 			t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
  6858 			t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
  6741 
  6859 
  6742 			if (tinymce.relaxedDomain)
  6860 			if (tinymce.relaxedDomain)
  6743 				t.iframeHTML += '<script type="text/javascript">document.domain = "' + tinymce.relaxedDomain + '";</script>';
  6861 				t.iframeHTML += '<script type="text/javascript">document.domain = "' + tinymce.relaxedDomain + '";</script>';
  6744 
  6862 
  7085 			e = null;
  7203 			e = null;
  7086 		},
  7204 		},
  7087 
  7205 
  7088 		
  7206 		
  7089 		focus : function(sf) {
  7207 		focus : function(sf) {
  7090 			var oed, t = this;
  7208 			var oed, t = this, ce = t.settings.content_editable;
  7091 
  7209 
  7092 			if (!sf) {
  7210 			if (!sf) {
  7093 				t.getWin().focus();
  7211 				// Is not content editable or the selection is outside the area in IE
       
  7212 				// the IE statement is needed to avoid bluring if element selections inside layers since
       
  7213 				// the layer is like it's own document in IE
       
  7214 				if (!ce && (!isIE || t.selection.getNode().ownerDocument != t.getDoc()))
       
  7215 					t.getWin().focus();
  7094 
  7216 
  7095 							}
  7217 							}
  7096 
  7218 
  7097 			if (EditorManager.activeEditor != t) {
  7219 			if (EditorManager.activeEditor != t) {
  7098 				if ((oed = EditorManager.activeEditor) != null)
  7220 				if ((oed = EditorManager.activeEditor) != null)
  7263 			o = {};
  7385 			o = {};
  7264 			t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o);
  7386 			t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o);
  7265 			if (o.terminate)
  7387 			if (o.terminate)
  7266 				return false;
  7388 				return false;
  7267 
  7389 
  7268 			// Comamnd callback
  7390 			// Command callback
  7269 			if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) {
  7391 			if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) {
  7270 				t.onExecCommand.dispatch(t, cmd, ui, val, a);
  7392 				t.onExecCommand.dispatch(t, cmd, ui, val, a);
  7271 				return true;
  7393 				return true;
  7272 			}
  7394 			}
  7273 
  7395 
  7429 			if (!t.initialized)
  7551 			if (!t.initialized)
  7430 				return;
  7552 				return;
  7431 
  7553 
  7432 			o = o || {};
  7554 			o = o || {};
  7433 			o.save = true;
  7555 			o.save = true;
       
  7556 
       
  7557 			// Add undo level will trigger onchange event
       
  7558 			if (!o.no_events) {
       
  7559 				t.undoManager.typing = 0;
       
  7560 				t.undoManager.add();
       
  7561 			}
  7434 
  7562 
  7435 			o.element = e;
  7563 			o.element = e;
  7436 			h = o.content = t.getContent(o);
  7564 			h = o.content = t.getContent(o);
  7437 
  7565 
  7438 			if (!o.no_events)
  7566 			if (!o.no_events)
  7472 				t.onBeforeSetContent.dispatch(t, o);
  7600 				t.onBeforeSetContent.dispatch(t, o);
  7473 
  7601 
  7474 			// Padd empty content in Gecko and Safari. Commands will otherwise fail on the content
  7602 			// Padd empty content in Gecko and Safari. Commands will otherwise fail on the content
  7475 			// It will also be impossible to place the caret in the editor unless there is a BR element present
  7603 			// It will also be impossible to place the caret in the editor unless there is a BR element present
  7476 			if (!tinymce.isIE && (h.length === 0 || /^\s+$/.test(h))) {
  7604 			if (!tinymce.isIE && (h.length === 0 || /^\s+$/.test(h))) {
  7477 				o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />', 1);
  7605 				o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />');
  7478 				o.format = 'raw';
  7606 				o.format = 'raw';
  7479 			}
  7607 			}
  7480 
  7608 
  7481 			o.content = t.dom.setHTML(t.getBody(), tinymce.trim(o.content));
  7609 			o.content = t.dom.setHTML(t.getBody(), tinymce.trim(o.content));
  7482 
  7610 
  7506 				h = t.serializer.serialize(t.getBody(), o);
  7634 				h = t.serializer.serialize(t.getBody(), o);
  7507 			} else
  7635 			} else
  7508 				h = t.getBody().innerHTML;
  7636 				h = t.getBody().innerHTML;
  7509 
  7637 
  7510 			h = h.replace(/^\s*|\s*$/g, '');
  7638 			h = h.replace(/^\s*|\s*$/g, '');
  7511 			o = {content : h};
  7639 			o.content = h;
  7512 			t.onGetContent.dispatch(t, o);
  7640 
       
  7641 			if (!o.no_events)
       
  7642 				t.onGetContent.dispatch(t, o);
  7513 
  7643 
  7514 			return o.content;
  7644 			return o.content;
  7515 		},
  7645 		},
  7516 
  7646 
  7517 		isDirty : function() {
  7647 		isDirty : function() {
  7727 			each(lo, function(v, k) {
  7857 			each(lo, function(v, k) {
  7728 				switch (k) {
  7858 				switch (k) {
  7729 					case 'contextmenu':
  7859 					case 'contextmenu':
  7730 						if (tinymce.isOpera) {
  7860 						if (tinymce.isOpera) {
  7731 							// Fake contextmenu on Opera
  7861 							// Fake contextmenu on Opera
  7732 							Event.add(t.getDoc(), 'mousedown', function(e) {
  7862 							Event.add(t.getBody(), 'mousedown', function(e) {
  7733 								if (e.ctrlKey) {
  7863 								if (e.ctrlKey) {
  7734 									e.fakeType = 'contextmenu';
  7864 									e.fakeType = 'contextmenu';
  7735 									eventHandler(e);
  7865 									eventHandler(e);
  7736 								}
  7866 								}
  7737 							});
  7867 							});
  7738 						} else
  7868 						} else
  7739 							Event.add(t.getDoc(), k, eventHandler);
  7869 							Event.add(t.getBody(), k, eventHandler);
  7740 						break;
  7870 						break;
  7741 
  7871 
  7742 					case 'paste':
  7872 					case 'paste':
  7743 						Event.add(t.getBody(), k, function(e) {
  7873 						Event.add(t.getBody(), k, function(e) {
  7744 							var tx, h, el, r;
  7874 							var tx, h, el, r;
  7820 							// Try new Gecko method
  7950 							// Try new Gecko method
  7821 							d.execCommand("styleWithCSS", 0, false);
  7951 							d.execCommand("styleWithCSS", 0, false);
  7822 						} catch (ex) {
  7952 						} catch (ex) {
  7823 							// Use old method
  7953 							// Use old method
  7824 							if (!t._isHidden())
  7954 							if (!t._isHidden())
  7825 								d.execCommand("useCSS", 0, true);
  7955 								try {d.execCommand("useCSS", 0, true);} catch (ex) {}
  7826 						}
  7956 						}
  7827 
  7957 
  7828 						if (!s.table_inline_editing)
  7958 						if (!s.table_inline_editing)
  7829 							try {d.execCommand('enableInlineTableEditing', false, false);} catch (ex) {}
  7959 							try {d.execCommand('enableInlineTableEditing', false, false);} catch (ex) {}
  7830 
  7960 
  8549 			} else
  8679 			} else
  8550 				ed.getDoc().execCommand('FontName', false, v);
  8680 				ed.getDoc().execCommand('FontName', false, v);
  8551 		},
  8681 		},
  8552 
  8682 
  8553 		FontSize : function(u, v) {
  8683 		FontSize : function(u, v) {
  8554 			var ed = this.editor, s = ed.settings, fz = tinymce.explode(s.font_size_style_values), fzc = tinymce.explode(s.font_size_classes);
  8684 			var ed = this.editor, s = ed.settings, fz = tinymce.explode(s.font_size_style_values), fzc = tinymce.explode(s.font_size_classes), h, bm;
  8555 
  8685 
       
  8686 			// Remove style sizes
       
  8687 			each(ed.dom.select('font'), function(e) {
       
  8688 				e.style.fontSize = '';
       
  8689 			});
       
  8690 
       
  8691 			// Let the browser add new size it will remove unneded ones in some browsers
  8556 			ed.getDoc().execCommand('FontSize', false, v);
  8692 			ed.getDoc().execCommand('FontSize', false, v);
  8557 
  8693 
  8558 			// Add style values
  8694 			// Add style values
  8559 			if (s.inline_styles) {
  8695 			if (s.inline_styles) {
  8560 				each(ed.dom.select('font'), function(e) {
  8696 				each(ed.dom.select('font'), function(e) {
  8561 					if (e.size === v) {
  8697 					// Try remove redundant font elements
       
  8698 					if (e.parentNode.nodeName == 'FONT' && e.size == e.parentNode.size) {
       
  8699 						if (!bm)
       
  8700 							bm = ed.selection.getBookmark();
       
  8701 
       
  8702 						ed.dom.remove(e, 1);
       
  8703 						return;
       
  8704 					}
       
  8705 
       
  8706 					// Setup font size based on font size value
       
  8707 					if (v = e.size) {
  8562 						if (fzc && fzc.length > 0)
  8708 						if (fzc && fzc.length > 0)
  8563 							ed.dom.setAttrib(e, 'class', fzc[parseInt(v) - 1]);
  8709 							ed.dom.setAttrib(e, 'class', fzc[parseInt(v) - 1]);
  8564 						else
  8710 						else
  8565 							ed.dom.setStyle(e, 'fontSize', fz[parseInt(v) - 1]);
  8711 							ed.dom.setStyle(e, 'fontSize', fz[parseInt(v) - 1]);
  8566 					}
  8712 					}
  8567 				});
  8713 				});
  8568 			}
  8714 			}
       
  8715 
       
  8716 			ed.selection.moveToBookmark(bm);
  8569 		},
  8717 		},
  8570 
  8718 
  8571 		queryCommandValue : function(c) {
  8719 		queryCommandValue : function(c) {
  8572 			var f = this['queryValue' + c];
  8720 			var f = this['queryValue' + c];
  8573 
  8721 
  9002 			} else
  9150 			} else
  9003 				ed.getDoc().execCommand('Redo', false, null);
  9151 				ed.getDoc().execCommand('Redo', false, null);
  9004 		},
  9152 		},
  9005 
  9153 
  9006 		FormatBlock : function(ui, val) {
  9154 		FormatBlock : function(ui, val) {
  9007 			var t = this, ed = t.editor;
  9155 			var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, bl, nb, b;
       
  9156 
       
  9157 			function isBlock(n) {
       
  9158 				return /^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(n.nodeName);
       
  9159 			};
       
  9160 
       
  9161 			bl = dom.getParent(s.getNode(), function(n) {
       
  9162 				return isBlock(n);
       
  9163 			});
       
  9164 
       
  9165 			// IE has an issue where it removes the parent div if you change format on the paragrah in <div><p>Content</p></div>
       
  9166 			// FF and Opera doesn't change parent DIV elements if you switch format
       
  9167 			if (bl) {
       
  9168 				if ((isIE && isBlock(bl.parentNode)) || bl.nodeName == 'DIV') {
       
  9169 					// Rename block element
       
  9170 					nb = ed.dom.create(val);
       
  9171 
       
  9172 					each(dom.getAttribs(bl), function(v) {
       
  9173 						dom.setAttrib(nb, v.nodeName, dom.getAttrib(bl, v.nodeName));
       
  9174 					});
       
  9175 
       
  9176 					b = s.getBookmark();
       
  9177 					dom.replace(nb, bl, 1);
       
  9178 					s.moveToBookmark(b);
       
  9179 					ed.nodeChanged();
       
  9180 					return;
       
  9181 				}
       
  9182 			}
  9008 
  9183 
  9009 			val = ed.settings.forced_root_block ? (val || '<p>') : val;
  9184 			val = ed.settings.forced_root_block ? (val || '<p>') : val;
  9010 
       
  9011 			if (/^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(ed.selection.getNode().nodeName))
       
  9012 				t.mceRemoveNode();
       
  9013 
  9185 
  9014 			if (val.indexOf('<') == -1)
  9186 			if (val.indexOf('<') == -1)
  9015 				val = '<' + val + '>';
  9187 				val = '<' + val + '>';
  9016 
  9188 
  9017 			if (tinymce.isGecko)
  9189 			if (tinymce.isGecko)
  9654 						// Create new block but ignore whitespace
  9826 						// Create new block but ignore whitespace
  9655 						if (nx.nodeType != 3 || /[^\s]/g.test(nx.nodeValue)) {
  9827 						if (nx.nodeType != 3 || /[^\s]/g.test(nx.nodeValue)) {
  9656 							// Store selection
  9828 							// Store selection
  9657 							if (si == -2 && r) {
  9829 							if (si == -2 && r) {
  9658 								if (!isIE) {
  9830 								if (!isIE) {
  9659 									so = r.startOffset;
  9831 									// If element is inside body, might not be the case in contentEdiable mode
  9660 									eo = r.endOffset;
  9832 									if (ed.dom.getParent(r.startContainer, function(e) {return e === b;})) {
  9661 									si = t.find(b, 0, r.startContainer);
  9833 										so = r.startOffset;
  9662 									ei = t.find(b, 0, r.endContainer);
  9834 										eo = r.endOffset;
       
  9835 										si = t.find(b, 0, r.startContainer);
       
  9836 										ei = t.find(b, 0, r.endContainer);
       
  9837 									}
  9663 								} else {
  9838 								} else {
  9664 									tr = d.body.createTextRange();
  9839 									tr = d.body.createTextRange();
  9665 									tr.moveToElementText(b);
  9840 									tr.moveToElementText(b);
  9666 									tr.collapse(1);
  9841 									tr.collapse(1);
  9667 									bp = tr.move('character', c) * -1;
  9842 									bp = tr.move('character', c) * -1;
  9694 			}
  9869 			}
  9695 
  9870 
  9696 			// Restore selection
  9871 			// Restore selection
  9697 			if (si != -2) {
  9872 			if (si != -2) {
  9698 				if (!isIE) {
  9873 				if (!isIE) {
  9699 					bl = d.getElementsByTagName(ed.settings.element)[0];
  9874 					bl = b.getElementsByTagName(ed.settings.element)[0];
  9700 					r = d.createRange();
  9875 					r = d.createRange();
  9701 
  9876 
  9702 					// Select last location or generated block
  9877 					// Select last location or generated block
  9703 					if (si != -1)
  9878 					if (si != -1)
  9704 						r.setStart(t.find(b, 1, si), so);
  9879 						r.setStart(t.find(b, 1, si), so);
  9916 				bef.innerHTML = '<br />';
 10091 				bef.innerHTML = '<br />';
  9917 
 10092 
  9918 			if (isEmpty(aft))
 10093 			if (isEmpty(aft))
  9919 				aft.innerHTML = isOpera ? '&nbsp;' : '<br />'; // Extra space for Opera so that the caret can move there
 10094 				aft.innerHTML = isOpera ? '&nbsp;' : '<br />'; // Extra space for Opera so that the caret can move there
  9920 
 10095 
  9921 			// Opera needs this one backwards
 10096 			// Opera needs this one backwards for older versions
  9922 			if (isOpera) {
 10097 			if (isOpera && parseFloat(opera.version()) < 9.5) {
  9923 				r.insertNode(bef);
 10098 				r.insertNode(bef);
  9924 				r.insertNode(aft);
 10099 				r.insertNode(aft);
  9925 			} else {
 10100 			} else {
  9926 				r.insertNode(aft);
 10101 				r.insertNode(aft);
  9927 				r.insertNode(bef);
 10102 				r.insertNode(bef);
 10127 			});
 10302 			});
 10128 
 10303 
 10129 			// Fix for bug #1897785, #1898007
 10304 			// Fix for bug #1897785, #1898007
 10130 			if (tinymce.isIE) {
 10305 			if (tinymce.isIE) {
 10131 				c.onShowMenu.add(function() {
 10306 				c.onShowMenu.add(function() {
 10132 					var s = ed.selection, n = s.getNode();
 10307 					bm = ed.selection.getBookmark(1);
 10133 
       
 10134 					if (n.nodeName == 'IMG')
       
 10135 						bm = s.getBookmark();
       
 10136 					else
       
 10137 						bm = 0;
       
 10138 				});
 10308 				});
 10139 
 10309 
 10140 				c.onHideMenu.add(function() {
 10310 				c.onHideMenu.add(function() {
 10141 					if (bm)
 10311 					if (bm)
 10142 						ed.selection.moveToBookmark(bm);
 10312 						ed.selection.moveToBookmark(bm);
 10281 
 10451 
 10282 			return c;
 10452 			return c;
 10283 		},
 10453 		},
 10284 
 10454 
 10285 		createColorSplitButton : function(id, s, cc) {
 10455 		createColorSplitButton : function(id, s, cc) {
 10286 			var t = this, ed = t.editor, cmd, c, cls;
 10456 			var t = this, ed = t.editor, cmd, c, cls, bm;
 10287 
 10457 
 10288 			if (t.get(id))
 10458 			if (t.get(id))
 10289 				return null;
 10459 				return null;
 10290 
 10460 
 10291 			s.title = ed.translate(s.title);
 10461 			s.title = ed.translate(s.title);
 10318 
 10488 
 10319 			// Remove the menu element when the editor is removed
 10489 			// Remove the menu element when the editor is removed
 10320 			ed.onRemove.add(function() {
 10490 			ed.onRemove.add(function() {
 10321 				c.destroy();
 10491 				c.destroy();
 10322 			});
 10492 			});
       
 10493 
       
 10494 			// Fix for bug #1897785, #1898007
       
 10495 			if (tinymce.isIE) {
       
 10496 				c.onShowMenu.add(function() {
       
 10497 					bm = ed.selection.getBookmark(1);
       
 10498 				});
       
 10499 
       
 10500 				c.onHideMenu.add(function() {
       
 10501 					if (bm) {
       
 10502 						ed.selection.moveToBookmark(bm);
       
 10503 						bm = 0;
       
 10504 					}
       
 10505 				});
       
 10506 			}
 10323 
 10507 
 10324 			return t.add(c);
 10508 			return t.add(c);
 10325 		},
 10509 		},
 10326 
 10510 
 10327 		createToolbar : function(id, s, cc) {
 10511 		createToolbar : function(id, s, cc) {
 10398 					s.center = true;
 10582 					s.center = true;
 10399 					s.help = false;
 10583 					s.help = false;
 10400 					s.dialogWidth = s.width + 'px';
 10584 					s.dialogWidth = s.width + 'px';
 10401 					s.dialogHeight = s.height + 'px';
 10585 					s.dialogHeight = s.height + 'px';
 10402 					s.scroll = s.scrollbars || false;
 10586 					s.scroll = s.scrollbars || false;
 10403 				} else
 10587 				}
 10404 					s.modal = s.alwaysRaised = s.dialog = s.centerscreen = s.dependent = true;
       
 10405 			}
 10588 			}
 10406 
 10589 
 10407 			// Build features string
 10590 			// Build features string
 10408 			each(s, function(v, k) {
 10591 			each(s, function(v, k) {
 10409 				if (tinymce.is(v, 'boolean'))
 10592 				if (tinymce.is(v, 'boolean'))