Make WordPress Core

Changeset 37154


Ignore:
Timestamp:
04/01/2016 09:12:18 PM (9 years ago)
Author:
azaozz
Message:

Editor, wpLink:

  • Restore the bottom half of the modal.
  • Make it always expanded and remove the toggle. It is used as advanced link options now, no need to have simple mode.

Props iseulde, adamsilverstein, azaozz.
Fixes #36359.

Location:
trunk/src/wp-includes
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-editor.php

    r37091 r37154  
    14131413        <div id="link-selector">
    14141414            <div id="link-options">
     1415                <p class="howto"><?php _e( 'Enter the destination URL' ); ?></p>
    14151416                <div>
    14161417                    <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>
     1418                    <input id="wp-link-url" type="text" /></label>
    14181419                </div>
    14191420                <div class="wp-link-text-field">
     
    14261427                </div>
    14271428            </div>
     1429            <p class="howto"><?php _e( 'Or link to existing content' ); ?></p>
     1430            <div id="search-panel">
     1431                <div class="link-search-wrapper">
     1432                    <label>
     1433                        <span class="search-label"><?php _e( 'Search' ); ?></span>
     1434                        <input type="search" id="wp-link-search" class="link-search-field" autocomplete="off" />
     1435                        <span class="spinner"></span>
     1436                    </label>
     1437                </div>
     1438                <div id="search-results" class="query-results" tabindex="0">
     1439                    <ul></ul>
     1440                    <div class="river-waiting">
     1441                        <span class="spinner"></span>
     1442                    </div>
     1443                </div>
     1444                <div id="most-recent-results" class="query-results" tabindex="0">
     1445                    <div class="query-notice" id="query-notice-message">
     1446                        <em class="query-notice-default"><?php _e( 'No search term specified. Showing recent items.' ); ?></em>
     1447                        <em class="query-notice-hint screen-reader-text"><?php _e( 'Search or use up and down arrow keys to select an item.' ); ?></em>
     1448                    </div>
     1449                    <ul></ul>
     1450                    <div class="river-waiting">
     1451                        <span class="spinner"></span>
     1452                    </div>
     1453                </div>
     1454            </div>
    14281455        </div>
    14291456        <div class="submitbox">
  • trunk/src/wp-includes/css/editor.css

    r37076 r37154  
    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;
     
    13751376}
    13761377
     1378#wp-link-wrap {
     1379    height: 500px;
     1380    margin-top: -250px;
     1381}
     1382
    13771383#wp-link-wrap .wp-link-text-field {
    13781384    display: none;
     
    14341440}
    14351441
    1436 #link-selector {
    1437     padding: 0 16px 50px;
     1442#wp-link-wrap #link-selector {
     1443    -webkit-overflow-scrolling: touch;
     1444    padding: 0 16px;
     1445    position: absolute;
     1446    top: 37px;
     1447    left: 0;
     1448    right: 0;
     1449    bottom: 44px;
    14381450}
    14391451
     
    14651477
    14661478#wp-link label input[type="text"] {
    1467     margin: 8px 0 0;
     1479    margin-top: 5px;
    14681480    width: 70%;
    14691481}
    14701482
    1471 #wp-link #link-options label span {
     1483#wp-link #link-options label span,
     1484#wp-link #search-panel label span.search-label {
    14721485    display: inline-block;
    14731486    width: 80px;
     
    14791492}
    14801493
     1494#wp-link .link-search-field {
     1495    float: left;
     1496    width: 250px;
     1497    max-width: 70%;
     1498}
     1499
     1500#wp-link .link-search-wrapper {
     1501    margin: 5px 0 9px;
     1502    display: block;
     1503    overflow: hidden;
     1504}
     1505
     1506#wp-link .link-search-wrapper span {
     1507    float: left;
     1508    margin-top: 4px;
     1509}
     1510
     1511#wp-link .link-search-wrapper .spinner {
     1512    margin-top: 5px;
     1513}
     1514
    14811515#wp-link .link-target {
    14821516    padding: 3px 0 0;
     
    14881522#wp-link .link-target label {
    14891523    max-width: 70%;
     1524}
     1525
     1526#wp-link .query-results {
     1527    border: 1px #dfdfdf solid;
     1528    margin: 0 0 12px;
     1529    background: #fff;
     1530    overflow: auto;
     1531    position: absolute;
     1532    left: 16px;
     1533    right: 16px;
     1534    bottom: 0;
     1535    top: 166px;
     1536}
     1537
     1538.has-text-field #wp-link .query-results {
     1539    top: 200px;
     1540}
     1541
     1542#wp-link li {
     1543    clear: both;
     1544    margin-bottom: 0;
     1545    border-bottom: 1px solid #f1f1f1;
     1546    color: #32373c;
     1547    padding: 4px 6px 4px 10px;
     1548    cursor: pointer;
     1549    position: relative;
     1550}
     1551
     1552#wp-link .query-notice {
     1553    padding: 0;
     1554    border-bottom: 1px solid #dfdfdf;
     1555    background-color: #f7fcfe;
     1556    color: #000;
     1557}
     1558
     1559#wp-link .query-notice .query-notice-default,
     1560#wp-link .query-notice .query-notice-hint {
     1561    display: block;
     1562    padding: 6px;
     1563    border-left: 4px solid #00a0d2;
     1564}
     1565
     1566#wp-link .unselectable.no-matches-found {
     1567    padding: 0;
     1568    border-bottom: 1px solid #dfdfdf;
     1569    background-color: #fef7f1;
     1570}
     1571
     1572#wp-link .no-matches-found .item-title {
     1573    display: block;
     1574    padding: 6px;
     1575    border-left: 4px solid #d54e21;
     1576}
     1577
     1578#wp-link .query-results em {
     1579    font-style: normal;
     1580}
     1581
     1582#wp-link li:hover {
     1583    background: #eaf2fa;
     1584    color: #151515;
     1585}
     1586
     1587#wp-link li.unselectable {
     1588    border-bottom: 1px solid #dfdfdf;
     1589}
     1590
     1591#wp-link li.unselectable:hover {
     1592    background: #fff;
     1593    cursor: auto;
     1594    color: #32373c;
     1595}
     1596
     1597#wp-link li.selected {
     1598    background: #ddd;
     1599    color: #32373c;
     1600}
     1601
     1602#wp-link li.selected .item-title {
     1603    font-weight: bold;
     1604}
     1605
     1606#wp-link li:last-child {
     1607    border: none;
     1608}
     1609
     1610#wp-link .item-title {
     1611    display: inline-block;
     1612    width: 80%;
     1613    width: -webkit-calc(100% - 68px);
     1614    width: calc(100% - 68px);
     1615    word-wrap: break-word;
     1616}
     1617
     1618#wp-link .item-info {
     1619    text-transform: uppercase;
     1620    color: #666;
     1621    font-size: 11px;
     1622    position: absolute;
     1623    right: 5px;
     1624    top: 5px;
     1625}
     1626
     1627#wp-link .river-waiting {
     1628    display: none;
     1629    padding: 10px 0;
    14901630}
    14911631
     
    15191659    }
    15201660
     1661    #wp-link-wrap .query-results {
     1662        top: 195px;
     1663    }
     1664
     1665    #wp-link-wrap.has-text-field .query-results {
     1666        top: 235px;
     1667    }
     1668
    15211669    #link-selector {
    15221670        padding: 0 16px 60px;
     1671    }
     1672
     1673    #wp-link-wrap #link-selector {
     1674        bottom: 52px;
    15231675    }
    15241676
     
    15501702        -webkit-transition: none;
    15511703        transition: none;
     1704        height: auto;
     1705        margin-top: 0;
     1706        top: 10px;
     1707        bottom: 10px;
     1708    }
     1709
     1710    #link-selector {
     1711        overflow: auto;
     1712    }
     1713
     1714    #search-panel .query-results {
     1715        position: static;
    15521716    }
    15531717}
     
    15661730        height: calc(100% - 92px);
    15671731        padding-bottom: 2px;
     1732    }
     1733
     1734    #search-panel .query-results {
     1735        position: static;
    15681736    }
    15691737}
  • trunk/src/wp-includes/js/wplink.js

    r36991 r37154  
    1 
    21var wpLink;
    32
    43( function( $, wpLinkL10n, wp ) {
    5     var editor, correctedURL, linkNode,
     4    var editor, searchTimer, River, Query, correctedURL, linkNode,
     5        emailRegexp = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
     6        urlRegexp = /^(https?|ftp):\/\/[A-Z0-9.-]+\.[A-Z]{2,4}[^ "]*$/i,
    67        inputs = {},
     8        rivers = {},
    79        isTouch = ( 'ontouchend' in document );
    810
     
    1214
    1315    wpLink = {
     16        timeToTriggerRiver: 150,
     17        minRiverAJAXDuration: 200,
     18        riverBottomThreshold: 5,
     19        keySensitivity: 100,
     20        lastSearch: '',
    1421        textarea: '',
    1522
     
    2431            inputs.text = $( '#wp-link-text' );
    2532            inputs.url = $( '#wp-link-url' );
     33            inputs.nonce = $( '#_ajax_linking_nonce' );
    2634            inputs.openInNewTab = $( '#wp-link-target' );
    27 
    28             if ( $.ui && $.ui.autocomplete ) {
    29                 wpLink.setAutocomplete();
    30             }
    31 
    32             inputs.dialog.on( 'keydown', wpLink.keydown );
    33             inputs.submit.on( 'click', function( event ) {
     35            inputs.search = $( '#wp-link-search' );
     36
     37            // Build Rivers
     38            rivers.search = new River( $( '#search-results' ) );
     39            rivers.recent = new River( $( '#most-recent-results' ) );
     40            rivers.elements = inputs.dialog.find( '.query-results' );
     41
     42            // Get search notice text
     43            inputs.queryNotice = $( '#query-notice-message' );
     44            inputs.queryNoticeTextDefault = inputs.queryNotice.find( '.query-notice-default' );
     45            inputs.queryNoticeTextHint = inputs.queryNotice.find( '.query-notice-hint' );
     46
     47            // Bind event handlers
     48            inputs.dialog.keydown( wpLink.keydown );
     49            inputs.dialog.keyup( wpLink.keyup );
     50            inputs.submit.click( function( event ) {
    3451                event.preventDefault();
    3552                wpLink.update();
     
    4158            });
    4259
     60            rivers.elements.on( 'river-select', wpLink.updateFields );
     61
     62            // Display 'hint' message when search field or 'query-results' box are focused
     63            inputs.search.on( 'focus.wplink', function() {
     64                inputs.queryNoticeTextDefault.hide();
     65                inputs.queryNoticeTextHint.removeClass( 'screen-reader-text' ).show();
     66            } ).on( 'blur.wplink', function() {
     67                inputs.queryNoticeTextDefault.show();
     68                inputs.queryNoticeTextHint.addClass( 'screen-reader-text' ).hide();
     69            } );
     70
     71            inputs.search.on( 'keyup input', function() {
     72                window.clearTimeout( searchTimer );
     73                searchTimer = window.setTimeout( function() {
     74                    wpLink.searchInternalLinks();
     75                }, 500 );
     76            });
     77
    4378            inputs.url.on( 'paste', function() {
    4479                setTimeout( wpLink.correctURL, 0 );
    4580            } );
    46         },
    47 
    48         setAutocomplete: function() {
    49             var $input = inputs.url,
    50                 cache, last;
    51 
    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                     }
    60 
    61                     if ( /^https?:/.test( request.term ) || request.term.indexOf( '.' ) !== -1 ) {
    62                         return response();
    63                     }
    64 
    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' );
    74 
    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 );
    87 
    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.
     81
     82            inputs.url.on( 'blur', wpLink.correctURL );
    14283        },
    14384
     
    208149        refresh: function( url, text ) {
    209150            var linkText = '';
     151
     152            // Refresh rivers (clear links, check visibility)
     153            rivers.search.refresh();
     154            rivers.recent.refresh();
    210155
    211156            if ( wpLink.isMCE() ) {
     
    238183                // IE will show a flashing cursor over the dialog.
    239184                window.setTimeout( function() {
    240                     inputs.url.focus()[0].select();
     185                    inputs.url[0].select();
     186                    inputs.url.focus();
    241187                } );
     188            }
     189
     190            // Load the most recent results if this is the first time opening the panel.
     191            if ( ! rivers.recent.ul.children().length ) {
     192                rivers.recent.ajax();
    242193            }
    243194
     
    272223        },
    273224
    274         mceRefresh: function( url, text ) {
    275             var linkText,
     225        mceRefresh: function( searchStr, text ) {
     226            var linkText, href,
    276227                linkNode = getLink(),
    277228                onlyText = this.hasSelectedText( linkNode );
     
    279230            if ( linkNode ) {
    280231                linkText = linkNode.innerText || linkNode.textContent;
     232                href = editor.dom.getAttrib( linkNode, 'href' );
    281233
    282234                if ( ! $.trim( linkText ) ) {
     
    284236                }
    285237
    286                 url = url || editor.dom.getAttrib( linkNode, 'href' );
    287 
    288                 if ( url !== '_wp_link_placeholder' ) {
    289                     inputs.url.val( url );
     238                if ( searchStr && ( urlRegexp.test( searchStr ) || emailRegexp.test( searchStr ) ) ) {
     239                    href = searchStr;
     240                }
     241
     242                if ( href !== '_wp_link_placeholder' ) {
     243                    inputs.url.val( href );
    290244                    inputs.openInNewTab.prop( 'checked', '_blank' === editor.dom.getAttrib( linkNode, 'target' ) );
    291245                    inputs.submit.val( wpLinkL10n.update );
     
    293247                    this.setDefaultValues( linkText );
    294248                }
     249
     250                if ( searchStr && searchStr !== href ) {
     251                    // The user has typed something in the inline dialog. Trigger a search with it.
     252                    inputs.search.val( searchStr );
     253                } else {
     254                    inputs.search.val( '' );
     255                }
     256
     257                // Always reset the search
     258                window.setTimeout( function() {
     259                    wpLink.searchInternalLinks();
     260                } );
    295261            } else {
    296262                linkText = editor.selection.getContent({ format: 'text' }) || text || '';
     
    425391                link, text;
    426392
    427             editor.focus();
    428 
    429393            if ( window.tinymce.isIE && editor.windowManager.wplinkBookmark ) {
    430394                editor.selection.moveToBookmark( editor.windowManager.wplinkBookmark );
     
    472436        },
    473437
     438        updateFields: function( e, li ) {
     439            inputs.url.val( li.children( '.item-permalink' ).val() );
     440        },
     441
     442        getUrlFromSelection: function( selection ) {
     443            if ( ! selection ) {
     444                if ( this.isMCE() ) {
     445                    selection = editor.selection.getContent({ format: 'text' });
     446                } else if ( document.selection && wpLink.range ) {
     447                    selection = wpLink.range.text;
     448                } else if ( typeof this.textarea.selectionStart !== 'undefined' ) {
     449                    selection = this.textarea.value.substring( this.textarea.selectionStart, this.textarea.selectionEnd );
     450                }
     451            }
     452
     453            selection = $.trim( selection );
     454
     455            if ( selection && emailRegexp.test( selection ) ) {
     456                // Selection is email address
     457                return 'mailto:' + selection;
     458            } else if ( selection && urlRegexp.test( selection ) ) {
     459                // Selection is URL
     460                return selection.replace( /&amp;|&#0?38;/gi, '&' );
     461            }
     462
     463            return '';
     464        },
     465
     466        setDefaultValues: function( selection ) {
     467            inputs.url.val( this.getUrlFromSelection( selection ) );
     468
     469            // Empty the search field and swap the "rivers".
     470            inputs.search.val('');
     471            wpLink.searchInternalLinks();
     472
     473            // Update save prompt.
     474            inputs.submit.val( wpLinkL10n.save );
     475        },
     476
     477        searchInternalLinks: function() {
     478            var waiting,
     479                search = inputs.search.val() || '';
     480
     481            if ( search.length > 2 ) {
     482                rivers.recent.hide();
     483                rivers.search.show();
     484
     485                // Don't search if the keypress didn't change the title.
     486                if ( wpLink.lastSearch == search )
     487                    return;
     488
     489                wpLink.lastSearch = search;
     490                waiting = inputs.search.parent().find( '.spinner' ).addClass( 'is-active' );
     491
     492                rivers.search.change( search );
     493                rivers.search.ajax( function() {
     494                    waiting.removeClass( 'is-active' );
     495                });
     496            } else {
     497                rivers.search.hide();
     498                rivers.recent.show();
     499            }
     500        },
     501
     502        next: function() {
     503            rivers.search.next();
     504            rivers.recent.next();
     505        },
     506
     507        prev: function() {
     508            rivers.search.prev();
     509            rivers.recent.prev();
     510        },
     511
    474512        keydown: function( event ) {
    475             var id;
     513            var fn, id;
    476514
    477515            // Escape key.
     
    493531                }
    494532            }
    495         },
    496 
    497         getUrlFromSelection: function( selection ) {
    498             var emailRegexp = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,
    499                 urlRegexp = /^(https?|ftp):\/\/[A-Z0-9.-]+\.[A-Z]{2,4}[^ "]*$/i;
    500 
    501             if ( ! selection ) {
    502                 if ( this.isMCE() ) {
    503                     selection = editor.selection.getContent({ format: 'text' });
    504                 } else if ( document.selection && wpLink.range ) {
    505                     selection = wpLink.range.text;
    506                 } else if ( typeof this.textarea.selectionStart !== 'undefined' ) {
    507                     selection = this.textarea.value.substring( this.textarea.selectionStart, this.textarea.selectionEnd );
    508                 }
    509             }
    510 
    511             selection = $.trim( selection );
    512 
    513             if ( selection && emailRegexp.test( selection ) ) {
    514                 // Selection is email address
    515                 return 'mailto:' + selection;
    516             } else if ( selection && urlRegexp.test( selection ) ) {
    517                 // Selection is URL
    518                 return selection.replace( /&amp;|&#0?38;/gi, '&' );
    519             }
    520 
    521             return '';
    522         },
    523 
    524         setDefaultValues: function( selection ) {
    525             inputs.url.val( this.getUrlFromSelection( selection ) );
    526 
    527             // Update save prompt.
    528             inputs.submit.val( wpLinkL10n.save );
     533
     534            // Up Arrow and Down Arrow keys.
     535            if ( 38 !== event.keyCode && 40 !== event.keyCode ) {
     536                return;
     537            }
     538
     539            if ( document.activeElement &&
     540                ( document.activeElement.id === 'link-title-field' || document.activeElement.id === 'url-field' ) ) {
     541                return;
     542            }
     543
     544            // Up Arrow key.
     545            fn = 38 === event.keyCode ? 'prev' : 'next';
     546            clearInterval( wpLink.keyInterval );
     547            wpLink[ fn ]();
     548            wpLink.keyInterval = setInterval( wpLink[ fn ], wpLink.keySensitivity );
     549            event.preventDefault();
     550        },
     551
     552        keyup: function( event ) {
     553            // Up Arrow and Down Arrow keys.
     554            if ( 38 === event.keyCode || 40 === event.keyCode ) {
     555                clearInterval( wpLink.keyInterval );
     556                event.preventDefault();
     557            }
     558        },
     559
     560        delayedCallback: function( func, delay ) {
     561            var timeoutTriggered, funcTriggered, funcArgs, funcContext;
     562
     563            if ( ! delay )
     564                return func;
     565
     566            setTimeout( function() {
     567                if ( funcTriggered )
     568                    return func.apply( funcContext, funcArgs );
     569                // Otherwise, wait.
     570                timeoutTriggered = true;
     571            }, delay );
     572
     573            return function() {
     574                if ( timeoutTriggered )
     575                    return func.apply( this, arguments );
     576                // Otherwise, wait.
     577                funcArgs = arguments;
     578                funcContext = this;
     579                funcTriggered = true;
     580            };
    529581        }
    530582    };
    531583
     584    River = function( element, search ) {
     585        var self = this;
     586        this.element = element;
     587        this.ul = element.children( 'ul' );
     588        this.contentHeight = element.children( '#link-selector-height' );
     589        this.waiting = element.find('.river-waiting');
     590
     591        this.change( search );
     592        this.refresh();
     593
     594        $( '#wp-link .query-results, #wp-link #link-selector' ).scroll( function() {
     595            self.maybeLoad();
     596        });
     597        element.on( 'click', 'li', function( event ) {
     598            self.select( $( this ), event );
     599        });
     600    };
     601
     602    $.extend( River.prototype, {
     603        refresh: function() {
     604            this.deselect();
     605            this.visible = this.element.is( ':visible' );
     606        },
     607        show: function() {
     608            if ( ! this.visible ) {
     609                this.deselect();
     610                this.element.show();
     611                this.visible = true;
     612            }
     613        },
     614        hide: function() {
     615            this.element.hide();
     616            this.visible = false;
     617        },
     618        // Selects a list item and triggers the river-select event.
     619        select: function( li, event ) {
     620            var liHeight, elHeight, liTop, elTop;
     621
     622            if ( li.hasClass( 'unselectable' ) || li == this.selected )
     623                return;
     624
     625            this.deselect();
     626            this.selected = li.addClass( 'selected' );
     627            // Make sure the element is visible
     628            liHeight = li.outerHeight();
     629            elHeight = this.element.height();
     630            liTop = li.position().top;
     631            elTop = this.element.scrollTop();
     632
     633            if ( liTop < 0 ) // Make first visible element
     634                this.element.scrollTop( elTop + liTop );
     635            else if ( liTop + liHeight > elHeight ) // Make last visible element
     636                this.element.scrollTop( elTop + liTop - elHeight + liHeight );
     637
     638            // Trigger the river-select event
     639            this.element.trigger( 'river-select', [ li, event, this ] );
     640        },
     641        deselect: function() {
     642            if ( this.selected )
     643                this.selected.removeClass( 'selected' );
     644            this.selected = false;
     645        },
     646        prev: function() {
     647            if ( ! this.visible )
     648                return;
     649
     650            var to;
     651            if ( this.selected ) {
     652                to = this.selected.prev( 'li' );
     653                if ( to.length )
     654                    this.select( to );
     655            }
     656        },
     657        next: function() {
     658            if ( ! this.visible )
     659                return;
     660
     661            var to = this.selected ? this.selected.next( 'li' ) : $( 'li:not(.unselectable):first', this.element );
     662            if ( to.length )
     663                this.select( to );
     664        },
     665        ajax: function( callback ) {
     666            var self = this,
     667                delay = this.query.page == 1 ? 0 : wpLink.minRiverAJAXDuration,
     668                response = wpLink.delayedCallback( function( results, params ) {
     669                    self.process( results, params );
     670                    if ( callback )
     671                        callback( results, params );
     672                }, delay );
     673
     674            this.query.ajax( response );
     675        },
     676        change: function( search ) {
     677            if ( this.query && this._search == search )
     678                return;
     679
     680            this._search = search;
     681            this.query = new Query( search );
     682            this.element.scrollTop( 0 );
     683        },
     684        process: function( results, params ) {
     685            var list = '', alt = true, classes = '',
     686                firstPage = params.page == 1;
     687
     688            if ( ! results ) {
     689                if ( firstPage ) {
     690                    list += '<li class="unselectable no-matches-found"><span class="item-title"><em>' +
     691                        wpLinkL10n.noMatchesFound + '</em></span></li>';
     692                }
     693            } else {
     694                $.each( results, function() {
     695                    classes = alt ? 'alternate' : '';
     696                    classes += this.title ? '' : ' no-title';
     697                    list += classes ? '<li class="' + classes + '">' : '<li>';
     698                    list += '<input type="hidden" class="item-permalink" value="' + this.permalink + '" />';
     699                    list += '<span class="item-title">';
     700                    list += this.title ? this.title : wpLinkL10n.noTitle;
     701                    list += '</span><span class="item-info">' + this.info + '</span></li>';
     702                    alt = ! alt;
     703                });
     704            }
     705
     706            this.ul[ firstPage ? 'html' : 'append' ]( list );
     707        },
     708        maybeLoad: function() {
     709            var self = this,
     710                el = this.element,
     711                bottom = el.scrollTop() + el.height();
     712
     713            if ( ! this.query.ready() || bottom < this.contentHeight.height() - wpLink.riverBottomThreshold )
     714                return;
     715
     716            setTimeout(function() {
     717                var newTop = el.scrollTop(),
     718                    newBottom = newTop + el.height();
     719
     720                if ( ! self.query.ready() || newBottom < self.contentHeight.height() - wpLink.riverBottomThreshold )
     721                    return;
     722
     723                self.waiting.addClass( 'is-active' );
     724                el.scrollTop( newTop + self.waiting.outerHeight() );
     725
     726                self.ajax( function() {
     727                    self.waiting.removeClass( 'is-active' );
     728                });
     729            }, wpLink.timeToTriggerRiver );
     730        }
     731    });
     732
     733    Query = function( search ) {
     734        this.page = 1;
     735        this.allLoaded = false;
     736        this.querying = false;
     737        this.search = search;
     738    };
     739
     740    $.extend( Query.prototype, {
     741        ready: function() {
     742            return ! ( this.querying || this.allLoaded );
     743        },
     744        ajax: function( callback ) {
     745            var self = this,
     746                query = {
     747                    action : 'wp-link-ajax',
     748                    page : this.page,
     749                    '_ajax_linking_nonce' : inputs.nonce.val()
     750                };
     751
     752            if ( this.search )
     753                query.search = this.search;
     754
     755            this.querying = true;
     756
     757            $.post( window.ajaxurl, query, function( r ) {
     758                self.page++;
     759                self.querying = false;
     760                self.allLoaded = ! r;
     761                callback( r, query );
     762            }, 'json' );
     763        }
     764    });
     765
    532766    $( document ).ready( wpLink.init );
    533767})( jQuery, window.wpLinkL10n, window.wp );
Note: See TracChangeset for help on using the changeset viewer.