]> git.donarmstrong.com Git - roundcube.git/blobdiff - program/js/tiny_mce/tiny_mce_src.js
Imported Upstream version 0.2~stable
[roundcube.git] / program / js / tiny_mce / tiny_mce_src.js
index a4fa1a61ed889c554fef0879b45027e4307836c8..eeaab3b1e4643b979022361cf7b1cddb5d699c0c 100644 (file)
@@ -3,25 +3,26 @@
 \r
 var tinymce = {\r
        majorVersion : '3',\r
-       minorVersion : '0.6.2',\r
-       releaseDate : '2008-04-07',\r
+       minorVersion : '1.0.1',\r
+       releaseDate : '2008-06-18',\r
 \r
        _init : function() {\r
-               var t = this, ua = navigator.userAgent, i, nl, n, base;\r
+               var t = this, d = document, w = window, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;\r
 \r
                // Browser checks\r
-               t.isOpera = window.opera && opera.buildNumber;\r
+               t.isOpera = w.opera && opera.buildNumber;\r
                t.isWebKit = /WebKit/.test(ua);\r
-               t.isOldWebKit = t.isWebKit && !window.getSelection().getRangeAt;\r
-               t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(navigator.appName);\r
+               t.isOldWebKit = t.isWebKit && !w.getSelection().getRangeAt;\r
+               t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);\r
                t.isIE6 = t.isIE && /MSIE [56]/.test(ua);\r
                t.isGecko = !t.isWebKit && /Gecko/.test(ua);\r
                t.isMac = ua.indexOf('Mac') != -1;\r
 \r
                // TinyMCE .NET webcontrol might be setting the values for TinyMCE\r
-               if (window.tinyMCEPreInit) {\r
+               if (w.tinyMCEPreInit) {\r
                        t.suffix = tinyMCEPreInit.suffix;\r
                        t.baseURL = tinyMCEPreInit.base;\r
+                       t.query = tinyMCEPreInit.query;\r
                        return;\r
                }\r
 \r
@@ -29,10 +30,15 @@ var tinymce = {
                t.suffix = '';\r
 \r
                // If base element found, add that infront of baseURL\r
-               nl = document.getElementsByTagName('base');\r
+               nl = d.getElementsByTagName('base');\r
                for (i=0; i<nl.length; i++) {\r
-                       if (nl[i].href)\r
-                               base = nl[i].href;\r
+                       if (v = nl[i].href) {\r
+                               // Host only value like http://site.com or http://site.com:8008\r
+                               if (/^https?:\/\/[^\/]+$/.test(v))\r
+                                       v += '/';\r
+\r
+                               base = v ? v.match(/.*\//)[0] : ''; // Get only directory\r
+                       }\r
                }\r
 \r
                function getBase(n) {\r
@@ -40,6 +46,9 @@ var tinymce = {
                                if (/_(src|dev)\.js/g.test(n.src))\r
                                        t.suffix = '_src';\r
 \r
+                               if ((p = n.src.indexOf('?')) != -1)\r
+                                       t.query = n.src.substring(p + 1);\r
+\r
                                t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));\r
 \r
                                // If path to script is relative and a base href was found add that one infront\r
@@ -53,14 +62,14 @@ var tinymce = {
                };\r
 \r
                // Check document\r
-               nl = document.getElementsByTagName('script');\r
+               nl = d.getElementsByTagName('script');\r
                for (i=0; i<nl.length; i++) {\r
                        if (getBase(nl[i]))\r
                                return;\r
                }\r
 \r
                // Check head\r
-               n = document.getElementsByTagName('head')[0];\r
+               n = d.getElementsByTagName('head')[0];\r
                if (n) {\r
                        nl = n.getElementsByTagName('script');\r
                        for (i=0; i<nl.length; i++) {\r
@@ -303,40 +312,71 @@ var tinymce = {
        },\r
 \r
        addUnload : function(f, s) {\r
-               var t = this, w = window, unload;\r
+               var t = this, w = window;\r
 \r
                f = {func : f, scope : s || this};\r
 \r
                if (!t.unloads) {\r
-                       unload = function() {\r
+                       function unload() {\r
                                var li = t.unloads, o, n;\r
 \r
-                               // Call unload handlers\r
-                               for (n in li) {\r
-                                       o = li[n];\r
+                               if (li) {\r
+                                       // Call unload handlers\r
+                                       for (n in li) {\r
+                                               o = li[n];\r
+\r
+                                               if (o && o.func)\r
+                                                       o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy\r
+                                       }\r
+\r
+                                       // Detach unload function\r
+                                       if (w.detachEvent) {\r
+                                               w.detachEvent('onbeforeunload', fakeUnload);\r
+                                               w.detachEvent('onunload', unload);\r
+                                       } else if (w.removeEventListener)\r
+                                               w.removeEventListener('unload', unload, false);\r
 \r
-                                       if (o && o.func)\r
-                                               o.func.call(o.scope, 1); // Send in one arg to distinct unload and user destroy\r
+                                       // Destroy references\r
+                                       t.unloads = o = li = w = unload = null;\r
+\r
+                                       // Run garbarge collector on IE\r
+                                       if (window.CollectGarbage)\r
+                                               window.CollectGarbage();\r
                                }\r
+                       };\r
 \r
-                               // Detach unload function\r
-                               if (w.detachEvent)\r
-                                       w.detachEvent('onunload', unload);\r
-                               else if (w.removeEventListener)\r
-                                       w.removeEventListener('unload', unload, false);\r
+                       function fakeUnload() {\r
+                               var d = document;\r
 \r
-                               // Destroy references\r
-                               o = li = w = unload = null;\r
+                               // Is there things still loading, then do some magic\r
+                               if (d.readyState == 'interactive') {\r
+                                       function stop() {\r
+                                               // Prevent memory leak\r
+                                               d.detachEvent('onstop', stop);\r
 \r
-                               // Run garbarge collector on IE\r
-                               if (window.CollectGarbage)\r
-                                       window.CollectGarbage();\r
+                                               // Call unload handler\r
+                                               unload();\r
+\r
+                                               d = null;\r
+                                       };\r
+\r
+                                       // Fire unload when the currently loading page is stopped\r
+                                       d.attachEvent('onstop', stop);\r
+\r
+                                       // Remove onstop listener after a while to prevent the unload function\r
+                                       // to execute if the user presses cancel in an onbeforeunload\r
+                                       // confirm dialog and then presses the browser stop button\r
+                                       window.setTimeout(function() {\r
+                                               d.detachEvent('onstop', stop);\r
+                                       }, 0);\r
+                               }\r
                        };\r
 \r
                        // Attach unload handler\r
-                       if (w.attachEvent)\r
+                       if (w.attachEvent) {\r
                                w.attachEvent('onunload', unload);\r
-                       else if (w.addEventListener)\r
+                               w.attachEvent('onbeforeunload', fakeUnload);\r
+                       } else if (w.addEventListener)\r
                                w.addEventListener('unload', unload, false);\r
 \r
                        // Setup initial unload handler array\r
@@ -362,7 +402,21 @@ var tinymce = {
        },\r
 \r
        explode : function(s, d) {\r
-               return tinymce.map(s.split(d || ','), tinymce.trim);\r
+               return s ? tinymce.map(s.split(d || ','), tinymce.trim) : s;\r
+       },\r
+\r
+       _addVer : function(u) {\r
+               var v;\r
+\r
+               if (!this.query)\r
+                       return u;\r
+\r
+               v = (u.indexOf('?') == -1 ? '?' : '&') + this.query;\r
+\r
+               if (u.indexOf('#') == -1)\r
+                       return u + v;\r
+\r
+               return u.replace('#', v + '#');\r
        }\r
 \r
        };\r
@@ -827,19 +881,24 @@ tinymce.create('static tinymce.util.XHR', {
 \r
                        x.send(o.data);\r
 \r
-                       // Wait for response, onReadyStateChange can not be used since it leaks memory in IE\r
-                       t = w.setInterval(function() {\r
-                               if (x.readyState == 4 || c++ > 10000) {\r
-                                       w.clearInterval(t);\r
-\r
+                       function ready() {\r
+                               if (!o.async || x.readyState == 4 || c++ > 10000) {\r
                                        if (o.success && c < 10000 && x.status == 200)\r
                                                o.success.call(o.success_scope, '' + x.responseText, x, o);\r
                                        else if (o.error)\r
                                                o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);\r
 \r
                                        x = null;\r
-                               }\r
-                       }, 10);\r
+                               } else\r
+                                       w.setTimeout(ready, 10);\r
+                       };\r
+\r
+                       // Syncronous request\r
+                       if (!o.async)\r
+                               return ready();\r
+\r
+                       // Wait for response, onReadyStateChange can not be used since it leaks memory in IE\r
+                       t = w.setTimeout(ready, 10);\r
                }\r
 \r
                }\r
@@ -1016,7 +1075,7 @@ tinymce.create('static tinymce.util.XHR', {
                                        }\r
 \r
                                        each(na.split(','), function(v) {\r
-                                               if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName == v)) {\r
+                                               if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName.toUpperCase() == v)) {\r
                                                        s = true;\r
                                                        return false; // Break loop\r
                                                }\r
@@ -1042,7 +1101,7 @@ tinymce.create('static tinymce.util.XHR', {
                get : function(e) {\r
                        var n;\r
 \r
-                       if (this.doc && typeof(e) == 'string') {\r
+                       if (e && this.doc && typeof(e) == 'string') {\r
                                n = e;\r
                                e = this.doc.getElementById(e);\r
 \r
@@ -1408,8 +1467,9 @@ tinymce.create('static tinymce.util.XHR', {
 \r
                                switch (n) {\r
                                        case "style":\r
+                                               // No mce_style for elements with these since they might get resized by the user\r
                                                if (s.keep_values) {\r
-                                                       if (v)\r
+                                                       if (v && !t._isRes(v))\r
                                                                e.setAttribute('mce_style', v, 2);\r
                                                        else\r
                                                                e.removeAttribute('mce_style', 2);\r
@@ -1432,6 +1492,10 @@ tinymce.create('static tinymce.util.XHR', {
                                                }\r
 \r
                                                break;\r
+                                       \r
+                                       case "shape":\r
+                                               e.setAttribute('mce_style', v);\r
+                                               break;\r
                                }\r
 \r
                                if (is(v) && v !== null && v.length !== 0)\r
@@ -1458,14 +1522,14 @@ tinymce.create('static tinymce.util.XHR', {
 \r
                        e = t.get(e);\r
 \r
-                       if (!e)\r
+                       if (!e || e.nodeType !== 1)\r
                                return false;\r
 \r
                        if (!is(dv))\r
                                dv = "";\r
 \r
                        // Try the mce variant for these\r
-                       if (/^(src|href|style|coords)$/.test(n)) {\r
+                       if (/^(src|href|style|coords|shape)$/.test(n)) {\r
                                v = e.getAttribute("mce_" + n);\r
 \r
                                if (v)\r
@@ -1499,7 +1563,7 @@ tinymce.create('static tinymce.util.XHR', {
                                        if (v) {\r
                                                v = t.serializeStyle(t.parseStyle(v));\r
 \r
-                                               if (t.settings.keep_values)\r
+                                               if (t.settings.keep_values && !t._isRes(v))\r
                                                        e.setAttribute('mce_style', v);\r
                                        }\r
 \r
@@ -1536,12 +1600,19 @@ tinymce.create('static tinymce.util.XHR', {
                                                break;\r
 \r
                                        case 'tabindex':\r
-                                               // IE returns 32768 as default value\r
+                                               // IE returns default value\r
                                                if (v === 32768)\r
                                                        v = '';\r
 \r
                                                break;\r
 \r
+                                       case 'maxlength':\r
+                                               // IE returns  default value\r
+                                               if (v === 2147483647)\r
+                                                       v = '';\r
+\r
+                                               break;\r
+\r
                                        case 'shape':\r
                                                v = v.toLowerCase();\r
                                                break;\r
@@ -1652,10 +1723,13 @@ tinymce.create('static tinymce.util.XHR', {
                                delete o[c];\r
                        };\r
 \r
+                       st = st.replace(/&(#?[a-z0-9]+);/g, '&$1_MCE_SEMI_'); // Protect entities\r
+\r
                        each(st.split(';'), function(v) {\r
                                var sv, ur = [];\r
 \r
                                if (v) {\r
+                                       v = v.replace(/_MCE_SEMI_/g, ';'); // Restore entities\r
                                        v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});\r
                                        v = v.split(':');\r
                                        sv = tinymce.trim(v[1]);\r
@@ -1667,7 +1741,7 @@ tinymce.create('static tinymce.util.XHR', {
 \r
                                        if (s.url_converter) {\r
                                                sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {\r
-                                                       return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null)) + ')';\r
+                                                       return 'url(' + s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null) + ')';\r
                                                });\r
                                        }\r
 \r
@@ -1697,6 +1771,9 @@ tinymce.create('static tinymce.util.XHR', {
 \r
                        each(o, function(v, k) {\r
                                if (k && v) {\r
+                                       if (tinymce.isGecko && k.indexOf('-moz-') === 0)\r
+                                               return;\r
+\r
                                        switch (k) {\r
                                                case 'color':\r
                                                case 'background-color':\r
@@ -1722,7 +1799,7 @@ tinymce.create('static tinymce.util.XHR', {
                                        return;\r
 \r
                                t.files[u] = true;\r
-                               t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : u});\r
+                               t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : tinymce._addVer(u)});\r
                        });\r
                },\r
 \r
@@ -1917,23 +1994,51 @@ tinymce.create('static tinymce.util.XHR', {
                        if (tinymce.isGecko) {\r
                                h = h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi, '<$1b$2>');\r
                                h = h.replace(/<(\/?)em>|<em( [^>]+)>/gi, '<$1i$2>');\r
-                       }\r
+                       } else if (isIE)\r
+                               h = h.replace(/&apos;/g, '&#39;'); // IE can't handle apos\r
 \r
                        // Fix some issues\r
                        h = h.replace(/<a( )([^>]+)\/>|<a\/>/gi, '<a$1$2></a>'); // Force open\r
 \r
                        // Store away src and href in mce_src and mce_href since browsers mess them up\r
                        if (s.keep_values) {\r
-                               // Wrap scripts in comments for serialization purposes\r
-                               if (h.indexOf('<script') !== -1) {\r
-                                       h = h.replace(/<script>/g, '<script type="text/javascript">');\r
-                                       h = h.replace(/<script(|[^>]+)>(\s*<!--|\/\/\s*<\[CDATA\[)?[\r\n]*/g, '<mce:script$1><!--\n');\r
-                                       h = h.replace(/\s*(\/\/\s*-->|\/\/\s*]]>)?<\/script>/g, '\n// --></mce:script>');\r
-                                       h = h.replace(/<mce:script(|[^>]+)><!--\n\/\/ --><\/mce:script>/g, '<mce:script$1></mce:script>');\r
+                               // Wrap scripts and styles in comments for serialization purposes\r
+                               if (/<script|style/.test(h)) {\r
+                                       function trim(s) {\r
+                                               // Remove prefix and suffix code for element\r
+                                               s = s.replace(/^[\r\n]*|[\r\n]*$/g, '');\r
+                                               s = s.replace(/^\s*(\/\/\s*<!--|\/\/\s*<\[CDATA\[|<!--|<\[CDATA\[)[\r\n]*/g, '');\r
+                                               s = s.replace(/\s*(\/\/\s*\]\]>|\/\/\s*-->|\]\]>|-->)\s*$/g, '');\r
+\r
+                                               return s;\r
+                                       };\r
+\r
+                                       // Preserve script elements\r
+                                       h = h.replace(/<script([^>]+|)>([\s\S]*?)<\/script>/g, function(v, a, b) {\r
+                                               // Remove prefix and suffix code for script element\r
+                                               b = trim(b);\r
+\r
+                                               // Force type attribute\r
+                                               if (!a)\r
+                                                       a = ' type="text/javascript"';\r
+\r
+                                               // Wrap contents in a comment\r
+                                               if (b)\r
+                                                       b = '<!--\n' + b + '\n// -->';\r
+\r
+                                               // Output fake element\r
+                                               return '<mce:script' + a + '>' + b + '</mce:script>';\r
+                                       });\r
+\r
+                                       // Preserve style elements\r
+                                       h = h.replace(/<style([^>]+|)>([\s\S]*?)<\/style>/g, function(v, a, b) {\r
+                                               b = trim(b);\r
+                                               return '<mce:style' + a + '><!--\n' + b + '\n--></mce:style><style' + a + ' mce_bogus="1">' + b + '</style>';\r
+                                       });\r
                                }\r
 \r
                                // Process all tags with src, href or style\r
-                               h = h.replace(/<([\w:]+) [^>]*(src|href|style|coords)[^>]*>/gi, function(a, n) {\r
+                               h = h.replace(/<([\w:]+) [^>]*(src|href|style|shape|coords)[^>]*>/gi, function(a, n) {\r
                                        function handle(m, b, c) {\r
                                                var u = c;\r
 \r
@@ -1946,6 +2051,10 @@ tinymce.create('static tinymce.util.XHR', {
                                                        //if (isIE)\r
                                                        //      u = t.serializeStyle(t.parseStyle(u));\r
 \r
+                                                       // No mce_style for elements with these since they might get resized by the user\r
+                                                       if (t._isRes(c))\r
+                                                               return m;\r
+\r
                                                        if (s.hex_colors) {\r
                                                                u = u.replace(/rgb\([^\)]+\)/g, function(v) {\r
                                                                        return t.toHex(v);\r
@@ -1957,7 +2066,7 @@ tinymce.create('static tinymce.util.XHR', {
                                                                        return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n)) + ')';\r
                                                                });\r
                                                        }\r
-                                               } else if (b != 'coords') {\r
+                                               } else if (b != 'coords' && b != 'shape') {\r
                                                        if (s.url_converter)\r
                                                                u = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n));\r
                                                }\r
@@ -1965,10 +2074,10 @@ tinymce.create('static tinymce.util.XHR', {
                                                return ' ' + b + '="' + c + '" mce_' + b + '="' + u + '"';\r
                                        };\r
 \r
-                                       a = a.replace(/ (src|href|style|coords)=[\"]([^\"]+)[\"]/gi, handle); // W3C\r
-                                       a = a.replace(/ (src|href|style|coords)=[\']([^\']+)[\']/gi, handle); // W3C\r
+                                       a = a.replace(/ (src|href|style|coords|shape)=[\"]([^\"]+)[\"]/gi, handle); // W3C\r
+                                       a = a.replace(/ (src|href|style|coords|shape)=[\']([^\']+)[\']/gi, handle); // W3C\r
 \r
-                                       return a.replace(/ (src|href|style|coords)=([^\s\"\'>]+)/gi, handle); // IE\r
+                                       return a.replace(/ (src|href|style|coords|shape)=([^\s\"\'>]+)/gi, handle); // IE\r
                                });\r
                        }\r
 \r
@@ -2083,7 +2192,7 @@ tinymce.create('static tinymce.util.XHR', {
 \r
                        n = n.nodeName || n;\r
 \r
-                       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);\r
+                       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);\r
                },\r
 \r
                // #if !jquery\r
@@ -2100,11 +2209,12 @@ tinymce.create('static tinymce.util.XHR', {
                                }\r
 \r
                                // Fix IE psuedo leak for elements since replacing elements if fairly common\r
-                               if (isIE && o.nodeType === 1) {\r
+                               // Will break parentNode for some unknown reason\r
+       /*                      if (isIE && o.nodeType === 1) {\r
                                        o.parentNode.insertBefore(n, o);\r
                                        o.outerHTML = '';\r
                                        return n;\r
-                               }\r
+                               }*/\r
 \r
                                return o.parentNode.replaceChild(n, o);\r
                        });\r
@@ -2253,6 +2363,11 @@ tinymce.create('static tinymce.util.XHR', {
                        // Manual destroy then remove unload handler\r
                        if (!s)\r
                                tinymce.removeUnload(t.destroy);\r
+               },\r
+\r
+               _isRes : function(c) {\r
+                       // Is live resizble element\r
+                       return /^(top|left|bottom|right|width|height)/i.test(c) || /;\s*(top|left|bottom|right|width|height)/i.test(c);\r
                }\r
 \r
                /*\r
@@ -2493,8 +2608,10 @@ tinymce.create('static tinymce.util.XHR', {
                        var t;\r
 \r
                        // No need since the document is already loaded\r
-                       if (window.tinyMCE_GZ && tinyMCE_GZ.loaded)\r
+                       if (window.tinyMCE_GZ && tinyMCE_GZ.loaded) {\r
+                               Event.domLoaded = 1;\r
                                return;\r
+                       }\r
 \r
                        if (isIE && document.location.protocol != 'https:') {\r
                                // Fake DOMContentLoaded on IE\r
@@ -2669,6 +2786,10 @@ tinymce.create('static tinymce.util.XHR', {
 /* file:jscripts/tiny_mce/classes/dom/Selection.js */\r
 \r
 (function() {\r
+       function trimNl(s) {\r
+               return s.replace(/[\n\r]+/g, '');\r
+       };\r
+\r
        // Shorten names\r
        var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each;\r
 \r
@@ -2718,15 +2839,13 @@ tinymce.create('static tinymce.util.XHR', {
                },\r
 \r
                setContent : function(h, s) {\r
-                       var t = this, r = t.getRng(), d;\r
+                       var t = this, r = t.getRng(), d = t.win.document;\r
 \r
                        s = s || {format : 'html'};\r
                        s.set = true;\r
                        h = t.dom.processHTML(h);\r
 \r
                        if (r.insertNode) {\r
-                               d = t.win.document;\r
-\r
                                // Gecko has a bug where if you insert &nbsp; using InsertHTML it will insert a space instead\r
                                // So we simply check if the input is HTML or text and then insert text using the insertNode method\r
                                if (tinymce.isGecko && h.indexOf('<') == -1) {\r
@@ -2748,10 +2867,13 @@ tinymce.create('static tinymce.util.XHR', {
                                        r.insertNode(t.getRng().createContextualFragment(h));\r
                                }\r
                        } else {\r
-                               if (r.item)\r
-                                       r.item(0).outerHTML = h;\r
-                               else\r
-                                       r.pasteHTML(h);\r
+                               if (r.item) {\r
+                                       // Delete content and get caret text selection\r
+                                       d.execCommand('Delete', false, null);\r
+                                       r = t.getRng();\r
+                               }\r
+\r
+                               r.pasteHTML(h);\r
                        }\r
                },\r
 \r
@@ -2766,7 +2888,7 @@ tinymce.create('static tinymce.util.XHR', {
                                r.collapse(1);\r
                                e = r.parentElement();\r
 \r
-                               if (e.nodeName == 'BODY')\r
+                               if (e && e.nodeName == 'BODY')\r
                                        return e.firstChild;\r
 \r
                                return e;\r
@@ -2791,7 +2913,7 @@ tinymce.create('static tinymce.util.XHR', {
                                r.collapse(0);\r
                                e = r.parentElement();\r
 \r
-                               if (e.nodeName == 'BODY')\r
+                               if (e && e.nodeName == 'BODY')\r
                                        return e.lastChild;\r
 \r
                                return e;\r
@@ -2886,7 +3008,7 @@ tinymce.create('static tinymce.util.XHR', {
                                                return d;\r
                                        }\r
 \r
-                                       p += tinymce.trim(n.nodeValue || '').length;\r
+                                       p += trimNl(n.nodeValue || '').length;\r
                                }\r
 \r
                                return null;\r
@@ -2900,7 +3022,7 @@ tinymce.create('static tinymce.util.XHR', {
                                        return {scrollX : sx, scrollY : sy};\r
 \r
                                // Count whitespace before\r
-                               (s.anchorNode.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});\r
+                               trimNl(s.anchorNode.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});\r
 \r
                                return {\r
                                        start : Math.max(e.start + s.anchorOffset - wb, 0),\r
@@ -2913,8 +3035,8 @@ tinymce.create('static tinymce.util.XHR', {
                                e = getPos(ro, r.startContainer, r.endContainer);\r
 \r
                                // Count whitespace before start and end container\r
-                               (r.startContainer.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});\r
-                               (r.endContainer.nodeValue || '').replace(/^\s+/, function(a) {wa = a.length;});\r
+                               //(r.startContainer.nodeValue || '').replace(/^\s+/, function(a) {wb = a.length;});\r
+                               //(r.endContainer.nodeValue || '').replace(/^\s+/, function(a) {wa = a.length;});\r
 \r
                                if (!e)\r
                                        return {scrollX : sx, scrollY : sy};\r
@@ -2939,10 +3061,10 @@ tinymce.create('static tinymce.util.XHR', {
                                        wa = wb = 0;\r
 \r
                                        nv = n.nodeValue || '';\r
-                                       nv.replace(/^\s+[^\s]/, function(a) {wb = a.length - 1;});\r
-                                       nv.replace(/[^\s]\s+$/, function(a) {wa = a.length - 1;});\r
+                                       //nv.replace(/^\s+[^\s]/, function(a) {wb = a.length - 1;});\r
+                                       //nv.replace(/[^\s]\s+$/, function(a) {wa = a.length - 1;});\r
 \r
-                                       nvl = tinymce.trim(nv).length;\r
+                                       nvl = trimNl(nv).length;\r
                                        p += nvl;\r
 \r
                                        if (p >= sp && !d.startNode) {\r
@@ -3295,7 +3417,7 @@ tinymce.create('static tinymce.util.XHR', {
                },\r
 \r
                writeComment : function(v) {\r
-                       this.node.appendChild(this.doc.createComment(v));\r
+                       this.node.appendChild(this.doc.createComment(v.replace(/\-\-/g, ' ')));\r
                },\r
 \r
                getContent : function() {\r
@@ -3945,43 +4067,24 @@ tinymce.create('static tinymce.util.XHR', {
                // Internal functions\r
 \r
                _postProcess : function(o) {\r
-                       var t = this, s = t.settings, h = o.content, sc = [], p, l;\r
+                       var t = this, s = t.settings, h = o.content, sc = [], p;\r
 \r
                        if (o.format == 'html') {\r
                                // Protect some elements\r
                                p = t._protect({\r
                                        content : h,\r
                                        patterns : [\r
-                                               /(<script[^>]*>)(.*?)(<\/script>)/g,\r
-                                               /(<style[^>]*>)(.*?)(<\/style>)/g,\r
-                                               /(<pre[^>]*>)(.*?)(<\/pre>)/g\r
+                                               {pattern : /(<script[^>]*>)(.*?)(<\/script>)/g},\r
+                                               {pattern : /(<style[^>]*>)(.*?)(<\/style>)/g},\r
+                                               {pattern : /(<pre[^>]*>)(.*?)(<\/pre>)/g, encode : 1}\r
                                        ]\r
                                });\r
 \r
                                h = p.content;\r
 \r
                                // Entity encode\r
-                               if (s.entity_encoding !== 'raw') {\r
-                                       if (s.entity_encoding.indexOf('named') != -1) {\r
-                                               t.setEntities(s.entities);\r
-                                               l = t.entityLookup;\r
-\r
-                                               h = h.replace(t.entitiesRE, function(a) {\r
-                                                       var v;\r
-\r
-                                                       if (v = l[a])\r
-                                                               a = '&' + v + ';';\r
-\r
-                                                       return a;\r
-                                               });\r
-                                       }\r
-\r
-                                       if (s.entity_encoding.indexOf('numeric') != -1) {\r
-                                               h = h.replace(/[\u007E-\uFFFF]/g, function(a) {\r
-                                                       return '&#' + a.charCodeAt(0) + ';';\r
-                                               });\r
-                                       }\r
-                               }\r
+                               if (s.entity_encoding !== 'raw')\r
+                                       h = t._encode(h);\r
 \r
                                // Use BR instead of &nbsp; padded P elements inside editor and use <p>&nbsp;</p> outside editor\r
 /*                             if (o.set)\r
@@ -4187,6 +4290,8 @@ tinymce.create('static tinymce.util.XHR', {
                },\r
 \r
                _protect : function(o) {\r
+                       var t = this;\r
+\r
                        o.items = o.items || [];\r
 \r
                        function enc(s) {\r
@@ -4212,8 +4317,13 @@ tinymce.create('static tinymce.util.XHR', {
                        };\r
 \r
                        each(o.patterns, function(p) {\r
-                               o.content = dec(enc(o.content).replace(p, function(x, a, b, c) {\r
-                                       o.items.push(dec(b));\r
+                               o.content = dec(enc(o.content).replace(p.pattern, function(x, a, b, c) {\r
+                                       b = dec(b);\r
+\r
+                                       if (p.encode)\r
+                                               b = t._encode(b);\r
+\r
+                                       o.items.push(b);\r
                                        return a + '<!--mce:' + (o.items.length - 1) + '-->' + c;\r
                                }));\r
                        });\r
@@ -4231,6 +4341,35 @@ tinymce.create('static tinymce.util.XHR', {
                        return h;\r
                },\r
 \r
+               _encode : function(h) {\r
+                       var t = this, s = t.settings, l;\r
+\r
+                       // Entity encode\r
+                       if (s.entity_encoding !== 'raw') {\r
+                               if (s.entity_encoding.indexOf('named') != -1) {\r
+                                       t.setEntities(s.entities);\r
+                                       l = t.entityLookup;\r
+\r
+                                       h = h.replace(t.entitiesRE, function(a) {\r
+                                               var v;\r
+\r
+                                               if (v = l[a])\r
+                                                       a = '&' + v + ';';\r
+\r
+                                               return a;\r
+                                       });\r
+                               }\r
+\r
+                               if (s.entity_encoding.indexOf('numeric') != -1) {\r
+                                       h = h.replace(/[\u007E-\uFFFF]/g, function(a) {\r
+                                               return '&#' + a.charCodeAt(0) + ';';\r
+                                       });\r
+                               }\r
+                       }\r
+\r
+                       return h;\r
+               },\r
+\r
                _setup : function() {\r
                        var t = this, s = this.settings;\r
 \r
@@ -4244,7 +4383,7 @@ tinymce.create('static tinymce.util.XHR', {
                        t.addValidChildRules(s.valid_child_elements);\r
 \r
                        if (s.invalid_elements)\r
-                               t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(',', '|').toLowerCase()) + ')$');\r
+                               t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(/,/g, '|').toLowerCase()) + ')$');\r
 \r
                        if (s.attrib_value_filter)\r
                                t.attribValueFilter = s.attribValueFilter;\r
@@ -4367,7 +4506,7 @@ tinymce.create('static tinymce.util.XHR', {
                        function loadScript(u) {\r
                                if (tinymce.dom.Event.domLoaded || t.settings.strict_mode) {\r
                                        tinymce.util.XHR.send({\r
-                                               url : u,\r
+                                               url : tinymce._addVer(u),\r
                                                error : t.settings.error,\r
                                                async : false,\r
                                                success : function(co) {\r
@@ -4375,7 +4514,7 @@ tinymce.create('static tinymce.util.XHR', {
                                                }\r
                                        });\r
                                } else\r
-                                       document.write('<script type="text/javascript" src="' + u + '"></script>');\r
+                                       document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"></script>');\r
                        };\r
 \r
                        if (!tinymce.is(u, 'string')) {\r
@@ -4512,7 +4651,7 @@ tinymce.create('static tinymce.util.XHR', {
                                                ol += 'tinymce.dom.ScriptLoader._onLoad(this,\'' + u + '\',' + ix + ');"';\r
                                        }\r
 \r
-                                       document.write('<script type="text/javascript" src="' + u + '"' + ol + '></script>');\r
+                                       document.write('<script type="text/javascript" src="' + tinymce._addVer(u) + '"' + ol + '></script>');\r
 \r
                                        if (!o.func)\r
                                                done(o);\r
@@ -4842,9 +4981,6 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                        this.onShowMenu = new tinymce.util.Dispatcher(this);\r
                        this.onHideMenu = new tinymce.util.Dispatcher(this);\r
                        this.classPrefix = 'mceMenu';\r
-\r
-                       // Fix for odd IE bug: #1903622\r
-                       this.fixIE = tinymce.isIE && DOM.win.top != DOM.win;\r
                },\r
 \r
                createMenu : function(s) {\r
@@ -4934,7 +5070,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                        t.element.update();\r
 \r
                        t.isMenuVisible = 1;\r
-                       t.mouseClickFunc = Event.add(co, t.fixIE ? 'mousedown' : 'click', function(e) {\r
+                       t.mouseClickFunc = Event.add(co, 'click', function(e) {\r
                                var m;\r
 \r
                                e = e.target;\r
@@ -4991,6 +5127,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                        if (s.keyboard_focus) {\r
                                Event.add(co, 'keydown', t._keyHandler, t);\r
                                DOM.select('a', 'menu_' + t.id)[0].focus(); // Select first link\r
+                               t._focusIdx = 0;\r
                        }\r
                },\r
 \r
@@ -5001,7 +5138,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                                return;\r
 \r
                        Event.remove(co, 'mouseover', t.mouseOverFunc);\r
-                       Event.remove(co, t.fixIE ? 'mousedown' : 'click', t.mouseClickFunc);\r
+                       Event.remove(co, 'click', t.mouseClickFunc);\r
                        Event.remove(co, 'keydown', t._keyHandler);\r
                        DOM.hide(co);\r
                        t.isMenuVisible = 0;\r
@@ -5079,9 +5216,32 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                // Internal functions\r
 \r
                _keyHandler : function(e) {\r
-                       // Accessibility feature\r
-                       if (e.keyCode == 27)\r
-                               this.hideMenu();\r
+                       var t = this, kc = e.keyCode;\r
+\r
+                       function focus(d) {\r
+                               var i = t._focusIdx + d, e = DOM.select('a', 'menu_' + t.id)[i];\r
+\r
+                               if (e) {\r
+                                       t._focusIdx = i;\r
+                                       e.focus();\r
+                               }\r
+                       };\r
+\r
+                       switch (kc) {\r
+                               case 38:\r
+                                       focus(-1); // Select first link\r
+                                       return;\r
+\r
+                               case 40:\r
+                                       focus(1);\r
+                                       return;\r
+\r
+                               case 13:\r
+                                       return;\r
+\r
+                               case 27:\r
+                                       return this.hideMenu();\r
+                       }\r
                },\r
 \r
                _add : function(tb, o) {\r
@@ -5138,12 +5298,15 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                },\r
 \r
                renderHTML : function() {\r
-                       var cp = this.classPrefix, s = this.settings, h = '<a id="' + this.id + '" href="javascript:;" class="' + cp + ' ' + cp + 'Enabled ' + s['class'] + '" onmousedown="return false;" onclick="return false;" title="' + DOM.encode(s.title) + '">';\r
+                       var cp = this.classPrefix, s = this.settings, h, l;\r
+\r
+                       l = DOM.encode(s.label || '');\r
+                       h = '<a id="' + this.id + '" href="javascript:;" class="' + cp + ' ' + cp + 'Enabled ' + s['class'] + (l ? ' ' + cp + 'Labeled' : '') +'" onmousedown="return false;" onclick="return false;" title="' + DOM.encode(s.title) + '">';\r
 \r
                        if (s.image)\r
-                               h += '<img class="mceIcon" src="' + s.image + '" /></a>';\r
+                               h += '<img class="mceIcon" src="' + s.image + '" />' + l + '</a>';\r
                        else\r
-                               h += '<span class="mceIcon ' + s['class'] + '"></span></a>';\r
+                               h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '') + '</a>';\r
 \r
                        return h;\r
                },\r
@@ -5242,6 +5405,9 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                        if (t.isDisabled() || t.items.length == 0)\r
                                return;\r
 \r
+                       if (t.menu && t.menu.isMenuVisible)\r
+                               return t.hideMenu();\r
+\r
                        if (!t.isMenuRendered) {\r
                                t.renderMenu();\r
                                t.isMenuRendered = true;\r
@@ -5253,7 +5419,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                        m = t.menu;\r
                        m.settings.offset_x = p2.x;\r
                        m.settings.offset_y = p2.y;\r
-                       m.settings.keyboard_focus = t._focused;\r
+                       m.settings.keyboard_focus = !tinymce.isOpera; // Opera is buggy when it comes to auto focus\r
 \r
                        // Select in menu\r
                        if (t.oldID)\r
@@ -5270,11 +5436,17 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
 \r
                        Event.add(DOM.doc, 'mousedown', t.hideMenu, t);\r
                        DOM.addClass(t.id, t.classPrefix + 'Selected');\r
+\r
+                       //DOM.get(t.id + '_text').focus();\r
                },\r
 \r
                hideMenu : function(e) {\r
                        var t = this;\r
 \r
+                       // Prevent double toogles by canceling the mouse click event to the button\r
+                       if (e && e.type == "mousedown" && (e.target.id == t.id + '_text' || e.target.id == t.id + '_open'))\r
+                               return;\r
+\r
                        if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {\r
                                DOM.removeClass(t.id, t.classPrefix + 'Selected');\r
                                Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r
@@ -5298,8 +5470,12 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
 \r
                        m.add({\r
                                title : t.settings.title,\r
-                               'class' : 'mceMenuItemTitle'\r
-                       }).setDisabled(1);\r
+                               'class' : 'mceMenuItemTitle',\r
+                               onclick : function() {\r
+                                       if (t.settings.onselect('') !== false)\r
+                                               t.select(''); // Must be runned after\r
+                               }\r
+                       });\r
 \r
                        each(t.items, function(o) {\r
                                o.id = DOM.uniqueId();\r
@@ -5319,8 +5495,40 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                        var t = this, cp = t.classPrefix;\r
 \r
                        Event.add(t.id, 'click', t.showMenu, t);\r
-                       Event.add(t.id + '_text', 'focus', function() {t._focused = 1;});\r
-                       Event.add(t.id + '_text', 'blur', function() {t._focused = 0;});\r
+                       Event.add(t.id + '_text', 'focus', function(e) {\r
+                               if (!t._focused) {\r
+                                       t.keyDownHandler = Event.add(t.id + '_text', 'keydown', function(e) {\r
+                                               var idx = -1, v, kc = e.keyCode;\r
+\r
+                                               // Find current index\r
+                                               each(t.items, function(v, i) {\r
+                                                       if (t.selectedValue == v.value)\r
+                                                               idx = i;\r
+                                               });\r
+\r
+                                               // Move up/down\r
+                                               if (kc == 38)\r
+                                                       v = t.items[idx - 1];\r
+                                               else if (kc == 40)\r
+                                                       v = t.items[idx + 1];\r
+                                               else if (kc == 13) {\r
+                                                       // Fake select on enter\r
+                                                       v = t.selectedValue;\r
+                                                       t.selectedValue = null; // Needs to be null to fake change\r
+                                                       t.settings.onselect(v);\r
+                                                       return Event.cancel(e);\r
+                                               }\r
+\r
+                                               if (v) {\r
+                                                       t.hideMenu();\r
+                                                       t.select(v.value);\r
+                                               }\r
+                                       });\r
+                               }\r
+\r
+                               t._focused = 1;\r
+                       });\r
+                       Event.add(t.id + '_text', 'blur', function() {Event.remove(t.id + '_text', 'keydown', t.keyDownHandler); t._focused = 0;});\r
 \r
                        // Old IE doesn't have hover on all elements\r
                        if (tinymce.isIE6 || !DOM.boxModel) {\r
@@ -5477,6 +5685,9 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                                t.isMenuRendered = true;\r
                        }\r
 \r
+                       if (t.isMenuVisible)\r
+                               return t.hideMenu();\r
+\r
                        p1 = DOM.getPos(t.settings.menu_container);\r
                        p2 = DOM.getPos(e);\r
 \r
@@ -5490,6 +5701,8 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
 \r
                        Event.add(DOM.doc, 'mousedown', t.hideMenu, t);\r
                        t.setState('Selected', 1);\r
+\r
+                       t.isMenuVisible = 1;\r
                },\r
 \r
                renderMenu : function() {\r
@@ -5510,12 +5723,18 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                hideMenu : function(e) {\r
                        var t = this;\r
 \r
+                       // Prevent double toogles by canceling the mouse click event to the button\r
+                       if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id || e.id === t.id + '_open';}))\r
+                               return;\r
+\r
                        if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {\r
                                t.setState('Selected', 0);\r
                                Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r
                                if (t.menu)\r
                                        t.menu.hideMenu();\r
                        }\r
+\r
+                       t.isMenuVisible = 0;\r
                },\r
 \r
                postRender : function() {\r
@@ -5620,6 +5839,9 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                                default_color : '#888888'\r
                        }, t.settings);\r
 \r
+                       t.onShowMenu = new tinymce.util.Dispatcher(t);\r
+                       t.onHideMenu = new tinymce.util.Dispatcher(t);\r
+\r
                        t.value = s.default_color;\r
                },\r
 \r
@@ -5634,6 +5856,9 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                                t.isMenuRendered = true;\r
                        }\r
 \r
+                       if (t.isMenuVisible)\r
+                               return t.hideMenu();\r
+\r
                        e = DOM.get(t.id);\r
                        DOM.show(t.id + '_menu');\r
                        DOM.addClass(e, 'mceSplitButtonSelected');\r
@@ -5655,17 +5880,29 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
 \r
                                DOM.select('a', t.id + '_menu')[0].focus(); // Select first link\r
                        }\r
+\r
+                       t.onShowMenu.dispatch(t);\r
+\r
+                       t.isMenuVisible = 1;\r
                },\r
 \r
                hideMenu : function(e) {\r
                        var t = this;\r
 \r
+                       // Prevent double toogles by canceling the mouse click event to the button\r
+                       if (e && e.type == "mousedown" && DOM.getParent(e.target, function(e) {return e.id === t.id + '_open';}))\r
+                               return;\r
+\r
                        if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceSplitButtonMenu');})) {\r
                                DOM.removeClass(t.id, 'mceSplitButtonSelected');\r
                                Event.remove(DOM.doc, 'mousedown', t.hideMenu, t);\r
                                Event.remove(t.id + '_menu', 'keydown', t._keyHandler);\r
                                DOM.hide(t.id + '_menu');\r
                        }\r
+\r
+                       t.onHideMenu.dispatch(t);\r
+\r
+                       t.isMenuVisible = 0;\r
                },\r
 \r
                renderMenu : function() {\r
@@ -5719,6 +5956,8 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
 \r
                                if (e.nodeName == 'A' && (c = e.getAttribute('mce_color')))\r
                                        t.setColor(c);\r
+\r
+                               return Event.cancel(e); // Prevent IE auto save warning\r
                        });\r
 \r
                        return w;\r
@@ -5914,7 +6153,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                },\r
 \r
                init : function(s) {\r
-                       var t = this, pl, sl = tinymce.ScriptLoader, c;\r
+                       var t = this, pl, sl = tinymce.ScriptLoader, c, e;\r
 \r
                        function execCallback(se, n, s) {\r
                                var f = se[n];\r
@@ -6042,7 +6281,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                        case "textareas":\r
                                        case "specific_textareas":\r
                                                function hasClass(n, c) {\r
-                                                       return new RegExp('\\b' + c + '\\b', 'g').test(n.className);\r
+                                                       return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c);\r
                                                };\r
 \r
                                                each(DOM.select('textarea'), function(v) {\r
@@ -6050,7 +6289,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                                                return;\r
 \r
                                                        if (!s.editor_selector || hasClass(v, s.editor_selector)) {\r
-                                                               v.id = v.id || v.name;\r
+                                                               // Can we use the name\r
+                                                               e = DOM.get(v.name);\r
+                                                               if (!v.id && !e)\r
+                                                                       v.id = v.name;\r
 \r
                                                                // Generate unique name if missing or already exists\r
                                                                if (!v.id || t.get(v.id))\r
@@ -6137,7 +6379,9 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
 \r
                                case "mceAddEditor":\r
                                case "mceAddControl":\r
-                                       new tinymce.Editor(v, t.settings).render();\r
+                                       if (!t.get(v))\r
+                                               new tinymce.Editor(v, t.settings).render();\r
+\r
                                        return true;\r
 \r
                                case "mceAddFrameControl":\r
@@ -6338,7 +6582,7 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                                apply_source_formatting : 1,\r
                                directionality : 'ltr',\r
                                forced_root_block : 'p',\r
-                               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',\r
+                               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',\r
                                hidden_input : 1,\r
                                padd_empty_editor : 1,\r
                                render_ui : 1,\r
@@ -6391,7 +6635,7 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
 \r
                        if (s.encoding == 'xml') {\r
                                t.onGetContent.add(function(ed, o) {\r
-                                       if (o.get)\r
+                                       if (o.save)\r
                                                o.content = DOM.encode(o.content);\r
                                });\r
                        }\r
@@ -6405,9 +6649,9 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                                });\r
                        }\r
 \r
-                       if (s.add_unload_trigger) {\r
+                       if (s.add_unload_trigger && !s.ask) {\r
                                t._beforeUnload = tinyMCE.onBeforeUnload.add(function() {\r
-                                       if (t.initialized && !t.destroyed)\r
+                                       if (t.initialized && !t.destroyed && !t.isHidden())\r
                                                t.save({format : 'raw', no_events : true});\r
                                });\r
                        }\r
@@ -6464,12 +6708,15 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                                sl.loadQueue(function() {\r
                                        if (s.ask) {\r
                                                function ask() {\r
-                                                       t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {\r
-                                                               if (s)\r
-                                                                       t.init();\r
-                                                               else\r
-                                                                       Event.remove(t.id, 'focus', ask);\r
-                                                       });\r
+                                                       // Yield for awhile to avoid focus bug on FF 3 when cancel is pressed\r
+                                                       window.setTimeout(function() {\r
+                                                               Event.remove(t.id, 'focus', ask);\r
+\r
+                                                               t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {\r
+                                                                       if (s)\r
+                                                                               t.init();\r
+                                                               });\r
+                                                       }, 0);\r
                                                };\r
 \r
                                                Event.add(t.id, 'focus', ask);\r
@@ -6531,7 +6778,8 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
 \r
                        // Pass through\r
                        t.undoManager.onAdd.add(function(um, l) {\r
-                               return t.onChange.dispatch(t, l, um);\r
+                               if (!l.initial)\r
+                                       return t.onChange.dispatch(t, l, um);\r
                        });\r
 \r
                        t.undoManager.onUndo.add(function(um, l) {\r
@@ -6572,8 +6820,8 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
 \r
                        // Measure box\r
                        if (s.render_ui) {\r
-                               w = s.width || e.style.width || e.clientWidth;\r
-                               h = s.height || e.style.height || e.clientHeight;\r
+                               w = s.width || e.style.width || e.offsetWidth;\r
+                               h = s.height || e.style.height || e.offsetHeight;\r
                                t.orgDisplay = e.style.display;\r
                                re = /^[0-9\.]+(|px)$/i;\r
 \r
@@ -6606,7 +6854,7 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                        if (h < 100)\r
                                h = 100;\r
 \r
-                       t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '"></base>';\r
+                       t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '" />';\r
                        t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';\r
 \r
                        if (tinymce.relaxedDomain)\r
@@ -6901,7 +7149,7 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                        // Remove empty contents\r
                        if (s.padd_empty_editor) {\r
                                t.onPostProcess.add(function(ed, o) {\r
-                                       o.content = o.content.replace(/^<p>(&nbsp;|#160;|\s|\u00a0)<\/p>$/, '');\r
+                                       o.content = o.content.replace(/^(<p>(&nbsp;|&#160;|\s|\u00a0|)<\/p>[\r\n]*|<br \/>[\r\n]*)$/, '');\r
                                });\r
                        }\r
 \r
@@ -6957,10 +7205,14 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
 \r
                \r
                focus : function(sf) {\r
-                       var oed, t = this;\r
+                       var oed, t = this, ce = t.settings.content_editable;\r
 \r
                        if (!sf) {\r
-                               t.getWin().focus();\r
+                               // Is not content editable or the selection is outside the area in IE\r
+                               // the IE statement is needed to avoid bluring if element selections inside layers since\r
+                               // the layer is like it's own document in IE\r
+                               if (!ce && (!isIE || t.selection.getNode().ownerDocument != t.getDoc()))\r
+                                       t.getWin().focus();\r
 \r
                                                        }\r
 \r
@@ -7125,7 +7377,7 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                },\r
 \r
                execCommand : function(cmd, ui, val, a) {\r
-                       var t = this, s = 0, o;\r
+                       var t = this, s = 0, o, st;\r
 \r
                        if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus))\r
                                t.focus();\r
@@ -7135,7 +7387,7 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                        if (o.terminate)\r
                                return false;\r
 \r
-                       // Comamnd callback\r
+                       // Command callback\r
                        if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) {\r
                                t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
                                return true;\r
@@ -7143,9 +7395,13 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
 \r
                        // Registred commands\r
                        if (o = t.execCommands[cmd]) {\r
-                               s = o.func.call(o.scope, ui, val);\r
-                               t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
-                               return s;\r
+                               st = o.func.call(o.scope, ui, val);\r
+\r
+                               // Fall through on true\r
+                               if (st !== true) {\r
+                                       t.onExecCommand.dispatch(t, cmd, ui, val, a);\r
+                                       return st;\r
+                               }\r
                        }\r
 \r
                        // Plugin commands\r
@@ -7178,15 +7434,20 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                },\r
 \r
                queryCommandState : function(c) {\r
-                       var t = this, o;\r
+                       var t = this, o, s;\r
 \r
                        // Is hidden then return undefined\r
                        if (t._isHidden())\r
                                return;\r
 \r
                        // Registred commands\r
-                       if (o = t.queryStateCommands[c])\r
-                               return o.func.call(o.scope);\r
+                       if (o = t.queryStateCommands[c]) {\r
+                               s = o.func.call(o.scope);\r
+\r
+                               // Fall though on true\r
+                               if (s !== true)\r
+                                       return s;\r
+                       }\r
 \r
                        // Registred commands\r
                        o = t.editorCommands.queryCommandState(c);\r
@@ -7202,15 +7463,20 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                },\r
 \r
                queryCommandValue : function(c) {\r
-                       var t = this, o;\r
+                       var t = this, o, s;\r
 \r
                        // Is hidden then return undefined\r
                        if (t._isHidden())\r
                                return;\r
 \r
                        // Registred commands\r
-                       if (o = t.queryValueCommands[c])\r
-                               return o.func.call(o.scope);\r
+                       if (o = t.queryValueCommands[c]) {\r
+                               s = o.func.call(o.scope);\r
+\r
+                               // Fall though on true\r
+                               if (s !== true)\r
+                                       return s;\r
+                       }\r
 \r
                        // Registred commands\r
                        o = t.editorCommands.queryCommandValue(c);\r
@@ -7288,6 +7554,12 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                        o = o || {};\r
                        o.save = true;\r
 \r
+                       // Add undo level will trigger onchange event\r
+                       if (!o.no_events) {\r
+                               t.undoManager.typing = 0;\r
+                               t.undoManager.add();\r
+                       }\r
+\r
                        o.element = e;\r
                        h = o.content = t.getContent(o);\r
 \r
@@ -7330,7 +7602,7 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                        // Padd empty content in Gecko and Safari. Commands will otherwise fail on the content\r
                        // It will also be impossible to place the caret in the editor unless there is a BR element present\r
                        if (!tinymce.isIE && (h.length === 0 || /^\s+$/.test(h))) {\r
-                               o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />', 1);\r
+                               o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />');\r
                                o.format = 'raw';\r
                        }\r
 \r
@@ -7364,8 +7636,10 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                                h = t.getBody().innerHTML;\r
 \r
                        h = h.replace(/^\s*|\s*$/g, '');\r
-                       o = {content : h};\r
-                       t.onGetContent.dispatch(t, o);\r
+                       o.content = h;\r
+\r
+                       if (!o.no_events)\r
+                               t.onGetContent.dispatch(t, o);\r
 \r
                        return o.content;\r
                },\r
@@ -7522,8 +7796,14 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                                t.dom.destroy();\r
 \r
                                // Remove all events\r
-                               Event.clear(t.getWin());\r
-                               Event.clear(t.getDoc());\r
+\r
+                               // Don't clear the window or document if content editable\r
+                               // is enabled since other instances might still be present\r
+                               if (!t.settings.content_editable) {\r
+                                       Event.clear(t.getWin());\r
+                                       Event.clear(t.getDoc());\r
+                               }\r
+\r
                                Event.clear(t.getBody());\r
                                Event.clear(t.formElement);\r
                        }\r
@@ -7579,14 +7859,14 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                                        case 'contextmenu':\r
                                                if (tinymce.isOpera) {\r
                                                        // Fake contextmenu on Opera\r
-                                                       Event.add(t.getDoc(), 'mousedown', function(e) {\r
+                                                       Event.add(t.getBody(), 'mousedown', function(e) {\r
                                                                if (e.ctrlKey) {\r
                                                                        e.fakeType = 'contextmenu';\r
                                                                        eventHandler(e);\r
                                                                }\r
                                                        });\r
                                                } else\r
-                                                       Event.add(t.getDoc(), k, eventHandler);\r
+                                                       Event.add(t.getBody(), k, eventHandler);\r
                                                break;\r
 \r
                                        case 'paste':\r
@@ -7672,7 +7952,7 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                                                } catch (ex) {\r
                                                        // Use old method\r
                                                        if (!t._isHidden())\r
-                                                               d.execCommand("useCSS", 0, true);\r
+                                                               try {d.execCommand("useCSS", 0, true);} catch (ex) {}\r
                                                }\r
 \r
                                                if (!s.table_inline_editing)\r
@@ -7856,7 +8136,6 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                                        var re = t.resizeInfo, cb;\r
 \r
                                        e = e.target;\r
-                                       e.removeAttribute('mce_style'); // Remove this one since it might change\r
 \r
                                        // Don't do this action for non image elements\r
                                        if (e.nodeName !== 'IMG')\r
@@ -7987,15 +8266,15 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
 \r
                                                        case 'U':\r
                                                        case 'STRIKE':\r
-                                                               sp = dom.create('span', {style : dom.getAttrib(n, 'style')});\r
-                                                               sp.style.textDecoration = n.nodeName == 'U' ? 'underline' : 'line-through';\r
-                                                               dom.setAttrib(sp, 'mce_style', '');\r
-                                                               dom.replace(sp, n, 1);\r
+                                                               //sp = dom.create('span', {style : dom.getAttrib(n, 'style')});\r
+                                                               n.style.textDecoration = n.nodeName == 'U' ? 'underline' : 'line-through';\r
+                                                               dom.setAttrib(n, 'mce_style', '');\r
+                                                               dom.setAttrib(n, 'mce_name', 'span');\r
                                                                break;\r
                                                }\r
                                        });\r
                                } else if (o.set) {\r
-                                       each(t.dom.select('table,span', o.node), function(n) {\r
+                                       each(t.dom.select('table,span', o.node).reverse(), function(n) {\r
                                                if (n.nodeName == 'TABLE') {\r
                                                        if (v = dom.getStyle(n, 'height'))\r
                                                                dom.setAttrib(n, 'height', v.replace(/[^0-9%]+/g, ''));\r
@@ -8026,8 +8305,9 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                        t.onPreProcess.add(convert);\r
 \r
                        if (!s.cleanup_on_startup) {\r
-                               t.onInit.add(function() {\r
-                                       convert(t, {node : t.getBody(), set : 1});\r
+                               t.onSetContent.add(function(ed, o) {\r
+                                       if (o.initial)\r
+                                               convert(t, {node : t.getBody(), set : 1});\r
                                });\r
                        }\r
                },\r
@@ -8079,7 +8359,7 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
 \r
                                                if (i != -1) {\r
                                                        dom.setAttrib(f, 'size', '' + (i + 1 || 1));\r
-                                                       f.style.fontSize = '';\r
+                                                       //f.style.fontSize = '';\r
                                                }\r
                                        } else if (cl) {\r
                                                i = inArray(cl, dom.getAttrib(n, 'class'));\r
@@ -8353,7 +8633,7 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                },\r
 \r
                mceInsertLink : function(u, v) {\r
-                       var ed = this.editor, e = ed.dom.getParent(ed.selection.getNode(), 'A');\r
+                       var ed = this.editor, s = ed.selection, e = ed.dom.getParent(s.getNode(), 'A');\r
 \r
                        if (tinymce.is(v, 'string'))\r
                                v = {href : v};\r
@@ -8400,6 +8680,42 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                                ed.getDoc().execCommand('FontName', false, v);\r
                },\r
 \r
+               FontSize : function(u, v) {\r
+                       var ed = this.editor, s = ed.settings, fz = tinymce.explode(s.font_size_style_values), fzc = tinymce.explode(s.font_size_classes), h, bm;\r
+\r
+                       // Remove style sizes\r
+                       each(ed.dom.select('font'), function(e) {\r
+                               e.style.fontSize = '';\r
+                       });\r
+\r
+                       // Let the browser add new size it will remove unneded ones in some browsers\r
+                       ed.getDoc().execCommand('FontSize', false, v);\r
+\r
+                       // Add style values\r
+                       if (s.inline_styles) {\r
+                               each(ed.dom.select('font'), function(e) {\r
+                                       // Try remove redundant font elements\r
+                                       if (e.parentNode.nodeName == 'FONT' && e.size == e.parentNode.size) {\r
+                                               if (!bm)\r
+                                                       bm = ed.selection.getBookmark();\r
+\r
+                                               ed.dom.remove(e, 1);\r
+                                               return;\r
+                                       }\r
+\r
+                                       // Setup font size based on font size value\r
+                                       if (v = e.size) {\r
+                                               if (fzc && fzc.length > 0)\r
+                                                       ed.dom.setAttrib(e, 'class', fzc[parseInt(v) - 1]);\r
+                                               else\r
+                                                       ed.dom.setStyle(e, 'fontSize', fz[parseInt(v) - 1]);\r
+                                       }\r
+                               });\r
+                       }\r
+\r
+                       ed.selection.moveToBookmark(bm);\r
+               },\r
+\r
                queryCommandValue : function(c) {\r
                        var f = this['queryValue' + c];\r
 \r
@@ -8836,12 +9152,36 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                },\r
 \r
                FormatBlock : function(ui, val) {\r
-                       var t = this, ed = t.editor;\r
+                       var t = this, ed = t.editor, s = ed.selection, dom = ed.dom, bl, nb, b;\r
 \r
-                       val = ed.settings.forced_root_block ? (val || '<p>') : val;\r
+                       function isBlock(n) {\r
+                               return /^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(n.nodeName);\r
+                       };\r
 \r
-                       if (/^(P|DIV|H[1-6]|ADDRESS|BLOCKQUOTE|PRE)$/.test(ed.selection.getNode().nodeName))\r
-                               t.mceRemoveNode();\r
+                       bl = dom.getParent(s.getNode(), function(n) {\r
+                               return isBlock(n);\r
+                       });\r
+\r
+                       // IE has an issue where it removes the parent div if you change format on the paragrah in <div><p>Content</p></div>\r
+                       // FF and Opera doesn't change parent DIV elements if you switch format\r
+                       if (bl) {\r
+                               if ((isIE && isBlock(bl.parentNode)) || bl.nodeName == 'DIV') {\r
+                                       // Rename block element\r
+                                       nb = ed.dom.create(val);\r
+\r
+                                       each(dom.getAttribs(bl), function(v) {\r
+                                               dom.setAttrib(nb, v.nodeName, dom.getAttrib(bl, v.nodeName));\r
+                                       });\r
+\r
+                                       b = s.getBookmark();\r
+                                       dom.replace(nb, bl, 1);\r
+                                       s.moveToBookmark(b);\r
+                                       ed.nodeChanged();\r
+                                       return;\r
+                               }\r
+                       }\r
+\r
+                       val = ed.settings.forced_root_block ? (val || '<p>') : val;\r
 \r
                        if (val.indexOf('<') == -1)\r
                                val = '<' + val + '>';\r
@@ -8918,7 +9258,7 @@ var tinyMCE = window.tinyMCE = tinymce.EditorManager;
                },\r
 \r
                queryStateUnderline : function() {\r
-                       var ed = this.editor, n;\r
+                       var ed = this.editor, n = ed.selection.getNode();\r
 \r
                        if (n && n.nodeName == 'A')\r
                                return false;\r
@@ -9187,7 +9527,7 @@ tinymce.create('tinymce.UndoManager', {
 \r
                // Add undo level if needed\r
                l.content = l.content.replace(/^\s*|\s*$/g, '');\r
-               la = t.data[t.index > 0 ? t.index - 1 : 0];\r
+               la = t.data[t.index > 0 && (t.index == 0 || t.index == t.data.length) ? t.index - 1 : t.index];\r
                if (!l.initial && la && l.content == la.content)\r
                        return null;\r
 \r
@@ -9205,9 +9545,14 @@ tinymce.create('tinymce.UndoManager', {
                if (s.custom_undo_redo_restore_selection && !l.initial)\r
                        l.bookmark = b = l.bookmark || ed.selection.getBookmark();\r
 \r
-               if (t.index < t.data.length && t.data[t.index].initial)\r
+               if (t.index < t.data.length)\r
                        t.index++;\r
 \r
+               // Only initial marked undo levels should be allowed as first item\r
+               // This to workaround a bug with Firefox and the blur event\r
+               if (t.data.length === 0 && !l.initial)\r
+                       return null;\r
+\r
                // Add level\r
                t.data.length = t.index + 1;\r
                t.data[t.index++] = l;\r
@@ -9483,10 +9828,13 @@ tinymce.create('tinymce.UndoManager', {
                                                        // Store selection\r
                                                        if (si == -2 && r) {\r
                                                                if (!isIE) {\r
-                                                                       so = r.startOffset;\r
-                                                                       eo = r.endOffset;\r
-                                                                       si = t.find(b, 0, r.startContainer);\r
-                                                                       ei = t.find(b, 0, r.endContainer);\r
+                                                                       // If element is inside body, might not be the case in contentEdiable mode\r
+                                                                       if (ed.dom.getParent(r.startContainer, function(e) {return e === b;})) {\r
+                                                                               so = r.startOffset;\r
+                                                                               eo = r.endOffset;\r
+                                                                               si = t.find(b, 0, r.startContainer);\r
+                                                                               ei = t.find(b, 0, r.endContainer);\r
+                                                                       }\r
                                                                } else {\r
                                                                        tr = d.body.createTextRange();\r
                                                                        tr.moveToElementText(b);\r
@@ -9523,7 +9871,7 @@ tinymce.create('tinymce.UndoManager', {
                        // Restore selection\r
                        if (si != -2) {\r
                                if (!isIE) {\r
-                                       bl = d.getElementsByTagName(ed.settings.element)[0];\r
+                                       bl = b.getElementsByTagName(ed.settings.element)[0];\r
                                        r = d.createRange();\r
 \r
                                        // Select last location or generated block\r
@@ -9564,8 +9912,8 @@ tinymce.create('tinymce.UndoManager', {
                },\r
 \r
                insertPara : function(e) {\r
-                       var t = this, ed = t.editor, d = ed.getDoc(), se = ed.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body;\r
-                       var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n, vp = ed.dom.getViewPort(ed.getWin()), y, ch;\r
+                       var t = this, ed = t.editor, dom = ed.dom, d = ed.getDoc(), se = ed.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body;\r
+                       var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n, vp = dom.getViewPort(ed.getWin()), y, ch;\r
 \r
                        function isEmpty(n) {\r
                                n = n.innerHTML;\r
@@ -9601,6 +9949,23 @@ tinymce.create('tinymce.UndoManager', {
                        en = dir ? s.focusNode : s.anchorNode;\r
                        eo = dir ? s.focusOffset : s.anchorOffset;\r
 \r
+                       // If selection is in empty table cell\r
+                       if (sn === en && /^(TD|TH)$/.test(sn.nodeName)) {\r
+                               dom.remove(sn.firstChild); // Remove BR\r
+\r
+                               // Create two new block elements\r
+                               ed.dom.add(sn, se.element, null, '<br />');\r
+                               aft = ed.dom.add(sn, se.element, null, '<br />');\r
+\r
+                               // Move caret into the last one\r
+                               r = d.createRange();\r
+                               r.selectNodeContents(aft);\r
+                               r.collapse(1);\r
+                               ed.selection.setRng(r);\r
+\r
+                               return false;\r
+                       }\r
+\r
                        // If the caret is in an invalid location in FF we need to move it into the first block\r
                        if (sn == b && en == b && b.firstChild && ed.dom.isBlock(b.firstChild)) {\r
                                sn = en = sn.firstChild;\r
@@ -9728,8 +10093,8 @@ tinymce.create('tinymce.UndoManager', {
                        if (isEmpty(aft))\r
                                aft.innerHTML = isOpera ? '&nbsp;' : '<br />'; // Extra space for Opera so that the caret can move there\r
 \r
-                       // Opera needs this one backwards\r
-                       if (isOpera) {\r
+                       // Opera needs this one backwards for older versions\r
+                       if (isOpera && parseFloat(opera.version()) < 9.5) {\r
                                r.insertNode(bef);\r
                                r.insertNode(aft);\r
                        } else {\r
@@ -9741,9 +10106,13 @@ tinymce.create('tinymce.UndoManager', {
                        aft.normalize();\r
                        bef.normalize();\r
 \r
+                       function first(n) {\r
+                               return d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() || n;\r
+                       };\r
+\r
                        // Move cursor and scroll into view\r
                        r = d.createRange();\r
-                       r.selectNodeContents(aft);\r
+                       r.selectNodeContents(isGecko ? first(aft) : aft);\r
                        r.collapse(1);\r
                        s.removeAllRanges();\r
                        s.addRange(r);\r
@@ -9935,12 +10304,7 @@ tinymce.create('tinymce.UndoManager', {
                        // Fix for bug #1897785, #1898007\r
                        if (tinymce.isIE) {\r
                                c.onShowMenu.add(function() {\r
-                                       var s = ed.selection, n = s.getNode();\r
-\r
-                                       if (n.nodeName == 'IMG')\r
-                                               bm = s.getBookmark();\r
-                                       else\r
-                                               bm = 0;\r
+                                       bm = ed.selection.getBookmark(1);\r
                                });\r
 \r
                                c.onHideMenu.add(function() {\r
@@ -10014,6 +10378,7 @@ tinymce.create('tinymce.UndoManager', {
                                return null;\r
 \r
                        s.title = ed.translate(s.title);\r
+                       s.label = ed.translate(s.label);\r
                        s.scope = s.scope || ed;\r
 \r
                        if (!s.onclick && !s.menu_button) {\r
@@ -10088,7 +10453,7 @@ tinymce.create('tinymce.UndoManager', {
                },\r
 \r
                createColorSplitButton : function(id, s, cc) {\r
-                       var t = this, ed = t.editor, cmd, c, cls;\r
+                       var t = this, ed = t.editor, cmd, c, cls, bm;\r
 \r
                        if (t.get(id))\r
                                return null;\r
@@ -10126,6 +10491,20 @@ tinymce.create('tinymce.UndoManager', {
                                c.destroy();\r
                        });\r
 \r
+                       // Fix for bug #1897785, #1898007\r
+                       if (tinymce.isIE) {\r
+                               c.onShowMenu.add(function() {\r
+                                       bm = ed.selection.getBookmark(1);\r
+                               });\r
+\r
+                               c.onHideMenu.add(function() {\r
+                                       if (bm) {\r
+                                               ed.selection.moveToBookmark(bm);\r
+                                               bm = 0;\r
+                                       }\r
+                               });\r
+                       }\r
+\r
                        return t.add(c);\r
                },\r
 \r
@@ -10205,8 +10584,7 @@ tinymce.create('tinymce.UndoManager', {
                                        s.dialogWidth = s.width + 'px';\r
                                        s.dialogHeight = s.height + 'px';\r
                                        s.scroll = s.scrollbars || false;\r
-                               } else\r
-                                       s.modal = s.alwaysRaised = s.dialog = s.centerscreen = s.dependent = true;\r
+                               }\r
                        }\r
 \r
                        // Build features string\r
@@ -10230,10 +10608,12 @@ tinymce.create('tinymce.UndoManager', {
                        if (tinymce.relaxedDomain)\r
                                u += (u.indexOf('?') == -1 ? '?' : '&') + 'mce_rdomain=' + tinymce.relaxedDomain;\r
 \r
+                       u = tinymce._addVer(u);\r
+\r
                        try {\r
                                if (isIE && mo) {\r
                                        w = 1;\r
-                                       window.showModalDialog(s.url || s.file, window, f);\r
+                                       window.showModalDialog(u, window, f);\r
                                } else\r
                                        w = window.open(u, s.name, f);\r
                        } catch (ex) {\r