Conditions | 1 |
Paths | 0 |
Total Lines | 958 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
1 | /** |
||
15 | (function(window, document, $, cmb, undefined){ |
||
16 | 'use strict'; |
||
17 | |||
18 | // localization strings |
||
19 | var l10n = window.cmb2_l10; |
||
20 | var setTimeout = window.setTimeout; |
||
21 | var $document; |
||
22 | var $id = function( selector ) { |
||
23 | return $( document.getElementById( selector ) ); |
||
24 | }; |
||
25 | var defaults = { |
||
26 | idNumber : false, |
||
27 | repeatEls : 'input:not([type="button"],[id^=filelist]),select,textarea,.cmb2-media-status', |
||
28 | noEmpty : 'input:not([type="button"]):not([type="radio"]):not([type="checkbox"]),textarea', |
||
29 | repeatUpdate : 'input:not([type="button"]),select,textarea,label', |
||
30 | styleBreakPoint : 450, |
||
31 | mediaHandlers : {}, |
||
32 | defaults : { |
||
33 | time_picker : l10n.defaults.time_picker, |
||
34 | date_picker : l10n.defaults.date_picker, |
||
35 | color_picker : l10n.defaults.color_picker || {}, |
||
36 | }, |
||
37 | media : { |
||
38 | frames : {}, |
||
39 | }, |
||
40 | }; |
||
41 | |||
42 | cmb.metabox = function() { |
||
43 | if ( cmb.$metabox ) { |
||
44 | return cmb.$metabox; |
||
45 | } |
||
46 | cmb.$metabox = $('.cmb2-wrap > .cmb2-metabox'); |
||
47 | return cmb.$metabox; |
||
48 | }; |
||
49 | |||
50 | cmb.init = function() { |
||
51 | $document = $( document ); |
||
52 | |||
53 | // Setup the CMB2 object defaults. |
||
54 | $.extend( cmb, defaults ); |
||
55 | |||
56 | cmb.trigger( 'cmb_pre_init' ); |
||
57 | |||
58 | var $metabox = cmb.metabox(); |
||
59 | var $repeatGroup = $metabox.find('.cmb-repeatable-group'); |
||
60 | |||
61 | /** |
||
62 | * Initialize time/date/color pickers |
||
63 | */ |
||
64 | cmb.initPickers( $metabox.find('input[type="text"].cmb2-timepicker'), $metabox.find('input[type="text"].cmb2-datepicker'), $metabox.find('input[type="text"].cmb2-colorpicker') ); |
||
65 | |||
66 | // Insert toggle button into DOM wherever there is multicheck. credit: Genesis Framework |
||
67 | $( '<p><span class="button cmb-multicheck-toggle">' + l10n.strings.check_toggle + '</span></p>' ).insertBefore( '.cmb2-checkbox-list:not(.no-select-all)' ); |
||
68 | |||
69 | // Make File List drag/drop sortable: |
||
70 | cmb.makeListSortable(); |
||
71 | |||
72 | $metabox |
||
73 | .on( 'change', '.cmb2_upload_file', function() { |
||
74 | cmb.media.field = $( this ).attr( 'id' ); |
||
75 | $id( cmb.media.field + '_id' ).val(''); |
||
76 | }) |
||
77 | // Media/file management |
||
78 | .on( 'click', '.cmb-multicheck-toggle', cmb.toggleCheckBoxes ) |
||
79 | .on( 'click', '.cmb2-upload-button', cmb.handleMedia ) |
||
80 | .on( 'click', '.cmb-attach-list li, .cmb2-media-status .img-status img, .cmb2-media-status .file-status > span', cmb.handleFileClick ) |
||
81 | .on( 'click', '.cmb2-remove-file-button', cmb.handleRemoveMedia ) |
||
82 | // Repeatable content |
||
83 | .on( 'click', '.cmb-add-group-row', cmb.addGroupRow ) |
||
84 | .on( 'click', '.cmb-add-row-button', cmb.addAjaxRow ) |
||
85 | .on( 'click', '.cmb-remove-group-row', cmb.removeGroupRow ) |
||
86 | .on( 'click', '.cmb-remove-row-button', cmb.removeAjaxRow ) |
||
87 | // Ajax oEmbed display |
||
88 | .on( 'keyup paste focusout', '.cmb2-oembed', cmb.maybeOembed ) |
||
89 | // Reset titles when removing a row |
||
90 | .on( 'cmb2_remove_row', '.cmb-repeatable-group', cmb.resetTitlesAndIterator ) |
||
91 | .on( 'click', '.cmbhandle, .cmbhandle + .cmbhandle-title', cmb.toggleHandle ); |
||
92 | |||
93 | if ( $repeatGroup.length ) { |
||
94 | $repeatGroup |
||
95 | .filter('.sortable').each( function() { |
||
96 | // Add sorting arrows |
||
97 | $( this ).find( '.button.cmb-remove-group-row' ).before( '<a class="button cmb-shift-rows move-up alignleft" href="#"><span class="'+ l10n.up_arrow_class +'"></span></a> <a class="button cmb-shift-rows move-down alignleft" href="#"><span class="'+ l10n.down_arrow_class +'"></span></a>' ); |
||
98 | }) |
||
99 | .on( 'click', '.cmb-shift-rows', cmb.shiftRows ) |
||
100 | .on( 'cmb2_add_row', cmb.emptyValue ); |
||
101 | } |
||
102 | |||
103 | // on pageload |
||
104 | setTimeout( cmb.resizeoEmbeds, 500); |
||
105 | // and on window resize |
||
106 | $( window ).on( 'resize', cmb.resizeoEmbeds ); |
||
107 | |||
108 | cmb.trigger( 'cmb_init' ); |
||
109 | }; |
||
110 | |||
111 | cmb.resetTitlesAndIterator = function( evt ) { |
||
112 | if ( ! evt.group ) { |
||
113 | return; |
||
114 | } |
||
115 | |||
116 | // Loop repeatable group tables |
||
117 | $( '.cmb-repeatable-group' ).each( function() { |
||
118 | var $table = $( this ); |
||
119 | // Loop repeatable group table rows |
||
120 | $table.find( '.cmb-repeatable-grouping' ).each( function( rowindex ) { |
||
121 | var $row = $( this ); |
||
122 | // Reset rows iterator |
||
123 | $row.data( 'iterator', rowindex ); |
||
124 | // Reset rows title |
||
125 | $row.find( '.cmb-group-title h4' ).text( $table.find( '.cmb-add-group-row' ).data( 'grouptitle' ).replace( '{#}', ( rowindex + 1 ) ) ); |
||
126 | }); |
||
127 | }); |
||
128 | }; |
||
129 | |||
130 | cmb.toggleHandle = function( evt ) { |
||
131 | evt.preventDefault(); |
||
132 | cmb.trigger( 'postbox-toggled', $( this ).parent('.postbox').toggleClass('closed') ); |
||
133 | }; |
||
134 | |||
135 | cmb.toggleCheckBoxes = function( evt ) { |
||
136 | evt.preventDefault(); |
||
137 | var $this = $( this ); |
||
138 | var $multicheck = $this.closest( '.cmb-td' ).find( 'input[type=checkbox]:not([disabled])' ); |
||
139 | |||
140 | // If the button has already been clicked once... |
||
141 | if ( $this.data( 'checked' ) ) { |
||
142 | // clear the checkboxes and remove the flag |
||
143 | $multicheck.prop( 'checked', false ); |
||
144 | $this.data( 'checked', false ); |
||
145 | } |
||
146 | // Otherwise mark the checkboxes and add a flag |
||
147 | else { |
||
148 | $multicheck.prop( 'checked', true ); |
||
149 | $this.data( 'checked', true ); |
||
150 | } |
||
151 | }; |
||
152 | |||
153 | cmb.handleMedia = function( evt ) { |
||
154 | evt.preventDefault(); |
||
155 | |||
156 | var $el = $( this ); |
||
157 | cmb.attach_id = ! $el.hasClass( 'cmb2-upload-list' ) ? $el.closest( '.cmb-td' ).find( '.cmb2-upload-file-id' ).val() : false; |
||
158 | // Clean up default 0 value |
||
159 | cmb.attach_id = '0' !== cmb.attach_id ? cmb.attach_id : false; |
||
160 | |||
161 | cmb._handleMedia( $el.prev('input.cmb2-upload-file').attr('id'), $el.hasClass( 'cmb2-upload-list' ) ); |
||
162 | }; |
||
163 | |||
164 | cmb.handleFileClick = function( evt ) { |
||
165 | evt.preventDefault(); |
||
166 | |||
167 | var $el = $( this ); |
||
168 | var $td = $el.closest( '.cmb-td' ); |
||
169 | var isList = $td.find( '.cmb2-upload-button' ).hasClass( 'cmb2-upload-list' ); |
||
170 | cmb.attach_id = isList ? $el.find( 'input[type="hidden"]' ).data( 'id' ) : $td.find( '.cmb2-upload-file-id' ).val(); |
||
171 | |||
172 | if ( cmb.attach_id ) { |
||
173 | cmb._handleMedia( $td.find( 'input.cmb2-upload-file' ).attr('id'), isList, cmb.attach_id ); |
||
174 | } |
||
175 | }; |
||
176 | |||
177 | cmb._handleMedia = function( formfield, isList ) { |
||
178 | if ( ! wp ) { |
||
|
|||
179 | return; |
||
180 | } |
||
181 | |||
182 | var media = cmb.media; |
||
183 | media.field = formfield; |
||
184 | media.$field = $id( media.field ); |
||
185 | media.fieldData = media.$field.data(); |
||
186 | media.previewSize = media.fieldData.previewsize; |
||
187 | media.fieldName = media.$field.attr('name'); |
||
188 | media.isList = isList; |
||
189 | |||
190 | var uploadStatus, attachment; |
||
191 | |||
192 | // If this field's media frame already exists, reopen it. |
||
193 | if ( media.field in media.frames ) { |
||
194 | media.frames[ media.field ].open(); |
||
195 | return; |
||
196 | } |
||
197 | |||
198 | // Create the media frame. |
||
199 | media.frames[ media.field ] = wp.media( { |
||
200 | title: cmb.metabox().find('label[for="' + media.field + '"]').text(), |
||
201 | library : media.fieldData.queryargs || {}, |
||
202 | button: { |
||
203 | text: l10n.strings[ isList ? 'upload_files' : 'upload_file' ] |
||
204 | }, |
||
205 | multiple: isList ? 'add' : false |
||
206 | } ); |
||
207 | |||
208 | cmb.trigger( 'cmb_media_modal_init', media ); |
||
209 | |||
210 | cmb.mediaHandlers.list = function( selection, returnIt ) { |
||
211 | // Get all of our selected files |
||
212 | attachment = selection.toJSON(); |
||
213 | |||
214 | media.$field.val(attachment.url); |
||
215 | $id( media.field +'_id' ).val(attachment.id); |
||
216 | |||
217 | // Setup our fileGroup array |
||
218 | var fileGroup = []; |
||
219 | |||
220 | // Loop through each attachment |
||
221 | $( attachment ).each( function() { |
||
222 | if ( this.type && this.type === 'image' ) { |
||
223 | var width = media.previewSize[0] ? media.previewSize[0] : 50; |
||
224 | var height = media.previewSize[1] ? media.previewSize[1] : 50; |
||
225 | |||
226 | // image preview |
||
227 | uploadStatus = '<li class="img-status">'+ |
||
228 | '<img width="'+ width +'" height="'+ height +'" src="' + this.url + '" class="attachment-'+ width +'px'+ height +'px" alt="'+ this.filename +'">'+ |
||
229 | '<p><a href="#" class="cmb2-remove-file-button" rel="'+ media.field +'['+ this.id +']">'+ l10n.strings.remove_image +'</a></p>'+ |
||
230 | '<input type="hidden" id="filelist-'+ this.id +'" data-id="'+ this.id +'" name="'+ media.fieldName +'['+ this.id +']" value="' + this.url + '">'+ |
||
231 | '</li>'; |
||
232 | |||
233 | } else { |
||
234 | // Standard generic output if it's not an image. |
||
235 | uploadStatus = '<li class="file-status"><span>'+ l10n.strings.file +' <strong>'+ this.filename +'</strong></span> (<a href="' + this.url + '" target="_blank" rel="external">'+ l10n.strings.download +'</a> / <a href="#" class="cmb2-remove-file-button" rel="'+ media.field +'['+ this.id +']">'+ l10n.strings.remove_file +'</a>)'+ |
||
236 | '<input type="hidden" id="filelist-'+ this.id +'" data-id="'+ this.id +'" name="'+ media.fieldName +'['+ this.id +']" value="' + this.url + '">'+ |
||
237 | '</li>'; |
||
238 | |||
239 | } |
||
240 | |||
241 | // Add our file to our fileGroup array |
||
242 | fileGroup.push( uploadStatus ); |
||
243 | }); |
||
244 | |||
245 | if ( ! returnIt ) { |
||
246 | // Append each item from our fileGroup array to .cmb2-media-status |
||
247 | $( fileGroup ).each( function() { |
||
248 | media.$field.siblings('.cmb2-media-status').slideDown().append(this); |
||
249 | }); |
||
250 | } else { |
||
251 | return fileGroup; |
||
252 | } |
||
253 | |||
254 | }; |
||
255 | |||
256 | cmb.mediaHandlers.single = function( selection ) { |
||
257 | // Only get one file from the uploader |
||
258 | attachment = selection.first().toJSON(); |
||
259 | |||
260 | media.$field.val(attachment.url); |
||
261 | $id( media.field +'_id' ).val(attachment.id); |
||
262 | |||
263 | if ( attachment.type && attachment.type === 'image' ) { |
||
264 | // image preview |
||
265 | var width = media.previewSize[0] ? media.previewSize[0] : 350; |
||
266 | uploadStatus = '<div class="img-status"><img width="'+ width +'px" style="max-width: '+ width +'px; width: 100%; height: auto;" src="' + attachment.url + '" alt="'+ attachment.filename +'" title="'+ attachment.filename +'" /><p><a href="#" class="cmb2-remove-file-button" rel="' + media.field + '">'+ l10n.strings.remove_image +'</a></p></div>'; |
||
267 | } else { |
||
268 | // Standard generic output if it's not an image. |
||
269 | uploadStatus = '<div class="file-status"><span>'+ l10n.strings.file +' <strong>'+ attachment.filename +'</strong></span> (<a href="'+ attachment.url +'" target="_blank" rel="external">'+ l10n.strings.download +'</a> / <a href="#" class="cmb2-remove-file-button" rel="'+ media.field +'">'+ l10n.strings.remove_file +'</a>)</div>'; |
||
270 | } |
||
271 | |||
272 | // add/display our output |
||
273 | media.$field.siblings('.cmb2-media-status').slideDown().html(uploadStatus); |
||
274 | }; |
||
275 | |||
276 | cmb.mediaHandlers.selectFile = function() { |
||
277 | var selection = media.frames[ media.field ].state().get('selection'); |
||
278 | var type = isList ? 'list' : 'single'; |
||
279 | |||
280 | if ( cmb.attach_id && isList ) { |
||
281 | $( '[data-id="'+ cmb.attach_id +'"]' ).parents( 'li' ).replaceWith( cmb.mediaHandlers.list( selection, true ) ); |
||
282 | } else { |
||
283 | cmb.mediaHandlers[type]( selection ); |
||
284 | } |
||
285 | |||
286 | cmb.trigger( 'cmb_media_modal_select', selection, media ); |
||
287 | }; |
||
288 | |||
289 | cmb.mediaHandlers.openModal = function() { |
||
290 | var selection = media.frames[ media.field ].state().get('selection'); |
||
291 | var attach; |
||
292 | |||
293 | if ( ! cmb.attach_id ) { |
||
294 | selection.reset(); |
||
295 | } else { |
||
296 | attach = wp.media.attachment( cmb.attach_id ); |
||
297 | attach.fetch(); |
||
298 | selection.set( attach ? [ attach ] : [] ); |
||
299 | } |
||
300 | |||
301 | cmb.trigger( 'cmb_media_modal_open', selection, media ); |
||
302 | }; |
||
303 | |||
304 | // When a file is selected, run a callback. |
||
305 | media.frames[ media.field ] |
||
306 | .on( 'select', cmb.mediaHandlers.selectFile ) |
||
307 | .on( 'open', cmb.mediaHandlers.openModal ); |
||
308 | |||
309 | // Finally, open the modal |
||
310 | media.frames[ media.field ].open(); |
||
311 | }; |
||
312 | |||
313 | cmb.handleRemoveMedia = function( evt ) { |
||
314 | evt.preventDefault(); |
||
315 | var $this = $( this ); |
||
316 | if ( $this.is( '.cmb-attach-list .cmb2-remove-file-button' ) ){ |
||
317 | $this.parents('li').remove(); |
||
318 | return false; |
||
319 | } |
||
320 | |||
321 | cmb.media.field = $this.attr('rel'); |
||
322 | |||
323 | cmb.metabox().find( 'input#' + cmb.media.field ).val(''); |
||
324 | cmb.metabox().find( 'input#' + cmb.media.field + '_id' ).val(''); |
||
325 | $this.parents('.cmb2-media-status').html(''); |
||
326 | |||
327 | return false; |
||
328 | }; |
||
329 | |||
330 | cmb.cleanRow = function( $row, prevNum, group ) { |
||
331 | var $elements = $row.find( cmb.repeatUpdate ); |
||
332 | if ( group ) { |
||
333 | |||
334 | var $other = $row.find( '[id]' ).not( cmb.repeatUpdate ); |
||
335 | |||
336 | // Remove extra ajaxed rows |
||
337 | $row.find('.cmb-repeat-table .cmb-repeat-row:not(:first-child)').remove(); |
||
338 | |||
339 | // Update all elements w/ an ID |
||
340 | if ( $other.length ) { |
||
341 | $other.each( function() { |
||
342 | var $_this = $( this ); |
||
343 | var oldID = $_this.attr( 'id' ); |
||
344 | var newID = oldID.replace( '_'+ prevNum, '_'+ cmb.idNumber ); |
||
345 | var $buttons = $row.find('[data-selector="'+ oldID +'"]'); |
||
346 | $_this.attr( 'id', newID ); |
||
347 | |||
348 | // Replace data-selector vars |
||
349 | if ( $buttons.length ) { |
||
350 | $buttons.attr( 'data-selector', newID ).data( 'selector', newID ); |
||
351 | } |
||
352 | }); |
||
353 | } |
||
354 | } |
||
355 | |||
356 | $elements.filter(':checked').prop( 'checked', false ); |
||
357 | $elements.filter(':selected').prop( 'selected', false ); |
||
358 | |||
359 | if ( $row.find('h3.cmb-group-title').length ) { |
||
360 | $row.find( 'h3.cmb-group-title' ).text( $row.data( 'title' ).replace( '{#}', ( cmb.idNumber + 1 ) ) ); |
||
361 | } |
||
362 | |||
363 | $elements.each( function() { |
||
364 | cmb.elReplacements( $( this ), prevNum ); |
||
365 | } ); |
||
366 | |||
367 | return cmb; |
||
368 | }; |
||
369 | |||
370 | cmb.elReplacements = function( $newInput, prevNum ) { |
||
371 | var oldFor = $newInput.attr( 'for' ); |
||
372 | var oldVal = $newInput.val(); |
||
373 | var type = $newInput.prop( 'type' ); |
||
374 | var checkable = 'radio' === type || 'checkbox' === type ? oldVal : false; |
||
375 | // var $next = $newInput.next(); |
||
376 | var attrs = {}; |
||
377 | var newID, oldID; |
||
378 | if ( oldFor ) { |
||
379 | attrs = { 'for' : oldFor.replace( '_'+ prevNum, '_'+ cmb.idNumber ) }; |
||
380 | } else { |
||
381 | var oldName = $newInput.attr( 'name' ); |
||
382 | // Replace 'name' attribute key |
||
383 | var newName = oldName ? oldName.replace( '['+ prevNum +']', '['+ cmb.idNumber +']' ) : ''; |
||
384 | oldID = $newInput.attr( 'id' ); |
||
385 | newID = oldID ? oldID.replace( '_'+ prevNum, '_'+ cmb.idNumber ) : ''; |
||
386 | attrs = { |
||
387 | id: newID, |
||
388 | name: newName, |
||
389 | // value: '', |
||
390 | 'data-iterator': cmb.idNumber, |
||
391 | }; |
||
392 | |||
393 | } |
||
394 | |||
395 | // Clear out old values |
||
396 | if ( undefined !== typeof( oldVal ) && oldVal || checkable ) { |
||
397 | attrs.value = checkable ? checkable : ''; |
||
398 | } |
||
399 | |||
400 | // Clear out textarea values |
||
401 | if ( 'TEXTAREA' === $newInput.prop('tagName') ) { |
||
402 | $newInput.html( '' ); |
||
403 | } |
||
404 | |||
405 | if ( checkable ) { |
||
406 | $newInput.removeAttr( 'checked' ); |
||
407 | } |
||
408 | |||
409 | $newInput |
||
410 | .removeClass( 'hasDatepicker' ) |
||
411 | .attr( attrs ).val( checkable ? checkable : '' ); |
||
412 | |||
413 | return $newInput; |
||
414 | }; |
||
415 | |||
416 | cmb.newRowHousekeeping = function( $row ) { |
||
417 | |||
418 | var $colorPicker = $row.find( '.wp-picker-container' ); |
||
419 | var $list = $row.find( '.cmb2-media-status' ); |
||
420 | |||
421 | if ( $colorPicker.length ) { |
||
422 | // Need to clean-up colorpicker before appending |
||
423 | $colorPicker.each( function() { |
||
424 | var $td = $( this ).parent(); |
||
425 | $td.html( $td.find( 'input[type="text"].cmb2-colorpicker' ).attr('style', '') ); |
||
426 | }); |
||
427 | } |
||
428 | |||
429 | // Need to clean-up colorpicker before appending |
||
430 | if ( $list.length ) { |
||
431 | $list.empty(); |
||
432 | } |
||
433 | |||
434 | return cmb; |
||
435 | }; |
||
436 | |||
437 | cmb.afterRowInsert = function( $row ) { |
||
438 | // Init pickers from new row |
||
439 | cmb.initPickers( $row.find('input[type="text"].cmb2-timepicker'), $row.find('input[type="text"].cmb2-datepicker'), $row.find('input[type="text"].cmb2-colorpicker') ); |
||
440 | }; |
||
441 | |||
442 | cmb.updateNameAttr = function () { |
||
443 | |||
444 | var $this = $( this ); |
||
445 | var name = $this.attr( 'name' ); // get current name |
||
446 | |||
447 | // If name is defined |
||
448 | if ( typeof name !== 'undefined' ) { |
||
449 | var prevNum = parseInt( $this.parents( '.cmb-repeatable-grouping' ).data( 'iterator' ), 10 ); |
||
450 | var newNum = prevNum - 1; // Subtract 1 to get new iterator number |
||
451 | |||
452 | // Update field name attributes so data is not orphaned when a row is removed and post is saved |
||
453 | var $newName = name.replace( '[' + prevNum + ']', '[' + newNum + ']' ); |
||
454 | |||
455 | // New name with replaced iterator |
||
456 | $this.attr( 'name', $newName ); |
||
457 | } |
||
458 | |||
459 | }; |
||
460 | |||
461 | cmb.emptyValue = function( evt, row ) { |
||
462 | $( cmb.noEmpty, row ).val( '' ); |
||
463 | }; |
||
464 | |||
465 | cmb.addGroupRow = function( evt ) { |
||
466 | evt.preventDefault(); |
||
467 | |||
468 | var $this = $( this ); |
||
469 | |||
470 | // before anything significant happens |
||
471 | cmb.triggerElement( $this, 'cmb2_add_group_row_start', $this ); |
||
472 | |||
473 | var $table = $id( $this.data('selector') ); |
||
474 | var $oldRow = $table.find('.cmb-repeatable-grouping').last(); |
||
475 | var prevNum = parseInt( $oldRow.data('iterator'), 10 ); |
||
476 | cmb.idNumber = parseInt( prevNum, 10 ) + 1; |
||
477 | var $row = $oldRow.clone(); |
||
478 | |||
479 | // Make sure the next number doesn't exist. |
||
480 | while ( $table.find( '.cmb-repeatable-grouping[data-iterator="'+ cmb.idNumber +'"]' ).length > 0 ) { |
||
481 | cmb.idNumber++; |
||
482 | } |
||
483 | |||
484 | cmb.newRowHousekeeping( $row.data( 'title', $this.data( 'grouptitle' ) ) ).cleanRow( $row, prevNum, true ); |
||
485 | $row.find( '.cmb-add-row-button' ).prop( 'disabled', false ); |
||
486 | |||
487 | var $newRow = $( '<div class="postbox cmb-row cmb-repeatable-grouping" data-iterator="'+ cmb.idNumber +'">'+ $row.html() +'</div>' ); |
||
488 | $oldRow.after( $newRow ); |
||
489 | |||
490 | cmb.afterRowInsert( $newRow ); |
||
491 | |||
492 | if ( $table.find('.cmb-repeatable-grouping').length <= 1 ) { |
||
493 | $table.find('.cmb-remove-group-row').prop( 'disabled', true ); |
||
494 | } else { |
||
495 | $table.find('.cmb-remove-group-row').prop( 'disabled', false ); |
||
496 | } |
||
497 | |||
498 | cmb.triggerElement( $table, { type: 'cmb2_add_row', group: true }, $newRow ); |
||
499 | |||
500 | }; |
||
501 | |||
502 | cmb.addAjaxRow = function( evt ) { |
||
503 | evt.preventDefault(); |
||
504 | |||
505 | var $this = $( this ); |
||
506 | var $table = $id( $this.data('selector') ); |
||
507 | var $emptyrow = $table.find('.empty-row'); |
||
508 | var prevNum = parseInt( $emptyrow.find('[data-iterator]').data('iterator'), 10 ); |
||
509 | cmb.idNumber = parseInt( prevNum, 10 ) + 1; |
||
510 | var $row = $emptyrow.clone(); |
||
511 | |||
512 | cmb.newRowHousekeeping( $row ).cleanRow( $row, prevNum ); |
||
513 | |||
514 | $emptyrow.removeClass('empty-row hidden').addClass('cmb-repeat-row'); |
||
515 | $emptyrow.after( $row ); |
||
516 | |||
517 | cmb.afterRowInsert( $row ); |
||
518 | |||
519 | cmb.triggerElement( $table, { type: 'cmb2_add_row', group: false }, $row ); |
||
520 | |||
521 | $table.find( '.cmb-remove-row-button' ).removeClass( 'button-disabled' ); |
||
522 | |||
523 | }; |
||
524 | |||
525 | cmb.removeGroupRow = function( evt ) { |
||
526 | evt.preventDefault(); |
||
527 | |||
528 | var $this = $( this ); |
||
529 | var $table = $id( $this.data('selector') ); |
||
530 | var $parent = $this.parents('.cmb-repeatable-grouping'); |
||
531 | var number = $table.find('.cmb-repeatable-grouping').length; |
||
532 | |||
533 | // Needs to always be at least one group. |
||
534 | if ( number < 2 ) { |
||
535 | return; |
||
536 | } |
||
537 | |||
538 | cmb.triggerElement( $table, 'cmb2_remove_group_row_start', $this ); |
||
539 | |||
540 | // when a group is removed loop through all next groups and update fields names |
||
541 | $parent.nextAll( '.cmb-repeatable-grouping' ).find( cmb.repeatEls ).each( cmb.updateNameAttr ); |
||
542 | |||
543 | $parent.remove(); |
||
544 | |||
545 | if ( number <= 2 ) { |
||
546 | $table.find('.cmb-remove-group-row').prop( 'disabled', true ); |
||
547 | } else { |
||
548 | $table.find('.cmb-remove-group-row').prop( 'disabled', false ); |
||
549 | } |
||
550 | |||
551 | cmb.triggerElement( $table, { type: 'cmb2_remove_row', group: true } ); |
||
552 | |||
553 | }; |
||
554 | |||
555 | cmb.removeAjaxRow = function( evt ) { |
||
556 | evt.preventDefault(); |
||
557 | |||
558 | var $this = $( this ); |
||
559 | |||
560 | // Check if disabled |
||
561 | if ( $this.hasClass( 'button-disabled' ) ) { |
||
562 | return; |
||
563 | } |
||
564 | |||
565 | var $parent = $this.parents('.cmb-row'); |
||
566 | var $table = $this.parents('.cmb-repeat-table'); |
||
567 | var number = $table.find('.cmb-row').length; |
||
568 | |||
569 | if ( number > 2 ) { |
||
570 | if ( $parent.hasClass('empty-row') ) { |
||
571 | $parent.prev().addClass( 'empty-row' ).removeClass('cmb-repeat-row'); |
||
572 | } |
||
573 | $this.parents('.cmb-repeat-table .cmb-row').remove(); |
||
574 | if ( number === 3 ) { |
||
575 | $table.find( '.cmb-remove-row-button' ).addClass( 'button-disabled' ); |
||
576 | } |
||
577 | |||
578 | cmb.triggerElement( $table, { type: 'cmb2_remove_row', group: false } ); |
||
579 | |||
580 | } else { |
||
581 | $this.addClass( 'button-disabled' ); |
||
582 | } |
||
583 | }; |
||
584 | |||
585 | cmb.shiftRows = function( evt ) { |
||
586 | |||
587 | evt.preventDefault(); |
||
588 | |||
589 | var $this = $( this ); |
||
590 | var $from = $this.parents( '.cmb-repeatable-grouping' ); |
||
591 | var $goto = $this.hasClass( 'move-up' ) ? $from.prev( '.cmb-repeatable-grouping' ) : $from.next( '.cmb-repeatable-grouping' ); |
||
592 | |||
593 | // Before shift occurs. |
||
594 | cmb.triggerElement( $this, 'cmb2_shift_rows_enter', $this, $from, $goto ); |
||
595 | |||
596 | if ( ! $goto.length ) { |
||
597 | return; |
||
598 | } |
||
599 | |||
600 | // About to shift |
||
601 | cmb.triggerElement( $this, 'cmb2_shift_rows_start', $this, $from, $goto ); |
||
602 | |||
603 | var inputVals = []; |
||
604 | // Loop this item's fields |
||
605 | $from.find( cmb.repeatEls ).each( function() { |
||
606 | var $element = $( this ); |
||
607 | var elType = $element.attr( 'type' ); |
||
608 | var val; |
||
609 | |||
610 | if ( $element.hasClass('cmb2-media-status') ) { |
||
611 | // special case for image previews |
||
612 | val = $element.html(); |
||
613 | } else if ( 'checkbox' === elType || 'radio' === elType ) { |
||
614 | val = $element.is(':checked'); |
||
615 | } else if ( 'select' === $element.prop('tagName') ) { |
||
616 | val = $element.is(':selected'); |
||
617 | } else { |
||
618 | val = $element.val(); |
||
619 | } |
||
620 | |||
621 | // Get all the current values per element |
||
622 | inputVals.push( { val: val, $: $element } ); |
||
623 | }); |
||
624 | // And swap them all |
||
625 | $goto.find( cmb.repeatEls ).each( function( index ) { |
||
626 | var $element = $( this ); |
||
627 | var elType = $element.attr( 'type' ); |
||
628 | var val; |
||
629 | |||
630 | if ( $element.hasClass('cmb2-media-status') ) { |
||
631 | var toRowId = $element.closest('.cmb-repeatable-grouping').attr('data-iterator'); |
||
632 | var fromRowId = inputVals[ index ].$.closest('.cmb-repeatable-grouping').attr('data-iterator'); |
||
633 | |||
634 | // special case for image previews |
||
635 | val = $element.html(); |
||
636 | $element.html( inputVals[ index ].val ); |
||
637 | inputVals[ index ].$.html( val ); |
||
638 | |||
639 | inputVals[ index ].$.find( 'input' ).each(function() { |
||
640 | var name = $( this ).attr( 'name' ); |
||
641 | name = name.replace( '['+toRowId+']', '['+fromRowId+']' ); |
||
642 | $( this ).attr( 'name', name ); |
||
643 | }); |
||
644 | $element.find('input').each(function() { |
||
645 | var name = $( this ).attr('name'); |
||
646 | name = name.replace('['+fromRowId+']', '['+toRowId+']'); |
||
647 | $( this ).attr('name', name); |
||
648 | }); |
||
649 | |||
650 | } |
||
651 | // handle checkbox swapping |
||
652 | else if ( 'checkbox' === elType ) { |
||
653 | inputVals[ index ].$.prop( 'checked', $element.is(':checked') ); |
||
654 | $element.prop( 'checked', inputVals[ index ].val ); |
||
655 | } |
||
656 | // handle radio swapping |
||
657 | else if ( 'radio' === elType ) { |
||
658 | if ( $element.is( ':checked' ) ) { |
||
659 | inputVals[ index ].$.attr( 'data-checked', 'true' ); |
||
660 | } |
||
661 | if ( inputVals[ index ].$.is( ':checked' ) ) { |
||
662 | $element.attr( 'data-checked', 'true' ); |
||
663 | } |
||
664 | } |
||
665 | // handle select swapping |
||
666 | else if ( 'select' === $element.prop('tagName') ) { |
||
667 | inputVals[ index ].$.prop( 'selected', $element.is(':selected') ); |
||
668 | $element.prop( 'selected', inputVals[ index ].val ); |
||
669 | } |
||
670 | // handle normal input swapping |
||
671 | else { |
||
672 | inputVals[ index ].$.val( $element.val() ); |
||
673 | $element.val( inputVals[ index ].val ); |
||
674 | } |
||
675 | }); |
||
676 | |||
677 | $from.find( 'input[data-checked=true]' ).prop( 'checked', true ).removeAttr( 'data-checked' ); |
||
678 | $goto.find( 'input[data-checked=true]' ).prop( 'checked', true ).removeAttr( 'data-checked' ); |
||
679 | |||
680 | // trigger color picker change event |
||
681 | $from.find( 'input[type="text"].cmb2-colorpicker' ).trigger( 'change' ); |
||
682 | $goto.find( 'input[type="text"].cmb2-colorpicker' ).trigger( 'change' ); |
||
683 | |||
684 | // shift done |
||
685 | cmb.triggerElement( $this, 'cmb2_shift_rows_complete', $this, $from, $goto ); |
||
686 | }; |
||
687 | |||
688 | cmb.initPickers = function( $timePickers, $datePickers, $colorPickers ) { |
||
689 | // Initialize jQuery UI timepickers |
||
690 | cmb.initDateTimePickers( $timePickers, 'timepicker', 'time_picker' ); |
||
691 | // Initialize jQuery UI datepickers |
||
692 | cmb.initDateTimePickers( $datePickers, 'datepicker', 'date_picker' ); |
||
693 | // Initialize color picker |
||
694 | cmb.initColorPickers( $colorPickers ); |
||
695 | }; |
||
696 | |||
697 | cmb.initDateTimePickers = function( $selector, method, defaultKey ) { |
||
698 | if ( $selector.length ) { |
||
699 | $selector[ method ]( 'destroy' ).each( function() { |
||
700 | var $this = $( this ); |
||
701 | var fieldOpts = $this.data( method ) || {}; |
||
702 | var options = $.extend( {}, cmb.defaults[ defaultKey ], fieldOpts ); |
||
703 | $this[ method ]( cmb.datePickerSetupOpts( fieldOpts, options, method ) ); |
||
704 | } ); |
||
705 | } |
||
706 | }; |
||
707 | |||
708 | cmb.datePickerSetupOpts = function( fieldOpts, options, method ) { |
||
709 | var existing = $.extend( {}, options ); |
||
710 | |||
711 | options.beforeShow = function( input, inst ) { |
||
712 | if ( 'timepicker' === method ) { |
||
713 | cmb.addTimePickerClasses( inst.dpDiv ); |
||
714 | } |
||
715 | |||
716 | // Wrap datepicker w/ class to narrow the scope of jQuery UI CSS and prevent conflicts |
||
717 | $id( 'ui-datepicker-div' ).addClass( 'cmb2-element' ); |
||
718 | |||
719 | // Let's be sure to call beforeShow if it was added |
||
720 | if ( 'function' === typeof existing.beforeShow ) { |
||
721 | existing.beforeShow( input, inst ); |
||
722 | } |
||
723 | }; |
||
724 | |||
725 | if ( 'timepicker' === method ) { |
||
726 | options.onChangeMonthYear = function( year, month, inst, picker ) { |
||
727 | cmb.addTimePickerClasses( inst.dpDiv ); |
||
728 | |||
729 | // Let's be sure to call onChangeMonthYear if it was added |
||
730 | if ( 'function' === typeof existing.onChangeMonthYear ) { |
||
731 | existing.onChangeMonthYear( year, month, inst, picker ); |
||
732 | } |
||
733 | }; |
||
734 | } |
||
735 | |||
736 | options.onClose = function( dateText, inst ) { |
||
737 | // Remove the class when we're done with it (and hide to remove FOUC). |
||
738 | $id( 'ui-datepicker-div' ).removeClass( 'cmb2-element' ).hide(); |
||
739 | |||
740 | // Let's be sure to call onClose if it was added |
||
741 | if ( 'function' === typeof existing.onClose ) { |
||
742 | existing.onClose( dateText, inst ); |
||
743 | } |
||
744 | }; |
||
745 | |||
746 | return options; |
||
747 | }; |
||
748 | |||
749 | // Adds classes to timepicker buttons. |
||
750 | cmb.addTimePickerClasses = function( $picker ) { |
||
751 | var func = cmb.addTimePickerClasses; |
||
752 | func.count = func.count || 0; |
||
753 | |||
754 | // Wait a bit to let the timepicker render, since these are pre-render events. |
||
755 | setTimeout( function() { |
||
756 | if ( $picker.find( '.ui-priority-secondary' ).length ) { |
||
757 | $picker.find( '.ui-priority-secondary' ).addClass( 'button-secondary' ); |
||
758 | $picker.find( '.ui-priority-primary' ).addClass( 'button-primary' ); |
||
759 | func.count = 0; |
||
760 | } else if ( func.count < 5 ) { |
||
761 | func.count++; |
||
762 | func( $picker ); |
||
763 | } |
||
764 | }, 10 ); |
||
765 | }; |
||
766 | |||
767 | cmb.initColorPickers = function( $selector ) { |
||
768 | if ( ! $selector.length ) { |
||
769 | return; |
||
770 | } |
||
771 | if ( typeof jQuery.wp === 'object' && typeof jQuery.wp.wpColorPicker === 'function' ) { |
||
772 | |||
773 | $selector.each( function() { |
||
774 | var $this = $( this ); |
||
775 | var fieldOpts = $this.data( 'colorpicker' ) || {}; |
||
776 | $this.wpColorPicker( $.extend( {}, cmb.defaults.color_picker, fieldOpts ) ); |
||
777 | } ); |
||
778 | |||
779 | } else { |
||
780 | $selector.each( function( i ) { |
||
781 | $( this ).after( '<div id="picker-' + i + '" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>' ); |
||
782 | $id( 'picker-' + i ).hide().farbtastic( $( this ) ); |
||
783 | } ) |
||
784 | .focus( function() { |
||
785 | $( this ).next().show(); |
||
786 | } ) |
||
787 | .blur( function() { |
||
788 | $( this ).next().hide(); |
||
789 | } ); |
||
790 | } |
||
791 | }; |
||
792 | |||
793 | cmb.makeListSortable = function() { |
||
794 | var $filelist = cmb.metabox().find( '.cmb2-media-status.cmb-attach-list' ); |
||
795 | if ( $filelist.length ) { |
||
796 | $filelist.sortable({ cursor: 'move' }).disableSelection(); |
||
797 | } |
||
798 | }; |
||
799 | |||
800 | cmb.maybeOembed = function( evt ) { |
||
801 | var $this = $( this ); |
||
802 | |||
803 | var m = { |
||
804 | focusout : function() { |
||
805 | setTimeout( function() { |
||
806 | // if it's been 2 seconds, hide our spinner |
||
807 | cmb.spinner( '.postbox .cmb2-metabox', true ); |
||
808 | }, 2000); |
||
809 | }, |
||
810 | keyup : function() { |
||
811 | var betw = function( min, max ) { |
||
812 | return ( evt.which <= max && evt.which >= min ); |
||
813 | }; |
||
814 | // Only Ajax on normal keystrokes |
||
815 | if ( betw( 48, 90 ) || betw( 96, 111 ) || betw( 8, 9 ) || evt.which === 187 || evt.which === 190 ) { |
||
816 | // fire our ajax function |
||
817 | cmb.doAjax( $this, evt ); |
||
818 | } |
||
819 | }, |
||
820 | paste : function() { |
||
821 | // paste event is fired before the value is filled, so wait a bit |
||
822 | setTimeout( function() { cmb.doAjax( $this ); }, 100); |
||
823 | } |
||
824 | }; |
||
825 | |||
826 | m[ evt.type ](); |
||
827 | }; |
||
828 | |||
829 | /** |
||
830 | * Resize oEmbed videos to fit in their respective metaboxes |
||
831 | */ |
||
832 | cmb.resizeoEmbeds = function() { |
||
833 | cmb.metabox().each( function() { |
||
834 | var $this = $( this ); |
||
835 | var $tableWrap = $this.parents('.inside'); |
||
836 | var isSide = $this.parents('.inner-sidebar').length || $this.parents( '#side-sortables' ).length; |
||
837 | var isSmall = isSide; |
||
838 | var isSmallest = false; |
||
839 | if ( ! $tableWrap.length ) { |
||
840 | return true; // continue |
||
841 | } |
||
842 | |||
843 | // Calculate new width |
||
844 | var tableW = $tableWrap.width(); |
||
845 | |||
846 | if ( cmb.styleBreakPoint > tableW ) { |
||
847 | isSmall = true; |
||
848 | isSmallest = ( cmb.styleBreakPoint - 62 ) > tableW; |
||
849 | } |
||
850 | |||
851 | tableW = isSmall ? tableW : Math.round(($tableWrap.width() * 0.82)*0.97); |
||
852 | var newWidth = tableW - 30; |
||
853 | if ( isSmall && ! isSide && ! isSmallest ) { |
||
854 | newWidth = newWidth - 75; |
||
855 | } |
||
856 | if ( newWidth > 639 ) { |
||
857 | return true; // continue |
||
858 | } |
||
859 | |||
860 | var $embeds = $this.find('.cmb-type-oembed .embed-status'); |
||
861 | var $children = $embeds.children().not('.cmb2-remove-wrapper'); |
||
862 | if ( ! $children.length ) { |
||
863 | return true; // continue |
||
864 | } |
||
865 | |||
866 | $children.each( function() { |
||
867 | var $this = $( this ); |
||
868 | var iwidth = $this.width(); |
||
869 | var iheight = $this.height(); |
||
870 | var _newWidth = newWidth; |
||
871 | if ( $this.parents( '.cmb-repeat-row' ).length && ! isSmall ) { |
||
872 | // Make room for our repeatable "remove" button column |
||
873 | _newWidth = newWidth - 91; |
||
874 | _newWidth = 785 > tableW ? _newWidth - 15 : _newWidth; |
||
875 | } |
||
876 | // Calc new height |
||
877 | var newHeight = Math.round((_newWidth * iheight)/iwidth); |
||
878 | $this.width(_newWidth).height(newHeight); |
||
879 | }); |
||
880 | |||
881 | }); |
||
882 | }; |
||
883 | |||
884 | /** |
||
885 | * Safely log things if query var is set |
||
886 | * @since 1.0.0 |
||
887 | */ |
||
888 | cmb.log = function() { |
||
889 | if ( l10n.script_debug && console && typeof console.log === 'function' ) { |
||
890 | console.log.apply(console, arguments); |
||
891 | } |
||
892 | }; |
||
893 | |||
894 | cmb.spinner = function( $context, hide ) { |
||
895 | if ( hide ) { |
||
896 | $('.cmb-spinner', $context ).hide(); |
||
897 | } |
||
898 | else { |
||
899 | $('.cmb-spinner', $context ).show(); |
||
900 | } |
||
901 | }; |
||
902 | |||
903 | // function for running our ajax |
||
904 | cmb.doAjax = function( $obj ) { |
||
905 | // get typed value |
||
906 | var oembed_url = $obj.val(); |
||
907 | // only proceed if the field contains more than 6 characters |
||
908 | if ( oembed_url.length < 6 ) { |
||
909 | return; |
||
910 | } |
||
911 | |||
912 | // get field id |
||
913 | var field_id = $obj.attr('id'); |
||
914 | var $context = $obj.closest( '.cmb-td' ); |
||
915 | var $embed_container = $context.find( '.embed-status' ); |
||
916 | var $embed_wrap = $context.find( '.embed_wrap' ); |
||
917 | var $child_el = $embed_container.find( ':first-child' ); |
||
918 | var oembed_width = $embed_container.length && $child_el.length ? $child_el.width() : $obj.width(); |
||
919 | |||
920 | cmb.log( 'oembed_url', oembed_url, field_id ); |
||
921 | |||
922 | // show our spinner |
||
923 | cmb.spinner( $context ); |
||
924 | // clear out previous results |
||
925 | $embed_wrap.html(''); |
||
926 | // and run our ajax function |
||
927 | setTimeout( function() { |
||
928 | // if they haven't typed in 500 ms |
||
929 | if ( $( '.cmb2-oembed:focus' ).val() !== oembed_url ) { |
||
930 | return; |
||
931 | } |
||
932 | $.ajax({ |
||
933 | type : 'post', |
||
934 | dataType : 'json', |
||
935 | url : l10n.ajaxurl, |
||
936 | data : { |
||
937 | 'action' : 'cmb2_oembed_handler', |
||
938 | 'oembed_url' : oembed_url, |
||
939 | 'oembed_width' : oembed_width > 300 ? oembed_width : 300, |
||
940 | 'field_id' : field_id, |
||
941 | 'object_id' : $obj.data( 'objectid' ), |
||
942 | 'object_type' : $obj.data( 'objecttype' ), |
||
943 | 'cmb2_ajax_nonce' : l10n.ajax_nonce |
||
944 | }, |
||
945 | success: function(response) { |
||
946 | cmb.log( response ); |
||
947 | // hide our spinner |
||
948 | cmb.spinner( $context, true ); |
||
949 | // and populate our results from ajax response |
||
950 | $embed_wrap.html( response.data ); |
||
951 | } |
||
952 | }); |
||
953 | |||
954 | }, 500); |
||
955 | |||
956 | }; |
||
957 | |||
958 | cmb.trigger = function( evtName ) { |
||
959 | var args = Array.prototype.slice.call( arguments, 1 ); |
||
960 | args.push( cmb ); |
||
961 | $document.trigger( evtName, args ); |
||
962 | }; |
||
963 | |||
964 | cmb.triggerElement = function( $el, evtName ) { |
||
965 | var args = Array.prototype.slice.call( arguments, 2 ); |
||
966 | args.push( cmb ); |
||
967 | $el.trigger( evtName, args ); |
||
968 | }; |
||
969 | |||
970 | $( cmb.init ); |
||
971 | |||
972 | })(window, document, jQuery, window.CMB2); |
||
973 |