]> git.mxchange.org Git - friendica.git/blobdiff - library/tinymce/jscripts/tiny_mce/tiny_mce_src.js
reverting tinymce changes, updating smarty to 3.1.19
[friendica.git] / library / tinymce / jscripts / tiny_mce / tiny_mce_src.js
index a0e114bea0084dd7b94a90aad0fac8cdb0c5508c..3bbe9ce95cfc7f9d24cdfa0ad478f7043e816825 100644 (file)
@@ -6,9 +6,9 @@
        var tinymce = {\r
                majorVersion : '3',\r
 \r
-               minorVersion : '5.0.1',\r
+               minorVersion : '5.8',\r
 \r
-               releaseDate : '2012-05-10',\r
+               releaseDate : '2012-11-20',\r
 \r
                _init : function() {\r
                        var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;\r
                        if (!t)\r
                                return o !== undef;\r
 \r
-                       if (t == 'array' && (o.hasOwnProperty && o instanceof Array))\r
+                       if (t == 'array' && tinymce.isArray(o))\r
                                return true;\r
 \r
                        return typeof(o) == t;\r
                },\r
 \r
+               isArray: Array.isArray || function(obj) {\r
+                       return Object.prototype.toString.call(obj) === "[object Array]";\r
+               },\r
+\r
                makeMap : function(items, delim, map) {\r
                        var i;\r
 \r
@@ -880,12 +884,12 @@ tinymce.create('tinymce.util.Dispatcher', {
                                ((s) ? "; secure" : "");\r
                },\r
 \r
-               remove : function(n, p) {\r
-                       var d = new Date();\r
+               remove : function(name, path, domain) {\r
+                       var date = new Date();\r
 \r
-                       d.setTime(d.getTime() - 1000);\r
+                       date.setTime(date.getTime() - 1000);\r
 \r
-                       this.set(n, '', d, p, d);\r
+                       this.set(name, '', date, path, domain);\r
                }\r
        });\r
 })();\r
@@ -921,7 +925,7 @@ tinymce.create('tinymce.util.Dispatcher', {
                }\r
 \r
                if (t == 'object') {\r
-                       if (o.hasOwnProperty && o instanceof Array) {\r
+                       if (o.hasOwnProperty && Object.prototype.toString.call(o) === '[object Array]') {\r
                                        for (i=0, v = '['; i<o.length; i++)\r
                                                v += (i > 0 ? ',' : '') + serialize(o[i], quote);\r
 \r
@@ -1083,12 +1087,18 @@ tinymce.create('static tinymce.util.XHR', {
 \r
                modifierPressed: function (e) {\r
                        return e.shiftKey || e.ctrlKey || e.altKey;\r
+               },\r
+\r
+               metaKeyPressed: function(e) {\r
+                       // Check if ctrl or meta key is pressed also check if alt is false for Polish users\r
+                       return tinymce.isMac ? e.metaKey : e.ctrlKey && !e.altKey;\r
                }\r
        };\r
 })(tinymce);\r
 \r
 tinymce.util.Quirks = function(editor) {\r
-       var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection, settings = editor.settings;\r
+       var VK = tinymce.VK, BACKSPACE = VK.BACKSPACE, DELETE = VK.DELETE, dom = editor.dom, selection = editor.selection,\r
+               settings = editor.settings, parser = editor.parser, serializer = editor.serializer, each = tinymce.each;\r
 \r
        function setEditorCommandState(cmd, state) {\r
                try {\r
@@ -1098,6 +1108,16 @@ tinymce.util.Quirks = function(editor) {
                }\r
        }\r
 \r
+       function getDocumentMode() {\r
+               var documentMode = editor.getDoc().documentMode;\r
+\r
+               return documentMode ? documentMode : 6;\r
+       };\r
+\r
+       function isDefaultPrevented(e) {\r
+               return e.isDefaultPrevented();\r
+       };\r
+\r
        function cleanupStylesWhenDeleting() {\r
                function removeMergedFormatSpans(isDelete) {\r
                        var rng, blockElm, node, clonedSpan;\r
@@ -1108,46 +1128,54 @@ tinymce.util.Quirks = function(editor) {
                        blockElm = dom.getParent(rng.startContainer, dom.isBlock);\r
 \r
                        // On delete clone the root span of the next block element\r
-                       if (isDelete)\r
+                       if (isDelete) {\r
                                blockElm = dom.getNext(blockElm, dom.isBlock);\r
+                       }\r
 \r
                        // Locate root span element and clone it since it would otherwise get merged by the "apple-style-span" on delete/backspace\r
                        if (blockElm) {\r
                                node = blockElm.firstChild;\r
 \r
                                // Ignore empty text nodes\r
-                               while (node && node.nodeType == 3 && node.nodeValue.length === 0)\r
+                               while (node && node.nodeType == 3 && node.nodeValue.length === 0) {\r
                                        node = node.nextSibling;\r
+                               }\r
 \r
                                if (node && node.nodeName === 'SPAN') {\r
                                        clonedSpan = node.cloneNode(false);\r
                                }\r
                        }\r
 \r
+                       each(dom.select('span', blockElm), function(span) {\r
+                               span.setAttribute('data-mce-mark', '1');\r
+                       });\r
+\r
                        // Do the backspace/delete action\r
                        editor.getDoc().execCommand(isDelete ? 'ForwardDelete' : 'Delete', false, null);\r
 \r
                        // Find all odd apple-style-spans\r
                        blockElm = dom.getParent(rng.startContainer, dom.isBlock);\r
-                       tinymce.each(dom.select('span.Apple-style-span,font.Apple-style-span', blockElm), function(span) {\r
+                       each(dom.select('span', blockElm), function(span) {\r
                                var bm = selection.getBookmark();\r
 \r
                                if (clonedSpan) {\r
                                        dom.replace(clonedSpan.cloneNode(false), span, true);\r
-                               } else {\r
+                               } else if (!span.getAttribute('data-mce-mark')) {\r
                                        dom.remove(span, true);\r
+                               } else {\r
+                                       span.removeAttribute('data-mce-mark');\r
                                }\r
 \r
                                // Restore the selection\r
                                selection.moveToBookmark(bm);\r
                        });\r
-               };\r
+               }\r
 \r
                editor.onKeyDown.add(function(editor, e) {\r
                        var isDelete;\r
 \r
                        isDelete = e.keyCode == DELETE;\r
-                       if (!e.isDefaultPrevented() && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {\r
+                       if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {\r
                                e.preventDefault();\r
                                removeMergedFormatSpans(isDelete);\r
                        }\r
@@ -1157,74 +1185,58 @@ tinymce.util.Quirks = function(editor) {
        };\r
        \r
        function emptyEditorWhenDeleting() {\r
-               function getEndPointNode(rng, start) {\r
-                       var container, offset, prefix = start ? 'start' : 'end';\r
-\r
-                       container = rng[prefix + 'Container'];\r
-                       offset = rng[prefix + 'Offset'];\r
+               function serializeRng(rng) {\r
+                       var body = dom.create("body");\r
+                       var contents = rng.cloneContents();\r
+                       body.appendChild(contents);\r
+                       return selection.serializer.serialize(body, {format: 'html'});\r
+               }\r
 \r
-                       // Resolve indexed container\r
-                       if (container.nodeType == 1 && container.hasChildNodes()) {\r
-                               container = container.childNodes[Math.min(start ? offset : (offset > 0 ? offset - 1 : 0), container.childNodes.length - 1)]\r
-                       }\r
+               function allContentsSelected(rng) {\r
+                       var selection = serializeRng(rng);\r
 \r
-                       return container;\r
-               };\r
+                       var allRng = dom.createRng();\r
+                       allRng.selectNode(editor.getBody());\r
 \r
-               function isAtStartEndOfBody(rng, start) {\r
-                       var container, offset, root, childNode, prefix = start ? 'start' : 'end', isAfter;\r
+                       var allSelection = serializeRng(allRng);\r
+                       return selection === allSelection;\r
+               }\r
 \r
-                       container = rng[prefix + 'Container'];\r
-                       offset = rng[prefix + 'Offset'];\r
-                       root = dom.getRoot();\r
+               editor.onKeyDown.add(function(editor, e) {\r
+                       var keyCode = e.keyCode, isCollapsed;\r
 \r
-                       // Resolve indexed container\r
-                       if (container.nodeType == 1) {\r
-                               isAfter = offset >= container.childNodes.length;\r
-                               container = getEndPointNode(rng, start);\r
+                       // Empty the editor if it's needed for example backspace at <p><b>|</b></p>\r
+                       if (!isDefaultPrevented(e) && (keyCode == DELETE || keyCode == BACKSPACE)) {\r
+                               isCollapsed = editor.selection.isCollapsed();\r
 \r
-                               if (container.nodeType == 3) {\r
-                                       offset = start && !isAfter ? 0 : container.nodeValue.length;\r
+                               // Selection is collapsed but the editor isn't empty\r
+                               if (isCollapsed && !dom.isEmpty(editor.getBody())) {\r
+                                       return;\r
                                }\r
-                       }\r
-\r
-                       // Check if start/end is in the middle of text\r
-                       if (container.nodeType == 3 && ((start && offset > 0) || (!start && offset < container.nodeValue.length))) {\r
-                               return false;\r
-                       }\r
 \r
-                       // Walk up the DOM tree to see if the endpoint is at the beginning/end of body\r
-                       while (container !== root) {\r
-                               childNode = container.parentNode[start ? 'firstChild' : 'lastChild'];\r
-\r
-                               // If first/last element is a BR then jump to it's sibling in case: <p>x<br></p>\r
-                               if (childNode.nodeName == "BR") {\r
-                                       childNode = childNode[start ? 'nextSibling' : 'previousSibling'] || childNode;\r
+                               // IE deletes all contents correctly when everything is selected\r
+                               if (tinymce.isIE && !isCollapsed) {\r
+                                       return;\r
                                }\r
 \r
-                               // If the childNode isn't the container node then break in case <p><span>A</span>[X]</p>\r
-                               if (childNode !== container) {\r
-                                       return false;\r
+                               // Selection isn't collapsed but not all the contents is selected\r
+                               if (!isCollapsed && !allContentsSelected(editor.selection.getRng())) {\r
+                                       return;\r
                                }\r
 \r
-                               container = container.parentNode;\r
+                               // Manually empty the editor\r
+                               editor.setContent('');\r
+                               editor.selection.setCursorLocation(editor.getBody(), 0);\r
+                               editor.nodeChanged();\r
                        }\r
+               });\r
+       };\r
 \r
-                       return true;\r
-               };\r
-\r
-               editor.onKeyDown.addToTop(function(editor, e) {\r
-                       var rng, keyCode = e.keyCode;\r
-\r
-                       if (!e.isDefaultPrevented() && (keyCode == DELETE || keyCode == BACKSPACE)) {\r
-                               rng = selection.getRng(true);\r
-\r
-                               if (isAtStartEndOfBody(rng, true) && isAtStartEndOfBody(rng, false) &&\r
-                                       (rng.collapsed || dom.findCommonAncestor(getEndPointNode(rng, true), getEndPointNode(rng)) === dom.getRoot())) {\r
-                                       editor.setContent('');\r
-                                       editor.nodeChanged();\r
-                                       e.preventDefault();\r
-                               }\r
+       function selectAll() {\r
+               editor.onKeyDown.add(function(editor, e) {\r
+                       if (!isDefaultPrevented(e) && e.keyCode == 65 && VK.metaKeyPressed(e)) {\r
+                               e.preventDefault();\r
+                               editor.execCommand('SelectAll');\r
                        }\r
                });\r
        };\r
@@ -1248,7 +1260,7 @@ tinymce.util.Quirks = function(editor) {
 \r
        function removeHrOnBackspace() {\r
                editor.onKeyDown.add(function(editor, e) {\r
-                       if (!e.isDefaultPrevented() && e.keyCode === BACKSPACE) {\r
+                       if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {\r
                                if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {\r
                                        var node = selection.getNode();\r
                                        var previousSibling = node.previousSibling;\r
@@ -1267,7 +1279,7 @@ tinymce.util.Quirks = function(editor) {
                // wouldn't get proper focus if the user clicked on the HTML element\r
                if (!Range.prototype.getClientRects) { // Detect getClientRects got introduced in FF 4\r
                        editor.onMouseDown.add(function(editor, e) {\r
-                               if (e.target.nodeName === "HTML") {\r
+                               if (!isDefaultPrevented(e) && e.target.nodeName === "HTML") {\r
                                        var body = editor.getBody();\r
 \r
                                        // Blur the body it's focused but not correctly focused\r
@@ -1311,7 +1323,7 @@ tinymce.util.Quirks = function(editor) {
                                if (target !== editor.getBody()) {\r
                                        dom.setAttrib(target, "style", null);\r
 \r
-                                       tinymce.each(template, function(attr) {\r
+                                       each(template, function(attr) {\r
                                                target.setAttributeNode(attr.cloneNode(true));\r
                                        });\r
                                }\r
@@ -1319,7 +1331,7 @@ tinymce.util.Quirks = function(editor) {
                }\r
 \r
                function isSelectionAcrossElements() {\r
-                       return !selection.isCollapsed() && selection.getStart() != selection.getEnd();\r
+                       return !selection.isCollapsed() && dom.getParent(selection.getStart(), dom.isBlock) != dom.getParent(selection.getEnd(), dom.isBlock);\r
                }\r
 \r
                function blockEvent(editor, e) {\r
@@ -1330,7 +1342,7 @@ tinymce.util.Quirks = function(editor) {
                editor.onKeyPress.add(function(editor, e) {\r
                        var applyAttributes;\r
 \r
-                       if ((e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) {\r
+                       if (!isDefaultPrevented(e) && (e.keyCode == 8 || e.keyCode == 46) && isSelectionAcrossElements()) {\r
                                applyAttributes = getAttributeApplyFunction();\r
                                editor.getDoc().execCommand('delete', false, null);\r
                                applyAttributes();\r
@@ -1342,7 +1354,7 @@ tinymce.util.Quirks = function(editor) {
                dom.bind(editor.getDoc(), 'cut', function(e) {\r
                        var applyAttributes;\r
 \r
-                       if (isSelectionAcrossElements()) {\r
+                       if (!isDefaultPrevented(e) && isSelectionAcrossElements()) {\r
                                applyAttributes = getAttributeApplyFunction();\r
                                editor.onKeyUp.addToTop(blockEvent);\r
 \r
@@ -1381,7 +1393,7 @@ tinymce.util.Quirks = function(editor) {
 \r
        function disableBackspaceIntoATable() {\r
                editor.onKeyDown.add(function(editor, e) {\r
-                       if (!e.isDefaultPrevented() && e.keyCode === BACKSPACE) {\r
+                       if (!isDefaultPrevented(e) && e.keyCode === BACKSPACE) {\r
                                if (selection.isCollapsed() && selection.getRng(true).startOffset === 0) {\r
                                        var previousSibling = selection.getNode().previousSibling;\r
                                        if (previousSibling && previousSibling.nodeName && previousSibling.nodeName.toLowerCase() === "table") {\r
@@ -1393,20 +1405,19 @@ tinymce.util.Quirks = function(editor) {
        }\r
 \r
        function addNewLinesBeforeBrInPre() {\r
-               var documentMode = editor.getDoc().documentMode;\r
-\r
                // IE8+ rendering mode does the right thing with BR in PRE\r
-               if (documentMode && documentMode > 7) {\r
+               if (getDocumentMode() > 7) {\r
                        return;\r
                }\r
 \r
                 // Enable display: none in area and add a specific class that hides all BR elements in PRE to\r
                 // avoid the caret from getting stuck at the BR elements while pressing the right arrow key\r
                setEditorCommandState('RespectVisibilityInDesign', true);\r
+               editor.contentStyles.push('.mceHideBrInPre pre br {display: none}');\r
                dom.addClass(editor.getBody(), 'mceHideBrInPre');\r
 \r
                // Adds a \n before all BR elements in PRE to get them visual\r
-               editor.parser.addNodeFilter('pre', function(nodes, name) {\r
+               parser.addNodeFilter('pre', function(nodes, name) {\r
                        var i = nodes.length, brNodes, j, brElm, sibling;\r
 \r
                        while (i--) {\r
@@ -1427,7 +1438,7 @@ tinymce.util.Quirks = function(editor) {
                });\r
 \r
                // Removes any \n before BR elements in PRE since other browsers and in contentEditable=false mode they will be visible\r
-               editor.serializer.addNodeFilter('pre', function(nodes, name) {\r
+               serializer.addNodeFilter('pre', function(nodes, name) {\r
                        var i = nodes.length, brNodes, j, brElm, sibling;\r
 \r
                        while (i--) {\r
@@ -1470,7 +1481,7 @@ tinymce.util.Quirks = function(editor) {
                        var isDelete, rng, container, offset, brElm, sibling, collapsed;\r
 \r
                        isDelete = e.keyCode == DELETE;\r
-                       if (!e.isDefaultPrevented() && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {\r
+                       if (!isDefaultPrevented(e) && (isDelete || e.keyCode == BACKSPACE) && !VK.modifierPressed(e)) {\r
                                rng = selection.getRng();\r
                                container = rng.startContainer;\r
                                offset = rng.startOffset;\r
@@ -1510,7 +1521,7 @@ tinymce.util.Quirks = function(editor) {
                editor.onKeyDown.add(function(editor, e) {\r
                        var rng, container, offset, root, parent;\r
 \r
-                       if (e.isDefaultPrevented() || e.keyCode != VK.BACKSPACE) {\r
+                       if (isDefaultPrevented(e) || e.keyCode != VK.BACKSPACE) {\r
                                return;\r
                        }\r
 \r
@@ -1534,10 +1545,10 @@ tinymce.util.Quirks = function(editor) {
                                editor.formatter.toggle('blockquote', null, parent);\r
 \r
                                // Move the caret to the beginning of container\r
+                               rng = dom.createRng();\r
                                rng.setStart(container, 0);\r
                                rng.setEnd(container, 0);\r
                                selection.setRng(rng);\r
-                               selection.collapse(false);\r
                        }\r
                });\r
        };\r
@@ -1562,7 +1573,7 @@ tinymce.util.Quirks = function(editor) {
 \r
        function addBrAfterLastLinks() {\r
                function fixLinks(editor, o) {\r
-                       tinymce.each(dom.select('a'), function(node) {\r
+                       each(dom.select('a'), function(node) {\r
                                var parentNode = node.parentNode, root = dom.getRoot();\r
 \r
                                if (parentNode.lastChild === node) {\r
@@ -1588,6 +1599,14 @@ tinymce.util.Quirks = function(editor) {
                editor.onSetContent.add(selection.onSetContent.add(fixLinks));\r
        };\r
 \r
+       function setDefaultBlockType() {\r
+               if (settings.forced_root_block) {\r
+                       editor.onInit.add(function() {\r
+                               setEditorCommandState('DefaultParagraphSeparator', settings.forced_root_block);\r
+                       });\r
+               }\r
+       }\r
+\r
        function removeGhostSelection() {\r
                function repaint(sender, args) {\r
                        if (!sender || !args.initial) {\r
@@ -1600,17 +1619,309 @@ tinymce.util.Quirks = function(editor) {
                editor.onSetContent.add(repaint);\r
        };\r
 \r
-       function deleteImageOnBackSpace() {\r
+       function deleteControlItemOnBackSpace() {\r
                editor.onKeyDown.add(function(editor, e) {\r
-                       if (!e.isDefaultPrevented() && e.keyCode == 8 && selection.getNode().nodeName == 'IMG') {\r
-                               e.preventDefault();\r
-                               editor.undoManager.beforeChange();\r
-                               dom.remove(selection.getNode());\r
-                               editor.undoManager.add();\r
+                       var rng;\r
+\r
+                       if (!isDefaultPrevented(e) && e.keyCode == BACKSPACE) {\r
+                               rng = editor.getDoc().selection.createRange();\r
+                               if (rng && rng.item) {\r
+                                       e.preventDefault();\r
+                                       editor.undoManager.beforeChange();\r
+                                       dom.remove(rng.item(0));\r
+                                       editor.undoManager.add();\r
+                               }\r
                        }\r
                });\r
        };\r
 \r
+       function renderEmptyBlocksFix() {\r
+               var emptyBlocksCSS;\r
+\r
+               // IE10+\r
+               if (getDocumentMode() >= 10) {\r
+                       emptyBlocksCSS = '';\r
+                       each('p div h1 h2 h3 h4 h5 h6'.split(' '), function(name, i) {\r
+                               emptyBlocksCSS += (i > 0 ? ',' : '') + name + ':empty';\r
+                       });\r
+\r
+                       editor.contentStyles.push(emptyBlocksCSS + '{padding-right: 1px !important}');\r
+               }\r
+       };\r
+\r
+       function fakeImageResize() {\r
+               var selectedElmX, selectedElmY, selectedElm, selectedElmGhost, selectedHandle, startX, startY, startW, startH, ratio,\r
+                       resizeHandles, width, height, rootDocument = document, editableDoc = editor.getDoc();\r
+\r
+               if (!settings.object_resizing || settings.webkit_fake_resize === false) {\r
+                       return;\r
+               }\r
+\r
+               // Try disabling object resizing if WebKit implements resizing in the future\r
+               setEditorCommandState("enableObjectResizing", false);\r
+\r
+               // Details about each resize handle how to scale etc\r
+               resizeHandles = {\r
+                       // Name: x multiplier, y multiplier, delta size x, delta size y\r
+                       n: [.5, 0, 0, -1],\r
+                       e: [1, .5, 1, 0],\r
+                       s: [.5, 1, 0, 1],\r
+                       w: [0, .5, -1, 0],\r
+                       nw: [0, 0, -1, -1],\r
+                       ne: [1, 0, 1, -1],\r
+                       se: [1, 1, 1, 1],\r
+                       sw : [0, 1, -1, 1]\r
+               };\r
+\r
+               function resizeElement(e) {\r
+                       var deltaX, deltaY;\r
+\r
+                       // Calc new width/height\r
+                       deltaX = e.screenX - startX;\r
+                       deltaY = e.screenY - startY;\r
+\r
+                       // Calc new size\r
+                       width = deltaX * selectedHandle[2] + startW;\r
+                       height = deltaY * selectedHandle[3] + startH;\r
+\r
+                       // Never scale down lower than 5 pixels\r
+                       width = width < 5 ? 5 : width;\r
+                       height = height < 5 ? 5 : height;\r
+\r
+                       // Constrain proportions when modifier key is pressed or if the nw, ne, sw, se corners are moved on an image\r
+                       if (VK.modifierPressed(e) || (selectedElm.nodeName == "IMG" && selectedHandle[2] * selectedHandle[3] !== 0)) {\r
+                               width = Math.round(height / ratio);\r
+                               height = Math.round(width * ratio);\r
+                       }\r
+\r
+                       // Update ghost size\r
+                       dom.setStyles(selectedElmGhost, {\r
+                               width: width,\r
+                               height: height\r
+                       });\r
+\r
+                       // Update ghost X position if needed\r
+                       if (selectedHandle[2] < 0 && selectedElmGhost.clientWidth <= width) {\r
+                               dom.setStyle(selectedElmGhost, 'left', selectedElmX + (startW - width));\r
+                       }\r
+\r
+                       // Update ghost Y position if needed\r
+                       if (selectedHandle[3] < 0 && selectedElmGhost.clientHeight <= height) {\r
+                               dom.setStyle(selectedElmGhost, 'top', selectedElmY + (startH - height));\r
+                       }\r
+               }\r
+\r
+               function endResize() {\r
+                       function setSizeProp(name, value) {\r
+                               if (value) {\r
+                                       // Resize by using style or attribute\r
+                                       if (selectedElm.style[name] || !editor.schema.isValid(selectedElm.nodeName.toLowerCase(), name)) {\r
+                                               dom.setStyle(selectedElm, name, value);\r
+                                       } else {\r
+                                               dom.setAttrib(selectedElm, name, value);\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       // Set width/height properties\r
+                       setSizeProp('width', width);\r
+                       setSizeProp('height', height);\r
+\r
+                       dom.unbind(editableDoc, 'mousemove', resizeElement);\r
+                       dom.unbind(editableDoc, 'mouseup', endResize);\r
+\r
+                       if (rootDocument != editableDoc) {\r
+                               dom.unbind(rootDocument, 'mousemove', resizeElement);\r
+                               dom.unbind(rootDocument, 'mouseup', endResize);\r
+                       }\r
+\r
+                       // Remove ghost and update resize handle positions\r
+                       dom.remove(selectedElmGhost);\r
+                       showResizeRect(selectedElm);\r
+               }\r
+\r
+               function showResizeRect(targetElm) {\r
+                       var position, targetWidth, targetHeight;\r
+\r
+                       hideResizeRect();\r
+\r
+                       // Get position and size of target\r
+                       position = dom.getPos(targetElm);\r
+                       selectedElmX = position.x;\r
+                       selectedElmY = position.y;\r
+                       targetWidth = targetElm.offsetWidth;\r
+                       targetHeight = targetElm.offsetHeight;\r
+\r
+                       // Reset width/height if user selects a new image/table\r
+                       if (selectedElm != targetElm) {\r
+                               selectedElm = targetElm;\r
+                               width = height = 0;\r
+                       }\r
+\r
+                       each(resizeHandles, function(handle, name) {\r
+                               var handleElm;\r
+\r
+                               // Get existing or render resize handle\r
+                               handleElm = dom.get('mceResizeHandle' + name);\r
+                               if (!handleElm) {\r
+                                       handleElm = dom.add(editableDoc.documentElement, 'div', {\r
+                                               id: 'mceResizeHandle' + name,\r
+                                               'class': 'mceResizeHandle',\r
+                                               style: 'cursor:' + name + '-resize; margin:0; padding:0'\r
+                                       });\r
+\r
+                                       dom.bind(handleElm, 'mousedown', function(e) {\r
+                                               e.preventDefault();\r
+\r
+                                               endResize();\r
+\r
+                                               startX = e.screenX;\r
+                                               startY = e.screenY;\r
+                                               startW = selectedElm.clientWidth;\r
+                                               startH = selectedElm.clientHeight;\r
+                                               ratio = startH / startW;\r
+                                               selectedHandle = handle;\r
+\r
+                                               selectedElmGhost = selectedElm.cloneNode(true);\r
+                                               dom.addClass(selectedElmGhost, 'mceClonedResizable');\r
+                                               dom.setStyles(selectedElmGhost, {\r
+                                                       left: selectedElmX,\r
+                                                       top: selectedElmY,\r
+                                                       margin: 0\r
+                                               });\r
+\r
+                                               editableDoc.documentElement.appendChild(selectedElmGhost);\r
+\r
+                                               dom.bind(editableDoc, 'mousemove', resizeElement);\r
+                                               dom.bind(editableDoc, 'mouseup', endResize);\r
+\r
+                                               if (rootDocument != editableDoc) {\r
+                                                       dom.bind(rootDocument, 'mousemove', resizeElement);\r
+                                                       dom.bind(rootDocument, 'mouseup', endResize);\r
+                                               }\r
+                                       });\r
+                               } else {\r
+                                       dom.show(handleElm);\r
+                               }\r
+\r
+                               // Position element\r
+                               dom.setStyles(handleElm, {\r
+                                       left: (targetWidth * handle[0] + selectedElmX) - (handleElm.offsetWidth / 2),\r
+                                       top: (targetHeight * handle[1] + selectedElmY) - (handleElm.offsetHeight / 2)\r
+                               });\r
+                       });\r
+\r
+                       // Only add resize rectangle on WebKit and only on images\r
+                       if (!tinymce.isOpera && selectedElm.nodeName == "IMG") {\r
+                               selectedElm.setAttribute('data-mce-selected', '1');\r
+                       }\r
+               }\r
+\r
+               function hideResizeRect() {\r
+                       if (selectedElm) {\r
+                               selectedElm.removeAttribute('data-mce-selected');\r
+                       }\r
+\r
+                       for (var name in resizeHandles) {\r
+                               dom.hide('mceResizeHandle' + name);\r
+                       }\r
+               }\r
+\r
+               // Add CSS for resize handles, cloned element and selected\r
+               editor.contentStyles.push(\r
+                       '.mceResizeHandle {' +\r
+                               'position: absolute;' +\r
+                               'border: 1px solid black;' +\r
+                               'background: #FFF;' +\r
+                               'width: 5px;' +\r
+                               'height: 5px;' +\r
+                               'z-index: 10000' +\r
+                       '}' +\r
+                       '.mceResizeHandle:hover {' +\r
+                               'background: #000' +\r
+                       '}' +\r
+                       'img[data-mce-selected] {' +\r
+                               'outline: 1px solid black' +\r
+                       '}' +\r
+                       'img.mceClonedResizable, table.mceClonedResizable {' +\r
+                               'position: absolute;' +\r
+                               'outline: 1px dashed black;' +\r
+                               'opacity: .5;' +\r
+                               'z-index: 10000' +\r
+                       '}'\r
+               );\r
+\r
+               function updateResizeRect() {\r
+                       var controlElm = dom.getParent(selection.getNode(), 'table,img');\r
+\r
+                       // Remove data-mce-selected from all elements since they might have been copied using Ctrl+c/v\r
+                       each(dom.select('img[data-mce-selected]'), function(img) {\r
+                               img.removeAttribute('data-mce-selected');\r
+                       });\r
+\r
+                       if (controlElm) {\r
+                               showResizeRect(controlElm);\r
+                       } else {\r
+                               hideResizeRect();\r
+                       }\r
+               }\r
+\r
+               // Show/hide resize rect when image is selected\r
+               editor.onNodeChange.add(updateResizeRect);\r
+\r
+               // Fixes WebKit quirk where it returns IMG on getNode if caret is after last image in container\r
+               dom.bind(editableDoc, 'selectionchange', updateResizeRect);\r
+\r
+               // Remove the internal attribute when serializing the DOM\r
+               editor.serializer.addAttributeFilter('data-mce-selected', function(nodes, name) {\r
+                       var i = nodes.length;\r
+\r
+                       while (i--) {\r
+                               nodes[i].attr(name, null);\r
+                       }\r
+               });\r
+       }\r
+\r
+       function keepNoScriptContents() {\r
+               if (getDocumentMode() < 9) {\r
+                       parser.addNodeFilter('noscript', function(nodes) {\r
+                               var i = nodes.length, node, textNode;\r
+\r
+                               while (i--) {\r
+                                       node = nodes[i];\r
+                                       textNode = node.firstChild;\r
+\r
+                                       if (textNode) {\r
+                                               node.attr('data-mce-innertext', textNode.value);\r
+                                       }\r
+                               }\r
+                       });\r
+\r
+                       serializer.addNodeFilter('noscript', function(nodes) {\r
+                               var i = nodes.length, node, textNode, value;\r
+\r
+                               while (i--) {\r
+                                       node = nodes[i];\r
+                                       textNode = nodes[i].firstChild;\r
+\r
+                                       if (textNode) {\r
+                                               textNode.value = tinymce.html.Entities.decode(textNode.value);\r
+                                       } else {\r
+                                               // Old IE can't retain noscript value so an attribute is used to store it\r
+                                               value = node.attributes.map['data-mce-innertext'];\r
+                                               if (value) {\r
+                                                       node.attr('data-mce-innertext', null);\r
+                                                       textNode = new tinymce.html.Node('#text', 3);\r
+                                                       textNode.value = value;\r
+                                                       textNode.raw = true;\r
+                                                       node.append(textNode);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       });\r
+               }\r
+       }\r
+\r
        // All browsers\r
        disableBackspaceIntoATable();\r
        removeBlockQuoteOnBackSpace();\r
@@ -1622,10 +1933,14 @@ tinymce.util.Quirks = function(editor) {
                cleanupStylesWhenDeleting();\r
                inputMethodFocus();\r
                selectControlElements();\r
+               setDefaultBlockType();\r
 \r
                // iOS\r
                if (tinymce.isIDevice) {\r
                        selectionChangeNodeChanged();\r
+               } else {\r
+                       fakeImageResize();\r
+                       selectAll();\r
                }\r
        }\r
 \r
@@ -1635,7 +1950,9 @@ tinymce.util.Quirks = function(editor) {
                ensureBodyHasRoleApplication();\r
                addNewLinesBeforeBrInPre();\r
                removePreSerializedStylesWhenSelectingControls();\r
-               deleteImageOnBackSpace();\r
+               deleteControlItemOnBackSpace();\r
+               renderEmptyBlocksFix();\r
+               keepNoScriptContents();\r
        }\r
 \r
        // Gecko\r
@@ -1647,6 +1964,11 @@ tinymce.util.Quirks = function(editor) {
                addBrAfterLastLinks();\r
                removeGhostSelection();\r
        }\r
+\r
+       // Opera\r
+       if (tinymce.isOpera) {\r
+               fakeImageResize();\r
+       }\r
 };\r
 (function(tinymce) {\r
        var namedEntities, baseEntities, reverseEntities,\r
@@ -2098,9 +2420,12 @@ tinymce.html.Styles = function(settings, schema) {
 \r
                if (!html5) {\r
                        html5 = mapCache.html5 = unpack({\r
-                                       A : 'id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title',\r
-                                       B : '#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video',\r
-                                       C : '#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video'\r
+                                       A : 'id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup',\r
+                                       B : '#|a|abbr|area|audio|b|bdo|br|button|canvas|cite|code|command|datalist|del|dfn|em|embed|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|meta|' +\r
+                                               'meter|noscript|object|output|progress|q|ruby|samp|script|select|small|span|strong|sub|sup|svg|textarea|time|var|video|wbr',\r
+                                       C : '#|a|abbr|area|address|article|aside|audio|b|bdo|blockquote|br|button|canvas|cite|code|command|datalist|del|details|dfn|dialog|div|dl|em|embed|fieldset|' +\r
+                                               'figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|i|iframe|img|input|ins|kbd|keygen|label|link|map|mark|menu|meta|meter|nav|noscript|ol|object|output|' +\r
+                                               'p|pre|progress|q|ruby|samp|script|section|select|small|span|strong|style|sub|sup|svg|table|textarea|time|ul|var|video'\r
                                }, 'html[A|manifest][body|head]' +\r
                                        'head[A][base|command|link|meta|noscript|script|style|title]' +\r
                                        'title[A][#]' +\r
@@ -2136,7 +2461,7 @@ tinymce.html.Styles = function(settings, schema) {
                                        'dl[A][dd|dt]' +\r
                                        'dt[A][B]' +\r
                                        'dd[A][C]' +\r
-                                       'a[A|href|target|ping|rel|media|type][C]' +\r
+                                       'a[A|href|target|ping|rel|media|type][B]' +\r
                                        'em[A][B]' +\r
                                        'strong[A][B]' +\r
                                        'small[A][B]' +\r
@@ -2182,7 +2507,8 @@ tinymce.html.Styles = function(settings, schema) {
                                        'form[A|accept-charset|action|autocomplete|enctype|method|name|novalidate|target][C]' +\r
                                        'fieldset[A|disabled|form|name][C|legend]' +\r
                                        'label[A|form|for][B]' +\r
-                                       'input[A|type|accept|alt|autocomplete|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value][]' +\r
+                                       'input[A|type|accept|alt|autocomplete|autofocus|checked|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|height|list|max|maxlength|min|' +\r
+                                               'multiple|pattern|placeholder|readonly|required|size|src|step|width|files|value|name][]' +\r
                                        'button[A|autofocus|disabled|form|formaction|formenctype|formmethod|formnovalidate|formtarget|name|value|type][B]' +\r
                                        'select[A|autofocus|disabled|form|multiple|name|size][option|optgroup]' +\r
                                        'datalist[A][B|option]' +\r
@@ -2196,7 +2522,7 @@ tinymce.html.Styles = function(settings, schema) {
                                        'area[A|shape|coords|href|alt|target|media|rel|ping|type][]' +\r
                                        'mathml[A][]' +\r
                                        'svg[A][]' +\r
-                                       'table[A|summary][caption|colgroup|thead|tfoot|tbody|tr]' +\r
+                                       'table[A|border][caption|colgroup|thead|tfoot|tbody|tr]' +\r
                                        'caption[A][C]' +\r
                                        'colgroup[A|span][col]' +\r
                                        'col[A|span][]' +\r
@@ -2205,7 +2531,8 @@ tinymce.html.Styles = function(settings, schema) {
                                        'tbody[A][tr]' +\r
                                        'tr[A][th|td]' +\r
                                        'th[A|headers|rowspan|colspan|scope][B]' +\r
-                                       'td[A|headers|rowspan|colspan][C]'\r
+                                       'td[A|headers|rowspan|colspan][C]' +\r
+                                       'wbr[A][]'\r
                        );\r
                }\r
 \r
@@ -2384,14 +2711,15 @@ tinymce.html.Styles = function(settings, schema) {
                }\r
 \r
                // Setup map objects\r
-               whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script style textarea');\r
-               selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li options p td tfoot th thead tr');\r
-               shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link meta param embed source');\r
+               whiteSpaceElementsMap = createLookupTable('whitespace_elements', 'pre script noscript style textarea');\r
+               selfClosingElementsMap = createLookupTable('self_closing_elements', 'colgroup dd dt li option p td tfoot th thead tr');\r
+               shortEndedElementsMap = createLookupTable('short_ended_elements', 'area base basefont br col frame hr img input isindex link meta param embed source wbr');\r
                boolAttrMap = createLookupTable('boolean_attributes', 'checked compact declare defer disabled ismap multiple nohref noresize noshade nowrap readonly selected autoplay loop controls');\r
                nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object', shortEndedElementsMap);\r
-               blockElementsMap = createLookupTable('block_elements', 'h1 h2 h3 h4 h5 h6 hr p div address pre form table tbody thead tfoot ' + \r
-                                               'th tr td li ol ul caption blockquote center dl dt dd dir fieldset ' + \r
-                                               'noscript menu isindex samp header footer article section hgroup aside nav figure');\r
+               textBlockElementsMap = createLookupTable('text_block_elements', 'h1 h2 h3 h4 h5 h6 p div address pre form ' + \r
+                                               'blockquote center dir fieldset header footer article section hgroup aside nav figure');\r
+               blockElementsMap = createLookupTable('block_elements', 'hr table tbody thead tfoot ' + \r
+                                               'th tr td li ol ul caption dl dt dd noscript menu isindex samp option datalist select optgroup', textBlockElementsMap);\r
 \r
                // Converts a wildcard expression string to a regexp for example *a will become /.*a/.\r
                function patternToRegExp(str) {\r
@@ -2565,8 +2893,15 @@ tinymce.html.Styles = function(settings, schema) {
                                        customElementsMap[name] = cloneName;\r
 \r
                                        // If it's not marked as inline then add it to valid block elements\r
-                                       if (!inline)\r
+                                       if (!inline) {\r
+                                               blockElementsMap[name.toUpperCase()] = {};\r
                                                blockElementsMap[name] = {};\r
+                                       }\r
+\r
+                                       // Add elements clone if needed\r
+                                       if (!elements[name]) {\r
+                                               elements[name] = elements[cloneName];\r
+                                       }\r
 \r
                                        // Add custom elements at span/div positions\r
                                        each(children, function(element, child) {\r
@@ -2691,6 +3026,10 @@ tinymce.html.Styles = function(settings, schema) {
                        return blockElementsMap;\r
                };\r
 \r
+               self.getTextBlockElements = function() {\r
+                       return textBlockElementsMap;\r
+               };\r
+\r
                self.getShortEndedElements = function() {\r
                        return shortEndedElementsMap;\r
                };\r
@@ -2713,6 +3052,36 @@ tinymce.html.Styles = function(settings, schema) {
                        return !!(parent && parent[child]);\r
                };\r
 \r
+               self.isValid = function(name, attr) {\r
+                       var attrPatterns, i, rule = getElementRule(name);\r
+\r
+                       // Check if it's a valid element\r
+                       if (rule) {\r
+                               if (attr) {\r
+                                       // Check if attribute name exists\r
+                                       if (rule.attributes[attr]) {\r
+                                               return true;\r
+                                       }\r
+\r
+                                       // Check if attribute matches a regexp pattern\r
+                                       attrPatterns = rule.attributePatterns;\r
+                                       if (attrPatterns) {\r
+                                               i = attrPatterns.length;\r
+                                               while (i--) {\r
+                                                       if (attrPatterns[i].pattern.test(name)) {\r
+                                                               return true;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               } else {\r
+                                       return true;\r
+                               }\r
+                       }\r
+\r
+                       // No match\r
+                       return false;\r
+               };\r
+               \r
                self.getElementRule = getElementRule;\r
 \r
                self.getCustomElements = function() {\r
@@ -2726,6 +3095,8 @@ tinymce.html.Styles = function(settings, schema) {
                self.addCustomElements = addCustomElements;\r
 \r
                self.addValidChildren = addValidChildren;\r
+\r
+               self.elements = elements;\r
        };\r
 })(tinymce);\r
 \r
@@ -2824,10 +3195,10 @@ tinymce.html.Styles = function(settings, schema) {
                                '(?:!DOCTYPE([\\w\\W]*?)>)|' + // DOCTYPE\r
                                '(?:\\?([^\\s\\/<>]+) ?([\\w\\W]*?)[?/]>)|' + // PI\r
                                '(?:\\/([^>]+)>)|' + // End element\r
-                               '(?:([A-Za-z0-9\\-\\:]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element\r
+                               '(?:([A-Za-z0-9\\-\\:\\.]+)((?:\\s+[^"\'>]+(?:(?:"[^"]*")|(?:\'[^\']*\')|[^>]*))*|\\/|\\s+)>)' + // Start element\r
                        ')', 'g');\r
 \r
-                       attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:\\.|[^\"])*)\")|(?:\'((?:\\.|[^\'])*)\')|([^>\s]+)))?/g;\r
+                       attrRegExp = /([\w:\-]+)(?:\s*=\s*(?:(?:\"((?:[^\"])*)\")|(?:\'((?:[^\'])*)\')|([^>\s]+)))?/g;\r
                        specialElements = {\r
                                'script' : /<\/script[^>]*>/gi,\r
                                'style' : /<\/style[^>]*>/gi,\r
@@ -2836,7 +3207,7 @@ tinymce.html.Styles = function(settings, schema) {
 \r
                        // Setup lookup tables for empty elements and boolean attributes\r
                        shortEndedElements = schema.getShortEndedElements();\r
-                       selfClosing = schema.getSelfClosingElements();\r
+                       selfClosing = settings.self_closing_elements || schema.getSelfClosingElements();\r
                        fillAttrsMap = schema.getBoolAttrs();\r
                        validate = settings.validate;\r
                        removeInternalElements = settings.remove_internals;\r
@@ -3310,7 +3681,7 @@ tinymce.html.Styles = function(settings, schema) {
                                                i = node.attributes.length;\r
                                                while (i--) {\r
                                                        name = node.attributes[i].name;\r
-                                                       if (name === "name" || name.indexOf('data-') === 0)\r
+                                                       if (name === "name" || name.indexOf('data-mce-') === 0)\r
                                                                return false;\r
                                                }\r
                                        }\r
@@ -3366,17 +3737,40 @@ tinymce.html.Styles = function(settings, schema) {
 \r
                function fixInvalidChildren(nodes) {\r
                        var ni, node, parent, parents, newParent, currentNode, tempNode, childNode, i,\r
-                               childClone, nonEmptyElements, nonSplitableElements, sibling, nextNode;\r
+                               childClone, nonEmptyElements, nonSplitableElements, textBlockElements, sibling, nextNode;\r
 \r
                        nonSplitableElements = tinymce.makeMap('tr,td,th,tbody,thead,tfoot,table');\r
                        nonEmptyElements = schema.getNonEmptyElements();\r
+                       textBlockElements = schema.getTextBlockElements();\r
 \r
                        for (ni = 0; ni < nodes.length; ni++) {\r
                                node = nodes[ni];\r
 \r
-                               // Already removed\r
-                               if (!node.parent)\r
+                               // Already removed or fixed\r
+                               if (!node.parent || node.fixed)\r
+                                       continue;\r
+\r
+                               // If the invalid element is a text block and the text block is within a parent LI element\r
+                               // Then unwrap the first text block and convert other sibling text blocks to LI elements similar to Word/Open Office\r
+                               if (textBlockElements[node.name] && node.parent.name == 'li') {\r
+                                       // Move sibling text blocks after LI element\r
+                                       sibling = node.next;\r
+                                       while (sibling) {\r
+                                               if (textBlockElements[sibling.name]) {\r
+                                                       sibling.name = 'li';\r
+                                                       sibling.fixed = true;\r
+                                                       node.parent.insert(sibling, node.parent);\r
+                                               } else {\r
+                                                       break;\r
+                                               }\r
+\r
+                                               sibling = sibling.next;\r
+                                       }\r
+\r
+                                       // Unwrap current text block\r
+                                       node.unwrap(node);\r
                                        continue;\r
+                               }\r
 \r
                                // Get list of all parent nodes until we find a valid parent to stick the child into\r
                                parents = [node];\r
@@ -3584,9 +3978,23 @@ tinymce.html.Styles = function(settings, schema) {
                                }\r
                        };\r
 \r
+                       function cloneAndExcludeBlocks(input) {\r
+                               var name, output = {};\r
+\r
+                               for (name in input) {\r
+                                       if (name !== 'li' && name != 'p') {\r
+                                               output[name] = input[name];\r
+                                       }\r
+                               }\r
+\r
+                               return output;\r
+                       };\r
+\r
                        parser = new tinymce.html.SaxParser({\r
                                validate : validate,\r
-                               fix_self_closing : !validate, // Let the DOM parser handle <li> in <li> or <p> in <p> for better results\r
+\r
+                               // Exclude P and LI from DOM parsing since it's treated better by the DOM parser\r
+                               self_closing_elements: cloneAndExcludeBlocks(schema.getSelfClosingElements()),\r
 \r
                                cdata: function(text) {\r
                                        node.append(createNode('#cdata', 4)).value = text;\r
@@ -3741,7 +4149,8 @@ tinymce.html.Styles = function(settings, schema) {
                                                        }\r
 \r
                                                        // Trim start white space\r
-                                                       textNode = node.prev;\r
+                                                       // Removed due to: #5424\r
+                                                       /*textNode = node.prev;\r
                                                        if (textNode && textNode.type === 3) {\r
                                                                text = textNode.value.replace(startWhiteSpaceRegExp, '');\r
 \r
@@ -3749,7 +4158,7 @@ tinymce.html.Styles = function(settings, schema) {
                                                                        textNode.value = text;\r
                                                                else\r
                                                                        textNode.remove();\r
-                                                       }\r
+                                                       }*/\r
                                                }\r
 \r
                                                // Check if we exited a whitespace preserved element\r
@@ -3764,7 +4173,7 @@ tinymce.html.Styles = function(settings, schema) {
                                                                        node.empty().append(new Node('#text', '3')).value = '\u00a0';\r
                                                                else {\r
                                                                        // Leave nodes that have a name like <a name="name">\r
-                                                                       if (!node.attributes.map.name) {\r
+                                                                       if (!node.attributes.map.name && !node.attributes.map.id) {\r
                                                                                tempNode = node.parent;\r
                                                                                node.empty().remove();\r
                                                                                node = tempNode;\r
@@ -3916,12 +4325,12 @@ tinymce.html.Styles = function(settings, schema) {
 \r
                // Force anchor names closed, unless the setting "allow_html_in_named_anchor" is explicitly included.\r
                if (!settings.allow_html_in_named_anchor) {\r
-                       self.addAttributeFilter('name', function(nodes, name) {\r
+                       self.addAttributeFilter('id,name', function(nodes, name) {\r
                                var i = nodes.length, sibling, prevSibling, parent, node;\r
 \r
                                while (i--) {\r
                                        node = nodes[i];\r
-                                       if (node.name === 'a' && node.firstChild) {\r
+                                       if (node.name === 'a' && node.firstChild && !node.attr('href')) {\r
                                                parent = node.parent;\r
 \r
                                                // Move children after current node\r
@@ -4259,6 +4668,12 @@ tinymce.dom = {};
                        }\r
                }\r
 \r
+               // Page already loaded then fire it directly\r
+               if (doc.readyState == "complete") {\r
+                       readyHandler();\r
+                       return;\r
+               }\r
+\r
                // Use W3C method\r
                if (w3cEventModel) {\r
                        addEvent(win, 'DOMContentLoaded', readyHandler);\r
@@ -4600,7 +5015,7 @@ tinymce.dom = {};
 \r
                        // Old API supported multiple targets\r
                        if (target && target instanceof Array) {\r
-                               var i = target;\r
+                               var i = target.length;\r
 \r
                                while (i--) {\r
                                        self.add(target[i], events, func, scope);\r
@@ -4660,12 +5075,20 @@ tinymce.dom = {};
                };\r
 \r
                self.prevent = function(e) {\r
+                       if (!e.preventDefault) {\r
+                               e = fix(e);\r
+                       }\r
+\r
                        e.preventDefault();\r
 \r
                        return false;\r
                };\r
 \r
                self.stop = function(e) {\r
+                       if (!e.stopPropagation) {\r
+                               e = fix(e);\r
+                       }\r
+\r
                        e.stopPropagation();\r
 \r
                        return false;\r
@@ -4794,6 +5217,11 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
                        blockElementsMap = s.schema ? s.schema.getBlockElements() : {};\r
 \r
                        t.isBlock = function(node) {\r
+                               // Fix for #5446\r
+                               if (!node) {\r
+                                       return false;\r
+                               }\r
+\r
                                // This function is called in module pattern style since it might be executed with the wrong this scope\r
                                var type = node.nodeType;\r
 \r
@@ -5434,6 +5862,32 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
                        return this.styles.serialize(o, name);\r
                },\r
 \r
+               addStyle: function(cssText) {\r
+                       var doc = this.doc, head;\r
+\r
+                       // Create style element if needed\r
+                       styleElm = doc.getElementById('mceDefaultStyles');\r
+                       if (!styleElm) {\r
+                               styleElm = doc.createElement('style'),\r
+                               styleElm.id = 'mceDefaultStyles';\r
+                               styleElm.type = 'text/css';\r
+\r
+                               head = doc.getElementsByTagName('head')[0];\r
+                               if (head.firstChild) {\r
+                                       head.insertBefore(styleElm, head.firstChild);\r
+                               } else {\r
+                                       head.appendChild(styleElm);\r
+                               }\r
+                       }\r
+\r
+                       // Append style data to old or new style element\r
+                       if (styleElm.styleSheet) {\r
+                               styleElm.styleSheet.cssText += cssText;\r
+                       } else {\r
+                               styleElm.appendChild(doc.createTextNode(cssText));\r
+                       }\r
+               },\r
+\r
                loadCSS : function(u) {\r
                        var t = this, d = t.doc, head;\r
 \r
@@ -5557,13 +6011,13 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
                                                // This seems to fix this problem\r
 \r
                                                // Create new div with HTML contents and a BR infront to keep comments\r
-                                               element = self.create('div');\r
-                                               element.innerHTML = '<br />' + html;\r
+                                               var newElement = self.create('div');\r
+                                               newElement.innerHTML = '<br />' + html;\r
 \r
                                                // Add all children from div to target\r
-                                               each (element.childNodes, function(node, i) {\r
+                                               each (tinymce.grep(newElement.childNodes), function(node, i) {\r
                                                        // Skip br element\r
-                                                       if (i)\r
+                                                       if (i && element.canHaveHTML)\r
                                                                element.appendChild(node);\r
                                                });\r
                                        }\r
@@ -6158,7 +6612,8 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
                        cloneContents : cloneContents,\r
                        insertNode : insertNode,\r
                        surroundContents : surroundContents,\r
-                       cloneRange : cloneRange\r
+                       cloneRange : cloneRange,\r
+                       toStringIE : toStringIE\r
                });\r
 \r
                function createDocumentFragment() {\r
@@ -6798,9 +7253,20 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
 \r
                        n.parentNode.removeChild(n);\r
                };\r
+\r
+               function toStringIE() {\r
+                       return dom.create('body', null, cloneContents()).outerText;\r
+               }\r
+               \r
+               return t;\r
        };\r
 \r
        ns.Range = Range;\r
+\r
+       // Older IE versions doesn't let you override toString by it's constructor so we have to stick it in the prototype\r
+       Range.prototype.toString = function() {\r
+               return this.toStringIE();\r
+       };\r
 })(tinymce.dom);\r
 \r
 (function() {\r
@@ -7156,7 +7622,8 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
                };\r
 \r
                this.addRange = function(rng) {\r
-                       var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, doc = selection.dom.doc, body = doc.body;\r
+                       var ieRng, ctrlRng, startContainer, startOffset, endContainer, endOffset, sibling,\r
+                               doc = selection.dom.doc, body = doc.body, nativeRng, ctrlElm;\r
 \r
                        function setEndPoint(start) {\r
                                var container, offset, marker, tmpRng, nodes;\r
@@ -7214,11 +7681,25 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
                                // Trick to place the caret inside an empty block element like <p></p>\r
                                if (startOffset == endOffset && !startContainer.hasChildNodes()) {\r
                                        if (startContainer.canHaveHTML) {\r
+                                               // Check if previous sibling is an empty block if it is then we need to render it\r
+                                               // IE would otherwise move the caret into the sibling instead of the empty startContainer see: #5236\r
+                                               // Example this: <p></p><p>|</p> would become this: <p>|</p><p></p>\r
+                                               sibling = startContainer.previousSibling;\r
+                                               if (sibling && !sibling.hasChildNodes() && dom.isBlock(sibling)) {\r
+                                                       sibling.innerHTML = '\uFEFF';\r
+                                               } else {\r
+                                                       sibling = null;\r
+                                               }\r
+\r
                                                startContainer.innerHTML = '<span>\uFEFF</span><span>\uFEFF</span>';\r
                                                ieRng.moveToElementText(startContainer.lastChild);\r
                                                ieRng.select();\r
                                                dom.doc.selection.clear();\r
                                                startContainer.innerHTML = '';\r
+\r
+                                               if (sibling) {\r
+                                                       sibling.innerHTML = '';\r
+                                               }\r
                                                return;\r
                                        } else {\r
                                                startOffset = dom.nodeIndex(startContainer);\r
@@ -7228,10 +7709,17 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
 \r
                                if (startOffset == endOffset - 1) {\r
                                        try {\r
+                                               ctrlElm = startContainer.childNodes[startOffset];\r
                                                ctrlRng = body.createControlRange();\r
-                                               ctrlRng.addElement(startContainer.childNodes[startOffset]);\r
+                                               ctrlRng.addElement(ctrlElm);\r
                                                ctrlRng.select();\r
-                                               return;\r
+\r
+                                               // Check if the range produced is on the correct element and is a control range\r
+                                               // On IE 8 it will select the parent contentEditable container if you select an inner element see: #5398\r
+                                               nativeRng = selection.getRng();\r
+                                               if (nativeRng.item && ctrlElm === nativeRng.item(0)) {\r
+                                                       return;\r
+                                               }\r
                                        } catch (ex) {\r
                                                // Ignore\r
                                        }\r
@@ -8816,12 +9304,13 @@ window.tinymce.dom.Sizzle = Sizzle;
        var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each, TreeWalker = tinymce.dom.TreeWalker;\r
 \r
        tinymce.create('tinymce.dom.Selection', {\r
-               Selection : function(dom, win, serializer) {\r
+               Selection : function(dom, win, serializer, editor) {\r
                        var t = this;\r
 \r
                        t.dom = dom;\r
                        t.win = win;\r
                        t.serializer = serializer;\r
+                       t.editor = editor;\r
 \r
                        // Add events\r
                        each([\r
@@ -8977,7 +9466,7 @@ window.tinymce.dom.Sizzle = Sizzle;
                },\r
 \r
                getStart : function() {\r
-                       var rng = this.getRng(), startElement, parentElement, checkRng, node;\r
+                       var self = this, rng = self.getRng(), startElement, parentElement, checkRng, node;\r
 \r
                        if (rng.duplicate || rng.item) {\r
                                // Control selection, return first item\r
@@ -8988,6 +9477,9 @@ window.tinymce.dom.Sizzle = Sizzle;
                                checkRng = rng.duplicate();\r
                                checkRng.collapse(1);\r
                                startElement = checkRng.parentElement();\r
+                               if (startElement.ownerDocument !== self.dom.doc) {\r
+                                       startElement = self.dom.getRoot();\r
+                               }\r
 \r
                                // Check if range parent is inside the start element, then return the inner parent element\r
                                // This will fix issues when a single element is selected, IE would otherwise return the wrong start element\r
@@ -9014,31 +9506,34 @@ window.tinymce.dom.Sizzle = Sizzle;
                },\r
 \r
                getEnd : function() {\r
-                       var t = this, r = t.getRng(), e, eo;\r
+                       var self = this, rng = self.getRng(), endElement, endOffset;\r
 \r
-                       if (r.duplicate || r.item) {\r
-                               if (r.item)\r
-                                       return r.item(0);\r
+                       if (rng.duplicate || rng.item) {\r
+                               if (rng.item)\r
+                                       return rng.item(0);\r
 \r
-                               r = r.duplicate();\r
-                               r.collapse(0);\r
-                               e = r.parentElement();\r
+                               rng = rng.duplicate();\r
+                               rng.collapse(0);\r
+                               endElement = rng.parentElement();\r
+                               if (endElement.ownerDocument !== self.dom.doc) {\r
+                                       endElement = self.dom.getRoot();\r
+                               }\r
 \r
-                               if (e && e.nodeName == 'BODY')\r
-                                       return e.lastChild || e;\r
+                               if (endElement && endElement.nodeName == 'BODY')\r
+                                       return endElement.lastChild || endElement;\r
 \r
-                               return e;\r
+                               return endElement;\r
                        } else {\r
-                               e = r.endContainer;\r
-                               eo = r.endOffset;\r
+                               endElement = rng.endContainer;\r
+                               endOffset = rng.endOffset;\r
 \r
-                               if (e.nodeType == 1 && e.hasChildNodes())\r
-                                       e = e.childNodes[eo > 0 ? eo - 1 : eo];\r
+                               if (endElement.nodeType == 1 && endElement.hasChildNodes())\r
+                                       endElement = endElement.childNodes[endOffset > 0 ? endOffset - 1 : endOffset];\r
 \r
-                               if (e && e.nodeType == 3)\r
-                                       return e.parentNode;\r
+                               if (endElement && endElement.nodeType == 3)\r
+                                       return endElement.parentNode;\r
 \r
-                               return e;\r
+                               return endElement;\r
                        }\r
                },\r
 \r
@@ -9784,14 +10279,76 @@ window.tinymce.dom.Sizzle = Sizzle;
                        }\r
                },\r
 \r
-               destroy : function(s) {\r
-                       var t = this;\r
+               selectorChanged: function(selector, callback) {\r
+                       var self = this, currentSelectors;\r
+\r
+                       if (!self.selectorChangedData) {\r
+                               self.selectorChangedData = {};\r
+                               currentSelectors = {};\r
+\r
+                               self.editor.onNodeChange.addToTop(function(ed, cm, node) {\r
+                                       var dom = self.dom, parents = dom.getParents(node, null, dom.getRoot()), matchedSelectors = {};\r
+\r
+                                       // Check for new matching selectors\r
+                                       each(self.selectorChangedData, function(callbacks, selector) {\r
+                                               each(parents, function(node) {\r
+                                                       if (dom.is(node, selector)) {\r
+                                                               if (!currentSelectors[selector]) {\r
+                                                                       // Execute callbacks\r
+                                                                       each(callbacks, function(callback) {\r
+                                                                               callback(true, {node: node, selector: selector, parents: parents});\r
+                                                                       });\r
+\r
+                                                                       currentSelectors[selector] = callbacks;\r
+                                                               }\r
+\r
+                                                               matchedSelectors[selector] = callbacks;\r
+                                                               return false;\r
+                                                       }\r
+                                               });\r
+                                       });\r
+\r
+                                       // Check if current selectors still match\r
+                                       each(currentSelectors, function(callbacks, selector) {\r
+                                               if (!matchedSelectors[selector]) {\r
+                                                       delete currentSelectors[selector];\r
+\r
+                                                       each(callbacks, function(callback) {\r
+                                                               callback(false, {node: node, selector: selector, parents: parents});\r
+                                                       });\r
+                                               }\r
+                                       });\r
+                               });\r
+                       }\r
+\r
+                       // Add selector listeners\r
+                       if (!self.selectorChangedData[selector]) {\r
+                               self.selectorChangedData[selector] = [];\r
+                       }\r
+\r
+                       self.selectorChangedData[selector].push(callback);\r
 \r
-                       t.win = null;\r
+                       return self;\r
+               },\r
+\r
+               scrollIntoView: function(elm) {\r
+                       var y, viewPort, self = this, dom = self.dom;\r
+\r
+                       viewPort = dom.getViewPort(self.editor.getWin());\r
+                       y = dom.getPos(elm).y;\r
+                       if (y < viewPort.y || y + 25 > viewPort.y + viewPort.h) {\r
+                               self.editor.getWin().scrollTo(0, y < viewPort.y ? y : y - viewPort.h + 25);\r
+                       }\r
+               },\r
+\r
+               destroy : function(manual) {\r
+                       var self = this;\r
+\r
+                       self.win = null;\r
 \r
                        // Manual destroy then remove unload handler\r
-                       if (!s)\r
-                               tinymce.removeUnload(t.destroy);\r
+                       if (!manual)\r
+                               tinymce.removeUnload(self.destroy);\r
                },\r
 \r
                // IE has an issue where you can't select/move the caret by clicking outside the body if the document is in standards mode\r
@@ -9956,6 +10513,18 @@ window.tinymce.dom.Sizzle = Sizzle;
                        }\r
                });\r
 \r
+               htmlParser.addNodeFilter('noscript', function(nodes) {\r
+                       var i = nodes.length, node;\r
+\r
+                       while (i--) {\r
+                               node = nodes[i].firstChild;\r
+\r
+                               if (node) {\r
+                                       node.value = tinymce.html.Entities.decode(node.value);\r
+                               }\r
+                       }\r
+               });\r
+\r
                // Force script into CDATA sections and remove the mce- prefix also add comments around styles\r
                htmlParser.addNodeFilter('script,style', function(nodes, name) {\r
                        var i = nodes.length, node, value;\r
@@ -10113,7 +10682,7 @@ window.tinymce.dom.Sizzle = Sizzle;
 \r
                                // Replace all BOM characters for now until we can find a better solution\r
                                if (!args.cleanup)\r
-                                       args.content = args.content.replace(/\uFEFF|\u200B/g, '');\r
+                                       args.content = args.content.replace(/\uFEFF/g, '');\r
 \r
                                // Post process\r
                                if (!args.no_events)\r
@@ -10207,11 +10776,10 @@ window.tinymce.dom.Sizzle = Sizzle;
                        }\r
 \r
                        // Create new script element\r
-                       elm = dom.create('script', {\r
-                               id : id,\r
-                               type : 'text/javascript',\r
-                               src : tinymce._addVer(url)\r
-                       });\r
+                       elm = document.createElement('script');\r
+                       elm.id = id;\r
+                       elm.type = 'text/javascript';\r
+                       elm.src = tinymce._addVer(url);\r
 \r
                        // Add onload listener for non IE browsers since IE9\r
                        // fires onload event before the script is parsed and executed\r
@@ -10575,12 +11143,15 @@ window.tinymce.dom.Sizzle = Sizzle;
 \r
                        t.destroy = function() {\r
                                each(items, function(item) {\r
-                                       dom.unbind(dom.get(item.id), 'focus', itemFocussed);\r
-                                       dom.unbind(dom.get(item.id), 'blur', itemBlurred);\r
+                                       var elm = dom.get(item.id);\r
+\r
+                                       dom.unbind(elm, 'focus', itemFocussed);\r
+                                       dom.unbind(elm, 'blur', itemBlurred);\r
                                });\r
 \r
-                               dom.unbind(dom.get(root), 'focus', rootFocussed);\r
-                               dom.unbind(dom.get(root), 'keydown', rootKeydown);\r
+                               var rootElm = dom.get(root);\r
+                               dom.unbind(rootElm, 'focus', rootFocussed);\r
+                               dom.unbind(rootElm, 'keydown', rootKeydown);\r
 \r
                                items = dom = root = t.focus = itemFocussed = itemBlurred = rootKeydown = rootFocussed = null;\r
                                t.destroy = function() {};\r
@@ -10659,21 +11230,23 @@ window.tinymce.dom.Sizzle = Sizzle;
 \r
                        // Set up state and listeners for each item.\r
                        each(items, function(item, idx) {\r
-                               var tabindex;\r
+                               var tabindex, elm;\r
 \r
                                if (!item.id) {\r
                                        item.id = dom.uniqueId('_mce_item_');\r
                                }\r
 \r
+                               elm = dom.get(item.id);\r
+\r
                                if (excludeFromTabOrder) {\r
-                                       dom.bind(item.id, 'blur', itemBlurred);\r
+                                       dom.bind(elm, 'blur', itemBlurred);\r
                                        tabindex = '-1';\r
                                } else {\r
                                        tabindex = (idx === 0 ? '0' : '-1');\r
                                }\r
 \r
-                               dom.setAttrib(item.id, 'tabindex', tabindex);\r
-                               dom.bind(dom.get(item.id), 'focus', itemFocussed);\r
+                               elm.setAttribute('tabindex', tabindex);\r
+                               dom.bind(elm, 'focus', itemFocussed);\r
                        });\r
                        \r
                        // Setup initial state for root element.\r
@@ -10682,10 +11255,11 @@ window.tinymce.dom.Sizzle = Sizzle;
                        }\r
 \r
                        dom.setAttrib(root, 'tabindex', '-1');\r
-                       \r
+\r
                        // Setup listeners for root element.\r
-                       dom.bind(dom.get(root), 'focus', rootFocussed);\r
-                       dom.bind(dom.get(root), 'keydown', rootKeydown);\r
+                       var rootElm = dom.get(root);\r
+                       dom.bind(rootElm, 'focus', rootFocussed);\r
+                       dom.bind(rootElm, 'keydown', rootKeydown);\r
                }\r
        });\r
 })(tinymce);\r
@@ -11326,7 +11900,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                        l = DOM.encode(s.label || '');\r
                        h = '<a role="button" id="' + this.id + '" href="javascript:;" class="' + cp + ' ' + cp + 'Enabled ' + s['class'] + (l ? ' ' + cp + 'Labeled' : '') +'" onmousedown="return false;" onclick="return false;" aria-labelledby="' + this.id + '_voice" title="' + DOM.encode(s.title) + '">';\r
                        if (s.image && !(this.editor  &&this.editor.forcedHighContrastMode) )\r
-                               h += '<img class="mceIcon" src="' + s.image + '" alt="' + DOM.encode(s.title) + '" />' + l;\r
+                               h += '<span class="mceIcon ' + s['class'] + '"><img class="mceIcon" src="' + s.image + '" alt="' + DOM.encode(s.title) + '" /></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '');\r
                        else\r
                                h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '');\r
 \r
@@ -12034,6 +12608,16 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                                DOM.select('a', t.id + '_menu')[0].focus(); // Select first link\r
                        }\r
 \r
+                       t.keyboardNav = new tinymce.ui.KeyboardNavigation({\r
+                               root: t.id + '_menu',\r
+                               items: DOM.select('a', t.id + '_menu'),\r
+                               onCancel: function() {\r
+                                       t.hideMenu();\r
+                                       t.focus();\r
+                               }\r
+                       });\r
+\r
+                       t.keyboardNav.focus();\r
                        t.isMenuVisible = 1;\r
                },\r
 \r
@@ -12054,6 +12638,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
 \r
                                t.isMenuVisible = 0;\r
                                t.onHideMenu.dispatch();\r
+                               t.keyboardNav.destroy();\r
                        }\r
                },\r
 \r
@@ -12118,15 +12703,6 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                        }\r
 \r
                        DOM.addClass(m, 'mceColorSplitMenu');\r
-                       \r
-                       new tinymce.ui.KeyboardNavigation({\r
-                               root: t.id + '_menu',\r
-                               items: DOM.select('a', t.id + '_menu'),\r
-                               onCancel: function() {\r
-                                       t.hideMenu();\r
-                                       t.focus();\r
-                               }\r
-                       });\r
 \r
                        // Prevent IE from scrolling and hindering click to occur #4019\r
                        Event.add(t.id + '_menu', 'mousedown', function(e) {return Event.cancel(e);});\r
@@ -12168,11 +12744,17 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                },\r
 \r
                destroy : function() {\r
-                       this.parent();\r
+                       var self = this;\r
+\r
+                       self.parent();\r
+\r
+                       Event.clear(self.id + '_menu');\r
+                       Event.clear(self.id + '_more');\r
+                       DOM.remove(self.id + '_menu');\r
 \r
-                       Event.clear(this.id + '_menu');\r
-                       Event.clear(this.id + '_more');\r
-                       DOM.remove(this.id + '_menu');\r
+                       if (self.keyboardNav) {\r
+                               self.keyboardNav.destroy();\r
+                       }\r
                }\r
        });\r
 })(tinymce);\r
@@ -12483,11 +13065,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                return c.constructor === RegExp ? c.test(n.className) : DOM.hasClass(n, c);\r
                        };\r
 \r
-                       s = extend({\r
-                               theme : "simple",\r
-                               language : "en"\r
-                       }, s);\r
-\r
                        t.settings = s;\r
 \r
                        // Legacy call\r
@@ -12589,6 +13166,9 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        if (id === undef)\r
                                return this.editors;\r
 \r
+                       if (!this.editors.hasOwnProperty(id))\r
+                               return undef;\r
+\r
                        return this.editors[id];\r
                },\r
 \r
@@ -12767,7 +13347,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        self.settings = settings = extend({\r
                                id : id,\r
                                language : 'en',\r
-                               theme : 'simple',\r
+                               theme : 'advanced',\r
                                skin : 'default',\r
                                delta_width : 0,\r
                                delta_height : 0,\r
@@ -12798,8 +13378,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                inline_styles : TRUE,\r
                                convert_fonts_to_spans : TRUE,\r
                                indent : 'simple',\r
-                               indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure',\r
-                               indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure',\r
+                               indent_before : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist',\r
+                               indent_after : 'p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,ul,li,area,table,thead,tfoot,tbody,tr,section,article,hgroup,aside,figure,option,optgroup,datalist',\r
                                validate : TRUE,\r
                                entity_encoding : 'named',\r
                                url_converter : self.convertURL,\r
@@ -12821,6 +13401,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
 \r
                        self.contentCSS = [];\r
 \r
+                       self.contentStyles = [];\r
+\r
                        // Creates all events like onClick, onSetContent etc see Editor.Events.js for the actual logic\r
                        self.setupEvents();\r
 \r
@@ -12859,6 +13441,12 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form'))\r
                                DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id);\r
 \r
+                       // Hide target element early to prevent content flashing\r
+                       if (!s.content_editable) {\r
+                               t.orgVisibility = t.getElement().style.visibility;\r
+                               t.getElement().style.visibility = 'hidden';\r
+                       }\r
+\r
                        if (tinymce.WindowManager)\r
                                t.windowManager = new tinymce.WindowManager(t);\r
 \r
@@ -12920,7 +13508,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                if (s.language && s.language_load !== false)\r
                                        sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');\r
 \r
-                               if (s.theme && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])\r
+                               if (s.theme && typeof s.theme != "function" && s.theme.charAt(0) != '-' && !ThemeManager.urls[s.theme])\r
                                        ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');\r
 \r
                                each(explode(s.plugins), function(p) {\r
@@ -12954,20 +13542,25 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                },\r
 \r
                init : function() {\r
-                       var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti, u, bi, bc, re, i, initializedPlugins = [];\r
+                       var n, t = this, s = t.settings, w, h, mh, e = t.getElement(), o, ti, u, bi, bc, re, i, initializedPlugins = [];\r
 \r
                        tinymce.add(t);\r
 \r
                        s.aria_label = s.aria_label || DOM.getAttrib(e, 'aria-label', t.getLang('aria.rich_text_area'));\r
 \r
                        if (s.theme) {\r
-                               s.theme = s.theme.replace(/-/, '');\r
-                               o = ThemeManager.get(s.theme);\r
-                               t.theme = new o();\r
+                               if (typeof s.theme != "function") {\r
+                                       s.theme = s.theme.replace(/-/, '');\r
+                                       o = ThemeManager.get(s.theme);\r
+                                       t.theme = new o();\r
 \r
-                               if (t.theme.init)\r
-                                       t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, ''));\r
+                                       if (t.theme.init)\r
+                                               t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, ''));\r
+                               } else {\r
+                                       t.theme = s.theme;\r
+                               }\r
                        }\r
+\r
                        function initPlugin(p) {\r
                                var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po;\r
                                if (c && tinymce.inArray(initializedPlugins,p) === -1) {\r
@@ -13001,36 +13594,68 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
 \r
                        t.controlManager = new tinymce.ControlManager(t);\r
 \r
-                       t.onExecCommand.add(function(ed, c) {\r
-                               // Don't refresh the select lists until caret move\r
-                               if (!/^(FontName|FontSize)$/.test(c))\r
-                                       t.nodeChanged();\r
-                       });\r
-\r
                        // Enables users to override the control factory\r
                        t.onBeforeRenderUI.dispatch(t, t.controlManager);\r
 \r
                        // Measure box\r
                        if (s.render_ui && t.theme) {\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
-                               if (re.test('' + w))\r
-                                       w = Math.max(parseInt(w, 10) + (o.deltaWidth || 0), 100);\r
+                               if (typeof s.theme != "function") {\r
+                                       w = s.width || e.style.width || e.offsetWidth;\r
+                                       h = s.height || e.style.height || e.offsetHeight;\r
+                                       mh = s.min_height || 100;\r
+                                       re = /^[0-9\.]+(|px)$/i;\r
+\r
+                                       if (re.test('' + w))\r
+                                               w = Math.max(parseInt(w, 10) + (o.deltaWidth || 0), 100);\r
+\r
+                                       if (re.test('' + h))\r
+                                               h = Math.max(parseInt(h, 10) + (o.deltaHeight || 0), mh);\r
+\r
+                                       // Render UI\r
+                                       o = t.theme.renderUI({\r
+                                               targetNode : e,\r
+                                               width : w,\r
+                                               height : h,\r
+                                               deltaWidth : s.delta_width,\r
+                                               deltaHeight : s.delta_height\r
+                                       });\r
 \r
-                               if (re.test('' + h))\r
-                                       h = Math.max(parseInt(h, 10) + (o.deltaHeight || 0), 100);\r
+                                       // Resize editor\r
+                                       DOM.setStyles(o.sizeContainer || o.editorContainer, {\r
+                                               width : w,\r
+                                               height : h\r
+                                       });\r
 \r
-                               // Render UI\r
-                               o = t.theme.renderUI({\r
-                                       targetNode : e,\r
-                                       width : w,\r
-                                       height : h,\r
-                                       deltaWidth : s.delta_width,\r
-                                       deltaHeight : s.delta_height\r
-                               });\r
+                                       h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : '');\r
+                                       if (h < mh)\r
+                                               h = mh;\r
+                               } else {\r
+                                       o = s.theme(t, e);\r
+\r
+                                       // Convert element type to id:s\r
+                                       if (o.editorContainer.nodeType) {\r
+                                               o.editorContainer = o.editorContainer.id = o.editorContainer.id || t.id + "_parent";\r
+                                       }\r
+\r
+                                       // Convert element type to id:s\r
+                                       if (o.iframeContainer.nodeType) {\r
+                                               o.iframeContainer = o.iframeContainer.id = o.iframeContainer.id || t.id + "_iframecontainer";\r
+                                       }\r
+\r
+                                       // Use specified iframe height or the targets offsetHeight\r
+                                       h = o.iframeHeight || e.offsetHeight;\r
+\r
+                                       // Store away the selection when it's changed to it can be restored later with a editor.focus() call\r
+                                       if (isIE) {\r
+                                               t.onInit.add(function(ed) {\r
+                                                       ed.dom.bind(ed.getBody(), 'beforedeactivate keydown', function() {\r
+                                                               ed.lastIERng = ed.selection.getRng();\r
+                                                       });\r
+                                               });\r
+                                       }\r
+                               }\r
 \r
                                t.editorContainer = o.editorContainer;\r
                        }\r
@@ -13042,6 +13667,11 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                });\r
                        }\r
 \r
+                       // Load specified content CSS last\r
+                       if (s.content_style) {\r
+                               t.contentStyles.push(s.content_style);\r
+                       }\r
+\r
                        // Content editable mode ends here\r
                        if (s.content_editable) {\r
                                e = n = o = null; // Fix IE leak\r
@@ -13052,16 +13682,6 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        if (document.domain && location.hostname != document.domain)\r
                                tinymce.relaxedDomain = document.domain;\r
 \r
-                       // Resize editor\r
-                       DOM.setStyles(o.sizeContainer || o.editorContainer, {\r
-                               width : w,\r
-                               height : h\r
-                       });\r
-\r
-                       h = (o.iframeHeight || h) + (typeof(h) == 'number' ? (o.deltaHeight || 0) : '');\r
-                       if (h < 100)\r
-                               h = 100;\r
-\r
                        t.iframeHTML = s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml">';\r
 \r
                        // We only need to override paths if we have to\r
@@ -13070,10 +13690,12 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                t.iframeHTML += '<base href="' + t.documentBaseURI.getURI() + '" />';\r
 \r
                        // IE8 doesn't support carets behind images setting ie7_compat would force IE8+ to run in IE7 compat mode.\r
-                       if (s.ie7_compat)\r
-                               t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=7" />';\r
-                       else\r
-                               t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=edge" />';\r
+                       if (tinymce.isIE8) {\r
+                               if (s.ie7_compat)\r
+                                       t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=7" />';\r
+                               else\r
+                                       t.iframeHTML += '<meta http-equiv="X-UA-Compatible" content="IE=edge" />';\r
+                       }\r
 \r
                        t.iframeHTML += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';\r
 \r
@@ -13120,7 +13742,14 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        });\r
 \r
                        t.contentAreaContainer = o.iframeContainer;\r
-                       DOM.get(o.editorContainer).style.display = t.orgDisplay;\r
+\r
+                       if (o.editorContainer) {\r
+                               DOM.get(o.editorContainer).style.display = t.orgDisplay;\r
+                       }\r
+\r
+                       // Restore visibility on target element\r
+                       e.style.visibility = t.orgVisibility;\r
+\r
                        DOM.get(t.id).style.display = 'none';\r
                        DOM.setAttrib(t.id, 'aria-hidden', true);\r
 \r
@@ -13131,7 +13760,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                },\r
 \r
                initContentBody : function() {\r
-                       var self = this, settings = self.settings, targetElm = DOM.get(self.id), doc = self.getDoc(), html, body;\r
+                       var self = this, settings = self.settings, targetElm = DOM.get(self.id), doc = self.getDoc(), html, body, contentCssText;\r
 \r
                        // Setup iframe body\r
                        if ((!isIE || !tinymce.relaxedDomain) && !settings.content_editable) {\r
@@ -13230,7 +13859,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
 \r
                        self.serializer = new tinymce.dom.Serializer(settings, self.dom, self.schema);\r
 \r
-                       self.selection = new tinymce.dom.Selection(self.dom, self.getWin(), self.serializer);\r
+                       self.selection = new tinymce.dom.Selection(self.dom, self.getWin(), self.serializer, self);\r
 \r
                        self.formatter = new tinymce.Formatter(self);\r
 \r
@@ -13240,6 +13869,12 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        self.enterKey = new tinymce.EnterKey(self);\r
                        self.editorCommands = new tinymce.EditorCommands(self);\r
 \r
+                       self.onExecCommand.add(function(editor, command) {\r
+                               // Don't refresh the select lists until caret move\r
+                               if (!/^(FontName|FontSize)$/.test(command))\r
+                                       self.nodeChanged();\r
+                       });\r
+\r
                        // Pass through\r
                        self.serializer.onPreProcess.add(function(se, o) {\r
                                return self.onPreProcess.dispatch(self, o, se);\r
@@ -13251,7 +13886,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
 \r
                        self.onPreInit.dispatch(self);\r
 \r
-                       if (!settings.gecko_spellcheck)\r
+                       if (!settings.browser_spellcheck && !settings.gecko_spellcheck)\r
                                doc.body.spellcheck = false;\r
 \r
                        if (!settings.readonly) {\r
@@ -13302,6 +13937,17 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        self.focus(true);\r
                        self.nodeChanged({initial : true});\r
 \r
+                       // Add editor specific CSS styles\r
+                       if (self.contentStyles.length > 0) {\r
+                               contentCssText = '';\r
+\r
+                               each(self.contentStyles, function(style) {\r
+                                       contentCssText += style + "\r\n";\r
+                               });\r
+\r
+                               self.dom.addStyle(contentCssText);\r
+                       }\r
+\r
                        // Load specified content CSS last\r
                        each(self.contentCSS, function(url) {\r
                                self.dom.loadCSS(url);\r
@@ -13327,6 +13973,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        var oed, self = this, selection = self.selection, contentEditable = self.settings.content_editable, ieRng, controlElm, doc = self.getDoc(), body;\r
 \r
                        if (!skip_focus) {\r
+                               if (self.lastIERng) {\r
+                                       selection.setRng(self.lastIERng);\r
+                               }\r
+\r
                                // Get selected control element\r
                                ieRng = selection.getRng();\r
                                if (ieRng.item) {\r
@@ -13673,6 +14323,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
 \r
                        // We must save before we hide so Safari doesn't crash\r
                        self.save();\r
+\r
+                       // defer the call to hide to prevent an IE9 crash #4921\r
                        DOM.hide(self.getContainer());\r
                        DOM.setStyle(self.id, 'display', self.orgDisplay);\r
                },\r
@@ -13789,13 +14441,16 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        if (!args.no_events)\r
                                self.onSetContent.dispatch(self, args);\r
 \r
-                       self.selection.normalize();\r
+                       // Don't normalize selection if the focused element isn't the body in content editable mode since it will steal focus otherwise\r
+                       if (!self.settings.content_editable || document.activeElement === self.getBody()) {\r
+                               self.selection.normalize();\r
+                       }\r
 \r
                        return args.content;\r
                },\r
 \r
                getContent : function(args) {\r
-                       var self = this, content;\r
+                       var self = this, content, body = self.getBody();\r
 \r
                        // Setup args object\r
                        args = args || {};\r
@@ -13809,11 +14464,18 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
 \r
                        // Get raw contents or by default the cleaned contents\r
                        if (args.format == 'raw')\r
-                               content = self.getBody().innerHTML;\r
+                               content = body.innerHTML;\r
+                       else if (args.format == 'text')\r
+                               content = body.innerText || body.textContent;\r
                        else\r
-                               content = self.serializer.serialize(self.getBody(), args);\r
+                               content = self.serializer.serialize(body, args);\r
 \r
-                       args.content = tinymce.trim(content);\r
+                       // Trim whitespace in beginning/end of HTML\r
+                       if (args.format != 'text') {\r
+                               args.content = tinymce.trim(content);\r
+                       } else {\r
+                               args.content = content;\r
+                       }\r
 \r
                        // Do post processing\r
                        if (!args.no_events)\r
@@ -13922,14 +14584,16 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                                return;\r
 \r
                                        case 'A':\r
-                                               value = dom.getAttrib(elm, 'name');\r
-                                               cls = 'mceItemAnchor';\r
+                                               if (!dom.getAttrib(elm, 'href', false)) {\r
+                                                       value = dom.getAttrib(elm, 'name') || elm.id;\r
+                                                       cls = 'mceItemAnchor';\r
 \r
-                                               if (value) {\r
-                                                       if (self.hasVisual)\r
-                                                               dom.addClass(elm, cls);\r
-                                                       else\r
-                                                               dom.removeClass(elm, cls);\r
+                                                       if (value) {\r
+                                                               if (self.hasVisual)\r
+                                                                       dom.addClass(elm, cls);\r
+                                                               else\r
+                                                                       dom.removeClass(elm, cls);\r
+                                                       }\r
                                                }\r
 \r
                                                return;\r
@@ -13940,22 +14604,29 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                },\r
 \r
                remove : function() {\r
-                       var self = this, elm = self.getContainer();\r
+                       var self = this, elm = self.getContainer(), doc = self.getDoc();\r
 \r
                        if (!self.removed) {\r
                                self.removed = 1; // Cancels post remove event execution\r
-                               self.hide();\r
+\r
+                               // Fixed bug where IE has a blinking cursor left from the editor\r
+                               if (isIE && doc)\r
+                                       doc.execCommand('SelectAll');\r
+\r
+                               // We must save before we hide so Safari doesn't crash\r
+                               self.save();\r
+\r
+                               DOM.setStyle(self.id, 'display', self.orgDisplay);\r
 \r
                                // Don't clear the window or document if content editable\r
                                // is enabled since other instances might still be present\r
                                if (!self.settings.content_editable) {\r
-                                       Event.clear(self.getWin());\r
-                                       Event.clear(self.getDoc());\r
+                                       Event.unbind(self.getWin());\r
+                                       Event.unbind(self.getDoc());\r
                                }\r
 \r
-                               Event.clear(self.getBody());\r
-                               Event.clear(self.formElement);\r
-                               Event.unbind(elm);\r
+                               Event.unbind(self.getBody());\r
+                               Event.clear(elm);\r
 \r
                                self.execCallback('remove_instance_callback', self);\r
                                self.onRemove.dispatch(self);\r
@@ -14157,8 +14828,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                // Handle legacy handle_event_callback option\r
                if (settings.handle_event_callback) {\r
                        self.onEvent.add(function(ed, e, o) {\r
-                               if (self.execCallback('handle_event_callback', e, ed, o) === false)\r
-                                       Event.cancel(e);\r
+                               if (self.execCallback('handle_event_callback', e, ed, o) === false) {\r
+                                       e.preventDefault();\r
+                                       e.stopPropagation();\r
+                               }\r
                        });\r
                }\r
 \r
@@ -14224,9 +14897,12 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        self.focus(true);\r
                };\r
 \r
-               function nodeChanged() {\r
-                       // Normalize selection for example <b>a</b><i>|a</i> becomes <b>a|</b><i>a</i>\r
-                       self.selection.normalize();\r
+               function nodeChanged(ed, e) {\r
+                       // Normalize selection for example <b>a</b><i>|a</i> becomes <b>a|</b><i>a</i> except for Ctrl+A since it selects everything\r
+                       if (e.keyCode != 65 || !tinymce.VK.metaKeyPressed(e)) {\r
+                               self.selection.normalize();\r
+                       }\r
+\r
                        self.nodeChanged();\r
                }\r
 \r
@@ -14270,7 +14946,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        var keyCode = e.keyCode;\r
 \r
                        if ((keyCode >= 33 && keyCode <= 36) || (keyCode >= 37 && keyCode <= 40) || keyCode == 13 || keyCode == 45 || keyCode == 46 || keyCode == 8 || (tinymce.isMac && (keyCode == 91 || keyCode == 93)) || e.ctrlKey)\r
-                               nodeChanged();\r
+                               nodeChanged(ed, e);\r
                });\r
 \r
                // Add reset handler\r
@@ -14623,7 +15299,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
 \r
                                        // Insert bookmark node and get the parent\r
                                        selection.setContent(bookmarkHtml);\r
-                                       parentNode = editor.selection.getNode();\r
+                                       parentNode = selection.getNode();\r
                                        rootNode = editor.getBody();\r
 \r
                                        // Opera will return the document node when selection is in root\r
@@ -14697,6 +15373,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                editor.setContent(editor.getContent().replace(/tiny_mce_marker/g, function() { return value }));\r
                        },\r
 \r
+                       mceToggleFormat : function(command, ui, value) {\r
+                               toggleFormat(value);\r
+                       },\r
+\r
                        mceSetContent : function(command, ui, value) {\r
                                editor.setContent(value);\r
                        },\r
@@ -14786,10 +15466,15 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        selectAll : function() {\r
                                var root = dom.getRoot(), rng = dom.createRng();\r
 \r
-                               rng.setStart(root, 0);\r
-                               rng.setEnd(root, root.childNodes.length);\r
+                               // Old IE does a better job with selectall than new versions\r
+                               if (selection.getRng().setStart) {\r
+                                       rng.setStart(root, 0);\r
+                                       rng.setEnd(root, root.childNodes.length);\r
 \r
-                               editor.selection.setRng(rng);\r
+                                       selection.setRng(rng);\r
+                               } else {\r
+                                       execNativeCommand('SelectAll');\r
+                               }\r
                        }\r
                });\r
 \r
@@ -14828,7 +15513,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        },\r
 \r
                        'InsertUnorderedList,InsertOrderedList' : function(command) {\r
-                               return dom.getParent(selection.getNode(), command == 'insertunorderedlist' ? 'UL' : 'OL');\r
+                               var list = dom.getParent(selection.getNode(), 'ul,ol');\r
+                               return list && \r
+                                    (command === 'insertunorderedlist' && list.tagName === 'UL'\r
+                                  || command === 'insertorderedlist' && list.tagName === 'OL');\r
                        }\r
                }, 'state');\r
 \r
@@ -14878,9 +15566,10 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                };\r
 \r
                // Create event instances\r
-               onAdd = new Dispatcher(self);\r
-               onUndo = new Dispatcher(self);\r
-               onRedo = new Dispatcher(self);\r
+               onBeforeAdd = new Dispatcher(self);\r
+               onAdd       = new Dispatcher(self);\r
+               onUndo      = new Dispatcher(self);\r
+               onRedo      = new Dispatcher(self);\r
 \r
                // Pass though onAdd event from UndoManager to Editor as onChange\r
                onAdd.add(function(undoman, level) {\r
@@ -14920,7 +15609,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                // Add undo level on save contents, drag end and blur/focusout\r
                editor.onSaveContent.add(addNonTypingUndoLevel);\r
                editor.dom.bind(editor.dom.getRoot(), 'dragend', addNonTypingUndoLevel);\r
-               editor.dom.bind(editor.getDoc(), tinymce.isGecko ? 'blur' : 'focusout', function(e) {\r
+               editor.dom.bind(editor.getBody(), 'focusout', function(e) {\r
                        if (!editor.removed && self.typing) {\r
                                addNonTypingUndoLevel();\r
                        }\r
@@ -14969,6 +15658,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                        data : data,\r
 \r
                        typing : false,\r
+                       \r
+                       onBeforeAdd: onBeforeAdd,\r
 \r
                        onAdd : onAdd,\r
 \r
@@ -14985,6 +15676,8 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
 \r
                                level = level || {};\r
                                level.content = getContent();\r
+                               \r
+                               self.onBeforeAdd.dispatch(self, level);\r
 \r
                                // Add undo level if needed\r
                                lastLevel = data[index];\r
@@ -15080,7 +15773,7 @@ tinymce.ForceBlocks = function(editor) {
        var settings = editor.settings, dom = editor.dom, selection = editor.selection, blockElements = editor.schema.getBlockElements();\r
 \r
        function addRootBlocks() {\r
-               var node = selection.getStart(), rootNode = editor.getBody(), rng, startContainer, startOffset, endContainer, endOffset, rootBlockNode, tempNode, offset = -0xFFFFFF, wrapped;\r
+               var node = selection.getStart(), rootNode = editor.getBody(), rng, startContainer, startOffset, endContainer, endOffset, rootBlockNode, tempNode, offset = -0xFFFFFF, wrapped, isInEditorDocument;\r
 \r
                if (!node || node.nodeType !== 1 || !settings.forced_root_block)\r
                        return;\r
@@ -15108,6 +15801,7 @@ tinymce.ForceBlocks = function(editor) {
                                rng.moveToElementText(node);\r
                        }\r
 \r
+                       isInEditorDocument = rng.parentElement().ownerDocument === editor.getDoc();\r
                        tmpRng = rng.duplicate();\r
                        tmpRng.collapse(true);\r
                        startOffset = tmpRng.move('character', offset) * -1;\r
@@ -15123,6 +15817,14 @@ tinymce.ForceBlocks = function(editor) {
                node = rootNode.firstChild;\r
                while (node) {\r
                        if (node.nodeType === 3 || (node.nodeType == 1 && !blockElements[node.nodeName])) {\r
+                               // Remove empty text nodes\r
+                               if (node.nodeType === 3 && node.nodeValue.length == 0) {\r
+                                       tempNode = node;\r
+                                       node = node.nextSibling;\r
+                                       dom.remove(tempNode);\r
+                                       continue;\r
+                               }\r
+\r
                                if (!rootBlockNode) {\r
                                        rootBlockNode = dom.create(settings.forced_root_block);\r
                                        node.parentNode.insertBefore(rootBlockNode, node);\r
@@ -15138,28 +15840,30 @@ tinymce.ForceBlocks = function(editor) {
                        }\r
                }\r
 \r
-               if (rng.setStart) {\r
-                       rng.setStart(startContainer, startOffset);\r
-                       rng.setEnd(endContainer, endOffset);\r
-                       selection.setRng(rng);\r
-               } else {\r
-                       try {\r
-                               rng = editor.getDoc().body.createTextRange();\r
-                               rng.moveToElementText(rootNode);\r
-                               rng.collapse(true);\r
-                               rng.moveStart('character', startOffset);\r
+               if (wrapped) {\r
+                       if (rng.setStart) {\r
+                               rng.setStart(startContainer, startOffset);\r
+                               rng.setEnd(endContainer, endOffset);\r
+                               selection.setRng(rng);\r
+                       } else {\r
+                               // Only select if the previous selection was inside the document to prevent auto focus in quirks mode\r
+                               if (isInEditorDocument) {\r
+                                       try {\r
+                                               rng = editor.getDoc().body.createTextRange();\r
+                                               rng.moveToElementText(rootNode);\r
+                                               rng.collapse(true);\r
+                                               rng.moveStart('character', startOffset);\r
 \r
-                               if (endOffset > 0)\r
-                                       rng.moveEnd('character', endOffset);\r
+                                               if (endOffset > 0)\r
+                                                       rng.moveEnd('character', endOffset);\r
 \r
-                               rng.select();\r
-                       } catch (ex) {\r
-                               // Ignore\r
+                                               rng.select();\r
+                                       } catch (ex) {\r
+                                               // Ignore\r
+                                       }\r
+                               }\r
                        }\r
-               }\r
 \r
-               // Only trigger nodeChange when we wrapped nodes to prevent a forever loop\r
-               if (wrapped) {\r
                        editor.nodeChanged();\r
                }\r
        };\r
@@ -15227,28 +15931,40 @@ tinymce.ForceBlocks = function(editor) {
                        return c;\r
                },\r
 \r
-               createControl : function(n) {\r
-                       var c, t = this, ed = t.editor;\r
+               createControl : function(name) {\r
+                       var ctrl, i, l, self = this, editor = self.editor, factories, ctrlName;\r
 \r
-                       each(ed.plugins, function(p) {\r
-                               if (p.createControl) {\r
-                                       c = p.createControl(n, t);\r
+                       // Build control factory cache\r
+                       if (!self.controlFactories) {\r
+                               self.controlFactories = [];\r
+                               each(editor.plugins, function(plugin) {\r
+                                       if (plugin.createControl) {\r
+                                               self.controlFactories.push(plugin);\r
+                                       }\r
+                               });\r
+                       }\r
 \r
-                                       if (c)\r
-                                               return false;\r
+                       // Create controls by asking cached factories\r
+                       factories = self.controlFactories;\r
+                       for (i = 0, l = factories.length; i < l; i++) {\r
+                               ctrl = factories[i].createControl(name, self);\r
+\r
+                               if (ctrl) {\r
+                                       return self.add(ctrl);\r
                                }\r
-                       });\r
+                       }\r
 \r
-                       switch (n) {\r
-                               case "|":\r
-                               case "separator":\r
-                                       return t.createSeparator();\r
+                       // Create sepearator\r
+                       if (name === "|" || name === "separator") {\r
+                               return self.createSeparator();\r
                        }\r
 \r
-                       if (!c && ed.buttons && (c = ed.buttons[n]))\r
-                               return t.createButton(n, c);\r
+                       // Create control from button collection\r
+                       if (editor.buttons && (ctrl = editor.buttons[name])) {\r
+                               return self.createButton(name, ctrl);\r
+                       }\r
 \r
-                       return t.add(c);\r
+                       return self.add(ctrl);\r
                },\r
 \r
                createDropMenu : function(id, s, cc) {\r
@@ -15676,19 +16392,21 @@ tinymce.ForceBlocks = function(editor) {
                        TreeWalker = tinymce.dom.TreeWalker,\r
                        rangeUtils = new tinymce.dom.RangeUtils(dom),\r
                        isValid = ed.schema.isValidChild,\r
+                       isArray = tinymce.isArray,\r
                        isBlock = dom.isBlock,\r
                        forcedRootBlock = ed.settings.forced_root_block,\r
                        nodeIndex = dom.nodeIndex,\r
-                       INVISIBLE_CHAR = tinymce.isGecko ? '\u200B' : '\uFEFF',\r
+                       INVISIBLE_CHAR = '\uFEFF',\r
                        MCE_ATTR_RE = /^(src|href|style)$/,\r
                        FALSE = false,\r
                        TRUE = true,\r
+                       formatChangeData,\r
                        undef,\r
                        getContentEditable = dom.getContentEditable;\r
 \r
-               function isArray(obj) {\r
-                       return obj instanceof Array;\r
-               };\r
+               function isTextBlock(name) {\r
+                       return !!ed.schema.getTextBlocks()[name.toLowerCase()];\r
+               }\r
 \r
                function getParents(node, selector) {\r
                        return dom.getParents(node, selector, dom.getRoot());\r
@@ -16254,6 +16972,11 @@ tinymce.ForceBlocks = function(editor) {
                        function process(node) {\r
                                var children, i, l, localContentEditable, lastContentEditable, hasContentEditableState;\r
 \r
+                               // Skip on text nodes as they have neither format to remove nor children\r
+                               if (node.nodeType === 3) {\r
+                                       return;\r
+                               }\r
+\r
                                // Node has a contentEditable value\r
                                if (node.nodeType === 1 && getContentEditable(node)) {\r
                                        lastContentEditable = contentEditable;\r
@@ -16564,7 +17287,7 @@ tinymce.ForceBlocks = function(editor) {
                                                matchedFormatNames.push(name);\r
                                        }\r
                                }\r
-                       });\r
+                       }, dom.getRoot());\r
 \r
                        return matchedFormatNames;\r
                };\r
@@ -16593,6 +17316,62 @@ tinymce.ForceBlocks = function(editor) {
                        return FALSE;\r
                };\r
 \r
+               function formatChanged(formats, callback, similar) {\r
+                       var currentFormats;\r
+\r
+                       // Setup format node change logic\r
+                       if (!formatChangeData) {\r
+                               formatChangeData = {};\r
+                               currentFormats = {};\r
+\r
+                               ed.onNodeChange.addToTop(function(ed, cm, node) {\r
+                                       var parents = getParents(node), matchedFormats = {};\r
+\r
+                                       // Check for new formats\r
+                                       each(formatChangeData, function(callbacks, format) {\r
+                                               each(parents, function(node) {\r
+                                                       if (matchNode(node, format, {}, callbacks.similar)) {\r
+                                                               if (!currentFormats[format]) {\r
+                                                                       // Execute callbacks\r
+                                                                       each(callbacks, function(callback) {\r
+                                                                               callback(true, {node: node, format: format, parents: parents});\r
+                                                                       });\r
+\r
+                                                                       currentFormats[format] = callbacks;\r
+                                                               }\r
+\r
+                                                               matchedFormats[format] = callbacks;\r
+                                                               return false;\r
+                                                       }\r
+                                               });\r
+                                       });\r
+\r
+                                       // Check if current formats still match\r
+                                       each(currentFormats, function(callbacks, format) {\r
+                                               if (!matchedFormats[format]) {\r
+                                                       delete currentFormats[format];\r
+\r
+                                                       each(callbacks, function(callback) {\r
+                                                               callback(false, {node: node, format: format, parents: parents});\r
+                                                       });\r
+                                               }\r
+                                       });\r
+                               });\r
+                       }\r
+\r
+                       // Add format listeners\r
+                       each(formats.split(','), function(format) {\r
+                               if (!formatChangeData[format]) {\r
+                                       formatChangeData[format] = [];\r
+                                       formatChangeData[format].similar = similar;\r
+                               }\r
+\r
+                               formatChangeData[format].push(callback);\r
+                       });\r
+\r
+                       return this;\r
+               };\r
+\r
                // Expose to public\r
                tinymce.extend(this, {\r
                        get : get,\r
@@ -16603,7 +17382,8 @@ tinymce.ForceBlocks = function(editor) {
                        match : match,\r
                        matchAll : matchAll,\r
                        matchNode : matchNode,\r
-                       canApply : canApply\r
+                       canApply : canApply,\r
+                       formatChanged: formatChanged\r
                });\r
 \r
                // Initialize\r
@@ -16690,6 +17470,10 @@ tinymce.ForceBlocks = function(editor) {
                                siblingName = start ? 'previousSibling' : 'nextSibling';\r
                                root = dom.getRoot();\r
 \r
+                               function isBogusBr(node) {\r
+                                       return node.nodeName == "BR" && node.getAttribute('data-mce-bogus') && !node.nextSibling;\r
+                               };\r
+\r
                                // If it's a text node and the offset is inside the text\r
                                if (container.nodeType == 3 && !isWhiteSpaceNode(container)) {\r
                                        if (start ? startOffset > 0 : endOffset < container.nodeValue.length) {\r
@@ -16704,7 +17488,7 @@ tinymce.ForceBlocks = function(editor) {
 \r
                                        // Walk left/right\r
                                        for (sibling = parent[siblingName]; sibling; sibling = sibling[siblingName]) {\r
-                                               if (!isBookmarkNode(sibling) && !isWhiteSpaceNode(sibling)) {\r
+                                               if (!isBookmarkNode(sibling) && !isWhiteSpaceNode(sibling) && !isBogusBr(sibling)) {\r
                                                        return parent;\r
                                                }\r
                                        }\r
@@ -16863,7 +17647,7 @@ tinymce.ForceBlocks = function(editor) {
 \r
                                // Expand to first wrappable block element or any block element\r
                                if (!node)\r
-                                       node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, isBlock);\r
+                                       node = dom.getParent(container.nodeType == 3 ? container.parentNode : container, isTextBlock);\r
 \r
                                // Exclude inner lists from wrapping\r
                                if (node && format[0].wrapper)\r
@@ -17509,6 +18293,21 @@ tinymce.ForceBlocks = function(editor) {
                                }\r
                        };\r
 \r
+                       // Checks if the parent caret container node isn't empty if that is the case it\r
+                       // will remove the bogus state on all children that isn't empty\r
+                       function unmarkBogusCaretParents() {\r
+                               var i, caretContainer, node;\r
+\r
+                               caretContainer = getParentCaretContainer(selection.getStart());\r
+                               if (caretContainer && !dom.isEmpty(caretContainer)) {\r
+                                       tinymce.walk(caretContainer, function(node) {\r
+                                               if (node.nodeType == 1 && node.id !== caretContainerId && !dom.isEmpty(node)) {\r
+                                                       dom.setAttrib(node, 'data-mce-bogus', null);\r
+                                               }\r
+                                       }, 'childNodes');\r
+                               }\r
+                       };\r
+\r
                        // Only bind the caret events once\r
                        if (!self._hasCaretEvents) {\r
                                // Mark current caret container elements as bogus when getting the contents so we don't end up with empty elements\r
@@ -17528,6 +18327,7 @@ tinymce.ForceBlocks = function(editor) {
                                tinymce.each('onMouseUp onKeyUp'.split(' '), function(name) {\r
                                        ed[name].addToTop(function() {\r
                                                removeCaretContainer();\r
+                                               unmarkBogusCaretParents();\r
                                        });\r
                                });\r
 \r
@@ -17538,16 +18338,12 @@ tinymce.ForceBlocks = function(editor) {
                                        if (keyCode == 8 || keyCode == 37 || keyCode == 39) {\r
                                                removeCaretContainer(getParentCaretContainer(selection.getStart()));\r
                                        }\r
+\r
+                                       unmarkBogusCaretParents();\r
                                });\r
 \r
                                // Remove bogus state if they got filled by contents using editor.selection.setContent\r
-                               selection.onSetContent.add(function() {\r
-                                       dom.getParent(selection.getStart(), function(node) {\r
-                                               if (node.id !== caretContainerId && dom.getAttrib(node, 'data-mce-bogus') && !dom.isEmpty(node)) {\r
-                                                       dom.setAttrib(node, 'data-mce-bogus', null);\r
-                                               }\r
-                                       });\r
-                               });\r
+                               selection.onSetContent.add(unmarkBogusCaretParents);\r
 \r
                                self._hasCaretEvents = true;\r
                        }\r
@@ -17664,21 +18460,63 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
        var TreeWalker = tinymce.dom.TreeWalker;\r
 \r
        tinymce.EnterKey = function(editor) {\r
-               var dom = editor.dom, selection = editor.selection, settings = editor.settings, undoManager = editor.undoManager;\r
+               var dom = editor.dom, selection = editor.selection, settings = editor.settings, undoManager = editor.undoManager, nonEmptyElementsMap = editor.schema.getNonEmptyElements();\r
 \r
                function handleEnterKey(evt) {\r
-                       var rng = selection.getRng(true), tmpRng, editableRoot, container, offset, parentBlock, documentMode,\r
+                       var rng = selection.getRng(true), tmpRng, editableRoot, container, offset, parentBlock, documentMode, shiftKey,\r
                                newBlock, fragment, containerBlock, parentBlockName, containerBlockName, newBlockName, isAfterLastNodeInContainer;\r
 \r
                        // Returns true if the block can be split into two blocks or not\r
                        function canSplitBlock(node) {\r
                                return node &&\r
                                        dom.isBlock(node) &&\r
-                                       !/^(TD|TH|CAPTION)$/.test(node.nodeName) &&\r
+                                       !/^(TD|TH|CAPTION|FORM)$/.test(node.nodeName) &&\r
                                        !/^(fixed|absolute)/i.test(node.style.position) && \r
                                        dom.getContentEditable(node) !== "true";\r
                        };\r
 \r
+                       // Renders empty block on IE\r
+                       function renderBlockOnIE(block) {\r
+                               var oldRng;\r
+\r
+                               if (tinymce.isIE && dom.isBlock(block)) {\r
+                                       oldRng = selection.getRng();\r
+                                       block.appendChild(dom.create('span', null, '\u00a0'));\r
+                                       selection.select(block);\r
+                                       block.lastChild.outerHTML = '';\r
+                                       selection.setRng(oldRng);\r
+                               }\r
+                       };\r
+\r
+                       // Remove the first empty inline element of the block so this: <p><b><em></em></b>x</p> becomes this: <p>x</p>\r
+                       function trimInlineElementsOnLeftSideOfBlock(block) {\r
+                               var node = block, firstChilds = [], i;\r
+\r
+                               // Find inner most first child ex: <p><i><b>*</b></i></p>\r
+                               while (node = node.firstChild) {\r
+                                       if (dom.isBlock(node)) {\r
+                                               return;\r
+                                       }\r
+\r
+                                       if (node.nodeType == 1 && !nonEmptyElementsMap[node.nodeName.toLowerCase()]) {\r
+                                               firstChilds.push(node);\r
+                                       }\r
+                               }\r
+\r
+                               i = firstChilds.length;\r
+                               while (i--) {\r
+                                       node = firstChilds[i];\r
+                                       if (!node.hasChildNodes() || (node.firstChild == node.lastChild && node.firstChild.nodeValue === '')) {\r
+                                               dom.remove(node);\r
+                                       } else {\r
+                                               // Remove <a> </a> see #5381\r
+                                               if (node.nodeName == "A" && (node.innerText || node.textContent) === ' ') {\r
+                                                       dom.remove(node);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       };\r
+                       \r
                        // Moves the caret to a suitable position within the root for example in the first non pure whitespace text node or before an image\r
                        function moveToCaretPosition(root) {\r
                                var walker, node, rng, y, viewPort, lastNode = root, tempElm;\r
@@ -17695,7 +18533,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                                        break;\r
                                                }\r
 \r
-                                               if (/^(BR|IMG)$/.test(node.nodeName)) {\r
+                                               if (nonEmptyElementsMap[node.nodeName.toLowerCase()]) {\r
                                                        rng.setStartBefore(node);\r
                                                        rng.setEndBefore(node);\r
                                                        break;\r
@@ -17756,6 +18594,11 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                if (settings.keep_styles !== false) {\r
                                        do {\r
                                                if (/^(SPAN|STRONG|B|EM|I|FONT|STRIKE|U)$/.test(node.nodeName)) {\r
+                                                       // Never clone a caret containers\r
+                                                       if (node.id == '_mce_caret') {\r
+                                                               continue;\r
+                                                       }\r
+\r
                                                        clonedNode = node.cloneNode(false);\r
                                                        dom.setAttrib(clonedNode, 'id', ''); // Remove ID since it needs to be document unique\r
 \r
@@ -17772,7 +18615,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
 \r
                                // BR is needed in empty blocks on non IE browsers\r
                                if (!tinymce.isIE) {\r
-                                       caretNode.innerHTML = '<br>';\r
+                                       caretNode.innerHTML = '<br data-mce-bogus="1">';\r
                                }\r
 \r
                                return block;\r
@@ -17792,6 +18635,11 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                        return true;\r
                                }\r
 \r
+                               // If the caret if before the first element in parentBlock\r
+                               if (start && container.nodeType == 1 && container == parentBlock.firstChild) {\r
+                                       return true;\r
+                               }\r
+\r
                                // Caret can be before/after a table\r
                                if (container.nodeName === "TABLE" || (container.previousSibling && container.previousSibling.nodeName == "TABLE")) {\r
                                        return (isAfterLastNodeInContainer && !start) || (!isAfterLastNodeInContainer && start);\r
@@ -17799,21 +18647,35 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
 \r
                                // Walk the DOM and look for text nodes or non empty elements\r
                                walker = new TreeWalker(container, parentBlock);\r
-                               while (node = (start ? walker.prev() : walker.next())) {\r
+       \r
+                               // If caret is in beginning or end of a text block then jump to the next/previous node\r
+                               if (container.nodeType == 3) {\r
+                                       if (start && offset == 0) {\r
+                                               walker.prev();\r
+                                       } else if (!start && offset == container.nodeValue.length) {\r
+                                               walker.next();\r
+                                       }\r
+                               }\r
+\r
+                               while (node = walker.current()) {\r
                                        if (node.nodeType === 1) {\r
                                                // Ignore bogus elements\r
-                                               if (node.getAttribute('data-mce-bogus')) {\r
-                                                       continue;\r
-                                               }\r
-\r
-                                               // Keep empty elements like <img />\r
-                                               name = node.nodeName.toLowerCase();\r
-                                               if (name === 'IMG') {\r
-                                                       return false;\r
+                                               if (!node.getAttribute('data-mce-bogus')) {\r
+                                                       // Keep empty elements like <img /> <input /> but not trailing br:s like <p>text|<br></p>\r
+                                                       name = node.nodeName.toLowerCase();\r
+                                                       if (nonEmptyElementsMap[name] && name !== 'br') {\r
+                                                               return false;\r
+                                                       }\r
                                                }\r
                                        } else if (node.nodeType === 3 && !/^[ \t\r\n]*$/.test(node.nodeValue)) {\r
                                                return false;\r
                                        }\r
+\r
+                                       if (start) {\r
+                                               walker.prev();\r
+                                       } else {\r
+                                               walker.next();\r
+                                       }\r
                                }\r
 \r
                                return true;\r
@@ -17897,6 +18759,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                } else if (isFirstOrLastLi()) {\r
                                        // Last LI in list then temove LI and add text block after list\r
                                        dom.insertAfter(newBlock, containerBlock);\r
+                                       renderBlockOnIE(newBlock);\r
                                } else {\r
                                        // Middle LI in list the split the list and insert a text block in the middle\r
                                        // Extract after fragment and insert it after the current block\r
@@ -17928,12 +18791,12 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                        \r
                        // Inserts a BR element if the forced_root_block option is set to false or empty string\r
                        function insertBr() {\r
-                               var brElm, extraBr;\r
+                               var brElm, extraBr, marker;\r
 \r
                                if (container && container.nodeType == 3 && offset >= container.nodeValue.length) {\r
                                        // Insert extra BR element at the end block elements\r
                                        if (!tinymce.isIE && !hasRightSideBr()) {\r
-                                               brElm = dom.create('br')\r
+                                               brElm = dom.create('br');\r
                                                rng.insertNode(brElm);\r
                                                rng.setStartAfter(brElm);\r
                                                rng.setEndAfter(brElm);\r
@@ -17949,6 +18812,12 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                        brElm.parentNode.insertBefore(dom.doc.createTextNode('\r'), brElm);\r
                                }\r
 \r
+                               // Insert temp marker and scroll to that\r
+                               marker = dom.create('span', {}, '&nbsp;');\r
+                               brElm.parentNode.insertBefore(marker, brElm);\r
+                               selection.scrollIntoView(marker);\r
+                               dom.remove(marker);\r
+\r
                                if (!extraBr) {\r
                                        rng.setStartAfter(brElm);\r
                                        rng.setEndAfter(brElm);\r
@@ -17988,6 +18857,22 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                return parent !== root ? editableRoot : root;\r
                        };\r
 \r
+                       // Adds a BR at the end of blocks that only contains an IMG or INPUT since these might be floated and then they won't expand the block\r
+                       function addBrToBlockIfNeeded(block) {\r
+                               var lastChild;\r
+\r
+                               // IE will render the blocks correctly other browsers needs a BR\r
+                               if (!tinymce.isIE) {\r
+                                       block.normalize(); // Remove empty text nodes that got left behind by the extract\r
+\r
+                                       // Check if the block is empty or contains a floated last child\r
+                                       lastChild = block.lastChild;\r
+                                       if (!lastChild || (/^(left|right)$/gi.test(dom.getStyle(lastChild, 'float', true)))) {\r
+                                               dom.add(block, 'br');\r
+                                       }\r
+                               }\r
+                       };\r
+\r
                        // Delete any selected contents\r
                        if (!rng.collapsed) {\r
                                editor.execCommand('Delete');\r
@@ -18002,15 +18887,20 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                        // Setup range items and newBlockName\r
                        container = rng.startContainer;\r
                        offset = rng.startOffset;\r
-                       newBlockName = settings.forced_root_block;\r
+                       newBlockName = (settings.force_p_newlines ? 'p' : '') || settings.forced_root_block;\r
                        newBlockName = newBlockName ? newBlockName.toUpperCase() : '';\r
                        documentMode = dom.doc.documentMode;\r
+                       shiftKey = evt.shiftKey;\r
 \r
                        // Resolve node index\r
                        if (container.nodeType == 1 && container.hasChildNodes()) {\r
                                isAfterLastNodeInContainer = offset > container.childNodes.length - 1;\r
                                container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container;\r
-                               offset = 0;\r
+                               if (isAfterLastNodeInContainer && container.nodeType == 3) {\r
+                                       offset = container.nodeValue.length;\r
+                               } else {\r
+                                       offset = 0;\r
+                               }\r
                        }\r
 \r
                        // Get editable root node normaly the body element but sometimes a div or span\r
@@ -18025,7 +18915,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
 \r
                        // If editable root isn't block nor the root of the editor\r
                        if (!dom.isBlock(editableRoot) && editableRoot != dom.getRoot()) {\r
-                               if (!newBlockName || evt.shiftKey) {\r
+                               if (!newBlockName || shiftKey) {\r
                                        insertBr();\r
                                }\r
 \r
@@ -18035,7 +18925,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                        // Wrap the current node and it's sibling in a default block if it's needed.\r
                        // for example this <td>text|<b>text2</b></td> will become this <td><p>text|<b>text2</p></b></td>\r
                        // This won't happen if root blocks are disabled or the shiftKey is pressed\r
-                       if ((newBlockName && !evt.shiftKey) || (!newBlockName && evt.shiftKey)) {\r
+                       if ((newBlockName && !shiftKey) || (!newBlockName && shiftKey)) {\r
                                container = wrapSelfAndSiblingsInDefaultBlock(container, offset);\r
                        }\r
 \r
@@ -18047,26 +18937,40 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                        parentBlockName = parentBlock ? parentBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5\r
                        containerBlockName = containerBlock ? containerBlock.nodeName.toUpperCase() : ''; // IE < 9 & HTML5\r
 \r
-                       // Handle enter inside an empty list item\r
-                       if (parentBlockName == 'LI' && dom.isEmpty(parentBlock)) {\r
-                               // Let the list plugin or browser handle nested lists for now\r
-                               if (/^(UL|OL|LI)$/.test(containerBlock.parentNode.nodeName)) {\r
-                                       return false;\r
+                       // Enter inside block contained within a LI then split or insert before/after LI\r
+                       if (containerBlockName == 'LI' && !evt.ctrlKey) {\r
+                               parentBlock = containerBlock;\r
+                               parentBlockName = containerBlockName;\r
+                       }\r
+\r
+                       // Handle enter in LI\r
+                       if (parentBlockName == 'LI') {\r
+                               if (!newBlockName && shiftKey) {\r
+                                       insertBr();\r
+                                       return;\r
                                }\r
 \r
-                               handleEmptyListItem();\r
-                               return;\r
+                               // Handle enter inside an empty list item\r
+                               if (dom.isEmpty(parentBlock)) {\r
+                                       // Let the list plugin or browser handle nested lists for now\r
+                                       if (/^(UL|OL|LI)$/.test(containerBlock.parentNode.nodeName)) {\r
+                                               return false;\r
+                                       }\r
+\r
+                                       handleEmptyListItem();\r
+                                       return;\r
+                               }\r
                        }\r
 \r
                        // Don't split PRE tags but insert a BR instead easier when writing code samples etc\r
                        if (parentBlockName == 'PRE' && settings.br_in_pre !== false) {\r
-                               if (!evt.shiftKey) {\r
+                               if (!shiftKey) {\r
                                        insertBr();\r
                                        return;\r
                                }\r
                        } else {\r
                                // If no root block is configured then insert a BR by default or if the shiftKey is pressed\r
-                               if ((!newBlockName && !evt.shiftKey && parentBlockName != 'LI') || (newBlockName && evt.shiftKey)) {\r
+                               if ((!newBlockName && !shiftKey && parentBlockName != 'LI') || (newBlockName && shiftKey)) {\r
                                        insertBr();\r
                                        return;\r
                                }\r
@@ -18091,9 +18995,12 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                } else {\r
                                        dom.insertAfter(newBlock, parentBlock);\r
                                }\r
+\r
+                               moveToCaretPosition(newBlock);\r
                        } else if (isCaretAtStartOrEndOfBlock(true)) {\r
                                // Insert new block before\r
                                newBlock = parentBlock.parentNode.insertBefore(createNewBlock(), parentBlock);\r
+                               renderBlockOnIE(newBlock);\r
                        } else {\r
                                // Extract after fragment and insert it after the current block\r
                                tmpRng = rng.cloneRange();\r
@@ -18102,10 +19009,12 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                trimLeadingLineBreaks(fragment);\r
                                newBlock = fragment.firstChild;\r
                                dom.insertAfter(fragment, parentBlock);\r
+                               trimInlineElementsOnLeftSideOfBlock(newBlock);\r
+                               addBrToBlockIfNeeded(parentBlock);\r
+                               moveToCaretPosition(newBlock);\r
                        }\r
 \r
                        dom.setAttrib(newBlock, 'id', ''); // Remove ID since it needs to be document unique\r
-                       moveToCaretPosition(newBlock);\r
                        undoManager.add();\r
                }\r
 \r