Ticket #24716: 24716.29.diff
File 24716.29.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 if ( '' !== $( this ).val() ) { 188 wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( '?search=' + $( this ).val() ) ); 189 } 190 }, 1000 ) ); 171 191 }, 172 192 173 193 createSelection: function() { … … 213 233 214 234 // Handle a frame-level event for editing an attachment. 215 235 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 236 }, 219 237 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 238 /** 233 239 * Open the Edit Attachment modal. 234 240 */ 235 241 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 242 var self = this; 243 // Create a new EditAttachment frame, passing along the library. 244 this.editAttachmentFrame = new media.view.Frame.EditAttachments({ 245 library: this.state().get('library'), 246 model: model 255 247 }); 248 $( 'body' ).on( 'keydown.media-modal', function( e ) { 249 self.editAttachmentFrame.keyEvent( e ); 250 } ); 256 251 }, 257 252 258 253 /** … … 324 319 }); 325 320 326 321 /** 322 * A router for handling the browser history and application state 323 */ 324 media.view.Frame.Router = Backbone.Router.extend({ 325 326 mediaFrame: '', 327 328 initialize: function( mediaFrame ){ 329 this.mediaFrame = mediaFrame; 330 }, 331 332 routes: { 333 'upload.php?item=:slug': 'showitem', 334 'upload.php?search=:query': 'search', 335 ':default': 'defaultRoute' 336 }, 337 338 // Map routes against the page URL 339 baseUrl: function( url ) { 340 return 'upload.php' + url; 341 }, 342 343 // Respond to the search route by filling the search field and trigggering the input event 344 search: function( query ) { 345 // Ensure modal closed, see back button 346 this.closeModal(); 347 $( '#media-search-input' ).val( query ).trigger( 'input' ); 348 }, 349 350 // Show the modal with a specific item 351 showitem: function( query ) { 352 var library = this.mediaFrame.state().get('library'); 353 354 // Remove existing modal if present 355 this.closeModal(); 356 // Trigger the media frame to open the correct item 357 this.mediaFrame.trigger( 'edit:attachment', library.findWhere( { id: parseInt( query, 10 ) } ) ); 358 }, 359 360 // Close the modal if set up 361 closeModal: function() { 362 if ( 'undefined' !== typeof this.mediaFrame.editAttachmentFrame ) { 363 this.mediaFrame.editAttachmentFrame.modal.close(); 364 } 365 }, 366 367 // Default route: make sure the modal and search are reset 368 defaultRoute: function() { 369 this.closeModal(); 370 $( '#media-search-input' ).val( '' ).trigger( 'input' ); 371 } 372 }); 373 374 /** 327 375 * A frame for editing the details of a specific media item. 328 376 * 329 377 * Opens in a modal by default. … … 330 378 * 331 379 * Requires an attachment model to be passed in the options hash under `model`. 332 380 */ 333 media.view.Frame.EditAttachment = media.view.Frame.extend({381 media.view.Frame.EditAttachments = media.view.Frame.extend({ 334 382 335 383 className: 'edit-attachment-frame', 336 384 template: media.template( 'edit-attachment-frame' ), … … 352 400 state: 'edit-attachment' 353 401 }); 354 402 403 this.library = this.options.library; 404 if ( this.options.model ) { 405 this.model = this.options.model; 406 } else { 407 this.model = this.library.at( 0 ); 408 } 409 355 410 this.createStates(); 356 411 357 412 this.on( 'content:render:edit-metadata', this.editMetadataContent, this ); … … 358 413 this.on( 'content:render:edit-image', this.editImageContentUgh, this ); 359 414 360 415 // Only need a tab to Edit Image for images. 361 if ( this.model.get( 'type' ) === 'image' ) {416 if ( 'undefined' !== typeof this.model && this.model.get( 'type' ) === 'image' ) { 362 417 this.on( 'router:create', this.createRouter, this ); 363 418 this.on( 'router:render', this.browseRouter, this ); 364 419 } … … 373 428 // Completely destroy the modal DOM element when closing it. 374 429 this.modal.close = function() { 375 430 self.modal.remove(); 431 $( 'body' ).off( 'keydown.media-modal' ); /* remove the keydown event */ 432 // Reset the browser URL 433 self.resetRoute(); 376 434 }; 377 435 378 436 this.modal.content( this ); … … 412 470 model: this.model 413 471 }); 414 472 this.content.set( view ); 473 // Update browser url when navigating media details 474 wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( '?item=' + this.model.id ) ); 415 475 }, 416 476 417 477 /** … … 464 524 }); 465 525 }, 466 526 527 getCurrentIndex: function() { 528 return this.library.indexOf( this.model ); 529 }, 530 531 hasNext: function() { 532 return ( this.getCurrentIndex() + 1 ) < this.library.length; 533 }, 534 535 hasPrevious: function() { 536 return ( this.getCurrentIndex() - 1 ) > -1; 537 }, 538 467 539 /** 468 540 * Click handler to switch to the previous media item. 469 541 */ 470 542 previousMediaItem: function() { 471 if ( ! this. options.hasPrevious )543 if ( ! this.hasPrevious() ) { 472 544 return; 473 this.modal.close(); 474 this.options.gridController.trigger( 'edit:attachment:previous', this.model ); 545 } 546 this.model = this.library.at( this.getCurrentIndex() - 1 ); 547 this.editMetadataContent(); 475 548 }, 476 549 477 550 /** … … 478 551 * Click handler to switch to the next media item. 479 552 */ 480 553 nextMediaItem: function() { 481 if ( ! this. options.hasNext )554 if ( ! this.hasNext() ) { 482 555 return; 483 this.modal.close(); 484 this.options.gridController.trigger( 'edit:attachment:next', this.model ); 556 } 557 this.model = this.library.at( this.getCurrentIndex() + 1 ); 558 this.editMetadataContent(); 559 }, 560 /** 561 * Respond to the keyboard events: right arrow, left arrow, escape. 562 */ 563 keyEvent: function( event ) { 564 var $target = $( event.target ); 565 566 // Pressing the escape key routes back to main url 567 if ( event.keyCode === 27 ) { 568 this.resetRoute(); 569 return event; 570 } 571 572 //Don't go left/right if we are in a textarea or input field 573 if ( $target.is( 'input' ) || $target.is( 'textarea' ) ) { 574 return event; 575 } 576 577 // The right arrow key 578 if ( event.keyCode === 39 ) { 579 if ( ! this.hasNext ) { return; } 580 _.debounce( this.nextMediaItem(), 250 ); 581 } 582 583 // The left arrow key 584 if ( event.keyCode === 37 ) { 585 if ( ! this.hasPrevious ) { return; } 586 _.debounce( this.previousMediaItem(), 250 ); 587 } 588 }, 589 590 resetRoute: function() { 591 wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( '' ) ); 592 return; 485 593 } 486 487 594 }); 488 595 489 596 media.view.GridFieldOptions = media.View.extend({