PluginProbe ʕ •ᴥ•ʔ
Custom Sidebars – Dynamic Sidebar Classic Widget Area Manager / 3.0.7.1
Custom Sidebars – Dynamic Sidebar Classic Widget Area Manager v3.0.7.1
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 / js / cs-cloning.js
custom-sidebars / js Last commit date
cs-cloning.js 9 years ago cs-cloning.min.js 9 years ago cs-visibility.js 9 years ago cs-visibility.min.js 9 years ago cs.js 9 years ago cs.min.js 9 years ago
cs-cloning.js
319 lines
1 /*! Custom Sidebars - v3.0.7.1
2 * https://premium.wpmudev.org/project/custom-sidebars-pro/
3 * Copyright (c) 2017; * Licensed GPLv2+ */
4 /*global jQuery:false */
5 /*global window:false */
6 /*global document:false */
7 /*global wp:false */
8 /*global wpmUi:false */
9
10 jQuery(function init_cloning() {
11 var $doc = jQuery( document ),
12 $all = jQuery( '#widgets-right' ),
13 is_cloning = false;
14
15 /**
16 * Moves the "Clone" button next to the save button.
17 */
18 var init_widget = function init_widget( ev, el ) {
19 var $widget = jQuery( el ).closest( '.widget' ),
20 $btn = $widget.find( '.csb-clone-button' ),
21 $target = $widget.find( '.widget-control-actions .widget-control-save' ),
22 $spinner = $widget.find( '.widget-control-actions .spinner' ),
23 $btn_save = $widget.find( '.widget-control-save' );
24
25 if ( $widget.data( '_csb_cloning' ) ) {
26 return;
27 }
28
29 $spinner.insertBefore( $target ).css({ 'float': 'left' });
30 $btn.insertBefore( $target ).click( clone_widget );
31 $btn_save.click( prepare_update_group );
32
33 $widget.data( '_csb_cloning', true );
34 };
35
36 /**
37 * Updates the group-counter when a widget is added.
38 */
39 var update_group_counter = function update_group_counter( ev, el ) {
40 // We do NOT want to change the group-id when we clone a widget...
41 if ( is_cloning ) { return false; }
42
43 var $widget = jQuery( el ).closest( '.widget' ),
44 $widget_group = $widget.find( 'input.csb-clone-group' ),
45 group_id = parseInt( $widget_group.val() ),
46 check = null;
47
48 do {
49 check = $all.find( 'input.csb-clone-group[value="' + group_id + '"]' );
50 if ( ! check.length || ( 1 === check.length && check[0] === $widget_group[0] ) ) {
51 break;
52 } else {
53 group_id += 1;
54 }
55 }
56 while ( true );
57
58 $widget_group.val( group_id );
59 update_template_groups();
60 };
61
62 /**
63 * Updates all group_id values for the widget-templates to the next free id.
64 */
65 var update_template_groups = function update_template_groups() {
66 var $groups = jQuery( '#widgets-left input.csb-clone-group' ),
67 next_id = parseInt( $groups.first().val() );
68
69 while ( $all.find( 'input.csb-clone-group[value="' + next_id + '"]' ).length ) {
70 next_id += 1;
71 }
72
73 $groups.val( next_id );
74 };
75
76 /**
77 * Viually highlights all widgets of the same group.
78 */
79 var mark_group = function mark_group( ev ) {
80 var $widget = jQuery( this ).closest( '.widget' ),
81 group_id = $widget.find( 'input.csb-clone-group' ).val(),
82 $members = $all.find( 'input.csb-clone-group[value="' + group_id + '"]' ).closest( '.widget' );
83
84 if ( isNaN( group_id ) || group_id < 1 ) {
85 return;
86 }
87
88 $members.addClass('csb-marker');
89 $widget.removeClass('csb-marker');
90 };
91
92 /**
93 * Removes the visual highlighting of group widgets.
94 */
95 var unmark_group = function unmark_group( ev ) {
96 var $marked = jQuery( '.widget.csb-marker' );
97 $marked.removeClass('csb-marker');
98 };
99
100 /**
101 * Adds icons to all widgets that are inside a group.
102 */
103 var init_group_icons = function init_group_icons() {
104 var $groups = $all.find( 'input.csb-clone-group' );
105
106 $groups.each(function() {
107 var group_id = jQuery( this ).val(),
108 $members = $all.find( 'input.csb-clone-group[value="' + group_id + '"]' ).closest( '.widget' ),
109 $titles = $members.find( '.widget-title h4, .widget-title h3' ),
110 action = 'add';
111
112 if ( isNaN( group_id ) || group_id < 1 ) {
113 action = 'remove';
114 }
115 if ( $members.length < 2 ) {
116 action = 'remove';
117 }
118
119 // Always remove the icons from the group.
120 $titles.removeClass( 'csb-group group-active' )
121 .find( '.btn-clone-group' ).remove();
122 $members.removeAttr( 'data-csb-icon' );
123
124 // If action is "add" then we add the icons again.
125 if ( action === 'add' ) {
126 $titles.addClass( 'csb-group group-active' )
127 .prepend( '<i class="dashicons dashicons-admin-links btn-clone-group"></i> ' );
128 $titles.find( '.btn-clone-group' )
129 .hover( mark_group, unmark_group )
130 .click( toggle_group );
131 }
132 });
133 };
134
135 /**
136 * Remove widget from group/assign to group again (only works until widget
137 * was saved.)
138 */
139 var toggle_group = function toggle_group( ev ) {
140 var $widget = jQuery( this ).closest( '.widget' ),
141 $title = $widget.find( '.widget-title h4' ),
142 $icon = $title.find( '.btn-clone-group' ),
143 $group = $widget.find( 'input.csb-clone-group' );
144
145 ev.preventDefault();
146 ev.stopPropagation();
147 if ( $title.hasClass( 'group-active' ) ) {
148 $title.removeClass( 'group-active' );
149 $icon.removeClass('dashicons-admin-links').addClass('dashicons-editor-unlink');
150 $group.data( 'group', $group.val() );
151 $group.val( 0 );
152 unmark_group();
153 } else {
154 $title.addClass( 'group-active' );
155 $icon.addClass('dashicons-admin-links').removeClass('dashicons-editor-unlink');
156 $group.val( $group.data( 'group' ) );
157 mark_group.call( this, [ev] );
158 }
159 return false;
160 };
161
162 /**
163 * Clones the widget:
164 * Add a new widget using default WordPress JS API and then update all the
165 * input values of the new widget to match the original widget.
166 */
167 var clone_widget = function clone_widget( ev ) {
168 var $widget = jQuery( this ).closest( '.widget' ),
169 $available = jQuery( '#widgets-left' ),
170 $chooser = jQuery( '.widgets-chooser' ),
171 $content = jQuery( '#wpbody-content' );
172
173 ev.preventDefault();
174 is_cloning = true;
175
176 // 1. If the current widget is new then first save the current widget
177 var state = $widget.find( 'input.csb-clone-state' ).val();
178 if ( 'new' === state ) {
179 window.wpWidgets.save( $widget, 0, 0, 0 );
180 }
181
182 // 2. Close any open chooser
183 window.wpWidgets.clearWidgetSelection();
184 $chooser.slideUp( 200, function() {
185 $chooser.hide();
186 $content.append( this );
187 });
188
189 // 3. Find the "widget-in-question".
190 var class_name = $widget.find('input.id_base').val(),
191 $base = $available.find('input.id_base[value="' + class_name + '"]'),
192 $in_question = $base.closest( '.widget' );
193 $in_question.addClass( 'widget-in-question' );
194
195 // 4. Provide data about the origin widget.
196 var group_id = $widget.find( 'input.csb-clone-group' ).val(),
197 $contr = $in_question.find( '.widget-control-actions' ),
198 $group = $in_question.find( 'input.csb-clone-group' ),
199 $state = $in_question.find( 'input.csb-clone-state' );
200 $group.val( group_id );
201 $state.val( 'empty' );
202
203 // 5. Select the current sidebar in the chooser.
204 var $sidebar = $widget.closest( '.widgets-sortables' ),
205 sb_id = $sidebar.attr( 'id' );
206 $chooser.find ( '.widgets-chooser-selected' ).removeClass( 'widgets-chooser-selected' );
207 $chooser.find( 'li' ).each( function() {
208 var $li = jQuery( this );
209 if ( sb_id === $li.data('sidebarId') ) {
210 $li.addClass( 'widgets-chooser-selected' ).focus();
211 }
212 });
213
214 // 6. Add the new widget to the sidebar.
215 // This will directly trigger the ajax command to save the widget.
216 window.wpWidgets.addWidget( $chooser );
217
218 // 7. Remove the custom elements and information again.
219 window.wpWidgets.clearWidgetSelection();
220 update_template_groups();
221
222 is_cloning = false;
223
224 return false;
225 };
226
227 /**
228 * Saves the specified widget if the clone-state is "empty".
229 */
230 var populate_widget = function populate_widget( $widget ) {
231 var $state = $widget.find( 'input.csb-clone-state' );
232
233 if ( $state.val() === 'empty' ) {
234 $widget.addClass( 'wpmui-loading' );
235 window.wpWidgets.save( $widget, 0, 1, 0 );
236 }
237 };
238
239 /**
240 * Update all widgets belonging to the same group.
241 */
242 var prepare_update_group = function prepare_update_group( ev ) {
243 var $widget = jQuery( this ).closest( '.widget' ),
244 group_id = $widget.find( 'input.csb-clone-group' ).val(),
245 $members = $all.find( 'input.csb-clone-group[value="' + group_id + '"]' ).closest( '.widget' ).not( $widget );
246
247 $members.each(function() {
248 var $item = jQuery( this ),
249 $state = $item.find( 'input.csb-clone-state' );
250
251 $item.addClass('wpmui-loading').attr( 'data-reload', true );
252 });
253 };
254
255 /**
256 * Update all widgets belonging to the same group.
257 */
258 var update_group_widgets = function update_group_widgets( el ) {
259 var $widgets = $all.find( '.widget[data-reload]' );
260
261 $widgets.each(function() {
262 var $item = jQuery( this ),
263 $state = $item.find( 'input.csb-clone-state' );
264
265 $state.val( 'empty' );
266 $item.removeAttr( 'data-reload' );
267 window.wpWidgets.save( $item, 0, 0, 0 );
268 });
269 };
270
271 /**
272 * Global ajax observer reacts to all ajax responses. We need this to find
273 * out when a new widget is saved for the first time.
274 */
275 var ajax_observer = function ajax_observer( ev, xhr, opt, resp ) {
276 var data = ( 'string' === typeof opt.data ? opt.data : '' ),
277 find_action = data.match( /^.*&action=([^&]+).*$/ ),
278 find_widget = data.match( /^.*&widget-id=([^&]+).*$/ ),
279 action = (find_action && find_action.length === 2 ? find_action[1] : ''),
280 widget = (find_widget && find_widget.length === 2 ? find_widget[1] : '');
281
282 if ( ! widget.length ) {
283 return;
284 }
285
286 var $base = jQuery( '.widget input.widget-id[value="' + widget + '"]' ),
287 $widget = $base.closest( '.widget' );
288
289 switch ( action ) {
290 case 'save-widget':
291 $widget.removeClass( 'wpmui-loading' );
292 if ( ! resp.length ) {
293 // Populate widget with data from group, if required.
294 populate_widget( $widget );
295 } else if ( resp.match( /^deleted:/ ) ) {
296 // Widget was deleted and is removed with animation.
297 window.setTimeout( init_group_icons, 400 );
298 } else {
299 // Existing widget was updated.
300 init_group_icons();
301 update_group_widgets( $widget );
302 }
303 break;
304
305 default:
306 // Unrelated ajax event.
307 }
308 };
309
310
311 $all.find( '.widget' ).each( init_widget );
312 $doc.on( 'widget-added', init_widget );
313 $doc.on( 'widget-added', update_group_counter );
314 $doc.ajaxSuccess( ajax_observer );
315
316 init_group_icons();
317 update_template_groups();
318 });
319