Ticket #21390: 21390.diff
File 21390.diff, 57.6 KB (added by , 12 years ago) |
---|
-
wp-admin/js/custom-background.js
37 37 } 38 38 }); 39 39 40 frame. toolbar.on( 'activate:select', function() {41 frame.toolbar.view().set({40 frame.on( 'toolbar:render:select', function( view ) { 41 view.set({ 42 42 select: { 43 43 style: 'primary', 44 44 text: $el.data('update'), -
wp-admin/js/custom-header.js
24 24 } 25 25 }); 26 26 27 frame. toolbar.on( 'activate:select', function() {28 frame.toolbar.view().set({27 frame.on( 'toolbar:render:select', function( view ) { 28 view.set({ 29 29 select: { 30 30 style: 'primary', 31 31 text: $el.data('update'), -
wp-includes/css/media-views-rtl.css
226 226 } 227 227 228 228 /** 229 * Selection Preview230 */231 .selected-img {232 float: right;233 margin-right: 0;234 margin-left: 14px;235 }236 237 .selection-preview img {238 float: right;239 margin-left: 0;240 margin-right: 1px;241 }242 243 .selection-preview .count {244 right: auto;245 left: 0;246 }247 248 .selection-preview .clear-selection {249 float: right;250 }251 252 /**253 229 * Attachment Details 254 230 */ 255 231 .attachment-info .thumbnail { -
wp-includes/css/media-views.css
80 80 */ 81 81 .media-modal { 82 82 position: fixed; 83 top: 60px;84 left: 40px;85 right: 40px;86 bottom: 40px;83 top: 30px; 84 left: 30px; 85 right: 30px; 86 bottom: 30px; 87 87 z-index: 160000; 88 88 } 89 89 … … 94 94 right: 0; 95 95 bottom: 0; 96 96 background: #000; 97 opacity: 0. 8;97 opacity: 0.7; 98 98 z-index: 159900; 99 99 } 100 100 101 .media-modal-backdrop div, 102 .uploader-window-content { 101 .media-modal-close { 103 102 position: absolute; 104 top: 10px;105 left: 10px;106 right: 10px;107 bottom: 10px;108 border: 1px dashed rgba( 255, 255, 255, 0.5 );103 top: 7px; 104 right: 7px; 105 width: 30px; 106 height: 30px; 107 z-index: 1000; 109 108 } 110 111 .media-modal-title { 112 position: absolute; 113 top: -40px; 114 left: 0; 115 height: 40px; 116 padding: 0; 117 margin: 0; 118 119 line-height: 40px; 120 color: #fff; 121 font-size: 16px; 122 font-weight: 200; 123 text-shadow: 0 0 16px rgba( 0, 0, 0, 0.6 ); 124 } 125 126 .media-modal-close { 127 position: absolute; 128 top: -27px; 129 right: 0; 109 .media-modal-close span { 110 display: block; 111 margin: 8px auto 0; 112 width: 15px; 130 113 height: 15px; 131 width: 15px; 132 background-position: -80px 0; 114 background-position: -100px 0; 133 115 } 134 116 135 117 .media-modal-close:active { … … 165 147 border: 0 solid #dfdfdf; 166 148 } 167 149 168 .media-frame-toolbar > .media-toolbar {169 top: auto;170 left: 200px;171 bottom: 0;172 border-width: 1px 0 0 0;173 box-shadow: 0 -4px 4px -4px rgba( 0, 0, 0, 0.1 );174 }175 176 .hide-toolbar .media-frame-toolbar > .media-toolbar {177 bottom: -61px;178 }179 180 150 .media-toolbar-primary { 181 151 float: right; 182 152 } … … 238 208 width: 100%; 239 209 } 240 210 241 .media-sidebar .selection-preview {242 display: block;243 padding-top: 5px;244 }245 246 211 .media-sidebar h3 { 247 212 position: relative; 248 213 font-weight: bold; … … 361 326 position: absolute; 362 327 top: 0; 363 328 left: 0; 329 right: 0; 364 330 bottom: 0; 365 width: 199px;366 331 margin: 0; 367 332 padding: 16px 0; 368 z-index: 200;369 333 border-right: 1px solid #d9d9d9; 370 334 box-shadow: inset -6px 0 6px -6px rgba( 0, 0, 0, 0.2 ); 371 335 -webkit-user-select: none; … … 374 338 user-select: none; 375 339 } 376 340 377 .media-menu li { 341 .media-menu > a { 342 display: block; 378 343 position: relative; 379 344 padding: 4px 20px; 380 345 margin: 0; … … 382 347 font-size: 14px; 383 348 color: #21759B; 384 349 text-shadow: 0 1px 0 #fff; 350 text-decoration: none; 385 351 } 386 352 387 .media-menu-item { 388 cursor: pointer; 353 .media-menu > a:hover { 354 color: #21759B; 355 background: rgba( 0, 0, 0, 0.04 ); 389 356 } 390 357 391 .media-menu li:hover{392 background: rgba( 0, 0, 0, 0.04 );358 .media-menu > a:active { 359 outline: none; 393 360 } 394 361 395 362 .media-menu .active, … … 407 374 } 408 375 409 376 /** 377 * Menu 378 */ 379 .media-router { 380 position: relative; 381 padding: 0 6px; 382 margin: 0; 383 clear: both; 384 -webkit-user-select: none; 385 -moz-user-select: none; 386 -ms-user-select: none; 387 user-select: none; 388 } 389 390 .media-router > a { 391 position: relative; 392 float: left; 393 padding: 2px 10px; 394 margin: 0; 395 height: 18px; 396 line-height: 18px; 397 font-size: 14px; 398 border-right: 1px solid #dfdfdf; 399 text-shadow: 0 1px 0 #fff; 400 text-decoration: none; 401 } 402 403 .media-router > a:last-child { 404 border-right: 0; 405 } 406 407 .media-router > a:active { 408 outline: none; 409 } 410 411 .media-router .active, 412 .media-router .active:hover { 413 color: #333; 414 } 415 416 .media-router .active:after { 417 content: ''; 418 display: block; 419 margin: -100px auto 0; 420 width: 7px; 421 height: 7px; 422 background: #fff; 423 box-shadow: 1px 1px 1px rgba( 0, 0, 0, 0.2 ); 424 z-index: 300; 425 426 -webkit-transform: rotate( 45deg ) translate( 75px, 75px ); 427 -moz-transform: rotate( 45deg ) translate( 75px, 75px ); 428 -ms-transform: rotate( 45deg ) translate( 75px, 75px ); 429 -o-transform: rotate( 45deg ) translate( 75px, 75px ); 430 transform: rotate( 45deg ) translate( 75px, 75px ); 431 } 432 433 /** 410 434 * Frame 411 435 */ 412 436 .media-frame { … … 418 442 bottom: 0; 419 443 } 420 444 421 .media-frame .region-content{445 .media-frame-menu { 422 446 position: absolute; 423 447 top: 0; 448 left: 0; 449 bottom: 0; 450 width: 199px; 451 z-index: 150; 452 } 453 454 .media-frame-title { 455 position: absolute; 456 top: 0; 424 457 left: 200px; 425 458 right: 0; 459 height: 45px; 460 z-index: 200; 461 } 462 463 .media-frame-router { 464 position: absolute; 465 top: 45px; 466 left: 200px; 467 right: 0; 468 height: 30px; 469 z-index: 200; 470 border-bottom: 1px solid #dfdfdf; 471 box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 ); 472 } 473 474 .media-frame-content { 475 position: absolute; 476 top: 75px; 477 left: 200px; 478 right: 0; 426 479 bottom: 61px; 427 480 height: auto; 428 481 width: auto; … … 430 483 overflow: auto; 431 484 } 432 485 433 .media-frame.hide-toolbar .region-content { 486 .media-frame-toolbar { 487 position: absolute; 488 left: 200px; 489 right: 0; 434 490 bottom: 0; 491 height: 60px; 492 z-index: 100; 493 border: 0 solid #dfdfdf; 494 border-width: 1px 0 0 0; 495 box-shadow: 0 -4px 4px -4px rgba( 0, 0, 0, 0.1 ); 435 496 } 436 497 498 .media-frame.hide-menu .media-frame-title, 499 .media-frame.hide-menu .media-frame-router, 500 .media-frame.hide-menu .media-frame-toolbar, 501 .media-frame.hide-menu .media-frame-content { 502 left: 0; 503 } 504 505 .media-frame.hide-menu .media-frame-menu { 506 left: -200px; 507 } 508 509 .media-frame.hide-toolbar .media-frame-content { 510 bottom: 0; 511 } 512 513 .media-frame.hide-toolbar .media-frame-toolbar { 514 bottom: -61px; 515 } 516 517 .media-frame.hide-router .media-frame-content { 518 top: 45px; 519 } 520 521 .media-frame.hide-router .media-frame-router { 522 display: none; 523 } 524 525 .media-frame.hide-router .media-frame-title { 526 border-bottom: 1px solid #dfdfdf; 527 box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 ); 528 } 529 437 530 .media-frame .media-toolbar .add-to-gallery { 438 531 display: none; 439 532 } 440 533 534 .media-frame-title h1 { 535 padding: 0 16px; 536 font-size: 22px; 537 font-weight: 200; 538 line-height: 45px; 539 margin: 0; 540 } 541 441 542 /** 442 543 * Iframes 443 544 */ … … 721 822 * Attachments Browser 722 823 */ 723 824 .media-frame .attachments-browser { 825 position: relative; 826 width: 100%; 827 height: 100%; 724 828 overflow: hidden; 725 829 } 726 830 … … 903 1007 } 904 1008 905 1009 .uploader-window-content { 906 border-color: #fff; 1010 position: absolute; 1011 top: 10px; 1012 left: 10px; 1013 right: 10px; 1014 bottom: 10px; 1015 border: 1px dashed #fff; 907 1016 } 908 1017 909 1018 .uploader-window h3 { … … 956 1065 margin: 4em 0; 957 1066 } 958 1067 1068 .uploader-inline .has-upload-message .upload-ui { 1069 margin: 0 0 4em; 1070 } 1071 959 1072 .uploader-inline h3 { 960 1073 font-size: 20px; 961 1074 line-height: 28px; … … 963 1076 margin-bottom: 1.6em; 964 1077 } 965 1078 1079 .uploader-inline .has-upload-message .upload-instructions { 1080 font-size: 14px; 1081 color: #464646; 1082 font-weight: normal; 1083 } 1084 966 1085 .uploader-inline .drop-instructions { 967 1086 display: none; 968 1087 } … … 1058 1177 vertical-align: top; 1059 1178 } 1060 1179 1061 .media-selection .attachment img{1180 .media-selection .attachment .icon { 1062 1181 width: 50%; 1063 1182 } 1064 1183 … … 1098 1217 } 1099 1218 1100 1219 /** 1101 * Selection Preview1102 */1103 .selection-preview {1104 position: relative;1105 height: 60px;1106 overflow: hidden;1107 }1108 1109 .selected-img {1110 float: left;1111 position: relative;1112 margin-right: 14px;1113 }1114 1115 .selection-preview img {1116 max-width: 40px;1117 max-height: 40px;1118 float: left;1119 margin-top: 6px;1120 margin-left: 1px;1121 border: 2px solid white;1122 box-shadow:1123 0 0 0 1px #ccc,1124 3px 3px 0 0 #fff,1125 3px 3px 0 1px #ccc,1126 6px 6px 0 0 #fff,1127 6px 6px 0 1px #ccc;1128 }1129 1130 .selection-preview .selected-count-1 img {1131 margin-top: 8px;1132 box-shadow: 0 0 0 1px #ccc;1133 }1134 1135 .selection-preview .selected-count-2 img {1136 margin-top: 7px;1137 box-shadow:1138 0 0 0 1px #ccc,1139 3px 3px 0 0 #fff,1140 3px 3px 0 1px #ccc;1141 }1142 1143 .selection-preview .count {1144 position: absolute;1145 bottom: 0;1146 right: 0;1147 height: 16px;1148 min-width: 8px;1149 padding: 0 4px;1150 font-size: 12px;1151 text-align: center;1152 font-weight: bold;1153 color: #999;1154 background: #fff;1155 box-shadow: -1px -1px 2px -1px rgba( 0, 0, 0, 0.2 );1156 }1157 1158 .selection-preview .clear-selection {1159 float: left;1160 line-height: 60px;1161 }1162 1163 /**1164 1220 * Spinner 1165 1221 */ 1166 1222 .media-sidebar .settings-save-status { … … 1296 1352 .embed-url { 1297 1353 display: block; 1298 1354 position: relative; 1299 height: 75px;1300 padding: 16px 16px;1355 height: 40px; 1356 padding: 0 16px 16px; 1301 1357 margin: 0; 1302 z-index: 50; 1358 z-index: 250; 1359 background: #fff; 1303 1360 border-bottom: 1px solid #dfdfdf; 1304 1361 box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.1 ); 1305 1362 font-size: 18px; 1306 1363 font-weight: 200; 1307 1364 } 1308 1365 1309 .embed-url span {1310 display: block;1311 padding: 4px 0 6px 2px;1312 }1313 1314 1366 .media-frame .embed-url input { 1315 1367 font-size: 18px; 1316 1368 padding: 12px 14px; … … 1323 1375 .embed-image-settings { 1324 1376 position: absolute; 1325 1377 background: #f5f5f5; 1326 top: 108px;1378 top: 57px; 1327 1379 left: 0; 1328 1380 right: 0; 1329 1381 bottom: 0; … … 1387 1439 * Responsive layout 1388 1440 */ 1389 1441 @media only screen and (max-width: 900px) { 1390 .media-modal { 1391 bottom: 20px; 1392 left: 20px; 1393 right: 20px; 1394 top: 40px; 1395 } 1396 1397 .media-modal-title { 1398 height: 30px; 1399 line-height: 30px; 1400 top: -30px; 1401 } 1402 1403 .media-modal-close { 1404 top: -23px; 1405 } 1406 1407 .media-modal-backdrop div, 1408 .uploader-window-content { 1409 top: 5px; 1410 left: 5px; 1411 right: 5px; 1412 bottom: 5px; 1413 } 1414 1415 .media-menu { 1442 .media-frame-menu { 1416 1443 width: 139px; 1417 1444 } 1418 1445 … … 1420 1447 padding: 4px 10px; 1421 1448 } 1422 1449 1423 .media-frame .region-content,1424 .media-frame-toolbar > .media-toolbar{1450 .media-frame-content, 1451 .media-frame-toolbar { 1425 1452 left: 140px; 1426 1453 } 1427 1454 -
wp-includes/js/media-editor.js
384 384 385 385 workflow = workflows[ id ] = wp.media( _.defaults( options || {}, { 386 386 frame: 'post', 387 state: ' upload',387 state: 'insert', 388 388 title: wp.media.view.l10n.addMedia, 389 389 multiple: true 390 390 } ) ); … … 408 408 }, this ); 409 409 410 410 workflow.state('embed').on( 'select', function() { 411 var embed = workflow.state().toJSON(); 411 var state = workflow.state(), 412 type = state.get('type'), 413 embed = state.props.toJSON(); 412 414 413 415 embed.url = embed.url || ''; 414 416 415 if ( 'link' === embed.type ) {417 if ( 'link' === type ) { 416 418 _.defaults( embed, { 417 419 title: embed.url, 418 420 linkUrl: embed.url … … 420 422 421 423 this.send.link( embed ); 422 424 423 } else if ( 'image' === embed.type ) {425 } else if ( 'image' === type ) { 424 426 _.defaults( embed, { 425 427 title: embed.url, 426 428 linkUrl: '', -
wp-includes/js/media-views.js
68 68 * wp.media.controller.Region 69 69 */ 70 70 media.controller.Region = function( options ) { 71 _.extend( this, _.pick( options || {}, 'id', 'controller', 'selector' ) ); 72 73 this.on( 'activate:empty', this.empty, this ); 74 this.mode('empty'); 71 _.extend( this, _.pick( options || {}, 'id', 'view', 'selector' ) ); 75 72 }; 76 73 77 74 // Use Backbone's self-propagating `extend` inheritance method. 78 75 media.controller.Region.extend = Backbone.Model.extend; 79 76 80 _.extend( media.controller.Region.prototype, Backbone.Events,{81 trigger: (function() {82 var eventSplitter = /\s+/,83 trigger = Backbone.Events.trigger;77 _.extend( media.controller.Region.prototype, { 78 mode: function( mode ) { 79 if ( ! mode ) 80 return this._mode; 84 81 85 return function( events ) { 86 var mode = ':' + this._mode, 87 modeEvents = events.split( eventSplitter ).join( mode ) + mode; 88 89 trigger.apply( this, arguments ); 90 trigger.apply( this, [ modeEvents ].concat( _.rest( arguments ) ) ); 82 // Bail if we're trying to change to the current mode. 83 if ( mode === this._mode ) 91 84 return this; 92 };93 }()),94 85 95 mode: function( mode ) { 96 if ( mode ) { 97 this.trigger( 'deactivate', this ); 98 this._mode = mode; 99 return this.trigger( 'activate', this ); 100 } 101 return this._mode; 86 this.trigger('deactivate'); 87 this._mode = mode; 88 this.render( mode ); 89 this.trigger('activate'); 90 return this; 102 91 }, 103 92 104 view: function( view ) { 105 var previous = this._view, 106 mode = this._mode, 107 id = this.id; 93 render: function( mode ) { 94 // If no mode is provided, just re-render the current mode. 95 // If the provided mode isn't active, perform a full switch. 96 if ( mode && mode !== this._mode ) 97 return this.mode( mode ); 108 98 109 // If no argument is provided, return the current view. 110 if ( ! view ) 111 return previous; 99 var set = { view: null }, 100 view; 112 101 113 // If we're attempting to switch to the current view, bail. 114 if ( view === previous ) 102 this.trigger( 'create', set ); 103 view = set.view; 104 this.trigger( 'render', view ); 105 if ( view ) 106 this.set( view ); 107 return this; 108 }, 109 110 get: function() { 111 return this.view.views.first( this.selector ); 112 }, 113 114 set: function( views, options ) { 115 if ( options ) 116 options.add = false; 117 return this.view.views.set( this.selector, views, options ); 118 }, 119 120 trigger: function( event ) { 121 var base; 122 if ( ! this._mode ) 115 123 return; 116 124 117 // Add classes to the new view. 118 if ( id ) 119 view.$el.addClass( 'region-' + id ); 125 var args = _.toArray( arguments ); 126 base = this.id + ':' + event; 120 127 121 if ( mode ) 122 view.$el.addClass( 'mode-' + mode ); 128 // Trigger `region:action:mode` event. 129 args[0] = base + ':' + this._mode; 130 this.view.trigger.apply( this.view, args ); 123 131 124 this.controller.views.set( this.selector, view ); 125 this._view = view; 126 }, 127 128 empty: function() { 129 this.view( new media.View() ); 132 // Trigger `region:action` event. 133 args[0] = base; 134 this.view.trigger.apply( this.view, args ); 135 return this; 130 136 } 131 137 }); 132 138 … … 208 214 // wp.media.controller.State 209 215 // --------------------------- 210 216 media.controller.State = Backbone.Model.extend({ 211 initialize: function() {212 this.on( 'activate', this._ activate, this );217 constructor: function() { 218 this.on( 'activate', this._preActivate, this ); 213 219 this.on( 'activate', this.activate, this ); 220 this.on( 'activate', this._postActivate, this ); 214 221 this.on( 'deactivate', this._deactivate, this ); 215 222 this.on( 'deactivate', this.deactivate, this ); 216 223 this.on( 'reset', this.reset, this ); 224 this.on( 'ready', this._ready, this ); 225 this.on( 'ready', this.ready, this ); 226 227 this.on( 'change:menu', this._updateMenu, this ); 228 229 Backbone.Model.apply( this, arguments ); 217 230 }, 218 231 232 ready: function() {}, 219 233 activate: function() {}, 220 _activate: function() { 234 deactivate: function() {}, 235 reset: function() {}, 236 237 _ready: function() { 238 this._updateMenu(); 239 }, 240 241 _preActivate: function() { 221 242 this.active = true; 243 }, 222 244 223 this.menu(); 224 this.toolbar(); 225 this.content(); 245 _postActivate: function() { 246 this.on( 'change:menu', this._menu, this ); 247 this.on( 'change:titleMode', this._title, this ); 248 this.on( 'change:content', this._content, this ); 249 this.on( 'change:toolbar', this._toolbar, this ); 250 251 this.frame.on( 'title:render:default', this._renderTitle, this ); 252 253 this._title(); 254 this._menu(); 255 this._toolbar(); 256 this._content(); 257 this._router(); 226 258 }, 227 259 228 deactivate: function() {}, 260 229 261 _deactivate: function() { 230 262 this.active = false; 263 264 this.frame.off( 'title:render:default', this._renderTitle, this ); 265 266 this.off( 'change:menu', this._menu, this ); 267 this.off( 'change:titleMode', this._title, this ); 268 this.off( 'change:content', this._content, this ); 269 this.off( 'change:toolbar', this._toolbar, this ); 231 270 }, 232 271 233 reset: function() {}, 272 _title: function() { 273 this.frame.title.render( this.get('titleMode') || 'default' ); 274 }, 234 275 235 menu: function() { 276 _renderTitle: function( view ) { 277 view.$el.text( this.get('title') || '' ); 278 }, 279 280 _router: function() { 281 var router = this.frame.router, 282 mode = this.get('router'), 283 view; 284 285 this.frame.$el.toggleClass( 'hide-router', ! mode ); 286 if ( ! mode ) 287 return; 288 289 this.frame.router.render( mode ); 290 291 view = router.get(); 292 if ( view.select ) 293 view.select( this.frame.content.mode() ); 294 }, 295 296 _menu: function() { 236 297 var menu = this.frame.menu, 237 298 mode = this.get('menu'), 238 299 view; … … 240 301 if ( ! mode ) 241 302 return; 242 303 243 if ( menu.mode() !== mode ) 244 menu.mode( mode ); 304 menu.mode( mode ); 245 305 246 view = menu. view();306 view = menu.get(); 247 307 if ( view.select ) 248 308 view.select( this.id ); 309 }, 310 311 _updateMenu: function() { 312 var previous = this.previous('menu'), 313 menu = this.get('menu'); 314 315 if ( previous ) 316 this.frame.off( 'menu:render:' + previous, this._renderMenu, this ); 317 318 if ( menu ) 319 this.frame.on( 'menu:render:' + menu, this._renderMenu, this ); 320 }, 321 322 _renderMenu: function( view ) { 323 var menuItem = this.get('menuItem'), 324 title = this.get('title'), 325 priority = this.get('priority'); 326 327 if ( ! menuItem && title ) { 328 menuItem = { text: title }; 329 330 if ( priority ) 331 menuItem.priority = priority; 332 } 333 334 if ( ! menuItem ) 335 return; 336 337 view.set( this.id, menuItem ); 249 338 } 250 339 }); 251 340 252 341 _.each(['toolbar','content'], function( region ) { 253 media.controller.State.prototype[ region ] = function() {342 media.controller.State.prototype[ '_' + region ] = function() { 254 343 var mode = this.get( region ); 255 344 if ( mode ) 256 this.frame[ region ]. mode( mode );345 this.frame[ region ].render( mode ); 257 346 }; 258 347 }); 259 348 … … 264 353 id: 'library', 265 354 multiple: false, 266 355 describe: false, 267 toolbar: ' main-attachments',356 toolbar: 'select', 268 357 sidebar: 'settings', 269 content: 'browse', 358 content: 'upload', 359 router: 'browse', 270 360 searchable: true, 271 361 filterable: false, 272 uploads: true, 273 sortable: true 362 sortable: true, 363 title: l10n.mediaLibraryTitle, 364 365 // Uses a user setting to override the content mode. 366 contentUserSetting: true 274 367 }, 275 368 276 369 initialize: function() { … … 290 383 this.set( 'gutter', 8 ); 291 384 292 385 this.resetDisplays(); 293 294 media.controller.State.prototype.initialize.apply( this, arguments );295 386 }, 296 387 297 388 activate: function() { … … 303 394 this.on( 'change:library change:exclude', this.buildComposite, this ); 304 395 this.on( 'change:excludeState', this._excludeState, this ); 305 396 306 // If we're in a workflow that supports multiple attachments, 307 // automatically select any uploading attachments. 308 if ( this.get('multiple') ) 309 wp.Uploader.queue.on( 'add', this.selectUpload, this ); 397 wp.Uploader.queue.on( 'add', this.uploading, this ); 310 398 311 399 selection.on( 'add remove reset', this.refreshSelection, this ); 312 400 313 this.refresh();314 401 this.on( 'insert', this._insertDisplaySettings, this ); 402 403 if ( this.get('contentUserSetting') ) { 404 this.frame.on( 'content:activate', this.saveContentMode, this ); 405 this.set( 'content', getUserSetting( 'libraryContent', this.get('content') ) ); 406 } 315 407 }, 316 408 317 409 deactivate: function() { 410 this.frame.off( 'content:activate', this.saveContentMode, this ); 411 318 412 // Unbind all event handlers that use this state as the context 319 413 // from the selection. 320 414 this.get('selection').off( null, null, this ); … … 332 426 this.resetDisplays(); 333 427 }, 334 428 335 refresh: function() {336 this.content();337 this.refreshSelection();338 },339 340 429 resetDisplays: function() { 341 430 this._displays = []; 342 431 this._defaultDisplaySettings = { … … 375 464 var selection = this.get('selection'), 376 465 mode = this.frame.content.mode(); 377 466 378 this.frame.toolbar. view().refresh();467 this.frame.toolbar.get().refresh(); 379 468 this.trigger( 'refresh:selection', this, selection ); 380 469 381 470 if ( ! selection.length && 'browse' !== mode && 'upload' !== mode ) 382 this. content();471 this.frame.content.render(); 383 472 }, 384 473 385 selectUpload: function( attachment ) { 386 this.get('selection').add( attachment ); 474 uploading: function( attachment ) { 475 var content = this.frame.content; 476 477 // If the uploader was selected, navigate to the browser. 478 if ( 'upload' === content.mode() ) 479 this.frame.content.mode('browse'); 480 481 // If we're in a workflow that supports multiple attachments, 482 // automatically select any uploading attachments. 483 if ( this.get('multiple') ) 484 this.get('selection').add( attachment ); 387 485 }, 388 486 487 saveContentMode: function() { 488 // Only track the browse router on library states. 489 if ( 'browse' !== this.get('router') ) 490 return; 491 492 setUserSetting( 'libraryContent', this.frame.content.mode() ); 493 }, 494 389 495 buildComposite: function() { 390 496 var original = this.get('_library'), 391 497 exclude = this.get('exclude'), … … 448 554 } 449 555 }); 450 556 451 452 // wp.media.controller.Upload453 // ---------------------------454 media.controller.Upload = media.controller.State.extend({455 defaults: _.defaults({456 id: 'upload',457 content: 'upload',458 toolbar: 'empty',459 uploads: true,460 461 // The state to navigate to when files are uploading.462 libraryState: 'library'463 }, media.controller.State.prototype.defaults ),464 465 initialize: function() {466 media.controller.State.prototype.initialize.apply( this, arguments );467 },468 469 activate: function() {470 wp.Uploader.queue.on( 'add', this.uploading, this );471 media.controller.State.prototype.activate.apply( this, arguments );472 },473 474 deactivate: function() {475 wp.Uploader.queue.off( null, null, this );476 media.controller.State.prototype.deactivate.apply( this, arguments );477 },478 479 uploading: function( attachment ) {480 var library = this.get('libraryState');481 482 this.frame.state( library ).get('selection').add( attachment );483 this.frame.setState( library );484 }485 });486 487 557 // wp.media.controller.Gallery 488 558 // --------------------------- 489 559 media.controller.Gallery = media.controller.Library.extend({ … … 496 566 sortable: true, 497 567 searchable: false, 498 568 toolbar: 'gallery-edit', 499 content: 'browse' 569 content: 'browse', 570 title: l10n.editGalleryTitle, 571 priority: 60 500 572 }, 501 573 502 574 initialize: function() { … … 519 591 // Watch for uploaded attachments. 520 592 this.get('library').observe( wp.Uploader.queue ); 521 593 522 this.frame. content.on( 'activate:browse', this.gallerySettings, this );594 this.frame.on( 'content:render:browse', this.gallerySettings, this ); 523 595 524 596 media.controller.Library.prototype.activate.apply( this, arguments ); 525 597 }, … … 528 600 // Stop watching for uploaded attachments. 529 601 this.get('library').unobserve( wp.Uploader.queue ); 530 602 531 this.frame.content.off( null, null, this ); 603 this.frame.off( 'content:render:browse', this.gallerySettings, this ); 604 532 605 media.controller.Library.prototype.deactivate.apply( this, arguments ); 533 606 }, 534 607 535 gallerySettings: function() { 536 var library = this.get('library'), 537 browser; 608 gallerySettings: function( browser ) { 609 var library = this.get('library'); 538 610 539 if ( ! library )611 if ( ! library || ! browser ) 540 612 return; 541 613 542 614 library.gallery = library.gallery || new Backbone.Model(); 543 615 544 browser = this.frame.content.view();545 546 616 browser.sidebar.set({ 547 617 gallery: new media.view.Settings.Gallery({ 548 618 controller: this, … … 570 640 filterable: 'uploaded', 571 641 multiple: false, 572 642 menu: 'main', 573 toolbar: 'featured-image' 643 toolbar: 'featured-image', 644 title: l10n.featuredImageTitle, 645 priority: 60 574 646 }, media.controller.Library.prototype.defaults ), 575 647 576 648 initialize: function() { … … 629 701 menu: 'main', 630 702 content: 'embed', 631 703 toolbar: 'main-embed', 632 type: 'link' 704 type: 'link', 705 706 title: l10n.fromUrlTitle, 707 priority: 120 633 708 }, 634 709 635 710 // The amount of time used when debouncing the scan. … … 637 712 638 713 initialize: function() { 639 714 this.debouncedScan = _.debounce( _.bind( this.scan, this ), this.sensitivity ); 640 this.on( 'change:url', this.debouncedScan, this ); 715 this.props = new Backbone.Model({ url: '' }); 716 this.props.on( 'change:url', this.debouncedScan, this ); 641 717 this.on( 'scan', this.scanImage, this ); 642 media.controller.State.prototype.initialize.apply( this, arguments );643 718 }, 644 719 645 720 scan: function() { … … 652 727 scanImage: function( attributes ) { 653 728 var frame = this.frame, 654 729 state = this, 655 url = this. get('url'),730 url = this.props.get('url'), 656 731 image = new Image(); 657 732 658 733 image.onload = function() { 659 if ( state !== frame.state() || url !== state. get('url') )734 if ( state !== frame.state() || url !== state.props.get('url') ) 660 735 return; 661 736 662 737 state.set({ … … 670 745 }, 671 746 672 747 reset: function() { 673 _.each( _.difference( _.keys( this.attributes ), _.keys( this.defaults ) ), function( key ) { 674 this.unset( key ); 675 }, this ); 748 this.props = new Backbone.Model({ url: '' }); 676 749 677 this.set( 'url', '' );678 679 750 if ( this.id === this.frame.state().id ) 680 this.frame.toolbar. view().refresh();751 this.frame.toolbar.get().refresh(); 681 752 } 682 753 }); 683 754 … … 1022 1093 // The constructor for the `Views` manager. 1023 1094 Views: media.Views, 1024 1095 1025 constructor: function( ) {1096 constructor: function( options ) { 1026 1097 this.views = new this.Views( this, this.views ); 1027 1098 this.on( 'ready', this.ready, this ); 1099 1100 if ( options && options.controller ) 1101 this.controller = options.controller; 1102 1028 1103 Backbone.View.apply( this, arguments ); 1029 1104 }, 1030 1105 … … 1097 1172 // Initialize regions. 1098 1173 _.each( this.regions, function( region ) { 1099 1174 this[ region ] = new media.controller.Region({ 1100 controller:this,1101 id: 1102 selector: 1175 view: this, 1176 id: region, 1177 selector: '.media-frame-' + region 1103 1178 }); 1104 1179 }, this ); 1105 1180 }, … … 1113 1188 // Ensure states have a reference to the frame. 1114 1189 this.states.on( 'add', function( model ) { 1115 1190 model.frame = this; 1191 model.trigger('ready'); 1116 1192 }, this ); 1117 1193 }, 1118 1194 … … 1131 1207 media.view.MediaFrame = media.view.Frame.extend({ 1132 1208 className: 'media-frame', 1133 1209 template: media.template('media-frame'), 1134 regions: ['menu',' content','toolbar'],1210 regions: ['menu','title','content','toolbar','router'], 1135 1211 1136 1212 initialize: function() { 1137 1213 media.view.Frame.prototype.initialize.apply( this, arguments ); … … 1173 1249 } 1174 1250 1175 1251 this.on( 'attach', _.bind( this.views.ready, this.views ), this ); 1252 1253 // Bind default title creation. 1254 this.on( 'title:create:default', this.createTitle, this ); 1255 this.title.mode('default'); 1176 1256 }, 1177 1257 1178 1258 render: function() { … … 1183 1263 return media.view.Frame.prototype.render.apply( this, arguments ); 1184 1264 }, 1185 1265 1266 createTitle: function( title ) { 1267 title.view = new media.View({ 1268 controller: this, 1269 tagName: 'h1' 1270 }); 1271 }, 1272 1273 createMenu: function( menu ) { 1274 menu.view = new media.view.Menu({ 1275 controller: this 1276 }); 1277 }, 1278 1279 createToolbar: function( toolbar ) { 1280 menu.view = new media.view.Toolbar({ 1281 controller: this 1282 }); 1283 }, 1284 1285 createRouter: function( router ) { 1286 router.view = new media.view.Router({ 1287 controller: this 1288 }); 1289 }, 1290 1186 1291 createIframeStates: function( options ) { 1187 1292 var settings = media.view.settings, 1188 1293 tabs = settings.tabs, … … 1208 1313 }, options ) ); 1209 1314 }, this ); 1210 1315 1211 this. content.on( 'activate:iframe', this.iframeContent, this );1212 this. menu.on( 'activate:main', this.iframeMenu, this );1316 this.on( 'content:create:iframe', this.iframeContent, this ); 1317 this.on( 'menu:render:main', this.iframeMenu, this ); 1213 1318 this.on( 'open', this.hijackThickbox, this ); 1214 1319 this.on( 'close', this.restoreThickbox, this ); 1215 1320 }, 1216 1321 1217 iframeContent: function( ) {1322 iframeContent: function( content ) { 1218 1323 this.$el.addClass('hide-toolbar'); 1219 this.content.view(new media.view.Iframe({1324 content.view = new media.view.Iframe({ 1220 1325 controller: this 1221 }) .render() );1326 }); 1222 1327 }, 1223 1328 1224 iframeMenu: function( ) {1329 iframeMenu: function( view ) { 1225 1330 var views = {}; 1226 1331 1332 if ( ! view ) 1333 return; 1334 1227 1335 _.each( media.view.settings.tabs, function( title, id ) { 1228 1336 views[ 'iframe:' + id ] = { 1229 1337 text: this.state( 'iframe:' + id ).get('title'), … … 1231 1339 }; 1232 1340 }, this ); 1233 1341 1234 this.menu.view().set( views );1342 view.set( views ); 1235 1343 }, 1236 1344 1237 1345 hijackThickbox: function() { … … 1305 1413 new media.controller.Library({ 1306 1414 selection: options.selection, 1307 1415 library: media.query( options.library ), 1308 multiple: this.options.multiple,1416 multiple: options.multiple, 1309 1417 menu: 'main', 1310 toolbar: 'select' 1311 }), 1312 1313 new media.controller.Upload({ 1314 menu: 'main' 1418 title: options.title, 1419 priority: 20 1315 1420 }) 1316 1421 ]); 1317 1422 }, 1318 1423 1319 1424 bindHandlers: function() { 1320 this.menu.on( 'activate:main', this.mainMenu, this ); 1321 this.content.on( 'activate:browse', this.browseContent, this ); 1322 this.content.on( 'activate:upload', this.uploadContent, this ); 1323 this.toolbar.on( 'activate:select', this.selectToolbar, this ); 1425 this.on( 'menu:create:main', this.createMenu, this ); 1426 this.on( 'router:create:browse', this.createRouter, this ); 1427 this.on( 'router:render:browse', this.browseRouter, this ); 1428 this.on( 'content:create:browse', this.browseContent, this ); 1429 this.on( 'content:render:upload', this.uploadContent, this ); 1430 this.on( 'toolbar:create:select', this.createSelectToolbar, this ); 1324 1431 1325 1432 this.on( 'refresh:selection', this.refreshSelectToolbar, this ); 1326 1433 }, 1327 1434 1328 mainMenu: function( options ) { 1329 this.menu.view( new media.view.Menu({ 1330 controller: this, 1331 silent: options && options.silent, 1332 1333 views: { 1334 upload: { 1335 text: l10n.uploadFilesTitle, 1336 priority: 20 1337 }, 1338 library: { 1339 text: l10n.mediaLibraryTitle, 1340 priority: 40 1341 } 1435 // Routers 1436 browseRouter: function( view ) { 1437 view.set({ 1438 upload: { 1439 text: l10n.uploadFilesTitle, 1440 priority: 20 1441 }, 1442 browse: { 1443 text: l10n.mediaLibraryTitle, 1444 priority: 40 1342 1445 } 1343 }) );1446 }); 1344 1447 }, 1345 1448 1346 1449 // Content 1347 browseContent: function( ) {1450 browseContent: function( content ) { 1348 1451 var state = this.state(); 1349 1452 1350 1453 this.$el.removeClass('hide-toolbar'); 1351 1454 1352 1455 // Browse our library of attachments. 1353 this.content.view(new media.view.AttachmentsBrowser({1456 content.view = new media.view.AttachmentsBrowser({ 1354 1457 controller: this, 1355 1458 collection: state.get('library'), 1356 1459 selection: state.get('selection'), 1357 1460 model: state, 1358 1461 sortable: state.get('sortable'), 1359 1462 search: state.get('searchable'), 1360 uploads: state.get('uploads'),1361 1463 filters: state.get('filterable'), 1362 1464 display: state.get('displaySettings'), 1363 1465 1364 1466 AttachmentView: state.get('AttachmentView') 1365 }) );1467 }); 1366 1468 }, 1367 1469 1368 1470 uploadContent: function() { 1369 this.$el.addClass('hide-toolbar'); 1370 1371 this.content.view( new media.view.UploaderInline({ 1471 this.$el.removeClass('hide-toolbar'); 1472 this.content.set( new media.view.UploaderInline({ 1372 1473 controller: this 1373 1474 }) ); 1374 1475 }, 1375 1476 1376 1477 // Toolbars 1377 selectToolbar: function(options ) {1478 createSelectToolbar: function( toolbar, options ) { 1378 1479 options = _.defaults( options || {}, { 1379 1480 event: 'select', 1380 1481 silent: false, 1381 1482 state: false 1382 1483 }); 1383 1484 1384 t his.toolbar.view(new media.view.Toolbar({1485 toolbar.view = new media.view.Toolbar({ 1385 1486 controller: this, 1386 1487 silent: options.silent, 1387 1488 … … 1402 1503 } 1403 1504 } 1404 1505 } 1405 }) );1506 }); 1406 1507 }, 1407 1508 1408 1509 refreshSelectToolbar: function() { … … 1411 1512 if ( ! selection || 'select' !== this.toolbar.mode() ) 1412 1513 return; 1413 1514 1414 this.toolbar. view().get('select').model.set( 'disabled', ! selection.length );1515 this.toolbar.get().get('select').model.set( 'disabled', ! selection.length ); 1415 1516 } 1416 1517 }); 1417 1518 … … 1430 1531 }, 1431 1532 1432 1533 createStates: function() { 1433 var options = this.options; 1434 1435 // Add the default states. 1436 this.states.add([ 1437 // Main states. 1438 new media.controller.Library({ 1439 selection: options.selection, 1440 library: media.query( options.library ), 1534 var options = this.options, 1535 selection = options.selection, 1536 library = { 1441 1537 editable: true, 1442 filterable: 'all',1443 1538 multiple: this.options.multiple, 1444 1539 menu: 'main', 1445 1540 … … 1448 1543 // Update user settings when users adjust the 1449 1544 // attachment display settings. 1450 1545 displayUserSettings: true 1451 } ),1546 }; 1452 1547 1453 new media.controller.Upload({ 1454 menu: 'main' 1455 }), 1548 // Add the default states. 1549 this.states.add([ 1550 // Main states. 1551 new media.controller.Library( _.defaults({ 1552 id: 'insert', 1553 title: l10n.insertMediaTitle, 1554 priority: 20, 1555 toolbar: 'main-insert', 1556 filterable: 'all', 1557 library: media.query( options.library ), 1558 selection: selection 1559 }, library ) ), 1456 1560 1561 new media.controller.Library( _.defaults({ 1562 id: 'gallery', 1563 title: l10n.createGalleryTitle, 1564 priority: 40, 1565 toolbar: 'main-gallery', 1566 filterable: 'uploaded', 1567 1568 library: media.query( _.defaults({ 1569 type: 'image' 1570 }, options.library ) ), 1571 1572 selection: new media.model.Selection( selection.models, { 1573 multiple: selection.multiple 1574 }) 1575 }, library ) ), 1576 1457 1577 // Embed states. 1458 1578 new media.controller.Embed(), 1459 1579 … … 1471 1591 multiple: true, 1472 1592 menu: 'gallery', 1473 1593 toolbar: 'gallery-add', 1474 excludeState: 'gallery-edit' 1475 }), 1476 1477 new media.controller.Upload({ 1478 id: 'gallery-upload', 1479 menu: 'gallery', 1480 libraryState: 'gallery-edit' 1594 excludeState: 'gallery-edit', 1595 title: l10n.addToGalleryTitle, 1596 priority: 100 1481 1597 }) 1482 1598 ]); 1483 1599 … … 1492 1608 1493 1609 bindHandlers: function() { 1494 1610 media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments ); 1611 this.on( 'menu:create:gallery', this.createMenu, this ); 1612 this.on( 'toolbar:create:main-insert', this.createSelectionToolbar, this ); 1613 this.on( 'toolbar:create:main-gallery', this.createSelectionToolbar, this ); 1495 1614 1496 1615 var handlers = { 1497 1616 menu: { 1617 'main': 'mainMenu', 1498 1618 'gallery': 'galleryMenu' 1499 1619 }, 1500 1620 … … 1504 1624 }, 1505 1625 1506 1626 toolbar: { 1507 'main-attachments': 'mainAttachmentsToolbar', 1627 'main-insert': 'mainInsertToolbar', 1628 'main-gallery': 'mainGalleryToolbar', 1508 1629 'main-embed': 'mainEmbedToolbar', 1509 1630 'featured-image': 'featuredImageToolbar', 1510 1631 'gallery-edit': 'galleryEditToolbar', … … 1514 1635 1515 1636 _.each( handlers, function( regionHandlers, region ) { 1516 1637 _.each( regionHandlers, function( callback, handler ) { 1517 this [ region ].on( 'activate:' + handler, this[ callback ], this );1638 this.on( region + ':render:' + handler, this[ callback ], this ); 1518 1639 }, this ); 1519 1640 }, this ); 1520 1641 }, 1521 1642 1522 1643 // Menus 1523 mainMenu: function() { 1524 media.view.MediaFrame.Select.prototype.mainMenu.call( this, { silent: true }); 1525 1526 this.menu.view().set({ 1644 mainMenu: function( view ) { 1645 view.set({ 1527 1646 'library-separator': new media.View({ 1528 1647 className: 'separator', 1529 priority: 60 1530 }), 1531 'embed': { 1532 text: l10n.fromUrlTitle, 1533 priority: 80 1534 } 1648 priority: 100 1649 }) 1535 1650 }); 1536 1537 if ( media.view.settings.post.featuredImageId ) {1538 this.menu.view().set( 'featured-image', {1539 text: l10n.featuredImageTitle,1540 priority: 1001541 });1542 }1543 1651 }, 1544 1652 1545 galleryMenu: function( ) {1653 galleryMenu: function( view ) { 1546 1654 var lastState = this.lastState(), 1547 1655 previous = lastState && lastState.id, 1548 1656 frame = this; 1549 1657 1550 this.menu.view( new media.view.Menu({ 1551 controller: this, 1552 views: { 1553 cancel: { 1554 text: l10n.cancelGalleryTitle, 1555 priority: 20, 1556 click: function() { 1557 if ( previous ) 1558 frame.setState( previous ); 1559 else 1560 frame.close(); 1561 } 1562 }, 1563 separateCancel: new media.View({ 1564 className: 'separator', 1565 priority: 40 1566 }), 1567 'gallery-edit': { 1568 text: l10n.editGalleryTitle, 1569 priority: 60 1570 }, 1571 'gallery-upload': { 1572 text: l10n.uploadImagesTitle, 1573 priority: 80 1574 }, 1575 'gallery-library': { 1576 text: l10n.mediaLibraryTitle, 1577 priority: 100 1658 view.set({ 1659 cancel: { 1660 text: l10n.cancelGalleryTitle, 1661 priority: 20, 1662 click: function() { 1663 if ( previous ) 1664 frame.setState( previous ); 1665 else 1666 frame.close(); 1578 1667 } 1579 } 1580 }) ); 1668 }, 1669 separateCancel: new media.View({ 1670 className: 'separator', 1671 priority: 40 1672 }) 1673 }); 1581 1674 }, 1582 1675 1583 1676 // Content … … 1587 1680 model: this.state() 1588 1681 }).render(); 1589 1682 1590 this.content. view( view );1683 this.content.set( view ); 1591 1684 view.url.focus(); 1592 1685 }, 1593 1686 … … 1617 1710 }); 1618 1711 1619 1712 // Browse our library of attachments. 1620 this.content. view( view );1713 this.content.set( view ); 1621 1714 }, 1622 1715 1623 // Sidebars 1624 onSidebarGallerySettings: function( options ) { 1625 var library = this.state().get('library'); 1716 // Toolbars 1717 createSelectionToolbar: function( toolbar ) { 1718 toolbar.view = new media.view.Toolbar.Selection({ 1719 controller: this, 1720 editable: this.state().get('editable') 1721 }); 1722 }, 1626 1723 1627 if ( ! library )1628 return;1724 mainInsertToolbar: function( view ) { 1725 var controller = this; 1629 1726 1630 library.gallery = library.gallery || new Backbone.Model(); 1727 view.button = 'insert'; 1728 view.set( 'insert', { 1729 style: 'primary', 1730 priority: 80, 1731 text: l10n.insertIntoPost, 1631 1732 1632 this.sidebar.view().set({ 1633 gallery: new media.view.Settings.Gallery({ 1634 controller: this, 1635 model: library.gallery, 1636 priority: 40 1637 }).render() 1638 }, options ); 1733 click: function() { 1734 var state = controller.state(), 1735 selection = state.get('selection'); 1736 1737 controller.close(); 1738 state.trigger( 'insert', selection ).reset(); 1739 } 1740 }); 1639 1741 }, 1640 1742 1641 // Toolbars 1642 mainAttachmentsToolbar: function() { 1643 this.toolbar.view( new media.view.Toolbar.Insert({ 1644 controller: this, 1645 editable: this.state().get('editable') 1646 }) ); 1743 mainGalleryToolbar: function( view ) { 1744 var controller = this; 1745 1746 view.button = 'gallery'; 1747 view.set( 'gallery', { 1748 style: 'primary', 1749 text: l10n.createNewGallery, 1750 priority: 60, 1751 1752 click: function() { 1753 var selection = controller.state().get('selection'), 1754 edit = controller.state('gallery-edit'), 1755 models = selection.where({ type: 'image' }); 1756 1757 edit.set( 'library', new media.model.Selection( models, { 1758 props: selection.props.toJSON(), 1759 multiple: true 1760 }) ); 1761 1762 this.controller.setState('gallery-edit'); 1763 } 1764 }); 1647 1765 }, 1648 1766 1649 1767 featuredImageToolbar: function() { 1650 this.toolbar. view( new media.view.Toolbar.Select({1768 this.toolbar.set( new media.view.Toolbar.Select({ 1651 1769 controller: this, 1652 1770 text: l10n.setFeaturedImage, 1653 1771 state: this.options.state || 'upload' … … 1655 1773 }, 1656 1774 1657 1775 mainEmbedToolbar: function() { 1658 this.toolbar. view( new media.view.Toolbar.Embed({1776 this.toolbar.set( new media.view.Toolbar.Embed({ 1659 1777 controller: this 1660 1778 }) ); 1661 1779 … … 1664 1782 1665 1783 galleryEditToolbar: function() { 1666 1784 var editing = this.state().get('editing'); 1667 this.toolbar. view( new media.view.Toolbar({1785 this.toolbar.set( new media.view.Toolbar({ 1668 1786 controller: this, 1669 1787 items: { 1670 1788 insert: { … … 1689 1807 }, 1690 1808 1691 1809 galleryAddToolbar: function() { 1692 this.toolbar. view( new media.view.Toolbar({1810 this.toolbar.set( new media.view.Toolbar({ 1693 1811 controller: this, 1694 1812 items: { 1695 1813 insert: { … … 1704 1822 1705 1823 edit.get('library').add( state.get('selection').models ); 1706 1824 state.trigger('reset'); 1707 controller.s tate('gallery-edit');1825 controller.setState('gallery-edit'); 1708 1826 } 1709 1827 } 1710 1828 } … … 1729 1847 }, 1730 1848 1731 1849 initialize: function() { 1732 this.controller = this.options.controller;1733 1734 1850 _.defaults( this.options, { 1735 1851 container: document.body, 1736 1852 title: '', … … 1838 1954 initialize: function() { 1839 1955 var uploader; 1840 1956 1841 this.controller = this.options.controller;1842 1843 1957 this.$browser = $('<a href="#" class="browser" />').hide().appendTo('body'); 1844 1958 1845 1959 uploader = this.options.uploader = _.defaults( this.options.uploader || {}, { … … 1906 2020 template: media.template('uploader-inline'), 1907 2021 1908 2022 initialize: function() { 1909 this.controller = this.options.controller; 2023 _.defaults( this.options, { 2024 message: '', 2025 status: true 2026 }); 1910 2027 1911 2028 if ( ! this.options.$browser && this.controller.uploader ) 1912 2029 this.options.$browser = this.controller.uploader.$browser; … … 1914 2031 if ( _.isUndefined( this.options.postId ) ) 1915 2032 this.options.postId = media.view.settings.post.id; 1916 2033 1917 this.views.set( '.upload-inline-status', new media.view.UploaderStatus({ 1918 controller: this.controller 1919 }) ); 2034 if ( this.options.status ) { 2035 this.views.set( '.upload-inline-status', new media.view.UploaderStatus({ 2036 controller: this.controller 2037 }) ); 2038 } 1920 2039 }, 1921 2040 1922 2041 ready: function() { … … 1951 2070 }, 1952 2071 1953 2072 initialize: function() { 1954 this.controller = this.options.controller;1955 1956 2073 this.queue = wp.Uploader.queue; 1957 2074 this.queue.on( 'add remove reset', this.visibility, this ); 1958 2075 this.queue.on( 'add remove reset change:percent', this.progress, this ); … … 2060 2177 className: 'media-toolbar', 2061 2178 2062 2179 initialize: function() { 2063 this.controller = this.options.controller;2064 2065 2180 this._views = {}; 2066 2181 this.$primary = $('<div class="media-toolbar-primary" />').prependTo( this.$el ); 2067 2182 this.$secondary = $('<div class="media-toolbar-secondary" />').prependTo( this.$el ); … … 2199 2314 // --------------------------- 2200 2315 media.view.Toolbar.Embed = media.view.Toolbar.Select.extend({ 2201 2316 initialize: function() { 2202 var controller = this.options.controller;2203 2204 2317 _.defaults( this.options, { 2205 2318 text: l10n.insertIntoPost 2206 2319 }); 2207 2320 2208 2321 media.view.Toolbar.Select.prototype.initialize.apply( this, arguments ); 2209 controller.on( 'change:url', this.refresh, this );2322 this.controller.state().props.on( 'change:url', this.refresh, this ); 2210 2323 }, 2211 2324 2212 2325 refresh: function() { 2213 var url = this.controller.state(). get('url');2326 var url = this.controller.state().props.get('url'); 2214 2327 this.get('select').model.set( 'disabled', ! url || /^https?:\/\/$/.test(url) ); 2215 2328 } 2216 2329 }); 2217 2330 2218 // wp.media.view.Toolbar. Insert2331 // wp.media.view.Toolbar.Selection 2219 2332 // ---------------------------- 2220 media.view.Toolbar.Insert = media.view.Toolbar.extend({ 2333 media.view.Toolbar.Selection = media.view.Toolbar.extend({ 2334 button: 'insert', 2335 2221 2336 initialize: function() { 2222 var controller = this.options.controller, 2223 selection = controller.state().get('selection'), 2224 selectionToLibrary; 2337 var controller = this.controller; 2225 2338 2226 selectionToLibrary = function( state, filter ) {2227 return function() {2228 var controller = this.controller,2229 selection = controller.state().get('selection'),2230 edit = controller.state( state ),2231 models = filter ? filter( selection ) : selection.models;2232 2233 edit.set( 'library', new media.model.Selection( models, {2234 props: selection.props.toJSON(),2235 multiple: true2236 }) );2237 2238 this.controller.setState( state );2239 };2240 };2241 2242 2339 this.options.items = _.defaults( this.options.items || {}, { 2243 2340 selection: new media.view.Selection({ 2244 2341 controller: controller, 2245 collection: selection,2342 collection: controller.state().get('selection'), 2246 2343 priority: -40, 2247 2344 2248 2345 // If the selection is editable, pass the callback to … … 2250 2347 editable: this.options.editable && function() { 2251 2348 this.controller.content.mode('edit-selection'); 2252 2349 } 2253 }).render(), 2254 2255 insert: { 2256 style: 'primary', 2257 priority: 80, 2258 text: l10n.insertIntoPost, 2259 2260 click: function() { 2261 controller.close(); 2262 controller.state().trigger( 'insert', selection ).reset(); 2263 } 2264 }, 2265 2266 gallery: { 2267 text: l10n.createNewGallery, 2268 priority: 40, 2269 click: selectionToLibrary('gallery-edit', function( selection ) { 2270 return selection.where({ type: 'image' }); 2271 }) 2272 } 2350 }).render() 2273 2351 }); 2274 2352 2275 2353 media.view.Toolbar.prototype.initialize.apply( this, arguments ); … … 2277 2355 2278 2356 refresh: function() { 2279 2357 var selection = this.controller.state().get('selection'), 2280 count = selection.length;2358 button = this.get( this.button ); 2281 2359 2282 this.get('insert').model.set( 'disabled', ! selection.length ); 2360 if ( ! button ) 2361 return; 2283 2362 2284 // Check if any attachment in the selection is an image. 2285 this.get('gallery').$el.toggle( count > 1 && selection.any( function( attachment ) { 2286 return 'image' === attachment.get('type'); 2287 }) ); 2363 button.model.set( 'disabled', ! selection.length ); 2288 2364 } 2289 2365 }); 2290 2366 … … 2388 2464 tagName: 'div', 2389 2465 2390 2466 initialize: function() { 2391 this.controller = this.options.controller; 2392 this._views = {}; 2467 this._views = {}; 2393 2468 2394 2469 this.set( _.extend( {}, this._views, this.options.views ), { silent: true }); 2395 2470 delete this.options.views; … … 2457 2532 } 2458 2533 }); 2459 2534 2535 /** 2536 * wp.media.view.MenuItem 2537 */ 2538 media.view.MenuItem = media.View.extend({ 2539 tagName: 'a', 2540 className: 'media-menu-item', 2460 2541 2542 attributes: { 2543 href: '#' 2544 }, 2545 2546 events: { 2547 'click': '_click' 2548 }, 2549 2550 _click: function( event ) { 2551 var clickOverride = this.options.click; 2552 2553 event.preventDefault(); 2554 2555 if ( clickOverride ) 2556 clickOverride.call( this ); 2557 else 2558 this.click(); 2559 }, 2560 2561 click: function() { 2562 var state = this.options.state; 2563 if ( state ) 2564 this.controller.setState( state ); 2565 }, 2566 2567 render: function() { 2568 var options = this.options; 2569 2570 if ( options.text ) 2571 this.$el.text( options.text ); 2572 else if ( options.html ) 2573 this.$el.html( options.html ); 2574 2575 return this; 2576 } 2577 }); 2578 2461 2579 /** 2462 2580 * wp.media.view.Menu 2463 2581 */ 2464 2582 media.view.Menu = media.view.PriorityList.extend({ 2465 tagName: ' ul',2583 tagName: 'div', 2466 2584 className: 'media-menu', 2585 property: 'state', 2586 ItemView: media.view.MenuItem, 2587 region: 'menu', 2467 2588 2468 toView: function( options, state) {2589 toView: function( options, id ) { 2469 2590 options = options || {}; 2470 options .state = options.state || state;2471 return new media.view.MenuItem( options ).render();2591 options[ this.property ] = options[ this.property ] || id; 2592 return new this.ItemView( options ).render(); 2472 2593 }, 2473 2594 2474 select: function( state ) { 2475 var view = this.get( state ); 2595 ready: function() { 2596 media.view.PriorityList.prototype.ready.apply( this, arguments ); 2597 this.visibility(); 2598 }, 2476 2599 2600 set: function() { 2601 media.view.PriorityList.prototype.set.apply( this, arguments ); 2602 this.visibility(); 2603 }, 2604 2605 unset: function() { 2606 media.view.PriorityList.prototype.unset.apply( this, arguments ); 2607 this.visibility(); 2608 }, 2609 2610 visibility: function() { 2611 var region = this.region, 2612 view = this.controller[ region ].get(), 2613 views = this.views.get(), 2614 hide = ! views || views.length < 2; 2615 2616 if ( this === view ) 2617 this.controller.$el.toggleClass( 'hide-' + region, hide ); 2618 }, 2619 2620 select: function( id ) { 2621 var view = this.get( id ); 2622 2477 2623 if ( ! view ) 2478 2624 return; 2479 2625 … … 2486 2632 } 2487 2633 }); 2488 2634 2489 media.view.MenuItem = media.View.extend({ 2490 tagName: 'li', 2491 className: 'media-menu-item', 2635 /** 2636 * wp.media.view.RouterItem 2637 */ 2638 media.view.RouterItem = media.view.MenuItem.extend({ 2639 click: function() { 2640 var contentMode = this.options.contentMode; 2641 if ( contentMode ) 2642 this.controller.content.mode( contentMode ); 2643 } 2644 }); 2492 2645 2493 events: { 2494 'click': 'click' 2495 }, 2646 /** 2647 * wp.media.view.Router 2648 */ 2649 media.view.Router = media.view.Menu.extend({ 2650 tagName: 'div', 2651 className: 'media-router', 2652 property: 'contentMode', 2653 ItemView: media.view.RouterItem, 2654 region: 'router', 2496 2655 2497 click: function() { 2498 var options = this.options; 2499 2500 if ( options.click ) 2501 options.click.call( this ); 2502 else if ( options.state ) 2503 this.controller.setState( options.state ); 2656 initialize: function() { 2657 this.controller.on( 'content:render', this.update, this ); 2658 media.view.Menu.prototype.initialize.apply( this, arguments ); 2504 2659 }, 2505 2660 2506 render: function() { 2507 var options = this.options; 2508 2509 if ( options.text ) 2510 this.$el.text( options.text ); 2511 else if ( options.html ) 2512 this.$el.html( options.html ); 2513 2514 return this; 2661 update: function() { 2662 var mode = this.controller.content.mode(); 2663 if ( mode ) 2664 this.select( mode ); 2515 2665 } 2516 2666 }); 2517 2667 2668 2518 2669 /** 2519 2670 * wp.media.view.Sidebar 2520 2671 */ … … 2546 2697 initialize: function() { 2547 2698 var selection = this.options.selection; 2548 2699 2549 this.controller = this.options.controller;2550 2551 2700 this.model.on( 'change:sizes change:uploading change:caption change:title', this.render, this ); 2552 2701 this.model.on( 'change:percent', this.progress, this ); 2553 2702 … … 2838 2987 }, 2839 2988 2840 2989 initialize: function() { 2841 this.controller = this.options.controller;2842 2990 this.el.id = _.uniqueId('__attachments-view-'); 2843 2991 2844 2992 _.defaults( this.options, { … … 3200 3348 className: 'attachments-browser', 3201 3349 3202 3350 initialize: function() { 3203 this.controller = this.options.controller;3204 3205 3351 _.defaults( this.options, { 3206 3352 filters: false, 3207 3353 search: true, 3208 uploads: false,3209 3354 display: false, 3210 3355 3211 3356 AttachmentView: media.view.Attachment.Library … … 3290 3435 this.removeContent(); 3291 3436 3292 3437 this.uploader = new media.view.UploaderInline({ 3293 controller: this.controller 3438 controller: this.controller, 3439 status: false, 3440 message: l10n.noItemsFound 3294 3441 }); 3295 3442 3296 3443 this.views.add( this.uploader ); … … 3322 3469 3323 3470 this.views.add( sidebar ); 3324 3471 3325 if ( options.uploads &&this.controller.uploader ) {3472 if ( this.controller.uploader ) { 3326 3473 sidebar.set( 'uploads', new media.view.UploaderStatus({ 3327 3474 controller: this.controller, 3328 3475 priority: 40 … … 3373 3520 }); 3374 3521 3375 3522 /** 3376 * wp.media.view.SelectionPreview3377 */3378 media.view.SelectionPreview = media.View.extend({3379 tagName: 'div',3380 className: 'selection-preview',3381 template: media.template('media-selection-preview'),3382 3383 events: {3384 'click .clear-selection': 'clear'3385 },3386 3387 initialize: function() {3388 _.defaults( this.options, {3389 clearable: true3390 });3391 3392 this.controller = this.options.controller;3393 this.collection.on( 'add change:url remove', this.render, this );3394 this.render();3395 },3396 3397 render: function() {3398 var options = _.clone( this.options ),3399 last, sizes, amount;3400 3401 // If nothing is selected, display nothing.3402 if ( ! this.collection.length ) {3403 this.$el.empty();3404 return this;3405 }3406 3407 options.count = this.collection.length;3408 last = this.collection.last();3409 sizes = last.get('sizes');3410 3411 if ( 'image' === last.get('type') )3412 options.thumbnail = ( sizes && sizes.thumbnail ) ? sizes.thumbnail.url : last.get('url');3413 else3414 options.thumbnail = last.get('icon');3415 3416 this.$el.html( this.template( options ) );3417 return this;3418 },3419 3420 clear: function( event ) {3421 event.preventDefault();3422 this.collection.reset();3423 }3424 });3425 3426 /**3427 3523 * wp.media.view.Selection 3428 3524 */ 3429 3525 media.view.Selection = media.View.extend({ … … 3442 3538 clearable: true 3443 3539 }); 3444 3540 3445 this.controller = this.options.controller;3446 3541 this.attachments = new media.view.Attachments({ 3447 3542 controller: this.controller, 3448 3543 collection: this.collection, … … 3768 3863 media.view.Iframe = media.View.extend({ 3769 3864 className: 'media-iframe', 3770 3865 3771 initialize: function() {3772 this.controller = this.options.controller;3773 },3774 3775 3866 render: function() { 3867 this.views.detach(); 3776 3868 this.$el.html( '<iframe src="' + this.controller.state().get('src') + '" />' ); 3869 this.views.render(); 3777 3870 return this; 3778 3871 } 3779 3872 }); … … 3785 3878 className: 'media-embed', 3786 3879 3787 3880 initialize: function() { 3788 this.controller = this.options.controller;3789 3790 3881 this.url = new media.view.EmbedUrl({ 3791 3882 controller: this.controller, 3792 model: this.model 3883 model: this.model.props 3793 3884 }).render(); 3794 3885 3795 3886 this._settings = new media.View(); … … 3826 3917 3827 3918 this.settings( new constructor({ 3828 3919 controller: this.controller, 3829 model: this.model ,3920 model: this.model.props, 3830 3921 priority: 40 3831 3922 }) ); 3832 3923 } … … 3846 3937 }, 3847 3938 3848 3939 initialize: function() { 3849 this.label = this.make( 'span', null, this.options.label || l10n.url );3850 3940 this.input = this.make( 'input', { 3851 3941 type: 'text', 3852 3942 value: this.model.get('url') || '' 3853 3943 }); 3854 3944 3855 this.$label = $( this.label );3856 3945 this.$input = $( this.input ); 3857 this.$el.append( [ this.label, this.input ]);3946 this.$el.append( this.input ); 3858 3947 3859 3948 this.model.on( 'change:url', this.render, this ); 3860 3949 }, -
wp-includes/media.php
1467 1467 1468 1468 // Library 1469 1469 'mediaLibraryTitle' => __( 'Media Library' ), 1470 'insertMediaTitle' => __( 'Insert Media' ), 1470 1471 'createNewGallery' => __( 'Create a new gallery' ), 1471 1472 'returnToLibrary' => __( '← Return to library' ), 1472 1473 'allMediaItems' => __( 'All media items' ), 1474 'noItemsFound' => __( 'No items found.' ), 1473 1475 'insertIntoPost' => $hier ? __( 'Insert into page' ) : __( 'Insert into post' ), 1474 1476 'uploadedToThisPost' => $hier ? __( 'Uploaded to this page' ) : __( 'Uploaded to this post' ), 1475 1477 'warnDelete' => __( "You are about to permanently delete this item.\n 'Cancel' to stop, 'OK' to delete." ), … … 1489 1491 'updateGallery' => __( 'Update gallery' ), 1490 1492 'continueEditing' => __( 'Continue editing' ), 1491 1493 'addToGallery' => __( 'Add to gallery' ), 1494 'addToGalleryTitle' => __( 'Add to Gallery' ), 1492 1495 'reverseOrder' => __( 'Reverse order' ), 1493 1496 ); 1494 1497 … … 1517 1520 ?> 1518 1521 <script type="text/html" id="tmpl-media-frame"> 1519 1522 <div class="media-frame-menu"></div> 1523 <div class="media-frame-title"></div> 1524 <div class="media-frame-router"></div> 1520 1525 <div class="media-frame-content"></div> 1521 1526 <div class="media-frame-toolbar"></div> 1522 1527 <div class="media-frame-uploader"></div> … … 1524 1529 1525 1530 <script type="text/html" id="tmpl-media-modal"> 1526 1531 <div class="media-modal wp-core-ui"> 1527 <h3 class="media-modal-title">{{ data.title }}</h3> 1528 <a class="media-modal-close media-modal-icon" href="#" title="<?php esc_attr_e('Close'); ?>"></a> 1532 <a class="media-modal-close" href="#" title="<?php esc_attr_e('Close'); ?>"><span class="media-modal-icon"></span></a> 1529 1533 <div class="media-modal-content"></div> 1530 1534 </div> 1531 <div class="media-modal-backdrop"> 1532 <div></div> 1533 </div> 1535 <div class="media-modal-backdrop"></div> 1534 1536 </script> 1535 1537 1536 1538 <script type="text/html" id="tmpl-uploader-window"> … … 1540 1542 </script> 1541 1543 1542 1544 <script type="text/html" id="tmpl-uploader-inline"> 1543 <div class="uploader-inline-content"> 1545 <# var messageClass = data.message ? 'has-upload-message' : 'no-upload-message'; #> 1546 <div class="uploader-inline-content {{ messageClass }}"> 1547 <# if ( data.message ) { #> 1548 <h3 class="upload-message">{{ data.message }}</h3> 1549 <# } #> 1544 1550 <?php if ( ! _device_can_upload() ) : ?> 1545 <h3 ><?php _e('The web browser on your device cannot be used to upload files. You may be able to use the <a href="http://wordpress.org/extend/mobile/">native app for your device</a> instead.'); ?></h3>1551 <h3 class="upload-instructions"><?php _e('The web browser on your device cannot be used to upload files. You may be able to use the <a href="http://wordpress.org/extend/mobile/">native app for your device</a> instead.'); ?></h3> 1546 1552 <?php elseif ( is_multisite() && ! is_upload_space_available() ) : ?> 1547 <h3 ><?php _e( 'Upload Limit Exceeded' ); ?></h3>1553 <h3 class="upload-instructions"><?php _e( 'Upload Limit Exceeded' ); ?></h3> 1548 1554 <?php do_action( 'upload_ui_over_quota' ); ?> 1549 1555 1550 1556 <?php else : ?> 1551 1557 <div class="upload-ui"> 1552 <h3 class=" drop-instructions"><?php _e( 'Drop files anywhere to upload' ); ?></h3>1558 <h3 class="upload-instructions drop-instructions"><?php _e( 'Drop files anywhere to upload' ); ?></h3> 1553 1559 <a href="#" class="browser button button-hero"><?php _e( 'Select Files' ); ?></a> 1554 1560 </div> 1555 1561 … … 1744 1750 <div class="selection-view"></div> 1745 1751 </script> 1746 1752 1747 <script type="text/html" id="tmpl-media-selection-preview">1748 <div class="selected-img selected-count-{{ data.count }}">1749 <# if ( data.thumbnail ) { #>1750 <img src="{{ data.thumbnail }}" draggable="false" />1751 <# } #>1752 1753 <span class="count">{{ data.count }}</span>1754 </div>1755 <# if ( data.clearable ) { #>1756 <a class="clear-selection" href="#"><?php _e('Clear selection'); ?></a>1757 <# } #>1758 </script>1759 1760 1753 <script type="text/html" id="tmpl-attachment-display-settings"> 1761 1754 <h3><?php _e('Attachment Display Settings'); ?></h3> 1762 1755