Make WordPress Core

Changeset 22046


Ignore:
Timestamp:
09/27/2012 06:53:54 AM (14 years ago)
Author:
koopersmith
Message:

Media JS: Use a custom Attachment views for both the media library and gallery screens.

To do so, the Attachment view code had to be shifted above the Workspace view code to ensure the subview is defined (preventing errors).

Also corrects an error in wp.media.view.Attachments.add where it was still using the default Attachment view.

see #21390, #21809.

Location:
trunk/wp-includes
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/css/media-views.css

    r21909 r22046  
    249249}
    250250
    251 .attachment.selected {
     251.attachment.library.selected {
    252252        border-color: #21759b;
    253253}
    254254
    255 .attachment.selected:after {
     255.attachment.library.selected:after {
    256256        content: '\2713';
    257257        display: block;
  • trunk/wp-includes/js/media-views.js

    r22045 r22046  
    368368
    369369        /**
    370          * wp.media.view.Workspace
    371          */
    372         media.view.Workspace = Backbone.View.extend({
    373                 tagName:   'div',
    374                 className: 'media-workspace',
    375                 template:  media.template('media-workspace'),
    376 
    377                 // The single `Attachment` view to be used in the `Attachments` view.
    378                 AttachmentView: media.view.Attachment,
    379 
    380                 events: {
    381                         'dragenter':  'maybeInitUploader',
    382                         'mouseenter': 'maybeInitUploader'
    383                 },
    384 
    385                 initialize: function() {
    386                         this.controller = this.options.controller;
    387 
    388                         _.defaults( this.options, {
    389                                 selectOne: false,
    390                                 uploader:  {}
    391                         });
    392 
    393                         this.$content = $('<div class="existing-attachments" />');
    394 
    395                         this.attachmentsView = new media.view.Attachments({
    396                                 controller: this.controller,
    397                                 directions: this.controller.get('multiple') ? l10n.selectMediaMultiple : l10n.selectMediaSingular,
    398                                 collection: this.collection,
    399 
    400                                 AttachmentView: this.AttachmentView
    401                         });
    402 
    403                         this.$content.append( this.attachmentsView.$el );
    404 
    405                         // Track uploading attachments.
    406                         wp.Uploader.queue.on( 'add remove reset change:percent', this.renderUploadProgress, this );
    407                         wp.Uploader.queue.on( 'add', this.selectUpload, this );
    408                 },
    409 
    410                 render: function() {
    411                         this.$content.detach();
    412 
    413                         this.attachmentsView.render();
    414                         this.renderUploadProgress();
    415                         this.$el.html( this.template( this.options ) ).append( this.$content );
    416                         this.$bar = this.$('.upload-attachments .media-progress-bar div');
    417                         return this;
    418                 },
    419 
    420                 maybeInitUploader: function() {
    421                         var workspace = this;
    422 
    423                         // If the uploader already exists or the body isn't in the DOM, bail.
    424                         if ( this.uploader || ! this.$el.closest('body').length )
    425                                 return;
    426 
    427                         this.uploader = new wp.Uploader( _.extend({
    428                                 container: this.$el,
    429                                 dropzone:  this.$el,
    430                                 browser:   this.$('.upload-attachments a')
    431                         }, this.options.uploader ) );
    432                 },
    433 
    434                 selectUpload: function( attachment ) {
    435                         this.controller.selection.add( attachment );
    436                 },
    437 
    438                 renderUploadProgress: function() {
    439                         var queue = wp.Uploader.queue;
    440 
    441                         this.$el.toggleClass( 'uploading', !! queue.length );
    442 
    443                         if ( ! this.$bar || ! queue.length )
    444                                 return;
    445 
    446                         this.$bar.width( ( queue.reduce( function( memo, attachment ) {
    447                                 if ( attachment.get('uploading') )
    448                                         return memo + ( attachment.get('percent') || 0 );
    449                                 else
    450                                         return memo + 100;
    451                         }, 0 ) / queue.length ) + '%' );
    452                 }
    453         });
    454 
    455         /**
    456          * wp.media.view.Workspace.Library
    457          */
    458         media.view.Workspace.Library = media.view.Workspace.extend({
    459                 // The single `Attachment` view to be used in the `Attachments` view.
    460                 // AttachmentView: media.view.Attachment.Library,
    461 
    462                 initialize: function() {
    463                         media.view.Workspace.prototype.initialize.apply( this, arguments );
    464 
    465                         // If this supports multiple attachments, initialize the sample toolbar view.
    466                         if ( this.controller.get('multiple') )
    467                                 this.initToolbarView();
    468                 },
    469 
    470                 // Initializes the toolbar view. Currently uses defaults set for
    471                 // inserting media into a post. This should be pulled out into the
    472                 // appropriate workflow when the time comes, but is currently here
    473                 // to test multiple selections.
    474                 initToolbarView: function() {
    475                         var controller = this.controller;
    476 
    477                         this.toolbarView = new media.view.Toolbar({
    478                                 items: {
    479                                         'selection-preview': new media.view.SelectionPreview({
    480                                                 controller: this.controller,
    481                                                 collection: this.controller.selection,
    482                                                 priority: -40
    483                                         }),
    484 
    485                                         'create-new-gallery': {
    486                                                 style:    'primary',
    487                                                 text:     l10n.createNewGallery,
    488                                                 priority: 40,
    489 
    490                                                 click: function() {
    491                                                         controller.render('gallery');
    492                                                 }
    493                                         },
    494 
    495                                         'insert-into-post': {
    496                                                 text:     l10n.insertIntoPost,
    497                                                 priority: 30,
    498                                                 click:    _.bind( controller.update, controller )
    499                                         },
    500 
    501                                         'add-to-gallery': {
    502                                                 text:     l10n.addToGallery,
    503                                                 priority: 20
    504                                         }
    505                                 }
    506                         });
    507 
    508                         this.controller.selection.on( 'add remove', function() {
    509                                 var count = this.controller.selection.length,
    510                                         showGallery;
    511 
    512                                 this.$el.toggleClass( 'with-toolbar', !! count );
    513 
    514                                 // Check if every attachment in the selection is an image.
    515                                 showGallery = count > 1 && this.controller.selection.all( function( attachment ) {
    516                                         return 'image' === attachment.get('type');
    517                                 });
    518 
    519                                 this.toolbarView.get('create-new-gallery').$el.toggle( showGallery );
    520                                 insert = this.toolbarView.get('insert-into-post');
    521                                 insert.model.set( 'style', showGallery ? '' : 'primary' );
    522                         }, this );
    523 
    524                         this.$content.append( this.toolbarView.$el );
    525                 }
    526         });
    527 
    528         /**
    529          * wp.media.view.Workspace.Gallery
    530          */
    531         media.view.Workspace.Gallery = media.view.Workspace.extend({
    532                 // The single `Attachment` view to be used in the `Attachments` view.
    533                 // AttachmentView: media.view.Attachment.Gallery,
    534 
    535                 initialize: function() {
    536                         media.view.Workspace.prototype.initialize.apply( this, arguments );
    537                         this.initToolbarView();
    538                 },
    539 
    540                 // Initializes the toolbar view. Currently uses defaults set for
    541                 // inserting media into a post. This should be pulled out into the
    542                 // appropriate workflow when the time comes, but is currently here
    543                 // to test multiple selections.
    544                 initToolbarView: function() {
    545                         var controller = this.controller;
    546 
    547                         this.toolbarView = new media.view.Toolbar({
    548                                 items: {
    549                                         'return-to-library': {
    550                                                 text:     l10n.returnToLibrary,
    551                                                 priority: -40,
    552 
    553                                                 click:  function() {
    554                                                         controller.render('library');
    555                                                 }
    556                                         },
    557 
    558                                         'insert-gallery-into-post': {
    559                                                 style:    'primary',
    560                                                 text:     l10n.insertGalleryIntoPost,
    561                                                 priority: 40,
    562                                                 click:    _.bind( controller.update, controller )
    563                                         },
    564 
    565                                         'add-images-from-library': {
    566                                                 text:     l10n.addImagesFromLibrary,
    567                                                 priority: 30
    568                                         }
    569                                 }
    570                         });
    571 
    572                         this.$el.addClass('with-toolbar');
    573                         this.$content.append( this.toolbarView.$el );
    574                 }
    575         });
    576 
    577 
    578         /**
    579          * wp.media.view.Attachments
    580          */
    581         media.view.Attachments = Backbone.View.extend({
    582                 tagName:   'div',
    583                 className: 'attachments',
    584                 template:  media.template('attachments'),
    585 
    586                 events: {
    587                         'keyup input': 'search'
    588                 },
    589 
    590                 initialize: function() {
    591                         this.controller = this.options.controller;
    592 
    593                         _.defaults( this.options, {
    594                                 refreshSensitivity: 200,
    595                                 refreshThreshold:   3,
    596                                 AttachmentView:     media.view.Attachment
    597                         });
    598 
    599                         _.each(['add','remove'], function( method ) {
    600                                 this.collection.on( method, function( attachment, attachments, options ) {
    601                                         this[ method ]( attachment, options.index );
    602                                 }, this );
    603                         }, this );
    604 
    605                         this.collection.on( 'reset', this.refresh, this );
    606 
    607                         this.$list = $('<ul />');
    608                         this.list  = this.$list[0];
    609 
    610                         this.scroll = _.chain( this.scroll ).bind( this ).throttle( this.options.refreshSensitivity ).value();
    611                         this.$list.on( 'scroll.attachments', this.scroll );
    612                 },
    613 
    614                 render: function() {
    615                         // Detach the list from the DOM to prevent event removal.
    616                         this.$list.detach();
    617 
    618                         this.$el.html( this.template( this.options ) ).append( this.$list );
    619                         this.refresh();
    620                         return this;
    621                 },
    622 
    623                 refresh: function() {
    624                         // If there are no elements, load some.
    625                         if ( ! this.collection.length ) {
    626                                 this.collection.more();
    627                                 this.$list.empty();
    628                                 return this;
    629                         }
    630 
    631                         // Otherwise, create all of the Attachment views, and replace
    632                         // the list in a single DOM operation.
    633                         this.$list.html( this.collection.map( function( attachment ) {
    634                                 return new this.options.AttachmentView({
    635                                         controller: this.controller,
    636                                         model:      attachment
    637                                 }).render().$el;
    638                         }, this ) );
    639 
    640                         // Then, trigger the scroll event to check if we're within the
    641                         // threshold to query for additional attachments.
    642                         this.scroll();
    643                         return this;
    644                 },
    645 
    646                 add: function( attachment, index ) {
    647                         var view, children;
    648 
    649                         view = new media.view.Attachment({
    650                                 controller: this.controller,
    651                                 model:      attachment
    652                         }).render();
    653 
    654                         children = this.$list.children();
    655 
    656                         if ( children.length > index )
    657                                 children.eq( index ).before( view.$el );
    658                         else
    659                                 this.$list.append( view.$el );
    660                 },
    661 
    662                 remove: function( attachment, index ) {
    663                         var children = this.$list.children();
    664                         if ( children.length )
    665                                 children.eq( index ).detach();
    666                 },
    667 
    668                 scroll: function( event ) {
    669                         // @todo: is this still necessary?
    670                         if ( ! this.$list.is(':visible') )
    671                                 return;
    672 
    673                         if ( this.list.scrollHeight < this.list.scrollTop + ( this.list.clientHeight * this.options.refreshThreshold ) ) {
    674                                 this.collection.more();
    675                         }
    676                 },
    677 
    678                 search: function( event ) {
    679                         var props = this.collection.props;
    680 
    681                         if ( event.target.value )
    682                                 props.set( 'search', event.target.value );
    683                         else
    684                                 props.unset('search');
    685                 }
    686         });
    687 
    688 
    689         /**
    690370         * wp.media.view.Attachment
    691371         */
    … …  
    770450
    771451        /**
     452         * wp.media.view.Attachment.Library
     453         */
     454        media.view.Attachment.Library = media.view.Attachment.extend({
     455                className: 'attachment library'
     456        });
     457
     458        /**
     459         * wp.media.view.Attachment.Gallery
     460         */
     461        media.view.Attachment.Gallery = media.view.Attachment.extend({
     462                events: {}
     463        });
     464
     465        /**
     466         * wp.media.view.Workspace
     467         */
     468        media.view.Workspace = Backbone.View.extend({
     469                tagName:   'div',
     470                className: 'media-workspace',
     471                template:  media.template('media-workspace'),
     472
     473                // The single `Attachment` view to be used in the `Attachments` view.
     474                AttachmentView: media.view.Attachment,
     475
     476                events: {
     477                        'dragenter':  'maybeInitUploader',
     478                        'mouseenter': 'maybeInitUploader'
     479                },
     480
     481                initialize: function() {
     482                        this.controller = this.options.controller;
     483
     484                        _.defaults( this.options, {
     485                                selectOne: false,
     486                                uploader:  {}
     487                        });
     488
     489                        this.$content = $('<div class="existing-attachments" />');
     490
     491                        this.attachmentsView = new media.view.Attachments({
     492                                controller: this.controller,
     493                                directions: this.controller.get('multiple') ? l10n.selectMediaMultiple : l10n.selectMediaSingular,
     494                                collection: this.collection,
     495
     496                                AttachmentView: this.AttachmentView
     497                        });
     498
     499                        this.$content.append( this.attachmentsView.$el );
     500
     501                        // Track uploading attachments.
     502                        wp.Uploader.queue.on( 'add remove reset change:percent', this.renderUploadProgress, this );
     503                        wp.Uploader.queue.on( 'add', this.selectUpload, this );
     504                },
     505
     506                render: function() {
     507                        this.$content.detach();
     508
     509                        this.attachmentsView.render();
     510                        this.renderUploadProgress();
     511                        this.$el.html( this.template( this.options ) ).append( this.$content );
     512                        this.$bar = this.$('.upload-attachments .media-progress-bar div');
     513                        return this;
     514                },
     515
     516                maybeInitUploader: function() {
     517                        var workspace = this;
     518
     519                        // If the uploader already exists or the body isn't in the DOM, bail.
     520                        if ( this.uploader || ! this.$el.closest('body').length )
     521                                return;
     522
     523                        this.uploader = new wp.Uploader( _.extend({
     524                                container: this.$el,
     525                                dropzone:  this.$el,
     526                                browser:   this.$('.upload-attachments a')
     527                        }, this.options.uploader ) );
     528                },
     529
     530                selectUpload: function( attachment ) {
     531                        this.controller.selection.add( attachment );
     532                },
     533
     534                renderUploadProgress: function() {
     535                        var queue = wp.Uploader.queue;
     536
     537                        this.$el.toggleClass( 'uploading', !! queue.length );
     538
     539                        if ( ! this.$bar || ! queue.length )
     540                                return;
     541
     542                        this.$bar.width( ( queue.reduce( function( memo, attachment ) {
     543                                if ( attachment.get('uploading') )
     544                                        return memo + ( attachment.get('percent') || 0 );
     545                                else
     546                                        return memo + 100;
     547                        }, 0 ) / queue.length ) + '%' );
     548                }
     549        });
     550
     551        /**
     552         * wp.media.view.Workspace.Library
     553         */
     554        media.view.Workspace.Library = media.view.Workspace.extend({
     555                // The single `Attachment` view to be used in the `Attachments` view.
     556                AttachmentView: media.view.Attachment.Library,
     557
     558                initialize: function() {
     559                        media.view.Workspace.prototype.initialize.apply( this, arguments );
     560
     561                        // If this supports multiple attachments, initialize the sample toolbar view.
     562                        if ( this.controller.get('multiple') )
     563                                this.initToolbarView();
     564                },
     565
     566                // Initializes the toolbar view. Currently uses defaults set for
     567                // inserting media into a post. This should be pulled out into the
     568                // appropriate workflow when the time comes, but is currently here
     569                // to test multiple selections.
     570                initToolbarView: function() {
     571                        var controller = this.controller;
     572
     573                        this.toolbarView = new media.view.Toolbar({
     574                                items: {
     575                                        'selection-preview': new media.view.SelectionPreview({
     576                                                controller: this.controller,
     577                                                collection: this.controller.selection,
     578                                                priority: -40
     579                                        }),
     580
     581                                        'create-new-gallery': {
     582                                                style:    'primary',
     583                                                text:     l10n.createNewGallery,
     584                                                priority: 40,
     585
     586                                                click: function() {
     587                                                        controller.render('gallery');
     588                                                }
     589                                        },
     590
     591                                        'insert-into-post': {
     592                                                text:     l10n.insertIntoPost,
     593                                                priority: 30,
     594                                                click:    _.bind( controller.update, controller )
     595                                        },
     596
     597                                        'add-to-gallery': {
     598                                                text:     l10n.addToGallery,
     599                                                priority: 20
     600                                        }
     601                                }
     602                        });
     603
     604                        this.controller.selection.on( 'add remove', function() {
     605                                var count = this.controller.selection.length,
     606                                        showGallery;
     607
     608                                this.$el.toggleClass( 'with-toolbar', !! count );
     609
     610                                // Check if every attachment in the selection is an image.
     611                                showGallery = count > 1 && this.controller.selection.all( function( attachment ) {
     612                                        return 'image' === attachment.get('type');
     613                                });
     614
     615                                this.toolbarView.get('create-new-gallery').$el.toggle( showGallery );
     616                                insert = this.toolbarView.get('insert-into-post');
     617                                insert.model.set( 'style', showGallery ? '' : 'primary' );
     618                        }, this );
     619
     620                        this.$content.append( this.toolbarView.$el );
     621                }
     622        });
     623
     624        /**
     625         * wp.media.view.Workspace.Gallery
     626         */
     627        media.view.Workspace.Gallery = media.view.Workspace.extend({
     628                // The single `Attachment` view to be used in the `Attachments` view.
     629                AttachmentView: media.view.Attachment.Gallery,
     630
     631                initialize: function() {
     632                        media.view.Workspace.prototype.initialize.apply( this, arguments );
     633                        this.initToolbarView();
     634                },
     635
     636                // Initializes the toolbar view. Currently uses defaults set for
     637                // inserting media into a post. This should be pulled out into the
     638                // appropriate workflow when the time comes, but is currently here
     639                // to test multiple selections.
     640                initToolbarView: function() {
     641                        var controller = this.controller;
     642
     643                        this.toolbarView = new media.view.Toolbar({
     644                                items: {
     645                                        'return-to-library': {
     646                                                text:     l10n.returnToLibrary,
     647                                                priority: -40,
     648
     649                                                click:  function() {
     650                                                        controller.render('library');
     651                                                }
     652                                        },
     653
     654                                        'insert-gallery-into-post': {
     655                                                style:    'primary',
     656                                                text:     l10n.insertGalleryIntoPost,
     657                                                priority: 40,
     658                                                click:    _.bind( controller.update, controller )
     659                                        },
     660
     661                                        'add-images-from-library': {
     662                                                text:     l10n.addImagesFromLibrary,
     663                                                priority: 30
     664                                        }
     665                                }
     666                        });
     667
     668                        this.$el.addClass('with-toolbar');
     669                        this.$content.append( this.toolbarView.$el );
     670                }
     671        });
     672
     673
     674        /**
     675         * wp.media.view.Attachments
     676         */
     677        media.view.Attachments = Backbone.View.extend({
     678                tagName:   'div',
     679                className: 'attachments',
     680                template:  media.template('attachments'),
     681
     682                events: {
     683                        'keyup input': 'search'
     684                },
     685
     686                initialize: function() {
     687                        this.controller = this.options.controller;
     688
     689                        _.defaults( this.options, {
     690                                refreshSensitivity: 200,
     691                                refreshThreshold:   3,
     692                                AttachmentView:     media.view.Attachment
     693                        });
     694
     695                        _.each(['add','remove'], function( method ) {
     696                                this.collection.on( method, function( attachment, attachments, options ) {
     697                                        this[ method ]( attachment, options.index );
     698                                }, this );
     699                        }, this );
     700
     701                        this.collection.on( 'reset', this.refresh, this );
     702
     703                        this.$list = $('<ul />');
     704                        this.list  = this.$list[0];
     705
     706                        this.scroll = _.chain( this.scroll ).bind( this ).throttle( this.options.refreshSensitivity ).value();
     707                        this.$list.on( 'scroll.attachments', this.scroll );
     708                },
     709
     710                render: function() {
     711                        // Detach the list from the DOM to prevent event removal.
     712                        this.$list.detach();
     713
     714                        this.$el.html( this.template( this.options ) ).append( this.$list );
     715                        this.refresh();
     716                        return this;
     717                },
     718
     719                refresh: function() {
     720                        // If there are no elements, load some.
     721                        if ( ! this.collection.length ) {
     722                                this.collection.more();
     723                                this.$list.empty();
     724                                return this;
     725                        }
     726
     727                        // Otherwise, create all of the Attachment views, and replace
     728                        // the list in a single DOM operation.
     729                        this.$list.html( this.collection.map( function( attachment ) {
     730                                return new this.options.AttachmentView({
     731                                        controller: this.controller,
     732                                        model:      attachment
     733                                }).render().$el;
     734                        }, this ) );
     735
     736                        // Then, trigger the scroll event to check if we're within the
     737                        // threshold to query for additional attachments.
     738                        this.scroll();
     739                        return this;
     740                },
     741
     742                add: function( attachment, index ) {
     743                        var view, children;
     744
     745                        view = new this.options.AttachmentView({
     746                                controller: this.controller,
     747                                model:      attachment
     748                        }).render();
     749
     750                        children = this.$list.children();
     751
     752                        if ( children.length > index )
     753                                children.eq( index ).before( view.$el );
     754                        else
     755                                this.$list.append( view.$el );
     756                },
     757
     758                remove: function( attachment, index ) {
     759                        var children = this.$list.children();
     760                        if ( children.length )
     761                                children.eq( index ).detach();
     762                },
     763
     764                scroll: function( event ) {
     765                        // @todo: is this still necessary?
     766                        if ( ! this.$list.is(':visible') )
     767                                return;
     768
     769                        if ( this.list.scrollHeight < this.list.scrollTop + ( this.list.clientHeight * this.options.refreshThreshold ) ) {
     770                                this.collection.more();
     771                        }
     772                },
     773
     774                search: function( event ) {
     775                        var props = this.collection.props;
     776
     777                        if ( event.target.value )
     778                                props.set( 'search', event.target.value );
     779                        else
     780                                props.unset('search');
     781                }
     782        });
     783
     784        /**
    772785         * wp.media.view.SelectionPreview
    773786         */
Note: See TracChangeset for help on using the changeset viewer.