Ticket #36359: 36359.1.patch
File 36359.1.patch, 25.0 KB (added by , 9 years ago) |
---|
-
src/wp-admin/includes/upgrade.php
1682 1682 if ( $wp_current_db_version < 36679 && is_multisite() ) { 1683 1683 $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name REGEXP '^[0-9]+_new_email$'" ); 1684 1684 } 1685 1686 // Remove unused user setting for wpLink.1687 delete_user_setting( 'wplink' );1688 1685 } 1689 1686 1690 1687 /** -
src/wp-includes/class-wp-editor.php
1402 1402 * @static 1403 1403 */ 1404 1404 public static function wp_link_dialog() { 1405 $search_panel_visible = '1' == get_user_setting( 'wplink', '0' ) ? ' search-panel-visible' : ''; 1406 1405 1407 // display: none is required here, see #WP27605 1406 1408 ?> 1407 1409 <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"> 1409 1411 <form id="wp-link" tabindex="-1"> 1410 1412 <?php wp_nonce_field( 'internal-linking', '_ajax_linking_nonce', false ); ?> 1411 1413 <h1 id="link-modal-title"><?php _e( 'Insert/edit link' ) ?></h1> … … 1412 1414 <button type="button" id="wp-link-close"><span class="screen-reader-text"><?php _e( 'Close' ); ?></span></button> 1413 1415 <div id="link-selector"> 1414 1416 <div id="link-options"> 1417 <p class="howto"><?php _e( 'Enter the destination URL' ); ?></p> 1415 1418 <div> 1416 1419 <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> 1418 1421 </div> 1419 1422 <div class="wp-link-text-field"> 1420 1423 <label><span><?php _e( 'Link Text' ); ?></span> … … 1425 1428 <input type="checkbox" id="wp-link-target" /> <?php _e( 'Open link in a new tab' ); ?></label> 1426 1429 </div> 1427 1430 </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> 1428 1457 </div> 1429 1458 <div class="submitbox"> 1430 1459 <div id="wp-link-cancel"> -
src/wp-includes/css/editor.css
95 95 } 96 96 97 97 .mce-textbox, 98 .mce-checkbox i.mce-i-checkbox { 98 .mce-checkbox i.mce-i-checkbox, 99 #wp-link .query-results { 99 100 border: 1px solid #ddd; 100 101 -webkit-border-radius: 0; 101 102 border-radius: 0; … … 1374 1375 height: 100%; 1375 1376 } 1376 1377 1378 #wp-link-wrap.search-panel-visible { 1379 height: 500px; 1380 margin-top: -250px; 1381 } 1382 1377 1383 #wp-link-wrap .wp-link-text-field { 1378 1384 display: none; 1379 1385 } … … 1437 1443 padding: 0 16px 50px; 1438 1444 } 1439 1445 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 1440 1456 #wp-link ol, 1441 1457 #wp-link ul { 1442 1458 list-style: none; … … 1444 1460 padding: 0; 1445 1461 } 1446 1462 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 1447 1477 #wp-link input[type="text"] { 1448 1478 -webkit-box-sizing: border-box; 1449 1479 -moz-box-sizing: border-box; … … 1463 1493 color: inherit; 1464 1494 } 1465 1495 1496 #wp-link-search-toggle { 1497 cursor: pointer; 1498 } 1499 1466 1500 #wp-link label input[type="text"] { 1467 margin : 8px 0 0;1501 margin-top: 5px; 1468 1502 width: 70%; 1469 1503 } 1470 1504 1471 #wp-link #link-options label span { 1505 #wp-link #link-options label span, 1506 #wp-link #search-panel label span.search-label { 1472 1507 display: inline-block; 1473 1508 width: 80px; 1474 1509 text-align: right; … … 1478 1513 word-wrap: break-word; 1479 1514 } 1480 1515 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 1481 1537 #wp-link .link-target { 1482 1538 padding: 3px 0 0; 1483 1539 white-space: nowrap; … … 1489 1545 max-width: 70%; 1490 1546 } 1491 1547 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 1492 1663 #wp-link .submitbox { 1493 1664 padding: 8px 16px; 1494 1665 background: #fcfcfc; … … 1518 1689 margin-top: -140px; 1519 1690 } 1520 1691 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 1521 1700 #link-selector { 1522 1701 padding: 0 16px 60px; 1523 1702 } 1524 1703 1704 #wp-link-wrap.search-panel-visible #link-selector { 1705 bottom: 52px; 1706 } 1707 1525 1708 #wp-link-cancel { 1526 1709 line-height: 32px; 1527 1710 } … … 1550 1733 -webkit-transition: none; 1551 1734 transition: none; 1552 1735 } 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 } 1553 1751 } 1554 1752 1555 1753 @media screen and ( max-height: 290px ) { … … 1566 1764 height: calc(100% - 92px); 1567 1765 padding-bottom: 2px; 1568 1766 } 1767 1768 #search-panel .query-results { 1769 position: static; 1770 } 1569 1771 } 1570 1772 1571 1773 div.wp-link-preview { -
src/wp-includes/js/wplink.js
1 1 /* global ajaxurl, tinymce, wpLinkL10n, setUserSetting, wpActiveEditor */ 2 2 var wpLink; 3 3 4 4 ( function( $, wpLinkL10n, wp ) { 5 var editor, correctedURL, linkNode, 5 var editor, searchTimer, River, Query, correctedURL, linkNode, 6 emailRegexp = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i, 7 urlRegexp = /^(https?|ftp):\/\/[A-Z0-9.-]+\.[A-Z]{2,4}[^ "]*$/i, 6 8 inputs = {}, 9 rivers = {}, 7 10 isTouch = ( 'ontouchend' in document ); 8 11 9 12 function getLink() { … … 11 14 } 12 15 13 16 wpLink = { 17 timeToTriggerRiver: 150, 18 minRiverAJAXDuration: 200, 19 riverBottomThreshold: 5, 20 keySensitivity: 100, 21 lastSearch: '', 14 22 textarea: '', 15 23 16 24 init: function() { … … 23 31 // Input 24 32 inputs.text = $( '#wp-link-text' ); 25 33 inputs.url = $( '#wp-link-url' ); 34 inputs.nonce = $( '#_ajax_linking_nonce' ); 26 35 inputs.openInNewTab = $( '#wp-link-target' ); 36 inputs.search = $( '#wp-link-search' ); 27 37 28 if ( $.ui && $.ui.autocomplete ) { 29 wpLink.setAutocomplete(); 30 } 38 // Build Rivers 39 rivers.search = new River( $( '#search-results' ) ); 40 rivers.recent = new River( $( '#most-recent-results' ) ); 41 rivers.elements = inputs.dialog.find( '.query-results' ); 31 42 32 inputs.dialog.on( 'keydown', wpLink.keydown ); 33 inputs.submit.on( 'click', function( event ) { 43 // Get search notice text 44 inputs.queryNotice = $( '#query-notice-message' ); 45 inputs.queryNoticeTextDefault = inputs.queryNotice.find( '.query-notice-default' ); 46 inputs.queryNoticeTextHint = inputs.queryNotice.find( '.query-notice-hint' ); 47 48 // Bind event handlers 49 inputs.dialog.keydown( wpLink.keydown ); 50 inputs.dialog.keyup( wpLink.keyup ); 51 inputs.submit.click( function( event ) { 34 52 event.preventDefault(); 35 53 wpLink.update(); 36 54 }); … … 40 58 wpLink.close(); 41 59 }); 42 60 43 inputs.url.on( 'paste', function() { 44 setTimeout( wpLink.correctURL, 0 ); 45 } ); 46 }, 61 $( '#wp-link-search-toggle' ).on( 'click', wpLink.toggleInternalLinking ); 47 62 48 setAutocomplete: function() { 49 var $input = inputs.url, 50 cache, last; 63 rivers.elements.on( 'river-select', wpLink.updateFields ); 51 64 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 }65 // Display 'hint' message when search field or 'query-results' box are focused 66 inputs.search.on( 'focus.wplink', function() { 67 inputs.queryNoticeTextDefault.hide(); 68 inputs.queryNoticeTextHint.removeClass( 'screen-reader-text' ).show(); 69 } ).on( 'blur.wplink', function() { 70 inputs.queryNoticeTextDefault.show(); 71 inputs.queryNoticeTextHint.addClass( 'screen-reader-text' ).hide(); 72 } ); 60 73 61 if ( /^https?:/.test( request.term ) || request.term.indexOf( '.' ) !== -1 ) { 62 return response(); 63 } 74 inputs.search.on( 'keyup input', function() { 75 var self = this; 64 76 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' ); 77 window.clearTimeout( searchTimer ); 78 searchTimer = window.setTimeout( function() { 79 wpLink.searchInternalLinks(); 80 }, 500 ); 81 }); 74 82 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 ); 83 inputs.url.on( 'paste', function() { 84 setTimeout( wpLink.correctURL, 0 ); 85 } ); 87 86 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> <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. 87 inputs.url.on( 'blur', wpLink.correctURL ); 142 88 }, 143 89 144 90 // If URL wasn't corrected last time and doesn't start with http:, https:, ? # or /, prepend http:// … … 208 154 refresh: function( url, text ) { 209 155 var linkText = ''; 210 156 157 // Refresh rivers (clear links, check visibility) 158 rivers.search.refresh(); 159 rivers.recent.refresh(); 160 211 161 if ( wpLink.isMCE() ) { 212 162 wpLink.mceRefresh( url, text ); 213 163 } else { … … 241 191 } ); 242 192 } 243 193 194 // Load the most recent results if this is the first time opening the panel. 195 if ( ! rivers.recent.ul.children().length ) { 196 rivers.recent.ajax(); 197 } 198 244 199 correctedURL = inputs.url.val().replace( /^http:\/\//, '' ); 245 200 }, 246 201 … … 286 241 url = url || editor.dom.getAttrib( linkNode, 'href' ); 287 242 288 243 if ( url !== '_wp_link_placeholder' ) { 289 inputs.url.val( url ); 244 // If the user has typed something in the inline dialog, 245 // and it looks like URL or email, add it to the URL field. 246 // Else assume it is a search string and add it to the search field. 247 if ( urlRegexp.test( url ) || emailRegexp.test( url ) ) { 248 inputs.url.val( url ); 249 } else { 250 inputs.search.val( url ); 251 window.setTimeout( function() { 252 wpLink.searchInternalLinks(); 253 } ); 254 } 255 290 256 inputs.openInNewTab.prop( 'checked', '_blank' === editor.dom.getAttrib( linkNode, 'target' ) ); 291 257 inputs.submit.val( wpLinkL10n.update ); 292 258 } else { … … 471 437 wp.a11y.speak( wpLinkL10n.linkInserted ); 472 438 }, 473 439 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 } 440 updateFields: function( e, li ) { 441 inputs.url.val( li.children( '.item-permalink' ).val() ); 495 442 }, 496 443 497 444 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 445 if ( ! selection ) { 502 446 if ( this.isMCE() ) { 503 447 selection = editor.selection.getContent({ format: 'text' }); … … 526 470 527 471 // Update save prompt. 528 472 inputs.submit.val( wpLinkL10n.save ); 473 }, 474 475 searchInternalLinks: function() { 476 var waiting, 477 search = inputs.search.val() || ''; 478 479 if ( search.length > 2 ) { 480 rivers.recent.hide(); 481 rivers.search.show(); 482 483 // Don't search if the keypress didn't change the title. 484 if ( wpLink.lastSearch == search ) 485 return; 486 487 wpLink.lastSearch = search; 488 waiting = inputs.search.parent().find( '.spinner' ).addClass( 'is-active' ); 489 490 rivers.search.change( search ); 491 rivers.search.ajax( function() { 492 waiting.removeClass( 'is-active' ); 493 }); 494 } else { 495 rivers.search.hide(); 496 rivers.recent.show(); 497 } 498 }, 499 500 next: function() { 501 rivers.search.next(); 502 rivers.recent.next(); 503 }, 504 505 prev: function() { 506 rivers.search.prev(); 507 rivers.recent.prev(); 508 }, 509 510 keydown: function( event ) { 511 var fn, id; 512 513 // Escape key. 514 if ( 27 === event.keyCode ) { 515 wpLink.close(); 516 event.stopImmediatePropagation(); 517 // Tab key. 518 } else if ( 9 === event.keyCode ) { 519 id = event.target.id; 520 521 // wp-link-submit must always be the last focusable element in the dialog. 522 // following focusable elements will be skipped on keyboard navigation. 523 if ( id === 'wp-link-submit' && ! event.shiftKey ) { 524 inputs.close.focus(); 525 event.preventDefault(); 526 } else if ( id === 'wp-link-close' && event.shiftKey ) { 527 inputs.submit.focus(); 528 event.preventDefault(); 529 } 530 } 531 532 // Up Arrow and Down Arrow keys. 533 if ( 38 !== event.keyCode && 40 !== event.keyCode ) { 534 return; 535 } 536 537 if ( document.activeElement && 538 ( document.activeElement.id === 'link-title-field' || document.activeElement.id === 'url-field' ) ) { 539 return; 540 } 541 542 // Up Arrow key. 543 fn = 38 === event.keyCode ? 'prev' : 'next'; 544 clearInterval( wpLink.keyInterval ); 545 wpLink[ fn ](); 546 wpLink.keyInterval = setInterval( wpLink[ fn ], wpLink.keySensitivity ); 547 event.preventDefault(); 548 }, 549 550 keyup: function( event ) { 551 // Up Arrow and Down Arrow keys. 552 if ( 38 === event.keyCode || 40 === event.keyCode ) { 553 clearInterval( wpLink.keyInterval ); 554 event.preventDefault(); 555 } 556 }, 557 558 delayedCallback: function( func, delay ) { 559 var timeoutTriggered, funcTriggered, funcArgs, funcContext; 560 561 if ( ! delay ) 562 return func; 563 564 setTimeout( function() { 565 if ( funcTriggered ) 566 return func.apply( funcContext, funcArgs ); 567 // Otherwise, wait. 568 timeoutTriggered = true; 569 }, delay ); 570 571 return function() { 572 if ( timeoutTriggered ) 573 return func.apply( this, arguments ); 574 // Otherwise, wait. 575 funcArgs = arguments; 576 funcContext = this; 577 funcTriggered = true; 578 }; 579 }, 580 581 toggleInternalLinking: function( event ) { 582 var visible = inputs.wrap.hasClass( 'search-panel-visible' ); 583 584 inputs.wrap.toggleClass( 'search-panel-visible', ! visible ); 585 setUserSetting( 'wplink', visible ? '0' : '1' ); 586 inputs[ ! visible ? 'search' : 'url' ].focus(); 587 event.preventDefault(); 529 588 } 530 589 }; 531 590 591 River = function( element, search ) { 592 var self = this; 593 this.element = element; 594 this.ul = element.children( 'ul' ); 595 this.contentHeight = element.children( '#link-selector-height' ); 596 this.waiting = element.find('.river-waiting'); 597 598 this.change( search ); 599 this.refresh(); 600 601 $( '#wp-link .query-results, #wp-link #link-selector' ).scroll( function() { 602 self.maybeLoad(); 603 }); 604 element.on( 'click', 'li', function( event ) { 605 self.select( $( this ), event ); 606 }); 607 }; 608 609 $.extend( River.prototype, { 610 refresh: function() { 611 this.deselect(); 612 this.visible = this.element.is( ':visible' ); 613 }, 614 show: function() { 615 if ( ! this.visible ) { 616 this.deselect(); 617 this.element.show(); 618 this.visible = true; 619 } 620 }, 621 hide: function() { 622 this.element.hide(); 623 this.visible = false; 624 }, 625 // Selects a list item and triggers the river-select event. 626 select: function( li, event ) { 627 var liHeight, elHeight, liTop, elTop; 628 629 if ( li.hasClass( 'unselectable' ) || li == this.selected ) 630 return; 631 632 this.deselect(); 633 this.selected = li.addClass( 'selected' ); 634 // Make sure the element is visible 635 liHeight = li.outerHeight(); 636 elHeight = this.element.height(); 637 liTop = li.position().top; 638 elTop = this.element.scrollTop(); 639 640 if ( liTop < 0 ) // Make first visible element 641 this.element.scrollTop( elTop + liTop ); 642 else if ( liTop + liHeight > elHeight ) // Make last visible element 643 this.element.scrollTop( elTop + liTop - elHeight + liHeight ); 644 645 // Trigger the river-select event 646 this.element.trigger( 'river-select', [ li, event, this ] ); 647 }, 648 deselect: function() { 649 if ( this.selected ) 650 this.selected.removeClass( 'selected' ); 651 this.selected = false; 652 }, 653 prev: function() { 654 if ( ! this.visible ) 655 return; 656 657 var to; 658 if ( this.selected ) { 659 to = this.selected.prev( 'li' ); 660 if ( to.length ) 661 this.select( to ); 662 } 663 }, 664 next: function() { 665 if ( ! this.visible ) 666 return; 667 668 var to = this.selected ? this.selected.next( 'li' ) : $( 'li:not(.unselectable):first', this.element ); 669 if ( to.length ) 670 this.select( to ); 671 }, 672 ajax: function( callback ) { 673 var self = this, 674 delay = this.query.page == 1 ? 0 : wpLink.minRiverAJAXDuration, 675 response = wpLink.delayedCallback( function( results, params ) { 676 self.process( results, params ); 677 if ( callback ) 678 callback( results, params ); 679 }, delay ); 680 681 this.query.ajax( response ); 682 }, 683 change: function( search ) { 684 if ( this.query && this._search == search ) 685 return; 686 687 this._search = search; 688 this.query = new Query( search ); 689 this.element.scrollTop( 0 ); 690 }, 691 process: function( results, params ) { 692 var list = '', alt = true, classes = '', 693 firstPage = params.page == 1; 694 695 if ( ! results ) { 696 if ( firstPage ) { 697 list += '<li class="unselectable no-matches-found"><span class="item-title"><em>' + 698 wpLinkL10n.noMatchesFound + '</em></span></li>'; 699 } 700 } else { 701 $.each( results, function() { 702 classes = alt ? 'alternate' : ''; 703 classes += this.title ? '' : ' no-title'; 704 list += classes ? '<li class="' + classes + '">' : '<li>'; 705 list += '<input type="hidden" class="item-permalink" value="' + this.permalink + '" />'; 706 list += '<span class="item-title">'; 707 list += this.title ? this.title : wpLinkL10n.noTitle; 708 list += '</span><span class="item-info">' + this.info + '</span></li>'; 709 alt = ! alt; 710 }); 711 } 712 713 this.ul[ firstPage ? 'html' : 'append' ]( list ); 714 }, 715 maybeLoad: function() { 716 var self = this, 717 el = this.element, 718 bottom = el.scrollTop() + el.height(); 719 720 if ( ! this.query.ready() || bottom < this.contentHeight.height() - wpLink.riverBottomThreshold ) 721 return; 722 723 setTimeout(function() { 724 var newTop = el.scrollTop(), 725 newBottom = newTop + el.height(); 726 727 if ( ! self.query.ready() || newBottom < self.contentHeight.height() - wpLink.riverBottomThreshold ) 728 return; 729 730 self.waiting.addClass( 'is-active' ); 731 el.scrollTop( newTop + self.waiting.outerHeight() ); 732 733 self.ajax( function() { 734 self.waiting.removeClass( 'is-active' ); 735 }); 736 }, wpLink.timeToTriggerRiver ); 737 } 738 }); 739 740 Query = function( search ) { 741 this.page = 1; 742 this.allLoaded = false; 743 this.querying = false; 744 this.search = search; 745 }; 746 747 $.extend( Query.prototype, { 748 ready: function() { 749 return ! ( this.querying || this.allLoaded ); 750 }, 751 ajax: function( callback ) { 752 var self = this, 753 query = { 754 action : 'wp-link-ajax', 755 page : this.page, 756 '_ajax_linking_nonce' : inputs.nonce.val() 757 }; 758 759 if ( this.search ) 760 query.search = this.search; 761 762 this.querying = true; 763 764 $.post( ajaxurl, query, function( r ) { 765 self.page++; 766 self.querying = false; 767 self.allLoaded = ! r; 768 callback( r, query ); 769 }, 'json' ); 770 } 771 }); 772 532 773 $( document ).ready( wpLink.init ); 533 774 })( jQuery, window.wpLinkL10n, window.wp );