Make WordPress Core

source: trunk/src/js/_enqueues/lib/link.js @ 58450

Last change on this file since 58450 was 58450, checked in by joedolson, 5 weeks ago

Editor: A11y: Set ARIA attributes for Classic Editor link inserter.

Set aria-modal and aria-hidden attributes when the Classic Editor link inserter modal is active, so that content behind the modal will be properly treated as inert when interacting with the modal.

Props lyonmuller, jwgoedert, sabernhardt, alexstine, afercia, rajinsharwar, rcreators, audrasjb, hmbashar, joedolson.
Fixes #60799.

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