web/wp-includes/js/media-editor.js
changeset 204 09a1c134465b
equal deleted inserted replaced
203:f507feede89a 204:09a1c134465b
       
     1 // WordPress, TinyMCE, and Media
       
     2 // -----------------------------
       
     3 (function($){
       
     4 	// Stores the editors' `wp.media.controller.Frame` instances.
       
     5 	var workflows = {};
       
     6 
       
     7 	wp.media.string = {
       
     8 		// Joins the `props` and `attachment` objects,
       
     9 		// outputting the proper object format based on the
       
    10 		// attachment's type.
       
    11 		props: function( props, attachment ) {
       
    12 			var link, linkUrl, size, sizes, fallbacks;
       
    13 
       
    14 			// Final fallbacks run after all processing has been completed.
       
    15 			fallbacks = function( props ) {
       
    16 				// Generate alt fallbacks and strip tags.
       
    17 				if ( 'image' === props.type && ! props.alt ) {
       
    18 					props.alt = props.caption || props.title || '';
       
    19 					props.alt = props.alt.replace( /<\/?[^>]+>/g, '' );
       
    20 				}
       
    21 
       
    22 				return props;
       
    23 			};
       
    24 
       
    25 			props = props ? _.clone( props ) : {};
       
    26 
       
    27 			if ( attachment && attachment.type )
       
    28 				props.type = attachment.type;
       
    29 
       
    30 			if ( 'image' === props.type ) {
       
    31 				props = _.defaults( props || {}, {
       
    32 					align:   getUserSetting( 'align', 'none' ),
       
    33 					size:    getUserSetting( 'imgsize', 'medium' ),
       
    34 					url:     '',
       
    35 					classes: []
       
    36 				});
       
    37 			}
       
    38 
       
    39 			// All attachment-specific settings follow.
       
    40 			if ( ! attachment )
       
    41 				return fallbacks( props );
       
    42 
       
    43 			props.title = props.title || attachment.title;
       
    44 
       
    45 			link = props.link || getUserSetting( 'urlbutton', 'post' );
       
    46 			if ( 'file' === link )
       
    47 				linkUrl = attachment.url;
       
    48 			else if ( 'post' === link )
       
    49 				linkUrl = attachment.link;
       
    50 			else if ( 'custom' === link )
       
    51 				linkUrl = props.linkUrl;
       
    52 			props.linkUrl = linkUrl || '';
       
    53 
       
    54 			// Format properties for images.
       
    55 			if ( 'image' === attachment.type ) {
       
    56 				props.classes.push( 'wp-image-' + attachment.id );
       
    57 
       
    58 				sizes = attachment.sizes;
       
    59 				size = sizes && sizes[ props.size ] ? sizes[ props.size ] : attachment;
       
    60 
       
    61 				_.extend( props, _.pick( attachment, 'align', 'caption', 'alt' ), {
       
    62 					width:     size.width,
       
    63 					height:    size.height,
       
    64 					src:       size.url,
       
    65 					captionId: 'attachment_' + attachment.id
       
    66 				});
       
    67 
       
    68 			// Format properties for non-images.
       
    69 			} else {
       
    70 				props.title = props.title || attachment.filename;
       
    71 				props.rel = props.rel || 'attachment wp-att-' + attachment.id;
       
    72 			}
       
    73 
       
    74 			return fallbacks( props );
       
    75 		},
       
    76 
       
    77 		link: function( props, attachment ) {
       
    78 			var options;
       
    79 
       
    80 			props = wp.media.string.props( props, attachment );
       
    81 
       
    82 			options = {
       
    83 				tag:     'a',
       
    84 				content: props.title,
       
    85 				attrs:   {
       
    86 					href: props.linkUrl
       
    87 				}
       
    88 			};
       
    89 
       
    90 			if ( props.rel )
       
    91 				options.attrs.rel = props.rel;
       
    92 
       
    93 			return wp.html.string( options );
       
    94 		},
       
    95 
       
    96 		image: function( props, attachment ) {
       
    97 			var img = {},
       
    98 				options, classes, shortcode, html;
       
    99 
       
   100 			props = wp.media.string.props( props, attachment );
       
   101 			classes = props.classes || [];
       
   102 
       
   103 			img.src = props.url;
       
   104 			_.extend( img, _.pick( props, 'width', 'height', 'alt' ) );
       
   105 
       
   106 			// Only assign the align class to the image if we're not printing
       
   107 			// a caption, since the alignment is sent to the shortcode.
       
   108 			if ( props.align && ! props.caption )
       
   109 				classes.push( 'align' + props.align );
       
   110 
       
   111 			if ( props.size )
       
   112 				classes.push( 'size-' + props.size );
       
   113 
       
   114 			img['class'] = _.compact( classes ).join(' ');
       
   115 
       
   116 			// Generate `img` tag options.
       
   117 			options = {
       
   118 				tag:    'img',
       
   119 				attrs:  img,
       
   120 				single: true
       
   121 			};
       
   122 
       
   123 			// Generate the `a` element options, if they exist.
       
   124 			if ( props.linkUrl ) {
       
   125 				options = {
       
   126 					tag:   'a',
       
   127 					attrs: {
       
   128 						href: props.linkUrl
       
   129 					},
       
   130 					content: options
       
   131 				};
       
   132 			}
       
   133 
       
   134 			html = wp.html.string( options );
       
   135 
       
   136 			// Generate the caption shortcode.
       
   137 			if ( props.caption ) {
       
   138 				shortcode = {};
       
   139 
       
   140 				if ( img.width )
       
   141 					shortcode.width = img.width;
       
   142 
       
   143 				if ( props.captionId )
       
   144 					shortcode.id = props.captionId;
       
   145 
       
   146 				if ( props.align )
       
   147 					shortcode.align = 'align' + props.align;
       
   148 
       
   149 				html = wp.shortcode.string({
       
   150 					tag:     'caption',
       
   151 					attrs:   shortcode,
       
   152 					content: html + ' ' + props.caption
       
   153 				});
       
   154 			}
       
   155 
       
   156 			return html;
       
   157 		}
       
   158 	};
       
   159 
       
   160 	wp.media.gallery = (function() {
       
   161 		var galleries = {};
       
   162 
       
   163 		return {
       
   164 			defaults: {
       
   165 				order:      'ASC',
       
   166 				id:         wp.media.view.settings.post.id,
       
   167 				itemtag:    'dl',
       
   168 				icontag:    'dt',
       
   169 				captiontag: 'dd',
       
   170 				columns:    3,
       
   171 				size:       'thumbnail',
       
   172 				orderby:    'menu_order ID'
       
   173 			},
       
   174 
       
   175 			attachments: function( shortcode ) {
       
   176 				var shortcodeString = shortcode.string(),
       
   177 					result = galleries[ shortcodeString ],
       
   178 					attrs, args, query, others;
       
   179 
       
   180 				delete galleries[ shortcodeString ];
       
   181 
       
   182 				if ( result )
       
   183 					return result;
       
   184 
       
   185 				// Fill the default shortcode attributes.
       
   186 				attrs = _.defaults( shortcode.attrs.named, wp.media.gallery.defaults );
       
   187 				args  = _.pick( attrs, 'orderby', 'order' );
       
   188 
       
   189 				args.type    = 'image';
       
   190 				args.perPage = -1;
       
   191 
       
   192 				// Mark the `orderby` override attribute.
       
   193 				if ( 'rand' === attrs.orderby )
       
   194 					attrs._orderbyRandom = true;
       
   195 
       
   196 				// Map the `orderby` attribute to the corresponding model property.
       
   197 				if ( ! attrs.orderby || /^menu_order(?: ID)?$/i.test( attrs.orderby ) )
       
   198 					args.orderby = 'menuOrder';
       
   199 
       
   200 				// Map the `ids` param to the correct query args.
       
   201 				if ( attrs.ids ) {
       
   202 					args.post__in = attrs.ids.split(',');
       
   203 					args.orderby  = 'post__in';
       
   204 				} else if ( attrs.include ) {
       
   205 					args.post__in = attrs.include.split(',');
       
   206 				}
       
   207 
       
   208 				if ( attrs.exclude )
       
   209 					args.post__not_in = attrs.exclude.split(',');
       
   210 
       
   211 				if ( ! args.post__in )
       
   212 					args.uploadedTo = attrs.id;
       
   213 
       
   214 				// Collect the attributes that were not included in `args`.
       
   215 				others = _.omit( attrs, 'id', 'ids', 'include', 'exclude', 'orderby', 'order' );
       
   216 
       
   217 				query = wp.media.query( args );
       
   218 				query.gallery = new Backbone.Model( others );
       
   219 				return query;
       
   220 			},
       
   221 
       
   222 			shortcode: function( attachments ) {
       
   223 				var props = attachments.props.toJSON(),
       
   224 					attrs = _.pick( props, 'orderby', 'order' ),
       
   225 					shortcode, clone;
       
   226 
       
   227 				if ( attachments.gallery )
       
   228 					_.extend( attrs, attachments.gallery.toJSON() );
       
   229 
       
   230 				// Convert all gallery shortcodes to use the `ids` property.
       
   231 				// Ignore `post__in` and `post__not_in`; the attachments in
       
   232 				// the collection will already reflect those properties.
       
   233 				attrs.ids = attachments.pluck('id');
       
   234 
       
   235 				// Copy the `uploadedTo` post ID.
       
   236 				if ( props.uploadedTo )
       
   237 					attrs.id = props.uploadedTo;
       
   238 
       
   239 				// Check if the gallery is randomly ordered.
       
   240 				if ( attrs._orderbyRandom )
       
   241 					attrs.orderby = 'rand';
       
   242 				delete attrs._orderbyRandom;
       
   243 
       
   244 				// If the `ids` attribute is set and `orderby` attribute
       
   245 				// is the default value, clear it for cleaner output.
       
   246 				if ( attrs.ids && 'post__in' === attrs.orderby )
       
   247 					delete attrs.orderby;
       
   248 
       
   249 				// Remove default attributes from the shortcode.
       
   250 				_.each( wp.media.gallery.defaults, function( value, key ) {
       
   251 					if ( value === attrs[ key ] )
       
   252 						delete attrs[ key ];
       
   253 				});
       
   254 
       
   255 				shortcode = new wp.shortcode({
       
   256 					tag:    'gallery',
       
   257 					attrs:  attrs,
       
   258 					type:   'single'
       
   259 				});
       
   260 
       
   261 				// Use a cloned version of the gallery.
       
   262 				clone = new wp.media.model.Attachments( attachments.models, {
       
   263 					props: props
       
   264 				});
       
   265 				clone.gallery = attachments.gallery;
       
   266 				galleries[ shortcode.string() ] = clone;
       
   267 
       
   268 				return shortcode;
       
   269 			},
       
   270 
       
   271 			edit: function( content ) {
       
   272 				var shortcode = wp.shortcode.next( 'gallery', content ),
       
   273 					defaultPostId = wp.media.gallery.defaults.id,
       
   274 					attachments, selection;
       
   275 
       
   276 				// Bail if we didn't match the shortcode or all of the content.
       
   277 				if ( ! shortcode || shortcode.content !== content )
       
   278 					return;
       
   279 
       
   280 				// Ignore the rest of the match object.
       
   281 				shortcode = shortcode.shortcode;
       
   282 
       
   283 				if ( _.isUndefined( shortcode.get('id') ) && ! _.isUndefined( defaultPostId ) )
       
   284 					shortcode.set( 'id', defaultPostId );
       
   285 
       
   286 				attachments = wp.media.gallery.attachments( shortcode );
       
   287 
       
   288 				selection = new wp.media.model.Selection( attachments.models, {
       
   289 					props:    attachments.props.toJSON(),
       
   290 					multiple: true
       
   291 				});
       
   292 
       
   293 				selection.gallery = attachments.gallery;
       
   294 
       
   295 				// Fetch the query's attachments, and then break ties from the
       
   296 				// query to allow for sorting.
       
   297 				selection.more().done( function() {
       
   298 					// Break ties with the query.
       
   299 					selection.props.set({ query: false });
       
   300 					selection.unmirror();
       
   301 					selection.props.unset('orderby');
       
   302 				});
       
   303 
       
   304 				// Destroy the previous gallery frame.
       
   305 				if ( this.frame )
       
   306 					this.frame.dispose();
       
   307 
       
   308 				// Store the current gallery frame.
       
   309 				this.frame = wp.media({
       
   310 					frame:     'post',
       
   311 					state:     'gallery-edit',
       
   312 					title:     wp.media.view.l10n.editGalleryTitle,
       
   313 					editing:   true,
       
   314 					multiple:  true,
       
   315 					selection: selection
       
   316 				}).open();
       
   317 
       
   318 				return this.frame;
       
   319 			}
       
   320 		};
       
   321 	}());
       
   322 
       
   323 	wp.media.featuredImage = {
       
   324 		get: function() {
       
   325 			return wp.media.view.settings.post.featuredImageId;
       
   326 		},
       
   327 
       
   328 		set: function( id ) {
       
   329 			var settings = wp.media.view.settings;
       
   330 
       
   331 			settings.post.featuredImageId = id;
       
   332 
       
   333 			wp.media.post( 'set-post-thumbnail', {
       
   334 				json:         true,
       
   335 				post_id:      settings.post.id,
       
   336 				thumbnail_id: settings.post.featuredImageId,
       
   337 				_wpnonce:     settings.post.nonce
       
   338 			}).done( function( html ) {
       
   339 				$( '.inside', '#postimagediv' ).html( html );
       
   340 			});
       
   341 		},
       
   342 
       
   343 		frame: function() {
       
   344 			if ( this._frame )
       
   345 				return this._frame;
       
   346 
       
   347 			this._frame = wp.media({
       
   348 				state: 'featured-image',
       
   349 				states: [ new wp.media.controller.FeaturedImage() ]
       
   350 			});
       
   351 
       
   352 			this._frame.on( 'toolbar:create:featured-image', function( toolbar ) {
       
   353 				this.createSelectToolbar( toolbar, {
       
   354 					text: wp.media.view.l10n.setFeaturedImage
       
   355 				});
       
   356 			}, this._frame );
       
   357 
       
   358 			this._frame.state('featured-image').on( 'select', this.select );
       
   359 			return this._frame;
       
   360 		},
       
   361 
       
   362 		select: function() {
       
   363 			var settings = wp.media.view.settings,
       
   364 				selection = this.get('selection').single();
       
   365 
       
   366 			if ( ! settings.post.featuredImageId )
       
   367 				return;
       
   368 
       
   369 			wp.media.featuredImage.set( selection ? selection.id : -1 );
       
   370 		},
       
   371 
       
   372 		init: function() {
       
   373 			// Open the content media manager to the 'featured image' tab when
       
   374 			// the post thumbnail is clicked.
       
   375 			$('#postimagediv').on( 'click', '#set-post-thumbnail', function( event ) {
       
   376 				event.preventDefault();
       
   377 				// Stop propagation to prevent thickbox from activating.
       
   378 				event.stopPropagation();
       
   379 
       
   380 				wp.media.featuredImage.frame().open();
       
   381 
       
   382 			// Update the featured image id when the 'remove' link is clicked.
       
   383 			}).on( 'click', '#remove-post-thumbnail', function() {
       
   384 				wp.media.view.settings.post.featuredImageId = -1;
       
   385 			});
       
   386 		}
       
   387 	};
       
   388 
       
   389 	$( wp.media.featuredImage.init );
       
   390 
       
   391 	wp.media.editor = {
       
   392 		insert: function( h ) {
       
   393 			var mce = typeof(tinymce) != 'undefined',
       
   394 				qt = typeof(QTags) != 'undefined',
       
   395 				wpActiveEditor = window.wpActiveEditor,
       
   396 				ed;
       
   397 
       
   398 			// Delegate to the global `send_to_editor` if it exists.
       
   399 			// This attempts to play nice with any themes/plugins that have
       
   400 			// overridden the insert functionality.
       
   401 			if ( window.send_to_editor )
       
   402 				return window.send_to_editor.apply( this, arguments );
       
   403 
       
   404 			if ( ! wpActiveEditor ) {
       
   405 				if ( mce && tinymce.activeEditor ) {
       
   406 					ed = tinymce.activeEditor;
       
   407 					wpActiveEditor = window.wpActiveEditor = ed.id;
       
   408 				} else if ( !qt ) {
       
   409 					return false;
       
   410 				}
       
   411 			} else if ( mce ) {
       
   412 				if ( tinymce.activeEditor && (tinymce.activeEditor.id == 'mce_fullscreen' || tinymce.activeEditor.id == 'wp_mce_fullscreen') )
       
   413 					ed = tinymce.activeEditor;
       
   414 				else
       
   415 					ed = tinymce.get(wpActiveEditor);
       
   416 			}
       
   417 
       
   418 			if ( ed && !ed.isHidden() ) {
       
   419 				// restore caret position on IE
       
   420 				if ( tinymce.isIE && ed.windowManager.insertimagebookmark )
       
   421 					ed.selection.moveToBookmark(ed.windowManager.insertimagebookmark);
       
   422 
       
   423 				if ( h.indexOf('[caption') !== -1 ) {
       
   424 					if ( ed.wpSetImgCaption )
       
   425 						h = ed.wpSetImgCaption(h);
       
   426 				} else if ( h.indexOf('[gallery') !== -1 ) {
       
   427 					if ( ed.plugins.wpgallery )
       
   428 						h = ed.plugins.wpgallery._do_gallery(h);
       
   429 				} else if ( h.indexOf('[embed') === 0 ) {
       
   430 					if ( ed.plugins.wordpress )
       
   431 						h = ed.plugins.wordpress._setEmbed(h);
       
   432 				}
       
   433 
       
   434 				ed.execCommand('mceInsertContent', false, h);
       
   435 			} else if ( qt ) {
       
   436 				QTags.insertContent(h);
       
   437 			} else {
       
   438 				document.getElementById(wpActiveEditor).value += h;
       
   439 			}
       
   440 
       
   441 			// If the old thickbox remove function exists, call it in case
       
   442 			// a theme/plugin overloaded it.
       
   443 			if ( window.tb_remove )
       
   444 				try { window.tb_remove(); } catch( e ) {}
       
   445 		},
       
   446 
       
   447 		add: function( id, options ) {
       
   448 			var workflow = this.get( id );
       
   449 
       
   450 			if ( workflow )
       
   451 				return workflow;
       
   452 
       
   453 			workflow = workflows[ id ] = wp.media( _.defaults( options || {}, {
       
   454 				frame:    'post',
       
   455 				state:    'insert',
       
   456 				title:    wp.media.view.l10n.addMedia,
       
   457 				multiple: true
       
   458 			} ) );
       
   459 
       
   460 			workflow.on( 'insert', function( selection ) {
       
   461 				var state = workflow.state();
       
   462 
       
   463 				selection = selection || state.get('selection');
       
   464 
       
   465 				if ( ! selection )
       
   466 					return;
       
   467 
       
   468 				$.when.apply( $, selection.map( function( attachment ) {
       
   469 					var display = state.display( attachment ).toJSON();
       
   470 					return this.send.attachment( display, attachment.toJSON() );
       
   471 				}, this ) ).done( function() {
       
   472 					wp.media.editor.insert( _.toArray( arguments ).join("\n\n") );
       
   473 				});
       
   474 			}, this );
       
   475 
       
   476 			workflow.state('gallery-edit').on( 'update', function( selection ) {
       
   477 				this.insert( wp.media.gallery.shortcode( selection ).string() );
       
   478 			}, this );
       
   479 
       
   480 			workflow.state('embed').on( 'select', function() {
       
   481 				var state = workflow.state(),
       
   482 					type = state.get('type'),
       
   483 					embed = state.props.toJSON();
       
   484 
       
   485 				embed.url = embed.url || '';
       
   486 
       
   487 				if ( 'link' === type ) {
       
   488 					_.defaults( embed, {
       
   489 						title:   embed.url,
       
   490 						linkUrl: embed.url
       
   491 					});
       
   492 
       
   493 					this.send.link( embed ).done( function( resp ) {
       
   494 						wp.media.editor.insert( resp );
       
   495 					});
       
   496 
       
   497 				} else if ( 'image' === type ) {
       
   498 					_.defaults( embed, {
       
   499 						title:   embed.url,
       
   500 						linkUrl: '',
       
   501 						align:   'none',
       
   502 						link:    'none'
       
   503 					});
       
   504 
       
   505 					if ( 'none' === embed.link )
       
   506 						embed.linkUrl = '';
       
   507 					else if ( 'file' === embed.link )
       
   508 						embed.linkUrl = embed.url;
       
   509 
       
   510 					this.insert( wp.media.string.image( embed ) );
       
   511 				}
       
   512 			}, this );
       
   513 
       
   514 			workflow.state('featured-image').on( 'select', wp.media.featuredImage.select );
       
   515 			workflow.setState( workflow.options.state );
       
   516 			return workflow;
       
   517 		},
       
   518 
       
   519 		id: function( id ) {
       
   520 			if ( id )
       
   521 				return id;
       
   522 
       
   523 			// If an empty `id` is provided, default to `wpActiveEditor`.
       
   524 			id = wpActiveEditor;
       
   525 
       
   526 			// If that doesn't work, fall back to `tinymce.activeEditor.id`.
       
   527 			if ( ! id && typeof tinymce !== 'undefined' && tinymce.activeEditor )
       
   528 				id = tinymce.activeEditor.id;
       
   529 
       
   530 			// Last but not least, fall back to the empty string.
       
   531 			id = id || '';
       
   532 			return id;
       
   533 		},
       
   534 
       
   535 		get: function( id ) {
       
   536 			id = this.id( id );
       
   537 			return workflows[ id ];
       
   538 		},
       
   539 
       
   540 		remove: function( id ) {
       
   541 			id = this.id( id );
       
   542 			delete workflows[ id ];
       
   543 		},
       
   544 
       
   545 		send: {
       
   546 			attachment: function( props, attachment ) {
       
   547 				var caption = attachment.caption,
       
   548 					options, html;
       
   549 
       
   550 				// If captions are disabled, clear the caption.
       
   551 				if ( ! wp.media.view.settings.captions )
       
   552 					delete attachment.caption;
       
   553 
       
   554 				props = wp.media.string.props( props, attachment );
       
   555 
       
   556 				options = {
       
   557 					id:           attachment.id,
       
   558 					post_content: attachment.description,
       
   559 					post_excerpt: caption
       
   560 				};
       
   561 
       
   562 				if ( props.linkUrl )
       
   563 					options.url = props.linkUrl;
       
   564 
       
   565 				if ( 'image' === attachment.type ) {
       
   566 					html = wp.media.string.image( props );
       
   567 
       
   568 					_.each({
       
   569 						align: 'align',
       
   570 						size:  'image-size',
       
   571 						alt:   'image_alt'
       
   572 					}, function( option, prop ) {
       
   573 						if ( props[ prop ] )
       
   574 							options[ option ] = props[ prop ];
       
   575 					});
       
   576 
       
   577 				} else {
       
   578 					html = wp.media.string.link( props );
       
   579 					options.post_title = props.title;
       
   580 				}
       
   581 
       
   582 				return wp.media.post( 'send-attachment-to-editor', {
       
   583 					nonce:      wp.media.view.settings.nonce.sendToEditor,
       
   584 					attachment: options,
       
   585 					html:       html,
       
   586 					post_id:    wp.media.view.settings.post.id
       
   587 				});
       
   588 			},
       
   589 
       
   590 			link: function( embed ) {
       
   591 				return wp.media.post( 'send-link-to-editor', {
       
   592 					nonce:   wp.media.view.settings.nonce.sendToEditor,
       
   593 					src:     embed.linkUrl,
       
   594 					title:   embed.title,
       
   595 					html:    wp.media.string.link( embed ),
       
   596 					post_id: wp.media.view.settings.post.id
       
   597 				});
       
   598 			}
       
   599 		},
       
   600 
       
   601 		open: function( id ) {
       
   602 			var workflow, editor;
       
   603 
       
   604 			id = this.id( id );
       
   605 
       
   606 			// Save a bookmark of the caret position in IE.
       
   607 			if ( typeof tinymce !== 'undefined' ) {
       
   608 				editor = tinymce.get( id );
       
   609 
       
   610 				if ( tinymce.isIE && editor && ! editor.isHidden() ) {
       
   611 					editor.focus();
       
   612 					editor.windowManager.insertimagebookmark = editor.selection.getBookmark();
       
   613 				}
       
   614 			}
       
   615 
       
   616 			workflow = this.get( id );
       
   617 
       
   618 			// Initialize the editor's workflow if we haven't yet.
       
   619 			if ( ! workflow )
       
   620 				workflow = this.add( id );
       
   621 
       
   622 			return workflow.open();
       
   623 		},
       
   624 
       
   625 		init: function() {
       
   626 			$(document.body).on( 'click', '.insert-media', function( event ) {
       
   627 				var $this = $(this),
       
   628 					editor = $this.data('editor');
       
   629 
       
   630 				event.preventDefault();
       
   631 
       
   632 				// Remove focus from the `.insert-media` button.
       
   633 				// Prevents Opera from showing the outline of the button
       
   634 				// above the modal.
       
   635 				//
       
   636 				// See: http://core.trac.wordpress.org/ticket/22445
       
   637 				$this.blur();
       
   638 
       
   639 				wp.media.editor.open( editor );
       
   640 			});
       
   641 		}
       
   642 	};
       
   643 
       
   644 	_.bindAll( wp.media.editor, 'open' );
       
   645 	$( wp.media.editor.init );
       
   646 }(jQuery));