|
1 | 1 | /**
|
2 |
| - * @license wysihtml v0.5.4 |
| 2 | + * @license wysihtml v0.5.5 |
3 | 3 | * https://github.com/Voog/wysihtml
|
4 | 4 | *
|
5 | 5 | * Author: Christopher Blum (https://github.com/tiff)
|
|
10 | 10 | *
|
11 | 11 | */
|
12 | 12 | var wysihtml5 = {
|
13 |
| - version: "0.5.4", |
| 13 | + version: "0.5.5", |
14 | 14 |
|
15 | 15 | // namespaces
|
16 | 16 | commands: {},
|
@@ -7119,6 +7119,10 @@ wysihtml5.browser = (function() {
|
7119 | 7119 | return ("styleFloat" in document.createElement("div").style) ? "styleFloat" : "cssFloat";
|
7120 | 7120 | }
|
7121 | 7121 | return key;
|
| 7122 | + }, |
| 7123 | + |
| 7124 | + usesControlRanges: function() { |
| 7125 | + return document.body && "createControlRange" in document.body; |
7122 | 7126 | }
|
7123 | 7127 | };
|
7124 | 7128 | })();
|
@@ -8136,8 +8140,8 @@ wysihtml5.dom.copyAttributes = function(attributesToCopy) {
|
8136 | 8140 |
|
8137 | 8141 | transferContentTo: function(targetNode, removeOldWrapper) {
|
8138 | 8142 | if (node.nodeType === 1) {
|
8139 |
| - if (wysihtml5.dom.domNode(targetNode).is.voidElement()) { |
8140 |
| - while (node.firstChild) { |
| 8143 | + if (wysihtml5.dom.domNode(targetNode).is.voidElement() || targetNode.nodeType === 3) { |
| 8144 | + while (node.lastChild) { |
8141 | 8145 | targetNode.parentNode.insertBefore(node.lastChild, targetNode.nextSibling);
|
8142 | 8146 | }
|
8143 | 8147 | } else {
|
@@ -11736,6 +11740,14 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
11736 | 11740 | return ret;
|
11737 | 11741 | }
|
11738 | 11742 |
|
| 11743 | + function getRangeNode(node, offset) { |
| 11744 | + if (node.nodeType === 3) { |
| 11745 | + return node; |
| 11746 | + } else { |
| 11747 | + return node.childNodes[offset] || node; |
| 11748 | + } |
| 11749 | + } |
| 11750 | + |
11739 | 11751 | function getWebkitSelectionFixNode(container) {
|
11740 | 11752 | var blankNode = document.createElement('span');
|
11741 | 11753 |
|
@@ -11806,7 +11818,7 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
11806 | 11818 | /** @scope wysihtml5.Selection.prototype */ {
|
11807 | 11819 | constructor: function(editor, contain, unselectableClass) {
|
11808 | 11820 | // Make sure that our external range library is initialized
|
11809 |
| - window.rangy.init(); |
| 11821 | + rangy.init(); |
11810 | 11822 |
|
11811 | 11823 | this.editor = editor;
|
11812 | 11824 | this.composer = editor.composer;
|
@@ -12133,11 +12145,16 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
12133 | 12145 | range.deleteContents();
|
12134 | 12146 | },
|
12135 | 12147 |
|
| 12148 | + getCaretNode: function () { |
| 12149 | + var selection = this.getSelection(); |
| 12150 | + return (selection && selection.anchorNode) ? getRangeNode(selection.anchorNode, selection.anchorOffset) : null; |
| 12151 | + }, |
| 12152 | + |
12136 | 12153 | getPreviousNode: function(node, ignoreEmpty) {
|
12137 | 12154 | var displayStyle;
|
12138 | 12155 | if (!node) {
|
12139 | 12156 | var selection = this.getSelection();
|
12140 |
| - node = selection.anchorNode; |
| 12157 | + node = (selection && selection.anchorNode) ? getRangeNode(selection.anchorNode, selection.anchorOffset) : null; |
12141 | 12158 | }
|
12142 | 12159 |
|
12143 | 12160 | if (node === this.contain) {
|
@@ -12257,15 +12274,24 @@ wysihtml5.quirks.ensureProperClearing = (function() {
|
12257 | 12274 | return (/^\s*$/).test(endtxt);
|
12258 | 12275 | },
|
12259 | 12276 |
|
12260 |
| - caretIsFirstInSelection: function() { |
| 12277 | + caretIsFirstInSelection: function(includeLineBreaks) { |
12261 | 12278 | var r = rangy.createRange(this.doc),
|
12262 | 12279 | s = this.getSelection(),
|
12263 | 12280 | range = this.getRange(),
|
12264 |
| - startNode = range.startContainer; |
| 12281 | + startNode = getRangeNode(range.startContainer, range.startOffset); |
12265 | 12282 |
|
12266 | 12283 | if (startNode) {
|
12267 | 12284 | if (startNode.nodeType === wysihtml5.TEXT_NODE) {
|
12268 |
| - return this.isCollapsed() && (startNode.nodeType === wysihtml5.TEXT_NODE && (/^\s*$/).test(startNode.data.substr(0,range.startOffset))); |
| 12285 | + if (!startNode.parentNode) { |
| 12286 | + return false; |
| 12287 | + } |
| 12288 | + if (!this.isCollapsed() || (startNode.parentNode.firstChild !== startNode && !wysihtml5.dom.domNode(startNode.previousSibling).is.block())) { |
| 12289 | + return false; |
| 12290 | + } |
| 12291 | + var ws = this.win.getComputedStyle(startNode.parentNode).whiteSpace; |
| 12292 | + return (ws === "pre" || ws === "pre-wrap") ? range.startOffset === 0 : (/^\s*$/).test(startNode.data.substr(0,range.startOffset)); |
| 12293 | + } else if (includeLineBreaks && wysihtml5.dom.domNode(startNode).is.lineBreak()) { |
| 12294 | + return true; |
12269 | 12295 | } else {
|
12270 | 12296 | r.selectNodeContents(this.getRange().commonAncestorContainer);
|
12271 | 12297 | r.collapse(true);
|
@@ -17526,31 +17552,36 @@ wysihtml5.views.View = Base.extend(
|
17526 | 17552 | var selection = composer.selection,
|
17527 | 17553 | prevNode = selection.getPreviousNode();
|
17528 | 17554 |
|
17529 |
| - if (selection.caretIsFirstInSelection() && |
17530 |
| - prevNode && |
17531 |
| - prevNode.nodeType === 1 && |
17532 |
| - (/block/).test(composer.win.getComputedStyle(prevNode).display) && |
17533 |
| - !domNode(prevNode).test({ |
17534 |
| - query: "ol, ul, table, tr, dl" |
17535 |
| - }) |
17536 |
| - ) { |
17537 |
| - if ((/^\s*$/).test(prevNode.textContent || prevNode.innerText)) { |
17538 |
| - // If heading is empty remove the heading node |
17539 |
| - prevNode.parentNode.removeChild(prevNode); |
17540 |
| - return true; |
17541 |
| - } else { |
17542 |
| - if (prevNode.lastChild) { |
17543 |
| - var selNode = prevNode.lastChild, |
17544 |
| - selectedNode = selection.getSelectedNode(), |
17545 |
| - commonAncestorNode = domNode(prevNode).commonAncestor(selectedNode, composer.element), |
17546 |
| - curNode = wysihtml5.dom.getParentElement(selectedNode, { |
17547 |
| - query: "h1, h2, h3, h4, h5, h6, p, pre, div, blockquote" |
17548 |
| - }, false, commonAncestorNode || composer.element); |
17549 |
| - |
17550 |
| - if (curNode) { |
17551 |
| - domNode(curNode).transferContentTo(prevNode, true); |
17552 |
| - selection.setAfter(selNode); |
17553 |
| - return true; |
| 17555 | + if (selection.caretIsFirstInSelection(wysihtml5.browser.usesControlRanges()) && prevNode) { |
| 17556 | + if (prevNode.nodeType === 1 && |
| 17557 | + wysihtml5.dom.domNode(prevNode).is.block() && |
| 17558 | + !domNode(prevNode).test({ |
| 17559 | + query: "ol, ul, table, tr, dl" |
| 17560 | + }) |
| 17561 | + ) { |
| 17562 | + if ((/^\s*$/).test(prevNode.textContent || prevNode.innerText)) { |
| 17563 | + // If heading is empty remove the heading node |
| 17564 | + prevNode.parentNode.removeChild(prevNode); |
| 17565 | + return true; |
| 17566 | + } else { |
| 17567 | + if (prevNode.lastChild) { |
| 17568 | + var selNode = prevNode.lastChild, |
| 17569 | + selectedNode = selection.getSelectedNode(), |
| 17570 | + commonAncestorNode = domNode(prevNode).commonAncestor(selectedNode, composer.element), |
| 17571 | + curNode = wysihtml5.dom.getParentElement(selectedNode, { |
| 17572 | + query: "h1, h2, h3, h4, h5, h6, p, pre, div, blockquote" |
| 17573 | + }, false, commonAncestorNode || composer.element); |
| 17574 | + |
| 17575 | + if (curNode) { |
| 17576 | + domNode(curNode).transferContentTo(prevNode, true); |
| 17577 | + selection.setAfter(selNode); |
| 17578 | + return true; |
| 17579 | + } else if (wysihtml5.browser.usesControlRanges()) { |
| 17580 | + selectedNode = selection.getCaretNode(); |
| 17581 | + domNode(selectedNode).transferContentTo(prevNode, true); |
| 17582 | + selection.setAfter(selNode); |
| 17583 | + return true; |
| 17584 | + } |
17554 | 17585 | }
|
17555 | 17586 | }
|
17556 | 17587 | }
|
@@ -17601,6 +17632,26 @@ wysihtml5.views.View = Base.extend(
|
17601 | 17632 | return false;
|
17602 | 17633 | },
|
17603 | 17634 |
|
| 17635 | + fixDeleteInTheBeginningOfControlSelection: function(composer) { |
| 17636 | + var selection = composer.selection, |
| 17637 | + prevNode = selection.getPreviousNode(), |
| 17638 | + selectedNode = selection.getSelectedNode(), |
| 17639 | + afterCaretNode; |
| 17640 | + |
| 17641 | + if (selection.caretIsFirstInSelection()) { |
| 17642 | + if (selectedNode.nodeType === 3) { |
| 17643 | + selectedNode = selectedNode.parentNode; |
| 17644 | + } |
| 17645 | + afterCaretNode = selectedNode.firstChild; |
| 17646 | + domNode(selectedNode).transferContentTo(prevNode, true); |
| 17647 | + if (afterCaretNode) { |
| 17648 | + composer.selection.setBefore(afterCaretNode); |
| 17649 | + } |
| 17650 | + return true; |
| 17651 | + } |
| 17652 | + return false; |
| 17653 | + }, |
| 17654 | + |
17604 | 17655 | // Table management
|
17605 | 17656 | // If present enableObjectResizing and enableInlineTableEditing command should be called with false to prevent native table handlers
|
17606 | 17657 | initTableHandling: function() {
|
@@ -17713,6 +17764,12 @@ wysihtml5.views.View = Base.extend(
|
17713 | 17764 | event.preventDefault();
|
17714 | 17765 | return;
|
17715 | 17766 | }
|
| 17767 | + if (wysihtml5.browser.usesControlRanges()) { |
| 17768 | + if (actions.fixDeleteInTheBeginningOfControlSelection(composer)) { |
| 17769 | + event.preventDefault(); |
| 17770 | + return; |
| 17771 | + } |
| 17772 | + } |
17716 | 17773 | } else {
|
17717 | 17774 | if (selection.containsUneditable()) {
|
17718 | 17775 | event.preventDefault();
|
@@ -17829,6 +17886,30 @@ wysihtml5.views.View = Base.extend(
|
17829 | 17886 | this.selection.selectNode(target);
|
17830 | 17887 | }
|
17831 | 17888 | }
|
| 17889 | + |
| 17890 | + // Saves mousedown position for IE controlSelect fix |
| 17891 | + if (wysihtml5.browser.usesControlRanges()) { |
| 17892 | + this.selection.lastMouseDownPos = {x: event.clientX, y: event.clientY}; |
| 17893 | + setTimeout(function() { |
| 17894 | + delete this.selection.lastMouseDownPos; |
| 17895 | + }.bind(this), 0); |
| 17896 | + } |
| 17897 | + }; |
| 17898 | + |
| 17899 | + // IE has this madness of control selects of overflowed and some other elements (weird box around element on selection and second click selects text) |
| 17900 | + // This fix handles the second click problem by adding cursor to the right position under cursor inside when controlSelection is made |
| 17901 | + var handleIEControlSelect = function(event) { |
| 17902 | + var target = event.target, |
| 17903 | + pos = this.selection.lastMouseDownPos; |
| 17904 | + if (pos) { |
| 17905 | + var caretPosition = document.body.createTextRange(); |
| 17906 | + setTimeout(function() { |
| 17907 | + try { |
| 17908 | + caretPosition.moveToPoint(pos.x, pos.y); |
| 17909 | + caretPosition.select(); |
| 17910 | + } catch (e) {} |
| 17911 | + }.bind(this), 0); |
| 17912 | + } |
17832 | 17913 | };
|
17833 | 17914 |
|
17834 | 17915 | var handleClick = function(event) {
|
@@ -17916,8 +17997,6 @@ wysihtml5.views.View = Base.extend(
|
17916 | 17997 | this.selection.getSelection().removeAllRanges();
|
17917 | 17998 | }).bind(this), 0);
|
17918 | 17999 | };
|
17919 |
| - |
17920 |
| - |
17921 | 18000 |
|
17922 | 18001 | // Testing requires actions to be accessible from out of scope
|
17923 | 18002 | wysihtml5.views.Composer.prototype.observeActions = actions;
|
@@ -17961,6 +18040,11 @@ wysihtml5.views.View = Base.extend(
|
17961 | 18040 | this.element.addEventListener("keyup", handleKeyUp.bind(this), false);
|
17962 | 18041 | this.element.addEventListener("keydown", handleKeyDown.bind(this), false);
|
17963 | 18042 |
|
| 18043 | + // IE controlselect madness fix |
| 18044 | + if (wysihtml5.browser.usesControlRanges()) { |
| 18045 | + this.element.addEventListener('mscontrolselect', handleIEControlSelect.bind(this), false); |
| 18046 | + } |
| 18047 | + |
17964 | 18048 | this.element.addEventListener("dragenter", (function() {
|
17965 | 18049 | this.parent.fire("unset_placeholder");
|
17966 | 18050 | }).bind(this), false);
|
|
0 commit comments