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 } |