Ticket #27491: 27491.diff
File 27491.diff, 12.7 KB (added by , 11 years ago) |
---|
-
src/wp-admin/css/customize-widgets.css
diff --git src/wp-admin/css/customize-widgets.css src/wp-admin/css/customize-widgets.css index f8530a1..9d3fdf3 100644
37 37 .customize-control-widget_form.previewer-loading .spinner { 38 38 opacity: 1.0; 39 39 } 40 .customize-control-widget_form.widget-form-disabled .widget-content { 41 opacity: 0.7; 42 pointer-events: none; 43 -moz-user-select: none; 44 -webkit-user-select: none; 45 -ms-user-select: none; 46 user-select: none; 47 } 40 48 41 49 .customize-control-widget_form .widget { 42 50 margin-bottom: 0; -
src/wp-admin/js/customize-widgets.js
diff --git src/wp-admin/js/customize-widgets.js src/wp-admin/js/customize-widgets.js index 43233a7..d1a2d57 100644
var WidgetCustomizer = ( function ($) { 8 8 Sidebar, 9 9 SidebarCollection, 10 10 OldPreviewer, 11 builtin_form_update_handlers, 11 12 customize = wp.customize, self = { 12 13 update_widget_ajax_action: null, 13 14 update_widget_nonce_value: null, … … var WidgetCustomizer = ( function ($) { 136 137 self.registered_sidebars = new SidebarCollection( self.registered_sidebars ); 137 138 138 139 /** 140 * Handlers for the widget-form-update event, organized by widget ID base. 141 * Other widgets may provide their own update handlers by adding 142 * listeners for the widget-form-update event. 143 */ 144 builtin_form_update_handlers = { 145 146 /** 147 * @param {jQuery.Event} e 148 * @param {String} args.widget_id 149 * @param {String} args.widget_id_base 150 * @param {String} args.new_form 151 * @param {Boolean} args.hard 152 * @param {wp.customize.controlConstructor.widget_form} args.customize_control 153 */ 154 rss: function ( e, args ) { 155 var old_widget_error = args.customize_control.container.find( '.widget-error:first' ), 156 new_widget_error = $( '<div>' + args.new_form + '</div>' ).find( '.widget-error:first' ); 157 158 if ( old_widget_error.length && new_widget_error.length ) { 159 old_widget_error.replaceWith( new_widget_error ); 160 } else if ( old_widget_error.length ) { 161 old_widget_error.remove(); 162 } else if ( new_widget_error.length ) { 163 args.customize_control.container.find( '.widget-content:first' ).prepend( new_widget_error ); 164 } 165 } 166 }; 167 168 /** 139 169 * On DOM ready, initialize some meta functionality independent of specific 140 170 * customizer controls. 141 171 */ … … var WidgetCustomizer = ( function ($) { 629 659 control._setupHighlightEffects(); 630 660 control._setupUpdateUI(); 631 661 control._setupRemoveUI(); 632 control.hook( 'init' );633 },634 635 /**636 * Hooks for widgets to support living in the customizer control637 */638 hooks: {639 _default: {},640 rss: {641 formUpdated: function ( serialized_form ) {642 var control = this,643 old_widget_error = control.container.find( '.widget-error:first' ),644 new_widget_error = serialized_form.find( '.widget-error:first' );645 646 if ( old_widget_error.length && new_widget_error.length ) {647 old_widget_error.replaceWith( new_widget_error );648 } else if ( old_widget_error.length ) {649 old_widget_error.remove();650 } else if ( new_widget_error.length ) {651 control.container.find( '.widget-content' ).prepend( new_widget_error );652 }653 }654 }655 },656 657 /**658 * Trigger an 'action' which a specific widget type can handle659 *660 * @param name661 */662 hook: function ( name ) {663 var args = Array.prototype.slice.call( arguments, 1 ), handler;664 665 if ( this.hooks[this.params.widget_id_base] && this.hooks[this.params.widget_id_base][name] ) {666 handler = this.hooks[this.params.widget_id_base][name];667 } else if ( this.hooks._default[name] ) {668 handler = this.hooks._default[name];669 }670 if ( handler ) {671 handler.apply( this, args );672 }673 662 }, 674 663 675 664 /** … … var WidgetCustomizer = ( function ($) { 687 676 688 677 control._update_count = 0; 689 678 control.is_widget_updating = false; 679 control.live_update_mode = true; 690 680 691 681 // Update widget whenever model changes 692 682 control.setting.bind( function( to, from ) { … … var WidgetCustomizer = ( function ($) { 967 957 var control = this, 968 958 widget_content, 969 959 save_btn, 970 update_widget_debounced; 960 update_widget_debounced, 961 form_update_event_handler; 971 962 972 963 widget_content = control.container.find( '.widget-content' ); 973 964 … … var WidgetCustomizer = ( function ($) { 978 969 save_btn.removeClass( 'button-primary' ).addClass( 'button-secondary' ); 979 970 save_btn.on( 'click', function ( e ) { 980 971 e.preventDefault(); 981 control.updateWidget( );972 control.updateWidget( { disable_form: true } ); 982 973 } ); 983 974 984 975 update_widget_debounced = _.debounce( function () { … … var WidgetCustomizer = ( function ($) { 996 987 997 988 // Handle widgets that support live previews 998 989 widget_content.on( 'change input propertychange', ':input', function ( e ) { 999 if ( e.type === 'change' ) { 1000 control.updateWidget(); 1001 } else if ( this.checkValidity && this.checkValidity() ) { 1002 update_widget_debounced(); 990 if ( control.live_update_mode ) { 991 if ( e.type === 'change' ) { 992 control.updateWidget(); 993 } else if ( this.checkValidity && this.checkValidity() ) { 994 update_widget_debounced(); 995 } 1003 996 } 1004 997 } ); 1005 998 … … var WidgetCustomizer = ( function ($) { 1018 1011 var is_rendered = !! rendered_widgets[control.params.widget_id]; 1019 1012 control.container.toggleClass( 'widget-rendered', is_rendered ); 1020 1013 } ); 1014 1015 form_update_event_handler = builtin_form_update_handlers[ control.params.widget_id_base ]; 1016 if ( form_update_event_handler ) { 1017 control.container.find( '.widget:first' ).on( 'widget-form-update', form_update_event_handler ); 1018 } 1021 1019 }, 1022 1020 1023 1021 /** … … var WidgetCustomizer = ( function ($) { 1147 1145 var control = this, 1148 1146 instance_override, 1149 1147 complete_callback, 1148 widget_root, 1150 1149 update_number, 1151 1150 widget_content, 1152 element_id_to_refocus = null,1153 active_input_selection_start = null,1154 active_input_selection_end = null,1155 1151 params, 1156 1152 data, 1157 1153 inputs, … … var WidgetCustomizer = ( function ($) { 1170 1166 control._update_count += 1; 1171 1167 update_number = control._update_count; 1172 1168 1173 widget_content = control.container.find( '.widget-content' ); 1174 1175 // @todo Support more selectors than IDs? 1176 if ( $.contains( control.container[0], document.activeElement ) && $( document.activeElement ).is( '[id]' ) ) { 1177 element_id_to_refocus = $( document.activeElement ).prop( 'id' ); 1178 // @todo IE8 support: http://stackoverflow.com/a/4207763/93579 1179 try { 1180 active_input_selection_start = document.activeElement.selectionStart; 1181 active_input_selection_end = document.activeElement.selectionEnd; 1182 } 1183 catch( e ) {} // catch InvalidStateError in case of checkboxes 1184 } 1169 widget_root = control.container.find( '.widget:first' ); 1170 widget_content = control.container.find( '.widget-content:first' ); 1185 1171 1186 1172 control.container.addClass( 'widget-form-loading' ); 1187 1173 control.container.addClass( 'previewer-loading' ); 1188 1174 processing = wp.customize.state( 'processing' ); 1189 1175 processing( processing() + 1 ); 1190 1176 1177 if ( ! control.live_update_mode ) { 1178 control.container.addClass( 'widget-form-disabled' ); 1179 } 1180 1191 1181 params = {}; 1192 1182 params.action = self.update_widget_ajax_action; 1193 1183 params.wp_customize = 'on'; … … var WidgetCustomizer = ( function ($) { 1217 1207 sanitized_form, 1218 1208 sanitized_inputs, 1219 1209 has_same_inputs_in_response, 1220 is_instance_identical; 1210 no_setting_change, 1211 is_live_update_aborted = false, 1212 event_data; 1221 1213 1222 1214 if ( r.success ) { 1223 1215 sanitized_form = $( '<div>' + r.data.form + '</div>' ); 1224 1225 control.hook( 'formUpdate', sanitized_form );1226 1227 1216 sanitized_inputs = sanitized_form.find( ':input, option' ); 1228 1217 has_same_inputs_in_response = control._getInputsSignature( inputs ) === control._getInputsSignature( sanitized_inputs ); 1229 1218 1230 if ( has_same_inputs_in_response ) {1219 if ( has_same_inputs_in_response && control.live_update_mode ) { 1231 1220 inputs.each( function ( i ) { 1232 1221 var input = $( this ), 1233 1222 sanitized_input = $( sanitized_inputs[i] ), 1234 1223 property = control._getInputStatePropertyName( this ), 1235 s tate,1224 submitted_state, 1236 1225 sanitized_state; 1237 1226 1238 s tate = input.data( 'state' + update_number );1227 submitted_state = input.data( 'state' + update_number ); 1239 1228 sanitized_state = sanitized_input.prop( property ); 1240 1229 input.data( 'sanitized', sanitized_state ); 1230 event_data = { 1231 'sanitized_state': sanitized_state, 1232 'submitted_state': submitted_state, 1233 'customize_control': control 1234 }; 1241 1235 1242 if ( s tate !== sanitized_state ) {1236 if ( submitted_state !== sanitized_state ) { 1243 1237 1244 1238 // Only update now if not currently focused on it, 1245 1239 // so that we don't cause the cursor 1246 1240 // it will be updated upon the change event 1247 1241 if ( args.ignore_active_element || ! input.is( document.activeElement ) ) { 1248 1242 input.prop( property, sanitized_state ); 1243 input.trigger( 'widget-sanitary-field', [ event_data ] ); 1244 } else { 1245 input.trigger( 'widget-unsanitary-field', [ event_data ] ); 1249 1246 } 1250 control.hook( 'unsanitaryField', input, sanitized_state, state );1251 1247 1252 1248 } else { 1253 control.hook( 'sanitaryField', input, state);1249 input.trigger( 'widget-sanitary-field', [ event_data ] ); 1254 1250 } 1255 1251 } ); 1256 control.hook( 'formUpdated', sanitized_form ); 1252 1253 } else if ( control.live_update_mode ) { 1254 control.live_update_mode = false; 1255 control.container.find( 'input[name="savewidget"]' ).show(); 1256 is_live_update_aborted = true; 1257 1257 } else { 1258 widget_content.html( sanitized_form.html() ); 1259 if ( element_id_to_refocus ) { 1260 // not using jQuery selector so we don't have to worry about escaping IDs with brackets and other characters 1261 $( document.getElementById( element_id_to_refocus ) ) 1262 .prop( { 1263 selectionStart: active_input_selection_start, 1264 selectionEnd: active_input_selection_end 1265 } ) 1266 .focus(); 1267 } 1268 control.hook( 'formRefreshed' ); 1258 widget_content.html( r.data.form ); 1259 control.container.removeClass( 'widget-form-disabled' ); 1260 } 1261 1262 if ( ! is_live_update_aborted ) { 1263 event_data = { 1264 'widget_id': control.params.widget_id, 1265 'widget_id_base': control.params.widget_id_base, 1266 'new_form': r.data.form, 1267 'hard': ! control.live_update_mode, // dynamic fields may need to be re-initialized (e.g. Chosen) 1268 'customize_control': control 1269 }; 1270 widget_root.trigger( 'widget-form-update', [ event_data ] ); // @todo THIS IS NOT GETTING LISTENED TO 1269 1271 } 1270 1272 1271 1273 /** … … var WidgetCustomizer = ( function ($) { 1273 1275 * needing to be rendered, and so we can preempt the event for the 1274 1276 * preview finishing loading. 1275 1277 */ 1276 is_instance_identical =_( control.setting() ).isEqual( r.data.instance );1277 if ( is_instance_identical) {1278 no_setting_change = is_live_update_aborted || _( control.setting() ).isEqual( r.data.instance ); 1279 if ( no_setting_change ) { 1278 1280 control.container.removeClass( 'previewer-loading' ); 1279 1281 } else { 1280 1282 control.is_widget_updating = true; // suppress triggering another updateWidget … … var WidgetCustomizer = ( function ($) { 1283 1285 } 1284 1286 1285 1287 if ( complete_callback ) { 1286 complete_callback.call( control, null, { no_change: is_instance_identical, ajax_finished: true } );1288 complete_callback.call( control, null, { no_change: no_setting_change, ajax_finished: true } ); 1287 1289 } 1288 1290 } else { 1289 1291 window.console && window.console.log( r ); -
src/wp-admin/js/widgets.js
diff --git src/wp-admin/js/widgets.js src/wp-admin/js/widgets.js index 046907b..9f935ed 100644
wpWidgets = { 332 332 333 333 save : function( widget, del, animate, order ) { 334 334 var sidebarId = widget.closest('div.widgets-sortables').attr('id'), 335 data = widget.find('form').serialize(), a ;335 data = widget.find('form').serialize(), a, eventData; 336 336 337 337 widget = $(widget); 338 338 $('.spinner', widget).show(); … … wpWidgets = { 374 374 } else { 375 375 $('.spinner').hide(); 376 376 if ( r && r.length > 2 ) { 377 $( 'div.widget-content', widget ).html( r);377 $( 'div.widget-content', widget ).html( r ); 378 378 wpWidgets.appendTitle( widget ); 379 eventData = { 380 'widget_id': widget.find( 'input.widget-id' ).val(), 381 'widget_id_base': widget.find( 'input.id_base' ).val(), 382 'new_form': r, 383 'hard': true, // soft updates only in customizer 384 'customize_control': null 385 }; 386 widget.trigger( 'widget-form-update', [ eventData ] ); 379 387 } 380 388 } 381 389 if ( order ) {