home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress / wp-admin / js / common.js < prev    next >
Encoding:
JavaScript  |  2017-10-24  |  32.1 KB  |  1,153 lines

  1. /* global setUserSetting, ajaxurl, commonL10n, alert, confirm, pagenow */
  2. var showNotice, adminMenu, columns, validateForm, screenMeta;
  3. ( function( $, window, undefined ) {
  4.     var $document = $( document ),
  5.         $window = $( window ),
  6.         $body = $( document.body );
  7.  
  8. // Removed in 3.3.
  9. // (perhaps) needed for back-compat
  10. adminMenu = {
  11.     init : function() {},
  12.     fold : function() {},
  13.     restoreMenuState : function() {},
  14.     toggle : function() {},
  15.     favorites : function() {}
  16. };
  17.  
  18. // show/hide/save table columns
  19. columns = {
  20.     init : function() {
  21.         var that = this;
  22.         $('.hide-column-tog', '#adv-settings').click( function() {
  23.             var $t = $(this), column = $t.val();
  24.             if ( $t.prop('checked') )
  25.                 that.checked(column);
  26.             else
  27.                 that.unchecked(column);
  28.  
  29.             columns.saveManageColumnsState();
  30.         });
  31.     },
  32.  
  33.     saveManageColumnsState : function() {
  34.         var hidden = this.hidden();
  35.         $.post(ajaxurl, {
  36.             action: 'hidden-columns',
  37.             hidden: hidden,
  38.             screenoptionnonce: $('#screenoptionnonce').val(),
  39.             page: pagenow
  40.         });
  41.     },
  42.  
  43.     checked : function(column) {
  44.         $('.column-' + column).removeClass( 'hidden' );
  45.         this.colSpanChange(+1);
  46.     },
  47.  
  48.     unchecked : function(column) {
  49.         $('.column-' + column).addClass( 'hidden' );
  50.         this.colSpanChange(-1);
  51.     },
  52.  
  53.     hidden : function() {
  54.         return $( '.manage-column[id]' ).filter( ':hidden' ).map(function() {
  55.             return this.id;
  56.         }).get().join( ',' );
  57.     },
  58.  
  59.     useCheckboxesForHidden : function() {
  60.         this.hidden = function(){
  61.             return $('.hide-column-tog').not(':checked').map(function() {
  62.                 var id = this.id;
  63.                 return id.substring( id, id.length - 5 );
  64.             }).get().join(',');
  65.         };
  66.     },
  67.  
  68.     colSpanChange : function(diff) {
  69.         var $t = $('table').find('.colspanchange'), n;
  70.         if ( !$t.length )
  71.             return;
  72.         n = parseInt( $t.attr('colspan'), 10 ) + diff;
  73.         $t.attr('colspan', n.toString());
  74.     }
  75. };
  76.  
  77. $document.ready(function(){columns.init();});
  78.  
  79. validateForm = function( form ) {
  80.     return !$( form )
  81.         .find( '.form-required' )
  82.         .filter( function() { return $( ':input:visible', this ).val() === ''; } )
  83.         .addClass( 'form-invalid' )
  84.         .find( ':input:visible' )
  85.         .change( function() { $( this ).closest( '.form-invalid' ).removeClass( 'form-invalid' ); } )
  86.         .length;
  87. };
  88.  
  89. // stub for doing better warnings
  90. showNotice = {
  91.     warn : function() {
  92.         var msg = commonL10n.warnDelete || '';
  93.         if ( confirm(msg) ) {
  94.             return true;
  95.         }
  96.  
  97.         return false;
  98.     },
  99.  
  100.     note : function(text) {
  101.         alert(text);
  102.     }
  103. };
  104.  
  105. screenMeta = {
  106.     element: null, // #screen-meta
  107.     toggles: null, // .screen-meta-toggle
  108.     page:    null, // #wpcontent
  109.  
  110.     init: function() {
  111.         this.element = $('#screen-meta');
  112.         this.toggles = $( '#screen-meta-links' ).find( '.show-settings' );
  113.         this.page    = $('#wpcontent');
  114.  
  115.         this.toggles.click( this.toggleEvent );
  116.     },
  117.  
  118.     toggleEvent: function() {
  119.         var panel = $( '#' + $( this ).attr( 'aria-controls' ) );
  120.  
  121.         if ( !panel.length )
  122.             return;
  123.  
  124.         if ( panel.is(':visible') )
  125.             screenMeta.close( panel, $(this) );
  126.         else
  127.             screenMeta.open( panel, $(this) );
  128.     },
  129.  
  130.     open: function( panel, button ) {
  131.  
  132.         $( '#screen-meta-links' ).find( '.screen-meta-toggle' ).not( button.parent() ).css( 'visibility', 'hidden' );
  133.  
  134.         panel.parent().show();
  135.         panel.slideDown( 'fast', function() {
  136.             panel.focus();
  137.             button.addClass( 'screen-meta-active' ).attr( 'aria-expanded', true );
  138.         });
  139.  
  140.         $document.trigger( 'screen:options:open' );
  141.     },
  142.  
  143.     close: function( panel, button ) {
  144.         panel.slideUp( 'fast', function() {
  145.             button.removeClass( 'screen-meta-active' ).attr( 'aria-expanded', false );
  146.             $('.screen-meta-toggle').css('visibility', '');
  147.             panel.parent().hide();
  148.         });
  149.  
  150.         $document.trigger( 'screen:options:close' );
  151.     }
  152. };
  153.  
  154. /**
  155.  * Help tabs.
  156.  */
  157. $('.contextual-help-tabs').delegate('a', 'click', function(e) {
  158.     var link = $(this),
  159.         panel;
  160.  
  161.     e.preventDefault();
  162.  
  163.     // Don't do anything if the click is for the tab already showing.
  164.     if ( link.is('.active a') )
  165.         return false;
  166.  
  167.     // Links
  168.     $('.contextual-help-tabs .active').removeClass('active');
  169.     link.parent('li').addClass('active');
  170.  
  171.     panel = $( link.attr('href') );
  172.  
  173.     // Panels
  174.     $('.help-tab-content').not( panel ).removeClass('active').hide();
  175.     panel.addClass('active').show();
  176. });
  177.  
  178. /**
  179.  * Update custom permalink structure via buttons.
  180.  */
  181.  
  182. var permalinkStructureFocused = false,
  183.     $permalinkStructure       = $( '#permalink_structure' ),
  184.     $permalinkStructureInputs = $( '.permalink-structure input:radio' ),
  185.     $permalinkCustomSelection = $( '#custom_selection' ),
  186.     $availableStructureTags   = $( '.form-table.permalink-structure .available-structure-tags button' );
  187.  
  188. // Change permalink structure input when selecting one of the common structures.
  189. $permalinkStructureInputs.on( 'change', function() {
  190.     if ( 'custom' === this.value ) {
  191.         return;
  192.     }
  193.  
  194.     $permalinkStructure.val( this.value );
  195.  
  196.     // Update button states after selection.
  197.     $availableStructureTags.each( function() {
  198.         changeStructureTagButtonState( $( this ) );
  199.     } );
  200. } );
  201.  
  202. $permalinkStructure.on( 'click input', function() {
  203.     $permalinkCustomSelection.prop( 'checked', true );
  204. } );
  205.  
  206. // Check if the permalink structure input field has had focus at least once.
  207. $permalinkStructure.on( 'focus', function( event ) {
  208.     permalinkStructureFocused = true;
  209.     $( this ).off( event );
  210. } );
  211.  
  212. /**
  213.  * Enables or disables a structure tag button depending on its usage.
  214.  *
  215.  * If the structure is already used in the custom permalink structure,
  216.  * it will be disabled.
  217.  *
  218.  * @param {object} button Button jQuery object.
  219.  */
  220. function changeStructureTagButtonState( button ) {
  221.     if ( -1 !== $permalinkStructure.val().indexOf( button.text().trim() ) ) {
  222.         button.attr( 'data-label', button.attr( 'aria-label' ) );
  223.         button.attr( 'aria-label', button.attr( 'data-used' ) );
  224.         button.attr( 'aria-pressed', true );
  225.         button.addClass( 'active' );
  226.     } else if ( button.attr( 'data-label' ) ) {
  227.         button.attr( 'aria-label', button.attr( 'data-label' ) );
  228.         button.attr( 'aria-pressed', false );
  229.         button.removeClass( 'active' );
  230.     }
  231. }
  232.  
  233. // Check initial button state.
  234. $availableStructureTags.each( function() {
  235.     changeStructureTagButtonState( $( this ) );
  236. } );
  237.  
  238. // Observe permalink structure field and disable buttons of tags that are already present.
  239. $permalinkStructure.on( 'change', function() {
  240.     $availableStructureTags.each( function() {
  241.         changeStructureTagButtonState( $( this ) );
  242.     } );
  243. } );
  244.  
  245. $availableStructureTags.on( 'click', function() {
  246.     var permalinkStructureValue = $permalinkStructure.val(),
  247.         selectionStart          = $permalinkStructure[ 0 ].selectionStart,
  248.         selectionEnd            = $permalinkStructure[ 0 ].selectionEnd,
  249.         textToAppend            = $( this ).text().trim(),
  250.         textToAnnounce          = $( this ).attr( 'data-added' ),
  251.         newSelectionStart;
  252.  
  253.     // Remove structure tag if already part of the structure.
  254.     if ( -1 !== permalinkStructureValue.indexOf( textToAppend ) ) {
  255.         permalinkStructureValue = permalinkStructureValue.replace( textToAppend + '/', '' );
  256.  
  257.         $permalinkStructure.val( '/' === permalinkStructureValue ? '' : permalinkStructureValue );
  258.  
  259.         // Announce change to screen readers.
  260.         $( '#custom_selection_updated' ).text( textToAnnounce );
  261.  
  262.         // Disable button.
  263.         changeStructureTagButtonState( $( this ) );
  264.  
  265.         return;
  266.     }
  267.  
  268.     // Input field never had focus, move selection to end of input.
  269.     if ( ! permalinkStructureFocused && 0 === selectionStart && 0 === selectionEnd ) {
  270.         selectionStart = selectionEnd = permalinkStructureValue.length;
  271.     }
  272.  
  273.     $permalinkCustomSelection.prop( 'checked', true );
  274.  
  275.     // Prepend and append slashes if necessary.
  276.     if ( '/' !== permalinkStructureValue.substr( 0, selectionStart ).substr( -1 ) ) {
  277.         textToAppend = '/' + textToAppend;
  278.     }
  279.  
  280.     if ( '/' !== permalinkStructureValue.substr( selectionEnd, 1 ) ) {
  281.         textToAppend = textToAppend + '/';
  282.     }
  283.  
  284.     // Insert structure tag at the specified position.
  285.     $permalinkStructure.val( permalinkStructureValue.substr( 0, selectionStart ) + textToAppend + permalinkStructureValue.substr( selectionEnd ) );
  286.  
  287.     // Announce change to screen readers.
  288.     $( '#custom_selection_updated' ).text( textToAnnounce );
  289.  
  290.     // Disable button.
  291.     changeStructureTagButtonState( $( this ) );
  292.  
  293.     // If input had focus give it back with cursor right after appended text.
  294.     if ( permalinkStructureFocused && $permalinkStructure[0].setSelectionRange ) {
  295.         newSelectionStart = ( permalinkStructureValue.substr( 0, selectionStart ) + textToAppend ).length;
  296.         $permalinkStructure[0].setSelectionRange( newSelectionStart, newSelectionStart );
  297.         $permalinkStructure.focus();
  298.     }
  299. } );
  300.  
  301. $document.ready( function() {
  302.     var checks, first, last, checked, sliced, mobileEvent, transitionTimeout, focusedRowActions,
  303.         lastClicked = false,
  304.         pageInput = $('input.current-page'),
  305.         currentPage = pageInput.val(),
  306.         isIOS = /iPhone|iPad|iPod/.test( navigator.userAgent ),
  307.         isAndroid = navigator.userAgent.indexOf( 'Android' ) !== -1,
  308.         isIE8 = $( document.documentElement ).hasClass( 'ie8' ),
  309.         $adminMenuWrap = $( '#adminmenuwrap' ),
  310.         $wpwrap = $( '#wpwrap' ),
  311.         $adminmenu = $( '#adminmenu' ),
  312.         $overlay = $( '#wp-responsive-overlay' ),
  313.         $toolbar = $( '#wp-toolbar' ),
  314.         $toolbarPopups = $toolbar.find( 'a[aria-haspopup="true"]' ),
  315.         $sortables = $('.meta-box-sortables'),
  316.         wpResponsiveActive = false,
  317.         $adminbar = $( '#wpadminbar' ),
  318.         lastScrollPosition = 0,
  319.         pinnedMenuTop = false,
  320.         pinnedMenuBottom = false,
  321.         menuTop = 0,
  322.         menuState,
  323.         menuIsPinned = false,
  324.         height = {
  325.             window: $window.height(),
  326.             wpwrap: $wpwrap.height(),
  327.             adminbar: $adminbar.height(),
  328.             menu: $adminMenuWrap.height()
  329.         },
  330.         $headerEnd = $( '.wp-header-end' );
  331.  
  332.  
  333.     // when the menu is folded, make the fly-out submenu header clickable
  334.     $adminmenu.on('click.wp-submenu-head', '.wp-submenu-head', function(e){
  335.         $(e.target).parent().siblings('a').get(0).click();
  336.     });
  337.  
  338.     $( '#collapse-button' ).on( 'click.collapse-menu', function() {
  339.         var viewportWidth = getViewportWidth() || 961;
  340.  
  341.         // reset any compensation for submenus near the bottom of the screen
  342.         $('#adminmenu div.wp-submenu').css('margin-top', '');
  343.  
  344.         if ( viewportWidth < 960 ) {
  345.             if ( $body.hasClass('auto-fold') ) {
  346.                 $body.removeClass('auto-fold').removeClass('folded');
  347.                 setUserSetting('unfold', 1);
  348.                 setUserSetting('mfold', 'o');
  349.                 menuState = 'open';
  350.             } else {
  351.                 $body.addClass('auto-fold');
  352.                 setUserSetting('unfold', 0);
  353.                 menuState = 'folded';
  354.             }
  355.         } else {
  356.             if ( $body.hasClass('folded') ) {
  357.                 $body.removeClass('folded');
  358.                 setUserSetting('mfold', 'o');
  359.                 menuState = 'open';
  360.             } else {
  361.                 $body.addClass('folded');
  362.                 setUserSetting('mfold', 'f');
  363.                 menuState = 'folded';
  364.             }
  365.         }
  366.  
  367.         $document.trigger( 'wp-collapse-menu', { state: menuState } );
  368.     });
  369.  
  370.     // Handle the `aria-haspopup` attribute on the current menu item when it has a sub-menu.
  371.     function currentMenuItemHasPopup() {
  372.         var $current = $( 'a.wp-has-current-submenu' );
  373.  
  374.         if ( 'folded' === menuState ) {
  375.             // When folded or auto-folded and not responsive view, the current menu item does have a fly-out sub-menu.
  376.             $current.attr( 'aria-haspopup', 'true' );
  377.         } else {
  378.             // When expanded or in responsive view, reset aria-haspopup.
  379.             $current.attr( 'aria-haspopup', 'false' );
  380.         }
  381.     }
  382.  
  383.     $document.on( 'wp-menu-state-set wp-collapse-menu wp-responsive-activate wp-responsive-deactivate', currentMenuItemHasPopup );
  384.  
  385.     /**
  386.      * Ensure an admin submenu is within the visual viewport.
  387.      *
  388.      * @since 4.1.0
  389.      *
  390.      * @param {jQuery} $menuItem The parent menu item containing the submenu.
  391.      */
  392.     function adjustSubmenu( $menuItem ) {
  393.         var bottomOffset, pageHeight, adjustment, theFold, menutop, wintop, maxtop,
  394.             $submenu = $menuItem.find( '.wp-submenu' );
  395.  
  396.         menutop = $menuItem.offset().top;
  397.         wintop = $window.scrollTop();
  398.         maxtop = menutop - wintop - 30; // max = make the top of the sub almost touch admin bar
  399.  
  400.         bottomOffset = menutop + $submenu.height() + 1; // Bottom offset of the menu
  401.         pageHeight = $wpwrap.height(); // Height of the entire page
  402.         adjustment = 60 + bottomOffset - pageHeight;
  403.         theFold = $window.height() + wintop - 50; // The fold
  404.  
  405.         if ( theFold < ( bottomOffset - adjustment ) ) {
  406.             adjustment = bottomOffset - theFold;
  407.         }
  408.  
  409.         if ( adjustment > maxtop ) {
  410.             adjustment = maxtop;
  411.         }
  412.  
  413.         if ( adjustment > 1 ) {
  414.             $submenu.css( 'margin-top', '-' + adjustment + 'px' );
  415.         } else {
  416.             $submenu.css( 'margin-top', '' );
  417.         }
  418.     }
  419.  
  420.     if ( 'ontouchstart' in window || /IEMobile\/[1-9]/.test(navigator.userAgent) ) { // touch screen device
  421.         // iOS Safari works with touchstart, the rest work with click
  422.         mobileEvent = isIOS ? 'touchstart' : 'click';
  423.  
  424.         // close any open submenus when touch/click is not on the menu
  425.         $body.on( mobileEvent+'.wp-mobile-hover', function(e) {
  426.             if ( $adminmenu.data('wp-responsive') ) {
  427.                 return;
  428.             }
  429.  
  430.             if ( ! $( e.target ).closest( '#adminmenu' ).length ) {
  431.                 $adminmenu.find( 'li.opensub' ).removeClass( 'opensub' );
  432.             }
  433.         });
  434.  
  435.         $adminmenu.find( 'a.wp-has-submenu' ).on( mobileEvent + '.wp-mobile-hover', function( event ) {
  436.             var $menuItem = $(this).parent();
  437.  
  438.             if ( $adminmenu.data( 'wp-responsive' ) ) {
  439.                 return;
  440.             }
  441.  
  442.             // Show the sub instead of following the link if:
  443.             //    - the submenu is not open
  444.             //    - the submenu is not shown inline or the menu is not folded
  445.             if ( ! $menuItem.hasClass( 'opensub' ) && ( ! $menuItem.hasClass( 'wp-menu-open' ) || $menuItem.width() < 40 ) ) {
  446.                 event.preventDefault();
  447.                 adjustSubmenu( $menuItem );
  448.                 $adminmenu.find( 'li.opensub' ).removeClass( 'opensub' );
  449.                 $menuItem.addClass('opensub');
  450.             }
  451.         });
  452.     }
  453.  
  454.     if ( ! isIOS && ! isAndroid ) {
  455.         $adminmenu.find( 'li.wp-has-submenu' ).hoverIntent({
  456.             over: function() {
  457.                 var $menuItem = $( this ),
  458.                     $submenu = $menuItem.find( '.wp-submenu' ),
  459.                     top = parseInt( $submenu.css( 'top' ), 10 );
  460.  
  461.                 if ( isNaN( top ) || top > -5 ) { // the submenu is visible
  462.                     return;
  463.                 }
  464.  
  465.                 if ( $adminmenu.data( 'wp-responsive' ) ) {
  466.                     // The menu is in responsive mode, bail
  467.                     return;
  468.                 }
  469.  
  470.                 adjustSubmenu( $menuItem );
  471.                 $adminmenu.find( 'li.opensub' ).removeClass( 'opensub' );
  472.                 $menuItem.addClass( 'opensub' );
  473.             },
  474.             out: function(){
  475.                 if ( $adminmenu.data( 'wp-responsive' ) ) {
  476.                     // The menu is in responsive mode, bail
  477.                     return;
  478.                 }
  479.  
  480.                 $( this ).removeClass( 'opensub' ).find( '.wp-submenu' ).css( 'margin-top', '' );
  481.             },
  482.             timeout: 200,
  483.             sensitivity: 7,
  484.             interval: 90
  485.         });
  486.  
  487.         $adminmenu.on( 'focus.adminmenu', '.wp-submenu a', function( event ) {
  488.             if ( $adminmenu.data( 'wp-responsive' ) ) {
  489.                 // The menu is in responsive mode, bail
  490.                 return;
  491.             }
  492.  
  493.             $( event.target ).closest( 'li.menu-top' ).addClass( 'opensub' );
  494.         }).on( 'blur.adminmenu', '.wp-submenu a', function( event ) {
  495.             if ( $adminmenu.data( 'wp-responsive' ) ) {
  496.                 return;
  497.             }
  498.  
  499.             $( event.target ).closest( 'li.menu-top' ).removeClass( 'opensub' );
  500.         }).find( 'li.wp-has-submenu.wp-not-current-submenu' ).on( 'focusin.adminmenu', function() {
  501.             adjustSubmenu( $( this ) );
  502.         });
  503.     }
  504.  
  505.     /*
  506.      * The `.below-h2` class is here just for backward compatibility with plugins
  507.      * that are (incorrectly) using it. Do not use. Use `.inline` instead. See #34570.
  508.      * If '.wp-header-end' is found, append the notices after it otherwise
  509.      * after the first h1 or h2 heading found within the main content.
  510.      */
  511.     if ( ! $headerEnd.length ) {
  512.         $headerEnd = $( '.wrap h1, .wrap h2' ).first();
  513.     }
  514.     $( 'div.updated, div.error, div.notice' ).not( '.inline, .below-h2' ).insertAfter( $headerEnd );
  515.  
  516.     // Make notices dismissible
  517.     function makeNoticesDismissible() {
  518.         $( '.notice.is-dismissible' ).each( function() {
  519.             var $el = $( this ),
  520.                 $button = $( '<button type="button" class="notice-dismiss"><span class="screen-reader-text"></span></button>' ),
  521.                 btnText = commonL10n.dismiss || '';
  522.  
  523.             // Ensure plain text
  524.             $button.find( '.screen-reader-text' ).text( btnText );
  525.             $button.on( 'click.wp-dismiss-notice', function( event ) {
  526.                 event.preventDefault();
  527.                 $el.fadeTo( 100, 0, function() {
  528.                     $el.slideUp( 100, function() {
  529.                         $el.remove();
  530.                     });
  531.                 });
  532.             });
  533.  
  534.             $el.append( $button );
  535.         });
  536.     }
  537.  
  538.     $document.on( 'wp-updates-notice-added wp-plugin-install-error wp-plugin-update-error wp-plugin-delete-error wp-theme-install-error wp-theme-delete-error', makeNoticesDismissible );
  539.  
  540.     // Init screen meta
  541.     screenMeta.init();
  542.  
  543.     // This event needs to be delegated. Ticket #37973.
  544.     $body.on( 'click', 'tbody > tr > .check-column :checkbox', function( event ) {
  545.         // Shift click to select a range of checkboxes.
  546.         if ( 'undefined' == event.shiftKey ) { return true; }
  547.         if ( event.shiftKey ) {
  548.             if ( !lastClicked ) { return true; }
  549.             checks = $( lastClicked ).closest( 'form' ).find( ':checkbox' ).filter( ':visible:enabled' );
  550.             first = checks.index( lastClicked );
  551.             last = checks.index( this );
  552.             checked = $(this).prop('checked');
  553.             if ( 0 < first && 0 < last && first != last ) {
  554.                 sliced = ( last > first ) ? checks.slice( first, last ) : checks.slice( last, first );
  555.                 sliced.prop( 'checked', function() {
  556.                     if ( $(this).closest('tr').is(':visible') )
  557.                         return checked;
  558.  
  559.                     return false;
  560.                 });
  561.             }
  562.         }
  563.         lastClicked = this;
  564.  
  565.         // Toggle the "Select all" checkboxes depending if the other ones are all checked or not.
  566.         var unchecked = $(this).closest('tbody').find(':checkbox').filter(':visible:enabled').not(':checked');
  567.         $(this).closest('table').children('thead, tfoot').find(':checkbox').prop('checked', function() {
  568.             return ( 0 === unchecked.length );
  569.         });
  570.  
  571.         return true;
  572.     });
  573.  
  574.     // This event needs to be delegated. Ticket #37973.
  575.     $body.on( 'click.wp-toggle-checkboxes', 'thead .check-column :checkbox, tfoot .check-column :checkbox', function( event ) {
  576.         var $this = $(this),
  577.             $table = $this.closest( 'table' ),
  578.             controlChecked = $this.prop('checked'),
  579.             toggle = event.shiftKey || $this.data('wp-toggle');
  580.  
  581.         $table.children( 'tbody' ).filter(':visible')
  582.             .children().children('.check-column').find(':checkbox')
  583.             .prop('checked', function() {
  584.                 if ( $(this).is(':hidden,:disabled') ) {
  585.                     return false;
  586.                 }
  587.  
  588.                 if ( toggle ) {
  589.                     return ! $(this).prop( 'checked' );
  590.                 } else if ( controlChecked ) {
  591.                     return true;
  592.                 }
  593.  
  594.                 return false;
  595.             });
  596.  
  597.         $table.children('thead,  tfoot').filter(':visible')
  598.             .children().children('.check-column').find(':checkbox')
  599.             .prop('checked', function() {
  600.                 if ( toggle ) {
  601.                     return false;
  602.                 } else if ( controlChecked ) {
  603.                     return true;
  604.                 }
  605.  
  606.                 return false;
  607.             });
  608.     });
  609.  
  610.     // Show row actions on keyboard focus of its parent container element or any other elements contained within
  611.     $( '#wpbody-content' ).on({
  612.         focusin: function() {
  613.             clearTimeout( transitionTimeout );
  614.             focusedRowActions = $( this ).find( '.row-actions' );
  615.             // transitionTimeout is necessary for Firefox, but Chrome won't remove the CSS class without a little help.
  616.             $( '.row-actions' ).not( this ).removeClass( 'visible' );
  617.             focusedRowActions.addClass( 'visible' );
  618.         },
  619.         focusout: function() {
  620.             // Tabbing between post title and .row-actions links needs a brief pause, otherwise
  621.             // the .row-actions div gets hidden in transit in some browsers (ahem, Firefox).
  622.             transitionTimeout = setTimeout( function() {
  623.                 focusedRowActions.removeClass( 'visible' );
  624.             }, 30 );
  625.         }
  626.     }, '.has-row-actions' );
  627.  
  628.     // Toggle list table rows on small screens
  629.     $( 'tbody' ).on( 'click', '.toggle-row', function() {
  630.         $( this ).closest( 'tr' ).toggleClass( 'is-expanded' );
  631.     });
  632.  
  633.     $('#default-password-nag-no').click( function() {
  634.         setUserSetting('default_password_nag', 'hide');
  635.         $('div.default-password-nag').hide();
  636.         return false;
  637.     });
  638.  
  639.     // tab in textareas
  640.     $('#newcontent').bind('keydown.wpevent_InsertTab', function(e) {
  641.         var el = e.target, selStart, selEnd, val, scroll, sel;
  642.  
  643.         if ( e.keyCode == 27 ) { // escape key
  644.             // when pressing Escape: Opera 12 and 27 blur form fields, IE 8 clears them
  645.             e.preventDefault();
  646.             $(el).data('tab-out', true);
  647.             return;
  648.         }
  649.  
  650.         if ( e.keyCode != 9 || e.ctrlKey || e.altKey || e.shiftKey ) // tab key
  651.             return;
  652.  
  653.         if ( $(el).data('tab-out') ) {
  654.             $(el).data('tab-out', false);
  655.             return;
  656.         }
  657.  
  658.         selStart = el.selectionStart;
  659.         selEnd = el.selectionEnd;
  660.         val = el.value;
  661.  
  662.         if ( document.selection ) {
  663.             el.focus();
  664.             sel = document.selection.createRange();
  665.             sel.text = '\t';
  666.         } else if ( selStart >= 0 ) {
  667.             scroll = this.scrollTop;
  668.             el.value = val.substring(0, selStart).concat('\t', val.substring(selEnd) );
  669.             el.selectionStart = el.selectionEnd = selStart + 1;
  670.             this.scrollTop = scroll;
  671.         }
  672.  
  673.         if ( e.stopPropagation )
  674.             e.stopPropagation();
  675.         if ( e.preventDefault )
  676.             e.preventDefault();
  677.     });
  678.  
  679.     if ( pageInput.length ) {
  680.         pageInput.closest('form').submit( function() {
  681.  
  682.             // Reset paging var for new filters/searches but not for bulk actions. See #17685.
  683.             if ( $('select[name="action"]').val() == -1 && $('select[name="action2"]').val() == -1 && pageInput.val() == currentPage )
  684.                 pageInput.val('1');
  685.         });
  686.     }
  687.  
  688.     $('.search-box input[type="search"], .search-box input[type="submit"]').mousedown(function () {
  689.         $('select[name^="action"]').val('-1');
  690.     });
  691.  
  692.     // Scroll into view when focused
  693.     $('#contextual-help-link, #show-settings-link').on( 'focus.scroll-into-view', function(e){
  694.         if ( e.target.scrollIntoView )
  695.             e.target.scrollIntoView(false);
  696.     });
  697.  
  698.     // Disable upload buttons until files are selected
  699.     (function(){
  700.         var button, input, form = $('form.wp-upload-form');
  701.         if ( ! form.length )
  702.             return;
  703.         button = form.find('input[type="submit"]');
  704.         input = form.find('input[type="file"]');
  705.  
  706.         function toggleUploadButton() {
  707.             button.prop('disabled', '' === input.map( function() {
  708.                 return $(this).val();
  709.             }).get().join(''));
  710.         }
  711.         toggleUploadButton();
  712.         input.on('change', toggleUploadButton);
  713.     })();
  714.  
  715.     function pinMenu( event ) {
  716.         var windowPos = $window.scrollTop(),
  717.             resizing = ! event || event.type !== 'scroll';
  718.  
  719.         if ( isIOS || isIE8 || $adminmenu.data( 'wp-responsive' ) ) {
  720.             return;
  721.         }
  722.  
  723.         if ( height.menu + height.adminbar < height.window ||
  724.             height.menu + height.adminbar + 20 > height.wpwrap ) {
  725.             unpinMenu();
  726.             return;
  727.         }
  728.  
  729.         menuIsPinned = true;
  730.  
  731.         if ( height.menu + height.adminbar > height.window ) {
  732.             // Check for overscrolling
  733.             if ( windowPos < 0 ) {
  734.                 if ( ! pinnedMenuTop ) {
  735.                     pinnedMenuTop = true;
  736.                     pinnedMenuBottom = false;
  737.  
  738.                     $adminMenuWrap.css({
  739.                         position: 'fixed',
  740.                         top: '',
  741.                         bottom: ''
  742.                     });
  743.                 }
  744.  
  745.                 return;
  746.             } else if ( windowPos + height.window > $document.height() - 1 ) {
  747.                 if ( ! pinnedMenuBottom ) {
  748.                     pinnedMenuBottom = true;
  749.                     pinnedMenuTop = false;
  750.  
  751.                     $adminMenuWrap.css({
  752.                         position: 'fixed',
  753.                         top: '',
  754.                         bottom: 0
  755.                     });
  756.                 }
  757.  
  758.                 return;
  759.             }
  760.  
  761.             if ( windowPos > lastScrollPosition ) {
  762.                 // Scrolling down
  763.                 if ( pinnedMenuTop ) {
  764.                     // let it scroll
  765.                     pinnedMenuTop = false;
  766.                     menuTop = $adminMenuWrap.offset().top - height.adminbar - ( windowPos - lastScrollPosition );
  767.  
  768.                     if ( menuTop + height.menu + height.adminbar < windowPos + height.window ) {
  769.                         menuTop = windowPos + height.window - height.menu - height.adminbar;
  770.                     }
  771.  
  772.                     $adminMenuWrap.css({
  773.                         position: 'absolute',
  774.                         top: menuTop,
  775.                         bottom: ''
  776.                     });
  777.                 } else if ( ! pinnedMenuBottom && $adminMenuWrap.offset().top + height.menu < windowPos + height.window ) {
  778.                     // pin the bottom
  779.                     pinnedMenuBottom = true;
  780.  
  781.                     $adminMenuWrap.css({
  782.                         position: 'fixed',
  783.                         top: '',
  784.                         bottom: 0
  785.                     });
  786.                 }
  787.             } else if ( windowPos < lastScrollPosition ) {
  788.                 // Scrolling up
  789.                 if ( pinnedMenuBottom ) {
  790.                     // let it scroll
  791.                     pinnedMenuBottom = false;
  792.                     menuTop = $adminMenuWrap.offset().top - height.adminbar + ( lastScrollPosition - windowPos );
  793.  
  794.                     if ( menuTop + height.menu > windowPos + height.window ) {
  795.                         menuTop = windowPos;
  796.                     }
  797.  
  798.                     $adminMenuWrap.css({
  799.                         position: 'absolute',
  800.                         top: menuTop,
  801.                         bottom: ''
  802.                     });
  803.                 } else if ( ! pinnedMenuTop && $adminMenuWrap.offset().top >= windowPos + height.adminbar ) {
  804.                     // pin the top
  805.                     pinnedMenuTop = true;
  806.  
  807.                     $adminMenuWrap.css({
  808.                         position: 'fixed',
  809.                         top: '',
  810.                         bottom: ''
  811.                     });
  812.                 }
  813.             } else if ( resizing ) {
  814.                 // Resizing
  815.                 pinnedMenuTop = pinnedMenuBottom = false;
  816.                 menuTop = windowPos + height.window - height.menu - height.adminbar - 1;
  817.  
  818.                 if ( menuTop > 0 ) {
  819.                     $adminMenuWrap.css({
  820.                         position: 'absolute',
  821.                         top: menuTop,
  822.                         bottom: ''
  823.                     });
  824.                 } else {
  825.                     unpinMenu();
  826.                 }
  827.             }
  828.         }
  829.  
  830.         lastScrollPosition = windowPos;
  831.     }
  832.  
  833.     function resetHeights() {
  834.         height = {
  835.             window: $window.height(),
  836.             wpwrap: $wpwrap.height(),
  837.             adminbar: $adminbar.height(),
  838.             menu: $adminMenuWrap.height()
  839.         };
  840.     }
  841.  
  842.     function unpinMenu() {
  843.         if ( isIOS || ! menuIsPinned ) {
  844.             return;
  845.         }
  846.  
  847.         pinnedMenuTop = pinnedMenuBottom = menuIsPinned = false;
  848.         $adminMenuWrap.css({
  849.             position: '',
  850.             top: '',
  851.             bottom: ''
  852.         });
  853.     }
  854.  
  855.     function setPinMenu() {
  856.         resetHeights();
  857.  
  858.         if ( $adminmenu.data('wp-responsive') ) {
  859.             $body.removeClass( 'sticky-menu' );
  860.             unpinMenu();
  861.         } else if ( height.menu + height.adminbar > height.window ) {
  862.             pinMenu();
  863.             $body.removeClass( 'sticky-menu' );
  864.         } else {
  865.             $body.addClass( 'sticky-menu' );
  866.             unpinMenu();
  867.         }
  868.     }
  869.  
  870.     if ( ! isIOS ) {
  871.         $window.on( 'scroll.pin-menu', pinMenu );
  872.         $document.on( 'tinymce-editor-init.pin-menu', function( event, editor ) {
  873.             editor.on( 'wp-autoresize', resetHeights );
  874.         });
  875.     }
  876.  
  877.     window.wpResponsive = {
  878.         init: function() {
  879.             var self = this;
  880.  
  881.             // Modify functionality based on custom activate/deactivate event
  882.             $document.on( 'wp-responsive-activate.wp-responsive', function() {
  883.                 self.activate();
  884.             }).on( 'wp-responsive-deactivate.wp-responsive', function() {
  885.                 self.deactivate();
  886.             });
  887.  
  888.             $( '#wp-admin-bar-menu-toggle a' ).attr( 'aria-expanded', 'false' );
  889.  
  890.             // Toggle sidebar when toggle is clicked
  891.             $( '#wp-admin-bar-menu-toggle' ).on( 'click.wp-responsive', function( event ) {
  892.                 event.preventDefault();
  893.  
  894.                 // close any open toolbar submenus
  895.                 $adminbar.find( '.hover' ).removeClass( 'hover' );
  896.  
  897.                 $wpwrap.toggleClass( 'wp-responsive-open' );
  898.                 if ( $wpwrap.hasClass( 'wp-responsive-open' ) ) {
  899.                     $(this).find('a').attr( 'aria-expanded', 'true' );
  900.                     $( '#adminmenu a:first' ).focus();
  901.                 } else {
  902.                     $(this).find('a').attr( 'aria-expanded', 'false' );
  903.                 }
  904.             } );
  905.  
  906.             // Add menu events
  907.             $adminmenu.on( 'click.wp-responsive', 'li.wp-has-submenu > a', function( event ) {
  908.                 if ( ! $adminmenu.data('wp-responsive') ) {
  909.                     return;
  910.                 }
  911.  
  912.                 $( this ).parent( 'li' ).toggleClass( 'selected' );
  913.                 event.preventDefault();
  914.             });
  915.  
  916.             self.trigger();
  917.             $document.on( 'wp-window-resized.wp-responsive', $.proxy( this.trigger, this ) );
  918.  
  919.             // This needs to run later as UI Sortable may be initialized later on $(document).ready()
  920.             $window.on( 'load.wp-responsive', function() {
  921.                 var width = navigator.userAgent.indexOf('AppleWebKit/') > -1 ? $window.width() : window.innerWidth;
  922.  
  923.                 if ( width <= 782 ) {
  924.                     self.disableSortables();
  925.                 }
  926.             });
  927.         },
  928.  
  929.         activate: function() {
  930.             setPinMenu();
  931.  
  932.             if ( ! $body.hasClass( 'auto-fold' ) ) {
  933.                 $body.addClass( 'auto-fold' );
  934.             }
  935.  
  936.             $adminmenu.data( 'wp-responsive', 1 );
  937.             this.disableSortables();
  938.         },
  939.  
  940.         deactivate: function() {
  941.             setPinMenu();
  942.             $adminmenu.removeData('wp-responsive');
  943.             this.enableSortables();
  944.         },
  945.  
  946.         trigger: function() {
  947.             var viewportWidth = getViewportWidth();
  948.  
  949.             // Exclude IE < 9, it doesn't support @media CSS rules.
  950.             if ( ! viewportWidth ) {
  951.                 return;
  952.             }
  953.  
  954.             if ( viewportWidth <= 782 ) {
  955.                 if ( ! wpResponsiveActive ) {
  956.                     $document.trigger( 'wp-responsive-activate' );
  957.                     wpResponsiveActive = true;
  958.                 }
  959.             } else {
  960.                 if ( wpResponsiveActive ) {
  961.                     $document.trigger( 'wp-responsive-deactivate' );
  962.                     wpResponsiveActive = false;
  963.                 }
  964.             }
  965.  
  966.             if ( viewportWidth <= 480 ) {
  967.                 this.enableOverlay();
  968.             } else {
  969.                 this.disableOverlay();
  970.             }
  971.         },
  972.  
  973.         enableOverlay: function() {
  974.             if ( $overlay.length === 0 ) {
  975.                 $overlay = $( '<div id="wp-responsive-overlay"></div>' )
  976.                     .insertAfter( '#wpcontent' )
  977.                     .hide()
  978.                     .on( 'click.wp-responsive', function() {
  979.                         $toolbar.find( '.menupop.hover' ).removeClass( 'hover' );
  980.                         $( this ).hide();
  981.                     });
  982.             }
  983.  
  984.             $toolbarPopups.on( 'click.wp-responsive', function() {
  985.                 $overlay.show();
  986.             });
  987.         },
  988.  
  989.         disableOverlay: function() {
  990.             $toolbarPopups.off( 'click.wp-responsive' );
  991.             $overlay.hide();
  992.         },
  993.  
  994.         disableSortables: function() {
  995.             if ( $sortables.length ) {
  996.                 try {
  997.                     $sortables.sortable('disable');
  998.                 } catch(e) {}
  999.             }
  1000.         },
  1001.  
  1002.         enableSortables: function() {
  1003.             if ( $sortables.length ) {
  1004.                 try {
  1005.                     $sortables.sortable('enable');
  1006.                 } catch(e) {}
  1007.             }
  1008.         }
  1009.     };
  1010.  
  1011.     // Add an ARIA role `button` to elements that behave like UI controls when JavaScript is on.
  1012.     function aria_button_if_js() {
  1013.         $( '.aria-button-if-js' ).attr( 'role', 'button' );
  1014.     }
  1015.  
  1016.     $( document ).ajaxComplete( function() {
  1017.         aria_button_if_js();
  1018.     });
  1019.  
  1020.     /**
  1021.      * @summary Get the viewport width.
  1022.      *
  1023.      * @since 4.7.0
  1024.      *
  1025.      * @returns {number|boolean} The current viewport width or false if the
  1026.      *                           browser doesn't support innerWidth (IE < 9).
  1027.      */
  1028.     function getViewportWidth() {
  1029.         var viewportWidth = false;
  1030.  
  1031.         if ( window.innerWidth ) {
  1032.             // On phones, window.innerWidth is affected by zooming.
  1033.             viewportWidth = Math.max( window.innerWidth, document.documentElement.clientWidth );
  1034.         }
  1035.  
  1036.         return viewportWidth;
  1037.     }
  1038.  
  1039.     /**
  1040.      * @summary Set the admin menu collapsed/expanded state.
  1041.      *
  1042.      * Sets the global variable `menuState` and triggers a custom event passing
  1043.      * the current menu state.
  1044.      *
  1045.      * @since 4.7.0
  1046.      *
  1047.      * @returns {void}
  1048.      */
  1049.     function setMenuState() {
  1050.         var viewportWidth = getViewportWidth() || 961;
  1051.  
  1052.         if ( viewportWidth <= 782  ) {
  1053.             menuState = 'responsive';
  1054.         } else if ( $body.hasClass( 'folded' ) || ( $body.hasClass( 'auto-fold' ) && viewportWidth <= 960 && viewportWidth > 782 ) ) {
  1055.             menuState = 'folded';
  1056.         } else {
  1057.             menuState = 'open';
  1058.         }
  1059.  
  1060.         $document.trigger( 'wp-menu-state-set', { state: menuState } );
  1061.     }
  1062.  
  1063.     // Set the menu state when the window gets resized.
  1064.     $document.on( 'wp-window-resized.set-menu-state', setMenuState );
  1065.  
  1066.     /**
  1067.      * @summary Set ARIA attributes on the collapse/expand menu button.
  1068.      *
  1069.      * When the admin menu is open or folded, updates the `aria-expanded` and
  1070.      * `aria-label` attributes of the button to give feedback to assistive
  1071.      * technologies. In the responsive view, the button is always hidden.
  1072.      *
  1073.      * @since 4.7.0
  1074.      *
  1075.      * @returns {void}
  1076.      */
  1077.     $document.on( 'wp-menu-state-set wp-collapse-menu', function( event, eventData ) {
  1078.         var $collapseButton = $( '#collapse-button' ),
  1079.             ariaExpanded = 'true',
  1080.             ariaLabelText = commonL10n.collapseMenu;
  1081.  
  1082.         if ( 'folded' === eventData.state ) {
  1083.             ariaExpanded = 'false';
  1084.             ariaLabelText = commonL10n.expandMenu;
  1085.         }
  1086.  
  1087.         $collapseButton.attr({
  1088.             'aria-expanded': ariaExpanded,
  1089.             'aria-label': ariaLabelText
  1090.         });
  1091.     });
  1092.  
  1093.     window.wpResponsive.init();
  1094.     setPinMenu();
  1095.     setMenuState();
  1096.     currentMenuItemHasPopup();
  1097.     makeNoticesDismissible();
  1098.     aria_button_if_js();
  1099.  
  1100.     $document.on( 'wp-pin-menu wp-window-resized.pin-menu postboxes-columnchange.pin-menu postbox-toggled.pin-menu wp-collapse-menu.pin-menu wp-scroll-start.pin-menu', setPinMenu );
  1101.  
  1102.     // Set initial focus on a specific element.
  1103.     $( '.wp-initial-focus' ).focus();
  1104.  
  1105.     // Toggle update details on update-core.php.
  1106.     $body.on( 'click', '.js-update-details-toggle', function() {
  1107.         var $updateNotice = $( this ).closest( '.js-update-details' ),
  1108.             $progressDiv = $( '#' + $updateNotice.data( 'update-details' ) );
  1109.  
  1110.         /*
  1111.          * When clicking on "Show details" move the progress div below the update
  1112.          * notice. Make sure it gets moved just the first time.
  1113.          */
  1114.         if ( ! $progressDiv.hasClass( 'update-details-moved' ) ) {
  1115.             $progressDiv.insertAfter( $updateNotice ).addClass( 'update-details-moved' );
  1116.         }
  1117.  
  1118.         // Toggle the progress div visibility.
  1119.         $progressDiv.toggle();
  1120.         // Toggle the Show Details button expanded state.
  1121.         $( this ).attr( 'aria-expanded', $progressDiv.is( ':visible' ) );
  1122.     });
  1123. });
  1124.  
  1125. // Fire a custom jQuery event at the end of window resize
  1126. ( function() {
  1127.     var timeout;
  1128.  
  1129.     function triggerEvent() {
  1130.         $document.trigger( 'wp-window-resized' );
  1131.     }
  1132.  
  1133.     function fireOnce() {
  1134.         window.clearTimeout( timeout );
  1135.         timeout = window.setTimeout( triggerEvent, 200 );
  1136.     }
  1137.  
  1138.     $window.on( 'resize.wp-fire-once', fireOnce );
  1139. }());
  1140.  
  1141. // Make Windows 8 devices play along nicely.
  1142. (function(){
  1143.     if ( '-ms-user-select' in document.documentElement.style && navigator.userAgent.match(/IEMobile\/10\.0/) ) {
  1144.         var msViewportStyle = document.createElement( 'style' );
  1145.         msViewportStyle.appendChild(
  1146.             document.createTextNode( '@-ms-viewport{width:auto!important}' )
  1147.         );
  1148.         document.getElementsByTagName( 'head' )[0].appendChild( msViewportStyle );
  1149.     }
  1150. })();
  1151.  
  1152. }( jQuery, window ));
  1153.