Ticket #27491: 27491.3.diff
File 27491.3.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 86c08bd..063361f 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 7dbb92b..4dd5a35 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 ($) { 137 138 self.registered_sidebars = new SidebarCollection( self.registered_sidebars ); 138 139 139 140 /** 141 * Handlers for the widget-form-update event, organized by widget ID base. 142 * Other widgets may provide their own update handlers by adding 143 * listeners for the widget-form-update event. 144 */ 145 builtin_form_update_handlers = { 146 147 /** 148 * @param {jQuery.Event} e 149 * @param {String} args.widget_id 150 * @param {String} args.widget_id_base 151 * @param {String} args.new_form 152 * @param {Boolean} args.hard 153 * @param {wp.customize.controlConstructor.widget_form} args.customize_control 154 */ 155 rss: function ( e, args ) { 156 var old_widget_error = args.customize_control.container.find( '.widget-error:first' ), 157 new_widget_error = $( '<div>' + args.new_form + '</div>' ).find( '.widget-error:first' ); 158 159 if ( old_widget_error.length && new_widget_error.length ) { 160 old_widget_error.replaceWith( new_widget_error ); 161 } else if ( old_widget_error.length ) { 162 old_widget_error.remove(); 163 } else if ( new_widget_error.length ) { 164 args.customize_control.container.find( '.widget-content:first' ).prepend( new_widget_error ); 165 } 166 } 167 }; 168 169 /** 140 170 * On DOM ready, initialize some meta functionality independent of specific 141 171 * customizer controls. 142 172 */ … … var WidgetCustomizer = ( function ($) { 630 660 control._setupHighlightEffects(); 631 661 control._setupUpdateUI(); 632 662 control._setupRemoveUI(); 633 control.hook( 'init' );634 },635 636 /**637 * Hooks for widgets to support living in the customizer control638 */639 hooks: {640 _default: {},641 rss: {642 formUpdated: function ( serialized_form ) {643 var control = this,644 old_widget_error = control.container.find( '.widget-error:first' ),645 new_widget_error = serialized_form.find( '.widget-error:first' );646 647 if ( old_widget_error.length && new_widget_error.length ) {648 old_widget_error.replaceWith( new_widget_error );649 } else if ( old_widget_error.length ) {650 old_widget_error.remove();651 } else if ( new_widget_error.length ) {652 control.container.find( '.widget-content' ).prepend( new_widget_error );653 }654 }655 }656 },657 658 /**659 * Trigger an 'action' which a specific widget type can handle660 *661 * @param name662 */663 hook: function ( name ) {664 var args = Array.prototype.slice.call( arguments, 1 ), handler;665 666 if ( this.hooks[this.params.widget_id_base] && this.hooks[this.params.widget_id_base][name] ) {667 handler = this.hooks[this.params.widget_id_base][name];668 } else if ( this.hooks._default[name] ) {669 handler = this.hooks._default[name];670 }671 if ( handler ) {672 handler.apply( this, args );673 }674 663 }, 675 664 676 665 /** … … var WidgetCustomizer = ( function ($) { 688 677 689 678 control._update_count = 0; 690 679 control.is_widget_updating = false; 680 control.live_update_mode = true; 691 681 692 682 // Update widget whenever model changes 693 683 control.setting.bind( function( to, from ) { … … var WidgetCustomizer = ( function ($) { 976 966 var control = this, 977 967 widget_content, 978 968 save_btn, 979 update_widget_debounced; 969 update_widget_debounced, 970 form_update_event_handler; 980 971 981 972 widget_content = control.container.find( '.widget-content' ); 982 973 … … var WidgetCustomizer = ( function ($) { 987 978 save_btn.removeClass( 'button-primary' ).addClass( 'button-secondary' ); 988 979 save_btn.on( 'click', function ( e ) { 989 980 e.preventDefault(); 990 control.updateWidget( );981 control.updateWidget( { disable_form: true } ); 991 982 } ); 992 983 993 984 update_widget_debounced = _.debounce( function () { … … var WidgetCustomizer = ( function ($) { 1005 996 1006 997 // Handle widgets that support live previews 1007 998 widget_content.on( 'change input propertychange', ':input', function ( e ) { 1008 if ( e.type === 'change' ) { 1009 control.updateWidget(); 1010 } else if ( this.checkValidity && this.checkValidity() ) { 1011 update_widget_debounced(); 999 if ( control.live_update_mode ) { 1000 if ( e.type === 'change' ) { 1001 control.updateWidget(); 1002 } else if ( this.checkValidity && this.checkValidity() ) { 1003 update_widget_debounced(); 1004 } 1012 1005 } 1013 1006 } ); 1014 1007 … … var WidgetCustomizer = ( function ($) { 1027 1020 var is_rendered = !! rendered_widgets[control.params.widget_id]; 1028 1021 control.container.toggleClass( 'widget-rendered', is_rendered ); 1029 1022 } ); 1023 1024 form_update_event_handler = builtin_form_update_handlers[ control.params.widget_id_base ]; 1025 if ( form_update_event_handler ) { 1026 control.container.find( '.widget:first' ).on( 'widget-form-update', form_update_event_handler ); 1027 } 1030 1028 }, 1031 1029 1032 1030 /** … … var WidgetCustomizer = ( function ($) { 1156 1154 var control = this, 1157 1155 instance_override, 1158 1156 complete_callback, 1157 widget_root, 1159 1158 update_number, 1160 1159 widget_content, 1161 element_id_to_refocus = null,1162 active_input_selection_start = null,1163 active_input_selection_end = null,1164 1160 params, 1165 1161 data, 1166 1162 inputs, … … var WidgetCustomizer = ( function ($) { 1179 1175 control._update_count += 1; 1180 1176 update_number = control._update_count; 1181 1177 1182 widget_content = control.container.find( '.widget-content' ); 1178 widget_root = control.container.find( '.widget:first' ); 1179 widget_content = control.container.find( '.widget-content:first' ); 1183 1180 1184 1181 // Remove a previous error message 1185 1182 widget_content.find( '.widget-error' ).remove(); 1186 1183 1187 // @todo Support more selectors than IDs?1188 if ( $.contains( control.container[0], document.activeElement ) && $( document.activeElement ).is( '[id]' ) ) {1189 element_id_to_refocus = $( document.activeElement ).prop( 'id' );1190 // @todo IE8 support: http://stackoverflow.com/a/4207763/935791191 try {1192 active_input_selection_start = document.activeElement.selectionStart;1193 active_input_selection_end = document.activeElement.selectionEnd;1194 }1195 catch( e ) {} // catch InvalidStateError in case of checkboxes1196 }1197 1198 1184 control.container.addClass( 'widget-form-loading' ); 1199 1185 control.container.addClass( 'previewer-loading' ); 1200 1186 processing = wp.customize.state( 'processing' ); 1201 1187 processing( processing() + 1 ); 1202 1188 1189 if ( ! control.live_update_mode ) { 1190 control.container.addClass( 'widget-form-disabled' ); 1191 } 1192 1203 1193 params = {}; 1204 1194 params.action = self.update_widget_ajax_action; 1205 1195 params.wp_customize = 'on'; … … var WidgetCustomizer = ( function ($) { 1229 1219 sanitized_form, 1230 1220 sanitized_inputs, 1231 1221 has_same_inputs_in_response, 1232 is_instance_identical; 1222 is_live_update_aborted = false, 1223 event_data; 1233 1224 1234 1225 // Check if the user is logged out. 1235 1226 if ( '0' === r ) { … … var WidgetCustomizer = ( function ($) { 1249 1240 1250 1241 if ( r.success ) { 1251 1242 sanitized_form = $( '<div>' + r.data.form + '</div>' ); 1252 1253 control.hook( 'formUpdate', sanitized_form );1254 1255 1243 sanitized_inputs = sanitized_form.find( ':input, option' ); 1256 1244 has_same_inputs_in_response = control._getInputsSignature( inputs ) === control._getInputsSignature( sanitized_inputs ); 1257 1245 1258 if ( has_same_inputs_in_response ) {1246 if ( has_same_inputs_in_response && control.live_update_mode ) { 1259 1247 inputs.each( function ( i ) { 1260 1248 var input = $( this ), 1261 1249 sanitized_input = $( sanitized_inputs[i] ), 1262 1250 property = control._getInputStatePropertyName( this ), 1263 s tate,1251 submitted_state, 1264 1252 sanitized_state; 1265 1253 1266 s tate = input.data( 'state' + update_number );1254 submitted_state = input.data( 'state' + update_number ); 1267 1255 sanitized_state = sanitized_input.prop( property ); 1268 1256 input.data( 'sanitized', sanitized_state ); 1257 event_data = { 1258 'sanitized_state': sanitized_state, 1259 'submitted_state': submitted_state, 1260 'customize_control': control 1261 }; 1269 1262 1270 if ( s tate !== sanitized_state ) {1263 if ( submitted_state !== sanitized_state ) { 1271 1264 1272 1265 // Only update now if not currently focused on it, 1273 1266 // so that we don't cause the cursor 1274 1267 // it will be updated upon the change event 1275 1268 if ( args.ignore_active_element || ! input.is( document.activeElement ) ) { 1276 1269 input.prop( property, sanitized_state ); 1270 input.trigger( 'widget-sanitary-field', [ event_data ] ); 1271 } else { 1272 input.trigger( 'widget-unsanitary-field', [ event_data ] ); 1277 1273 } 1278 control.hook( 'unsanitaryField', input, sanitized_state, state );1279 1274 1280 1275 } else { 1281 control.hook( 'sanitaryField', input, state);1276 input.trigger( 'widget-sanitary-field', [ event_data ] ); 1282 1277 } 1283 1278 } ); 1284 control.hook( 'formUpdated', sanitized_form ); 1279 1280 } else if ( control.live_update_mode ) { 1281 control.live_update_mode = false; 1282 control.container.find( 'input[name="savewidget"]' ).show(); 1283 is_live_update_aborted = true; 1285 1284 } else { 1286 widget_content.html( sanitized_form.html() ); 1287 if ( element_id_to_refocus ) { 1288 // not using jQuery selector so we don't have to worry about escaping IDs with brackets and other characters 1289 $( document.getElementById( element_id_to_refocus ) ) 1290 .prop( { 1291 selectionStart: active_input_selection_start, 1292 selectionEnd: active_input_selection_end 1293 } ) 1294 .focus(); 1295 } 1296 control.hook( 'formRefreshed' ); 1285 widget_content.html( r.data.form ); 1286 control.container.removeClass( 'widget-form-disabled' ); 1287 } 1288 1289 if ( ! is_live_update_aborted ) { 1290 event_data = { 1291 'widget_id': control.params.widget_id, 1292 'widget_id_base': control.params.widget_id_base, 1293 'new_form': r.data.form, 1294 'hard': ! control.live_update_mode, // dynamic fields may need to be re-initialized (e.g. Chosen) 1295 'customize_control': control 1296 }; 1297 widget_root.trigger( 'widget-form-update', [ event_data ] ); 1297 1298 } 1298 1299 1299 1300 /** … … var WidgetCustomizer = ( function ($) { 1301 1302 * needing to be rendered, and so we can preempt the event for the 1302 1303 * preview finishing loading. 1303 1304 */ 1304 is_instance_identical = _( control.setting() ).isEqual( r.data.instance ); 1305 if ( ! is_instance_identical ) { 1305 if ( ! is_live_update_aborted && ! _( control.setting() ).isEqual( r.data.instance ) ) { 1306 1306 control.is_widget_updating = true; // suppress triggering another updateWidget 1307 1307 control.setting( r.data.instance ); 1308 1308 control.is_widget_updating = false; 1309 1309 } 1310 1310 1311 1311 if ( complete_callback ) { 1312 complete_callback.call( control, null, { no_change: is_instance_identical, ajax_finished: true } );1312 complete_callback.call( control, null, { no_change: no_setting_change, ajax_finished: true } ); 1313 1313 } 1314 1314 } else { 1315 1315 message = self.i18n.error; -
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 ) {