wp/wp-includes/js/tinymce/plugins/wplink/plugin.js
changeset 7 cf61fcea0001
parent 5 5e2f62d02dcd
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
     1 /* global tinymce */
     1 ( function( tinymce ) {
     2 tinymce.PluginManager.add( 'wplink', function( editor ) {
     2 	tinymce.ui.Factory.add( 'WPLinkPreview', tinymce.ui.Control.extend( {
     3 	editor.addCommand( 'WP_Link', function() {
     3 		url: '#',
     4 		window.wpLink && window.wpLink.open( editor.id );
     4 		renderHtml: function() {
     5 	});
     5 			return (
     6 
     6 				'<div id="' + this._id + '" class="wp-link-preview">' +
     7 	// WP default shortcut
     7 					'<a href="' + this.url + '" target="_blank" rel="noopener" tabindex="-1">' + this.url + '</a>' +
     8 	editor.addShortcut( 'Alt+Shift+A', '', 'WP_Link' );
     8 				'</div>'
     9 	// The "de-facto standard" shortcut, see #27305
     9 			);
    10 	editor.addShortcut( 'Meta+K', '', 'WP_Link' );
    10 		},
    11 
    11 		setURL: function( url ) {
    12 	editor.addButton( 'link', {
    12 			var index, lastIndex;
    13 		icon: 'link',
    13 
    14 		tooltip: 'Insert/edit link',
    14 			if ( this.url !== url ) {
    15 		cmd: 'WP_Link',
    15 				this.url = url;
    16 		stateSelector: 'a[href]'
    16 
    17 	});
    17 				url = window.decodeURIComponent( url );
    18 
    18 
    19 	editor.addButton( 'unlink', {
    19 				url = url.replace( /^(?:https?:)?\/\/(?:www\.)?/, '' );
    20 		icon: 'unlink',
    20 
    21 		tooltip: 'Remove link',
    21 				if ( ( index = url.indexOf( '?' ) ) !== -1 ) {
    22 		cmd: 'unlink'
    22 					url = url.slice( 0, index );
    23 	});
    23 				}
    24 
    24 
    25 	editor.addMenuItem( 'link', {
    25 				if ( ( index = url.indexOf( '#' ) ) !== -1 ) {
    26 		icon: 'link',
    26 					url = url.slice( 0, index );
    27 		text: 'Insert/edit link',
    27 				}
    28 		cmd: 'WP_Link',
    28 
    29 		stateSelector: 'a[href]',
    29 				url = url.replace( /(?:index)?\.html$/, '' );
    30 		context: 'insert',
    30 
    31 		prependToContext: true
    31 				if ( url.charAt( url.length - 1 ) === '/' ) {
    32 	});
    32 					url = url.slice( 0, -1 );
    33 
    33 				}
    34 	editor.on( 'pastepreprocess', function( event ) {
    34 
    35 		var pastedStr = event.content;
    35 				// If nothing's left (maybe the URL was just a fragment), use the whole URL.
    36 
    36 				if ( url === '' ) {
    37 		if ( ! editor.selection.isCollapsed() ) {
    37 					url = this.url;
    38 			pastedStr = pastedStr.replace( /<[^>]+>/g, '' );
    38 				}
    39 			pastedStr = tinymce.trim( pastedStr );
    39 
    40 
    40 				// If the URL is longer that 40 chars, concatenate the beginning (after the domain) and ending with ...
    41 			if ( /^(?:https?:)?\/\/\S+$/i.test( pastedStr ) ) {
    41 				if ( url.length > 40 && ( index = url.indexOf( '/' ) ) !== -1 && ( lastIndex = url.lastIndexOf( '/' ) ) !== -1 && lastIndex !== index ) {
    42 				editor.execCommand( 'mceInsertLink', false, {
    42 					// If the beginning + ending are shorter that 40 chars, show more of the ending
    43 					href: editor.dom.decode( pastedStr )
    43 					if ( index + url.length - lastIndex < 40 ) {
       
    44 						lastIndex = -( 40 - ( index + 1 ) );
       
    45 					}
       
    46 
       
    47 					url = url.slice( 0, index + 1 ) + '\u2026' + url.slice( lastIndex );
       
    48 				}
       
    49 
       
    50 				tinymce.$( this.getEl().firstChild ).attr( 'href', this.url ).text( url );
       
    51 			}
       
    52 		}
       
    53 	} ) );
       
    54 
       
    55 	tinymce.ui.Factory.add( 'WPLinkInput', tinymce.ui.Control.extend( {
       
    56 		renderHtml: function() {
       
    57 			return (
       
    58 				'<div id="' + this._id + '" class="wp-link-input">' +
       
    59 					'<input type="text" value="" placeholder="' + tinymce.translate( 'Paste URL or type to search' ) + '" />' +
       
    60 					'<input type="text" style="display:none" value="" />' +
       
    61 				'</div>'
       
    62 			);
       
    63 		},
       
    64 		setURL: function( url ) {
       
    65 			this.getEl().firstChild.value = url;
       
    66 		},
       
    67 		getURL: function() {
       
    68 			return tinymce.trim( this.getEl().firstChild.value );
       
    69 		},
       
    70 		getLinkText: function() {
       
    71 			var text = this.getEl().firstChild.nextSibling.value;
       
    72 
       
    73 			if ( ! tinymce.trim( text ) ) {
       
    74 				return '';
       
    75 			}
       
    76 
       
    77 			return text.replace( /[\r\n\t ]+/g, ' ' );
       
    78 		},
       
    79 		reset: function() {
       
    80 			var urlInput = this.getEl().firstChild;
       
    81 
       
    82 			urlInput.value = '';
       
    83 			urlInput.nextSibling.value = '';
       
    84 		}
       
    85 	} ) );
       
    86 
       
    87 	tinymce.PluginManager.add( 'wplink', function( editor ) {
       
    88 		var toolbar;
       
    89 		var editToolbar;
       
    90 		var previewInstance;
       
    91 		var inputInstance;
       
    92 		var linkNode;
       
    93 		var doingUndoRedo;
       
    94 		var doingUndoRedoTimer;
       
    95 		var $ = window.jQuery;
       
    96 		var emailRegex = /^(mailto:)?[a-z0-9._%+-]+@[a-z0-9][a-z0-9.-]*\.[a-z]{2,63}$/i;
       
    97 		var urlRegex1 = /^https?:\/\/([^\s/?.#-][^\s\/?.#]*\.?)+(\/[^\s"]*)?$/i;
       
    98 		var urlRegex2 = /^https?:\/\/[^\/]+\.[^\/]+($|\/)/i;
       
    99 		var speak = ( typeof window.wp !== 'undefined' && window.wp.a11y && window.wp.a11y.speak ) ? window.wp.a11y.speak : function() {};
       
   100 		var hasLinkError = false;
       
   101 
       
   102 		function getSelectedLink() {
       
   103 			var href, html,
       
   104 				node = editor.selection.getStart(),
       
   105 				link = editor.dom.getParent( node, 'a[href]' );
       
   106 
       
   107 			if ( ! link ) {
       
   108 				html = editor.selection.getContent({ format: 'raw' });
       
   109 
       
   110 				if ( html && html.indexOf( '</a>' ) !== -1 ) {
       
   111 					href = html.match( /href="([^">]+)"/ );
       
   112 
       
   113 					if ( href && href[1] ) {
       
   114 						link = editor.$( 'a[href="' + href[1] + '"]', node )[0];
       
   115 					}
       
   116 
       
   117 					if ( link ) {
       
   118 						editor.selection.select( link );
       
   119 					}
       
   120 				}
       
   121 			}
       
   122 
       
   123 			return link;
       
   124 		}
       
   125 
       
   126 		function removePlaceholders() {
       
   127 			editor.$( 'a' ).each( function( i, element ) {
       
   128 				var $element = editor.$( element );
       
   129 
       
   130 				if ( $element.attr( 'href' ) === '_wp_link_placeholder' ) {
       
   131 					editor.dom.remove( element, true );
       
   132 				} else if ( $element.attr( 'data-wplink-edit' ) ) {
       
   133 					$element.attr( 'data-wplink-edit', null );
       
   134 				}
       
   135 			});
       
   136 		}
       
   137 
       
   138 		function removePlaceholderStrings( content, dataAttr ) {
       
   139 			return content.replace( /(<a [^>]+>)([\s\S]*?)<\/a>/g, function( all, tag, text ) {
       
   140 				if ( tag.indexOf( ' href="_wp_link_placeholder"' ) > -1 ) {
       
   141 					return text;
       
   142 				}
       
   143 
       
   144 				if ( dataAttr ) {
       
   145 					tag = tag.replace( / data-wplink-edit="true"/g, '' );
       
   146 				}
       
   147 
       
   148 				tag = tag.replace( / data-wplink-url-error="true"/g, '' );
       
   149 
       
   150 				return tag + text + '</a>';
       
   151 			});
       
   152 		}
       
   153 
       
   154 		function checkLink( node ) {
       
   155 			var $link = editor.$( node );
       
   156 			var href = $link.attr( 'href' );
       
   157 
       
   158 			if ( ! href || typeof $ === 'undefined' ) {
       
   159 				return;
       
   160 			}
       
   161 
       
   162 			hasLinkError = false;
       
   163 
       
   164 			if ( /^http/i.test( href ) && ( ! urlRegex1.test( href ) || ! urlRegex2.test( href ) ) ) {
       
   165 				hasLinkError = true;
       
   166 				$link.attr( 'data-wplink-url-error', 'true' );
       
   167 				speak( editor.translate( 'Warning: the link has been inserted but may have errors. Please test it.' ), 'assertive' );
       
   168 			} else {
       
   169 				$link.removeAttr( 'data-wplink-url-error' );
       
   170 			}
       
   171 		}
       
   172 
       
   173 		editor.on( 'preinit', function() {
       
   174 			if ( editor.wp && editor.wp._createToolbar ) {
       
   175 				toolbar = editor.wp._createToolbar( [
       
   176 					'wp_link_preview',
       
   177 					'wp_link_edit',
       
   178 					'wp_link_remove'
       
   179 				], true );
       
   180 
       
   181 				var editButtons = [
       
   182 					'wp_link_input',
       
   183 					'wp_link_apply'
       
   184 				];
       
   185 
       
   186 				if ( typeof window.wpLink !== 'undefined' ) {
       
   187 					editButtons.push( 'wp_link_advanced' );
       
   188 				}
       
   189 
       
   190 				editToolbar = editor.wp._createToolbar( editButtons, true );
       
   191 
       
   192 				editToolbar.on( 'show', function() {
       
   193 					if ( typeof window.wpLink === 'undefined' || ! window.wpLink.modalOpen ) {
       
   194 						window.setTimeout( function() {
       
   195 							var element = editToolbar.$el.find( 'input.ui-autocomplete-input' )[0],
       
   196 								selection = linkNode && ( linkNode.textContent || linkNode.innerText );
       
   197 
       
   198 							if ( element ) {
       
   199 								if ( ! element.value && selection && typeof window.wpLink !== 'undefined' ) {
       
   200 									element.value = window.wpLink.getUrlFromSelection( selection );
       
   201 								}
       
   202 
       
   203 								if ( ! doingUndoRedo ) {
       
   204 									element.focus();
       
   205 									element.select();
       
   206 								}
       
   207 							}
       
   208 						} );
       
   209 					}
    44 				} );
   210 				} );
    45 
   211 
       
   212 				editToolbar.on( 'hide', function() {
       
   213 					if ( ! editToolbar.scrolling ) {
       
   214 						editor.execCommand( 'wp_link_cancel' );
       
   215 					}
       
   216 				} );
       
   217 			}
       
   218 		} );
       
   219 
       
   220 		editor.addCommand( 'WP_Link', function() {
       
   221 			if ( tinymce.Env.ie && tinymce.Env.ie < 10 && typeof window.wpLink !== 'undefined' ) {
       
   222 				window.wpLink.open( editor.id );
       
   223 				return;
       
   224 			}
       
   225 
       
   226 			linkNode = getSelectedLink();
       
   227 			editToolbar.tempHide = false;
       
   228 
       
   229 			if ( linkNode ) {
       
   230 				editor.dom.setAttribs( linkNode, { 'data-wplink-edit': true } );
       
   231 			} else {
       
   232 				removePlaceholders();
       
   233 				editor.execCommand( 'mceInsertLink', false, { href: '_wp_link_placeholder' } );
       
   234 
       
   235 				linkNode = editor.$( 'a[href="_wp_link_placeholder"]' )[0];
       
   236 				editor.nodeChanged();
       
   237 			}
       
   238 		} );
       
   239 
       
   240 		editor.addCommand( 'wp_link_apply', function() {
       
   241 			if ( editToolbar.scrolling ) {
       
   242 				return;
       
   243 			}
       
   244 
       
   245 			var href, text;
       
   246 
       
   247 			if ( linkNode ) {
       
   248 				href = inputInstance.getURL();
       
   249 				text = inputInstance.getLinkText();
       
   250 				editor.focus();
       
   251 
       
   252 				var parser = document.createElement( 'a' );
       
   253 				parser.href = href;
       
   254 
       
   255 				if ( 'javascript:' === parser.protocol || 'data:' === parser.protocol ) { // jshint ignore:line
       
   256 					href = '';
       
   257 				}
       
   258 
       
   259 				if ( ! href ) {
       
   260 					editor.dom.remove( linkNode, true );
       
   261 					return;
       
   262 				}
       
   263 
       
   264 				if ( ! /^(?:[a-z]+:|#|\?|\.|\/)/.test( href ) && ! emailRegex.test( href ) ) {
       
   265 					href = 'http://' + href;
       
   266 				}
       
   267 
       
   268 				editor.dom.setAttribs( linkNode, { href: href, 'data-wplink-edit': null } );
       
   269 
       
   270 				if ( ! tinymce.trim( linkNode.innerHTML ) ) {
       
   271 					editor.$( linkNode ).text( text || href );
       
   272 				}
       
   273 
       
   274 				checkLink( linkNode );
       
   275 			}
       
   276 
       
   277 			inputInstance.reset();
       
   278 			editor.nodeChanged();
       
   279 
       
   280 			// Audible confirmation message when a link has been inserted in the Editor.
       
   281 			if ( typeof window.wpLinkL10n !== 'undefined' && ! hasLinkError ) {
       
   282 				speak( window.wpLinkL10n.linkInserted );
       
   283 			}
       
   284 		} );
       
   285 
       
   286 		editor.addCommand( 'wp_link_cancel', function() {
       
   287 			if ( ! editToolbar.tempHide ) {
       
   288 				inputInstance.reset();
       
   289 				removePlaceholders();
       
   290 			}
       
   291 		} );
       
   292 
       
   293 		editor.addCommand( 'wp_unlink', function() {
       
   294 			editor.execCommand( 'unlink' );
       
   295 			editToolbar.tempHide = false;
       
   296 			editor.execCommand( 'wp_link_cancel' );
       
   297 		} );
       
   298 
       
   299 		// WP default shortcuts
       
   300 		editor.addShortcut( 'access+a', '', 'WP_Link' );
       
   301 		editor.addShortcut( 'access+s', '', 'wp_unlink' );
       
   302 		// The "de-facto standard" shortcut, see #27305
       
   303 		editor.addShortcut( 'meta+k', '', 'WP_Link' );
       
   304 
       
   305 		editor.addButton( 'link', {
       
   306 			icon: 'link',
       
   307 			tooltip: 'Insert/edit link',
       
   308 			cmd: 'WP_Link',
       
   309 			stateSelector: 'a[href]'
       
   310 		});
       
   311 
       
   312 		editor.addButton( 'unlink', {
       
   313 			icon: 'unlink',
       
   314 			tooltip: 'Remove link',
       
   315 			cmd: 'unlink'
       
   316 		});
       
   317 
       
   318 		editor.addMenuItem( 'link', {
       
   319 			icon: 'link',
       
   320 			text: 'Insert/edit link',
       
   321 			cmd: 'WP_Link',
       
   322 			stateSelector: 'a[href]',
       
   323 			context: 'insert',
       
   324 			prependToContext: true
       
   325 		});
       
   326 
       
   327 		editor.on( 'pastepreprocess', function( event ) {
       
   328 			var pastedStr = event.content,
       
   329 				regExp = /^(?:https?:)?\/\/\S+$/i;
       
   330 
       
   331 			if ( ! editor.selection.isCollapsed() && ! regExp.test( editor.selection.getContent() ) ) {
       
   332 				pastedStr = pastedStr.replace( /<[^>]+>/g, '' );
       
   333 				pastedStr = tinymce.trim( pastedStr );
       
   334 
       
   335 				if ( regExp.test( pastedStr ) ) {
       
   336 					editor.execCommand( 'mceInsertLink', false, {
       
   337 						href: editor.dom.decode( pastedStr )
       
   338 					} );
       
   339 
       
   340 					event.preventDefault();
       
   341 				}
       
   342 			}
       
   343 		} );
       
   344 
       
   345 		// Remove any remaining placeholders on saving.
       
   346 		editor.on( 'savecontent', function( event ) {
       
   347 			event.content = removePlaceholderStrings( event.content, true );
       
   348 		});
       
   349 
       
   350 		// Prevent adding undo levels on inserting link placeholder.
       
   351 		editor.on( 'BeforeAddUndo', function( event ) {
       
   352 			if ( event.lastLevel && event.lastLevel.content && event.level.content &&
       
   353 				event.lastLevel.content === removePlaceholderStrings( event.level.content ) ) {
       
   354 
    46 				event.preventDefault();
   355 				event.preventDefault();
    47 			}
   356 			}
    48 		}
   357 		});
       
   358 
       
   359 		// When doing undo and redo with keyboard shortcuts (Ctrl|Cmd+Z, Ctrl|Cmd+Shift+Z, Ctrl|Cmd+Y),
       
   360 		// set a flag to not focus the inline dialog. The editor has to remain focused so the users can do consecutive undo/redo.
       
   361 		editor.on( 'keydown', function( event ) {
       
   362 			if ( event.keyCode === 27 ) { // Esc
       
   363 				editor.execCommand( 'wp_link_cancel' );
       
   364 			}
       
   365 
       
   366 			if ( event.altKey || ( tinymce.Env.mac && ( ! event.metaKey || event.ctrlKey ) ) ||
       
   367 				( ! tinymce.Env.mac && ! event.ctrlKey ) ) {
       
   368 
       
   369 				return;
       
   370 			}
       
   371 
       
   372 			if ( event.keyCode === 89 || event.keyCode === 90 ) { // Y or Z
       
   373 				doingUndoRedo = true;
       
   374 
       
   375 				window.clearTimeout( doingUndoRedoTimer );
       
   376 				doingUndoRedoTimer = window.setTimeout( function() {
       
   377 					doingUndoRedo = false;
       
   378 				}, 500 );
       
   379 			}
       
   380 		} );
       
   381 
       
   382 		editor.addButton( 'wp_link_preview', {
       
   383 			type: 'WPLinkPreview',
       
   384 			onPostRender: function() {
       
   385 				previewInstance = this;
       
   386 			}
       
   387 		} );
       
   388 
       
   389 		editor.addButton( 'wp_link_input', {
       
   390 			type: 'WPLinkInput',
       
   391 			onPostRender: function() {
       
   392 				var element = this.getEl(),
       
   393 					input = element.firstChild,
       
   394 					$input, cache, last;
       
   395 
       
   396 				inputInstance = this;
       
   397 
       
   398 				if ( $ && $.ui && $.ui.autocomplete ) {
       
   399 					$input = $( input );
       
   400 
       
   401 					$input.on( 'keydown', function() {
       
   402 						$input.removeAttr( 'aria-activedescendant' );
       
   403 					} )
       
   404 					.autocomplete( {
       
   405 						source: function( request, response ) {
       
   406 							if ( last === request.term ) {
       
   407 								response( cache );
       
   408 								return;
       
   409 							}
       
   410 
       
   411 							if ( /^https?:/.test( request.term ) || request.term.indexOf( '.' ) !== -1 ) {
       
   412 								return response();
       
   413 							}
       
   414 
       
   415 							$.post( window.ajaxurl, {
       
   416 								action: 'wp-link-ajax',
       
   417 								page: 1,
       
   418 								search: request.term,
       
   419 								_ajax_linking_nonce: $( '#_ajax_linking_nonce' ).val()
       
   420 							}, function( data ) {
       
   421 								cache = data;
       
   422 								response( data );
       
   423 							}, 'json' );
       
   424 
       
   425 							last = request.term;
       
   426 						},
       
   427 						focus: function( event, ui ) {
       
   428 							$input.attr( 'aria-activedescendant', 'mce-wp-autocomplete-' + ui.item.ID );
       
   429 							/*
       
   430 							 * Don't empty the URL input field, when using the arrow keys to
       
   431 							 * highlight items. See api.jqueryui.com/autocomplete/#event-focus
       
   432 							 */
       
   433 							event.preventDefault();
       
   434 						},
       
   435 						select: function( event, ui ) {
       
   436 							$input.val( ui.item.permalink );
       
   437 							$( element.firstChild.nextSibling ).val( ui.item.title );
       
   438 
       
   439 							if ( 9 === event.keyCode && typeof window.wpLinkL10n !== 'undefined' ) {
       
   440 								// Audible confirmation message when a link has been selected.
       
   441 								speak( window.wpLinkL10n.linkSelected );
       
   442 							}
       
   443 
       
   444 							return false;
       
   445 						},
       
   446 						open: function() {
       
   447 							$input.attr( 'aria-expanded', 'true' );
       
   448 							editToolbar.blockHide = true;
       
   449 						},
       
   450 						close: function() {
       
   451 							$input.attr( 'aria-expanded', 'false' );
       
   452 							editToolbar.blockHide = false;
       
   453 						},
       
   454 						minLength: 2,
       
   455 						position: {
       
   456 							my: 'left top+2'
       
   457 						},
       
   458 						messages: {
       
   459 							noResults: ( typeof window.uiAutocompleteL10n !== 'undefined' ) ? window.uiAutocompleteL10n.noResults : '',
       
   460 							results: function( number ) {
       
   461 								if ( typeof window.uiAutocompleteL10n !== 'undefined' ) {
       
   462 									if ( number > 1 ) {
       
   463 										return window.uiAutocompleteL10n.manyResults.replace( '%d', number );
       
   464 									}
       
   465 
       
   466 									return window.uiAutocompleteL10n.oneResult;
       
   467 								}
       
   468 							}
       
   469 						}
       
   470 					} ).autocomplete( 'instance' )._renderItem = function( ul, item ) {
       
   471 						var fallbackTitle = ( typeof window.wpLinkL10n !== 'undefined' ) ? window.wpLinkL10n.noTitle : '',
       
   472 							title = item.title ? item.title : fallbackTitle;
       
   473 
       
   474 						return $( '<li role="option" id="mce-wp-autocomplete-' + item.ID + '">' )
       
   475 						.append( '<span>' + title + '</span>&nbsp;<span class="wp-editor-float-right">' + item.info + '</span>' )
       
   476 						.appendTo( ul );
       
   477 					};
       
   478 
       
   479 					$input.attr( {
       
   480 						'role': 'combobox',
       
   481 						'aria-autocomplete': 'list',
       
   482 						'aria-expanded': 'false',
       
   483 						'aria-owns': $input.autocomplete( 'widget' ).attr( 'id' )
       
   484 					} )
       
   485 					.on( 'focus', function() {
       
   486 						var inputValue = $input.val();
       
   487 						/*
       
   488 						 * Don't trigger a search if the URL field already has a link or is empty.
       
   489 						 * Also, avoids screen readers announce `No search results`.
       
   490 						 */
       
   491 						if ( inputValue && ! /^https?:/.test( inputValue ) ) {
       
   492 							$input.autocomplete( 'search' );
       
   493 						}
       
   494 					} )
       
   495 					// Returns a jQuery object containing the menu element.
       
   496 					.autocomplete( 'widget' )
       
   497 						.addClass( 'wplink-autocomplete' )
       
   498 						.attr( 'role', 'listbox' )
       
   499 						.removeAttr( 'tabindex' ) // Remove the `tabindex=0` attribute added by jQuery UI.
       
   500 						/*
       
   501 						 * Looks like Safari and VoiceOver need an `aria-selected` attribute. See ticket #33301.
       
   502 						 * The `menufocus` and `menublur` events are the same events used to add and remove
       
   503 						 * the `ui-state-focus` CSS class on the menu items. See jQuery UI Menu Widget.
       
   504 						 */
       
   505 						.on( 'menufocus', function( event, ui ) {
       
   506 							ui.item.attr( 'aria-selected', 'true' );
       
   507 						})
       
   508 						.on( 'menublur', function() {
       
   509 							/*
       
   510 							 * The `menublur` event returns an object where the item is `null`
       
   511 							 * so we need to find the active item with other means.
       
   512 							 */
       
   513 							$( this ).find( '[aria-selected="true"]' ).removeAttr( 'aria-selected' );
       
   514 						});
       
   515 				}
       
   516 
       
   517 				tinymce.$( input ).on( 'keydown', function( event ) {
       
   518 					if ( event.keyCode === 13 ) {
       
   519 						editor.execCommand( 'wp_link_apply' );
       
   520 						event.preventDefault();
       
   521 					}
       
   522 				} );
       
   523 			}
       
   524 		} );
       
   525 
       
   526 		editor.on( 'wptoolbar', function( event ) {
       
   527 			var linkNode = editor.dom.getParent( event.element, 'a' ),
       
   528 				$linkNode, href, edit;
       
   529 
       
   530 			if ( typeof window.wpLink !== 'undefined' && window.wpLink.modalOpen ) {
       
   531 				editToolbar.tempHide = true;
       
   532 				return;
       
   533 			}
       
   534 
       
   535 			editToolbar.tempHide = false;
       
   536 
       
   537 			if ( linkNode ) {
       
   538 				$linkNode = editor.$( linkNode );
       
   539 				href = $linkNode.attr( 'href' );
       
   540 				edit = $linkNode.attr( 'data-wplink-edit' );
       
   541 
       
   542 				if ( href === '_wp_link_placeholder' || edit ) {
       
   543 					if ( href !== '_wp_link_placeholder' && ! inputInstance.getURL() ) {
       
   544 						inputInstance.setURL( href );
       
   545 					}
       
   546 
       
   547 					event.element = linkNode;
       
   548 					event.toolbar = editToolbar;
       
   549 				} else if ( href && ! $linkNode.find( 'img' ).length ) {
       
   550 					previewInstance.setURL( href );
       
   551 					event.element = linkNode;
       
   552 					event.toolbar = toolbar;
       
   553 
       
   554 					if ( $linkNode.attr( 'data-wplink-url-error' ) === 'true' ) {
       
   555 						toolbar.$el.find( '.wp-link-preview a' ).addClass( 'wplink-url-error' );
       
   556 					} else {
       
   557 						toolbar.$el.find( '.wp-link-preview a' ).removeClass( 'wplink-url-error' );
       
   558 						hasLinkError = false;
       
   559 					}
       
   560 				}
       
   561 			} else if ( editToolbar.visible() ) {
       
   562 				editor.execCommand( 'wp_link_cancel' );
       
   563 			}
       
   564 		} );
       
   565 
       
   566 		editor.addButton( 'wp_link_edit', {
       
   567 			tooltip: 'Edit|button', // '|button' is not displayed, only used for context
       
   568 			icon: 'dashicon dashicons-edit',
       
   569 			cmd: 'WP_Link'
       
   570 		} );
       
   571 
       
   572 		editor.addButton( 'wp_link_remove', {
       
   573 			tooltip: 'Remove link',
       
   574 			icon: 'dashicon dashicons-editor-unlink',
       
   575 			cmd: 'wp_unlink'
       
   576 		} );
       
   577 
       
   578 		editor.addButton( 'wp_link_advanced', {
       
   579 			tooltip: 'Link options',
       
   580 			icon: 'dashicon dashicons-admin-generic',
       
   581 			onclick: function() {
       
   582 				if ( typeof window.wpLink !== 'undefined' ) {
       
   583 					var url = inputInstance.getURL() || null,
       
   584 						text = inputInstance.getLinkText() || null;
       
   585 
       
   586 					/*
       
   587 					 * Accessibility note: moving focus back to the editor confuses
       
   588 					 * screen readers. They will announce again the Editor ARIA role
       
   589 					 * `application` and the iframe `title` attribute.
       
   590 					 *
       
   591 					 * Unfortunately IE looses the selection when the editor iframe
       
   592 					 * looses focus, so without returning focus to the editor, the code
       
   593 					 * in the modal will not be able to get the selection, place the caret
       
   594 					 * at the same location, etc.
       
   595 					 */
       
   596 					if ( tinymce.Env.ie ) {
       
   597 						editor.focus(); // Needed for IE
       
   598 					}
       
   599 
       
   600 					editToolbar.tempHide = true;
       
   601 					window.wpLink.open( editor.id, url, text, linkNode );
       
   602 
       
   603 					inputInstance.reset();
       
   604 				}
       
   605 			}
       
   606 		} );
       
   607 
       
   608 		editor.addButton( 'wp_link_apply', {
       
   609 			tooltip: 'Apply',
       
   610 			icon: 'dashicon dashicons-editor-break',
       
   611 			cmd: 'wp_link_apply',
       
   612 			classes: 'widget btn primary'
       
   613 		} );
       
   614 
       
   615 		return {
       
   616 			close: function() {
       
   617 				editToolbar.tempHide = false;
       
   618 				editor.execCommand( 'wp_link_cancel' );
       
   619 			},
       
   620 			checkLink: checkLink
       
   621 		};
    49 	} );
   622 	} );
    50 });
   623 } )( window.tinymce );