Support for WebP images (#3861)
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / js / 3rdParty / redactor2 / redactor.js
index d0f82d2539e32f2237326f491c576ddb886ad810..3e27079dd9b4acb0fc91597a09279abee6558ac5 100644 (file)
                emptyHtml: '<p>&#x200b;</p>',
                invisibleSpace: '&#x200b;',
                emptyHtmlRendered: $('').html('​').html(),
-               imageTypes: ['image/png', 'image/jpeg', 'image/gif'],
+               imageTypes: ['image/png', 'image/jpeg', 'image/gif', 'image/webp'],
                userAgent: navigator.userAgent.toLowerCase(),
                observe: {
                        dropdowns: []
                                },
                                dragover: function (e) {
                                        e.preventDefault();
-                                       e.stopPropagation();
                                        
                                        if (e.target.tagName === 'IMG') {
                                                $(e.target).addClass('redactor-image-dragover');
                                                this.indent.repositionItem($item);
                                        }
                                        
+                                       var tmpWrapper = null;
                                        if ($item.length === 0) {
+                                               // `formatBlock` does not handle custom elements gracefully, always
+                                               // treating them as inline elements, causing these to be chopped up
+                                               // into separate elements. We can mitigate this problem by introducing
+                                               // a temporary intermediate `<div>` which will serve as a block wrapper.
+                                               var block = this.selection.block();
+                                               if (block && block.nodeName.indexOf('-') !== -1) {
+                                                       this.selection.save();
+                                                       
+                                                       tmpWrapper = elCreate('div');
+                                                       while (block.childNodes.length) {
+                                                               tmpWrapper.appendChild(block.childNodes[0]);
+                                                       }
+                                                       block.appendChild(tmpWrapper);
+                                                       
+                                                       this.selection.restore();
+                                               }
+                                               
                                                document.execCommand('formatblock', false, 'p');
                                                $item = $(this.selection.current());
                                                var $next = $item.next();
                                        
                                        // normalize
                                        this.selection.save();
+                                       
+                                       if (tmpWrapper !== null) {
+                                               var parent = tmpWrapper.parentNode;
+                                               while (tmpWrapper.childNodes.length) {
+                                                       parent.insertBefore(tmpWrapper.childNodes[0], tmpWrapper);
+                                               }
+                                               parent.removeChild(tmpWrapper);
+                                       }
+                                       
                                        this.indent.removeEmpty();
                                        this.indent.normalize();
                                        this.selection.restore();
                                        }
                                },
                                formatUncollapsed: function (tag, params) {
+                                       var element;
+                                       
                                        this.selection.save();
+
+                                       var range = window.getSelection().getRangeAt(0);
+                                       var contents = range.cloneContents();
+                                       if (contents.querySelector(tag) === null) {
+                                               element = range.startContainer;
+                                               if (element.nodeType === Node.TEXT_NODE) {
+                                                       element = element.parentElement;
+                                               }
+
+                                               var parentWithTheSameTag = element.closest(tag);
+                                               if (parentWithTheSameTag !== null && this.core.editor()[0].contains(parentWithTheSameTag)) {
+                                                       // We need to split the matching parent element
+                                                       // by moving everything to the left and the right
+                                                       // into separate nodes.
+                                                       var leftElement = document.createElement(tag);
+                                                       parentWithTheSameTag.insertAdjacentElement("beforebegin", leftElement);
+
+                                                       var leftRange = document.createRange();
+                                                       leftRange.selectNodeContents(parentWithTheSameTag);
+                                                       leftRange.setEnd(range.startContainer, range.startOffset);
+                                                       leftElement.appendChild(leftRange.extractContents());
+
+                                                       var rightElement = document.createElement(tag);
+                                                       parentWithTheSameTag.insertAdjacentElement("afterend", rightElement);
+
+                                                       var rightRange = document.createRange();
+                                                       rightRange.selectNodeContents(parentWithTheSameTag);
+                                                       rightRange.setStart(range.endContainer, range.endOffset);
+                                                       rightElement.appendChild(rightRange.extractContents());
+
+                                                       // Finally remove the offending parent element.
+                                                       var parentElement = parentWithTheSameTag.parentElement;
+                                                       while (parentWithTheSameTag.childNodes.length) {
+                                                               parentElement.insertBefore(parentWithTheSameTag.childNodes[0], parentWithTheSameTag);
+                                                       }
+                                                       parentWithTheSameTag.remove();
+                                                       
+                                                       return;
+                                               }
+                                       }
                                        
                                        var nodes = this.inline.getClearedNodes();
                                        this.inline.setNodesStriked(nodes, tag, params);
                                        // WoltLab: Chrome misbehaves in some cases, causing the `<strike>` element for
                                        // contained elements to be stripped. Instead, those children are assigned the
                                        // CSS style `text-decoration-line: line-through`.
-                                       var chromeElements = this.core.editor()[0].querySelectorAll('[style*="line-through"]'), element, strike;
+                                       var chromeElements = this.core.editor()[0].querySelectorAll('[style*="line-through"]'), strike;
                                        for (var i = 0, length = chromeElements.length; i < length; i++) {
                                                element = chromeElements[0];