Make WordPress Core

Ticket #36359: 36359.patch

File 36359.patch, 23.9 KB (added by azaozz, 10 years ago)
  • src/wp-admin/includes/upgrade.php

     
    16821682        if ( $wp_current_db_version < 36679 && is_multisite() ) {
    16831683                $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name REGEXP '^[0-9]+_new_email$'" );
    16841684        }
    1685 
    1686         // Remove unused user setting for wpLink.
    1687         delete_user_setting( 'wplink' );
    16881685}
    16891686
    16901687/**
  • src/wp-includes/class-wp-editor.php

     
    14021402         * @static
    14031403         */
    14041404        public static function wp_link_dialog() {
     1405                $search_panel_visible = '1' == get_user_setting( 'wplink', '0' ) ? ' search-panel-visible' : '';
     1406
    14051407                // display: none is required here, see #WP27605
    14061408                ?>
    14071409                <div id="wp-link-backdrop" style="display: none"></div>
    1408                 <div id="wp-link-wrap" class="wp-core-ui" style="display: none" role="dialog" aria-labelledby="link-modal-title">
     1410                <div id="wp-link-wrap" class="wp-core-ui<?php echo $search_panel_visible; ?>" style="display: none" role="dialog" aria-labelledby="link-modal-title">
    14091411                <form id="wp-link" tabindex="-1">
    14101412                <?php wp_nonce_field( 'internal-linking', '_ajax_linking_nonce', false ); ?>
    14111413                <h1 id="link-modal-title"><?php _e( 'Insert/edit link' ) ?></h1>
     
    14121414                <button type="button" id="wp-link-close"><span class="screen-reader-text"><?php _e( 'Close' ); ?></span></button>
    14131415                <div id="link-selector">
    14141416                        <div id="link-options">
     1417                                <p class="howto"><?php _e( 'Enter the destination URL' ); ?></p>
    14151418                                <div>
    14161419                                        <label><span><?php _e( 'URL' ); ?></span>
    1417                                         <input id="wp-link-url" type="text" role="combobox" aria-autocomplete="list" aria-expanded="false" placeholder="<?php _e( 'Paste URL or type to search' ); ?>" /></label>
     1420                                        <input id="wp-link-url" type="text" /></label>
    14181421                                </div>
    14191422                                <div class="wp-link-text-field">
    14201423                                        <label><span><?php _e( 'Link Text' ); ?></span>
     
    14251428                                        <input type="checkbox" id="wp-link-target" /> <?php _e( 'Open link in a new tab' ); ?></label>
    14261429                                </div>
    14271430                        </div>
     1431                        <p class="howto"><a href="#" id="wp-link-search-toggle"><?php _e( 'Or link to existing content' ); ?></a></p>
     1432                        <div id="search-panel">
     1433                                <div class="link-search-wrapper">
     1434                                        <label>
     1435                                                <span class="search-label"><?php _e( 'Search' ); ?></span>
     1436                                                <input type="search" id="wp-link-search" class="link-search-field" autocomplete="off" />
     1437                                                <span class="spinner"></span>
     1438                                        </label>
     1439                                </div>
     1440                                <div id="search-results" class="query-results" tabindex="0">
     1441                                        <ul></ul>
     1442                                        <div class="river-waiting">
     1443                                                <span class="spinner"></span>
     1444                                        </div>
     1445                                </div>
     1446                                <div id="most-recent-results" class="query-results" tabindex="0">
     1447                                        <div class="query-notice" id="query-notice-message">
     1448                                                <em class="query-notice-default"><?php _e( 'No search term specified. Showing recent items.' ); ?></em>
     1449                                                <em class="query-notice-hint screen-reader-text"><?php _e( 'Search or use up and down arrow keys to select an item.' ); ?></em>
     1450                                        </div>
     1451                                        <ul></ul>
     1452                                        <div class="river-waiting">
     1453                                                <span class="spinner"></span>
     1454                                        </div>
     1455                                </div>
     1456                        </div>
    14281457                </div>
    14291458                <div class="submitbox">
    14301459                        <div id="wp-link-cancel">
  • src/wp-includes/css/editor.css

     
    9595}
    9696
    9797.mce-textbox,
    98 .mce-checkbox i.mce-i-checkbox {
     98.mce-checkbox i.mce-i-checkbox,
     99#wp-link .query-results {
    99100        border: 1px solid #ddd;
    100101        -webkit-border-radius: 0;
    101102        border-radius: 0;
     
    13741375        height: 100%;
    13751376}
    13761377
     1378#wp-link-wrap.search-panel-visible {
     1379        height: 500px;
     1380        margin-top: -250px;
     1381}
     1382
    13771383#wp-link-wrap .wp-link-text-field {
    13781384        display: none;
    13791385}
     
    14371443        padding: 0 16px 50px;
    14381444}
    14391445
     1446#wp-link-wrap.search-panel-visible #link-selector {
     1447        -webkit-overflow-scrolling: touch;
     1448        padding: 0 16px;
     1449        position: absolute;
     1450        top: 36px;
     1451        left: 0;
     1452        right: 0;
     1453        bottom: 44px;
     1454}
     1455
    14401456#wp-link ol,
    14411457#wp-link ul {
    14421458        list-style: none;
     
    14441460        padding: 0;
    14451461}
    14461462
     1463#wp-link-search-toggle:after {
     1464        display: inline-block;
     1465        font: normal 20px/1 dashicons;
     1466        vertical-align: top;
     1467        speak: none;
     1468        -webkit-font-smoothing: antialiased;
     1469        -moz-osx-font-smoothing: grayscale;
     1470        content: "\f140";
     1471}
     1472
     1473.search-panel-visible #wp-link-search-toggle:after {
     1474        content: "\f142";
     1475}
     1476
    14471477#wp-link input[type="text"] {
    14481478        -webkit-box-sizing: border-box;
    14491479        -moz-box-sizing: border-box;
     
    14631493        color: inherit;
    14641494}
    14651495
     1496#wp-link-search-toggle {
     1497        cursor: pointer;
     1498}
     1499
    14661500#wp-link label input[type="text"] {
    1467         margin: 8px 0 0;
     1501        margin-top: 5px;
    14681502        width: 70%;
    14691503}
    14701504
    1471 #wp-link #link-options label span {
     1505#wp-link #link-options label span,
     1506#wp-link #search-panel label span.search-label {
    14721507        display: inline-block;
    14731508        width: 80px;
    14741509        text-align: right;
     
    14781513        word-wrap: break-word;
    14791514}
    14801515
     1516#wp-link .link-search-field {
     1517        float: left;
     1518        width: 250px;
     1519        max-width: 70%;
     1520}
     1521
     1522#wp-link .link-search-wrapper {
     1523        margin: 5px 0 9px;
     1524        display: block;
     1525        overflow: hidden;
     1526}
     1527
     1528#wp-link .link-search-wrapper span {
     1529        float: left;
     1530        margin-top: 4px;
     1531}
     1532
     1533#wp-link .link-search-wrapper .spinner {
     1534        margin-top: 5px;
     1535}
     1536
    14811537#wp-link .link-target {
    14821538        padding: 3px 0 0;
    14831539        white-space: nowrap;
     
    14891545        max-width: 70%;
    14901546}
    14911547
     1548#wp-link .query-results {
     1549        border: 1px #dfdfdf solid;
     1550        margin: 0;
     1551        background: #fff;
     1552        overflow: auto;
     1553        position: absolute;
     1554        left: 16px;
     1555        right: 16px;
     1556        bottom: 16px;
     1557        top: 172px;
     1558}
     1559
     1560.has-text-field #wp-link .query-results {
     1561        top: 205px;
     1562}
     1563
     1564#wp-link li {
     1565        clear: both;
     1566        margin-bottom: 0;
     1567        border-bottom: 1px solid #f1f1f1;
     1568        color: #32373c;
     1569        padding: 4px 6px 4px 10px;
     1570        cursor: pointer;
     1571        position: relative;
     1572}
     1573
     1574#wp-link .query-notice {
     1575        padding: 0;
     1576        border-bottom: 1px solid #dfdfdf;
     1577        background-color: #f7fcfe;
     1578        color: #000;
     1579}
     1580
     1581#wp-link .query-notice .query-notice-default,
     1582#wp-link .query-notice .query-notice-hint {
     1583        display: block;
     1584        padding: 6px;
     1585        border-left: 4px solid #00a0d2;
     1586}
     1587
     1588#wp-link .unselectable.no-matches-found {
     1589        padding: 0;
     1590        border-bottom: 1px solid #dfdfdf;
     1591        background-color: #fef7f1;
     1592}
     1593
     1594#wp-link .no-matches-found .item-title {
     1595        display: block;
     1596        padding: 6px;
     1597        border-left: 4px solid #d54e21;
     1598}
     1599
     1600#wp-link .query-results em {
     1601        font-style: normal;
     1602}
     1603
     1604#wp-link li:hover {
     1605        background: #eaf2fa;
     1606        color: #151515;
     1607}
     1608
     1609#wp-link li.unselectable {
     1610        border-bottom: 1px solid #dfdfdf;
     1611}
     1612
     1613#wp-link li.unselectable:hover {
     1614        background: #fff;
     1615        cursor: auto;
     1616        color: #32373c;
     1617}
     1618
     1619#wp-link li.selected {
     1620        background: #ddd;
     1621        color: #32373c;
     1622}
     1623
     1624#wp-link li.selected .item-title {
     1625        font-weight: bold;
     1626}
     1627
     1628#wp-link li:last-child {
     1629        border: none;
     1630}
     1631
     1632#wp-link .item-title {
     1633        display: inline-block;
     1634        width: 80%;
     1635        width: -webkit-calc(100% - 68px);
     1636        width: calc(100% - 68px);
     1637        word-wrap: break-word;
     1638}
     1639
     1640#wp-link .item-info {
     1641        text-transform: uppercase;
     1642        color: #666;
     1643        font-size: 11px;
     1644        position: absolute;
     1645        right: 5px;
     1646        top: 5px;
     1647}
     1648
     1649#wp-link #search-results,
     1650#wp-link #search-panel {
     1651        display: none;
     1652}
     1653
     1654#wp-link-wrap.search-panel-visible #search-panel {
     1655        display: block;
     1656}
     1657
     1658#wp-link .river-waiting {
     1659        display: none;
     1660        padding: 10px 0;
     1661}
     1662
    14921663#wp-link .submitbox {
    14931664        padding: 8px 16px;
    14941665        background: #fcfcfc;
     
    15181689                margin-top: -140px;
    15191690        }
    15201691
     1692        #wp-link-wrap.search-panel-visible .query-results {
     1693                top: 195px;
     1694        }
     1695
     1696        #wp-link-wrap.search-panel-visible.has-text-field .query-results {
     1697                top: 235px;
     1698        }
     1699
    15211700        #link-selector {
    15221701                padding: 0 16px 60px;
    15231702        }
    15241703
     1704        #wp-link-wrap.search-panel-visible #link-selector {
     1705                bottom: 52px;
     1706        }
     1707
    15251708        #wp-link-cancel {
    15261709                line-height: 32px;
    15271710        }
     
    15501733                -webkit-transition: none;
    15511734                transition: none;
    15521735        }
     1736
     1737        #wp-link-wrap.search-panel-visible {
     1738                height: auto;
     1739                margin-top: 0;
     1740                top: 10px;
     1741                bottom: 10px;
     1742        }
     1743
     1744        .search-panel-visible #link-selector {
     1745                overflow: auto;
     1746        }
     1747
     1748        .search-panel-visible #search-panel .query-results {
     1749                position: static;
     1750        }
    15531751}
    15541752
    15551753@media screen and ( max-height: 290px ) {
     
    15661764                height: calc(100% - 92px);
    15671765                padding-bottom: 2px;
    15681766        }
     1767
     1768        #search-panel .query-results {
     1769                position: static;
     1770        }
    15691771}
    15701772
    15711773div.wp-link-preview {
  • src/wp-includes/js/wplink.js

     
    1 
     1/* global ajaxurl, tinymce, wpLinkL10n, setUserSetting, wpActiveEditor */
    22var wpLink;
    33
    44( function( $, wpLinkL10n, wp ) {
    5         var editor, correctedURL, linkNode,
     5        var editor, searchTimer, River, Query, correctedURL, linkNode,
    66                inputs = {},
     7                rivers = {},
    78                isTouch = ( 'ontouchend' in document );
    89
    910        function getLink() {
     
    1112        }
    1213
    1314        wpLink = {
     15                timeToTriggerRiver: 150,
     16                minRiverAJAXDuration: 200,
     17                riverBottomThreshold: 5,
     18                keySensitivity: 100,
     19                lastSearch: '',
    1420                textarea: '',
    1521
    1622                init: function() {
     
    2329                        // Input
    2430                        inputs.text = $( '#wp-link-text' );
    2531                        inputs.url = $( '#wp-link-url' );
     32                        inputs.nonce = $( '#_ajax_linking_nonce' );
    2633                        inputs.openInNewTab = $( '#wp-link-target' );
     34                        inputs.search = $( '#wp-link-search' );
    2735
    28                         if ( $.ui && $.ui.autocomplete ) {
    29                                 wpLink.setAutocomplete();
    30                         }
     36                        // Build Rivers
     37                        rivers.search = new River( $( '#search-results' ) );
     38                        rivers.recent = new River( $( '#most-recent-results' ) );
     39                        rivers.elements = inputs.dialog.find( '.query-results' );
    3140
    32                         inputs.dialog.on( 'keydown', wpLink.keydown );
    33                         inputs.submit.on( 'click', function( event ) {
     41                        // Get search notice text
     42                        inputs.queryNotice = $( '#query-notice-message' );
     43                        inputs.queryNoticeTextDefault = inputs.queryNotice.find( '.query-notice-default' );
     44                        inputs.queryNoticeTextHint = inputs.queryNotice.find( '.query-notice-hint' );
     45
     46                        // Bind event handlers
     47                        inputs.dialog.keydown( wpLink.keydown );
     48                        inputs.dialog.keyup( wpLink.keyup );
     49                        inputs.submit.click( function( event ) {
    3450                                event.preventDefault();
    3551                                wpLink.update();
    3652                        });
     
    4056                                wpLink.close();
    4157                        });
    4258
    43                         inputs.url.on( 'paste', function() {
    44                                 setTimeout( wpLink.correctURL, 0 );
    45                         } );
    46                 },
     59                        $( '#wp-link-search-toggle' ).on( 'click', wpLink.toggleInternalLinking );
    4760
    48                 setAutocomplete: function() {
    49                         var $input = inputs.url,
    50                                 cache, last;
     61                        rivers.elements.on( 'river-select', wpLink.updateFields );
    5162
    52                         $input.on( 'keydown', function() {
    53                                 $input.removeAttr( 'aria-activedescendant' );
    54                         } ).autocomplete( {
    55                                 source: function( request, response ) {
    56                                         if ( last === request.term ) {
    57                                                 response( cache );
    58                                                 return;
    59                                         }
     63                        // Display 'hint' message when search field or 'query-results' box are focused
     64                        inputs.search.on( 'focus.wplink', function() {
     65                                inputs.queryNoticeTextDefault.hide();
     66                                inputs.queryNoticeTextHint.removeClass( 'screen-reader-text' ).show();
     67                        } ).on( 'blur.wplink', function() {
     68                                inputs.queryNoticeTextDefault.show();
     69                                inputs.queryNoticeTextHint.addClass( 'screen-reader-text' ).hide();
     70                        } );
    6071
    61                                         if ( /^https?:/.test( request.term ) || request.term.indexOf( '.' ) !== -1 ) {
    62                                                 return response();
    63                                         }
     72                        inputs.search.on( 'keyup input', function() {
     73                                var self = this;
    6474
    65                                         $.post( window.ajaxurl, {
    66                                                 action: 'wp-link-ajax',
    67                                                 page: 1,
    68                                                 search: request.term,
    69                                                 _ajax_linking_nonce: $( '#_ajax_linking_nonce' ).val()
    70                                         }, function( data ) {
    71                                                 cache = data;
    72                                                 response( data );
    73                                         }, 'json' );
     75                                window.clearTimeout( searchTimer );
     76                                searchTimer = window.setTimeout( function() {
     77                                        wpLink.searchInternalLinks.call( self );
     78                                }, 500 );
     79                        });
    7480
    75                                         last = request.term;
    76                                 },
    77                                 focus: function( event, ui ) {
    78                                         $input.attr( 'aria-activedescendant', 'mce-wp-autocomplete-' + ui.item.ID );
    79                                         /*
    80                                          * Don't empty the URL input field, when using the arrow keys to
    81                                          * highlight items. See api.jqueryui.com/autocomplete/#event-focus
    82                                          */
    83                                         event.preventDefault();
    84                                 },
    85                                 select: function( event, ui ) {
    86                                         $input.val( ui.item.permalink );
     81                        inputs.url.on( 'paste', function() {
     82                                setTimeout( wpLink.correctURL, 0 );
     83                        } );
    8784
    88                                         if ( inputs.wrap.hasClass( 'has-text-field' ) && $.trim( inputs.text.val() ) === '' ) {
    89                                                 inputs.text.val( ui.item.title );
    90                                         }
    91 
    92                                         // Audible confirmation message when a link has been selected.
    93                                         wp.a11y.speak( wpLinkL10n.linkSelected );
    94 
    95                                         return false;
    96                                 },
    97                                 open: function() {
    98                                         $input.attr( 'aria-expanded', 'true' );
    99                                 },
    100                                 close: function() {
    101                                         $input.attr( 'aria-expanded', 'false' );
    102                                 },
    103                                 minLength: 2,
    104                                 position: {
    105                                         my: 'left top+2'
    106                                 },
    107                                 messages: {
    108                                         noResults: ( typeof window.uiAutocompleteL10n !== 'undefined' ) ? window.uiAutocompleteL10n.noResults : '',
    109                                         results: function( number ) {
    110                                                 if ( typeof window.uiAutocompleteL10n !== 'undefined' ) {
    111                                                         if ( number > 1 ) {
    112                                                                 return window.uiAutocompleteL10n.manyResults.replace( '%d', number );
    113                                                         }
    114 
    115                                                         return window.uiAutocompleteL10n.oneResult;
    116                                                 }
    117                                         }
    118                                 }
    119                         } ).autocomplete( 'instance' )._renderItem = function( ul, item ) {
    120                                 return $( '<li role="option" id="mce-wp-autocomplete-' + item.ID + '">' )
    121                                 .append( '<span class="item-title">' + item.title + '</span>&nbsp;<span class="item-date alignright">' + item.info + '</span>' )
    122                                 .appendTo( ul );
    123                         };
    124 
    125                         $input.attr( {
    126                                 'aria-owns': $input.autocomplete( 'widget' ).attr( 'id' )
    127                         } )
    128                         .on( 'focus', function() {
    129                                 var inputValue = $input.val();
    130                                 /*
    131                                  * Don't trigger a search if the URL field already has a link or is empty.
    132                                  * Also, avoids screen readers announce `No search results`.
    133                                  */
    134                                 if ( inputValue && ! /^https?:/.test( inputValue ) ) {
    135                                         $input.autocomplete( 'search' );
    136                                 }
    137                         } )
    138                         .autocomplete( 'widget' )
    139                                 .addClass( 'wplink-autocomplete' )
    140                                 .attr( 'role', 'listbox' )
    141                                 .removeAttr( 'tabindex' ); // Remove the `tabindex=0` attribute added by jQuery UI.
     85                        inputs.url.on( 'blur', wpLink.correctURL );
    14286                },
    14387
    14488                // If URL wasn't corrected last time and doesn't start with http:, https:, ? # or /, prepend http://
     
    208152                refresh: function( url, text ) {
    209153                        var linkText = '';
    210154
     155                        // Refresh rivers (clear links, check visibility)
     156                        rivers.search.refresh();
     157                        rivers.recent.refresh();
     158
    211159                        if ( wpLink.isMCE() ) {
    212160                                wpLink.mceRefresh( url, text );
    213161                        } else {
     
    241189                                } );
    242190                        }
    243191
     192                        // Load the most recent results if this is the first time opening the panel.
     193                        if ( ! rivers.recent.ul.children().length ) {
     194                                rivers.recent.ajax();
     195                        }
     196
    244197                        correctedURL = inputs.url.val().replace( /^http:\/\//, '' );
    245198                },
    246199
     
    471424                        wp.a11y.speak( wpLinkL10n.linkInserted );
    472425                },
    473426
    474                 keydown: function( event ) {
    475                         var id;
    476 
    477                         // Escape key.
    478                         if ( 27 === event.keyCode ) {
    479                                 wpLink.close();
    480                                 event.stopImmediatePropagation();
    481                         // Tab key.
    482                         } else if ( 9 === event.keyCode ) {
    483                                 id = event.target.id;
    484 
    485                                 // wp-link-submit must always be the last focusable element in the dialog.
    486                                 // following focusable elements will be skipped on keyboard navigation.
    487                                 if ( id === 'wp-link-submit' && ! event.shiftKey ) {
    488                                         inputs.close.focus();
    489                                         event.preventDefault();
    490                                 } else if ( id === 'wp-link-close' && event.shiftKey ) {
    491                                         inputs.submit.focus();
    492                                         event.preventDefault();
    493                                 }
    494                         }
     427                updateFields: function( e, li ) {
     428                        inputs.url.val( li.children( '.item-permalink' ).val() );
    495429                },
    496430
    497431                getUrlFromSelection: function( selection ) {
     
    526460
    527461                        // Update save prompt.
    528462                        inputs.submit.val( wpLinkL10n.save );
     463                },
     464
     465                searchInternalLinks: function() {
     466                        var t = $( this ), waiting,
     467                                search = t.val();
     468
     469                        if ( search.length > 2 ) {
     470                                rivers.recent.hide();
     471                                rivers.search.show();
     472
     473                                // Don't search if the keypress didn't change the title.
     474                                if ( wpLink.lastSearch == search )
     475                                        return;
     476
     477                                wpLink.lastSearch = search;
     478                                waiting = t.parent().find( '.spinner' ).addClass( 'is-active' );
     479
     480                                rivers.search.change( search );
     481                                rivers.search.ajax( function() {
     482                                        waiting.removeClass( 'is-active' );
     483                                });
     484                        } else {
     485                                rivers.search.hide();
     486                                rivers.recent.show();
     487                        }
     488                },
     489
     490                next: function() {
     491                        rivers.search.next();
     492                        rivers.recent.next();
     493                },
     494
     495                prev: function() {
     496                        rivers.search.prev();
     497                        rivers.recent.prev();
     498                },
     499
     500                keydown: function( event ) {
     501                        var fn, id;
     502
     503                        // Escape key.
     504                        if ( 27 === event.keyCode ) {
     505                                wpLink.close();
     506                                event.stopImmediatePropagation();
     507                        // Tab key.
     508                        } else if ( 9 === event.keyCode ) {
     509                                id = event.target.id;
     510
     511                                // wp-link-submit must always be the last focusable element in the dialog.
     512                                // following focusable elements will be skipped on keyboard navigation.
     513                                if ( id === 'wp-link-submit' && ! event.shiftKey ) {
     514                                        inputs.close.focus();
     515                                        event.preventDefault();
     516                                } else if ( id === 'wp-link-close' && event.shiftKey ) {
     517                                        inputs.submit.focus();
     518                                        event.preventDefault();
     519                                }
     520                        }
     521
     522                        // Up Arrow and Down Arrow keys.
     523                        if ( 38 !== event.keyCode && 40 !== event.keyCode ) {
     524                                return;
     525                        }
     526
     527                        if ( document.activeElement &&
     528                                ( document.activeElement.id === 'link-title-field' || document.activeElement.id === 'url-field' ) ) {
     529                                return;
     530                        }
     531
     532                        // Up Arrow key.
     533                        fn = 38 === event.keyCode ? 'prev' : 'next';
     534                        clearInterval( wpLink.keyInterval );
     535                        wpLink[ fn ]();
     536                        wpLink.keyInterval = setInterval( wpLink[ fn ], wpLink.keySensitivity );
     537                        event.preventDefault();
     538                },
     539
     540                keyup: function( event ) {
     541                        // Up Arrow and Down Arrow keys.
     542                        if ( 38 === event.keyCode || 40 === event.keyCode ) {
     543                                clearInterval( wpLink.keyInterval );
     544                                event.preventDefault();
     545                        }
     546                },
     547
     548                delayedCallback: function( func, delay ) {
     549                        var timeoutTriggered, funcTriggered, funcArgs, funcContext;
     550
     551                        if ( ! delay )
     552                                return func;
     553
     554                        setTimeout( function() {
     555                                if ( funcTriggered )
     556                                        return func.apply( funcContext, funcArgs );
     557                                // Otherwise, wait.
     558                                timeoutTriggered = true;
     559                        }, delay );
     560
     561                        return function() {
     562                                if ( timeoutTriggered )
     563                                        return func.apply( this, arguments );
     564                                // Otherwise, wait.
     565                                funcArgs = arguments;
     566                                funcContext = this;
     567                                funcTriggered = true;
     568                        };
     569                },
     570
     571                toggleInternalLinking: function( event ) {
     572                        var visible = inputs.wrap.hasClass( 'search-panel-visible' );
     573
     574                        inputs.wrap.toggleClass( 'search-panel-visible', ! visible );
     575                        setUserSetting( 'wplink', visible ? '0' : '1' );
     576                        inputs[ ! visible ? 'search' : 'url' ].focus();
     577                        event.preventDefault();
    529578                }
    530579        };
    531580
     581        River = function( element, search ) {
     582                var self = this;
     583                this.element = element;
     584                this.ul = element.children( 'ul' );
     585                this.contentHeight = element.children( '#link-selector-height' );
     586                this.waiting = element.find('.river-waiting');
     587
     588                this.change( search );
     589                this.refresh();
     590
     591                $( '#wp-link .query-results, #wp-link #link-selector' ).scroll( function() {
     592                        self.maybeLoad();
     593                });
     594                element.on( 'click', 'li', function( event ) {
     595                        self.select( $( this ), event );
     596                });
     597        };
     598
     599        $.extend( River.prototype, {
     600                refresh: function() {
     601                        this.deselect();
     602                        this.visible = this.element.is( ':visible' );
     603                },
     604                show: function() {
     605                        if ( ! this.visible ) {
     606                                this.deselect();
     607                                this.element.show();
     608                                this.visible = true;
     609                        }
     610                },
     611                hide: function() {
     612                        this.element.hide();
     613                        this.visible = false;
     614                },
     615                // Selects a list item and triggers the river-select event.
     616                select: function( li, event ) {
     617                        var liHeight, elHeight, liTop, elTop;
     618
     619                        if ( li.hasClass( 'unselectable' ) || li == this.selected )
     620                                return;
     621
     622                        this.deselect();
     623                        this.selected = li.addClass( 'selected' );
     624                        // Make sure the element is visible
     625                        liHeight = li.outerHeight();
     626                        elHeight = this.element.height();
     627                        liTop = li.position().top;
     628                        elTop = this.element.scrollTop();
     629
     630                        if ( liTop < 0 ) // Make first visible element
     631                                this.element.scrollTop( elTop + liTop );
     632                        else if ( liTop + liHeight > elHeight ) // Make last visible element
     633                                this.element.scrollTop( elTop + liTop - elHeight + liHeight );
     634
     635                        // Trigger the river-select event
     636                        this.element.trigger( 'river-select', [ li, event, this ] );
     637                },
     638                deselect: function() {
     639                        if ( this.selected )
     640                                this.selected.removeClass( 'selected' );
     641                        this.selected = false;
     642                },
     643                prev: function() {
     644                        if ( ! this.visible )
     645                                return;
     646
     647                        var to;
     648                        if ( this.selected ) {
     649                                to = this.selected.prev( 'li' );
     650                                if ( to.length )
     651                                        this.select( to );
     652                        }
     653                },
     654                next: function() {
     655                        if ( ! this.visible )
     656                                return;
     657
     658                        var to = this.selected ? this.selected.next( 'li' ) : $( 'li:not(.unselectable):first', this.element );
     659                        if ( to.length )
     660                                this.select( to );
     661                },
     662                ajax: function( callback ) {
     663                        var self = this,
     664                                delay = this.query.page == 1 ? 0 : wpLink.minRiverAJAXDuration,
     665                                response = wpLink.delayedCallback( function( results, params ) {
     666                                        self.process( results, params );
     667                                        if ( callback )
     668                                                callback( results, params );
     669                                }, delay );
     670
     671                        this.query.ajax( response );
     672                },
     673                change: function( search ) {
     674                        if ( this.query && this._search == search )
     675                                return;
     676
     677                        this._search = search;
     678                        this.query = new Query( search );
     679                        this.element.scrollTop( 0 );
     680                },
     681                process: function( results, params ) {
     682                        var list = '', alt = true, classes = '',
     683                                firstPage = params.page == 1;
     684
     685                        if ( ! results ) {
     686                                if ( firstPage ) {
     687                                        list += '<li class="unselectable no-matches-found"><span class="item-title"><em>' +
     688                                                wpLinkL10n.noMatchesFound + '</em></span></li>';
     689                                }
     690                        } else {
     691                                $.each( results, function() {
     692                                        classes = alt ? 'alternate' : '';
     693                                        classes += this.title ? '' : ' no-title';
     694                                        list += classes ? '<li class="' + classes + '">' : '<li>';
     695                                        list += '<input type="hidden" class="item-permalink" value="' + this.permalink + '" />';
     696                                        list += '<span class="item-title">';
     697                                        list += this.title ? this.title : wpLinkL10n.noTitle;
     698                                        list += '</span><span class="item-info">' + this.info + '</span></li>';
     699                                        alt = ! alt;
     700                                });
     701                        }
     702
     703                        this.ul[ firstPage ? 'html' : 'append' ]( list );
     704                },
     705                maybeLoad: function() {
     706                        var self = this,
     707                                el = this.element,
     708                                bottom = el.scrollTop() + el.height();
     709
     710                        if ( ! this.query.ready() || bottom < this.contentHeight.height() - wpLink.riverBottomThreshold )
     711                                return;
     712
     713                        setTimeout(function() {
     714                                var newTop = el.scrollTop(),
     715                                        newBottom = newTop + el.height();
     716
     717                                if ( ! self.query.ready() || newBottom < self.contentHeight.height() - wpLink.riverBottomThreshold )
     718                                        return;
     719
     720                                self.waiting.addClass( 'is-active' );
     721                                el.scrollTop( newTop + self.waiting.outerHeight() );
     722
     723                                self.ajax( function() {
     724                                        self.waiting.removeClass( 'is-active' );
     725                                });
     726                        }, wpLink.timeToTriggerRiver );
     727                }
     728        });
     729
     730        Query = function( search ) {
     731                this.page = 1;
     732                this.allLoaded = false;
     733                this.querying = false;
     734                this.search = search;
     735        };
     736
     737        $.extend( Query.prototype, {
     738                ready: function() {
     739                        return ! ( this.querying || this.allLoaded );
     740                },
     741                ajax: function( callback ) {
     742                        var self = this,
     743                                query = {
     744                                        action : 'wp-link-ajax',
     745                                        page : this.page,
     746                                        '_ajax_linking_nonce' : inputs.nonce.val()
     747                                };
     748
     749                        if ( this.search )
     750                                query.search = this.search;
     751
     752                        this.querying = true;
     753
     754                        $.post( ajaxurl, query, function( r ) {
     755                                self.page++;
     756                                self.querying = false;
     757                                self.allLoaded = ! r;
     758                                callback( r, query );
     759                        }, 'json' );
     760                }
     761        });
     762
    532763        $( document ).ready( wpLink.init );
    533764})( jQuery, window.wpLinkL10n, window.wp );