Ticket #21390: 21390.2.diff
File 21390.2.diff, 58.4 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, 367 368 // Sync the selection from the last state when 'multiple' matches. 369 syncLastSelection: true 274 370 }, 275 371 276 372 initialize: function() { … … 290 386 this.set( 'gutter', 8 ); 291 387 292 388 this.resetDisplays(); 293 294 media.controller.State.prototype.initialize.apply( this, arguments );295 389 }, 296 390 297 391 activate: function() { 298 392 var library = this.get('library'), 299 393 selection = this.get('selection'); 300 394 395 if ( this.get('syncLastSelection') ) { 396 this.getLastSelection(); 397 } 398 301 399 this._excludeStateLibrary(); 302 400 this.buildComposite(); 303 401 this.on( 'change:library change:exclude', this.buildComposite, this ); 304 402 this.on( 'change:excludeState', this._excludeState, this ); 305 403 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 ); 404 wp.Uploader.queue.on( 'add', this.uploading, this ); 310 405 311 406 selection.on( 'add remove reset', this.refreshSelection, this ); 312 407 313 this.refresh();314 408 this.on( 'insert', this._insertDisplaySettings, this ); 409 410 if ( this.get('contentUserSetting') ) { 411 this.frame.on( 'content:activate', this.saveContentMode, this ); 412 this.set( 'content', getUserSetting( 'libraryContent', this.get('content') ) ); 413 } 315 414 }, 316 415 317 416 deactivate: function() { 417 this.frame.off( 'content:activate', this.saveContentMode, this ); 418 318 419 // Unbind all event handlers that use this state as the context 319 420 // from the selection. 320 421 this.get('selection').off( null, null, this ); … … 332 433 this.resetDisplays(); 333 434 }, 334 435 335 refresh: function() {336 this.content();337 this.refreshSelection();338 },339 340 436 resetDisplays: function() { 341 437 this._displays = []; 342 438 this._defaultDisplaySettings = { … … 371 467 setUserSetting( 'urlbutton', display.link ); 372 468 }, 373 469 470 getLastSelection: function() { 471 var selection = this.get('selection'), 472 lastState = this.frame.lastState(), 473 lastSelection = lastState && lastState.get('selection'); 474 475 if ( ! lastSelection || lastSelection.multiple !== selection.multiple ) 476 return; 477 478 selection.reset( lastSelection.toArray() ).single( lastSelection.single() ); 479 }, 480 374 481 refreshSelection: function() { 375 482 var selection = this.get('selection'), 376 483 mode = this.frame.content.mode(); 377 484 378 this.frame.toolbar. view().refresh();485 this.frame.toolbar.get().refresh(); 379 486 this.trigger( 'refresh:selection', this, selection ); 380 487 381 488 if ( ! selection.length && 'browse' !== mode && 'upload' !== mode ) 382 this. content();489 this.frame.content.render(); 383 490 }, 384 491 385 selectUpload: function( attachment ) { 386 this.get('selection').add( attachment ); 492 uploading: function( attachment ) { 493 var content = this.frame.content; 494 495 // If the uploader was selected, navigate to the browser. 496 if ( 'upload' === content.mode() ) 497 this.frame.content.mode('browse'); 498 499 // If we're in a workflow that supports multiple attachments, 500 // automatically select any uploading attachments. 501 if ( this.get('multiple') ) 502 this.get('selection').add( attachment ); 387 503 }, 388 504 505 saveContentMode: function() { 506 // Only track the browse router on library states. 507 if ( 'browse' !== this.get('router') ) 508 return; 509 510 setUserSetting( 'libraryContent', this.frame.content.mode() ); 511 }, 512 389 513 buildComposite: function() { 390 514 var original = this.get('_library'), 391 515 exclude = this.get('exclude'), … … 448 572 } 449 573 }); 450 574 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 575 // wp.media.controller.Gallery 488 576 // --------------------------- 489 577 media.controller.Gallery = media.controller.Library.extend({ … … 496 584 sortable: true, 497 585 searchable: false, 498 586 toolbar: 'gallery-edit', 499 content: 'browse' 587 content: 'browse', 588 title: l10n.editGalleryTitle, 589 priority: 60 500 590 }, 501 591 502 592 initialize: function() { … … 519 609 // Watch for uploaded attachments. 520 610 this.get('library').observe( wp.Uploader.queue ); 521 611 522 this.frame. content.on( 'activate:browse', this.gallerySettings, this );612 this.frame.on( 'content:render:browse', this.gallerySettings, this ); 523 613 524 614 media.controller.Library.prototype.activate.apply( this, arguments ); 525 615 }, … … 528 618 // Stop watching for uploaded attachments. 529 619 this.get('library').unobserve( wp.Uploader.queue ); 530 620 531 this.frame.content.off( null, null, this ); 621 this.frame.off( 'content:render:browse', this.gallerySettings, this ); 622 532 623 media.controller.Library.prototype.deactivate.apply( this, arguments ); 533 624 }, 534 625 535 gallerySettings: function() { 536 var library = this.get('library'), 537 browser; 626 gallerySettings: function( browser ) { 627 var library = this.get('library'); 538 628 539 if ( ! library )629 if ( ! library || ! browser ) 540 630 return; 541 631 542 632 library.gallery = library.gallery || new Backbone.Model(); 543 633 544 browser = this.frame.content.view();545 546 634 browser.sidebar.set({ 547 635 gallery: new media.view.Settings.Gallery({ 548 636 controller: this, … … 570 658 filterable: 'uploaded', 571 659 multiple: false, 572 660 menu: 'main', 573 toolbar: 'featured-image' 661 toolbar: 'featured-image', 662 title: l10n.featuredImageTitle, 663 priority: 60 574 664 }, media.controller.Library.prototype.defaults ), 575 665 576 666 initialize: function() { … … 629 719 menu: 'main', 630 720 content: 'embed', 631 721 toolbar: 'main-embed', 632 type: 'link' 722 type: 'link', 723 724 title: l10n.fromUrlTitle, 725 priority: 120 633 726 }, 634 727 635 728 // The amount of time used when debouncing the scan. … … 637 730 638 731 initialize: function() { 639 732 this.debouncedScan = _.debounce( _.bind( this.scan, this ), this.sensitivity ); 640 this.on( 'change:url', this.debouncedScan, this ); 733 this.props = new Backbone.Model({ url: '' }); 734 this.props.on( 'change:url', this.debouncedScan, this ); 641 735 this.on( 'scan', this.scanImage, this ); 642 media.controller.State.prototype.initialize.apply( this, arguments );643 736 }, 644 737 645 738 scan: function() { … … 652 745 scanImage: function( attributes ) { 653 746 var frame = this.frame, 654 747 state = this, 655 url = this. get('url'),748 url = this.props.get('url'), 656 749 image = new Image(); 657 750 658 751 image.onload = function() { 659 if ( state !== frame.state() || url !== state. get('url') )752 if ( state !== frame.state() || url !== state.props.get('url') ) 660 753 return; 661 754 662 755 state.set({ … … 670 763 }, 671 764 672 765 reset: function() { 673 _.each( _.difference( _.keys( this.attributes ), _.keys( this.defaults ) ), function( key ) { 674 this.unset( key ); 675 }, this ); 766 this.props = new Backbone.Model({ url: '' }); 676 767 677 this.set( 'url', '' );678 679 768 if ( this.id === this.frame.state().id ) 680 this.frame.toolbar. view().refresh();769 this.frame.toolbar.get().refresh(); 681 770 } 682 771 }); 683 772 … … 1022 1111 // The constructor for the `Views` manager. 1023 1112 Views: media.Views, 1024 1113 1025 constructor: function( ) {1114 constructor: function( options ) { 1026 1115 this.views = new this.Views( this, this.views ); 1027 1116 this.on( 'ready', this.ready, this ); 1117 1118 if ( options && options.controller ) 1119 this.controller = options.controller; 1120 1028 1121 Backbone.View.apply( this, arguments ); 1029 1122 }, 1030 1123 … … 1097 1190 // Initialize regions. 1098 1191 _.each( this.regions, function( region ) { 1099 1192 this[ region ] = new media.controller.Region({ 1100 controller:this,1101 id: 1102 selector: 1193 view: this, 1194 id: region, 1195 selector: '.media-frame-' + region 1103 1196 }); 1104 1197 }, this ); 1105 1198 }, … … 1113 1206 // Ensure states have a reference to the frame. 1114 1207 this.states.on( 'add', function( model ) { 1115 1208 model.frame = this; 1209 model.trigger('ready'); 1116 1210 }, this ); 1117 1211 }, 1118 1212 … … 1131 1225 media.view.MediaFrame = media.view.Frame.extend({ 1132 1226 className: 'media-frame', 1133 1227 template: media.template('media-frame'), 1134 regions: ['menu',' content','toolbar'],1228 regions: ['menu','title','content','toolbar','router'], 1135 1229 1136 1230 initialize: function() { 1137 1231 media.view.Frame.prototype.initialize.apply( this, arguments ); … … 1173 1267 } 1174 1268 1175 1269 this.on( 'attach', _.bind( this.views.ready, this.views ), this ); 1270 1271 // Bind default title creation. 1272 this.on( 'title:create:default', this.createTitle, this ); 1273 this.title.mode('default'); 1176 1274 }, 1177 1275 1178 1276 render: function() { … … 1183 1281 return media.view.Frame.prototype.render.apply( this, arguments ); 1184 1282 }, 1185 1283 1284 createTitle: function( title ) { 1285 title.view = new media.View({ 1286 controller: this, 1287 tagName: 'h1' 1288 }); 1289 }, 1290 1291 createMenu: function( menu ) { 1292 menu.view = new media.view.Menu({ 1293 controller: this 1294 }); 1295 }, 1296 1297 createToolbar: function( toolbar ) { 1298 menu.view = new media.view.Toolbar({ 1299 controller: this 1300 }); 1301 }, 1302 1303 createRouter: function( router ) { 1304 router.view = new media.view.Router({ 1305 controller: this 1306 }); 1307 }, 1308 1186 1309 createIframeStates: function( options ) { 1187 1310 var settings = media.view.settings, 1188 1311 tabs = settings.tabs, … … 1208 1331 }, options ) ); 1209 1332 }, this ); 1210 1333 1211 this. content.on( 'activate:iframe', this.iframeContent, this );1212 this. menu.on( 'activate:main', this.iframeMenu, this );1334 this.on( 'content:create:iframe', this.iframeContent, this ); 1335 this.on( 'menu:render:main', this.iframeMenu, this ); 1213 1336 this.on( 'open', this.hijackThickbox, this ); 1214 1337 this.on( 'close', this.restoreThickbox, this ); 1215 1338 }, 1216 1339 1217 iframeContent: function( ) {1340 iframeContent: function( content ) { 1218 1341 this.$el.addClass('hide-toolbar'); 1219 this.content.view(new media.view.Iframe({1342 content.view = new media.view.Iframe({ 1220 1343 controller: this 1221 }) .render() );1344 }); 1222 1345 }, 1223 1346 1224 iframeMenu: function( ) {1347 iframeMenu: function( view ) { 1225 1348 var views = {}; 1226 1349 1350 if ( ! view ) 1351 return; 1352 1227 1353 _.each( media.view.settings.tabs, function( title, id ) { 1228 1354 views[ 'iframe:' + id ] = { 1229 1355 text: this.state( 'iframe:' + id ).get('title'), … … 1231 1357 }; 1232 1358 }, this ); 1233 1359 1234 this.menu.view().set( views );1360 view.set( views ); 1235 1361 }, 1236 1362 1237 1363 hijackThickbox: function() { … … 1305 1431 new media.controller.Library({ 1306 1432 selection: options.selection, 1307 1433 library: media.query( options.library ), 1308 multiple: this.options.multiple,1434 multiple: options.multiple, 1309 1435 menu: 'main', 1310 toolbar: 'select' 1311 }), 1312 1313 new media.controller.Upload({ 1314 menu: 'main' 1436 title: options.title, 1437 priority: 20 1315 1438 }) 1316 1439 ]); 1317 1440 }, 1318 1441 1319 1442 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 ); 1443 this.on( 'menu:create:main', this.createMenu, this ); 1444 this.on( 'router:create:browse', this.createRouter, this ); 1445 this.on( 'router:render:browse', this.browseRouter, this ); 1446 this.on( 'content:create:browse', this.browseContent, this ); 1447 this.on( 'content:render:upload', this.uploadContent, this ); 1448 this.on( 'toolbar:create:select', this.createSelectToolbar, this ); 1324 1449 1325 1450 this.on( 'refresh:selection', this.refreshSelectToolbar, this ); 1326 1451 }, 1327 1452 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 } 1453 // Routers 1454 browseRouter: function( view ) { 1455 view.set({ 1456 upload: { 1457 text: l10n.uploadFilesTitle, 1458 priority: 20 1459 }, 1460 browse: { 1461 text: l10n.mediaLibraryTitle, 1462 priority: 40 1342 1463 } 1343 }) );1464 }); 1344 1465 }, 1345 1466 1346 1467 // Content 1347 browseContent: function( ) {1468 browseContent: function( content ) { 1348 1469 var state = this.state(); 1349 1470 1350 1471 this.$el.removeClass('hide-toolbar'); 1351 1472 1352 1473 // Browse our library of attachments. 1353 this.content.view(new media.view.AttachmentsBrowser({1474 content.view = new media.view.AttachmentsBrowser({ 1354 1475 controller: this, 1355 1476 collection: state.get('library'), 1356 1477 selection: state.get('selection'), 1357 1478 model: state, 1358 1479 sortable: state.get('sortable'), 1359 1480 search: state.get('searchable'), 1360 uploads: state.get('uploads'),1361 1481 filters: state.get('filterable'), 1362 1482 display: state.get('displaySettings'), 1363 1483 1364 1484 AttachmentView: state.get('AttachmentView') 1365 }) );1485 }); 1366 1486 }, 1367 1487 1368 1488 uploadContent: function() { 1369 this.$el.addClass('hide-toolbar'); 1370 1371 this.content.view( new media.view.UploaderInline({ 1489 this.$el.removeClass('hide-toolbar'); 1490 this.content.set( new media.view.UploaderInline({ 1372 1491 controller: this 1373 1492 }) ); 1374 1493 }, 1375 1494 1376 1495 // Toolbars 1377 selectToolbar: function(options ) {1496 createSelectToolbar: function( toolbar, options ) { 1378 1497 options = _.defaults( options || {}, { 1379 1498 event: 'select', 1380 1499 silent: false, 1381 1500 state: false 1382 1501 }); 1383 1502 1384 t his.toolbar.view(new media.view.Toolbar({1503 toolbar.view = new media.view.Toolbar({ 1385 1504 controller: this, 1386 1505 silent: options.silent, 1387 1506 … … 1402 1521 } 1403 1522 } 1404 1523 } 1405 }) );1524 }); 1406 1525 }, 1407 1526 1408 1527 refreshSelectToolbar: function() { … … 1411 1530 if ( ! selection || 'select' !== this.toolbar.mode() ) 1412 1531 return; 1413 1532 1414 this.toolbar. view().get('select').model.set( 'disabled', ! selection.length );1533 this.toolbar.get().get('select').model.set( 'disabled', ! selection.length ); 1415 1534 } 1416 1535 }); 1417 1536 … … 1430 1549 }, 1431 1550 1432 1551 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 ), 1552 var options = this.options, 1553 selection = options.selection, 1554 library = { 1441 1555 editable: true, 1442 filterable: 'all',1443 1556 multiple: this.options.multiple, 1444 1557 menu: 'main', 1445 1558 … … 1448 1561 // Update user settings when users adjust the 1449 1562 // attachment display settings. 1450 1563 displayUserSettings: true 1451 } ),1564 }; 1452 1565 1453 new media.controller.Upload({ 1454 menu: 'main' 1455 }), 1566 // Add the default states. 1567 this.states.add([ 1568 // Main states. 1569 new media.controller.Library( _.defaults({ 1570 id: 'insert', 1571 title: l10n.insertMediaTitle, 1572 priority: 20, 1573 toolbar: 'main-insert', 1574 filterable: 'all', 1575 library: media.query( options.library ), 1576 selection: selection 1577 }, library ) ), 1456 1578 1579 new media.controller.Library( _.defaults({ 1580 id: 'gallery', 1581 title: l10n.createGalleryTitle, 1582 priority: 40, 1583 toolbar: 'main-gallery', 1584 filterable: 'uploaded', 1585 1586 library: media.query( _.defaults({ 1587 type: 'image' 1588 }, options.library ) ), 1589 1590 selection: new media.model.Selection( selection.models, { 1591 multiple: selection.multiple 1592 }) 1593 }, library ) ), 1594 1457 1595 // Embed states. 1458 1596 new media.controller.Embed(), 1459 1597 … … 1471 1609 multiple: true, 1472 1610 menu: 'gallery', 1473 1611 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' 1612 excludeState: 'gallery-edit', 1613 title: l10n.addToGalleryTitle, 1614 priority: 100 1481 1615 }) 1482 1616 ]); 1483 1617 … … 1492 1626 1493 1627 bindHandlers: function() { 1494 1628 media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments ); 1629 this.on( 'menu:create:gallery', this.createMenu, this ); 1630 this.on( 'toolbar:create:main-insert', this.createSelectionToolbar, this ); 1631 this.on( 'toolbar:create:main-gallery', this.createSelectionToolbar, this ); 1495 1632 1496 1633 var handlers = { 1497 1634 menu: { 1635 'main': 'mainMenu', 1498 1636 'gallery': 'galleryMenu' 1499 1637 }, 1500 1638 … … 1504 1642 }, 1505 1643 1506 1644 toolbar: { 1507 'main-attachments': 'mainAttachmentsToolbar', 1645 'main-insert': 'mainInsertToolbar', 1646 'main-gallery': 'mainGalleryToolbar', 1508 1647 'main-embed': 'mainEmbedToolbar', 1509 1648 'featured-image': 'featuredImageToolbar', 1510 1649 'gallery-edit': 'galleryEditToolbar', … … 1514 1653 1515 1654 _.each( handlers, function( regionHandlers, region ) { 1516 1655 _.each( regionHandlers, function( callback, handler ) { 1517 this [ region ].on( 'activate:' + handler, this[ callback ], this );1656 this.on( region + ':render:' + handler, this[ callback ], this ); 1518 1657 }, this ); 1519 1658 }, this ); 1520 1659 }, 1521 1660 1522 1661 // Menus 1523 mainMenu: function() { 1524 media.view.MediaFrame.Select.prototype.mainMenu.call( this, { silent: true }); 1525 1526 this.menu.view().set({ 1662 mainMenu: function( view ) { 1663 view.set({ 1527 1664 'library-separator': new media.View({ 1528 1665 className: 'separator', 1529 priority: 60 1530 }), 1531 'embed': { 1532 text: l10n.fromUrlTitle, 1533 priority: 80 1534 } 1666 priority: 100 1667 }) 1535 1668 }); 1536 1537 if ( media.view.settings.post.featuredImageId ) {1538 this.menu.view().set( 'featured-image', {1539 text: l10n.featuredImageTitle,1540 priority: 1001541 });1542 }1543 1669 }, 1544 1670 1545 galleryMenu: function( ) {1671 galleryMenu: function( view ) { 1546 1672 var lastState = this.lastState(), 1547 1673 previous = lastState && lastState.id, 1548 1674 frame = this; 1549 1675 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 1676 view.set({ 1677 cancel: { 1678 text: l10n.cancelGalleryTitle, 1679 priority: 20, 1680 click: function() { 1681 if ( previous ) 1682 frame.setState( previous ); 1683 else 1684 frame.close(); 1578 1685 } 1579 } 1580 }) ); 1686 }, 1687 separateCancel: new media.View({ 1688 className: 'separator', 1689 priority: 40 1690 }) 1691 }); 1581 1692 }, 1582 1693 1583 1694 // Content … … 1587 1698 model: this.state() 1588 1699 }).render(); 1589 1700 1590 this.content. view( view );1701 this.content.set( view ); 1591 1702 view.url.focus(); 1592 1703 }, 1593 1704 … … 1617 1728 }); 1618 1729 1619 1730 // Browse our library of attachments. 1620 this.content. view( view );1731 this.content.set( view ); 1621 1732 }, 1622 1733 1623 // Sidebars 1624 onSidebarGallerySettings: function( options ) { 1625 var library = this.state().get('library'); 1734 // Toolbars 1735 createSelectionToolbar: function( toolbar ) { 1736 toolbar.view = new media.view.Toolbar.Selection({ 1737 controller: this, 1738 editable: this.state().get('editable') 1739 }); 1740 }, 1626 1741 1627 if ( ! library )1628 return;1742 mainInsertToolbar: function( view ) { 1743 var controller = this; 1629 1744 1630 library.gallery = library.gallery || new Backbone.Model(); 1745 view.button = 'insert'; 1746 view.set( 'insert', { 1747 style: 'primary', 1748 priority: 80, 1749 text: l10n.insertIntoPost, 1631 1750 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 ); 1751 click: function() { 1752 var state = controller.state(), 1753 selection = state.get('selection'); 1754 1755 controller.close(); 1756 state.trigger( 'insert', selection ).reset(); 1757 } 1758 }); 1639 1759 }, 1640 1760 1641 // Toolbars 1642 mainAttachmentsToolbar: function() { 1643 this.toolbar.view( new media.view.Toolbar.Insert({ 1644 controller: this, 1645 editable: this.state().get('editable') 1646 }) ); 1761 mainGalleryToolbar: function( view ) { 1762 var controller = this; 1763 1764 view.button = 'gallery'; 1765 view.set( 'gallery', { 1766 style: 'primary', 1767 text: l10n.createNewGallery, 1768 priority: 60, 1769 1770 click: function() { 1771 var selection = controller.state().get('selection'), 1772 edit = controller.state('gallery-edit'), 1773 models = selection.where({ type: 'image' }); 1774 1775 edit.set( 'library', new media.model.Selection( models, { 1776 props: selection.props.toJSON(), 1777 multiple: true 1778 }) ); 1779 1780 this.controller.setState('gallery-edit'); 1781 } 1782 }); 1647 1783 }, 1648 1784 1649 1785 featuredImageToolbar: function() { 1650 this.toolbar. view( new media.view.Toolbar.Select({1786 this.toolbar.set( new media.view.Toolbar.Select({ 1651 1787 controller: this, 1652 1788 text: l10n.setFeaturedImage, 1653 1789 state: this.options.state || 'upload' … … 1655 1791 }, 1656 1792 1657 1793 mainEmbedToolbar: function() { 1658 this.toolbar. view( new media.view.Toolbar.Embed({1794 this.toolbar.set( new media.view.Toolbar.Embed({ 1659 1795 controller: this 1660 1796 }) ); 1661 1797 … … 1664 1800 1665 1801 galleryEditToolbar: function() { 1666 1802 var editing = this.state().get('editing'); 1667 this.toolbar. view( new media.view.Toolbar({1803 this.toolbar.set( new media.view.Toolbar({ 1668 1804 controller: this, 1669 1805 items: { 1670 1806 insert: { … … 1689 1825 }, 1690 1826 1691 1827 galleryAddToolbar: function() { 1692 this.toolbar. view( new media.view.Toolbar({1828 this.toolbar.set( new media.view.Toolbar({ 1693 1829 controller: this, 1694 1830 items: { 1695 1831 insert: { … … 1704 1840 1705 1841 edit.get('library').add( state.get('selection').models ); 1706 1842 state.trigger('reset'); 1707 controller.s tate('gallery-edit');1843 controller.setState('gallery-edit'); 1708 1844 } 1709 1845 } 1710 1846 } … … 1729 1865 }, 1730 1866 1731 1867 initialize: function() { 1732 this.controller = this.options.controller;1733 1734 1868 _.defaults( this.options, { 1735 1869 container: document.body, 1736 1870 title: '', … … 1838 1972 initialize: function() { 1839 1973 var uploader; 1840 1974 1841 this.controller = this.options.controller;1842 1843 1975 this.$browser = $('<a href="#" class="browser" />').hide().appendTo('body'); 1844 1976 1845 1977 uploader = this.options.uploader = _.defaults( this.options.uploader || {}, { … … 1906 2038 template: media.template('uploader-inline'), 1907 2039 1908 2040 initialize: function() { 1909 this.controller = this.options.controller; 2041 _.defaults( this.options, { 2042 message: '', 2043 status: true 2044 }); 1910 2045 1911 2046 if ( ! this.options.$browser && this.controller.uploader ) 1912 2047 this.options.$browser = this.controller.uploader.$browser; … … 1914 2049 if ( _.isUndefined( this.options.postId ) ) 1915 2050 this.options.postId = media.view.settings.post.id; 1916 2051 1917 this.views.set( '.upload-inline-status', new media.view.UploaderStatus({ 1918 controller: this.controller 1919 }) ); 2052 if ( this.options.status ) { 2053 this.views.set( '.upload-inline-status', new media.view.UploaderStatus({ 2054 controller: this.controller 2055 }) ); 2056 } 1920 2057 }, 1921 2058 1922 2059 ready: function() { … … 1951 2088 }, 1952 2089 1953 2090 initialize: function() { 1954 this.controller = this.options.controller;1955 1956 2091 this.queue = wp.Uploader.queue; 1957 2092 this.queue.on( 'add remove reset', this.visibility, this ); 1958 2093 this.queue.on( 'add remove reset change:percent', this.progress, this ); … … 2060 2195 className: 'media-toolbar', 2061 2196 2062 2197 initialize: function() { 2063 this.controller = this.options.controller;2064 2065 2198 this._views = {}; 2066 2199 this.$primary = $('<div class="media-toolbar-primary" />').prependTo( this.$el ); 2067 2200 this.$secondary = $('<div class="media-toolbar-secondary" />').prependTo( this.$el ); … … 2199 2332 // --------------------------- 2200 2333 media.view.Toolbar.Embed = media.view.Toolbar.Select.extend({ 2201 2334 initialize: function() { 2202 var controller = this.options.controller;2203 2204 2335 _.defaults( this.options, { 2205 2336 text: l10n.insertIntoPost 2206 2337 }); 2207 2338 2208 2339 media.view.Toolbar.Select.prototype.initialize.apply( this, arguments ); 2209 controller.on( 'change:url', this.refresh, this );2340 this.controller.state().props.on( 'change:url', this.refresh, this ); 2210 2341 }, 2211 2342 2212 2343 refresh: function() { 2213 var url = this.controller.state(). get('url');2344 var url = this.controller.state().props.get('url'); 2214 2345 this.get('select').model.set( 'disabled', ! url || /^https?:\/\/$/.test(url) ); 2215 2346 } 2216 2347 }); 2217 2348 2218 // wp.media.view.Toolbar.Insert 2219 // ---------------------------- 2220 media.view.Toolbar.Insert = media.view.Toolbar.extend({ 2349 // wp.media.view.Toolbar.Selection 2350 // ------------------------------- 2351 media.view.Toolbar.Selection = media.view.Toolbar.extend({ 2352 button: 'insert', 2353 2221 2354 initialize: function() { 2222 var controller = this.options.controller, 2223 selection = controller.state().get('selection'), 2224 selectionToLibrary; 2355 var controller = this.controller; 2225 2356 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 2357 this.options.items = _.defaults( this.options.items || {}, { 2243 2358 selection: new media.view.Selection({ 2244 2359 controller: controller, 2245 collection: selection,2360 collection: controller.state().get('selection'), 2246 2361 priority: -40, 2247 2362 2248 2363 // If the selection is editable, pass the callback to … … 2250 2365 editable: this.options.editable && function() { 2251 2366 this.controller.content.mode('edit-selection'); 2252 2367 } 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 } 2368 }).render() 2273 2369 }); 2274 2370 2275 2371 media.view.Toolbar.prototype.initialize.apply( this, arguments ); … … 2277 2373 2278 2374 refresh: function() { 2279 2375 var selection = this.controller.state().get('selection'), 2280 count = selection.length;2376 button = this.get( this.button ); 2281 2377 2282 this.get('insert').model.set( 'disabled', ! selection.length ); 2378 if ( ! button ) 2379 return; 2283 2380 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 }) ); 2381 button.model.set( 'disabled', ! selection.length ); 2288 2382 } 2289 2383 }); 2290 2384 … … 2388 2482 tagName: 'div', 2389 2483 2390 2484 initialize: function() { 2391 this.controller = this.options.controller; 2392 this._views = {}; 2485 this._views = {}; 2393 2486 2394 2487 this.set( _.extend( {}, this._views, this.options.views ), { silent: true }); 2395 2488 delete this.options.views; … … 2457 2550 } 2458 2551 }); 2459 2552 2553 /** 2554 * wp.media.view.MenuItem 2555 */ 2556 media.view.MenuItem = media.View.extend({ 2557 tagName: 'a', 2558 className: 'media-menu-item', 2460 2559 2560 attributes: { 2561 href: '#' 2562 }, 2563 2564 events: { 2565 'click': '_click' 2566 }, 2567 2568 _click: function( event ) { 2569 var clickOverride = this.options.click; 2570 2571 event.preventDefault(); 2572 2573 if ( clickOverride ) 2574 clickOverride.call( this ); 2575 else 2576 this.click(); 2577 }, 2578 2579 click: function() { 2580 var state = this.options.state; 2581 if ( state ) 2582 this.controller.setState( state ); 2583 }, 2584 2585 render: function() { 2586 var options = this.options; 2587 2588 if ( options.text ) 2589 this.$el.text( options.text ); 2590 else if ( options.html ) 2591 this.$el.html( options.html ); 2592 2593 return this; 2594 } 2595 }); 2596 2461 2597 /** 2462 2598 * wp.media.view.Menu 2463 2599 */ 2464 2600 media.view.Menu = media.view.PriorityList.extend({ 2465 tagName: ' ul',2601 tagName: 'div', 2466 2602 className: 'media-menu', 2603 property: 'state', 2604 ItemView: media.view.MenuItem, 2605 region: 'menu', 2467 2606 2468 toView: function( options, state) {2607 toView: function( options, id ) { 2469 2608 options = options || {}; 2470 options .state = options.state || state;2471 return new media.view.MenuItem( options ).render();2609 options[ this.property ] = options[ this.property ] || id; 2610 return new this.ItemView( options ).render(); 2472 2611 }, 2473 2612 2474 select: function( state ) { 2475 var view = this.get( state ); 2613 ready: function() { 2614 media.view.PriorityList.prototype.ready.apply( this, arguments ); 2615 this.visibility(); 2616 }, 2476 2617 2618 set: function() { 2619 media.view.PriorityList.prototype.set.apply( this, arguments ); 2620 this.visibility(); 2621 }, 2622 2623 unset: function() { 2624 media.view.PriorityList.prototype.unset.apply( this, arguments ); 2625 this.visibility(); 2626 }, 2627 2628 visibility: function() { 2629 var region = this.region, 2630 view = this.controller[ region ].get(), 2631 views = this.views.get(), 2632 hide = ! views || views.length < 2; 2633 2634 if ( this === view ) 2635 this.controller.$el.toggleClass( 'hide-' + region, hide ); 2636 }, 2637 2638 select: function( id ) { 2639 var view = this.get( id ); 2640 2477 2641 if ( ! view ) 2478 2642 return; 2479 2643 … … 2486 2650 } 2487 2651 }); 2488 2652 2489 media.view.MenuItem = media.View.extend({ 2490 tagName: 'li', 2491 className: 'media-menu-item', 2653 /** 2654 * wp.media.view.RouterItem 2655 */ 2656 media.view.RouterItem = media.view.MenuItem.extend({ 2657 click: function() { 2658 var contentMode = this.options.contentMode; 2659 if ( contentMode ) 2660 this.controller.content.mode( contentMode ); 2661 } 2662 }); 2492 2663 2493 events: { 2494 'click': 'click' 2495 }, 2664 /** 2665 * wp.media.view.Router 2666 */ 2667 media.view.Router = media.view.Menu.extend({ 2668 tagName: 'div', 2669 className: 'media-router', 2670 property: 'contentMode', 2671 ItemView: media.view.RouterItem, 2672 region: 'router', 2496 2673 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 ); 2674 initialize: function() { 2675 this.controller.on( 'content:render', this.update, this ); 2676 media.view.Menu.prototype.initialize.apply( this, arguments ); 2504 2677 }, 2505 2678 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; 2679 update: function() { 2680 var mode = this.controller.content.mode(); 2681 if ( mode ) 2682 this.select( mode ); 2515 2683 } 2516 2684 }); 2517 2685 2686 2518 2687 /** 2519 2688 * wp.media.view.Sidebar 2520 2689 */ … … 2546 2715 initialize: function() { 2547 2716 var selection = this.options.selection; 2548 2717 2549 this.controller = this.options.controller;2550 2551 2718 this.model.on( 'change:sizes change:uploading change:caption change:title', this.render, this ); 2552 2719 this.model.on( 'change:percent', this.progress, this ); 2553 2720 … … 2838 3005 }, 2839 3006 2840 3007 initialize: function() { 2841 this.controller = this.options.controller;2842 3008 this.el.id = _.uniqueId('__attachments-view-'); 2843 3009 2844 3010 _.defaults( this.options, { … … 3200 3366 className: 'attachments-browser', 3201 3367 3202 3368 initialize: function() { 3203 this.controller = this.options.controller;3204 3205 3369 _.defaults( this.options, { 3206 3370 filters: false, 3207 3371 search: true, 3208 uploads: false,3209 3372 display: false, 3210 3373 3211 3374 AttachmentView: media.view.Attachment.Library … … 3290 3453 this.removeContent(); 3291 3454 3292 3455 this.uploader = new media.view.UploaderInline({ 3293 controller: this.controller 3456 controller: this.controller, 3457 status: false, 3458 message: l10n.noItemsFound 3294 3459 }); 3295 3460 3296 3461 this.views.add( this.uploader ); … … 3322 3487 3323 3488 this.views.add( sidebar ); 3324 3489 3325 if ( options.uploads &&this.controller.uploader ) {3490 if ( this.controller.uploader ) { 3326 3491 sidebar.set( 'uploads', new media.view.UploaderStatus({ 3327 3492 controller: this.controller, 3328 3493 priority: 40 … … 3373 3538 }); 3374 3539 3375 3540 /** 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 3541 * wp.media.view.Selection 3428 3542 */ 3429 3543 media.view.Selection = media.View.extend({ … … 3442 3556 clearable: true 3443 3557 }); 3444 3558 3445 this.controller = this.options.controller;3446 3559 this.attachments = new media.view.Attachments({ 3447 3560 controller: this.controller, 3448 3561 collection: this.collection, … … 3768 3881 media.view.Iframe = media.View.extend({ 3769 3882 className: 'media-iframe', 3770 3883 3771 initialize: function() {3772 this.controller = this.options.controller;3773 },3774 3775 3884 render: function() { 3885 this.views.detach(); 3776 3886 this.$el.html( '<iframe src="' + this.controller.state().get('src') + '" />' ); 3887 this.views.render(); 3777 3888 return this; 3778 3889 } 3779 3890 }); … … 3785 3896 className: 'media-embed', 3786 3897 3787 3898 initialize: function() { 3788 this.controller = this.options.controller;3789 3790 3899 this.url = new media.view.EmbedUrl({ 3791 3900 controller: this.controller, 3792 model: this.model 3901 model: this.model.props 3793 3902 }).render(); 3794 3903 3795 3904 this._settings = new media.View(); … … 3826 3935 3827 3936 this.settings( new constructor({ 3828 3937 controller: this.controller, 3829 model: this.model ,3938 model: this.model.props, 3830 3939 priority: 40 3831 3940 }) ); 3832 3941 } … … 3846 3955 }, 3847 3956 3848 3957 initialize: function() { 3849 this.label = this.make( 'span', null, this.options.label || l10n.url );3850 3958 this.input = this.make( 'input', { 3851 3959 type: 'text', 3852 3960 value: this.model.get('url') || '' 3853 3961 }); 3854 3962 3855 this.$label = $( this.label );3856 3963 this.$input = $( this.input ); 3857 this.$el.append( [ this.label, this.input ]);3964 this.$el.append( this.input ); 3858 3965 3859 3966 this.model.on( 'change:url', this.render, this ); 3860 3967 }, -
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