bindings
6 months ago
commands
2 weeks ago
pro
2 weeks ago
_acf-compatibility.js
1 year ago
_acf-condition-types.js
8 months ago
_acf-condition.js
1 year ago
_acf-conditions.js
1 year ago
_acf-field-accordion.js
6 months ago
_acf-field-button-group.js
8 months ago
_acf-field-checkbox.js
1 month ago
_acf-field-color-picker.js
8 months ago
_acf-field-date-picker.js
1 month ago
_acf-field-date-time-picker.js
1 month ago
_acf-field-file.js
1 month ago
_acf-field-google-map.js
6 months ago
_acf-field-icon-picker.js
1 month ago
_acf-field-image.js
1 month ago
_acf-field-link.js
1 year ago
_acf-field-oembed.js
1 month ago
_acf-field-page-link.js
1 year ago
_acf-field-post-object.js
1 year ago
_acf-field-radio.js
1 month ago
_acf-field-range.js
1 year ago
_acf-field-relationship.js
1 month ago
_acf-field-select.js
1 month ago
_acf-field-tab.js
1 month ago
_acf-field-taxonomy.js
8 months ago
_acf-field-time-picker.js
1 month ago
_acf-field-true-false.js
1 month ago
_acf-field-url.js
1 year ago
_acf-field-user.js
1 year ago
_acf-field-wysiwyg.js
1 month ago
_acf-field.js
1 year ago
_acf-fields.js
1 year ago
_acf-helpers.js
1 year ago
_acf-hooks.js
1 year ago
_acf-internal-post-type.js
8 months ago
_acf-media.js
2 weeks ago
_acf-modal.js
1 year ago
_acf-model.js
1 year ago
_acf-notice.js
8 months ago
_acf-panel.js
1 year ago
_acf-popup.js
8 months ago
_acf-postbox.js
1 year ago
_acf-screen.js
10 months ago
_acf-select2.js
1 year ago
_acf-tinymce.js
6 months ago
_acf-tooltip.js
10 months ago
_acf-unload.js
1 year ago
_acf-validation.js
1 month ago
_acf.js
7 months ago
_browse-fields-modal.js
8 months ago
_field-group-compatibility.js
1 year ago
_field-group-conditions.js
1 year ago
_field-group-field.js
4 months ago
_field-group-fields.js
10 months ago
_field-group-locations.js
1 year ago
_field-group-settings.js
1 year ago
_field-group.js
10 months ago
acf-escaped-html-notice.js
1 year ago
acf-field-group.js
1 year ago
acf-input.js
1 year ago
acf-internal-post-type.js
1 year ago
acf.js
1 year ago
_acf-media.js
884 lines
| 1 | ( function ( $, undefined ) { |
| 2 | /** |
| 3 | * acf.newMediaPopup |
| 4 | * |
| 5 | * description |
| 6 | * |
| 7 | * @date 10/1/18 |
| 8 | * @since ACF 5.6.5 |
| 9 | * |
| 10 | * @param type $var Description. Default. |
| 11 | * @return type Description. |
| 12 | */ |
| 13 | |
| 14 | acf.newMediaPopup = function ( args ) { |
| 15 | // args |
| 16 | var popup = null; |
| 17 | var args = acf.parseArgs( args, { |
| 18 | mode: 'select', // 'select', 'edit' |
| 19 | title: '', // 'Upload Image' |
| 20 | button: '', // 'Select Image' |
| 21 | type: '', // 'image', '' |
| 22 | field: false, // field instance |
| 23 | allowedTypes: '', // '.jpg, .png, etc' |
| 24 | library: 'all', // 'all', 'uploadedTo' |
| 25 | multiple: false, // false, true, 'add' |
| 26 | attachment: 0, // the attachment to edit |
| 27 | autoOpen: true, // open the popup automatically |
| 28 | open: function () {}, // callback after close |
| 29 | select: function () {}, // callback after select |
| 30 | close: function () {}, // callback after close |
| 31 | } ); |
| 32 | |
| 33 | // initialize |
| 34 | if ( args.mode == 'edit' ) { |
| 35 | popup = new acf.models.EditMediaPopup( args ); |
| 36 | } else { |
| 37 | popup = new acf.models.SelectMediaPopup( args ); |
| 38 | } |
| 39 | |
| 40 | // open popup (allow frame customization before opening) |
| 41 | if ( args.autoOpen ) { |
| 42 | setTimeout( function () { |
| 43 | popup.open(); |
| 44 | }, 1 ); |
| 45 | } |
| 46 | |
| 47 | // action |
| 48 | acf.doAction( 'new_media_popup', popup ); |
| 49 | |
| 50 | // return |
| 51 | return popup; |
| 52 | }; |
| 53 | |
| 54 | /** |
| 55 | * getPostID |
| 56 | * |
| 57 | * description |
| 58 | * |
| 59 | * @date 10/1/18 |
| 60 | * @since ACF 5.6.5 |
| 61 | * |
| 62 | * @param type $var Description. Default. |
| 63 | * @return type Description. |
| 64 | */ |
| 65 | |
| 66 | var getPostID = function () { |
| 67 | var postID = acf.get( 'post_id' ); |
| 68 | return acf.isNumeric( postID ) ? postID : 0; |
| 69 | }; |
| 70 | |
| 71 | /** |
| 72 | * acf.getMimeTypes |
| 73 | * |
| 74 | * description |
| 75 | * |
| 76 | * @date 11/1/18 |
| 77 | * @since ACF 5.6.5 |
| 78 | * |
| 79 | * @param type $var Description. Default. |
| 80 | * @return type Description. |
| 81 | */ |
| 82 | |
| 83 | acf.getMimeTypes = function () { |
| 84 | return this.get( 'mimeTypes' ); |
| 85 | }; |
| 86 | |
| 87 | acf.getMimeType = function ( name ) { |
| 88 | // vars |
| 89 | var allTypes = acf.getMimeTypes(); |
| 90 | |
| 91 | // search |
| 92 | if ( allTypes[ name ] !== undefined ) { |
| 93 | return allTypes[ name ]; |
| 94 | } |
| 95 | |
| 96 | // some types contain a mixed key such as "jpg|jpeg|jpe" |
| 97 | for ( var key in allTypes ) { |
| 98 | if ( key.indexOf( name ) !== -1 ) { |
| 99 | return allTypes[ key ]; |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | // return |
| 104 | return false; |
| 105 | }; |
| 106 | |
| 107 | /** |
| 108 | * MediaPopup |
| 109 | * |
| 110 | * description |
| 111 | * |
| 112 | * @date 10/1/18 |
| 113 | * @since ACF 5.6.5 |
| 114 | * |
| 115 | * @param type $var Description. Default. |
| 116 | * @return type Description. |
| 117 | */ |
| 118 | |
| 119 | var MediaPopup = acf.Model.extend( { |
| 120 | id: 'MediaPopup', |
| 121 | data: {}, |
| 122 | defaults: {}, |
| 123 | frame: false, |
| 124 | |
| 125 | setup: function ( props ) { |
| 126 | $.extend( this.data, props ); |
| 127 | }, |
| 128 | |
| 129 | initialize: function () { |
| 130 | // vars |
| 131 | var options = this.getFrameOptions(); |
| 132 | |
| 133 | // add states |
| 134 | this.addFrameStates( options ); |
| 135 | |
| 136 | // create frame |
| 137 | var frame = wp.media( options ); |
| 138 | |
| 139 | // add args reference |
| 140 | frame.acf = this; |
| 141 | |
| 142 | // add events |
| 143 | this.addFrameEvents( frame, options ); |
| 144 | |
| 145 | // store frame |
| 146 | this.frame = frame; |
| 147 | }, |
| 148 | |
| 149 | open: function () { |
| 150 | this.frame.open(); |
| 151 | }, |
| 152 | |
| 153 | close: function () { |
| 154 | this.frame.close(); |
| 155 | }, |
| 156 | |
| 157 | remove: function () { |
| 158 | this.frame.detach(); |
| 159 | this.frame.remove(); |
| 160 | }, |
| 161 | |
| 162 | getFrameOptions: function () { |
| 163 | // vars |
| 164 | var options = { |
| 165 | title: this.get( 'title' ), |
| 166 | multiple: this.get( 'multiple' ), |
| 167 | library: {}, |
| 168 | states: [], |
| 169 | }; |
| 170 | |
| 171 | // type |
| 172 | if ( this.get( 'type' ) ) { |
| 173 | options.library.type = this.get( 'type' ); |
| 174 | } |
| 175 | |
| 176 | // type |
| 177 | if ( this.get( 'library' ) === 'uploadedTo' ) { |
| 178 | options.library.uploadedTo = getPostID(); |
| 179 | } |
| 180 | |
| 181 | // attachment |
| 182 | if ( this.get( 'attachment' ) ) { |
| 183 | options.library.post__in = [ this.get( 'attachment' ) ]; |
| 184 | } |
| 185 | |
| 186 | // button |
| 187 | if ( this.get( 'button' ) ) { |
| 188 | options.button = { |
| 189 | text: this.get( 'button' ), |
| 190 | }; |
| 191 | } |
| 192 | |
| 193 | // return |
| 194 | return options; |
| 195 | }, |
| 196 | |
| 197 | addFrameStates: function ( options ) { |
| 198 | // create query |
| 199 | var Query = wp.media.query( options.library ); |
| 200 | |
| 201 | // add _acfuploader |
| 202 | // this is super wack! |
| 203 | // if you add _acfuploader to the options.library args, new uploads will not be added to the library view. |
| 204 | // this has been traced back to the wp.media.model.Query initialize function (which can't be overridden) |
| 205 | // Adding any custom args will cause the Attachments to not observe the uploader queue |
| 206 | // To bypass this security issue, we add in the args AFTER the Query has been initialized |
| 207 | // options.library._acfuploader = settings.field; |
| 208 | if ( |
| 209 | this.get( 'field' ) && |
| 210 | acf.isset( Query, 'mirroring', 'args' ) |
| 211 | ) { |
| 212 | Query.mirroring.args._acfuploader = this.get( 'field' ); |
| 213 | } |
| 214 | |
| 215 | // add states |
| 216 | options.states.push( |
| 217 | // main state |
| 218 | new wp.media.controller.Library( { |
| 219 | library: Query, |
| 220 | multiple: this.get( 'multiple' ), |
| 221 | title: this.get( 'title' ), |
| 222 | priority: 20, |
| 223 | filterable: 'all', |
| 224 | editable: true, |
| 225 | allowLocalEdits: true, |
| 226 | } ) |
| 227 | ); |
| 228 | |
| 229 | // edit image functionality (added in WP 3.9) |
| 230 | if ( acf.isset( wp, 'media', 'controller', 'EditImage' ) ) { |
| 231 | options.states.push( new wp.media.controller.EditImage() ); |
| 232 | } |
| 233 | }, |
| 234 | |
| 235 | addFrameEvents: function ( frame, options ) { |
| 236 | // log all events |
| 237 | //frame.on('all', function( e ) { |
| 238 | // console.log( 'frame all: %o', e ); |
| 239 | //}); |
| 240 | |
| 241 | // add class |
| 242 | frame.on( |
| 243 | 'open', |
| 244 | function () { |
| 245 | this.$el |
| 246 | .closest( '.media-modal' ) |
| 247 | .addClass( |
| 248 | 'acf-media-modal -' + this.acf.get( 'mode' ) |
| 249 | ); |
| 250 | }, |
| 251 | frame |
| 252 | ); |
| 253 | |
| 254 | // edit image view |
| 255 | // source: media-views.js:2410 editImageContent() |
| 256 | frame.on( |
| 257 | 'content:render:edit-image', |
| 258 | function () { |
| 259 | var image = this.state().get( 'image' ); |
| 260 | var view = new wp.media.view.EditImage( { |
| 261 | model: image, |
| 262 | controller: this, |
| 263 | } ).render(); |
| 264 | this.content.set( view ); |
| 265 | |
| 266 | // after creating the wrapper view, load the actual editor via an ajax call |
| 267 | view.loadEditor(); |
| 268 | }, |
| 269 | frame |
| 270 | ); |
| 271 | |
| 272 | // update toolbar button |
| 273 | //frame.on( 'toolbar:create:select', function( toolbar ) { |
| 274 | // toolbar.view = new wp.media.view.Toolbar.Select({ |
| 275 | // text: frame.options._button, |
| 276 | // controller: this |
| 277 | // }); |
| 278 | //}, frame ); |
| 279 | |
| 280 | // on select |
| 281 | frame.on( 'select', function () { |
| 282 | // vars |
| 283 | var selection = frame.state().get( 'selection' ); |
| 284 | |
| 285 | // if selecting images |
| 286 | if ( selection ) { |
| 287 | // loop |
| 288 | selection.each( function ( attachment, i ) { |
| 289 | frame.acf |
| 290 | .get( 'select' ) |
| 291 | .apply( frame.acf, [ attachment, i ] ); |
| 292 | } ); |
| 293 | } |
| 294 | } ); |
| 295 | |
| 296 | // on close |
| 297 | frame.on( 'close', function () { |
| 298 | // callback and remove |
| 299 | setTimeout( function () { |
| 300 | frame.acf.get( 'close' ).apply( frame.acf ); |
| 301 | frame.acf.remove(); |
| 302 | }, 1 ); |
| 303 | } ); |
| 304 | }, |
| 305 | } ); |
| 306 | |
| 307 | /** |
| 308 | * acf.models.SelectMediaPopup |
| 309 | * |
| 310 | * description |
| 311 | * |
| 312 | * @date 10/1/18 |
| 313 | * @since ACF 5.6.5 |
| 314 | * |
| 315 | * @param type $var Description. Default. |
| 316 | * @return type Description. |
| 317 | */ |
| 318 | |
| 319 | acf.models.SelectMediaPopup = MediaPopup.extend( { |
| 320 | id: 'SelectMediaPopup', |
| 321 | setup: function ( props ) { |
| 322 | // default button |
| 323 | if ( ! props.button ) { |
| 324 | props.button = acf._x( 'Select', 'verb' ); |
| 325 | } |
| 326 | |
| 327 | // parent |
| 328 | MediaPopup.prototype.setup.apply( this, arguments ); |
| 329 | }, |
| 330 | |
| 331 | addFrameEvents: function ( frame, options ) { |
| 332 | // plupload |
| 333 | // adds _acfuploader param to validate uploads |
| 334 | if ( |
| 335 | acf.isset( _wpPluploadSettings, 'defaults', 'multipart_params' ) |
| 336 | ) { |
| 337 | // add _acfuploader so that Uploader will inherit |
| 338 | _wpPluploadSettings.defaults.multipart_params._acfuploader = this.get( |
| 339 | 'field' |
| 340 | ); |
| 341 | |
| 342 | // remove acf_field so future Uploaders won't inherit |
| 343 | frame.on( 'open', function () { |
| 344 | delete _wpPluploadSettings |
| 345 | .defaults.multipart_params._acfuploader; |
| 346 | } ); |
| 347 | } |
| 348 | |
| 349 | // browse |
| 350 | frame.on( 'content:activate:browse', function () { |
| 351 | // vars |
| 352 | var toolbar = false; |
| 353 | |
| 354 | // populate above vars making sure to allow for failure |
| 355 | // perhaps toolbar does not exist because the frame open is Upload Files |
| 356 | try { |
| 357 | toolbar = frame.content.get().toolbar; |
| 358 | } catch ( e ) { |
| 359 | console.log( e ); |
| 360 | return; |
| 361 | } |
| 362 | |
| 363 | // callback |
| 364 | frame.acf.customizeFilters.apply( frame.acf, [ toolbar ] ); |
| 365 | } ); |
| 366 | |
| 367 | // parent |
| 368 | MediaPopup.prototype.addFrameEvents.apply( this, arguments ); |
| 369 | }, |
| 370 | |
| 371 | customizeFilters: function ( toolbar ) { |
| 372 | // Get the AttachmentFilters view from the toolbar. |
| 373 | // WP < 7.0: toolbar.get('filters') returns the AttachmentFilters view directly. |
| 374 | // WP 7.0+: toolbar.get('filters') returns a wrapper View; the |
| 375 | // AttachmentFilters view is nested inside its subviews. |
| 376 | var filtersView = toolbar.get( 'filters' ); |
| 377 | var filters = filtersView; |
| 378 | |
| 379 | if ( filtersView && ! filtersView.filters ) { |
| 380 | // WP 7.0+: find the AttachmentFilters view in the container's subviews. |
| 381 | var subviews = filtersView.views ? filtersView.views.get() : []; |
| 382 | for ( var i = 0; i < subviews.length; i++ ) { |
| 383 | if ( subviews[ i ].filters ) { |
| 384 | filters = subviews[ i ]; |
| 385 | break; |
| 386 | } |
| 387 | } |
| 388 | } |
| 389 | |
| 390 | // Bail if the AttachmentFilters view couldn't be resolved (e.g. core |
| 391 | // moves the view again), so the modal degrades to the default filters |
| 392 | // instead of crashing. |
| 393 | if ( ! filters || ! filters.filters ) { |
| 394 | return; |
| 395 | } |
| 396 | |
| 397 | // image |
| 398 | if ( this.get( 'type' ) == 'image' ) { |
| 399 | // update all |
| 400 | filters.filters.all.text = acf.__( 'All images' ); |
| 401 | |
| 402 | // remove some filters |
| 403 | delete filters.filters.audio; |
| 404 | delete filters.filters.video; |
| 405 | delete filters.filters.image; |
| 406 | |
| 407 | // update all filters to show images |
| 408 | $.each( filters.filters, function ( i, filter ) { |
| 409 | filter.props.type = filter.props.type || 'image'; |
| 410 | } ); |
| 411 | } |
| 412 | |
| 413 | // specific types |
| 414 | if ( this.get( 'allowedTypes' ) ) { |
| 415 | // convert ".jpg, .png" into ["jpg", "png"] |
| 416 | var allowedTypes = this.get( 'allowedTypes' ) |
| 417 | .split( ' ' ) |
| 418 | .join( '' ) |
| 419 | .split( '.' ) |
| 420 | .join( '' ) |
| 421 | .split( ',' ); |
| 422 | |
| 423 | // loop |
| 424 | allowedTypes.map( function ( name ) { |
| 425 | // get type |
| 426 | var mimeType = acf.getMimeType( name ); |
| 427 | |
| 428 | // bail early if no type |
| 429 | if ( ! mimeType ) return; |
| 430 | |
| 431 | // create new filter |
| 432 | var newFilter = { |
| 433 | text: mimeType, |
| 434 | props: { |
| 435 | status: null, |
| 436 | type: mimeType, |
| 437 | uploadedTo: null, |
| 438 | orderby: 'date', |
| 439 | order: 'DESC', |
| 440 | }, |
| 441 | priority: 20, |
| 442 | }; |
| 443 | |
| 444 | // append |
| 445 | filters.filters[ mimeType ] = newFilter; |
| 446 | } ); |
| 447 | } |
| 448 | |
| 449 | // uploaded to post |
| 450 | if ( this.get( 'library' ) === 'uploadedTo' ) { |
| 451 | // vars |
| 452 | var uploadedTo = this.frame.options.library.uploadedTo; |
| 453 | |
| 454 | // remove some filters |
| 455 | delete filters.filters.unattached; |
| 456 | delete filters.filters.uploaded; |
| 457 | |
| 458 | // add uploadedTo to filters |
| 459 | $.each( filters.filters, function ( i, filter ) { |
| 460 | filter.text += |
| 461 | ' (' + acf.__( 'Uploaded to this post' ) + ')'; |
| 462 | filter.props.uploadedTo = uploadedTo; |
| 463 | } ); |
| 464 | } |
| 465 | |
| 466 | // add _acfuploader to filters |
| 467 | var field = this.get( 'field' ); |
| 468 | $.each( filters.filters, function ( k, filter ) { |
| 469 | filter.props._acfuploader = field; |
| 470 | } ); |
| 471 | |
| 472 | // add _acfuploader to search |
| 473 | var search = toolbar.get( 'search' ); |
| 474 | search.model.attributes._acfuploader = field; |
| 475 | |
| 476 | // render (custom function added to prototype) |
| 477 | if ( filters.renderFilters ) { |
| 478 | filters.renderFilters(); |
| 479 | } |
| 480 | }, |
| 481 | } ); |
| 482 | |
| 483 | /** |
| 484 | * acf.models.EditMediaPopup |
| 485 | * |
| 486 | * description |
| 487 | * |
| 488 | * @date 10/1/18 |
| 489 | * @since ACF 5.6.5 |
| 490 | * |
| 491 | * @param type $var Description. Default. |
| 492 | * @return type Description. |
| 493 | */ |
| 494 | |
| 495 | acf.models.EditMediaPopup = MediaPopup.extend( { |
| 496 | id: 'SelectMediaPopup', |
| 497 | setup: function ( props ) { |
| 498 | // default button |
| 499 | if ( ! props.button ) { |
| 500 | props.button = acf._x( 'Update', 'verb' ); |
| 501 | } |
| 502 | |
| 503 | // parent |
| 504 | MediaPopup.prototype.setup.apply( this, arguments ); |
| 505 | }, |
| 506 | |
| 507 | addFrameEvents: function ( frame, options ) { |
| 508 | // add class |
| 509 | frame.on( |
| 510 | 'open', |
| 511 | function () { |
| 512 | // add class |
| 513 | this.$el |
| 514 | .closest( '.media-modal' ) |
| 515 | .addClass( 'acf-expanded' ); |
| 516 | |
| 517 | // set to browse |
| 518 | if ( this.content.mode() != 'browse' ) { |
| 519 | this.content.mode( 'browse' ); |
| 520 | } |
| 521 | |
| 522 | // set selection |
| 523 | var state = this.state(); |
| 524 | var selection = state.get( 'selection' ); |
| 525 | var attachment = wp.media.attachment( |
| 526 | frame.acf.get( 'attachment' ) |
| 527 | ); |
| 528 | selection.add( attachment ); |
| 529 | }, |
| 530 | frame |
| 531 | ); |
| 532 | |
| 533 | // parent |
| 534 | MediaPopup.prototype.addFrameEvents.apply( this, arguments ); |
| 535 | }, |
| 536 | } ); |
| 537 | |
| 538 | /** |
| 539 | * customizePrototypes |
| 540 | * |
| 541 | * description |
| 542 | * |
| 543 | * @date 11/1/18 |
| 544 | * @since ACF 5.6.5 |
| 545 | * |
| 546 | * @param type $var Description. Default. |
| 547 | * @return type Description. |
| 548 | */ |
| 549 | |
| 550 | var customizePrototypes = new acf.Model( { |
| 551 | id: 'customizePrototypes', |
| 552 | wait: 'ready', |
| 553 | |
| 554 | initialize: function () { |
| 555 | // bail early if no media views |
| 556 | if ( ! acf.isset( window, 'wp', 'media', 'view' ) ) { |
| 557 | return; |
| 558 | } |
| 559 | |
| 560 | // fix bug where CPT without "editor" does not set post.id setting which then prevents uploadedTo from working |
| 561 | var postID = getPostID(); |
| 562 | if ( |
| 563 | postID && |
| 564 | acf.isset( wp, 'media', 'view', 'settings', 'post' ) |
| 565 | ) { |
| 566 | wp.media.view.settings.post.id = postID; |
| 567 | } |
| 568 | |
| 569 | // customize |
| 570 | this.customizeAttachmentsButton(); |
| 571 | this.customizeAttachmentsRouter(); |
| 572 | this.customizeAttachmentFilters(); |
| 573 | this.customizeAttachmentCompat(); |
| 574 | this.customizeAttachmentLibrary(); |
| 575 | }, |
| 576 | |
| 577 | customizeAttachmentsButton: function () { |
| 578 | // validate |
| 579 | if ( ! acf.isset( wp, 'media', 'view', 'Button' ) ) { |
| 580 | return; |
| 581 | } |
| 582 | |
| 583 | // Extend |
| 584 | var Button = wp.media.view.Button; |
| 585 | wp.media.view.Button = Button.extend( { |
| 586 | // Fix bug where "Select" button appears blank after editing an image. |
| 587 | // Do this by simplifying Button initialize function and avoid deleting this.options. |
| 588 | initialize: function () { |
| 589 | var options = _.defaults( this.options, this.defaults ); |
| 590 | this.model = new Backbone.Model( options ); |
| 591 | this.listenTo( this.model, 'change', this.render ); |
| 592 | }, |
| 593 | } ); |
| 594 | }, |
| 595 | |
| 596 | customizeAttachmentsRouter: function () { |
| 597 | // validate |
| 598 | if ( ! acf.isset( wp, 'media', 'view', 'Router' ) ) { |
| 599 | return; |
| 600 | } |
| 601 | |
| 602 | // vars |
| 603 | var Parent = wp.media.view.Router; |
| 604 | |
| 605 | // extend |
| 606 | wp.media.view.Router = Parent.extend( { |
| 607 | addExpand: function () { |
| 608 | // vars |
| 609 | var $a = $( |
| 610 | [ |
| 611 | '<a href="#" class="acf-expand-details">', |
| 612 | '<span class="is-closed"><i class="acf-icon -left -small"></i>' + |
| 613 | acf.__( 'Expand Details' ) + |
| 614 | '</span>', |
| 615 | '<span class="is-open"><i class="acf-icon -right -small"></i>' + |
| 616 | acf.__( 'Collapse Details' ) + |
| 617 | '</span>', |
| 618 | '</a>', |
| 619 | ].join( '' ) |
| 620 | ); |
| 621 | |
| 622 | // add events |
| 623 | $a.on( 'click', function ( e ) { |
| 624 | e.preventDefault(); |
| 625 | var $div = $( this ).closest( '.media-modal' ); |
| 626 | if ( $div.hasClass( 'acf-expanded' ) ) { |
| 627 | $div.removeClass( 'acf-expanded' ); |
| 628 | } else { |
| 629 | $div.addClass( 'acf-expanded' ); |
| 630 | } |
| 631 | } ); |
| 632 | |
| 633 | // append |
| 634 | this.$el.append( $a ); |
| 635 | }, |
| 636 | |
| 637 | initialize: function () { |
| 638 | // initialize |
| 639 | Parent.prototype.initialize.apply( this, arguments ); |
| 640 | |
| 641 | // add buttons |
| 642 | this.addExpand(); |
| 643 | |
| 644 | // return |
| 645 | return this; |
| 646 | }, |
| 647 | } ); |
| 648 | }, |
| 649 | |
| 650 | customizeAttachmentFilters: function () { |
| 651 | // validate |
| 652 | if ( |
| 653 | ! acf.isset( wp, 'media', 'view', 'AttachmentFilters', 'All' ) |
| 654 | ) { |
| 655 | return; |
| 656 | } |
| 657 | |
| 658 | // vars |
| 659 | var Parent = wp.media.view.AttachmentFilters.All; |
| 660 | |
| 661 | // renderFilters |
| 662 | // copied from media-views.js:6939 |
| 663 | Parent.prototype.renderFilters = function () { |
| 664 | // Build `<option>` elements. |
| 665 | this.$el.html( |
| 666 | _.chain( this.filters ) |
| 667 | .map( function ( filter, value ) { |
| 668 | return { |
| 669 | el: $( '<option></option>' ) |
| 670 | .val( value ) |
| 671 | .html( filter.text )[ 0 ], |
| 672 | priority: filter.priority || 50, |
| 673 | }; |
| 674 | }, this ) |
| 675 | .sortBy( 'priority' ) |
| 676 | .pluck( 'el' ) |
| 677 | .value() |
| 678 | ); |
| 679 | }; |
| 680 | }, |
| 681 | |
| 682 | customizeAttachmentCompat: function () { |
| 683 | // validate |
| 684 | if ( ! acf.isset( wp, 'media', 'view', 'AttachmentCompat' ) ) { |
| 685 | return; |
| 686 | } |
| 687 | |
| 688 | // vars |
| 689 | var AttachmentCompat = wp.media.view.AttachmentCompat; |
| 690 | var timeout = false; |
| 691 | |
| 692 | // extend |
| 693 | wp.media.view.AttachmentCompat = AttachmentCompat.extend( { |
| 694 | render: function () { |
| 695 | // WP bug |
| 696 | // When multiple media frames exist on the same page (WP content, WYSIWYG, image, file ), |
| 697 | // WP creates multiple instances of this AttachmentCompat view. |
| 698 | // Each instance will attempt to render when a new modal is created. |
| 699 | // Use a property to avoid this and only render once per instance. |
| 700 | if ( this.rendered ) { |
| 701 | return this; |
| 702 | } |
| 703 | |
| 704 | // render HTML |
| 705 | AttachmentCompat.prototype.render.apply( this, arguments ); |
| 706 | |
| 707 | // when uploading, render is called twice. |
| 708 | // ignore first render by checking for #acf-form-data element |
| 709 | if ( ! this.$( '#acf-form-data' ).length ) { |
| 710 | return this; |
| 711 | } |
| 712 | |
| 713 | // clear timeout |
| 714 | clearTimeout( timeout ); |
| 715 | |
| 716 | // setTimeout |
| 717 | timeout = setTimeout( |
| 718 | $.proxy( function () { |
| 719 | this.rendered = true; |
| 720 | acf.doAction( 'append', this.$el ); |
| 721 | }, this ), |
| 722 | 50 |
| 723 | ); |
| 724 | |
| 725 | // return |
| 726 | return this; |
| 727 | }, |
| 728 | |
| 729 | save: function ( event ) { |
| 730 | var data = {}; |
| 731 | |
| 732 | if ( event ) { |
| 733 | event.preventDefault(); |
| 734 | } |
| 735 | |
| 736 | //_.each( this.$el.serializeArray(), function( pair ) { |
| 737 | // data[ pair.name ] = pair.value; |
| 738 | //}); |
| 739 | |
| 740 | // Serialize data more thoroughly to allow checkbox inputs to save. |
| 741 | data = acf.serializeForAjax( this.$el ); |
| 742 | |
| 743 | this.controller.trigger( 'attachment:compat:waiting', [ |
| 744 | 'waiting', |
| 745 | ] ); |
| 746 | this.model |
| 747 | .saveCompat( data ) |
| 748 | .always( _.bind( this.postSave, this ) ); |
| 749 | }, |
| 750 | } ); |
| 751 | }, |
| 752 | |
| 753 | customizeAttachmentLibrary: function () { |
| 754 | // validate |
| 755 | if ( ! acf.isset( wp, 'media', 'view', 'Attachment', 'Library' ) ) { |
| 756 | return; |
| 757 | } |
| 758 | |
| 759 | // vars |
| 760 | var AttachmentLibrary = wp.media.view.Attachment.Library; |
| 761 | |
| 762 | // extend |
| 763 | wp.media.view.Attachment.Library = AttachmentLibrary.extend( { |
| 764 | render: function () { |
| 765 | // vars |
| 766 | var popup = acf.isget( this, 'controller', 'acf' ); |
| 767 | var attributes = acf.isget( this, 'model', 'attributes' ); |
| 768 | |
| 769 | // check vars exist to avoid errors |
| 770 | if ( popup && attributes ) { |
| 771 | // show errors |
| 772 | if ( attributes.acf_errors ) { |
| 773 | this.$el.addClass( 'acf-disabled' ); |
| 774 | } |
| 775 | |
| 776 | // disable selected |
| 777 | var selected = popup.get( 'selected' ); |
| 778 | if ( |
| 779 | selected && |
| 780 | selected.indexOf( attributes.id ) > -1 |
| 781 | ) { |
| 782 | this.$el.addClass( 'acf-selected' ); |
| 783 | } |
| 784 | } |
| 785 | |
| 786 | // render |
| 787 | return AttachmentLibrary.prototype.render.apply( |
| 788 | this, |
| 789 | arguments |
| 790 | ); |
| 791 | }, |
| 792 | |
| 793 | /* |
| 794 | * toggleSelection |
| 795 | * |
| 796 | * This function is called before an attachment is selected |
| 797 | * A good place to check for errors and prevent the 'select' function from being fired |
| 798 | * |
| 799 | * @type function |
| 800 | * @date 29/09/2016 |
| 801 | * @since ACF 5.4.0 |
| 802 | * |
| 803 | * @param options (object) |
| 804 | * @return n/a |
| 805 | */ |
| 806 | |
| 807 | toggleSelection: function ( options ) { |
| 808 | // vars |
| 809 | // source: wp-includes/js/media-views.js:2880 |
| 810 | var collection = this.collection, |
| 811 | selection = this.options.selection, |
| 812 | model = this.model, |
| 813 | single = selection.single(); |
| 814 | |
| 815 | // vars |
| 816 | var frame = this.controller; |
| 817 | var errors = acf.isget( |
| 818 | this, |
| 819 | 'model', |
| 820 | 'attributes', |
| 821 | 'acf_errors' |
| 822 | ); |
| 823 | var $sidebar = frame.$el.find( |
| 824 | '.media-frame-content .media-sidebar' |
| 825 | ); |
| 826 | |
| 827 | // remove previous error |
| 828 | $sidebar.children( '.acf-selection-error' ).remove(); |
| 829 | |
| 830 | // show attachment details |
| 831 | $sidebar.children().removeClass( 'acf-hidden' ); |
| 832 | |
| 833 | // add message |
| 834 | if ( frame && errors ) { |
| 835 | // vars |
| 836 | var filename = acf.isget( |
| 837 | this, |
| 838 | 'model', |
| 839 | 'attributes', |
| 840 | 'filename' |
| 841 | ); |
| 842 | |
| 843 | // hide attachment details |
| 844 | // Gallery field continues to show previously selected attachment... |
| 845 | $sidebar.children().addClass( 'acf-hidden' ); |
| 846 | |
| 847 | // append message |
| 848 | $sidebar.prepend( |
| 849 | [ |
| 850 | '<div class="acf-selection-error">', |
| 851 | '<span class="selection-error-label">' + |
| 852 | acf.__( 'Restricted' ) + |
| 853 | '</span>', |
| 854 | '<span class="selection-error-filename">' + |
| 855 | filename + |
| 856 | '</span>', |
| 857 | '<span class="selection-error-message">' + |
| 858 | errors + |
| 859 | '</span>', |
| 860 | '</div>', |
| 861 | ].join( '' ) |
| 862 | ); |
| 863 | |
| 864 | // reset selection (unselects all attachments) |
| 865 | selection.reset(); |
| 866 | |
| 867 | // set single (attachment displayed in sidebar) |
| 868 | selection.single( model ); |
| 869 | |
| 870 | // return and prevent 'select' form being fired |
| 871 | return; |
| 872 | } |
| 873 | |
| 874 | // return |
| 875 | return AttachmentLibrary.prototype.toggleSelection.apply( |
| 876 | this, |
| 877 | arguments |
| 878 | ); |
| 879 | }, |
| 880 | } ); |
| 881 | }, |
| 882 | } ); |
| 883 | } )( jQuery ); |
| 884 |