/**\r
- * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.\r
+ * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.\r
* For licensing, see LICENSE.md or http://ckeditor.com/license\r
*/\r
\r
\r
( function() {\r
CKEDITOR.dialog.add( 'link', function( editor ) {\r
- var plugin = CKEDITOR.plugins.link;\r
+ var plugin = CKEDITOR.plugins.link,\r
+ initialLinkText;\r
+\r
+ function createRangeForLink( editor, link ) {\r
+ var range = editor.createRange();\r
+\r
+ range.setStartBefore( link );\r
+ range.setEndAfter( link );\r
+\r
+ return range;\r
+ }\r
+\r
+ function insertLinksIntoSelection( editor, data ) {\r
+ var attributes = plugin.getLinkAttributes( editor, data ),\r
+ ranges = editor.getSelection().getRanges(),\r
+ style = new CKEDITOR.style( {\r
+ element: 'a',\r
+ attributes: attributes.set\r
+ } ),\r
+ rangesToSelect = [],\r
+ range,\r
+ text,\r
+ nestedLinks,\r
+ i,\r
+ j;\r
+\r
+ style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why.\r
+\r
+ for ( i = 0; i < ranges.length; i++ ) {\r
+ range = ranges[ i ];\r
+\r
+ // Use link URL as text with a collapsed cursor.\r
+ if ( range.collapsed ) {\r
+ // Short mailto link text view (http://dev.ckeditor.com/ticket/5736).\r
+ text = new CKEDITOR.dom.text( data.linkText || ( data.type == 'email' ?\r
+ data.email.address : attributes.set[ 'data-cke-saved-href' ] ), editor.document );\r
+ range.insertNode( text );\r
+ range.selectNodeContents( text );\r
+ } else if ( initialLinkText !== data.linkText ) {\r
+ text = new CKEDITOR.dom.text( data.linkText, editor.document );\r
+\r
+ // Shrink range to preserve block element.\r
+ range.shrink( CKEDITOR.SHRINK_TEXT );\r
+\r
+ // Use extractHtmlFromRange to remove markup within the selection. Also this method is a little\r
+ // smarter than range#deleteContents as it plays better e.g. with table cells.\r
+ editor.editable().extractHtmlFromRange( range );\r
+\r
+ range.insertNode( text );\r
+ }\r
+\r
+ // Editable links nested within current range should be removed, so that the link is applied to whole selection.\r
+ nestedLinks = range._find( 'a' );\r
+\r
+ for ( j = 0; j < nestedLinks.length; j++ ) {\r
+ nestedLinks[ j ].remove( true );\r
+ }\r
+\r
+\r
+ // Apply style.\r
+ style.applyToRange( range, editor );\r
+\r
+ rangesToSelect.push( range );\r
+ }\r
+\r
+ editor.getSelection().selectRanges( rangesToSelect );\r
+ }\r
+\r
+ function editLinksInSelection( editor, selectedElements, data ) {\r
+ var attributes = plugin.getLinkAttributes( editor, data ),\r
+ ranges = [],\r
+ element,\r
+ href,\r
+ textView,\r
+ newText,\r
+ i;\r
+\r
+ for ( i = 0; i < selectedElements.length; i++ ) {\r
+ // We're only editing an existing link, so just overwrite the attributes.\r
+ element = selectedElements[ i ];\r
+ href = element.data( 'cke-saved-href' );\r
+ textView = element.getHtml();\r
+\r
+ element.setAttributes( attributes.set );\r
+ element.removeAttributes( attributes.removed );\r
+\r
+\r
+ if ( data.linkText && initialLinkText != data.linkText ) {\r
+ // Display text has been changed.\r
+ newText = data.linkText;\r
+ } else if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 ) {\r
+ // Update text view when user changes protocol (http://dev.ckeditor.com/ticket/4612).\r
+ // Short mailto link text view (http://dev.ckeditor.com/ticket/5736).\r
+ newText = data.type == 'email' ? data.email.address : attributes.set[ 'data-cke-saved-href' ];\r
+ }\r
+\r
+ if ( newText ) {\r
+ element.setText( newText );\r
+ }\r
+\r
+ ranges.push( createRangeForLink( editor, element ) );\r
+ }\r
+\r
+ // We changed the content, so need to select it again.\r
+ editor.getSelection().selectRanges( ranges );\r
+ }\r
\r
// Handles the event when the "Target" selection box is changed.\r
var targetChanged = function() {\r
\r
return {\r
title: linkLang.title,\r
- minWidth: 350,\r
- minHeight: 230,\r
+ minWidth: ( CKEDITOR.skinName || editor.config.skin ) == 'moono-lisa' ? 450 : 350,\r
+ minHeight: 240,\r
contents: [ {\r
id: 'info',\r
label: linkLang.info,\r
title: linkLang.info,\r
elements: [ {\r
+ type: 'text',\r
+ id: 'linkDisplayText',\r
+ label: linkLang.displayText,\r
+ setup: function() {\r
+ this.enable();\r
+\r
+ this.setValue( editor.getSelection().getSelectedText() );\r
+\r
+ // Keep inner text so that it can be compared in commit function. By obtaining value from getData()\r
+ // we get value stripped from new line chars which is important when comparing the value later on.\r
+ initialLinkText = this.getValue();\r
+ },\r
+ commit: function( data ) {\r
+ data.linkText = this.isEnabled() ? this.getValue() : '';\r
+ }\r
+ },\r
+ {\r
id: 'linkType',\r
type: 'select',\r
label: linkLang.type,\r
label: commonLang.protocol,\r
'default': 'http://',\r
items: [\r
- // Force 'ltr' for protocol names in BIDI. (#5433)\r
+ // Force 'ltr' for protocol names in BIDI. (http://dev.ckeditor.com/ticket/5433)\r
[ 'http://\u200E', 'http://' ],\r
[ 'https://\u200E', 'https://' ],\r
[ 'ftp://\u200E', 'ftp://' ],\r
},\r
commit: function( data ) {\r
// IE will not trigger the onChange event if the mouse has been used\r
- // to carry all the operations #4724\r
+ // to carry all the operations http://dev.ckeditor.com/ticket/4724\r
this.onChange();\r
\r
if ( !data.url )\r
setup: setupAdvParams,\r
commit: commitAdvParams\r
} ]\r
+ },\r
+ {\r
+ type: 'hbox',\r
+ widths: [ '45%', '55%' ],\r
+ children: [ {\r
+ type: 'checkbox',\r
+ id: 'download',\r
+ requiredContent: 'a[download]',\r
+ label: linkLang.download,\r
+ setup: function( data ) {\r
+ if ( data.download !== undefined )\r
+ this.setValue( 'checked', 'checked' );\r
+ },\r
+ commit: function( data ) {\r
+ if ( this.getValue() ) {\r
+ data.download = this.getValue();\r
+ }\r
+ }\r
+ } ]\r
} ]\r
} ]\r
} ],\r
onShow: function() {\r
var editor = this.getParentEditor(),\r
selection = editor.getSelection(),\r
- element = null;\r
+ displayTextField = this.getContentElement( 'info', 'linkDisplayText' ).getElement().getParent().getParent(),\r
+ elements = plugin.getSelectedLink( editor, true ),\r
+ firstLink = elements[ 0 ] || null;\r
\r
// Fill in all the relevant fields if there's already one link selected.\r
- if ( ( element = plugin.getSelectedLink( editor ) ) && element.hasAttribute( 'href' ) ) {\r
+ if ( firstLink && firstLink.hasAttribute( 'href' ) ) {\r
// Don't change selection if some element is already selected.\r
// For example - don't destroy fake selection.\r
- if ( !selection.getSelectedElement() )\r
- selection.selectElement( element );\r
- } else {\r
- element = null;\r
+ if ( !selection.getSelectedElement() && !selection.isInTable() ) {\r
+ selection.selectElement( firstLink );\r
+ }\r
}\r
\r
- var data = plugin.parseLinkAttributes( editor, element );\r
+ var data = plugin.parseLinkAttributes( editor, firstLink );\r
+\r
+ // Here we'll decide whether or not we want to show Display Text field.\r
+ if ( elements.length <= 1 && plugin.showDisplayTextForElement( firstLink, editor ) ) {\r
+ displayTextField.show();\r
+ } else {\r
+ displayTextField.hide();\r
+ }\r
\r
// Record down the selected element in the dialog.\r
- this._.selectedElement = element;\r
+ this._.selectedElements = elements;\r
\r
this.setupContent( data );\r
},\r
// Collect data from fields.\r
this.commitContent( data );\r
\r
- var selection = editor.getSelection(),\r
- attributes = plugin.getLinkAttributes( editor, data );\r
-\r
- if ( !this._.selectedElement ) {\r
- var range = selection.getRanges()[ 0 ];\r
-\r
- // Use link URL as text with a collapsed cursor.\r
- if ( range.collapsed ) {\r
- // Short mailto link text view (#5736).\r
- var text = new CKEDITOR.dom.text( data.type == 'email' ?\r
- data.email.address : attributes.set[ 'data-cke-saved-href' ], editor.document );\r
- range.insertNode( text );\r
- range.selectNodeContents( text );\r
- }\r
-\r
- // Apply style.\r
- var style = new CKEDITOR.style( {\r
- element: 'a',\r
- attributes: attributes.set\r
- } );\r
-\r
- style.type = CKEDITOR.STYLE_INLINE; // need to override... dunno why.\r
- style.applyToRange( range, editor );\r
- range.select();\r
+ if ( !this._.selectedElements.length ) {\r
+ insertLinksIntoSelection( editor, data );\r
} else {\r
- // We're only editing an existing link, so just overwrite the attributes.\r
- var element = this._.selectedElement,\r
- href = element.data( 'cke-saved-href' ),\r
- textView = element.getHtml();\r
-\r
- element.setAttributes( attributes.set );\r
- element.removeAttributes( attributes.removed );\r
-\r
- // Update text view when user changes protocol (#4612).\r
- if ( href == textView || data.type == 'email' && textView.indexOf( '@' ) != -1 ) {\r
- // Short mailto link text view (#5736).\r
- element.setHtml( data.type == 'email' ?\r
- data.email.address : attributes.set[ 'data-cke-saved-href' ] );\r
-\r
- // We changed the content, so need to select it again.\r
- selection.selectElement( element );\r
- }\r
+ editLinksInSelection( editor, this._.selectedElements, data );\r
\r
- delete this._.selectedElement;\r
+ delete this._.selectedElements;\r
}\r
},\r
onLoad: function() {\r