wp/wp-includes/js/media-grid.js
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
   263 					url += '?search=' + val;
   263 					url += '?search=' + val;
   264 					this.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } );
   264 					this.gridRouter.navigate( this.gridRouter.baseUrl( url ), { replace: true } );
   265 				}
   265 				}
   266 			}, 1000 );
   266 			}, 1000 );
   267 
   267 
   268 		// Update the URL when entering search string (at most once per second)
   268 		// Update the URL when entering search string (at most once per second).
   269 		search.on( 'input', _.bind( input, this ) );
   269 		search.on( 'input', _.bind( input, this ) );
   270 
   270 
   271 		this.gridRouter
   271 		this.gridRouter
   272 			.on( 'route:search', function () {
   272 			.on( 'route:search', function () {
   273 				var href = window.location.href;
   273 				var href = window.location.href;
   344 		}
   344 		}
   345 
   345 
   346 		$browser = this.$('.attachments-browser');
   346 		$browser = this.$('.attachments-browser');
   347 		$toolbar = $browser.find('.media-toolbar');
   347 		$toolbar = $browser.find('.media-toolbar');
   348 
   348 
   349 		// Offset doesn't appear to take top margin into account, hence +16
   349 		// Offset doesn't appear to take top margin into account, hence +16.
   350 		if ( ( $browser.offset().top + 16 ) < this.$window.scrollTop() + this.$adminBar.height() ) {
   350 		if ( ( $browser.offset().top + 16 ) < this.$window.scrollTop() + this.$adminBar.height() ) {
   351 			$browser.addClass( 'fixed' );
   351 			$browser.addClass( 'fixed' );
   352 			$toolbar.css('width', $browser.width() + 'px');
   352 			$toolbar.css('width', $browser.width() + 'px');
   353 		} else {
   353 		} else {
   354 			$browser.removeClass( 'fixed' );
   354 			$browser.removeClass( 'fixed' );
   432 		}
   432 		}
   433 		this.browserView.dfd.done( _.bind( this.startHistory, this ) );
   433 		this.browserView.dfd.done( _.bind( this.startHistory, this ) );
   434 	},
   434 	},
   435 
   435 
   436 	startHistory: function() {
   436 	startHistory: function() {
   437 		// Verify pushState support and activate
   437 		// Verify pushState support and activate.
   438 		if ( window.history && window.history.pushState ) {
   438 		if ( window.history && window.history.pushState ) {
   439 			if ( Backbone.History.started ) {
   439 			if ( Backbone.History.started ) {
   440 				Backbone.history.stop();
   440 				Backbone.history.stop();
   441 			}
   441 			}
   442 			Backbone.history.start( {
   442 			Backbone.history.start( {
   527 		'upload.php?item=:slug':           'showItem',
   527 		'upload.php?item=:slug':           'showItem',
   528 		'upload.php?search=:query':        'search',
   528 		'upload.php?search=:query':        'search',
   529 		'upload.php':                      'reset'
   529 		'upload.php':                      'reset'
   530 	},
   530 	},
   531 
   531 
   532 	// Map routes against the page URL
   532 	// Map routes against the page URL.
   533 	baseUrl: function( url ) {
   533 	baseUrl: function( url ) {
   534 		return 'upload.php' + url;
   534 		return 'upload.php' + url;
   535 	},
   535 	},
   536 
   536 
   537 	reset: function() {
   537 	reset: function() {
   540 		if ( frame ) {
   540 		if ( frame ) {
   541 			frame.close();
   541 			frame.close();
   542 		}
   542 		}
   543 	},
   543 	},
   544 
   544 
   545 	// Respond to the search route by filling the search field and trigggering the input event
   545 	// Respond to the search route by filling the search field and trigggering the input event.
   546 	search: function( query ) {
   546 	search: function( query ) {
   547 		jQuery( '#media-search-input' ).val( query ).trigger( 'input' );
   547 		jQuery( '#media-search-input' ).val( query ).trigger( 'input' );
   548 	},
   548 	},
   549 
   549 
   550 	// Show the modal with a specific item
   550 	// Show the modal with a specific item.
   551 	showItem: function( query ) {
   551 	showItem: function( query ) {
   552 		var media = wp.media,
   552 		var media = wp.media,
   553 			frame = media.frames.browse,
   553 			frame = media.frames.browse,
   554 			library = frame.state().get('library'),
   554 			library = frame.state().get('library'),
   555 			item;
   555 			item;
   556 
   556 
   557 		// Trigger the media frame to open the correct item
   557 		// Trigger the media frame to open the correct item.
   558 		item = library.findWhere( { id: parseInt( query, 10 ) } );
   558 		item = library.findWhere( { id: parseInt( query, 10 ) } );
   559 		item.set( 'skipHistory', true );
   559 		item.set( 'skipHistory', true );
   560 
   560 
   561 		if ( item ) {
   561 		if ( item ) {
   562 			frame.trigger( 'edit:attachment', item );
   562 			frame.trigger( 'edit:attachment', item );
   716 				$( 'body' ).on( 'keydown.media-modal', _.bind( this.keyEvent, this ) );
   716 				$( 'body' ).on( 'keydown.media-modal', _.bind( this.keyEvent, this ) );
   717 			}, this ) );
   717 			}, this ) );
   718 
   718 
   719 			// Completely destroy the modal DOM element when closing it.
   719 			// Completely destroy the modal DOM element when closing it.
   720 			this.modal.on( 'close', _.bind( function() {
   720 			this.modal.on( 'close', _.bind( function() {
   721 				$( 'body' ).off( 'keydown.media-modal' ); /* remove the keydown event */
   721 				// Remove the keydown event.
   722 				// Restore the original focus item if possible
   722 				$( 'body' ).off( 'keydown.media-modal' );
       
   723 				// Move focus back to the original item in the grid if possible.
   723 				$( 'li.attachment[data-id="' + this.model.get( 'id' ) +'"]' ).focus();
   724 				$( 'li.attachment[data-id="' + this.model.get( 'id' ) +'"]' ).focus();
   724 				this.resetRoute();
   725 				this.resetRoute();
   725 			}, this ) );
   726 			}, this ) );
   726 
   727 
   727 			// Set this frame as the modal's content.
   728 			// Set this frame as the modal's content.
   798 	editImageModeRender: function( view ) {
   799 	editImageModeRender: function( view ) {
   799 		view.on( 'ready', view.loadEditor );
   800 		view.on( 'ready', view.loadEditor );
   800 	},
   801 	},
   801 
   802 
   802 	toggleNav: function() {
   803 	toggleNav: function() {
   803 		this.$('.left').toggleClass( 'disabled', ! this.hasPrevious() );
   804 		this.$( '.left' ).prop( 'disabled', ! this.hasPrevious() );
   804 		this.$('.right').toggleClass( 'disabled', ! this.hasNext() );
   805 		this.$( '.right' ).prop( 'disabled', ! this.hasNext() );
   805 	},
   806 	},
   806 
   807 
   807 	/**
   808 	/**
   808 	 * Rerender the view.
   809 	 * Rerender the view.
   809 	 */
   810 	 */
   829 	 */
   830 	 */
   830 	previousMediaItem: function() {
   831 	previousMediaItem: function() {
   831 		if ( ! this.hasPrevious() ) {
   832 		if ( ! this.hasPrevious() ) {
   832 			return;
   833 			return;
   833 		}
   834 		}
       
   835 
   834 		this.trigger( 'refresh', this.library.at( this.getCurrentIndex() - 1 ) );
   836 		this.trigger( 'refresh', this.library.at( this.getCurrentIndex() - 1 ) );
   835 		this.$( '.left' ).focus();
   837 		// Move focus to the Previous button. When there are no more items, to the Next button.
       
   838 		this.focusNavButton( this.hasPrevious() ? '.left' : '.right' );
   836 	},
   839 	},
   837 
   840 
   838 	/**
   841 	/**
   839 	 * Click handler to switch to the next media item.
   842 	 * Click handler to switch to the next media item.
   840 	 */
   843 	 */
   841 	nextMediaItem: function() {
   844 	nextMediaItem: function() {
   842 		if ( ! this.hasNext() ) {
   845 		if ( ! this.hasNext() ) {
   843 			return;
   846 			return;
   844 		}
   847 		}
       
   848 
   845 		this.trigger( 'refresh', this.library.at( this.getCurrentIndex() + 1 ) );
   849 		this.trigger( 'refresh', this.library.at( this.getCurrentIndex() + 1 ) );
   846 		this.$( '.right' ).focus();
   850 		// Move focus to the Next button. When there are no more items, to the Previous button.
       
   851 		this.focusNavButton( this.hasNext() ? '.right' : '.left' );
       
   852 	},
       
   853 
       
   854 	/**
       
   855 	 * Set focus to the navigation buttons depending on the browsing direction.
       
   856 	 *
       
   857 	 * @since 5.3.0
       
   858 	 *
       
   859 	 * @param {string} which A CSS selector to target the button to focus.
       
   860 	 */
       
   861 	focusNavButton: function( which ) {
       
   862 		$( which ).focus();
   847 	},
   863 	},
   848 
   864 
   849 	getCurrentIndex: function() {
   865 	getCurrentIndex: function() {
   850 		return this.library.indexOf( this.model );
   866 		return this.library.indexOf( this.model );
   851 	},
   867 	},
   864 	keyEvent: function( event ) {
   880 	keyEvent: function( event ) {
   865 		if ( ( 'INPUT' === event.target.nodeName || 'TEXTAREA' === event.target.nodeName ) && ! ( event.target.readOnly || event.target.disabled ) ) {
   881 		if ( ( 'INPUT' === event.target.nodeName || 'TEXTAREA' === event.target.nodeName ) && ! ( event.target.readOnly || event.target.disabled ) ) {
   866 			return;
   882 			return;
   867 		}
   883 		}
   868 
   884 
   869 		// The right arrow key
   885 		// The right arrow key.
   870 		if ( 39 === event.keyCode ) {
   886 		if ( 39 === event.keyCode ) {
   871 			this.nextMediaItem();
   887 			this.nextMediaItem();
   872 		}
   888 		}
   873 		// The left arrow key
   889 		// The left arrow key.
   874 		if ( 37 === event.keyCode ) {
   890 		if ( 37 === event.keyCode ) {
   875 			this.previousMediaItem();
   891 			this.previousMediaItem();
   876 		}
   892 		}
   877 	},
   893 	},
   878 
   894 
   939 	toggleBulkEditHandler: function() {
   955 	toggleBulkEditHandler: function() {
   940 		var toolbar = this.controller.content.get().toolbar, children;
   956 		var toolbar = this.controller.content.get().toolbar, children;
   941 
   957 
   942 		children = toolbar.$( '.media-toolbar-secondary > *, .media-toolbar-primary > *' );
   958 		children = toolbar.$( '.media-toolbar-secondary > *, .media-toolbar-primary > *' );
   943 
   959 
   944 		// TODO: the Frame should be doing all of this.
   960 		// @todo The Frame should be doing all of this.
   945 		if ( this.controller.isModeActive( 'select' ) ) {
   961 		if ( this.controller.isModeActive( 'select' ) ) {
   946 			this.model.set( {
   962 			this.model.set( {
   947 				size: 'large',
   963 				size: 'large',
   948 				text: l10n.cancel
   964 				text: l10n.cancel
   949 			} );
   965 			} );
   950 			children.not( '.spinner, .media-button' ).hide();
   966 			children.not( '.spinner, .media-button' ).hide();
   951 			this.$el.show();
   967 			this.$el.show();
       
   968 			toolbar.$el.addClass( 'media-toolbar-mode-select' );
   952 			toolbar.$( '.delete-selected-button' ).removeClass( 'hidden' );
   969 			toolbar.$( '.delete-selected-button' ).removeClass( 'hidden' );
   953 		} else {
   970 		} else {
   954 			this.model.set( {
   971 			this.model.set( {
   955 				size: '',
   972 				size: '',
   956 				text: l10n.bulkSelect
   973 				text: l10n.bulkSelect
   957 			} );
   974 			} );
   958 			this.controller.content.get().$el.removeClass( 'fixed' );
   975 			this.controller.content.get().$el.removeClass( 'fixed' );
   959 			toolbar.$el.css( 'width', '' );
   976 			toolbar.$el.css( 'width', '' );
       
   977 			toolbar.$el.removeClass( 'media-toolbar-mode-select' );
   960 			toolbar.$( '.delete-selected-button' ).addClass( 'hidden' );
   978 			toolbar.$( '.delete-selected-button' ).addClass( 'hidden' );
   961 			children.not( '.media-button' ).show();
   979 			children.not( '.media-button' ).show();
   962 			this.controller.state().get( 'selection' ).reset();
   980 			this.controller.state().get( 'selection' ).reset();
   963 		}
   981 		}
   964 	}
   982 	}