| @@ -18,8 +18,14 @@ | ||
| 18 | 18 | var $document; |
| 19 | 19 | var $id = function( selector ) { |
| 20 | 20 | return $( document.getElementById( selector ) ); |
| 21 | 21 | }; |
| 22 | + var getRowId = function( id, newIterator ) { | |
| 23 | + id = id.split('-'); | |
| 24 | + id.splice(id.length - 1, 1); | |
| 25 | + id.push( newIterator ); | |
| 26 | + return id.join('-'); | |
| 27 | + }; | |
| 22 | 28 | cmb.$id = $id; |
| 23 | 29 | var defaults = { |
| 24 | 30 | idNumber : false, |
| 25 | 31 | repeatEls : 'input:not([type="button"]),select,textarea,.cmb2-media-status', |
| @@ -191,11 +197,21 @@ | ||
| 191 | 197 | |
| 192 | 198 | // Loop repeatable group table rows |
| 193 | 199 | $table.find( '.cmb-repeatable-grouping' ).each( function( rowindex ) { |
| 194 | 200 | var $row = $( this ); |
| 201 | + var prevIterator = parseInt( $row.data( 'iterator' ), 10 ); | |
| 202 | + if ( prevIterator === rowindex ) { | |
| 203 | + return; | |
| 204 | + } | |
| 195 | 205 | |
| 196 | 206 | // Reset rows iterator |
| 197 | - $row.attr( 'data-iterator', rowindex ).data( 'iterator', rowindex ); | |
| 207 | + $row | |
| 208 | + .attr( 'data-iterator', rowindex ) | |
| 209 | + .data( 'iterator', rowindex ) | |
| 210 | + .attr('id', getRowId( $row.attr('id'), rowindex ) ) | |
| 211 | + .find( cmb.repeatEls ).each( function() { | |
| 212 | + cmb.updateNameAttr( $( this ), prevIterator, rowindex ); | |
| 213 | + }); | |
| 198 | 214 | |
| 199 | 215 | cmb.resetGroupTitles( $row, rowindex, groupTitle ); |
| 200 | 216 | }); |
| 201 | 217 | }; |
| @@ -220,19 +236,11 @@ | ||
| 220 | 236 | evt.preventDefault(); |
| 221 | 237 | var $this = $( this ); |
| 222 | 238 | var $multicheck = $this.closest( '.cmb-td' ).find( 'input[type=checkbox]:not([disabled])' ); |
| 223 | 239 | |
| 224 | - // If the button has already been clicked once... | |
| 225 | - if ( $this.data( 'checked' ) ) { | |
| 226 | - // clear the checkboxes and remove the flag | |
| 227 | - $multicheck.prop( 'checked', false ); | |
| 228 | - $this.data( 'checked', false ); | |
| 229 | - } | |
| 230 | - // Otherwise mark the checkboxes and add a flag | |
| 231 | - else { | |
| 232 | - $multicheck.prop( 'checked', true ); | |
| 233 | - $this.data( 'checked', true ); | |
| 234 | - } | |
| 240 | + var $toggled = ! $this.data( 'checked' ); | |
| 241 | + $multicheck.prop( 'checked', $toggled ).trigger( 'change' ); | |
| 242 | + $this.data( 'checked', $toggled ); | |
| 235 | 243 | }; |
| 236 | 244 | |
| 237 | 245 | cmb.handleMedia = function( evt ) { |
| 238 | 246 | evt.preventDefault(); |
| @@ -241,9 +249,9 @@ | ||
| 241 | 249 | cmb.attach_id = ! $el.hasClass( 'cmb2-upload-list' ) ? $el.closest( '.cmb-td' ).find( '.cmb2-upload-file-id' ).val() : false; |
| 242 | 250 | // Clean up default 0 value |
| 243 | 251 | cmb.attach_id = '0' !== cmb.attach_id ? cmb.attach_id : false; |
| 244 | 252 | |
| 245 | - cmb._handleMedia( $el.prev('input.cmb2-upload-file').attr('id'), $el.hasClass( 'cmb2-upload-list' ) ); | |
| 253 | + cmb.handleFieldMedia( $el.prev('input.cmb2-upload-file'), $el.hasClass( 'cmb2-upload-list' ) ); | |
| 246 | 254 | }; |
| 247 | 255 | |
| 248 | 256 | cmb.handleFileClick = function( evt ) { |
| 249 | 257 | if ( $( evt.target ).is( 'a' ) ) { |
| @@ -257,36 +265,52 @@ | ||
| 257 | 265 | var isList = $td.find( '.cmb2-upload-button' ).hasClass( 'cmb2-upload-list' ); |
| 258 | 266 | cmb.attach_id = isList ? $el.find( 'input[type="hidden"]' ).data( 'id' ) : $td.find( '.cmb2-upload-file-id' ).val(); |
| 259 | 267 | |
| 260 | 268 | if ( cmb.attach_id ) { |
| 261 | - cmb._handleMedia( $td.find( 'input.cmb2-upload-file' ).attr( 'id' ), isList, cmb.attach_id ); | |
| 269 | + cmb.handleFieldMedia( $td.find( 'input.cmb2-upload-file' ), isList ); | |
| 262 | 270 | } |
| 263 | 271 | }; |
| 264 | 272 | |
| 273 | + // Leaving this in for back-compat... | |
| 265 | 274 | cmb._handleMedia = function( id, isList ) { |
| 275 | + return cmb.handleFieldMedia( $id( id ), isList ); | |
| 276 | + }; | |
| 277 | + | |
| 278 | + cmb.handleFieldMedia = function( $field, isList ) { | |
| 266 | 279 | if ( ! wp ) { |
| 267 | 280 | return; |
| 268 | 281 | } |
| 269 | 282 | |
| 283 | + var id = $field.attr('id'); | |
| 284 | + var fieldData = $field.data(); | |
| 270 | 285 | var media, handlers; |
| 271 | 286 | |
| 287 | + // Get/set unique id since actual id cold _not_ be unique due to bad replacements, etc... | |
| 288 | + var uid = fieldData.mediaid; | |
| 289 | + if ( ! uid ) { | |
| 290 | + uid = _.uniqueId(); | |
| 291 | + $field.attr('data-mediaid', uid).data('mediaid', uid); | |
| 292 | + fieldData.mediaid = uid; | |
| 293 | + } | |
| 294 | + | |
| 272 | 295 | handlers = cmb.mediaHandlers; |
| 273 | 296 | media = cmb.media; |
| 297 | + media.mediaid = uid; | |
| 274 | 298 | media.field = id; |
| 275 | - media.$field = $id( media.field ); | |
| 276 | - media.fieldData = media.$field.data(); | |
| 299 | + media.$field = $field; | |
| 300 | + media.fieldData = fieldData; | |
| 277 | 301 | media.previewSize = media.fieldData.previewsize; |
| 278 | 302 | media.sizeName = media.fieldData.sizename; |
| 279 | - media.fieldName = media.$field.attr('name'); | |
| 303 | + media.fieldName = $field.attr('name'); | |
| 280 | 304 | media.isList = isList; |
| 281 | 305 | |
| 282 | 306 | // If this field's media frame already exists, reopen it. |
| 283 | - if ( id in media.frames ) { | |
| 284 | - return media.frames[ id ].open(); | |
| 307 | + if ( uid in media.frames ) { | |
| 308 | + return media.frames[ uid ].open(); | |
| 285 | 309 | } |
| 286 | 310 | |
| 287 | 311 | // Create the media frame. |
| 288 | - media.frames[ id ] = wp.media( { | |
| 312 | + media.frames[ uid ] = wp.media( { | |
| 289 | 313 | title: cmb.metabox().find('label[for="' + id + '"]').text(), |
| 290 | 314 | library : media.fieldData.queryargs || {}, |
| 291 | 315 | button: { |
| 292 | 316 | text: l10n.strings[ isList ? 'upload_files' : 'upload_file' ] |
| @@ -294,9 +318,9 @@ | ||
| 294 | 318 | multiple: isList ? 'add' : false |
| 295 | 319 | } ); |
| 296 | 320 | |
| 297 | 321 | // Enable the additional media filters: https://github.com/CMB2/CMB2/issues/873 |
| 298 | - media.frames[ id ].states.first().set( 'filterable', 'all' ); | |
| 322 | + media.frames[ uid ].states.first().set( 'filterable', 'all' ); | |
| 299 | 323 | |
| 300 | 324 | cmb.trigger( 'cmb_media_modal_init', media ); |
| 301 | 325 | |
| 302 | 326 | handlers.list = function( selection, returnIt ) { |
| @@ -342,9 +366,10 @@ | ||
| 342 | 366 | // Only get one file from the uploader |
| 343 | 367 | var attachment = selection.first(); |
| 344 | 368 | |
| 345 | 369 | media.$field.val( attachment.get( 'url' ) ); |
| 346 | - $id( media.field +'_id' ).val( attachment.get( 'id' ) ); | |
| 370 | + media.$field.closest( '.cmb-td' ).find('.cmb2-upload-file-id') | |
| 371 | + .val( attachment.get( 'id' ) ); | |
| 347 | 372 | |
| 348 | 373 | // Image preview or standard generic output if it's not an image. |
| 349 | 374 | var attachmentHtml = handlers.getAttachmentHtml( attachment, 'single' ); |
| 350 | 375 | |
| @@ -429,9 +454,9 @@ | ||
| 429 | 454 | return this; |
| 430 | 455 | }; |
| 431 | 456 | |
| 432 | 457 | handlers.selectFile = function() { |
| 433 | - var selection = media.frames[ id ].state().get( 'selection' ); | |
| 458 | + var selection = media.frames[ uid ].state().get( 'selection' ); | |
| 434 | 459 | var type = isList ? 'list' : 'single'; |
| 435 | 460 | |
| 436 | 461 | if ( cmb.attach_id && isList ) { |
| 437 | 462 | $( '[data-id="'+ cmb.attach_id +'"]' ).parents( 'li' ).replaceWith( handlers.list( selection, true ) ); |
| @@ -442,9 +467,9 @@ | ||
| 442 | 467 | cmb.trigger( 'cmb_media_modal_select', selection, media ); |
| 443 | 468 | }; |
| 444 | 469 | |
| 445 | 470 | handlers.openModal = function() { |
| 446 | - var selection = media.frames[ id ].state().get( 'selection' ); | |
| 471 | + var selection = media.frames[ uid ].state().get( 'selection' ); | |
| 447 | 472 | var attach; |
| 448 | 473 | |
| 449 | 474 | if ( ! cmb.attach_id ) { |
| 450 | 475 | selection.reset(); |
| @@ -457,14 +482,14 @@ | ||
| 457 | 482 | cmb.trigger( 'cmb_media_modal_open', selection, media ); |
| 458 | 483 | }; |
| 459 | 484 | |
| 460 | 485 | // When a file is selected, run a callback. |
| 461 | - media.frames[ id ] | |
| 486 | + media.frames[ uid ] | |
| 462 | 487 | .on( 'select', handlers.selectFile ) |
| 463 | 488 | .on( 'open', handlers.openModal ); |
| 464 | 489 | |
| 465 | 490 | // Finally, open the modal |
| 466 | - media.frames[ id ].open(); | |
| 491 | + media.frames[ uid ].open(); | |
| 467 | 492 | }; |
| 468 | 493 | |
| 469 | 494 | cmb.handleRemoveMedia = function( evt ) { |
| 470 | 495 | evt.preventDefault(); |
| @@ -473,12 +498,14 @@ | ||
| 473 | 498 | $this.parents( '.cmb2-media-item' ).remove(); |
| 474 | 499 | return false; |
| 475 | 500 | } |
| 476 | 501 | |
| 477 | - cmb.media.field = $this.attr('rel'); | |
| 502 | + var $cell = $this.closest( '.cmb-td' ); | |
| 503 | + cmb.media.$field = $cell.find('.cmb2-upload-file'); | |
| 504 | + cmb.media.field = cmb.media.$field.attr('id'); | |
| 478 | 505 | |
| 479 | - cmb.metabox().find( document.getElementById( cmb.media.field ) ).val(''); | |
| 480 | - cmb.metabox().find( document.getElementById( cmb.media.field + '_id' ) ).val(''); | |
| 506 | + cmb.media.$field.val(''); | |
| 507 | + $cell.find('.cmb2-upload-file-id').val(''); | |
| 481 | 508 | $this.parents('.cmb2-media-status').html(''); |
| 482 | 509 | |
| 483 | 510 | return false; |
| 484 | 511 | }; |
| @@ -659,14 +686,8 @@ | ||
| 659 | 686 | var prevNum = parseInt( $oldRow.data('iterator'), 10 ); |
| 660 | 687 | cmb.idNumber = parseInt( prevNum, 10 ) + 1; |
| 661 | 688 | var $row = $oldRow.clone(); |
| 662 | 689 | var nodeName = $row.prop('nodeName') || 'div'; |
| 663 | - var getRowId = function( id ) { | |
| 664 | - id = id.split('-'); | |
| 665 | - id.splice(id.length - 1, 1); | |
| 666 | - id.push( cmb.idNumber ); | |
| 667 | - return id.join('-'); | |
| 668 | - }; | |
| 669 | 690 | |
| 670 | 691 | // Make sure the next number doesn't exist. |
| 671 | 692 | while ( $table.find( '.cmb-repeatable-grouping[data-iterator="'+ cmb.idNumber +'"]' ).length > 0 ) { |
| 672 | 693 | cmb.idNumber++; |
| @@ -674,9 +695,9 @@ | ||
| 674 | 695 | |
| 675 | 696 | cmb.newRowHousekeeping( $row.data( 'title', $this.data( 'grouptitle' ) ) ).cleanRow( $row, prevNum, true ); |
| 676 | 697 | $row.find( '.cmb-add-row-button' ).prop( 'disabled', false ); |
| 677 | 698 | |
| 678 | - var $newRow = $( '<' + nodeName + ' id="'+ getRowId( $oldRow.attr('id') ) +'" class="postbox cmb-row cmb-repeatable-grouping" data-iterator="'+ cmb.idNumber +'">'+ $row.html() +'</' + nodeName + '>' ); | |
| 699 | + var $newRow = $( '<' + nodeName + ' id="'+ getRowId( $oldRow.attr('id'), cmb.idNumber ) +'" class="postbox cmb-row cmb-repeatable-grouping" data-iterator="'+ cmb.idNumber +'">'+ $row.html() +'</' + nodeName + '>' ); | |
| 679 | 700 | $oldRow.after( $newRow ); |
| 680 | 701 | |
| 681 | 702 | cmb.afterRowInsert( $newRow ); |
| 682 | 703 | cmb.makeRepeatableSortable( $newRow ); |
| @@ -724,17 +745,8 @@ | ||
| 724 | 745 | } |
| 725 | 746 | |
| 726 | 747 | cmb.triggerElement( $table, 'cmb2_remove_group_row_start', $this ); |
| 727 | 748 | |
| 728 | - // When a group is removed, loop through all next groups and update fields names. | |
| 729 | - $parent.nextAll( '.cmb-repeatable-grouping' ).find( cmb.repeatEls ).each( function() { | |
| 730 | - var $el = $( this ); | |
| 731 | - var prevNum = parseInt( $el.parents( '.cmb-repeatable-grouping' ).data( 'iterator' ), 10 ); | |
| 732 | - var newNum = prevNum - 1; // Subtract 1 to get new iterator number | |
| 733 | - | |
| 734 | - cmb.updateNameAttr( $el, prevNum, newNum ); | |
| 735 | - } ); | |
| 736 | - | |
| 737 | 749 | $parent.remove(); |
| 738 | 750 | |
| 739 | 751 | cmb.triggerElement( $table, { type: 'cmb2_remove_row', group: true } ); |
| 740 | 752 | }; |
| @@ -798,12 +810,12 @@ | ||
| 798 | 810 | var fromIterator = $from.attr('data-iterator'); |
| 799 | 811 | var toIterator = $goto.attr('data-iterator'); |
| 800 | 812 | |
| 801 | 813 | // Replace name attributes in both groups. |
| 802 | - $from.attr( 'data-iterator', toIterator ).find( cmb.repeatEls ).each( function() { | |
| 814 | + $from.find( cmb.repeatEls ).each( function() { | |
| 803 | 815 | cmb.updateNameAttr( $( this ), fromIterator, toIterator ); |
| 804 | 816 | }); |
| 805 | - $goto.attr( 'data-iterator', fromIterator ).find( cmb.repeatEls ).each( function() { | |
| 817 | + $goto.find( cmb.repeatEls ).each( function() { | |
| 806 | 818 | cmb.updateNameAttr( $( this ), toIterator, fromIterator ); |
| 807 | 819 | }); |
| 808 | 820 | |
| 809 | 821 | // Replace titles in both groups. |
| @@ -811,8 +823,14 @@ | ||
| 811 | 823 | if ( groupTitle ) { |
| 812 | 824 | cmb.resetGroupTitles( $from, toIterator, groupTitle ); |
| 813 | 825 | cmb.resetGroupTitles( $goto, fromIterator, groupTitle ); |
| 814 | 826 | } |
| 827 | + | |
| 828 | + // Update the iterators | |
| 829 | + $from.data( 'iterator', toIterator ); | |
| 830 | + $from.attr( 'data-iterator', toIterator ); | |
| 831 | + $goto.data( 'iterator', fromIterator ); | |
| 832 | + $goto.attr( 'data-iterator', fromIterator ); | |
| 815 | 833 | |
| 816 | 834 | // Now move the group to it's destination. |
| 817 | 835 | $goto[moveUp ? 'before' : 'after']( $from ); |
| 818 | 836 | |