diff options
Diffstat (limited to 'sources/plugins/link/dialogs')
-rw-r--r-- | sources/plugins/link/dialogs/anchor.js | 27 | ||||
-rw-r--r-- | sources/plugins/link/dialogs/link.js | 202 |
2 files changed, 141 insertions, 88 deletions
diff --git a/sources/plugins/link/dialogs/anchor.js b/sources/plugins/link/dialogs/anchor.js index 2b32b71..04a4abe 100644 --- a/sources/plugins/link/dialogs/anchor.js +++ b/sources/plugins/link/dialogs/anchor.js | |||
@@ -18,6 +18,21 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) { | |||
18 | } ), 'cke_anchor', 'anchor' ); | 18 | } ), 'cke_anchor', 'anchor' ); |
19 | } | 19 | } |
20 | 20 | ||
21 | |||
22 | function getSelectedAnchor( selection ) { | ||
23 | var range = selection.getRanges()[ 0 ], | ||
24 | element = selection.getSelectedElement(); | ||
25 | |||
26 | // In case of table cell selection, we want to shrink selection from td to a element. | ||
27 | range.shrink( CKEDITOR.SHRINK_ELEMENT ); | ||
28 | element = range.getEnclosedNode(); | ||
29 | |||
30 | if ( element && element.type === CKEDITOR.NODE_ELEMENT && | ||
31 | ( element.data( 'cke-real-element-type' ) === 'anchor' || element.is( 'a' ) ) ) { | ||
32 | return element; | ||
33 | } | ||
34 | } | ||
35 | |||
21 | return { | 36 | return { |
22 | title: editor.lang.link.anchor.title, | 37 | title: editor.lang.link.anchor.title, |
23 | minWidth: 300, | 38 | minWidth: 300, |
@@ -35,9 +50,10 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) { | |||
35 | var newFake = createFakeAnchor( editor, attributes ); | 50 | var newFake = createFakeAnchor( editor, attributes ); |
36 | newFake.replace( this._.selectedElement ); | 51 | newFake.replace( this._.selectedElement ); |
37 | 52 | ||
38 | // Selecting fake element for IE. (#11377) | 53 | // Selecting fake element for IE. (http://dev.ckeditor.com/ticket/11377) |
39 | if ( CKEDITOR.env.ie ) | 54 | if ( CKEDITOR.env.ie ) { |
40 | editor.getSelection().selectElement( newFake ); | 55 | editor.getSelection().selectElement( newFake ); |
56 | } | ||
41 | } else { | 57 | } else { |
42 | this._.selectedElement.setAttributes( attributes ); | 58 | this._.selectedElement.setAttributes( attributes ); |
43 | } | 59 | } |
@@ -56,7 +72,7 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) { | |||
56 | // Apply style. | 72 | // Apply style. |
57 | var style = new CKEDITOR.style( { element: 'a', attributes: attributes } ); | 73 | var style = new CKEDITOR.style( { element: 'a', attributes: attributes } ); |
58 | style.type = CKEDITOR.STYLE_INLINE; | 74 | style.type = CKEDITOR.STYLE_INLINE; |
59 | editor.applyStyle( style ); | 75 | style.applyToRange( range ); |
60 | } | 76 | } |
61 | } | 77 | } |
62 | }, | 78 | }, |
@@ -67,7 +83,7 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) { | |||
67 | 83 | ||
68 | onShow: function() { | 84 | onShow: function() { |
69 | var sel = editor.getSelection(), | 85 | var sel = editor.getSelection(), |
70 | fullySelected = sel.getSelectedElement(), | 86 | fullySelected = getSelectedAnchor( sel ), |
71 | fakeSelected = fullySelected && fullySelected.data( 'cke-realelement' ), | 87 | fakeSelected = fullySelected && fullySelected.data( 'cke-realelement' ), |
72 | linkElement = fakeSelected ? | 88 | linkElement = fakeSelected ? |
73 | CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, fullySelected ) : | 89 | CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, fullySelected ) : |
@@ -77,8 +93,9 @@ CKEDITOR.dialog.add( 'anchor', function( editor ) { | |||
77 | loadElements.call( this, linkElement ); | 93 | loadElements.call( this, linkElement ); |
78 | !fakeSelected && sel.selectElement( linkElement ); | 94 | !fakeSelected && sel.selectElement( linkElement ); |
79 | 95 | ||
80 | if ( fullySelected ) | 96 | if ( fullySelected ) { |
81 | this._.selectedElement = fullySelected; | 97 | this._.selectedElement = fullySelected; |
98 | } | ||
82 | } | 99 | } |
83 | 100 | ||
84 | this.getContentElement( 'info', 'txtName' ).focus(); | 101 | this.getContentElement( 'info', 'txtName' ).focus(); |
diff --git a/sources/plugins/link/dialogs/link.js b/sources/plugins/link/dialogs/link.js index 914471f..4c60928 100644 --- a/sources/plugins/link/dialogs/link.js +++ b/sources/plugins/link/dialogs/link.js | |||
@@ -10,6 +10,110 @@ | |||
10 | var plugin = CKEDITOR.plugins.link, | 10 | var plugin = CKEDITOR.plugins.link, |
11 | initialLinkText; | 11 | initialLinkText; |
12 | 12 | ||
13 | function createRangeForLink( editor, link ) { | ||
14 | var range = editor.createRange(); | ||
15 | |||
16 | range.setStartBefore( link ); | ||
17 | range.setEndAfter( link ); | ||
18 | |||
19 | return range; | ||
20 | } | ||
21 | |||
22 | function insertLinksIntoSelection( editor, data ) { | ||
23 | var attributes = plugin.getLinkAttributes( editor, data ), | ||
24 | ranges = editor.getSelection().getRanges(), | ||
25 | style = new CKEDITOR.style( { | ||
26 | element: 'a', | ||
27 | attributes: attributes.set | ||
28 | } ), | ||
29 | rangesToSelect = [], | ||
30 | range, | ||
31 | text, | ||
32 | nestedLinks, | ||
33 | i, | ||
34 | j; | ||
35 | |||
36 | style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why. | ||
37 | |||
38 | for ( i = 0; i < ranges.length; i++ ) { | ||
39 | range = ranges[ i ]; | ||
40 | |||
41 | // Use link URL as text with a collapsed cursor. | ||
42 | if ( range.collapsed ) { | ||
43 | // Short mailto link text view (http://dev.ckeditor.com/ticket/5736). | ||
44 | text = new CKEDITOR.dom.text( data.linkText || ( data.type == 'email' ? | ||
45 | data.email.address : attributes.set[ 'data-cke-saved-href' ] ), editor.document ); | ||
46 | range.insertNode( text ); | ||
47 | range.selectNodeContents( text ); | ||
48 | } else if ( initialLinkText !== data.linkText ) { | ||
49 | text = new CKEDITOR.dom.text( data.linkText, editor.document ); | ||
50 | |||
51 | // Shrink range to preserve block element. | ||
52 | range.shrink( CKEDITOR.SHRINK_TEXT ); | ||
53 | |||
54 | // Use extractHtmlFromRange to remove markup within the selection. Also this method is a little | ||
55 | // smarter than range#deleteContents as it plays better e.g. with table cells. | ||
56 | editor.editable().extractHtmlFromRange( range ); | ||
57 | |||
58 | range.insertNode( text ); | ||
59 | } | ||
60 | |||
61 | // Editable links nested within current range should be removed, so that the link is applied to whole selection. | ||
62 | nestedLinks = range._find( 'a' ); | ||
63 | |||
64 | for ( j = 0; j < nestedLinks.length; j++ ) { | ||
65 | nestedLinks[ j ].remove( true ); | ||
66 | } | ||
67 | |||
68 | |||
69 | // Apply style. | ||
70 | style.applyToRange( range, editor ); | ||
71 | |||
72 | rangesToSelect.push( range ); | ||
73 | } | ||
74 | |||
75 | editor.getSelection().selectRanges( rangesToSelect ); | ||
76 | } | ||
77 | |||
78 | function editLinksInSelection( editor, selectedElements, data ) { | ||
79 | var attributes = plugin.getLinkAttributes( editor, data ), | ||
80 | ranges = [], | ||
81 | element, | ||
82 | href, | ||
83 | textView, | ||
84 | newText, | ||
85 | i; | ||
86 | |||
87 | for ( i = 0; i < selectedElements.length; i++ ) { | ||
88 | // We're only editing an existing link, so just overwrite the attributes. | ||
89 | element = selectedElements[ i ]; | ||
90 | href = element.data( 'cke-saved-href' ); | ||
91 | textView = element.getHtml(); | ||
92 | |||
93 | element.setAttributes( attributes.set ); | ||
94 | element.removeAttributes( attributes.removed ); | ||
95 | |||
96 | |||
97 | if ( data.linkText && initialLinkText != data.linkText ) { | ||
98 | // Display text has been changed. | ||
99 | newText = data.linkText; | ||
100 | } else if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 ) { | ||
101 | // Update text view when user changes protocol (http://dev.ckeditor.com/ticket/4612). | ||
102 | // Short mailto link text view (http://dev.ckeditor.com/ticket/5736). | ||
103 | newText = data.type == 'email' ? data.email.address : attributes.set[ 'data-cke-saved-href' ]; | ||
104 | } | ||
105 | |||
106 | if ( newText ) { | ||
107 | element.setText( newText ); | ||
108 | } | ||
109 | |||
110 | ranges.push( createRangeForLink( editor, element ) ); | ||
111 | } | ||
112 | |||
113 | // We changed the content, so need to select it again. | ||
114 | editor.getSelection().selectRanges( ranges ); | ||
115 | } | ||
116 | |||
13 | // Handles the event when the "Target" selection box is changed. | 117 | // Handles the event when the "Target" selection box is changed. |
14 | var targetChanged = function() { | 118 | var targetChanged = function() { |
15 | var dialog = this.getDialog(), | 119 | var dialog = this.getDialog(), |
@@ -163,7 +267,7 @@ | |||
163 | label: commonLang.protocol, | 267 | label: commonLang.protocol, |
164 | 'default': 'http://', | 268 | 'default': 'http://', |
165 | items: [ | 269 | items: [ |
166 | // Force 'ltr' for protocol names in BIDI. (#5433) | 270 | // Force 'ltr' for protocol names in BIDI. (http://dev.ckeditor.com/ticket/5433) |
167 | [ 'http://\u200E', 'http://' ], | 271 | [ 'http://\u200E', 'http://' ], |
168 | [ 'https://\u200E', 'https://' ], | 272 | [ 'https://\u200E', 'https://' ], |
169 | [ 'ftp://\u200E', 'ftp://' ], | 273 | [ 'ftp://\u200E', 'ftp://' ], |
@@ -236,7 +340,7 @@ | |||
236 | }, | 340 | }, |
237 | commit: function( data ) { | 341 | commit: function( data ) { |
238 | // IE will not trigger the onChange event if the mouse has been used | 342 | // IE will not trigger the onChange event if the mouse has been used |
239 | // to carry all the operations #4724 | 343 | // to carry all the operations http://dev.ckeditor.com/ticket/4724 |
240 | this.onChange(); | 344 | this.onChange(); |
241 | 345 | ||
242 | if ( !data.url ) | 346 | if ( !data.url ) |
@@ -819,33 +923,30 @@ | |||
819 | onShow: function() { | 923 | onShow: function() { |
820 | var editor = this.getParentEditor(), | 924 | var editor = this.getParentEditor(), |
821 | selection = editor.getSelection(), | 925 | selection = editor.getSelection(), |
822 | selectedElement = selection.getSelectedElement(), | ||
823 | displayTextField = this.getContentElement( 'info', 'linkDisplayText' ).getElement().getParent().getParent(), | 926 | displayTextField = this.getContentElement( 'info', 'linkDisplayText' ).getElement().getParent().getParent(), |
824 | element = null; | 927 | elements = plugin.getSelectedLink( editor, true ), |
928 | firstLink = elements[ 0 ] || null; | ||
825 | 929 | ||
826 | // Fill in all the relevant fields if there's already one link selected. | 930 | // Fill in all the relevant fields if there's already one link selected. |
827 | if ( ( element = plugin.getSelectedLink( editor ) ) && element.hasAttribute( 'href' ) ) { | 931 | if ( firstLink && firstLink.hasAttribute( 'href' ) ) { |
828 | // Don't change selection if some element is already selected. | 932 | // Don't change selection if some element is already selected. |
829 | // For example - don't destroy fake selection. | 933 | // For example - don't destroy fake selection. |
830 | if ( !selectedElement ) { | 934 | if ( !selection.getSelectedElement() && !selection.isInTable() ) { |
831 | selection.selectElement( element ); | 935 | selection.selectElement( firstLink ); |
832 | selectedElement = element; | ||
833 | } | 936 | } |
834 | } else { | ||
835 | element = null; | ||
836 | } | 937 | } |
837 | 938 | ||
939 | var data = plugin.parseLinkAttributes( editor, firstLink ); | ||
940 | |||
838 | // Here we'll decide whether or not we want to show Display Text field. | 941 | // Here we'll decide whether or not we want to show Display Text field. |
839 | if ( plugin.showDisplayTextForElement( selectedElement, editor ) ) { | 942 | if ( elements.length <= 1 && plugin.showDisplayTextForElement( firstLink, editor ) ) { |
840 | displayTextField.show(); | 943 | displayTextField.show(); |
841 | } else { | 944 | } else { |
842 | displayTextField.hide(); | 945 | displayTextField.hide(); |
843 | } | 946 | } |
844 | 947 | ||
845 | var data = plugin.parseLinkAttributes( editor, element ); | ||
846 | |||
847 | // Record down the selected element in the dialog. | 948 | // Record down the selected element in the dialog. |
848 | this._.selectedElement = element; | 949 | this._.selectedElements = elements; |
849 | 950 | ||
850 | this.setupContent( data ); | 951 | this.setupContent( data ); |
851 | }, | 952 | }, |
@@ -855,77 +956,12 @@ | |||
855 | // Collect data from fields. | 956 | // Collect data from fields. |
856 | this.commitContent( data ); | 957 | this.commitContent( data ); |
857 | 958 | ||
858 | var selection = editor.getSelection(), | 959 | if ( !this._.selectedElements.length ) { |
859 | attributes = plugin.getLinkAttributes( editor, data ), | 960 | insertLinksIntoSelection( editor, data ); |
860 | bm, | ||
861 | nestedLinks; | ||
862 | |||
863 | if ( !this._.selectedElement ) { | ||
864 | var range = selection.getRanges()[ 0 ], | ||
865 | text; | ||
866 | |||
867 | // Use link URL as text with a collapsed cursor. | ||
868 | if ( range.collapsed ) { | ||
869 | // Short mailto link text view (#5736). | ||
870 | text = new CKEDITOR.dom.text( data.linkText || ( data.type == 'email' ? | ||
871 | data.email.address : attributes.set[ 'data-cke-saved-href' ] ), editor.document ); | ||
872 | range.insertNode( text ); | ||
873 | range.selectNodeContents( text ); | ||
874 | } else if ( initialLinkText !== data.linkText ) { | ||
875 | text = new CKEDITOR.dom.text( data.linkText, editor.document ); | ||
876 | |||
877 | // Shrink range to preserve block element. | ||
878 | range.shrink( CKEDITOR.SHRINK_TEXT ); | ||
879 | |||
880 | // Use extractHtmlFromRange to remove markup within the selection. Also this method is a little | ||
881 | // smarter than range#deleteContents as it plays better e.g. with table cells. | ||
882 | editor.editable().extractHtmlFromRange( range ); | ||
883 | |||
884 | range.insertNode( text ); | ||
885 | } | ||
886 | |||
887 | // Editable links nested within current range should be removed, so that the link is applied to whole selection. | ||
888 | nestedLinks = range._find( 'a' ); | ||
889 | |||
890 | for ( var i = 0; i < nestedLinks.length; i++ ) { | ||
891 | nestedLinks[ i ].remove( true ); | ||
892 | } | ||
893 | |||
894 | // Apply style. | ||
895 | var style = new CKEDITOR.style( { | ||
896 | element: 'a', | ||
897 | attributes: attributes.set | ||
898 | } ); | ||
899 | |||
900 | style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why. | ||
901 | style.applyToRange( range, editor ); | ||
902 | range.select(); | ||
903 | } else { | 961 | } else { |
904 | // We're only editing an existing link, so just overwrite the attributes. | 962 | editLinksInSelection( editor, this._.selectedElements, data ); |
905 | var element = this._.selectedElement, | ||
906 | href = element.data( 'cke-saved-href' ), | ||
907 | textView = element.getHtml(), | ||
908 | newText; | ||
909 | |||
910 | element.setAttributes( attributes.set ); | ||
911 | element.removeAttributes( attributes.removed ); | ||
912 | |||
913 | if ( data.linkText && initialLinkText != data.linkText ) { | ||
914 | // Display text has been changed. | ||
915 | newText = data.linkText; | ||
916 | } else if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 ) { | ||
917 | // Update text view when user changes protocol (#4612). | ||
918 | // Short mailto link text view (#5736). | ||
919 | newText = data.type == 'email' ? data.email.address : attributes.set[ 'data-cke-saved-href' ]; | ||
920 | } | ||
921 | |||
922 | if ( newText ) { | ||
923 | element.setText( newText ); | ||
924 | // We changed the content, so need to select it again. | ||
925 | selection.selectElement( element ); | ||
926 | } | ||
927 | 963 | ||
928 | delete this._.selectedElement; | 964 | delete this._.selectedElements; |
929 | } | 965 | } |
930 | }, | 966 | }, |
931 | onLoad: function() { | 967 | onLoad: function() { |