Index: CKEditor/releases/latest/_source/plugins/link/dialogs/link.js
===================================================================
--- CKEditor/releases/latest/_source/plugins/link/dialogs/link.js	(revision 4887)
+++ CKEditor/releases/latest/_source/plugins/link/dialogs/link.js	(revision 5194)
@@ -18,16 +18,24 @@
 
 		popupFeatures = popupFeatures.getElement();
-
-		if ( value == 'popup' )
-		{
-			popupFeatures.show();
-			targetName.setLabel( editor.lang.link.targetPopupName );
-		}
-		else
-		{
-			popupFeatures.hide();
-			targetName.setLabel( editor.lang.link.targetFrameName );
-			this.getDialog().setValueOf( 'target', 'linkTargetName', value.charAt( 0 ) == '_' ? value : '' );
-		}
+		popupFeatures.hide();
+		targetName.setValue( '' );
+
+		switch ( value )
+ 		{
+			case 'frame' :
+				targetName.setLabel( editor.lang.link.targetFrameName );
+				targetName.getElement().show();
+				break;
+			case 'popup' :
+				popupFeatures.show();
+				targetName.setLabel( editor.lang.link.targetPopupName );
+				targetName.getElement().show();
+				break;
+			default :
+				targetName.setValue( value );
+				targetName.getElement().hide();
+				break;
+ 		}
+
 	};
 
@@ -70,9 +78,10 @@
 
 	// Loads the parameters in a selected link to the link dialog fields.
-	var emailRegex = /^mailto:([^?]+)(?:\?(.+))?$/,
+	var javascriptProtocolRegex = /^javascript:/,
+		emailRegex = /^mailto:([^?]+)(?:\?(.+))?$/,
 		emailSubjectRegex = /subject=([^;?:@&=$,\/]*)/,
 		emailBodyRegex = /body=([^;?:@&=$,\/]*)/,
 		anchorRegex = /^#(.*)$/,
-		urlRegex = /^(?!javascript)((?:http|https|ftp|news):\/\/)?(.*)$/,
+		urlRegex = /^((?:http|https|ftp|news):\/\/)?(.*)$/,
 		selectableTargets = /^(_(?:self|top|parent|blank))$/,
 		encodedEmailLinkRegex = /^javascript:void\(location\.href='mailto:'\+String\.fromCharCode\(([^)]+)\)(?:\+'(.*)')?\)$/,
@@ -86,4 +95,5 @@
 	{
 		var href = element ? ( element.getAttribute( '_cke_saved_href' ) || element.getAttribute( 'href' ) ) : '',
+		 	javascriptMatch,
 			emailMatch,
 			anchorMatch,
@@ -91,22 +101,7 @@
 			retval = {};
 
-		if ( ( anchorMatch = href.match( anchorRegex ) ) )
+		if ( ( javascriptMatch = href.match( javascriptProtocolRegex ) ) )
 		{
-			retval.type = 'anchor';
-			retval.anchor = {};
-			retval.anchor.name = retval.anchor.id = anchorMatch[1];
-		}
-		// urlRegex matches empty strings, so need to check for href as well.
-		else if ( href && ( urlMatch = href.match( urlRegex ) ) )
-		{
-			retval.type = 'url';
-			retval.url = {};
-			retval.url.protocol = urlMatch[1];
-			retval.url.url = urlMatch[2];
-		}
-		// Protected email link as encoded string.
-		else if ( !emailProtection || emailProtection == 'encode' )
-		{
-			if( emailProtection == 'encode' )
+			if ( emailProtection == 'encode' )
 			{
 				href = href.replace( encodedEmailLinkRegex,
@@ -116,10 +111,45 @@
 							       String.fromCharCode.apply( String, protectedAddress.split( ',' ) ) +
 							       ( rest && unescapeSingleQuote( rest ) );
-						} );
-			}
-
-			emailMatch = href.match( emailRegex );
-
-			if( emailMatch )
+						});
+			}
+			// Protected email link as function call.
+			else if ( emailProtection )
+			{
+				href.replace( functionCallProtectedEmailLinkRegex, function( match, funcName, funcArgs )
+				{
+					if ( funcName == compiledProtectionFunction.name )
+					{
+						retval.type = 'email';
+						var email = retval.email = {};
+
+						var paramRegex = /[^,\s]+/g,
+							paramQuoteRegex = /(^')|('$)/g,
+							paramsMatch = funcArgs.match( paramRegex ),
+							paramsMatchLength = paramsMatch.length,
+							paramName,
+							paramVal;
+
+						for ( var i = 0; i < paramsMatchLength; i++ )
+						{
+							paramVal = decodeURIComponent( unescapeSingleQuote( paramsMatch[ i ].replace( paramQuoteRegex, '' ) ) );
+							paramName = compiledProtectionFunction.params[ i ].toLowerCase();
+							email[ paramName ] = paramVal;
+						}
+						email.address = [ email.name, email.domain ].join( '@' );
+					}
+				} );
+			}
+		}
+
+		if ( !retval.type )
+		{
+			if ( ( anchorMatch = href.match( anchorRegex ) ) )
+			{
+				retval.type = 'anchor';
+				retval.anchor = {};
+				retval.anchor.name = retval.anchor.id = anchorMatch[1];
+			}
+			// Protected email link as encoded string.
+			else if ( ( emailMatch = href.match( emailRegex ) ) )
 			{
 				var subjectMatch = href.match( emailSubjectRegex ),
@@ -132,34 +162,15 @@
 				bodyMatch && ( email.body = decodeURIComponent( bodyMatch[ 1 ] ) );
 			}
+			// urlRegex matches empty strings, so need to check for href as well.
+			else if (  href && ( urlMatch = href.match( urlRegex ) ) )
+			{
+				retval.type = 'url';
+				retval.url = {};
+				retval.url.protocol = urlMatch[1];
+				retval.url.url = urlMatch[2];
+			}
+			else
+				retval.type = 'url';
 		}
-		// Protected email link as function call.
-		else if( emailProtection )
-		{
-			href.replace( functionCallProtectedEmailLinkRegex, function( match, funcName, funcArgs )
-			{
-				if( funcName == compiledProtectionFunction.name )
-				{
-					retval.type = 'email';
-					var email = retval.email = {};
-
-					var paramRegex = /[^,\s]+/g,
-						paramQuoteRegex = /(^')|('$)/g,
-						paramsMatch = funcArgs.match( paramRegex ),
-						paramsMatchLength = paramsMatch.length,
-						paramName,
-						paramVal;
-
-					for ( var i = 0; i < paramsMatchLength; i++ )
-					{
-						paramVal = decodeURIComponent( unescapeSingleQuote( paramsMatch[ i ].replace( paramQuoteRegex, '' ) ) );
-						paramName = compiledProtectionFunction.params[ i ].toLowerCase();
-						email[ paramName ] = paramVal;
-					}
-					email.address = [ email.name, email.domain ].join( '@' );
-				}
-			} );
-		}
-		else
-			retval.type = 'url';
 
 		// Load target and popup settings.
@@ -228,5 +239,5 @@
 			anchors = retval.anchors = [];
 
-		for( var i = 0; i < elements.count() ; i++ )
+		for ( var i = 0; i < elements.count() ; i++ )
 		{
 			var item = elements.getItem( i );
@@ -299,5 +310,5 @@
 
 	// Compile the protection function pattern.
-	if( emailProtection && emailProtection != 'encode' )
+	if ( emailProtection && emailProtection != 'encode' )
 	{
 		var compiledProtectionFunction = {};
@@ -370,5 +381,5 @@
 						items :
 						[
-							[ editor.lang.common.url, 'url' ],
+							[ editor.lang.link.toUrl, 'url' ],
 							[ editor.lang.link.toAnchor, 'anchor' ],
 							[ editor.lang.link.toEmail, 'email' ]
@@ -426,4 +437,5 @@
 										id : 'url',
 										label : editor.lang.common.url,
+										required: true,
 										onLoad : function ()
 										{
@@ -475,11 +487,11 @@
 											this.allowOnChange = true;
 
-											var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
-											if ( linkType && linkType.getValue() == 'url' )
-												this.select();
-
 										},
 										commit : function( data )
 										{
+											// IE will not trigger the onChange event if the mouse has been used
+											// to carry all the operations #4724
+											this.onChange();
+
 											if ( !data.url )
 												data.url = {};
@@ -514,7 +526,7 @@
 						[
 							{
-								type : 'html',
+								type : 'fieldset',
 								id : 'selectAnchorText',
-								html : CKEDITOR.tools.htmlEncode( editor.lang.link.selectAnchor ),
+								label : editor.lang.link.selectAnchor,
 								setup : function( data )
 								{
@@ -523,5 +535,88 @@
 									else
 										this.getElement().hide();
-								}
+								},
+								children :
+								[
+									{
+										type : 'hbox',
+										id : 'selectAnchor',
+										children :
+										[
+											{
+												type : 'select',
+												id : 'anchorName',
+												'default' : '',
+												label : editor.lang.link.anchorName,
+												style : 'width: 100%;',
+												items :
+												[
+													[ '' ]
+												],
+												setup : function( data )
+												{
+													this.clear();
+													this.add( '' );
+													for ( var i = 0 ; i < data.anchors.length ; i++ )
+													{
+														if ( data.anchors[i].name )
+															this.add( data.anchors[i].name );
+													}
+
+													if ( data.anchor )
+														this.setValue( data.anchor.name );
+
+													var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
+													if ( linkType && linkType.getValue() == 'email' )
+														this.focus();
+												},
+												commit : function( data )
+												{
+													if ( !data.anchor )
+														data.anchor = {};
+
+													data.anchor.name = this.getValue();
+												}
+											},
+											{
+												type : 'select',
+												id : 'anchorId',
+												'default' : '',
+												label : editor.lang.link.anchorId,
+												style : 'width: 100%;',
+												items :
+												[
+													[ '' ]
+												],
+												setup : function( data )
+												{
+													this.clear();
+													this.add( '' );
+													for ( var i = 0 ; i < data.anchors.length ; i++ )
+													{
+														if ( data.anchors[i].id )
+															this.add( data.anchors[i].id );
+													}
+
+													if ( data.anchor )
+														this.setValue( data.anchor.id );
+												},
+												commit : function( data )
+												{
+													if ( !data.anchor )
+														data.anchor = {};
+
+													data.anchor.id = this.getValue();
+												}
+											}
+										],
+										setup : function( data )
+										{
+											if ( data.anchors.length > 0 )
+												this.getElement().show();
+											else
+												this.getElement().hide();
+										}
+									}
+								]
 							},
 							{
@@ -529,88 +624,10 @@
 								id : 'noAnchors',
 								style : 'text-align: center;',
-								html : '<div>' + CKEDITOR.tools.htmlEncode( editor.lang.link.noAnchors ) + '</div>',
+								html : '<div role="label" tabIndex="-1">' + CKEDITOR.tools.htmlEncode( editor.lang.link.noAnchors ) + '</div>',
+								// Focus the first element defined in above html.
+								focus : true,
 								setup : function( data )
 								{
 									if ( data.anchors.length < 1 )
-										this.getElement().show();
-									else
-										this.getElement().hide();
-								}
-							},
-							{
-								type : 'hbox',
-								id : 'selectAnchor',
-								children :
-								[
-									{
-										type : 'select',
-										id : 'anchorName',
-										'default' : '',
-										label : editor.lang.link.anchorName,
-										style : 'width: 100%;',
-										items :
-										[
-											[ '' ]
-										],
-										setup : function( data )
-										{
-											this.clear();
-											this.add( '' );
-											for ( var i = 0 ; i < data.anchors.length ; i++ )
-											{
-												if ( data.anchors[i].name )
-													this.add( data.anchors[i].name );
-											}
-
-											if ( data.anchor )
-												this.setValue( data.anchor.name );
-
-											var linkType = this.getDialog().getContentElement( 'info', 'linkType' );
-											if ( linkType && linkType.getValue() == 'email' )
-												this.focus();
-										},
-										commit : function( data )
-										{
-											if ( !data.anchor )
-												data.anchor = {};
-
-											data.anchor.name = this.getValue();
-										}
-									},
-									{
-										type : 'select',
-										id : 'anchorId',
-										'default' : '',
-										label : editor.lang.link.anchorId,
-										style : 'width: 100%;',
-										items :
-										[
-											[ '' ]
-										],
-										setup : function( data )
-										{
-											this.clear();
-											this.add( '' );
-											for ( var i = 0 ; i < data.anchors.length ; i++ )
-											{
-												if ( data.anchors[i].id )
-													this.add( data.anchors[i].id );
-											}
-
-											if ( data.anchor )
-												this.setValue( data.anchor.id );
-										},
-										commit : function( data )
-										{
-											if ( !data.anchor )
-												data.anchor = {};
-
-											data.anchor.id = this.getValue();
-										}
-									}
-								],
-								setup : function( data )
-								{
-									if ( data.anchors.length > 0 )
 										this.getElement().show();
 									else
@@ -635,4 +652,5 @@
 								id : 'emailAddress',
 								label : editor.lang.link.emailAddress,
+								required : true,
 								validate : function()
 								{
@@ -722,16 +740,16 @@
 								type : 'select',
 								id : 'linkTargetType',
-								label : editor.lang.link.target,
+								label : editor.lang.common.target,
 								'default' : 'notSet',
 								style : 'width : 100%;',
 								'items' :
 								[
-									[ editor.lang.link.targetNotSet, 'notSet' ],
+									[ editor.lang.common.notSet, 'notSet' ],
 									[ editor.lang.link.targetFrame, 'frame' ],
 									[ editor.lang.link.targetPopup, 'popup' ],
-									[ editor.lang.link.targetNew, '_blank' ],
-									[ editor.lang.link.targetTop, '_top' ],
-									[ editor.lang.link.targetSelf, '_self' ],
-									[ editor.lang.link.targetParent, '_parent' ]
+									[ editor.lang.common.targetNew, '_blank' ],
+									[ editor.lang.common.targetTop, '_top' ],
+									[ editor.lang.common.targetSelf, '_self' ],
+									[ editor.lang.common.targetParent, '_parent' ]
 								],
 								onChange : targetChanged,
@@ -778,143 +796,146 @@
 						[
 							{
-								type : 'html',
-								html : CKEDITOR.tools.htmlEncode( editor.lang.link.popupFeatures )
-							},
-							{
-								type : 'hbox',
+								type : 'fieldset',
+								label : editor.lang.link.popupFeatures,
 								children :
 								[
 									{
-										type : 'checkbox',
-										id : 'resizable',
-										label : editor.lang.link.popupResizable,
-										setup : setupPopupParams,
-										commit : commitPopupParams
+										type : 'hbox',
+										children :
+										[
+											{
+												type : 'checkbox',
+												id : 'resizable',
+												label : editor.lang.link.popupResizable,
+												setup : setupPopupParams,
+												commit : commitPopupParams
+											},
+											{
+												type : 'checkbox',
+												id : 'status',
+												label : editor.lang.link.popupStatusBar,
+												setup : setupPopupParams,
+												commit : commitPopupParams
+
+											}
+										]
 									},
 									{
-										type : 'checkbox',
-										id : 'status',
-										label : editor.lang.link.popupStatusBar,
-										setup : setupPopupParams,
-										commit : commitPopupParams
-
-									}
-								]
-							},
-							{
-								type : 'hbox',
-								children :
-								[
-									{
-										type : 'checkbox',
-										id : 'location',
-										label : editor.lang.link.popupLocationBar,
-										setup : setupPopupParams,
-										commit : commitPopupParams
-
+										type : 'hbox',
+										children :
+										[
+											{
+												type : 'checkbox',
+												id : 'location',
+												label : editor.lang.link.popupLocationBar,
+												setup : setupPopupParams,
+												commit : commitPopupParams
+
+											},
+											{
+												type : 'checkbox',
+												id : 'toolbar',
+												label : editor.lang.link.popupToolbar,
+												setup : setupPopupParams,
+												commit : commitPopupParams
+
+											}
+										]
 									},
 									{
-										type : 'checkbox',
-										id : 'toolbar',
-										label : editor.lang.link.popupToolbar,
-										setup : setupPopupParams,
-										commit : commitPopupParams
-
-									}
-								]
-							},
-							{
-								type : 'hbox',
-								children :
-								[
-									{
-										type : 'checkbox',
-										id : 'menubar',
-										label : editor.lang.link.popupMenuBar,
-										setup : setupPopupParams,
-										commit : commitPopupParams
-
+										type : 'hbox',
+										children :
+										[
+											{
+												type : 'checkbox',
+												id : 'menubar',
+												label : editor.lang.link.popupMenuBar,
+												setup : setupPopupParams,
+												commit : commitPopupParams
+
+											},
+											{
+												type : 'checkbox',
+												id : 'fullscreen',
+												label : editor.lang.link.popupFullScreen,
+												setup : setupPopupParams,
+												commit : commitPopupParams
+
+											}
+										]
 									},
 									{
-										type : 'checkbox',
-										id : 'fullscreen',
-										label : editor.lang.link.popupFullScreen,
-										setup : setupPopupParams,
-										commit : commitPopupParams
-
-									}
-								]
-							},
-							{
-								type : 'hbox',
-								children :
-								[
-									{
-										type : 'checkbox',
-										id : 'scrollbars',
-										label : editor.lang.link.popupScrollBars,
-										setup : setupPopupParams,
-										commit : commitPopupParams
-
+										type : 'hbox',
+										children :
+										[
+											{
+												type : 'checkbox',
+												id : 'scrollbars',
+												label : editor.lang.link.popupScrollBars,
+												setup : setupPopupParams,
+												commit : commitPopupParams
+
+											},
+											{
+												type : 'checkbox',
+												id : 'dependent',
+												label : editor.lang.link.popupDependent,
+												setup : setupPopupParams,
+												commit : commitPopupParams
+
+											}
+										]
 									},
 									{
-										type : 'checkbox',
-										id : 'dependent',
-										label : editor.lang.link.popupDependent,
-										setup : setupPopupParams,
-										commit : commitPopupParams
-
-									}
-								]
-							},
-							{
-								type : 'hbox',
-								children :
-								[
-									{
-										type :  'text',
-										widths : [ '30%', '70%' ],
-										labelLayout : 'horizontal',
-										label : editor.lang.link.popupWidth,
-										id : 'width',
-										setup : setupPopupParams,
-										commit : commitPopupParams
-
+										type : 'hbox',
+										children :
+										[
+											{
+												type :  'text',
+												widths : [ '30%', '70%' ],
+												labelLayout : 'horizontal',
+												label : editor.lang.link.popupWidth,
+												id : 'width',
+												setup : setupPopupParams,
+												commit : commitPopupParams
+
+											},
+											{
+												type :  'text',
+												labelLayout : 'horizontal',
+												widths : [ '55%', '45%' ],
+												label : editor.lang.link.popupLeft,
+												id : 'left',
+												setup : setupPopupParams,
+												commit : commitPopupParams
+
+											}
+										]
 									},
 									{
-										type :  'text',
-										labelLayout : 'horizontal',
-										widths : [ '55%', '45%' ],
-										label : editor.lang.link.popupLeft,
-										id : 'left',
-										setup : setupPopupParams,
-										commit : commitPopupParams
-
-									}
-								]
-							},
-							{
-								type : 'hbox',
-								children :
-								[
-									{
-										type :  'text',
-										labelLayout : 'horizontal',
-										widths : [ '30%', '70%' ],
-										label : editor.lang.link.popupHeight,
-										id : 'height',
-										setup : setupPopupParams,
-										commit : commitPopupParams
-
-									},
-									{
-										type :  'text',
-										labelLayout : 'horizontal',
-										label : editor.lang.link.popupTop,
-										widths : [ '55%', '45%' ],
-										id : 'top',
-										setup : setupPopupParams,
-										commit : commitPopupParams
-
+										type : 'hbox',
+										children :
+										[
+											{
+												type :  'text',
+												labelLayout : 'horizontal',
+												widths : [ '30%', '70%' ],
+												label : editor.lang.link.popupHeight,
+												id : 'height',
+												setup : setupPopupParams,
+												commit : commitPopupParams
+
+											},
+											{
+												type :  'text',
+												labelLayout : 'horizontal',
+												label : editor.lang.link.popupTop,
+												widths : [ '55%', '45%' ],
+												id : 'top',
+												setup : setupPopupParams,
+												commit : commitPopupParams
+
+											}
+										]
 									}
 								]
@@ -979,5 +1000,5 @@
 										items :
 										[
-											[ editor.lang.link.langDirNotSet, '' ],
+											[ editor.lang.common.notSet, '' ],
 											[ editor.lang.link.langDirLTR, 'ltr' ],
 											[ editor.lang.link.langDirRTL, 'rtl' ]
@@ -1313,5 +1334,7 @@
 			{
 				// We're only editing an existing link, so just overwrite the attributes.
-				var element = this._.selectedElement;
+				var element = this._.selectedElement,
+					href = element.getAttribute( '_cke_saved_href' ),
+					textView = element.getHtml();
 
 				// IE BUG: Setting the name attribute to an existing link doesn't work.
@@ -1334,5 +1357,7 @@
 				element.setAttributes( attributes );
 				element.removeAttributes( removeAttributes );
-
+				// Update text view when user changes protocol #4612.
+				if (href == textView)
+					element.setHtml( attributes._cke_saved_href );
 				// Make the element display as an anchor if a name has been set.
 				if ( element.getAttribute( 'name' ) )
@@ -1355,4 +1380,15 @@
 				this.hidePage( 'target' );		//Hide Target tab.
 
+		},
+		// Inital focus on 'url' field if link is of type URL.
+		onFocus : function()
+		{
+			var linkType = this.getContentElement( 'info', 'linkType' ),
+					urlField;
+			if ( linkType && linkType.getValue( ) == 'url' )
+			{
+				urlField = this.getContentElement( 'info', 'url' );
+				urlField.select();
+			}
 		}
 	};
@@ -1360,20 +1396,26 @@
 
 /**
- * The e-mail address anti-spam protection option.
+ * The e-mail address anti-spam protection option. The protection will be
+ * applied when creating or modifying e-mail links through the editor interface.<br>
+ * Two methods of protection can be choosed:
+ * <ol>	<li>The e-mail parts (name, domain and any other query string) are
+ *			assembled into a function call pattern. Such function must be
+ *			provided by the developer in the pages that will use the contents.
+ *		<li>Only the e-mail address is obfuscated into a special string that
+ *			has no meaning for humans or spam bots, but which is properly
+ *			rendered and accepted by the browser.</li></ol>
+ * Both approaches require JavaScript to be enabled.
  * @name CKEDITOR.config.emailProtection
- * @type {String}
- * Two forms of protection could be choosed from :
- * 1. The whole address parts ( name, domain with any other query string ) are assembled into a
- *   function call pattern which invoke you own provided function, with the specified arguments.
- * 2. Only the e-mail address is obfuscated into unicode code point sequences, replacement are
- *   done by a String.fromCharCode() call.
- * Note: Both approaches require JavaScript to be enabled.
- * @default ''
+ * @since 3.1
+ * @type String
+ * @default '' (empty string = disabled)
  * @example
- *  config.emailProtection = '';
- *  // href="mailto:tester@ckeditor.com?subject=subject&body=body"
- *  config.emailProtection = 'encode';
- *  // href="<a href=\"javascript:void(location.href=\'mailto:\'+String.fromCharCode(116,101,115,116,101,114,64,99,107,101,100,105,116,111,114,46,99,111,109)+\'?subject=subject&body=body\')\">e-mail</a>"
- *  config.emailProtection = 'mt(NAME,DOMAIN,SUBJECT,BODY)';
- *  // href="javascript:mt('tester','ckeditor.com','subject','body')"
+ * // href="mailto:tester@ckeditor.com?subject=subject&body=body"
+ * config.emailProtection = '';
+ * @example
+ * // href="<a href=\"javascript:void(location.href=\'mailto:\'+String.fromCharCode(116,101,115,116,101,114,64,99,107,101,100,105,116,111,114,46,99,111,109)+\'?subject=subject&body=body\')\">e-mail</a>"
+ * config.emailProtection = 'encode';
+ * @example
+ * // href="javascript:mt('tester','ckeditor.com','subject','body')"
+ * config.emailProtection = 'mt(NAME,DOMAIN,SUBJECT,BODY)';
  */
