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