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> <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 ); |