Changeset 41851
- Timestamp:
- 10/13/2017 02:38:19 AM (7 years ago)
- Location:
- trunk/src/wp-admin
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/css/common.css
r41836 r41851 1467 1467 display: block; 1468 1468 margin: 0; 1469 padding: 5px 12px;1469 padding: 5px 8px; 1470 1470 font-weight: 600; 1471 1471 text-decoration: none; … … 1473 1473 1474 1474 .wrap #templateside span.notice { 1475 1475 margin-left: -12px; 1476 1476 } 1477 1477 1478 1478 #templateside li.notice a { 1479 1479 padding: 0; 1480 1480 } 1481 1481 … … 3037 3037 height: calc( 100vh - 280px ); 3038 3038 } 3039 #templateside { 3040 margin-top: 31px; 3041 overflow: scroll; 3042 } 3039 3040 #templateside > h2 { 3041 padding-top: 6px; 3042 padding-bottom: 6px; 3043 margin: 0; 3044 border-bottom: solid 1px #ccc; 3045 } 3046 3047 #templateside ol, 3048 #templateside ul { 3049 margin: .5em 0; 3050 padding: 0; 3051 } 3052 #templateside > ul { 3053 margin-top: 0; 3054 overflow: auto; 3055 padding: 2px; 3056 height: calc(100vh - 280px); 3057 } 3058 #templateside ul ul { 3059 padding-left: 12px; 3060 } 3061 3062 /* 3063 * Styles for Theme and Plugin editors. 3064 */ 3065 3066 /* Hide collapsed items. */ 3067 [role="treeitem"][aria-expanded="false"] > ul { 3068 display: none; 3069 } 3070 3071 /* Use arrow dashicons for folder states, but hide from screen readers. */ 3072 [role="treeitem"] span[aria-hidden] { 3073 display: inline; 3074 font-family: dashicons; 3075 font-size: 20px; 3076 position: absolute; 3077 pointer-events: none; 3078 } 3079 [role="treeitem"][aria-expanded="false"] > .folder-label .icon:after { 3080 content: "\f139"; 3081 } 3082 [role="treeitem"][aria-expanded="true"] > .folder-label .icon:after { 3083 content: "\f140"; 3084 } 3085 [role="treeitem"] .folder-label { 3086 display: block; 3087 padding: 3px 3px 3px 12px; 3088 cursor: pointer; 3089 } 3090 3091 /* Remove outline, and create our own focus and hover styles */ 3092 [role="treeitem"] { 3093 outline: 0; 3094 } 3095 [role="treeitem"] .folder-label.focus { 3096 color: #124964; 3097 box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8); 3098 } 3099 [role="treeitem"].hover, 3100 [role="treeitem"] .folder-label.hover { 3101 background-color: #DDDDDD; 3102 } 3103 3104 .tree-folder { 3105 margin: 0; 3106 position: relative; 3107 } 3108 [role="treeitem"] li { 3109 position: relative; 3110 } 3111 3112 /* Styles for folder indicators/depth */ 3113 .tree-folder .tree-folder::after { 3114 content: ' '; 3115 display: block; 3116 position: absolute; 3117 left: 2px; 3118 border-left: 1px solid #ccc; 3119 top: -13px; 3120 bottom: 10px; 3121 } 3122 .tree-folder > li::before { 3123 content: ' '; 3124 position: absolute; 3125 display: block; 3126 border-left: 1px solid #ccc; 3127 left: 2px; 3128 top: -5px; 3129 height: 18px; 3130 width: 7px; 3131 border-bottom: 1px solid #ccc; 3132 } 3133 .tree-folder > li::after { 3134 content: ' '; 3135 position: absolute; 3136 display: block; 3137 border-left: 1px solid #ccc; 3138 left: 2px; 3139 bottom: -7px; 3140 top: 0; 3141 } 3142 3143 /* current-file needs to adjustment for .notice styles */ 3144 #templateside .current-file { 3145 margin: -4px 0 -2px; 3146 } 3147 .tree-folder > .current-file::before { 3148 left: 4px; 3149 height: 15px; 3150 width: 6px; 3151 border-left: none; 3152 top: 3px; 3153 } 3154 .tree-folder > .current-file::after { 3155 bottom: -4px; 3156 height: 7px; 3157 left: 2px; 3158 top: auto; 3159 } 3160 3161 /* Lines shouldn't continue on last item */ 3162 .tree-folder > li:last-child::after, 3163 .tree-folder li:last-child > .tree-folder::after { 3164 display: none; 3165 } 3166 3043 3167 3044 3168 #theme-plugin-editor-label { … … 3091 3215 } 3092 3216 3093 #templateside h2,3094 3217 #postcustomstuff p.submit { 3095 3218 margin: 0; … … 3098 3221 #templateside h4 { 3099 3222 margin: 1em 0 0; 3100 }3101 3102 #templateside ol,3103 #templateside ul {3104 margin: .5em 0;3105 padding: 0;3106 3223 } 3107 3224 … … 3654 3771 } 3655 3772 3773 #templateside ul ul { 3774 padding-left: 1.5em; 3775 } 3776 [role="treeitem"] .folder-label { 3777 display: block; 3778 padding: 5px; 3779 } 3780 .tree-folder > li::before, 3781 .tree-folder > li::after, 3782 .tree-folder .tree-folder::after { 3783 left: -8px; 3784 } 3785 .tree-folder > li::before { 3786 top: 0px; 3787 height: 13px; 3788 } 3789 .tree-folder > .current-file::before { 3790 left: -5px; 3791 top: 7px; 3792 width: 4px; 3793 } 3794 .tree-folder > .current-file::after { 3795 height: 9px; 3796 left: -8px; 3797 } 3798 .wrap #templateside span.notice { 3799 margin-left: -14px; 3800 } 3801 3656 3802 .fileedit-sub .alignright { 3657 3803 margin-top: 15px; -
trunk/src/wp-admin/includes/misc.php
r41741 r41851 268 268 } 269 269 update_option( 'recently_edited', $oldfiles ); 270 } 271 272 /** 273 * Makes a tree structure for the Theme Editor's file list. 274 * 275 * @since 4.9.0 276 * @access private 277 * 278 * @param array $allowed_files List of theme file paths. 279 * @return array Tree structure for listing theme files. 280 */ 281 function wp_make_theme_file_tree( $allowed_files ) { 282 $tree_list = array(); 283 foreach ( $allowed_files as $file_name => $absolute_filename ) { 284 $list = explode( '/', $file_name ); 285 $last_dir = &$tree_list; 286 foreach ( $list as $dir ) { 287 $last_dir =& $last_dir[ $dir ]; 288 } 289 $last_dir = $file_name; 290 } 291 return $tree_list; 292 } 293 294 /** 295 * Outputs the formatted file list for the Theme Editor. 296 * 297 * @since 4.9.0 298 * @access private 299 * 300 * @param array|string $tree List of file/folder paths, or filename. 301 * @param int $level The aria-level for the current iteration. 302 * @param int $size The aria-setsize for the current iteration. 303 * @param int $index The aria-posinset for the current iteration. 304 */ 305 function wp_print_theme_file_tree( $tree, $level = 2, $size = 1, $index = 1 ) { 306 global $relative_file, $stylesheet; 307 308 if ( is_array( $tree ) ) { 309 $index = 0; 310 $size = count( $tree ); 311 foreach ( $tree as $label => $theme_file ) : 312 $index++; 313 if ( ! is_array( $theme_file ) ) { 314 wp_print_theme_file_tree( $theme_file, $level, $index, $size ); 315 continue; 316 } 317 ?> 318 <li role="treeitem" aria-expanded="true" tabindex="-1" 319 aria-level="<?php echo esc_attr( $level ); ?>" 320 aria-setsize="<?php echo esc_attr( $size ); ?>" 321 aria-posinset="<?php echo esc_attr( $index ); ?>"> 322 <span class="folder-label"><?php echo esc_html( $label ); ?> <span class="screen-reader-text"><?php _e( 'folder' ); ?></span><span aria-hidden="true" class="icon"></span></span> 323 <ul role="group" class="tree-folder"><?php wp_print_theme_file_tree( $theme_file, $level + 1, $index, $size ); ?></ul> 324 </li> 325 <?php 326 endforeach; 327 } else { 328 $filename = $tree; 329 $url = add_query_arg( 330 array( 331 'file' => rawurlencode( $tree ), 332 'theme' => rawurlencode( $stylesheet ), 333 ), 334 admin_url( 'theme-editor.php' ) 335 ); 336 ?> 337 <li role="none" class="<?php echo esc_attr( $relative_file === $filename ? 'current-file' : '' ); ?>"> 338 <a role="treeitem" tabindex="<?php echo esc_attr( $relative_file === $filename ? '0' : '-1' ); ?>" 339 href="<?php echo esc_url( $url ); ?>" 340 aria-level="<?php echo esc_attr( $level ); ?>" 341 aria-setsize="<?php echo esc_attr( $size ); ?>" 342 aria-posinset="<?php echo esc_attr( $index ); ?>"> 343 <?php 344 $file_description = esc_html( get_file_description( $filename ) ); 345 if ( $file_description !== $filename && basename( $filename ) !== $file_description ) { 346 $file_description .= '<br /><span class="nonessential">(' . esc_html( $filename ) . ')</span>'; 347 } 348 349 if ( $relative_file === $filename ) { 350 echo '<span class="notice notice-info">' . $file_description . '</span>'; 351 } else { 352 echo $file_description; 353 } 354 ?> 355 </a> 356 </li> 357 <?php 358 } 359 } 360 361 /** 362 * Makes a tree structure for the Plugin Editor's file list. 363 * 364 * @since 4.9.0 365 * @access private 366 * 367 * @param string $plugin_editable_files List of plugin file paths. 368 * @return array Tree structure for listing plugin files. 369 */ 370 function wp_make_plugin_file_tree( $plugin_editable_files ) { 371 $tree_list = array(); 372 foreach ( $plugin_editable_files as $plugin_file ) { 373 $list = explode( '/', preg_replace( '#^.+?/#', '', $plugin_file ) ); 374 $last_dir = &$tree_list; 375 foreach ( $list as $dir ) { 376 $last_dir =& $last_dir[ $dir ]; 377 } 378 $last_dir = $plugin_file; 379 } 380 return $tree_list; 381 } 382 383 /** 384 * Outputs the formatted file list for the Plugin Editor. 385 * 386 * @since 4.9.0 387 * @access private 388 * 389 * @param array|string $tree List of file/folder paths, or filename. 390 * @param string $label Name of file or folder to print. 391 * @param int $level The aria-level for the current iteration. 392 * @param int $size The aria-setsize for the current iteration. 393 * @param int $index The aria-posinset for the current iteration. 394 */ 395 function wp_print_plugin_file_tree( $tree, $label = '', $level = 2, $size = 1, $index = 1 ) { 396 global $file, $plugin; 397 if ( is_array( $tree ) ) { 398 $index = 0; 399 $size = count( $tree ); 400 foreach ( $tree as $label => $plugin_file ) : 401 $index++; 402 if ( ! is_array( $plugin_file ) ) { 403 wp_print_plugin_file_tree( $plugin_file, $label, $level, $index, $size ); 404 continue; 405 } 406 ?> 407 <li role="treeitem" aria-expanded="true" tabindex="-1" 408 aria-level="<?php echo esc_attr( $level ); ?>" 409 aria-setsize="<?php echo esc_attr( $size ); ?>" 410 aria-posinset="<?php echo esc_attr( $index ); ?>"> 411 <span class="folder-label"><?php echo esc_html( $label ); ?> <span class="screen-reader-text"><?php _e( 'folder' ); ?></span><span aria-hidden="true" class="icon"></span></span> 412 <ul role="group" class="tree-folder"><?php wp_print_plugin_file_tree( $plugin_file, '', $level + 1, $index, $size ); ?></ul> 413 </li> 414 <?php 415 endforeach; 416 } else { 417 $url = add_query_arg( 418 array( 419 'file' => rawurlencode( $tree ), 420 'plugin' => rawurlencode( $plugin ), 421 ), 422 admin_url( 'plugin-editor.php' ) 423 ); 424 ?> 425 <li role="none" class="<?php echo esc_attr( $file === $tree ? 'current-file' : '' ); ?>"> 426 <a role="treeitem" tabindex="<?php echo esc_attr( $file === $tree ? '0' : '-1' ); ?>" 427 href="<?php echo esc_url( $url ); ?>" 428 aria-level="<?php echo esc_attr( $level ); ?>" 429 aria-setsize="<?php echo esc_attr( $size ); ?>" 430 aria-posinset="<?php echo esc_attr( $index ); ?>"> 431 <?php 432 if ( $file === $tree ) { 433 echo '<span class="notice notice-info">' . esc_html( $label ) . '</span>'; 434 } else { 435 echo esc_html( $label ); 436 } 437 ?> 438 </a> 439 </li> 440 <?php 441 } 270 442 } 271 443 -
trunk/src/wp-admin/js/theme-plugin-editor.js
r41805 r41851 7 7 wp.themePluginEditor = (function( $ ) { 8 8 'use strict'; 9 10 var component = { 9 var component, TreeLinks; 10 11 component = { 11 12 l10n: { 12 13 lintError: { … … 67 68 } 68 69 70 $( component.initFileBrowser ); 71 69 72 $( window ).on( 'beforeunload', function() { 70 73 if ( component.dirty ) { … … 87 90 }); 88 91 89 // hide modal92 // Hide modal. 90 93 component.warning.remove(); 91 94 $( 'body' ).removeClass( 'modal-open' ); 92 95 93 // return focus - is this a trap?96 // Return focus - is this a trap? 94 97 component.instance.codemirror.focus(); 95 98 }; … … 149 152 } 150 153 151 request.done( function 154 request.done( function( response ) { 152 155 component.lastSaveNoticeCode = 'file_saved'; 153 156 component.addNotice({ … … 160 163 } ); 161 164 162 request.fail( function 165 request.fail( function( response ) { 163 166 var notice = $.extend( 164 167 { … … 351 354 }; 352 355 356 /** 357 * Initialization of the file browser's folder states. 358 * 359 * @since 4.9.0 360 * @returns {void} 361 */ 362 component.initFileBrowser = function initFileBrowser() { 363 364 var $templateside = $( '#templateside' ); 365 366 // Collapse all folders. 367 $templateside.find( '[role="group"]' ).parent().attr( 'aria-expanded', false ); 368 369 // Expand ancestors to the current file. 370 $templateside.find( '.notice' ).parents( '[aria-expanded]' ).attr( 'aria-expanded', true ); 371 372 // Find Tree elements and enhance them. 373 $templateside.find( '[role="tree"]' ).each( function() { 374 var treeLinks = new TreeLinks( this ); 375 treeLinks.init(); 376 } ); 377 378 // Scroll the current file into view. 379 $templateside.find( '.current-file' ).each( function() { 380 this.scrollIntoView( false ); 381 } ); 382 }; 383 384 /* jshint ignore:start */ 385 /* jscs:disable */ 386 /* eslint-disable */ 387 388 /** 389 * Creates a new TreeitemLink. 390 * 391 * @since 4.9.0 392 * @class 393 * @private 394 * @see {@link https://www.w3.org/TR/wai-aria-practices-1.1/examples/treeview/treeview-2/treeview-2b.html|W3C Treeview Example} 395 * @license W3C-20150513 396 */ 397 var TreeitemLink = (function () { 398 /** 399 * This content is licensed according to the W3C Software License at 400 * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document 401 * 402 * File: TreeitemLink.js 403 * 404 * Desc: Treeitem widget that implements ARIA Authoring Practices 405 * for a tree being used as a file viewer 406 * 407 * Author: Jon Gunderson, Ku Ja Eun and Nicholas Hoyt 408 */ 409 410 /** 411 * @constructor 412 * 413 * @desc 414 * Treeitem object for representing the state and user interactions for a 415 * treeItem widget 416 * 417 * @param node 418 * An element with the role=tree attribute 419 */ 420 421 var TreeitemLink = function (node, treeObj, group) { 422 423 // Check whether node is a DOM element 424 if (typeof node !== 'object') { 425 return; 426 } 427 428 node.tabIndex = -1; 429 this.tree = treeObj; 430 this.groupTreeitem = group; 431 this.domNode = node; 432 this.label = node.textContent.trim(); 433 this.stopDefaultClick = false; 434 435 if (node.getAttribute('aria-label')) { 436 this.label = node.getAttribute('aria-label').trim(); 437 } 438 439 this.isExpandable = false; 440 this.isVisible = false; 441 this.inGroup = false; 442 443 if (group) { 444 this.inGroup = true; 445 } 446 447 var elem = node.firstElementChild; 448 449 while (elem) { 450 451 if (elem.tagName.toLowerCase() == 'ul') { 452 elem.setAttribute('role', 'group'); 453 this.isExpandable = true; 454 break; 455 } 456 457 elem = elem.nextElementSibling; 458 } 459 460 this.keyCode = Object.freeze({ 461 RETURN: 13, 462 SPACE: 32, 463 PAGEUP: 33, 464 PAGEDOWN: 34, 465 END: 35, 466 HOME: 36, 467 LEFT: 37, 468 UP: 38, 469 RIGHT: 39, 470 DOWN: 40 471 }); 472 }; 473 474 TreeitemLink.prototype.init = function () { 475 this.domNode.tabIndex = -1; 476 477 if (!this.domNode.getAttribute('role')) { 478 this.domNode.setAttribute('role', 'treeitem'); 479 } 480 481 this.domNode.addEventListener('keydown', this.handleKeydown.bind(this)); 482 this.domNode.addEventListener('click', this.handleClick.bind(this)); 483 this.domNode.addEventListener('focus', this.handleFocus.bind(this)); 484 this.domNode.addEventListener('blur', this.handleBlur.bind(this)); 485 486 if (this.isExpandable) { 487 this.domNode.firstElementChild.addEventListener('mouseover', this.handleMouseOver.bind(this)); 488 this.domNode.firstElementChild.addEventListener('mouseout', this.handleMouseOut.bind(this)); 489 } 490 else { 491 this.domNode.addEventListener('mouseover', this.handleMouseOver.bind(this)); 492 this.domNode.addEventListener('mouseout', this.handleMouseOut.bind(this)); 493 } 494 }; 495 496 TreeitemLink.prototype.isExpanded = function () { 497 498 if (this.isExpandable) { 499 return this.domNode.getAttribute('aria-expanded') === 'true'; 500 } 501 502 return false; 503 504 }; 505 506 /* EVENT HANDLERS */ 507 508 TreeitemLink.prototype.handleKeydown = function (event) { 509 var tgt = event.currentTarget, 510 flag = false, 511 _char = event.key, 512 clickEvent; 513 514 function isPrintableCharacter(str) { 515 return str.length === 1 && str.match(/\S/); 516 } 517 518 function printableCharacter(item) { 519 if (_char == '*') { 520 item.tree.expandAllSiblingItems(item); 521 flag = true; 522 } 523 else { 524 if (isPrintableCharacter(_char)) { 525 item.tree.setFocusByFirstCharacter(item, _char); 526 flag = true; 527 } 528 } 529 } 530 531 this.stopDefaultClick = false; 532 533 if (event.altKey || event.ctrlKey || event.metaKey) { 534 return; 535 } 536 537 if (event.shift) { 538 if (event.keyCode == this.keyCode.SPACE || event.keyCode == this.keyCode.RETURN) { 539 event.stopPropagation(); 540 this.stopDefaultClick = true; 541 } 542 else { 543 if (isPrintableCharacter(_char)) { 544 printableCharacter(this); 545 } 546 } 547 } 548 else { 549 switch (event.keyCode) { 550 case this.keyCode.SPACE: 551 case this.keyCode.RETURN: 552 if (this.isExpandable) { 553 if (this.isExpanded()) { 554 this.tree.collapseTreeitem(this); 555 } 556 else { 557 this.tree.expandTreeitem(this); 558 } 559 flag = true; 560 } 561 else { 562 event.stopPropagation(); 563 this.stopDefaultClick = true; 564 } 565 break; 566 567 case this.keyCode.UP: 568 this.tree.setFocusToPreviousItem(this); 569 flag = true; 570 break; 571 572 case this.keyCode.DOWN: 573 this.tree.setFocusToNextItem(this); 574 flag = true; 575 break; 576 577 case this.keyCode.RIGHT: 578 if (this.isExpandable) { 579 if (this.isExpanded()) { 580 this.tree.setFocusToNextItem(this); 581 } 582 else { 583 this.tree.expandTreeitem(this); 584 } 585 } 586 flag = true; 587 break; 588 589 case this.keyCode.LEFT: 590 if (this.isExpandable && this.isExpanded()) { 591 this.tree.collapseTreeitem(this); 592 flag = true; 593 } 594 else { 595 if (this.inGroup) { 596 this.tree.setFocusToParentItem(this); 597 flag = true; 598 } 599 } 600 break; 601 602 case this.keyCode.HOME: 603 this.tree.setFocusToFirstItem(); 604 flag = true; 605 break; 606 607 case this.keyCode.END: 608 this.tree.setFocusToLastItem(); 609 flag = true; 610 break; 611 612 default: 613 if (isPrintableCharacter(_char)) { 614 printableCharacter(this); 615 } 616 break; 617 } 618 } 619 620 if (flag) { 621 event.stopPropagation(); 622 event.preventDefault(); 623 } 624 }; 625 626 TreeitemLink.prototype.handleClick = function (event) { 627 628 // only process click events that directly happened on this treeitem 629 if (event.target !== this.domNode && event.target !== this.domNode.firstElementChild) { 630 return; 631 } 632 633 if (this.isExpandable) { 634 if (this.isExpanded()) { 635 this.tree.collapseTreeitem(this); 636 } 637 else { 638 this.tree.expandTreeitem(this); 639 } 640 event.stopPropagation(); 641 } 642 }; 643 644 TreeitemLink.prototype.handleFocus = function (event) { 645 var node = this.domNode; 646 if (this.isExpandable) { 647 node = node.firstElementChild; 648 } 649 node.classList.add('focus'); 650 }; 651 652 TreeitemLink.prototype.handleBlur = function (event) { 653 var node = this.domNode; 654 if (this.isExpandable) { 655 node = node.firstElementChild; 656 } 657 node.classList.remove('focus'); 658 }; 659 660 TreeitemLink.prototype.handleMouseOver = function (event) { 661 event.currentTarget.classList.add('hover'); 662 }; 663 664 TreeitemLink.prototype.handleMouseOut = function (event) { 665 event.currentTarget.classList.remove('hover'); 666 }; 667 668 return TreeitemLink; 669 })(); 670 671 /** 672 * Creates a new TreeLinks. 673 * 674 * @since 4.9.0 675 * @class 676 * @private 677 * @see {@link https://www.w3.org/TR/wai-aria-practices-1.1/examples/treeview/treeview-2/treeview-2b.html|W3C Treeview Example} 678 * @license W3C-20150513 679 */ 680 TreeLinks = (function () { 681 /* 682 * This content is licensed according to the W3C Software License at 683 * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document 684 * 685 * File: TreeLinks.js 686 * 687 * Desc: Tree widget that implements ARIA Authoring Practices 688 * for a tree being used as a file viewer 689 * 690 * Author: Jon Gunderson, Ku Ja Eun and Nicholas Hoyt 691 */ 692 693 /* 694 * @constructor 695 * 696 * @desc 697 * Tree item object for representing the state and user interactions for a 698 * tree widget 699 * 700 * @param node 701 * An element with the role=tree attribute 702 */ 703 704 var TreeLinks = function (node) { 705 // Check whether node is a DOM element 706 if (typeof node !== 'object') { 707 return; 708 } 709 710 this.domNode = node; 711 712 this.treeitems = []; 713 this.firstChars = []; 714 715 this.firstTreeitem = null; 716 this.lastTreeitem = null; 717 718 }; 719 720 TreeLinks.prototype.init = function () { 721 722 function findTreeitems(node, tree, group) { 723 724 var elem = node.firstElementChild; 725 var ti = group; 726 727 while (elem) { 728 729 if ((elem.tagName.toLowerCase() === 'li' && elem.firstElementChild.tagName.toLowerCase() === 'span') || elem.tagName.toLowerCase() === 'a') { 730 ti = new TreeitemLink(elem, tree, group); 731 ti.init(); 732 tree.treeitems.push(ti); 733 tree.firstChars.push(ti.label.substring(0, 1).toLowerCase()); 734 } 735 736 if (elem.firstElementChild) { 737 findTreeitems(elem, tree, ti); 738 } 739 740 elem = elem.nextElementSibling; 741 } 742 } 743 744 // initialize pop up menus 745 if (!this.domNode.getAttribute('role')) { 746 this.domNode.setAttribute('role', 'tree'); 747 } 748 749 findTreeitems(this.domNode, this, false); 750 751 this.updateVisibleTreeitems(); 752 753 this.firstTreeitem.domNode.tabIndex = 0; 754 755 }; 756 757 TreeLinks.prototype.setFocusToItem = function (treeitem) { 758 759 for (var i = 0; i < this.treeitems.length; i++) { 760 var ti = this.treeitems[i]; 761 762 if (ti === treeitem) { 763 ti.domNode.tabIndex = 0; 764 ti.domNode.focus(); 765 } 766 else { 767 ti.domNode.tabIndex = -1; 768 } 769 } 770 771 }; 772 773 TreeLinks.prototype.setFocusToNextItem = function (currentItem) { 774 775 var nextItem = false; 776 777 for (var i = (this.treeitems.length - 1); i >= 0; i--) { 778 var ti = this.treeitems[i]; 779 if (ti === currentItem) { 780 break; 781 } 782 if (ti.isVisible) { 783 nextItem = ti; 784 } 785 } 786 787 if (nextItem) { 788 this.setFocusToItem(nextItem); 789 } 790 791 }; 792 793 TreeLinks.prototype.setFocusToPreviousItem = function (currentItem) { 794 795 var prevItem = false; 796 797 for (var i = 0; i < this.treeitems.length; i++) { 798 var ti = this.treeitems[i]; 799 if (ti === currentItem) { 800 break; 801 } 802 if (ti.isVisible) { 803 prevItem = ti; 804 } 805 } 806 807 if (prevItem) { 808 this.setFocusToItem(prevItem); 809 } 810 }; 811 812 TreeLinks.prototype.setFocusToParentItem = function (currentItem) { 813 814 if (currentItem.groupTreeitem) { 815 this.setFocusToItem(currentItem.groupTreeitem); 816 } 817 }; 818 819 TreeLinks.prototype.setFocusToFirstItem = function () { 820 this.setFocusToItem(this.firstTreeitem); 821 }; 822 823 TreeLinks.prototype.setFocusToLastItem = function () { 824 this.setFocusToItem(this.lastTreeitem); 825 }; 826 827 TreeLinks.prototype.expandTreeitem = function (currentItem) { 828 829 if (currentItem.isExpandable) { 830 currentItem.domNode.setAttribute('aria-expanded', true); 831 this.updateVisibleTreeitems(); 832 } 833 834 }; 835 836 TreeLinks.prototype.expandAllSiblingItems = function (currentItem) { 837 for (var i = 0; i < this.treeitems.length; i++) { 838 var ti = this.treeitems[i]; 839 840 if ((ti.groupTreeitem === currentItem.groupTreeitem) && ti.isExpandable) { 841 this.expandTreeitem(ti); 842 } 843 } 844 845 }; 846 847 TreeLinks.prototype.collapseTreeitem = function (currentItem) { 848 849 var groupTreeitem = false; 850 851 if (currentItem.isExpanded()) { 852 groupTreeitem = currentItem; 853 } 854 else { 855 groupTreeitem = currentItem.groupTreeitem; 856 } 857 858 if (groupTreeitem) { 859 groupTreeitem.domNode.setAttribute('aria-expanded', false); 860 this.updateVisibleTreeitems(); 861 this.setFocusToItem(groupTreeitem); 862 } 863 864 }; 865 866 TreeLinks.prototype.updateVisibleTreeitems = function () { 867 868 this.firstTreeitem = this.treeitems[0]; 869 870 for (var i = 0; i < this.treeitems.length; i++) { 871 var ti = this.treeitems[i]; 872 873 var parent = ti.domNode.parentNode; 874 875 ti.isVisible = true; 876 877 while (parent && (parent !== this.domNode)) { 878 879 if (parent.getAttribute('aria-expanded') == 'false') { 880 ti.isVisible = false; 881 } 882 parent = parent.parentNode; 883 } 884 885 if (ti.isVisible) { 886 this.lastTreeitem = ti; 887 } 888 } 889 890 }; 891 892 TreeLinks.prototype.setFocusByFirstCharacter = function (currentItem, _char) { 893 var start, index; 894 _char = _char.toLowerCase(); 895 896 // Get start index for search based on position of currentItem 897 start = this.treeitems.indexOf(currentItem) + 1; 898 if (start === this.treeitems.length) { 899 start = 0; 900 } 901 902 // Check remaining slots in the menu 903 index = this.getIndexFirstChars(start, _char); 904 905 // If not found in remaining slots, check from beginning 906 if (index === -1) { 907 index = this.getIndexFirstChars(0, _char); 908 } 909 910 // If match was found... 911 if (index > -1) { 912 this.setFocusToItem(this.treeitems[index]); 913 } 914 }; 915 916 TreeLinks.prototype.getIndexFirstChars = function (startIndex, _char) { 917 for (var i = startIndex; i < this.firstChars.length; i++) { 918 if (this.treeitems[i].isVisible) { 919 if (_char === this.firstChars[i]) { 920 return i; 921 } 922 } 923 } 924 return -1; 925 }; 926 927 return TreeLinks; 928 })(); 929 930 /* jshint ignore:end */ 931 /* jscs:enable */ 932 /* eslint-enable */ 933 353 934 return component; 354 935 })( jQuery ); -
trunk/src/wp-admin/plugin-editor.php
r41774 r41851 232 232 233 233 <div id="templateside"> 234 <h2 ><?php _e( 'Plugin Files' ); ?></h2>234 <h2 id="plugin-files-label"><?php _e( 'Plugin Files' ); ?></h2> 235 235 236 236 <?php … … 242 242 } 243 243 ?> 244 <ul> 245 <?php foreach ( $plugin_editable_files as $plugin_file ) : ?> 246 <li class="<?php echo esc_attr( $file === $plugin_file ? 'notice notice-info' : '' ); ?>"> 247 <a href="plugin-editor.php?file=<?php echo urlencode( $plugin_file ); ?>&plugin=<?php echo urlencode( $plugin ); ?>"><?php echo esc_html( preg_replace( '#^.+?/#', '', $plugin_file ) ); ?></a> 248 </li> 249 <?php endforeach; ?> 244 <ul role="tree" aria-labelledby="plugin-files-label"> 245 <li role="treeitem" tabindex="-1" aria-expanded="true" 246 aria-level="1" 247 aria-posinset="1" 248 aria-setsize="1"> 249 <ul role="group" style="padding-left: 0;"> 250 <?php wp_print_plugin_file_tree( wp_make_plugin_file_tree( $plugin_editable_files ) ); ?> 251 </ul> 250 252 </ul> 251 253 </div> -
trunk/src/wp-admin/theme-editor.php
r41806 r41851 88 88 break; 89 89 } 90 } 91 92 // Move functions.php and style.css to the top. 93 if ( isset( $allowed_files['functions.php'] ) ) { 94 $allowed_files = array( 'functions.php' => $allowed_files['functions.php'] ) + $allowed_files; 95 } 96 if ( isset( $allowed_files['style.css'] ) ) { 97 $allowed_files = array( 'style.css' => $allowed_files['style.css'] ) + $allowed_files; 90 98 } 91 99 … … 206 214 echo '<div class="error"><p><strong>' . __( 'This theme is broken.' ) . '</strong> ' . $theme->errors()->get_error_message() . '</p></div>'; 207 215 ?> 208 <div id="templateside"> 209 <?php 210 if ( $allowed_files ) : 211 $previous_file_type = ''; 212 213 foreach ( $allowed_files as $filename => $absolute_filename ) : 214 $file_type = substr( $filename, strrpos( $filename, '.' ) ); 215 216 if ( $file_type !== $previous_file_type ) { 217 if ( '' !== $previous_file_type ) { 218 echo "\t</ul>\n"; 219 } 220 221 switch ( $file_type ) { 222 case '.php': 223 if ( $has_templates || $theme->parent() ) : 224 echo "\t<h2>" . __( 'Templates' ) . "</h2>\n"; 225 if ( $theme->parent() ) { 226 echo '<p class="howto">' . sprintf( __( 'This child theme inherits templates from a parent theme, %s.' ), 227 sprintf( '<a href="%s">%s</a>', 228 self_admin_url( 'theme-editor.php?theme=' . urlencode( $theme->get_template() ) ), 229 $theme->parent()->display( 'Name' ) 230 ) 231 ) . "</p>\n"; 232 } 233 endif; 234 break; 235 case '.css': 236 echo "\t<h2>" . _x( 'Styles', 'Theme stylesheets in theme editor' ) . "</h2>\n"; 237 break; 238 default: 239 /* translators: %s: file extension */ 240 echo "\t<h2>" . sprintf( __( '%s files' ), $file_type ) . "</h2>\n"; 241 break; 242 } 243 244 echo "\t<ul>\n"; 216 <div id="templateside"> 217 <h2 id="theme-files-label"><?php _e( 'Theme Files' ); ?></h2> 218 <?php 219 if ( $has_templates || $theme->parent() ) : 220 if ( $theme->parent() ) { 221 /* translators: %s: link to edit parent theme */ 222 echo '<p class="howto">' . sprintf( __( 'This child theme inherits templates from a parent theme, %s.' ), 223 sprintf( '<a href="%s">%s</a>', 224 self_admin_url( 'theme-editor.php?theme=' . urlencode( $theme->get_template() ) ), 225 $theme->parent()->display( 'Name' ) 226 ) 227 ) . "</p>\n"; 245 228 } 246 247 $file_description = esc_html( get_file_description( $filename ) ); 248 if ( $filename !== basename( $absolute_filename ) || $file_description !== $filename ) { 249 $file_description .= '<br /><span class="nonessential">(' . esc_html( $filename ) . ')</span>'; 250 } 251 252 if ( $absolute_filename === $file ) { 253 $file_description = '<span class="notice notice-info">' . $file_description . '</span>'; 254 } 255 256 $previous_file_type = $file_type; 257 ?> 258 <li><a href="theme-editor.php?file=<?php echo urlencode( $filename ) ?>&theme=<?php echo urlencode( $stylesheet ) ?>"><?php echo $file_description; ?></a></li> 259 <?php 260 endforeach; 261 ?> 262 </ul> 263 <?php endif; ?> 264 </div> 229 endif; 230 ?> 231 <ul role="tree" aria-labelledby="theme-files-label"> 232 <li role="treeitem" tabindex="-1" aria-expanded="true" 233 aria-level="1" 234 aria-posinset="1" 235 aria-setsize="1"> 236 <ul role="group" style="padding-left: 0;"> 237 <?php wp_print_theme_file_tree( wp_make_theme_file_tree( $allowed_files ) ); ?> 238 </ul> 239 </li> 240 </ul> 241 </div> 242 265 243 <?php if ( $error ) : 266 244 echo '<div class="error"><p>' . __('Oops, no such file exists! Double check the name and try again, merci.') . '</p></div>';
Note: See TracChangeset
for help on using the changeset viewer.