PluginProbe ʕ •ᴥ•ʔ
Custom Sidebars – Dynamic Sidebar Classic Widget Area Manager / 3.32
Custom Sidebars – Dynamic Sidebar Classic Widget Area Manager v3.32
trunk 2.1.2.0 3.0.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.3 3.31 3.32 3.35 3.36 3.37 3.38
custom-sidebars / assets / js / cs.js
custom-sidebars / assets / js Last commit date
cs-cloning.js 5 years ago cs-cloning.min.js 5 years ago cs-visibility.js 5 years ago cs-visibility.min.js 5 years ago cs.js 5 years ago cs.min.js 5 years ago retirement-admin-notice.js 5 years ago
cs.js
1723 lines
1 /*! Custom Sidebars - v3.2.3
2 * Copyright (c) 2020; * Licensed GPLv2+ */
3 /*global window:false */
4 /*global console:false */
5 /*global document:false */
6 /*global wp:false */
7 /*global wpmUi:false */
8 /*global csSidebars:false */
9 /*global csSidebarsData:false */
10
11 /**
12 * CsSidebar class
13 *
14 * This adds new functionality to each sidebar.
15 *
16 * Note: Before the first CsSidebar object is created the class csSidebars below
17 * must be initialized!
18 */
19
20
21 /*
22 * http://blog.stevenlevithan.com/archives/faster-trim-javascript
23 */
24 function trim( str ) {
25 str = str.replace(/^\s\s*/, '');
26 for (var i = str.length - 1; i >= 0; i--) {
27 if (/\S/.test(str.charAt(i))) {
28 str = str.substring(0, i + 1);
29 break;
30 }
31 }
32 return str;
33 }
34
35 function CsSidebar(id, type) {
36 var editbar;
37
38 /**
39 * Replace % to fix bug http://wordpress.org/support/topic/in-wp-35-sidebars-are-not-collapsable-anymore?replies=16#post-3990447
40 * We'll use this.id to select and the original id for html
41 *
42 * @since 1.2
43 */
44 this.id = id.split('%').join('\\%');
45
46 /**
47 * Either 'custom' or 'theme'
48 *
49 * @since 2.0
50 */
51 this.type = type;
52
53 this.sb = jQuery('#' + this.id);
54 this.widgets = '';
55 this.name = trim(this.sb.find('.sidebar-name h2').text());
56 this.description = trim(this.sb.find('.sidebar-description').text());
57
58 // Add one of two editbars to each sidebar.
59 if ( type === 'custom' ) {
60 editbar = window.csSidebars.extras.find('.cs-custom-sidebar').clone();
61 } else {
62 editbar = window.csSidebars.extras.find('.cs-theme-sidebar').clone();
63 }
64
65 this.sb.parent().append(editbar);
66
67 // Customize the links and label-tags.
68 editbar.find('label').each(function(){
69 var me = jQuery( this );
70 window.csSidebars.addIdToLabel( me, id );
71 });
72 }
73
74 /**
75 * Returns the sidebar ID.
76 *
77 * @since 2.0
78 */
79 CsSidebar.prototype.getID = function() {
80 return this.id.split('\\').join('');
81 };
82
83
84 /**
85 * =============================================================================
86 *
87 *
88 * csSidebars class
89 *
90 * This is the collection of all CsSidebar objects.
91 */
92 window.csSidebars = null;
93
94 (function($){
95 window.csSidebars = {
96 /**
97 * List of all CsSidebar objects.
98 * @type array
99 */
100 sidebars: [],
101
102 /**
103 * This is the same prefix as defined in class-custom-sidebars.php
104 * @type string
105 */
106 sidebar_prefix: 'cs-',
107
108 /**
109 * Form for the edit-sidebar popup.
110 * @type jQuery object
111 */
112 edit_form: null,
113
114 /**
115 * Form for the delete-sidebar popup.
116 * @type jQuery object
117 */
118 delete_form: null,
119
120 /**
121 * Form for the export/import popup.
122 * @type jQuery object
123 */
124 export_form: null,
125
126 /**
127 * Form for the location popup.
128 * @type jQuery object
129 */
130 location_form: null,
131
132 /**
133 * Shortcut to '#widgets-right'
134 * @type jQuery object
135 */
136 right: null,
137
138 /**
139 * Shortcut to '#cs-widgets-extra'
140 * @type jQuery object
141 */
142 extras: null,
143
144 /**
145 * Stores the callback functions associated with the toolbar actions.
146 * @see csSidebars.handleAction()
147 * @see csSidebars.registerAction()
148 * @type Object
149 */
150 action_handlers: {},
151
152
153 /*====================================*\
154 ========================================
155 == ==
156 == INITIALIZATION ==
157 == ==
158 ========================================
159 \*====================================*/
160
161 init: function(){
162 if ( 'undefined' === typeof( csSidebarsData ) ) {
163 // Inside theme customizer we load the JS but have no widget-data.
164 return;
165 }
166
167 csSidebars
168 .initControls()
169 .initTopTools()
170 .initSidebars()
171 .initToolbars()
172 .initColumns();
173 },
174
175 /**
176 * =====================================================================
177 * Initialize DOM and find jQuery objects
178 *
179 * @since 1.0.0
180 */
181 initControls: function(){
182 csSidebars.right = jQuery( '#widgets-right' );
183 csSidebars.extras = jQuery( '#cs-widgets-extra' );
184
185 if ( null === csSidebars.edit_form ) {
186 csSidebars.edit_form = csSidebars.extras.find( '.cs-editor' ).clone();
187 csSidebars.extras.find( '.cs-editor' ).remove();
188 }
189
190 if ( null === csSidebars.delete_form ) {
191 csSidebars.delete_form = csSidebars.extras.find( '.cs-delete' ).clone();
192 csSidebars.extras.find( '.cs-delete' ).remove();
193 }
194
195 if ( null === csSidebars.export_form ) {
196 csSidebars.export_form = csSidebars.extras.find( '.cs-export' ).clone();
197 csSidebars.extras.find( '.cs-export' ).remove();
198 }
199
200 if ( null === csSidebars.location_form ) {
201 csSidebars.location_form = csSidebars.extras.find( '.cs-location' ).clone();
202 csSidebars.extras.find( '.cs-location' ).remove();
203 }
204
205 jQuery('#cs-title-options')
206 .detach()
207 .prependTo( csSidebars.right );
208
209 return csSidebars;
210 },
211
212 /**
213 * =====================================================================
214 * Arrange sidebars in left/right columns.
215 * Left column: Custom sidebars. Right column: Theme sidebars.
216 *
217 * @since 2.0
218 */
219 initColumns: function() {
220 var col1 = csSidebars.right.find( '.sidebars-column-1' ),
221 col2 = csSidebars.right.find( '.sidebars-column-2' ),
222 title = jQuery( '<div class="cs-title"><h2></h2></div>' ),
223 sidebars = csSidebars.right.find( '.widgets-holder-wrap' );
224
225 if ( ! col2.length ) {
226 col2 = jQuery( '<div class="sidebars-column-2"></div>' );
227 col2.appendTo( csSidebars.right );
228 }
229
230 function toggle_sort() {
231 var me = jQuery( this ),
232 col = me.closest( '.sidebars-column-1, .sidebars-column-2' ),
233 dir = col.data( 'sort-dir' );
234
235 dir = ('asc' === dir ? 'desc' : 'asc');
236 csSidebars.sort_sidebars( col, dir );
237 }
238
239 title
240 .find( 'h2' )
241 .append( '<span class="cs-title-val"></span><i class="cs-icon dashicons dashicons-sort"></i>' )
242 .css({'cursor': 'pointer'});
243
244 title
245 .clone()
246 .prependTo( col1 )
247 .click( toggle_sort )
248 .find('.cs-title-val')
249 .text( csSidebarsData.custom_sidebars );
250
251 title
252 .clone()
253 .prependTo( col2 )
254 .click( toggle_sort )
255 .find( '.cs-title-val' )
256 .text( csSidebarsData.theme_sidebars );
257
258 col1 = jQuery( '<div class="inner"></div>' ).appendTo( col1 );
259 col2 = jQuery( '<div class="inner"></div>' ).appendTo( col2 );
260
261 sidebars.each(function check_sidebar() {
262 var me = jQuery( this ),
263 sbar = me.find( '.widgets-sortables' );
264
265 if ( csSidebars.isCustomSidebar( sbar) ) {
266 me.appendTo( col1 );
267 } else {
268 me.appendTo( col2 );
269 }
270 });
271 },
272
273 /**
274 * =====================================================================
275 * Initialization function, creates a CsSidebar object for each sidebar.
276 *
277 * @since 1.0.0
278 */
279 initSidebars: function(){
280 csSidebars.right.find('.widgets-sortables').each(function() {
281 var key, sb,
282 state = false,
283 me = jQuery( this ),
284 id = me.attr('id');
285
286 if ( me.data( 'cs-init' ) === true ) { return; }
287 me.data( 'cs-init', true );
288
289 if ( csSidebars.isCustomSidebar( this ) ) {
290 sb = csSidebars.add( id, 'custom' );
291 } else {
292 sb = csSidebars.add( id, 'theme' );
293
294 // Set correct "replaceable" flag for the toolbar.
295 for ( key in csSidebarsData.replaceable ) {
296 if ( ! csSidebarsData.replaceable.hasOwnProperty( key ) ) {
297 continue;
298 }
299 if ( csSidebarsData.replaceable[key] === id ) {
300 state = true;
301 break;
302 }
303 }
304
305 csSidebars.setReplaceable( sb, state, false );
306 }
307 });
308 return csSidebars;
309 },
310
311 /**
312 * =====================================================================
313 * Initialize the top toolbar, above the sidebar list.
314 *
315 * @since 1.0.0
316 */
317 initTopTools: function() {
318 var btn_create = jQuery( '.btn-create-sidebar' ),
319 btn_export = jQuery( '.btn-export' ),
320 topbar = jQuery( '.cs-options' ),
321 txt_filter = jQuery( '<input type="search" class="cs-filter" />' ),
322 data = {};
323
324 // Button: Add new sidebar.
325 btn_create.click(function() {
326 data.id = '';
327 data.title = csSidebarsData.title_new;
328 data.button = csSidebarsData.btn_new;
329 data.description = '';
330 data.name = '';
331
332 csSidebars.showEditor( data );
333 });
334
335 // Button: Export sidebars.
336 btn_export.click( csSidebars.showExport );
337
338 // Add Sidebar filter.
339 txt_filter
340 .appendTo( topbar )
341 .attr( 'placeholder', csSidebarsData.filter )
342 .keyup( csSidebars.filter_sidebars )
343 .on( 'search', csSidebars.filter_sidebars );
344
345 return csSidebars;
346 },
347
348 /**
349 * =====================================================================
350 * Hook up all the functions in the sidebar toolbar.
351 * Toolbar is in the bottom of each sidebar.
352 *
353 * @since 1.0.0
354 */
355 initToolbars: function() {
356 function tool_action( ev ) {
357 var me = jQuery( ev.target ).closest( '.cs-tool' ),
358 action = me.data( 'action' ),
359 id = csSidebars.getIdFromEditbar( me ),
360 sb = csSidebars.find( id );
361
362 // Return value False means: Execute the default click handler.
363 return ! csSidebars.handleAction( action, sb );
364 }
365
366 csSidebars.registerAction( 'edit', csSidebars.showEditor );
367 csSidebars.registerAction( 'location', csSidebars.showLocations );
368 csSidebars.registerAction( 'delete', csSidebars.showRemove );
369 csSidebars.registerAction( 'replaceable', csSidebars.setReplaceable );
370
371 csSidebars.right.on('click', '.cs-tool', tool_action);
372
373 return csSidebars;
374 },
375
376 /**
377 * Triggers the callback function for the specified toolbar action.
378 *
379 * @since 2.0
380 */
381 handleAction: function( action, sb ) {
382 if ( 'function' === typeof csSidebars.action_handlers[ action ] ) {
383 return !! csSidebars.action_handlers[ action ]( sb );
384 }
385 return false;
386 },
387
388 /**
389 * Registers a new callback function that is triggered when the
390 * associated toolbar icon is clicked.
391 *
392 * @since 2.0
393 */
394 registerAction: function( action, callback ) {
395 csSidebars.action_handlers[ action ] = callback;
396 },
397
398 /**
399 * Displays a error notification that something has gone wrong.
400 *
401 * @since 2.0
402 * @param mixed details Ajax response string/object.
403 */
404 showAjaxError: function( details ) {
405 var msg = {};
406
407 msg.message = csSidebarsData.ajax_error;
408 msg.details = details;
409 msg.parent = '#widgets-right';
410 msg.insert_after = '#cs-title-options';
411 msg.id = 'editor';
412 msg.type = 'err';
413
414 wpmUi.message( msg );
415 },
416
417 /**
418 * Sorts the sidebars in the specified column
419 *
420 * @since 2.0.9.7
421 * @param jQuery col Sidebar container/column.
422 * @param string dir "asc|desc"
423 */
424 sort_sidebars: function( col, dir ) {
425 var sidebars = col.find( '.widgets-holder-wrap' ),
426 icon = col.find( '.cs-title .cs-icon' );
427
428 sidebars.sortElements(function( a, b ) {
429 var val_a = jQuery(a).find('.sidebar-name h2').text(),
430 val_b = jQuery(b).find('.sidebar-name h2').text();
431
432 if ( dir === 'asc' ) {
433 return val_a > val_b ? 1 : -1;
434 } else {
435 return val_a < val_b ? 1 : -1;
436 }
437 });
438
439 // Change the indicator.
440 col.data( 'sort-dir', dir );
441 if ( 'asc' === dir ) {
442 icon
443 .removeClass( 'dashicons-arrow-down dashicons-sort' )
444 .addClass( 'dashicons-arrow-up' );
445 } else {
446 icon
447 .removeClass( 'dashicons-arrow-up dashicons-sort' )
448 .addClass( 'dashicons-arrow-down' );
449 }
450 },
451
452 /**
453 * Filters the sidebars by title
454 *
455 * @since 2.0.9.7
456 */
457 filter_sidebars: function( ev ) {
458 var query = jQuery( 'input.cs-filter' ).val().toLowerCase(),
459 all = csSidebars.right.find( '.widgets-holder-wrap' );
460
461 all.each(function(){
462 var sb = jQuery( this ),
463 title = sb.find( '.sidebar-name h2' ).text();
464
465 if ( title.toLowerCase().indexOf( query ) !== -1 ) {
466 sb.show();
467 } else {
468 sb.hide();
469 }
470 });
471 jQuery( window ).trigger( 'cs-resize' );
472 },
473
474
475 /*============================*\
476 ================================
477 == ==
478 == EDITOR ==
479 == ==
480 ================================
481 \*============================*/
482
483 /**
484 * =====================================================================
485 * Show the editor for a custom sidebar as a popup window.
486 *
487 * @since 2.0
488 * @param Object data Data describing the popup window.
489 * - id .. ID of the sidebar (text).
490 * - name .. Value of field "name".
491 * - description .. Value of field "description".
492 * - title .. Text for the window title.
493 * - button .. Caption of the save button.
494 *
495 * or a CsSidebar object.
496 */
497 showEditor: function( data ) {
498
499 var popup = null,
500 ajax = null;
501
502 if ( data instanceof CsSidebar ) {
503 data = {
504 id: data.getID(),
505 title: csSidebarsData.title_edit.replace( '[Sidebar]', data.name ),
506 button: csSidebarsData.btn_edit
507 };
508 }
509
510 // Hide the "extra" fields
511 function hide_extras() {
512 popup.$().removeClass( 'csb-has-more' );
513 popup.size( 782, 215 );
514 }
515
516 // Show the "extra" fields
517 function show_extras() {
518 popup.$().addClass( 'csb-has-more' );
519 popup.size( 782, 545 );
520 }
521
522 // Toggle the "extra" fields based on the checkbox state.
523 function toggle_extras() {
524 if ( jQuery( this ).prop( 'checked' ) ) {
525 show_extras();
526 } else {
527 hide_extras();
528 }
529 }
530
531 // Populates the input fields in the editor with given data.
532 function set_values( data, okay, xhr ) {
533 popup.loading( false );
534
535 // Ignore error responses from Ajax.
536 if ( ! data ) {
537 return false;
538 }
539
540 if ( ! okay ) {
541 popup.destroy();
542 csSidebars.showAjaxError( data );
543 return false;
544 }
545
546 if ( data.sidebar ) {
547 data = data.sidebar;
548 }
549
550 // Populate known fields.
551 if ( data.id ) {
552 popup.$().find( '#csb-id' ).val( data.id );
553 }
554 if ( data.name ) {
555 popup.$().find( '#csb-name' ).val( data.name );
556 }
557 if ( data.description ) {
558 popup.$().find( '#csb-description' ).val( data.description );
559 }
560 if ( data.before_title ) {
561 popup.$().find( '#csb-before-title' ).val( data.before_title );
562 }
563 if ( data.after_title ) {
564 popup.$().find( '#csb-after-title' ).val( data.after_title );
565 }
566 if ( data.before_widget ) {
567 popup.$().find( '#csb-before-widget' ).val( data.before_widget );
568 }
569 if ( data.after_widget ) {
570 popup.$().find( '#csb-after-widget' ).val( data.after_widget );
571 }
572 if ( data.button ) {
573 popup.$().find( '.btn-save' ).text( data.button );
574 }
575 if ( data.advance ) {
576 popup.$().find( '#csb-more' ).prop( 'checked', true );
577 show_extras();
578 }
579 }
580
581 // Close popup after ajax request
582 function handle_done_save( resp, okay, xhr ) {
583 var msg = {}, sb;
584
585 popup.loading( false );
586 popup.destroy();
587
588 msg.message = resp.message;
589 // msg.details = resp;
590 msg.parent = '#widgets-right';
591 msg.insert_after = '#cs-title-options';
592 msg.id = 'editor';
593
594 if ( okay ) {
595 if ( 'update' === resp.action ) {
596 // Update the name/description of the sidebar.
597 sb = csSidebars.find( resp.data.id );
598 csSidebars.updateSidebar( sb, resp.data );
599 } else if ( 'insert' === resp.action ) {
600 // Insert a brand new sidebar container.
601 csSidebars.insertSidebar( resp.data );
602 $('.cs-wrap .custom-sidebars-add-new').detach();
603 }
604 } else {
605 msg.type = 'err';
606 }
607 wpmUi.message( msg );
608 }
609
610 // Submit the data via ajax.
611 function save_data() {
612 var form = popup.$().find( 'form' );
613 if ( 0 < popup.$('#csb-more:checked').length ) {
614 jQuery('<input>').attr({
615 type: 'hidden',
616 value: 'show',
617 name: 'advance'
618 }).appendTo(form);
619 }
620 // Start loading-animation.
621 popup.loading( true );
622 ajax.reset()
623 .data( form )
624 .ondone( handle_done_save )
625 .load_json();
626 return false;
627 }
628
629 // Show the EDITOR popup.
630 popup = wpmUi.popup()
631 .modal( true )
632 .title( data.title )
633 .onshow( hide_extras )
634 .content( csSidebars.edit_form );
635
636 hide_extras();
637 set_values( data, true, null );
638
639 // Create new ajax object to get sidebar details.
640 ajax = wpmUi.ajax( null, 'cs-ajax' );
641 if ( data.id ) {
642 popup.loading( true );
643 ajax.reset()
644 .data({
645 'do': 'get',
646 'sb': data.id,
647 '_wpnonce': csSidebarsData._wpnonce_get
648 })
649 .ondone( set_values )
650 .load_json();
651 }
652
653 popup.show();
654 popup.$().find( '#csb-name' ).focus();
655
656 /**
657 * handle enter key on new sidebar name
658 */
659 popup.$().on( 'keypress', '#csb-name', function(e) {
660 if ( 13 === e.keyCode ) {
661 if ( 0 < $(this).val().length ) {
662 $('#csb-description').focus();
663 }
664 }
665 });
666
667 /**
668 * handle enter key on new sidebar description
669 */
670 popup.$().on( 'keypress', '#csb-description', function(e) {
671 if ( 13 === e.keyCode ) {
672 popup.$('.btn-save').click();
673 }
674 });
675
676 // Add event hooks to the editor.
677 popup.$().on( 'click', '#csb-more', toggle_extras );
678 popup.$().on( 'click', '.btn-save', save_data );
679 popup.$().on( 'click', '.btn-cancel', popup.destroy );
680
681 return true;
682 },
683
684 /**
685 * Update the name/description of an existing sidebar container.
686 *
687 * @since 1.0.0
688 */
689 updateSidebar: function( sb, data ) {
690 // Update the title.
691 sb.sb
692 .find( '.sidebar-name h2' )
693 .text( data.name );
694
695 // Update description.
696 sb.sb
697 .find( '.sidebar-description' )
698 .html( '<p class="description"></p>' )
699 .find( '.description' )
700 .text( data.description );
701
702 return csSidebars;
703 },
704
705 /**
706 * Insert a brand new sidebar container.
707 *
708 * @since 1.0.0
709 */
710 insertSidebar: function( data ) {
711 var box = jQuery( '<div class="widgets-holder-wrap"></div>' ),
712 inner = jQuery( '<div class="widgets-sortables ui-sortable"></div>' ),
713 name = jQuery( '<div class="sidebar-name"><div class="sidebar-name-arrow"><br></div><h2></h2></div>' ),
714 desc = jQuery( '<div class="sidebar-description"></div>' ),
715 col = csSidebars.right.find( '.sidebars-column-1 > .inner:first' );
716
717 // Set sidebar specific values.
718 inner.attr( 'id', data.id );
719
720 name
721 .find( 'h2' )
722 .text( data.name );
723
724 desc
725 .html( '<p class="description"></p>' )
726 .find( '.description' )
727 .text( data.description );
728
729 // Assemble the new sidebar box in correct order.
730 name.appendTo( inner );
731 desc.appendTo( inner );
732 inner.appendTo( box );
733
734 // Display the new sidebar on screen.
735 box.prependTo( col );
736
737 // Remove hooks added by wpWidgets.init()
738 jQuery( '#widgets-right .sidebar-name' ).unbind( 'click' );
739 jQuery( '#widgets-left .sidebar-name' ).unbind( 'click' );
740 jQuery( document.body ).unbind('click.widgets-toggle');
741 jQuery('.widgets-chooser')
742 .off( 'click.widgets-chooser' )
743 .off( 'keyup.widgets-chooser' );
744 jQuery( '#available-widgets .widget .widget-title' ).off( 'click.widgets-chooser' );
745 jQuery( '.widgets-chooser-sidebars' ).empty();
746
747 // Re-Init the page using wpWidgets.init()
748 window.wpWidgets.init();
749
750 // Add the plugin toolbar to the new sidebar.
751 csSidebars.initSidebars();
752
753 return csSidebars;
754 },
755
756
757 /*============================*\
758 ================================
759 == ==
760 == EXPORT ==
761 == ==
762 ================================
763 \*============================*/
764
765 /**
766 * Shows a popup window with the export/import form.
767 *
768 * @since 2.0
769 */
770 showExport: function() {
771 var popup = null,
772 ajax = null;
773
774 // Download export file.
775 function do_export( ev ) {
776 var form = jQuery( this ).closest( 'form' );
777
778 ajax.reset()
779 .data( form )
780 .load_http();
781
782 popup.destroy();
783
784 ev.preventDefault();
785 return false;
786 }
787
788 // Ajax handler after import file was uploaded.
789 function handle_done_upload( resp, okay, xhr ) {
790 var msg = {};
791 popup.loading( false );
792
793 if ( okay ) {
794 popup
795 .size( 900, 600 )
796 .content( resp.html );
797 } else {
798 msg.message = resp.message;
799 // msg.details = resp;
800 msg.parent = popup.$().find( '.wpmui-wnd-content' );
801 msg.insert_after = false;
802 msg.id = 'export';
803 //Change msg.class to msg['class']. Reserved words not allowed as unquoted properties in older version of javascript
804 msg['class'] = 'wpmui-wnd-err';
805 msg.type = 'err';
806 wpmUi.message( msg );
807 }
808 }
809
810 // Upload the import file.
811 function do_upload( ev ) {
812 var form = jQuery( this ).closest( 'form' );
813
814 popup.loading( true );
815 ajax.reset()
816 .data( form )
817 .ondone( handle_done_upload )
818 .load_json( 'cs-ajax' );
819
820 ev.preventDefault();
821 return false;
822 }
823
824 // Import preview: Toggle widgets
825 function toggle_widgets() {
826 var me = jQuery( this ),
827 checked = me.prop( 'checked' ),
828 items = popup.$().find( '.column-widgets, .import-widgets' );
829
830 if ( checked ) {
831 items.show();
832 } else {
833 items.hide();
834 }
835 }
836
837 // Import preview: Cancel.
838 function show_overview() {
839 popup.size( 782, 480 );
840 popup.content( csSidebars.export_form );
841 }
842
843 // Import preview: Import the data.
844 function do_import() {
845 var form = popup.$().find( '.frm-import' );
846
847 popup.loading( true );
848
849 ajax.reset()
850 .data( form )
851 .load_http( '_self' );
852 }
853
854 // Show the EXPORT popup.
855 popup = wpmUi.popup()
856 .modal( true )
857 .size( 782, 480 )
858 .title( csSidebarsData.title_export )
859 .content( csSidebars.export_form )
860 .show();
861
862 ajax = wpmUi.ajax( null, 'cs-ajax' );
863
864 // Events for the Import / Export view.
865 popup.$().on( 'submit', '.frm-export', do_export );
866 popup.$().on( 'submit', '.frm-preview-import', do_upload );
867
868 // Events for the Import preview.
869 popup.$().on( 'change', '#import-widgets', toggle_widgets );
870 popup.$().on( 'click', '.btn-cancel', show_overview );
871 popup.$().on( 'click', '.btn-import', do_import );
872
873 return true;
874 },
875
876
877 /*============================*\
878 ================================
879 == ==
880 == REMOVE ==
881 == ==
882 ================================
883 \*============================*/
884
885 /**
886 * =====================================================================
887 * Ask for confirmation before deleting a sidebar
888 */
889 showRemove: function( sb ) {
890 var popup = null,
891 ajax = null,
892 id = sb.getID(),
893 name = sb.name;
894
895 // Insert the sidebar name into the delete message.
896 function insert_name( el ) {
897 el.find('.name').text( name );
898 }
899
900 // Closes the delete confirmation.
901 function close_popup() {
902 popup.loading( false );
903 popup.destroy();
904 }
905
906 // Handle response of the delete ajax-call.
907 function handle_done( resp, okay, xhr ) {
908 var msg = {};
909
910 popup.loading( false );
911 popup.destroy();
912
913 msg.message = resp.message;
914 // msg.details = resp;
915 msg.parent = '#widgets-right';
916 msg.insert_after = '#cs-title-options';
917 msg.id = 'editor';
918
919 if ( okay ) {
920 // Remove the Sidebar from the page.
921 csSidebars.right
922 .find('#' + id)
923 .closest('.widgets-holder-wrap')
924 .remove();
925
926 // Remove object from internal collection.
927 csSidebars.remove( id );
928
929 // show "Create a custom sidebar to get started." if it is
930 // needed.
931 if ( "delete" === resp.action ) {
932 window.csSidebars.showGetStartedBox();
933 }
934 } else {
935 msg.type = 'err';
936 }
937
938 wpmUi.message( msg );
939 }
940
941 // Deletes the sidebar and closes the confirmation popup.
942 function delete_sidebar() {
943 popup.loading( true );
944 ajax.reset()
945 .data({
946 'do': 'delete',
947 'sb': id,
948 '_wpnonce': $('#_wp_nonce_cs_delete_sidebar').val()
949 })
950 .ondone( handle_done )
951 .load_json();
952 }
953
954 // Show the REMOVE popup.
955 popup = wpmUi.popup()
956 .modal( true )
957 .size( 560, 160 )
958 .title( csSidebarsData.title_delete )
959 .content( csSidebars.delete_form )
960 .onshow( insert_name )
961 .show();
962
963 // Create new ajax object.
964 ajax = wpmUi.ajax( null, 'cs-ajax' );
965
966 popup.$().on( 'click', '.btn-cancel', close_popup );
967 popup.$().on( 'click', '.btn-delete', delete_sidebar );
968
969 return true;
970 },
971
972
973 /*==============================*\
974 ==================================
975 == ==
976 == LOCATION ==
977 == ==
978 ==================================
979 \*==============================*/
980
981 /**
982 * =====================================================================
983 * Show popup to assign sidebar to default categories.
984 *
985 * @since 2.0
986 */
987 showLocations: function( sb ){
988 var popup = null,
989 ajax = null,
990 form = null,
991 id = sb.getID();
992
993 /**
994 * (_) add new rule
995 *
996 * @since 3.2.0
997 */
998 function _add_new_rule( data, table ) {
999 var template = wp.template('custom-sidebars-new-rule-row');
1000 $('tbody', table ).append( template( data ) );
1001 $('tfoot', table).hide();
1002 $('tbody .dashicons-trash', table).on( 'click', function() {
1003 $(this).closest('tr').detach();
1004 if ( 0 === $('tbody tr', table ).length ) {
1005 $('tfoot', table).show();
1006 }
1007 });
1008 return false;
1009 }
1010
1011 // Display the location data after it was loaded by ajax.
1012 function handle_done_load( resp, okay, xhr ) {
1013 var theme_sb, opt, name, msg = {}; // Only used in error case.
1014
1015 popup.loading( false );
1016
1017 if ( ! okay ) {
1018 popup.destroy();
1019 csSidebars.showAjaxError( resp );
1020 return;
1021 }
1022
1023 // Display the sidebar name.
1024 popup.$().find( '.sb-name' ).text( resp.sidebar.name );
1025 var sb_id = resp.sidebar.id;
1026
1027 /**
1028 * hide message
1029 */
1030 popup.$().find('.message.no-sidebars').hide();
1031
1032 /**
1033 * Count sidebars
1034 */
1035 var visible_sidebars = 0;
1036
1037 // Only show settings for replaceable sidebars
1038 var sidebars = popup.$().find( '.cs-replaceable' );
1039 sidebars.hide();
1040 resp.replaceable = wpmUi.obj( resp.replaceable );
1041 for ( var key0 in resp.replaceable ) {
1042 if ( ! resp.replaceable.hasOwnProperty( key0 ) ) {
1043 continue;
1044 }
1045 sidebars.filter( '.' + resp.replaceable[key0] ).show();
1046 visible_sidebars++;
1047 }
1048
1049 /**
1050 * no visible_sidebars - show information about it
1051 */
1052 if ( 0 === visible_sidebars ) {
1053 popup.$().find( '.wpmui-box, .message, .button-primary' ).hide();
1054 popup.$().find('.message.no-sidebars').show().parent().addClass('notice notice-error').removeClass('hidden');
1055 }
1056
1057 // Add a new option to the replacement list.
1058 function _add_option( item, lists, key ) {
1059 var opt = jQuery( '<option></option>' );
1060 opt.attr( 'value', key ).text( item.name );
1061 lists.append( opt );
1062 }
1063
1064 // Check if the current sidebar is a replacement in the list.
1065 function _select_option( replacement, sidebar, key, lists ) {
1066 var row = lists
1067 .closest( '.cs-replaceable' )
1068 .filter('.' + sidebar),
1069 option = row
1070 .find( 'option[value="' + key + '"]' ),
1071 group = row.find( 'optgroup.used' ),
1072 check = row.find( '.detail-toggle' );
1073
1074 if ( replacement === sb_id ) {
1075 option.prop( 'selected', true );
1076 if ( true !== check.prop( 'checked' ) ) {
1077 check.prop( 'checked', true );
1078 row.addClass( 'open' );
1079
1080 // Upgrade the select list with chosen.
1081 wpmUi.upgrade_multiselect( row );
1082 }
1083 } else {
1084 if ( ! group.length ) {
1085 group = jQuery( '<optgroup class="used">' )
1086 .attr( 'label', row.data( 'lbl-used' ) )
1087 .appendTo( row.find( '.details select' ) );
1088 }
1089 option.detach().appendTo( group );
1090 }
1091 }
1092
1093 // ----- Category ----------------------------------------------
1094 // Refresh list for single categories and category archives.
1095 var lst_cat = popup.$().find( '.cs-datalist.cs-cat' );
1096 var lst_act = popup.$().find( '.cs-datalist.cs-arc-cat' );
1097 var data_cat = resp.categories;
1098 lst_act.empty();
1099 lst_cat.empty();
1100 // Add the options
1101 for ( var key1 in data_cat ) {
1102 _add_option( data_cat[ key1 ], lst_act, key1 );
1103 _add_option( data_cat[ key1 ], lst_cat, key1 );
1104 }
1105
1106 // Select options
1107 for ( var key2 in data_cat ) {
1108 if ( data_cat[ key2 ].single ) {
1109 for ( theme_sb in data_cat[ key2 ].single ) {
1110 _select_option(
1111 data_cat[ key2 ].single[ theme_sb ],
1112 theme_sb,
1113 key2,
1114 lst_cat
1115 );
1116 }
1117 }
1118 if ( data_cat[ key2 ].archive ) {
1119 for ( theme_sb in data_cat[ key2 ].archive ) {
1120 _select_option(
1121 data_cat[ key2 ].archive[ theme_sb ],
1122 theme_sb,
1123 key2,
1124 lst_act
1125 );
1126 }
1127 }
1128 }
1129
1130 // ----- Post Type ---------------------------------------------
1131 // Refresh list for single posttypes.
1132 var lst_pst = popup.$().find( '.cs-datalist.cs-pt' );
1133 var data_pst = resp.posttypes;
1134 lst_pst.empty();
1135 // Add the options
1136 for ( var key3 in data_pst ) {
1137 opt = jQuery( '<option></option>' );
1138 name = data_pst[ key3 ].name;
1139 opt.attr( 'value', key3 ).text( name );
1140 lst_pst.append( opt );
1141 }
1142
1143 // Select options
1144 for ( var key4 in data_pst ) {
1145 if ( data_pst[ key4 ].single ) {
1146 for ( theme_sb in data_pst[ key4 ].single ) {
1147 _select_option(
1148 data_pst[ key4 ].single[ theme_sb ],
1149 theme_sb,
1150 key4,
1151 lst_pst
1152 );
1153 }
1154 }
1155 }
1156
1157 // ----- Archives ----------------------------------------------
1158 // Refresh list for archive types.
1159 var lst_arc = popup.$().find( '.cs-datalist.cs-arc' );
1160 var data_arc = resp.archives;
1161 lst_arc.empty();
1162 // Add the options
1163 for ( var key5 in data_arc ) {
1164 opt = jQuery( '<option></option>' );
1165 name = data_arc[ key5 ].name;
1166 opt.attr( 'value', key5 ).text( name );
1167 lst_arc.append( opt );
1168 }
1169
1170 // Select options
1171 for ( var key6 in data_arc ) {
1172 if ( data_arc[ key6 ].archive ) {
1173 for ( theme_sb in data_arc[ key6 ].archive ) {
1174 _select_option(
1175 data_arc[ key6 ].archive[ theme_sb ],
1176 theme_sb,
1177 key6,
1178 lst_arc
1179 );
1180 }
1181 }
1182 }
1183
1184 // ----- Authors ----------------------------------------------
1185 // Refresh list for authors.
1186 var lst_aut = popup.$().find( '.cs-datalist.cs-arc-aut' );
1187 var data_aut = resp.authors;
1188 lst_aut.empty();
1189 // Add the options
1190 for ( var key7 in data_aut ) {
1191 opt = jQuery( '<option></option>' );
1192 name = data_aut[ key7 ].name;
1193 opt.attr( 'value', key7 ).text( name );
1194 lst_aut.append( opt );
1195 }
1196
1197 // Select options
1198 for ( var key8 in data_aut ) {
1199 if ( data_aut[ key8 ].archive ) {
1200 for ( theme_sb in data_aut[ key8 ].archive ) {
1201 _select_option(
1202 data_aut[ key8 ].archive[ theme_sb ],
1203 theme_sb,
1204 key8,
1205 lst_aut
1206 );
1207 }
1208 }
1209 }
1210
1211 // ----- 3rd part plugins ----------------------------------------------
1212 var lst_3rd = popup.$().find( '.cs-3rd-part .cs-datalist' );
1213 lst_3rd.each( function() {
1214 var data_3rd = resp[$(this).data('id')];
1215 $(this).empty();
1216 // Add the options
1217 for ( var key9 in data_3rd ) {
1218 opt = jQuery( '<option></option>' );
1219 name = data_3rd[ key9 ].name;
1220 opt.attr( 'value', key9 ).text( name );
1221 $(this).append( opt );
1222 }
1223 // Select options
1224 for ( var key10 in data_3rd ) {
1225 if ( data_3rd[ key10 ].archive ) {
1226 for ( theme_sb in data_3rd[ key10 ].archive ) {
1227 _select_option(
1228 data_3rd[ key10 ].archive[ theme_sb ],
1229 theme_sb,
1230 key10,
1231 $(this)
1232 );
1233 }
1234 }
1235 }
1236 });
1237
1238 /**
1239 * ----- Custom Taxomies ----------------------------------------------
1240 * @since 3.1.4
1241 */
1242 var lst_custom_taxonomies = popup.$().find( '.cf-custom-taxonomies .cs-datalist' );
1243 lst_custom_taxonomies.each( function() {
1244 var data_custom_taxonomy = resp[$(this).data('id')];
1245 $(this).empty();
1246 // Add the options
1247 for ( var key_custom_taxonomy in data_custom_taxonomy ) {
1248 opt = jQuery( '<option></option>' );
1249 name = data_custom_taxonomy[ key_custom_taxonomy ].name;
1250 opt.attr( 'value', key_custom_taxonomy ).text( name );
1251 $(this).append( opt );
1252 }
1253 // Select options
1254 for ( var key_custom_tax in data_custom_taxonomy ) {
1255 if ( data_custom_taxonomy[ key_custom_tax ].single ) {
1256 for ( theme_sb in data_custom_taxonomy[ key_custom_tax ].single ) {
1257 _select_option(
1258 data_custom_taxonomy[ key_custom_tax ].single[ theme_sb ],
1259 theme_sb,
1260 key_custom_tax,
1261 $(this)
1262 );
1263 }
1264 }
1265 }
1266 });
1267
1268 /**
1269 * ----- @media screen width ------------------------------------------
1270 *
1271 * @since 3.2.0
1272 */
1273 var table = popup.$().find('.csb-media-screen-width table' );
1274 $.each( resp.screen, function( size, value ) {
1275 $.each( value, function( minmax, mode ) {
1276 var data = {
1277 minmax: minmax,
1278 mode: mode,
1279 size: size
1280 };
1281 _add_new_rule( data, table );
1282 });
1283 });
1284
1285 } // end: handle_done_load()
1286
1287 // User clicks on "replace <sidebar> for <category>" checkbox.
1288 function toggle_details( ev ) {
1289 var inp = jQuery( this ),
1290 row = inp.closest( '.cs-replaceable' ),
1291 sel = row.find( 'select' );
1292
1293 if ( inp.prop( 'checked' ) ) {
1294 row.addClass( 'open' );
1295
1296 // Upgrade the select list with chosen.
1297 wpmUi.upgrade_multiselect( row );
1298
1299 // Tell the select list to render the contents again.
1300 sel.trigger( 'change.select2' );
1301 } else {
1302 row.removeClass( 'open' );
1303
1304 // Remove all selected options.
1305 sel.val( [] );
1306 }
1307 }
1308
1309 // After saving data via ajax is done.
1310 function handle_done_save( resp, okay, xhr ) {
1311 var msg = {};
1312
1313 popup.loading( false );
1314 popup.destroy();
1315
1316 msg.message = resp.message;
1317 // msg.details = resp;
1318 msg.parent = '#widgets-right';
1319 msg.insert_after = '#cs-title-options';
1320 msg.id = 'editor';
1321
1322 if ( ! okay ) {
1323 msg.type = 'err';
1324 }
1325
1326 wpmUi.message( msg );
1327 }
1328
1329 // Submit the data and close the popup.
1330 function save_data() {
1331 popup.loading( true );
1332 ajax.reset()
1333 .data( form )
1334 .ondone( handle_done_save )
1335 .load_json();
1336 }
1337
1338 /**
1339 * add new rule
1340 *
1341 * @since 3.2.0
1342 */
1343 function add_new_rule() {
1344 var table = $('table', $(this).parent());
1345 var data = {
1346 minmax: 'max',
1347 mode: 'hide',
1348 size: 0
1349 };
1350 _add_new_rule( data, table );
1351 return false;
1352 }
1353
1354 // Show the LOCATION popup.
1355 popup = wpmUi.popup()
1356 .modal( true )
1357 .size( 782, 560 )
1358 .title( csSidebarsData.title_location )
1359 .content( csSidebars.location_form )
1360 .show();
1361
1362 popup.loading( true );
1363 form = popup.$().find( '.frm-location' );
1364 form.find( '.sb-id' ).val( id );
1365
1366 // Initialize ajax object.
1367 ajax = wpmUi.ajax( null, 'cs-ajax' );
1368 ajax.reset()
1369 .data({
1370 'do': 'get-location',
1371 'sb': id
1372 })
1373 .ondone( handle_done_load )
1374 .load_json();
1375
1376 // Attach events.
1377 popup.$().on( 'click', '.detail-toggle', toggle_details );
1378 popup.$().on( 'click', '.btn-save', save_data );
1379 popup.$().on( 'click', '.btn-cancel', popup.destroy );
1380 popup.$().on( 'click', '.btn-add-rule', add_new_rule );
1381
1382 return true;
1383 },
1384
1385 /*======================================*\
1386 ==========================================
1387 == ==
1388 == REPLACEABLE FLAG ==
1389 == ==
1390 ==========================================
1391 \*======================================*/
1392
1393 /**
1394 * =====================================================================
1395 * Change the replaceable flag
1396 *
1397 * @since 1.0.0
1398 */
1399 setReplaceable: function( sb, state, do_ajax ) {
1400 var ajax,
1401 theme_sb = csSidebars.right.find( '.sidebars-column-2 .widgets-holder-wrap' ),
1402 the_bar = jQuery( sb.sb ).closest( '.widgets-holder-wrap' ),
1403 chk = the_bar.find( '.cs-toolbar .chk-replaceable' ),
1404 marker = the_bar.find( '.replace-marker' ),
1405 btn_replaceable = the_bar.find( '.cs-toolbar .btn-replaceable' );
1406
1407 // After changing a sidebars "replaceable" flag.
1408 function handle_done_replaceable( resp, okay, xhr ) {
1409 // Adjust the "replaceable" flag to match the data returned by the ajax request.
1410 if ( resp instanceof Object && typeof resp.replaceable === 'object' ) {
1411 csSidebarsData.replaceable = wpmUi.obj( resp.replaceable );
1412
1413 theme_sb.find( '.widgets-sortables' ).each(function() {
1414 var _state = false,
1415 _me = jQuery( this ),
1416 _id = _me.attr( 'id' ),
1417 _sb = csSidebars.find( _id );
1418
1419 for ( var key in csSidebarsData.replaceable ) {
1420 if ( ! csSidebarsData.replaceable.hasOwnProperty( key ) ) {
1421 continue;
1422 }
1423 if ( csSidebarsData.replaceable[key] === _id ) {
1424 _state = true;
1425 break;
1426 }
1427 }
1428 csSidebars.setReplaceable( _sb, _state, false );
1429 });
1430 }
1431
1432 // Enable the checkboxes again after the ajax request is handled.
1433 theme_sb.find( '.cs-toolbar .chk-replaceable' ).prop( 'disabled', false );
1434 theme_sb.find( '.cs-toolbar .btn-replaceable' ).removeClass( 'wpmui-loading' );
1435 }
1436
1437 if ( undefined === state ) { state = chk.prop( 'checked' ); }
1438 if ( undefined === do_ajax ) { do_ajax = true; }
1439
1440 if ( chk.data( 'active' ) === state ) {
1441 return false;
1442 }
1443 chk.data( 'active', state );
1444 chk.prop( 'checked', state );
1445
1446 if ( state ) {
1447 if ( ! marker.length ) {
1448 jQuery( '<div></div>' )
1449 .appendTo( the_bar )
1450 .attr( 'data-label', csSidebarsData.lbl_replaceable )
1451 .addClass( 'replace-marker' );
1452 }
1453 the_bar.addClass( 'replaceable' );
1454 } else {
1455 marker.remove();
1456 the_bar.removeClass( 'replaceable' );
1457 }
1458
1459 if ( do_ajax ) {
1460 // Disable the checkbox until ajax request is done.
1461 theme_sb.find( '.cs-toolbar .chk-replaceable' ).prop( 'disabled', true );
1462 theme_sb.find( '.cs-toolbar .btn-replaceable' ).addClass( 'wpmui-loading' );
1463
1464 ajax = wpmUi.ajax( null, 'cs-ajax' );
1465 ajax.reset()
1466 .data({
1467 'do': 'replaceable',
1468 'state': state,
1469 'sb': sb.getID()
1470 })
1471 .ondone( handle_done_replaceable )
1472 .load_json();
1473 }
1474
1475 /**
1476 * This function is called by csSidebars.handleAction. Return value
1477 * False means that the default click event should be executed after
1478 * this function was called.
1479 */
1480 return false;
1481 },
1482
1483 /*=============================*\
1484 =================================
1485 == ==
1486 == HELPERS ==
1487 == ==
1488 =================================
1489 \*=============================*/
1490
1491 /**
1492 * =====================================================================
1493 * Find the specified CsSidebar object.
1494 *
1495 * @since 1.0.0
1496 */
1497 find: function(id){
1498 return csSidebars.sidebars[id];
1499 },
1500
1501 /**
1502 * =====================================================================
1503 * Create a new CsSidebar object.
1504 *
1505 * @since 1.0.0
1506 */
1507 add: function(id, type){
1508 csSidebars.sidebars[id] = new CsSidebar(id, type);
1509 return csSidebars.sidebars[id];
1510 },
1511
1512 /**
1513 * =====================================================================
1514 * Removes a new CsSidebar object.
1515 *
1516 * @since 2.0
1517 */
1518 remove: function(id){
1519 delete csSidebars.sidebars[id];
1520 },
1521
1522 /**
1523 * =====================================================================
1524 * Returns true when the specified ID is recognized as a sidebar
1525 * that was created by the custom sidebars plugin.
1526 *
1527 * @since 2.0
1528 */
1529 isCustomSidebar: function( el ) {
1530 var id = jQuery( el ).attr('id'),
1531 prefix = id.substr(0, csSidebars.sidebar_prefix.length);
1532
1533 return prefix === csSidebars.sidebar_prefix;
1534 },
1535
1536 /**
1537 * =====================================================================
1538 * Append the specified sidebar ID to the label and input element.
1539 *
1540 * @since 2.0
1541 */
1542 addIdToLabel: function( $obj, id ){
1543 if ( true !== $obj.data( 'label-done' ) ) {
1544 var prefix = $obj.attr('for');
1545 $obj.attr( 'for', prefix + id );
1546 $obj.find( '.has-label' ).attr( 'id', prefix + id );
1547 $obj.data( 'label-done', true );
1548 }
1549 },
1550
1551 /**
1552 * =====================================================================
1553 * Returns the sidebar ID based on the sidebar DOM object.
1554 *
1555 * @since 2.0
1556 * @param jQuery $obj Any DOM object inside the Sidebar HTML structure.
1557 * @return string The sidebar ID
1558 */
1559 getIdFromEditbar: function( $obj ){
1560 var wrapper = $obj.closest( '.widgets-holder-wrap' ),
1561 sb = wrapper.find( '.widgets-sortables:first' ),
1562 id = sb.attr( 'id' );
1563 return id;
1564 },
1565
1566 /**
1567 * =====================================================================
1568 * Show "Create a custom sidebar to get started." box.
1569 *
1570 * @since 3.0.4
1571 */
1572 showGetStartedBox: function() {
1573 if ( 0 === $(".sidebars-column-1 .inner .widgets-holder-wrap").length ) {
1574 var template = wp.template('custom-sidebars-new');
1575 $(".sidebars-column-1 .inner").before( template() );
1576 $(".custom-sidebars-add-new").on( "click", function() {
1577 $( "button.btn-create-sidebar" ).click();
1578 });
1579 }
1580 }
1581 };
1582
1583 jQuery(function($){
1584 $('#csfooter').hide();
1585 if ( $('#widgets-right').length > 0 ) {
1586 csSidebars.init();
1587 }
1588 $('.defaultsContainer').hide();
1589
1590 $( '#widgets-right .widgets-sortables' ).on( "sort", function(event, ui) {
1591 var topx = $('#widgets-right').top;
1592 ui.position.top = - $('#widgets-right').css('top');
1593 });
1594 });
1595 /**
1596 * add new sidebar placeholder
1597 */
1598 jQuery(document).ready( function($) {
1599 window.setTimeout( function() {
1600 window.csSidebars.showGetStartedBox();
1601 }, 1000);
1602 });
1603 })(jQuery);
1604
1605 /**
1606 * jQuery.fn.sortElements
1607 * --------------
1608 * @param Function comparator:
1609 * Exactly the same behaviour as [1,2,3].sort(comparator)
1610 *
1611 * @param Function getSortable
1612 * A function that should return the element that is
1613 * to be sorted. The comparator will run on the
1614 * current collection, but you may want the actual
1615 * resulting sort to occur on a parent or another
1616 * associated element.
1617 *
1618 * E.g. $('td').sortElements(comparator, function(){
1619 * return this.parentNode;
1620 * })
1621 *
1622 * The <td>'s parent (<tr>) will be sorted instead
1623 * of the <td> itself.
1624 *
1625 * @see http://james.padolsey.com/javascript/sorting-elements-with-jquery/
1626 */
1627 jQuery.fn.sortElements = (function(){
1628 var sort = [].sort;
1629 return function(comparator, getSortable) {
1630 getSortable = getSortable || function(){return this;};
1631 var placements = this.map(function(){
1632 var sortElement = getSortable.call(this),
1633 parentNode = sortElement.parentNode,
1634 // Since the element itself will change position, we have
1635 // to have some way of storing its original position in
1636 // the DOM. The easiest way is to have a 'flag' node:
1637 nextSibling = parentNode.insertBefore(
1638 document.createTextNode(''),
1639 sortElement.nextSibling
1640 );
1641 return function() {
1642 if (parentNode === this) {
1643 throw new Error(
1644 "You can't sort elements if any one is a descendant of another."
1645 );
1646 }
1647 // Insert before flag:
1648 parentNode.insertBefore(this, nextSibling);
1649 // Remove flag:
1650 parentNode.removeChild(nextSibling);
1651 };
1652 });
1653 return sort.call(this, comparator).each(function(i){
1654 placements[i].call(getSortable.call(this));
1655 });
1656 };
1657 })();
1658
1659
1660 /*global console:false */
1661 /*global document:false */
1662 /*global ajaxurl:false */
1663 (function($){
1664 jQuery(document).ready( function($) {
1665 $('#screen-options-wrap .cs-allow-author input[type=checkbox]').on( 'change', function() {
1666 var data = {
1667 'action': 'custom_sidebars_allow_author',
1668 '_wpnonce': $('#custom_sidebars_allow_author').val(),
1669 'value': this.checked
1670 };
1671 $.post( ajaxurl, data );
1672 });
1673 });
1674 })(jQuery);
1675
1676 /*global console:false */
1677 /*global document:false */
1678 /*global ajaxurl:false */
1679
1680 /**
1681 * Handle "Custom sidebars configuration is allowed for:" option on
1682 * widgets screen options.
1683 */
1684 (function($){
1685 jQuery(document).ready( function($) {
1686 $('#screen-options-wrap .cs-custom-taxonomies input[type=checkbox]').on( 'change', function() {
1687 var data = {
1688 'action': 'custom_sidebars_metabox_custom_taxonomies',
1689 '_wpnonce': $('#custom_sidebars_custom_taxonomies').val(),
1690 'fields': {}
1691 };
1692 $('#screen-options-wrap .cs-custom-taxonomies input[type=checkbox]').each( function() {
1693 data.fields[$(this).val()] = this.checked;
1694 });
1695 $.post( ajaxurl, data );
1696 });
1697 });
1698 })(jQuery);
1699
1700 /*global console:false */
1701 /*global document:false */
1702 /*global ajaxurl:false */
1703
1704 /**
1705 * Handle "Custom sidebars configuration is allowed for:" option on
1706 * widgets screen options.
1707 */
1708 (function($){
1709 jQuery(document).ready( function($) {
1710 $('#screen-options-wrap .cs-roles input[type=checkbox]').on( 'change', function() {
1711 var data = {
1712 'action': 'custom_sidebars_metabox_roles',
1713 '_wpnonce': $('#custom_sidebars_metabox_roles').val(),
1714 'fields': {}
1715 };
1716 $('#screen-options-wrap .cs-roles input[type=checkbox]').each( function() {
1717 data.fields[$(this).val()] = this.checked;
1718 });
1719 $.post( ajaxurl, data );
1720 });
1721 });
1722 })(jQuery);
1723