Ticket #24716: 24716.31.diff
File 24716.31.diff, 8.9 KB (added by , 10 years ago) |
---|
-
src/wp-admin/upload.php
24 24 wp_enqueue_media(); 25 25 wp_enqueue_script( 'media-grid' ); 26 26 wp_enqueue_script( 'media' ); 27 wp_localize_script( 'media-grid', 'mediaGridSettings', array( 'adminUrl' => parse_url( self_admin_url(), PHP_URL_PATH ) ) ); 27 28 28 29 require_once( ABSPATH . 'wp-admin/admin-header.php' ); 29 30 include( ABSPATH . 'wp-admin/admin-footer.php' ); -
src/wp-includes/js/media-grid.js
1 /* global _wpMediaViewsL10n, setUserSetting, deleteUserSetting, MediaElementPlayer 1 /* global _wpMediaViewsL10n, setUserSetting, deleteUserSetting, MediaElementPlayer, mediaGridSettings*/ 2 2 (function($, _, Backbone, wp) { 3 3 var media = wp.media, l10n; 4 4 … … 120 120 * @global wp.Uploader 121 121 */ 122 122 initialize: function() { 123 var self = this; 123 124 _.defaults( this.options, { 124 125 title: l10n.mediaLibraryTitle, 125 126 modal: false, … … 168 169 this.createStates(); 169 170 this.bindHandlers(); 170 171 this.render(); 172 173 // Set up the Backbone router after a brief delay 174 _.delay( function(){ 175 wp.media.mediarouter = new media.view.Frame.Router( self ); 176 // Verify pushState support and activate 177 if ( window.history && window.history.pushState ) { 178 Backbone.history.start({ 179 root: mediaGridSettings.adminUrl, 180 pushState: true 181 }); 182 } 183 }, 150); 184 185 // Update the URL when entering search string (at most once per second) 186 $( '#media-search-input' ).on( 'input', _.debounce( function() { 187 var $val = $( this ).val(); 188 wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( ( '' == $val ) ? '' : ( '?search=' + $val ) ) ); 189 }, 1000 ) ); 171 190 }, 172 191 173 192 createSelection: function() { … … 213 232 214 233 // Handle a frame-level event for editing an attachment. 215 234 this.on( 'edit:attachment', this.editAttachment, this ); 216 this.on( 'edit:attachment:next', this.editNextAttachment, this );217 this.on( 'edit:attachment:previous', this.editPreviousAttachment, this );218 235 }, 219 236 220 editPreviousAttachment: function( currentModel ) {221 var library = this.state().get('library'),222 currentModelIndex = library.indexOf( currentModel );223 this.trigger( 'edit:attachment', library.at( currentModelIndex - 1 ) );224 },225 226 editNextAttachment: function( currentModel ) {227 var library = this.state().get('library'),228 currentModelIndex = library.indexOf( currentModel );229 this.trigger( 'edit:attachment', library.at( currentModelIndex + 1 ) );230 },231 232 237 /** 233 238 * Open the Edit Attachment modal. 234 239 */ 235 240 editAttachment: function( model ) { 236 var library = this.state().get('library'), hasPrevious, hasNext; 237 if ( library.indexOf( model ) > 0 ) { 238 hasPrevious = true; 239 } 240 else { 241 hasPrevious = false; 242 } 243 if ( library.indexOf( model ) < library.length - 1 ) { 244 hasNext = true; 245 } 246 else { 247 hasNext = false; 248 } 249 250 new media.view.Frame.EditAttachment({ 251 hasPrevious: hasPrevious, 252 hasNext: hasNext, 253 model: model, 254 gridController: this 241 var self = this; 242 // Create a new EditAttachment frame, passing along the library. 243 this.editAttachmentFrame = new media.view.Frame.EditAttachments({ 244 library: this.state().get('library'), 245 model: model 255 246 }); 247 $( 'body' ).on( 'keydown.media-modal', function( e ) { 248 self.editAttachmentFrame.keyEvent( e ); 249 } ); 256 250 }, 257 251 258 252 /** … … 324 318 }); 325 319 326 320 /** 321 * A router for handling the browser history and application state 322 */ 323 media.view.Frame.Router = Backbone.Router.extend({ 324 325 mediaFrame: '', 326 327 initialize: function( mediaFrame ){ 328 this.mediaFrame = mediaFrame; 329 }, 330 331 routes: { 332 'upload.php?item=:slug': 'showitem', 333 'upload.php?search=:query': 'search', 334 ':default': 'defaultRoute' 335 }, 336 337 // Map routes against the page URL 338 baseUrl: function( url ) { 339 return 'upload.php' + url; 340 }, 341 342 // Respond to the search route by filling the search field and trigggering the input event 343 search: function( query ) { 344 // Ensure modal closed, see back button 345 this.closeModal(); 346 $( '#media-search-input' ).val( query ).trigger( 'input' ); 347 }, 348 349 // Show the modal with a specific item 350 showitem: function( query ) { 351 var library = this.mediaFrame.state().get('library'); 352 353 // Remove existing modal if present 354 this.closeModal(); 355 // Trigger the media frame to open the correct item 356 this.mediaFrame.trigger( 'edit:attachment', library.findWhere( { id: parseInt( query, 10 ) } ) ); 357 }, 358 359 // Close the modal if set up 360 closeModal: function() { 361 if ( 'undefined' !== typeof this.mediaFrame.editAttachmentFrame ) { 362 this.mediaFrame.editAttachmentFrame.modal.close(); 363 } 364 }, 365 366 // Default route: make sure the modal and search are reset 367 defaultRoute: function() { 368 this.closeModal(); 369 $( '#media-search-input' ).val( '' ).trigger( 'input' ); 370 } 371 }); 372 373 /** 327 374 * A frame for editing the details of a specific media item. 328 375 * 329 376 * Opens in a modal by default. … … 330 377 * 331 378 * Requires an attachment model to be passed in the options hash under `model`. 332 379 */ 333 media.view.Frame.EditAttachment = media.view.Frame.extend({380 media.view.Frame.EditAttachments = media.view.Frame.extend({ 334 381 335 382 className: 'edit-attachment-frame', 336 383 template: media.template( 'edit-attachment-frame' ), … … 352 399 state: 'edit-attachment' 353 400 }); 354 401 402 this.library = this.options.library; 403 if ( this.options.model ) { 404 this.model = this.options.model; 405 } else { 406 this.model = this.library.at( 0 ); 407 } 408 355 409 this.createStates(); 356 410 357 411 this.on( 'content:render:edit-metadata', this.editMetadataContent, this ); … … 358 412 this.on( 'content:render:edit-image', this.editImageContentUgh, this ); 359 413 360 414 // Only need a tab to Edit Image for images. 361 if ( this.model.get( 'type' ) === 'image' ) {415 if ( 'undefined' !== typeof this.model && this.model.get( 'type' ) === 'image' ) { 362 416 this.on( 'router:create', this.createRouter, this ); 363 417 this.on( 'router:render', this.browseRouter, this ); 364 418 } … … 373 427 // Completely destroy the modal DOM element when closing it. 374 428 this.modal.close = function() { 375 429 self.modal.remove(); 430 $( 'body' ).off( 'keydown.media-modal' ); /* remove the keydown event */ 431 // Reset the browser URL 432 self.resetRoute(); 376 433 }; 377 434 378 435 this.modal.content( this ); … … 412 469 model: this.model 413 470 }); 414 471 this.content.set( view ); 472 // Update browser url when navigating media details 473 wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( '?item=' + this.model.id ) ); 415 474 }, 416 475 417 476 /** … … 464 523 }); 465 524 }, 466 525 526 getCurrentIndex: function() { 527 return this.library.indexOf( this.model ); 528 }, 529 530 hasNext: function() { 531 return ( this.getCurrentIndex() + 1 ) < this.library.length; 532 }, 533 534 hasPrevious: function() { 535 return ( this.getCurrentIndex() - 1 ) > -1; 536 }, 537 467 538 /** 468 539 * Click handler to switch to the previous media item. 469 540 */ 470 541 previousMediaItem: function() { 471 if ( ! this. options.hasPrevious )542 if ( ! this.hasPrevious() ) { 472 543 return; 473 this.modal.close(); 474 this.options.gridController.trigger( 'edit:attachment:previous', this.model ); 544 } 545 this.model = this.library.at( this.getCurrentIndex() - 1 ); 546 this.editMetadataContent(); 475 547 }, 476 548 477 549 /** … … 478 550 * Click handler to switch to the next media item. 479 551 */ 480 552 nextMediaItem: function() { 481 if ( ! this. options.hasNext )553 if ( ! this.hasNext() ) { 482 554 return; 483 this.modal.close(); 484 this.options.gridController.trigger( 'edit:attachment:next', this.model ); 555 } 556 this.model = this.library.at( this.getCurrentIndex() + 1 ); 557 this.editMetadataContent(); 558 }, 559 /** 560 * Respond to the keyboard events: right arrow, left arrow, escape. 561 */ 562 keyEvent: function( event ) { 563 var $target = $( event.target ); 564 565 // Pressing the escape key routes back to main url 566 if ( event.keyCode === 27 ) { 567 this.resetRoute(); 568 return event; 569 } 570 571 //Don't go left/right if we are in a textarea or input field 572 if ( $target.is( 'input' ) || $target.is( 'textarea' ) ) { 573 return event; 574 } 575 576 // The right arrow key 577 if ( event.keyCode === 39 ) { 578 if ( ! this.hasNext ) { return; } 579 _.debounce( this.nextMediaItem(), 250 ); 580 } 581 582 // The left arrow key 583 if ( event.keyCode === 37 ) { 584 if ( ! this.hasPrevious ) { return; } 585 _.debounce( this.previousMediaItem(), 250 ); 586 } 587 }, 588 589 resetRoute: function() { 590 wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( '' ) ); 591 return; 485 592 } 486 487 593 }); 488 594 489 595 media.view.GridFieldOptions = media.View.extend({