|
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 |
|
|
91 | 91 | * @global wp.Uploader |
92 | 92 | */ |
93 | 93 | initialize: function() { |
| 94 | + var self = this; |
94 | 95 | _.defaults( this.options, { |
95 | 96 | title: l10n.mediaLibraryTitle, |
96 | 97 | modal: false, |
|
140 | 141 | this.createStates(); |
141 | 142 | this.bindHandlers(); |
142 | 143 | this.render(); |
| 144 | + |
| 145 | + // Set up the Backbone router after a brief delay |
| 146 | + _.delay( function(){ |
| 147 | + wp.media.mediarouter = new media.view.Frame.Router( self ); |
| 148 | + // Verify pushState support and activate |
| 149 | + if ( window.history && window.history.pushState ) { |
| 150 | + Backbone.history.start({ |
| 151 | + root: mediaGridSettings.adminUrl, |
| 152 | + pushState: true |
| 153 | + }); |
| 154 | + } |
| 155 | + }, 250); |
| 156 | + |
| 157 | + // Update the URL when entering search string (at most once per second) |
| 158 | + $( '#media-search-input' ).on( 'input', _.debounce( function() { |
| 159 | + var $val = $( this ).val(); |
| 160 | + wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( ( '' === $val ) ? '' : ( '?search=' + $val ) ) ); |
| 161 | + }, 1000 ) ); |
143 | 162 | }, |
144 | 163 |
|
145 | 164 | createSelection: function() { |
|
218 | 237 | * Open the Edit Attachment modal. |
219 | 238 | */ |
220 | 239 | editAttachment: function( model ) { |
221 | | - var library = this.state().get('library'); |
| 240 | + var self = this, |
| 241 | + library = this.state().get('library'); |
222 | 242 |
|
223 | 243 | // Create a new EditAttachment frame, passing along the library and the attachment model. |
224 | | - this.editAttachmentFrame = new media.view.Frame.EditAttachment({ |
| 244 | + this.editAttachmentFrame = new media.view.Frame.EditAttachments({ |
225 | 245 | library: library, |
226 | 246 | model: model |
227 | 247 | }); |
228 | 248 |
|
229 | 249 | // Listen to events on the edit attachment frame for triggering pagination callback handlers. |
230 | 250 | this.listenTo( this.editAttachmentFrame, 'edit:attachment:next', this.editNextAttachment ); |
231 | 251 | this.listenTo( this.editAttachmentFrame, 'edit:attachment:previous', this.editPreviousAttachment ); |
| 252 | + // Listen to keyboard events on the modal |
| 253 | + $( 'body' ).on( 'keydown.media-modal', function( e ) { |
| 254 | + self.editAttachmentFrame.keyEvent( e ); |
| 255 | + } ); |
232 | 256 | }, |
233 | 257 |
|
234 | 258 | /** |
|
299 | 323 | } |
300 | 324 | }); |
301 | 325 |
|
| 326 | + /** |
| 327 | + * A router for handling the browser history and application state |
| 328 | + */ |
| 329 | + media.view.Frame.Router = Backbone.Router.extend({ |
| 330 | + |
| 331 | + mediaFrame: '', |
| 332 | + |
| 333 | + initialize: function( mediaFrame ){ |
| 334 | + this.mediaFrame = mediaFrame; |
| 335 | + }, |
| 336 | + |
| 337 | + routes: { |
| 338 | + 'upload.php?item=:slug': 'showitem', |
| 339 | + 'upload.php?search=:query': 'search', |
| 340 | + ':default': 'defaultRoute' |
| 341 | + }, |
| 342 | + |
| 343 | + // Map routes against the page URL |
| 344 | + baseUrl: function( url ) { |
| 345 | + return 'upload.php' + url; |
| 346 | + }, |
| 347 | + |
| 348 | + // Respond to the search route by filling the search field and trigggering the input event |
| 349 | + search: function( query ) { |
| 350 | + // Ensure modal closed, see back button |
| 351 | + this.closeModal(); |
| 352 | + $( '#media-search-input' ).val( query ).trigger( 'input' ); |
| 353 | + }, |
| 354 | + |
| 355 | + // Show the modal with a specific item |
| 356 | + showitem: function( query ) { |
| 357 | + var library = this.mediaFrame.state().get('library'); |
| 358 | + |
| 359 | + // Remove existing modal if present |
| 360 | + this.closeModal(); |
| 361 | + // Trigger the media frame to open the correct item |
| 362 | + this.mediaFrame.trigger( 'edit:attachment', library.findWhere( { id: parseInt( query, 10 ) } ) ); |
| 363 | + }, |
| 364 | + |
| 365 | + // Close the modal if set up |
| 366 | + closeModal: function() { |
| 367 | + if ( 'undefined' !== typeof this.mediaFrame.editAttachmentFrame ) { |
| 368 | + this.mediaFrame.editAttachmentFrame.modal.close(); |
| 369 | + } |
| 370 | + }, |
| 371 | + |
| 372 | + // Default route: make sure the modal and search are reset |
| 373 | + defaultRoute: function() { |
| 374 | + this.closeModal(); |
| 375 | + $( '#media-search-input' ).val( '' ).trigger( 'input' ); |
| 376 | + } |
| 377 | + }); |
| 378 | + |
302 | 379 | /** |
303 | 380 | * A frame for editing the details of a specific media item. |
304 | 381 | * |
305 | 382 | * Opens in a modal by default. |
306 | 383 | * |
307 | 384 | * Requires an attachment model to be passed in the options hash under `model`. |
308 | 385 | */ |
309 | | - media.view.Frame.EditAttachment = media.view.Frame.extend({ |
| 386 | + media.view.Frame.EditAttachments = media.view.Frame.extend({ |
310 | 387 |
|
311 | 388 | className: 'edit-attachment-frame', |
312 | 389 | template: media.template( 'edit-attachment-frame' ), |
|
328 | 405 | state: 'edit-attachment' |
329 | 406 | }); |
330 | 407 |
|
| 408 | + this.library = this.options.library; |
| 409 | + if ( this.options.model ) { |
| 410 | + this.model = this.options.model; |
| 411 | + } else { |
| 412 | + this.model = this.library.at( 0 ); |
| 413 | + } |
| 414 | + |
331 | 415 | this.createStates(); |
332 | 416 |
|
333 | 417 | this.on( 'content:render:edit-metadata', this.editMetadataContent, this ); |
334 | 418 | this.on( 'content:render:edit-image', this.editImageContentUgh, this ); |
335 | 419 |
|
336 | 420 | // Only need a tab to Edit Image for images. |
337 | | - if ( this.model.get( 'type' ) === 'image' ) { |
| 421 | + if ( 'undefined' !== typeof this.model && this.model.get( 'type' ) === 'image' ) { |
338 | 422 | this.on( 'router:create', this.createRouter, this ); |
339 | 423 | this.on( 'router:render', this.browseRouter, this ); |
340 | 424 | } |
|
352 | 436 | // Completely destroy the modal DOM element when closing it. |
353 | 437 | this.modal.close = function() { |
354 | 438 | self.modal.remove(); |
| 439 | + $( 'body' ).off( 'keydown.media-modal' ); /* remove the keydown event */ |
355 | 440 | }; |
356 | 441 |
|
357 | 442 | this.modal.content( this ); |
|
391 | 476 | model: this.model |
392 | 477 | }); |
393 | 478 | this.content.set( view ); |
| 479 | + // Update browser url when navigating media details |
| 480 | + wp.media.mediarouter.navigate( wp.media.mediarouter.baseUrl( '?item=' + this.model.id ) ); |
394 | 481 | }, |
395 | 482 |
|
396 | 483 | /** |
|
461 | 548 | return; |
462 | 549 | this.modal.close(); |
463 | 550 | this.trigger( 'edit:attachment:next', this.model ); |
| 551 | + }, |
| 552 | + |
| 553 | + getCurrentIndex: function() { |
| 554 | + return this.library.indexOf( this.model ); |
| 555 | + }, |
| 556 | + |
| 557 | + hasNext: function() { |
| 558 | + return ( this.getCurrentIndex() + 1 ) < this.library.length; |
| 559 | + }, |
| 560 | + |
| 561 | + hasPrevious: function() { |
| 562 | + return ( this.getCurrentIndex() - 1 ) > -1; |
| 563 | + }, |
| 564 | + /** |
| 565 | + * Respond to the keyboard events: right arrow, left arrow, escape. |
| 566 | + */ |
| 567 | + keyEvent: function( event ) { |
| 568 | + var $target = $( event.target ); |
| 569 | + // Pressing the escape key routes back to main url |
| 570 | + if ( event.keyCode === 27 ) { |
| 571 | + this.resetRoute(); |
| 572 | + return event; |
| 573 | + } |
| 574 | + //Don't go left/right if we are in a textarea or input field |
| 575 | + if ( $target.is( 'input' ) || $target.is( 'textarea' ) ) { |
| 576 | + return event; |
| 577 | + } |
| 578 | + // The right arrow key |
| 579 | + if ( event.keyCode === 39 ) { |
| 580 | + if ( ! this.hasNext ) { return; } |
| 581 | + _.debounce( this.nextMediaItem(), 250 ); |
| 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; |
464 | 593 | } |
465 | 594 | }); |
466 | 595 |
|
|
0 commit comments