]> git.mxchange.org Git - friendica.git/blobdiff - library/tinymce/jscripts/tiny_mce/tiny_mce_src.js
updated tinymce to 3.5.11
[friendica.git] / library / tinymce / jscripts / tiny_mce / tiny_mce_src.js
index 3bbe9ce95cfc7f9d24cdfa0ad478f7043e816825..c9442c4989dec4eb9522f58a9e2924deb0b06b3e 100644 (file)
@@ -6,18 +6,20 @@
        var tinymce = {\r
                majorVersion : '3',\r
 \r
-               minorVersion : '5.8',\r
+               minorVersion : '5.11',\r
 \r
-               releaseDate : '2012-11-20',\r
+               releaseDate : '2014-05-08',\r
 \r
                _init : function() {\r
                        var t = this, d = document, na = navigator, ua = na.userAgent, i, nl, n, base, p, v;\r
 \r
+                       t.isIE11 = ua.indexOf('Trident/') != -1 && (ua.indexOf('rv:') != -1 || na.appName.indexOf('Netscape') != -1);\r
+\r
                        t.isOpera = win.opera && opera.buildNumber;\r
 \r
                        t.isWebKit = /WebKit/.test(ua);\r
 \r
-                       t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName);\r
+                       t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(na.appName) || t.isIE11;\r
 \r
                        t.isIE6 = t.isIE && /MSIE [56]/.test(ua);\r
 \r
@@ -27,7 +29,7 @@
 \r
                        t.isIE9 = t.isIE && /MSIE [9]/.test(ua);\r
 \r
-                       t.isGecko = !t.isWebKit && /Gecko/.test(ua);\r
+                       t.isGecko = !t.isWebKit && !t.isIE11 && /Gecko/.test(ua);\r
 \r
                        t.isMac = ua.indexOf('Mac') != -1;\r
 \r
@@ -1120,55 +1122,68 @@ tinymce.util.Quirks = function(editor) {
 \r
        function cleanupStylesWhenDeleting() {\r
                function removeMergedFormatSpans(isDelete) {\r
-                       var rng, blockElm, node, clonedSpan;\r
+                       var rng, blockElm, wrapperElm, bookmark, container, offset, elm;\r
 \r
-                       rng = selection.getRng();\r
+                       function isAtStartOrEndOfElm() {\r
+                               if (container.nodeType == 3) {\r
+                                       if (isDelete && offset == container.length) {\r
+                                               return true;\r
+                                       }\r
+\r
+                                       if (!isDelete && offset === 0) {\r
+                                               return true;\r
+                                       }\r
+                               }\r
+                       }\r
 \r
-                       // Find root block\r
-                       blockElm = dom.getParent(rng.startContainer, dom.isBlock);\r
+                       rng = selection.getRng();\r
+                       var tmpRng = [rng.startContainer, rng.startOffset, rng.endContainer, rng.endOffset];\r
 \r
-                       // On delete clone the root span of the next block element\r
-                       if (isDelete) {\r
-                               blockElm = dom.getNext(blockElm, dom.isBlock);\r
+                       if (!rng.collapsed) {\r
+                               isDelete = true;\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
+                       container = rng[(isDelete ? 'start' : 'end') + 'Container'];\r
+                       offset = rng[(isDelete ? 'start' : 'end') + 'Offset'];\r
 \r
-                               // Ignore empty text nodes\r
-                               while (node && node.nodeType == 3 && node.nodeValue.length === 0) {\r
-                                       node = node.nextSibling;\r
+                       if (container.nodeType == 3) {\r
+                               blockElm = dom.getParent(rng.startContainer, dom.isBlock);\r
+\r
+                               // On delete clone the root span of the next block element\r
+                               if (isDelete) {\r
+                                       blockElm = dom.getNext(blockElm, dom.isBlock);\r
                                }\r
 \r
-                               if (node && node.nodeName === 'SPAN') {\r
-                                       clonedSpan = node.cloneNode(false);\r
+                               if (blockElm && (isAtStartOrEndOfElm() || !rng.collapsed)) {\r
+                                       // Wrap children of block in a EM and let WebKit stick is\r
+                                       // runtime styles junk into that EM\r
+                                       wrapperElm = dom.create('em', {'id': '__mceDel'});\r
+\r
+                                       each(tinymce.grep(blockElm.childNodes), function(node) {\r
+                                               wrapperElm.appendChild(node);\r
+                                       });\r
+\r
+                                       blockElm.appendChild(wrapperElm);\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
+                       rng = dom.createRng();\r
+                       rng.setStart(tmpRng[0], tmpRng[1]);\r
+                       rng.setEnd(tmpRng[2], tmpRng[3]);\r
+                       selection.setRng(rng);\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
-                       each(dom.select('span', blockElm), function(span) {\r
-                               var bm = selection.getBookmark();\r
+                       // Remove temp wrapper element\r
+                       if (wrapperElm) {\r
+                               bookmark = selection.getBookmark();\r
 \r
-                               if (clonedSpan) {\r
-                                       dom.replace(clonedSpan.cloneNode(false), span, true);\r
-                               } else if (!span.getAttribute('data-mce-mark')) {\r
-                                       dom.remove(span, true);\r
-                               } else {\r
-                                       span.removeAttribute('data-mce-mark');\r
+                               while (elm = dom.get('__mceDel')) {\r
+                                       dom.remove(elm, true);\r
                                }\r
 \r
-                               // Restore the selection\r
-                               selection.moveToBookmark(bm);\r
-                       });\r
+                               selection.moveToBookmark(bookmark);\r
+                       }\r
                }\r
 \r
                editor.onKeyDown.add(function(editor, e) {\r
@@ -1490,6 +1505,12 @@ tinymce.util.Quirks = function(editor) {
                                // Override delete if the start container is a text node and is at the beginning of text or\r
                                // just before/after the last character to be deleted in collapsed mode\r
                                if (container.nodeType == 3 && container.nodeValue.length > 0 && ((offset === 0 && !collapsed) || (collapsed && offset === (isDelete ? 0 : 1)))) {\r
+                                       // Edge case when deleting <p><b><img> |x</b></p>\r
+                                       sibling = container.previousSibling;\r
+                                       if (sibling && sibling.nodeName == "IMG") {\r
+                                               return;\r
+                                       }\r
+\r
                                        nonEmptyElements = editor.schema.getNonEmptyElements();\r
 \r
                                        // Prevent default logic since it's broken\r
@@ -1922,6 +1943,40 @@ tinymce.util.Quirks = function(editor) {
                }\r
        }\r
 \r
+       function bodyHeight() {\r
+               editor.contentStyles.push('body {min-height: 100px}');\r
+               editor.onClick.add(function(ed, e) {\r
+                       if (e.target.nodeName == 'HTML') {\r
+                               editor.execCommand('SelectAll');\r
+                               editor.selection.collapse(true);\r
+                               editor.nodeChanged();\r
+                       }\r
+               });\r
+       }\r
+\r
+       function fixControlSelection() {\r
+               editor.onInit.add(function() {\r
+                       var selectedRng;\r
+\r
+                       editor.getBody().addEventListener('mscontrolselect', function(e) {\r
+                               setTimeout(function() {\r
+                                       if (editor.selection.getNode() != e.target) {\r
+                                               selectedRng = editor.selection.getRng();\r
+                                               selection.fakeRng = editor.dom.createRng();\r
+                                               selection.fakeRng.setStartBefore(e.target);\r
+                                               selection.fakeRng.setEndAfter(e.target);\r
+                                       }\r
+                               }, 0);\r
+                       }, false);\r
+\r
+                       editor.getDoc().addEventListener('selectionchange', function(e) {\r
+                               if (selectedRng && !tinymce.dom.RangeUtils.compareRanges(editor.selection.getRng(), selectedRng)) {\r
+                                       selection.fakeRng = selectedRng = null;\r
+                               }\r
+                       }, false);\r
+               });\r
+       }\r
+\r
        // All browsers\r
        disableBackspaceIntoATable();\r
        removeBlockQuoteOnBackSpace();\r
@@ -1945,7 +2000,7 @@ tinymce.util.Quirks = function(editor) {
        }\r
 \r
        // IE\r
-       if (tinymce.isIE) {\r
+       if (tinymce.isIE && !tinymce.isIE11) {\r
                removeHrOnBackspace();\r
                ensureBodyHasRoleApplication();\r
                addNewLinesBeforeBrInPre();\r
@@ -1955,8 +2010,14 @@ tinymce.util.Quirks = function(editor) {
                keepNoScriptContents();\r
        }\r
 \r
+       // IE 11+\r
+       if (tinymce.isIE11) {\r
+               bodyHeight();\r
+               fixControlSelection();\r
+       }\r
+\r
        // Gecko\r
-       if (tinymce.isGecko) {\r
+       if (tinymce.isGecko && !tinymce.isIE11) {\r
                removeHrOnBackspace();\r
                focusBody();\r
                removeStylesWhenDeletingAccrossBlockElements();\r
@@ -2193,6 +2254,12 @@ tinymce.html.Styles = function(settings, schema) {
                        function compress(prefix, suffix) {\r
                                var top, right, bottom, left;\r
 \r
+                               // IE 11 will produce a border-image: none when getting the style attribute from <p style="border: 1px solid red"></p>\r
+                               // So lets asume it shouldn't be there\r
+                               if (styles['border-image'] === 'none') {\r
+                                       delete styles['border-image'];\r
+                               }\r
+\r
                                // Get values and check it it needs compressing\r
                                top = styles[prefix + '-top' + suffix];\r
                                if (!top)\r
@@ -2715,7 +2782,7 @@ tinymce.html.Styles = function(settings, schema) {
                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
+               nonEmptyElementsMap = createLookupTable('non_empty_elements', 'td th iframe video audio object script', shortEndedElementsMap);\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
@@ -5236,7 +5303,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
                fixDoc: function(doc) {\r
                        var settings = this.settings, name;\r
 \r
-                       if (isIE && settings.schema) {\r
+                       if (isIE && !tinymce.isIE11 && settings.schema) {\r
                                // Add missing HTML 4/5 elements to IE\r
                                ('abbr article aside audio canvas ' +\r
                                'details figcaption figure footer ' +\r
@@ -5257,7 +5324,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
                        var self = this, clone, doc;\r
 \r
                        // TODO: Add feature detection here in the future\r
-                       if (!isIE || node.nodeType !== 1 || deep) {\r
+                       if (!isIE || tinymce.isIE11 || node.nodeType !== 1 || deep) {\r
                                return node.cloneNode(deep);\r
                        }\r
 \r
@@ -5530,7 +5597,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
                                switch (na) {\r
                                        case 'opacity':\r
                                                // IE specific opacity\r
-                                               if (isIE) {\r
+                                               if (isIE && ! tinymce.isIE11) {\r
                                                        s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")";\r
 \r
                                                        if (!n.currentStyle || !n.currentStyle.hasLayout)\r
@@ -5542,7 +5609,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
                                                break;\r
 \r
                                        case 'float':\r
-                                               isIE ? s.styleFloat = v : s.cssFloat = v;\r
+                                               (isIE && ! tinymce.isIE11) ? s.styleFloat = v : s.cssFloat = v;\r
                                                break;\r
                                        \r
                                        default:\r
@@ -5908,7 +5975,7 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
                                // IE 8 has a bug where dynamically loading stylesheets would produce a 1 item remaining bug\r
                                // This fix seems to resolve that issue by realcing the document ones a stylesheet finishes loading\r
                                // It's ugly but it seems to work fine.\r
-                               if (isIE && d.documentMode && d.recalc) {\r
+                               if (isIE && !tinymce.isIE11 && d.documentMode && d.recalc) {\r
                                        link.onload = function() {\r
                                                if (d.recalc)\r
                                                        d.recalc();\r
@@ -6227,7 +6294,12 @@ tinymce.dom.TreeWalker = function(start_node, root_node) {
 \r
                                                // Import\r
                                                case 3:\r
-                                                       addClasses(r.styleSheet);\r
+                                                       try {\r
+                                                               addClasses(r.styleSheet);\r
+                                                       } catch (ex) {\r
+                                                               // Ignore\r
+                                                       }\r
+\r
                                                        break;\r
                                        }\r
                                });\r
@@ -9329,7 +9401,7 @@ window.tinymce.dom.Sizzle = Sizzle;
                        if (!t.win.getSelection)\r
                                t.tridentSel = new tinymce.dom.TridentSelection(t);\r
 \r
-                       if (tinymce.isIE && dom.boxModel)\r
+                       if (tinymce.isIE && ! tinymce.isIE11 && dom.boxModel)\r
                                this._fixIESelection();\r
 \r
                        // Prevent leaks\r
@@ -9621,8 +9693,20 @@ window.tinymce.dom.Sizzle = Sizzle;
                        }\r
 \r
                        // Handle simple range\r
-                       if (type)\r
-                               return {rng : t.getRng()};\r
+                       if (type) {\r
+                               rng = t.getRng();\r
+\r
+                               if (rng.setStart) {\r
+                                       rng = {\r
+                                               startContainer: rng.startContainer,\r
+                                               startOffset: rng.startOffset,\r
+                                               endContainer: rng.endContainer,\r
+                                               endOffset: rng.endOffset\r
+                                       };\r
+                               }\r
+\r
+                               return {rng : rng};\r
+                       }\r
 \r
                        rng = t.getRng();\r
                        id = dom.uniqueId();\r
@@ -9688,7 +9772,7 @@ window.tinymce.dom.Sizzle = Sizzle;
                },\r
 \r
                moveToBookmark : function(bookmark) {\r
-                       var t = this, dom = t.dom, marker1, marker2, rng, root, startContainer, endContainer, startOffset, endOffset;\r
+                       var t = this, dom = t.dom, marker1, marker2, rng, rng2, root, startContainer, endContainer, startOffset, endOffset;\r
 \r
                        function setEndPoint(start) {\r
                                var point = bookmark[start ? 'start' : 'end'], i, node, offset, children;\r
@@ -9818,8 +9902,24 @@ window.tinymce.dom.Sizzle = Sizzle;
                                        }\r
                                } else if (bookmark.name) {\r
                                        t.select(dom.select(bookmark.name)[bookmark.index]);\r
-                               } else if (bookmark.rng)\r
-                                       t.setRng(bookmark.rng);\r
+                               } else if (bookmark.rng) {\r
+                                       rng = bookmark.rng;\r
+\r
+                                       if (rng.startContainer) {\r
+                                               rng2 = t.dom.createRng();\r
+\r
+                                               try {\r
+                                                       rng2.setStart(rng.startContainer, rng.startOffset);\r
+                                                       rng2.setEnd(rng.endContainer, rng.endOffset);\r
+                                               } catch (e) {\r
+                                                       // Might fail with index error\r
+                                               }\r
+\r
+                                               rng = rng2;\r
+                                       }\r
+\r
+                                       t.setRng(rng);\r
+                               }\r
                        }\r
                },\r
 \r
@@ -9904,6 +10004,11 @@ window.tinymce.dom.Sizzle = Sizzle;
                getRng : function(w3c) {\r
                        var self = this, selection, rng, elm, doc = self.win.document;\r
 \r
+                       // Workaround for IE 11 not being able to select images properly see #6613 see quirk fix\r
+                       if (self.fakeRng) {\r
+                               return self.fakeRng;\r
+                       }\r
+\r
                        // Found tridentSel object then we need to use that one\r
                        if (w3c && self.tridentSel) {\r
                                return self.tridentSel.getRangeAt(0);\r
@@ -9918,7 +10023,7 @@ window.tinymce.dom.Sizzle = Sizzle;
                        }\r
 \r
                        // We have W3C ranges and it's IE then fake control selection since IE9 doesn't handle that correctly yet\r
-                       if (tinymce.isIE && rng && rng.setStart && doc.selection.createRange().item) {\r
+                       if (tinymce.isIE && ! tinymce.isIE11 && rng && rng.setStart && doc.selection.createRange().item) {\r
                                elm = doc.selection.createRange().item(0);\r
                                rng = doc.createRange();\r
                                rng.setStartBefore(elm);\r
@@ -10783,7 +10888,7 @@ window.tinymce.dom.Sizzle = Sizzle;
 \r
                        // Add onload listener for non IE browsers since IE9\r
                        // fires onload event before the script is parsed and executed\r
-                       if (!tinymce.isIE)\r
+                       if (!tinymce.isIE || tinymce.isIE11)\r
                                elm.onload = done;\r
 \r
                        // Add onerror event will get fired on some browsers but not all of them\r
@@ -11196,18 +11301,22 @@ window.tinymce.dom.Sizzle = Sizzle;
                                switch (evt.keyCode) {\r
                                        case DOM_VK_LEFT:\r
                                                if (enableLeftRight) t.moveFocus(-1);\r
+                                               Event.cancel(evt);\r
                                                break;\r
        \r
                                        case DOM_VK_RIGHT:\r
                                                if (enableLeftRight) t.moveFocus(1);\r
+                                               Event.cancel(evt);\r
                                                break;\r
        \r
                                        case DOM_VK_UP:\r
                                                if (enableUpDown) t.moveFocus(-1);\r
+                                               Event.cancel(evt);\r
                                                break;\r
 \r
                                        case DOM_VK_DOWN:\r
                                                if (enableUpDown) t.moveFocus(1);\r
+                                               Event.cancel(evt);\r
                                                break;\r
 \r
                                        case DOM_VK_ESCAPE:\r
@@ -11904,7 +12013,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                        else\r
                                h += '<span class="mceIcon ' + s['class'] + '"></span>' + (l ? '<span class="' + cp + 'Label">' + l + '</span>' : '');\r
 \r
-                       h += '<span class="mceVoiceLabel mceIconOnly" style="display: none;" id="' + this.id + '_voice">' + s.title + '</span>'; \r
+                       h += '<span class="mceVoiceLabel mceIconOnly" style="display: none;" id="' + this.id + '_voice">' + s.title + '</span>';\r
                        h += '</a>';\r
                        return h;\r
                },\r
@@ -11929,9 +12038,11 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                                        return s.onclick.call(s.scope, e);\r
                                }\r
                        });\r
-                       tinymce.dom.Event.add(t.id, 'keyup', function(e) {\r
-                               if (!t.isDisabled() && e.keyCode==tinymce.VK.SPACEBAR)\r
+                       tinymce.dom.Event.add(t.id, 'keydown', function(e) {\r
+                               if (!t.isDisabled() && e.keyCode==tinymce.VK.SPACEBAR) {\r
+                                       tinymce.dom.Event.cancel(e);\r
                                        return s.onclick.call(s.scope, e);\r
+                               }\r
                        });\r
                }\r
        });\r
@@ -12344,7 +12455,7 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
 \r
                        // Accessibility keyhandler\r
                        Event.add(t.id, 'keydown', function(e) {\r
-                               var bf;\r
+                               var bf, DOM_VK_LEFT = 37, DOM_VK_RIGHT = 39, DOM_VK_UP = 38, DOM_VK_DOWN = 40, DOM_VK_RETURN = 13, DOM_VK_SPACE = 32;\r
 \r
                                Event.remove(t.id, 'change', ch);\r
                                changeListenerAdded = false;\r
@@ -12356,14 +12467,12 @@ tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
                                        Event.remove(t.id, 'blur', bf);\r
                                });\r
 \r
-                               //prevent default left and right keys on chrome - so that the keyboard navigation is used.\r
-                               if (tinymce.isWebKit && (e.keyCode==37 ||e.keyCode==39)) {\r
-                                       return Event.prevent(e);\r
-                               }\r
-                               \r
-                               if (e.keyCode == 13 || e.keyCode == 32) {\r
+                               if (e.keyCode == DOM_VK_RETURN || e.keyCode == DOM_VK_SPACE) {\r
                                        onChange(e);\r
                                        return Event.cancel(e);\r
+                               } else if (e.keyCode == DOM_VK_DOWN || e.keyCode == DOM_VK_UP) {\r
+                                       // allow native implementation (navigate select element options)\r
+                                       e.stopImmediatePropagation();\r
                                }\r
                        });\r
 \r
@@ -13252,7 +13361,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                        ed.render();\r
 \r
                                        // Fix IE memory leaks\r
-                                       if (tinymce.isIE) {\r
+                                       if (tinymce.isIE && ! tinymce.isIE11) {\r
                                                w.attachEvent('onunload', clr);\r
                                        }\r
 \r
@@ -13650,10 +13759,16 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                        // 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
+                                                       ed.dom.bind(ed.getBody(), 'beforedeactivate keydown keyup', function() {\r
+                                                               ed.bookmark = ed.selection.getBookmark(1);\r
                                                        });\r
                                                });\r
+\r
+                                               t.onNodeChange.add(function(ed) {\r
+                                                       if (document.activeElement.id == ed.id + "_ifr") {\r
+                                                               ed.bookmark = ed.selection.getBookmark(1);\r
+                                                       }\r
+                                               });\r
                                        }\r
                                }\r
 \r
@@ -13973,8 +14088,9 @@ 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
+                               if (self.bookmark) {\r
+                                       selection.moveToBookmark(self.bookmark);\r
+                                       self.bookmark = null;\r
                                }\r
 \r
                                // Get selected control element\r
@@ -13995,7 +14111,7 @@ tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
                                        body = self.getBody();\r
 \r
                                        // Check for setActive since it doesn't scroll to the element\r
-                                       if (body.setActive) {\r
+                                       if (body.setActive && ! tinymce.isIE11) {\r
                                                body.setActive();\r
                                        } else {\r
                                                body.focus();\r
@@ -16405,7 +16521,11 @@ tinymce.ForceBlocks = function(editor) {
                        getContentEditable = dom.getContentEditable;\r
 \r
                function isTextBlock(name) {\r
-                       return !!ed.schema.getTextBlocks()[name.toLowerCase()];\r
+                       if (name.nodeType) {\r
+                               name = name.nodeName;\r
+                       }\r
+\r
+                       return !!ed.schema.getTextBlockElements()[name.toLowerCase()];\r
                }\r
 \r
                function getParents(node, selector) {\r
@@ -16766,7 +16886,7 @@ tinymce.ForceBlocks = function(editor) {
 \r
                                                // Is it valid to wrap this item\r
                                                if (contentEditable && !hasContentEditableState && isValid(wrapName, nodeName) && isValid(parentName, wrapName) &&\r
-                                                               !(!node_specific && node.nodeType === 3 && node.nodeValue.length === 1 && node.nodeValue.charCodeAt(0) === 65279) && !isCaretNode(node)) {\r
+                                                               !(!node_specific && node.nodeType === 3 && node.nodeValue.length === 1 && node.nodeValue.charCodeAt(0) === 65279) && !isCaretNode(node) && (!format.inline || !isBlock(node))) {\r
                                                        // Start wrapping\r
                                                        if (!currentWrapElm) {\r
                                                                // Wrap the node\r
@@ -18046,10 +18166,6 @@ tinymce.ForceBlocks = function(editor) {
                        return next;\r
                };\r
 \r
-               function isTextBlock(name) {\r
-                       return /^(h[1-6]|p|div|pre|address|dl|dt|dd)$/.test(name);\r
-               };\r
-\r
                function getContainer(rng, start) {\r
                        var container, offset, lastIdx, walker;\r
 \r
@@ -18285,11 +18401,23 @@ tinymce.ForceBlocks = function(editor) {
                                        node.appendChild(dom.doc.createTextNode(INVISIBLE_CHAR));\r
                                        node = node.firstChild;\r
 \r
-                                       // Insert caret container after the formated node\r
-                                       dom.insertAfter(caretContainer, formatNode);\r
+                                       var block = dom.getParent(formatNode, isTextBlock);\r
+\r
+                                       if (block && dom.isEmpty(block)) {\r
+                                               // Replace formatNode with caretContainer when removing format from empty block like <p><b>|</b></p>\r
+                                               formatNode.parentNode.replaceChild(caretContainer, formatNode);\r
+                                       } else {\r
+                                               // Insert caret container after the formated node\r
+                                               dom.insertAfter(caretContainer, formatNode);\r
+                                       }\r
 \r
                                        // Move selection to text node\r
                                        selection.setCursorLocation(node, 1);\r
+\r
+                                       // If the formatNode is empty, we can remove it safely. \r
+                                       if (dom.isEmpty(formatNode)) {\r
+                                               dom.remove(formatNode);\r
+                                       }\r
                                }\r
                        };\r
 \r
@@ -18479,7 +18607,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                        function renderBlockOnIE(block) {\r
                                var oldRng;\r
 \r
-                               if (tinymce.isIE && dom.isBlock(block)) {\r
+                               if (tinymce.isIE && !tinymce.isIE11 && dom.isBlock(block)) {\r
                                        oldRng = selection.getRng();\r
                                        block.appendChild(dom.create('span', null, '\u00a0'));\r
                                        selection.select(block);\r
@@ -18614,7 +18742,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                }\r
 \r
                                // BR is needed in empty blocks on non IE browsers\r
-                               if (!tinymce.isIE) {\r
+                               if (!tinymce.isIE || tinymce.isIE11) {\r
                                        caretNode.innerHTML = '<br data-mce-bogus="1">';\r
                                }\r
 \r
@@ -18776,26 +18904,24 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                undoManager.add();\r
                        };\r
 \r
-                       // Walks the parent block to the right and look for BR elements\r
-                       function hasRightSideBr() {\r
+                       // Walks the parent block to the right and look for any contents\r
+                       function hasRightSideContent() {\r
                                var walker = new TreeWalker(container, parentBlock), node;\r
 \r
-                               while (node = walker.current()) {\r
-                                       if (node.nodeName == 'BR') {\r
+                               while (node = walker.next()) {\r
+                                       if (nonEmptyElementsMap[node.nodeName.toLowerCase()] || node.length > 0) {\r
                                                return true;\r
                                        }\r
-\r
-                                       node = walker.next();\r
                                }\r
                        }\r
-                       \r
+\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, 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
+                                       if ((!tinymce.isIE || tinymce.isIE11) && !hasRightSideContent()) {\r
                                                brElm = dom.create('br');\r
                                                rng.insertNode(brElm);\r
                                                rng.setStartAfter(brElm);\r
@@ -18808,7 +18934,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                rng.insertNode(brElm);\r
 \r
                                // Rendering modes below IE8 doesn't display BR elements in PRE unless we have a \n before it\r
-                               if (tinymce.isIE && parentBlockName == 'PRE' && (!documentMode || documentMode < 8)) {\r
+                               if ((tinymce.isIE && !tinymce.isIE11) && parentBlockName == 'PRE' && (!documentMode || documentMode < 8)) {\r
                                        brElm.parentNode.insertBefore(dom.doc.createTextNode('\r'), brElm);\r
                                }\r
 \r
@@ -18862,7 +18988,7 @@ tinymce.onAddEditor.add(function(tinymce, ed) {
                                var lastChild;\r
 \r
                                // IE will render the blocks correctly other browsers needs a BR\r
-                               if (!tinymce.isIE) {\r
+                               if (!tinymce.isIE || tinymce.isIE11) {\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