|
36 | 36 | holdDistance: 0 | triggerOffset * ( config.magicline_holdDistance || 0.5 ),
|
37 | 37 | boxColor: config.magicline_color || '#ff0000',
|
38 | 38 | rtl: config.contentsLangDirection == 'rtl',
|
39 |
| - triggers: config.magicline_everywhere ? CKEDITOR.dtd.$block : { table:1,hr:1,div:1,ul:1,ol:1,dl:1,form:1,blockquote:1 } |
| 39 | + triggers: config.magicline_everywhere ? dtd.$block : { table:1,hr:1,div:1,ul:1,ol:1,dl:1,form:1,blockquote:1 } |
40 | 40 | },
|
41 | 41 | scrollTimeout, hideTimeout, checkMouseTimeoutPending, checkMouseTimeout, checkMouseTimer;
|
42 | 42 |
|
|
72 | 72 | && !isFlowBreaker( node ); // -> Node can be neither floated nor positioned nor aligned.
|
73 | 73 | };
|
74 | 74 |
|
75 |
| - // %REMOVE_START% |
76 |
| - // Editor commands for accessing difficult focus spaces. |
77 |
| - editor.addCommand( 'accessSpaceBefore', accessSpaceCommand( that ) ); |
78 |
| - editor.addCommand( 'accessSpaceAfter', accessSpaceCommand( that, true ) ); |
79 |
| - // %REMOVE_END% |
80 | 75 | editor.on( 'contentDom', addListeners, this );
|
81 | 76 |
|
82 | 77 | function addListeners() {
|
|
99 | 94 |
|
100 | 95 | // Enabling the box inside of inline editable is pointless.
|
101 | 96 | // There's no need to access spaces inside paragraphs, links, spans, etc.
|
102 |
| - if ( editable.is( CKEDITOR.dtd.$inline ) ) |
| 97 | + if ( editable.is( dtd.$inline ) ) |
103 | 98 | return;
|
104 | 99 |
|
105 | 100 | // Handle in-line editing by setting appropriate position.
|
|
274 | 269 | that.debug.showHidden( that.hiddenMode ); // %REMOVE_LINE%
|
275 | 270 | });
|
276 | 271 |
|
| 272 | + // Editor commands for accessing difficult focus spaces. |
| 273 | + editor.addCommand( 'accessPreviousSpace', accessFocusSpaceCmd( that ) ); |
| 274 | + editor.addCommand( 'accessNextSpace', accessFocusSpaceCmd( that, true ) ); |
| 275 | + |
| 276 | + editor.setKeystroke( [ |
| 277 | + [ config.magicline_keystrokePrevious, 'accessPreviousSpace' ], |
| 278 | + [ config.magicline_keystrokeNext, 'accessNextSpace' ] |
| 279 | + ] ); |
| 280 | + |
277 | 281 | // This method handles mousemove mouse for box toggling.
|
278 | 282 | // It uses mouse position to determine underlying element, then
|
279 | 283 | // it tries to use different trigger type in order to place the box
|
|
332 | 336 | }
|
333 | 337 | }
|
334 | 338 |
|
335 |
| - // Constant values, types and so on. |
336 |
| - var EDGE_TOP = 128, |
| 339 | + // Some shorthands for common methods to save bytes |
| 340 | + var extend = CKEDITOR.tools.extend, |
| 341 | + newElement = CKEDITOR.dom.element, |
| 342 | + newElementFromHtml = newElement.createFromHtml, |
| 343 | + env = CKEDITOR.env, |
| 344 | + dtd = CKEDITOR.dtd, |
| 345 | + |
| 346 | + // Constant values, types and so on. |
| 347 | + EDGE_TOP = 128, |
337 | 348 | EDGE_BOTTOM = 64,
|
338 | 349 | EDGE_MIDDLE = 32,
|
339 | 350 | TYPE_EDGE = 16,
|
|
342 | 353 | LOOK_BOTTOM = 2,
|
343 | 354 | LOOK_NORMAL = 1,
|
344 | 355 | WHITE_SPACE = '\u00A0',
|
345 |
| - DTD_LISTITEM = CKEDITOR.dtd.$listItem, |
346 |
| - DTD_TABLECONTENT = CKEDITOR.dtd.$tableContent, |
| 356 | + DTD_LISTITEM = dtd.$listItem, |
| 357 | + DTD_TABLECONTENT = dtd.$tableContent, |
| 358 | + DTD_NONACCESSIBLE = extend( {}, dtd.$nonEditable, dtd.$empty ), |
347 | 359 |
|
348 | 360 | // Minimum time that must elapse between two update*Size calls.
|
349 | 361 | // It prevents constant getComuptedStyle calls and improves performance.
|
|
352 | 364 | // Shared CSS stuff for box elements
|
353 | 365 | CSS_COMMON = 'width:0px;height:0px;padding:0px;margin:0px;display:block;' + 'z-index:9999;color:#fff;position:absolute;font-size: 0px;line-height:0px;',
|
354 | 366 | CSS_TRIANGLE = CSS_COMMON + 'border-color:transparent;display:block;border-style:solid;',
|
355 |
| - TRIANGLE_HTML = '<span>' + WHITE_SPACE + '</span>', |
356 |
| - |
357 |
| - // Some shorthands for common methods to save bytes |
358 |
| - extend = CKEDITOR.tools.extend, |
359 |
| - newElement = CKEDITOR.dom.element, |
360 |
| - newElementFromHtml = newElement.createFromHtml, |
361 |
| - env = CKEDITOR.env; |
362 |
| - |
363 |
| - // %REMOVE_START% |
364 |
| - // Access focus space on demand by looking for closest parent trigger |
365 |
| - // or using current element under the caret as reference. |
366 |
| - function accessSpaceCommand( that, insertAfter ) { |
367 |
| - return { |
368 |
| - canUndo: true, |
369 |
| - modes: { wysiwyg:1 }, |
370 |
| - exec: function( editor ) { |
371 |
| - var selection = editor.getSelection(), |
372 |
| - selected = selection.getStartElement(), |
373 |
| - range = selection.getRanges()[ 0 ], |
374 |
| - target = getAscendantTrigger( that, selected ) || selected; |
375 |
| - |
376 |
| - if ( !isHtml( target ) ) |
377 |
| - return; |
378 |
| - |
379 |
| - accessFocusSpace( that, function( accessNode ) { |
380 |
| - if ( target.equals( that.editable ) ) |
381 |
| - range.insertNode( accessNode ); |
382 |
| - else |
383 |
| - accessNode[ insertAfter ? 'insertAfter' : 'insertBefore' ]( target ); |
384 |
| - }); |
385 |
| - |
386 |
| - that.line.detach(); |
387 |
| - } |
388 |
| - }; |
389 |
| - } |
390 |
| - // %REMOVE_END% |
| 367 | + TRIANGLE_HTML = '<span>' + WHITE_SPACE + '</span>'; |
391 | 368 |
|
392 | 369 | function areSiblings( that, upper, lower ) {
|
393 | 370 | return isHtml( upper ) && isHtml( lower ) && lower.equals( upper.getNext( function( node ) {
|
|
731 | 708 |
|
732 | 709 | that.editor.focus();
|
733 | 710 |
|
734 |
| - if( !env.ie && that.enterMode != CKEDITOR.ENTER_BR ) |
| 711 | + if ( !env.ie && that.enterMode != CKEDITOR.ENTER_BR ) |
735 | 712 | that.hotNode.scrollIntoView();
|
736 | 713 |
|
737 | 714 | event.data.preventDefault( true );
|
|
782 | 759 | editor.fire( 'saveSnapshot' );
|
783 | 760 | }
|
784 | 761 |
|
| 762 | + // Access focus space on demand by taking an element under the caret as a reference. |
| 763 | + // The space is accessed provided the element under the caret is trigger AND: |
| 764 | + // |
| 765 | + // 1. First/last-child of its parent: |
| 766 | + // +----------------------- Parent element -+ |
| 767 | + // | +------------------------------ DIV -+ | <-- Access before |
| 768 | + // | | Foo^ | | |
| 769 | + // | | | | |
| 770 | + // | +------------------------------------+ | <-- Access after |
| 771 | + // +----------------------------------------+ |
| 772 | + // |
| 773 | + // OR |
| 774 | + // |
| 775 | + // 2. It has a direct sibling element, which is also a trigger: |
| 776 | + // +-------------------------------- DIV#1 -+ |
| 777 | + // | Foo^ | |
| 778 | + // | | |
| 779 | + // +----------------------------------------+ |
| 780 | + // <-- Access here |
| 781 | + // +-------------------------------- DIV#2 -+ |
| 782 | + // | Bar | |
| 783 | + // | | |
| 784 | + // +----------------------------------------+ |
| 785 | + // |
| 786 | + // OR |
| 787 | + // |
| 788 | + // 3. It has a direct sibling, which is a trigger and has a valid neighbour trigger, |
| 789 | + // but belongs to dtd.$.empty/nonEditable: |
| 790 | + // +------------------------------------ P -+ |
| 791 | + // | Foo^ | |
| 792 | + // | | |
| 793 | + // +----------------------------------------+ |
| 794 | + // +----------------------------------- HR -+ |
| 795 | + // <-- Access here |
| 796 | + // +-------------------------------- DIV#2 -+ |
| 797 | + // | Bar | |
| 798 | + // | | |
| 799 | + // +----------------------------------------+ |
| 800 | + // |
| 801 | + function accessFocusSpaceCmd( that, insertAfter ) { |
| 802 | + return { |
| 803 | + canUndo: true, |
| 804 | + modes: { wysiwyg: 1 }, |
| 805 | + exec: ( function() { |
| 806 | + // Inserts line (accessNode) at the position by taking target node as a reference. |
| 807 | + function doAccess( target ) { |
| 808 | + accessFocusSpace( that, function( accessNode ) { |
| 809 | + accessNode[ insertAfter ? 'insertAfter' : 'insertBefore' ]( target ); |
| 810 | + }); |
| 811 | + |
| 812 | + if( !env.ie && that.enterMode != CKEDITOR.ENTER_BR ) |
| 813 | + that.hotNode.scrollIntoView(); |
| 814 | + |
| 815 | + // Detach the line if was visible (previously triggered by mouse). |
| 816 | + that.line.detach(); |
| 817 | + } |
| 818 | + |
| 819 | + return function( editor ) { |
| 820 | + var selected = editor.getSelection().getStartElement(); |
| 821 | + |
| 822 | + // That holds element from mouse. Replace it with the |
| 823 | + // element under the caret. |
| 824 | + that.element = selected; |
| 825 | + |
| 826 | + // (3.) Handle the following cases where selected neighbour |
| 827 | + // is a trigger inaccessible for the caret AND: |
| 828 | + // - Is first/last-child |
| 829 | + // OR |
| 830 | + // - Has a sibling, which is also a trigger. |
| 831 | + var neighbor = getNonEmptyNeighbour( that, selected, !insertAfter ), |
| 832 | + neighborSibling; |
| 833 | + |
| 834 | + // Check for a neighbour that belongs to triggers. |
| 835 | + // Consider only non-accessible elements (they cannot have any children) |
| 836 | + // since they cannot be given a caret inside, to run the command |
| 837 | + // the regular way (1. & 2.). |
| 838 | + if ( isHtml( neighbor ) && neighbor.is( that.triggers ) && neighbor.is( DTD_NONACCESSIBLE ) && |
| 839 | + ( |
| 840 | + // Check whether neighbor is first/last-child. |
| 841 | + !getNonEmptyNeighbour( that, neighbor, !insertAfter ) |
| 842 | + || |
| 843 | + // Check for a sibling of a neighbour that also is a trigger. |
| 844 | + ( |
| 845 | + ( neighborSibling = getNonEmptyNeighbour( that, neighbor, !insertAfter ) ) && |
| 846 | + isHtml( neighborSibling ) && |
| 847 | + neighborSibling.is( that.triggers ) |
| 848 | + ) |
| 849 | + ) |
| 850 | + ) { |
| 851 | + doAccess( neighbor ); |
| 852 | + return; |
| 853 | + } |
| 854 | + |
| 855 | + // Look for possible target element DOWN "selected" DOM branch (towards editable) |
| 856 | + // that belong to that.triggers |
| 857 | + var target = getAscendantTrigger( that, selected ); |
| 858 | + |
| 859 | + // No HTML target -> no access. |
| 860 | + if ( !isHtml( target ) ) |
| 861 | + return; |
| 862 | + |
| 863 | + // (1.) Target is first/last child -> access. |
| 864 | + if ( !getNonEmptyNeighbour( that, target, !insertAfter ) ) { |
| 865 | + doAccess( target ); |
| 866 | + return; |
| 867 | + } |
| 868 | + |
| 869 | + var sibling = getNonEmptyNeighbour( that, target, !insertAfter ); |
| 870 | + |
| 871 | + // (2.) Target has a sibling that belongs to that.triggers -> access. |
| 872 | + if ( sibling && isHtml( sibling ) && sibling.is( that.triggers ) ) { |
| 873 | + doAccess( target ); |
| 874 | + return; |
| 875 | + } |
| 876 | + }; |
| 877 | + })() |
| 878 | + }; |
| 879 | + } |
| 880 | + |
785 | 881 | function isLine( that, node ) {
|
786 | 882 | if ( !( node && node.type == CKEDITOR.NODE_ELEMENT && node.$ ) )
|
787 | 883 | return false;
|
|
1545 | 1641 | * @see CKEDITOR.config#magicline_triggerOffset
|
1546 | 1642 | */
|
1547 | 1643 |
|
1548 |
| -// %REMOVE_START% |
1549 |
| - |
1550 | 1644 | /**
|
1551 |
| - * Defines default keystroke that access the space before an element that |
1552 |
| - * holds start of the current selection or just simply holds the caret. |
| 1645 | + * Defines default keystroke that access the closest unreachable focus space **before** |
| 1646 | + * the caret (start of the selection). If there's no any focus space, selection remains. |
1553 | 1647 | *
|
1554 |
| - * // Changes keystroke to CTRL + SHIFT + , |
1555 |
| - * CKEDITOR.config.magicline_keystrokeBefore = CKEDITOR.CTRL + CKEDITOR.SHIFT + 188; |
| 1648 | + * // Changes keystroke to CTRL + , |
| 1649 | + * CKEDITOR.config.magicline_keystrokePrevious = CKEDITOR.CTRL + 188; |
1556 | 1650 | *
|
1557 |
| - * @ignore |
1558 |
| - * @cfg {Number} [magicline_keystrokeBefore=CKEDITOR.CTRL + CKEDITOR.SHIFT + 219 (CTRL + SHIFT + [)] |
| 1651 | + * @cfg {Number} [magicline_keystrokePrevious=CKEDITOR.CTRL + CKEDITOR.ALT + 219 (CTRL + ALT + [)] |
1559 | 1652 | * @member CKEDITOR.config
|
1560 | 1653 | */
|
1561 |
| -// CKEDITOR.config.magicline_keystrokeBefore = CKEDITOR.CTRL + CKEDITOR.SHIFT + 219; // CTRL + SHIFT + [ |
| 1654 | +CKEDITOR.config.magicline_keystrokePrevious = CKEDITOR.CTRL + CKEDITOR.ALT + 219; // CTRL + ALT + [ |
1562 | 1655 |
|
1563 | 1656 | /**
|
1564 |
| - * Defines default keystroke that access the space after an element that |
1565 |
| - * holds start of the current selection or just simply holds the caret. |
| 1657 | + * Defines default keystroke that access the closest unreachable focus space **after** |
| 1658 | + * the caret (start of the selection). If there's no any focus space, selection remains. |
1566 | 1659 | *
|
1567 |
| - * // Changes keystroke to CTRL + SHIFT + . |
1568 |
| - * CKEDITOR.config.magicline_keystrokeBefore = CKEDITOR.CTRL + CKEDITOR.SHIFT + 190; |
| 1660 | + * // Changes keystroke to CTRL + . |
| 1661 | + * CKEDITOR.config.magicline_keystrokeNext = CKEDITOR.CTRL + 190; |
1569 | 1662 | *
|
1570 |
| - * @ignore |
1571 |
| - * @cfg {Number} [magicline_keystrokeBefore=CKEDITOR.CTRL + CKEDITOR.SHIFT + 221 (CTRK + SHIFT + ])] |
| 1663 | + * @cfg {Number} [magicline_keystrokeNext=CKEDITOR.CTRL + CKEDITOR.ALT + 221 (CTRL + ALT + ])] |
1572 | 1664 | * @member CKEDITOR.config
|
1573 | 1665 | */
|
1574 |
| -// CKEDITOR.config.magicline_keystrokeAfter = CKEDITOR.CTRL + CKEDITOR.SHIFT + 221; // CTRL + SHIFT + ] |
1575 |
| - |
1576 |
| -// %REMOVE_END% |
| 1666 | +CKEDITOR.config.magicline_keystrokeNext = CKEDITOR.CTRL + CKEDITOR.ALT + 221; // CTRL + ALT + ] |
1577 | 1667 |
|
1578 | 1668 | /**
|
1579 | 1669 | * Defines box color. The color may be adjusted to enhance readability.
|
|
0 commit comments