Ticket #27491: 27491.2.diff
File 27491.2.diff, 12.8 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 eb552ad..64032da 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 ($) { 968 958 var control = this, 969 959 widget_content, 970 960 save_btn, 971 update_widget_debounced; 961 update_widget_debounced, 962 form_update_event_handler; 972 963 973 964 widget_content = control.container.find( '.widget-content' ); 974 965 … … var WidgetCustomizer = ( function ($) { 979 970 save_btn.removeClass( 'button-primary' ).addClass( 'button-secondary' ); 980 971 save_btn.on( 'click', function ( e ) { 981 972 e.preventDefault(); 982 control.updateWidget( );973 control.updateWidget( { disable_form: true } ); 983 974 } ); 984 975 985 976 update_widget_debounced = _.debounce( function () { … … var WidgetCustomizer = ( function ($) { 997 988 998 989 // Handle widgets that support live previews 999 990 widget_content.on( 'change input propertychange', ':input', function ( e ) { 1000 if ( e.type === 'change' ) { 1001 control.updateWidget(); 1002 } else if ( this.checkValidity && this.checkValidity() ) { 1003 update_widget_debounced(); 991 if ( control.live_update_mode ) { 992 if ( e.type === 'change' ) { 993 control.updateWidget(); 994 } else if ( this.checkValidity && this.checkValidity() ) { 995 update_widget_debounced(); 996 } 1004 997 } 1005 998 } ); 1006 999 … … var WidgetCustomizer = ( function ($) { 1019 1012 var is_rendered = !! rendered_widgets[control.params.widget_id]; 1020 1013 control.container.toggleClass( 'widget-rendered', is_rendered ); 1021 1014 } ); 1015 1016 form_update_event_handler = builtin_form_update_handlers[ control.params.widget_id_base ]; 1017 if ( form_update_event_handler ) { 1018 control.container.find( '.widget:first' ).on( 'widget-form-update', form_update_event_handler ); 1019 } 1022 1020 }, 1023 1021 1024 1022 /** … … var WidgetCustomizer = ( function ($) { 1148 1146 var control = this, 1149 1147 instance_override, 1150 1148 complete_callback, 1149 widget_root, 1151 1150 update_number, 1152 1151 widget_content, 1153 element_id_to_refocus = null,1154 active_input_selection_start = null,1155 active_input_selection_end = null,1156 1152 params, 1157 1153 data, 1158 1154 inputs, … … var WidgetCustomizer = ( function ($) { 1171 1167 control._update_count += 1; 1172 1168 update_number = control._update_count; 1173 1169 1174 widget_content = control.container.find( '.widget-content' ); 1170 widget_root = control.container.find( '.widget:first' ); 1171 widget_content = control.container.find( '.widget-content:first' ); 1175 1172 1176 1173 // Remove a previous error message 1177 1174 widget_content.find( '.widget-error' ).remove(); 1178 1175 1179 // @todo Support more selectors than IDs?1180 if ( $.contains( control.container[0], document.activeElement ) && $( document.activeElement ).is( '[id]' ) ) {1181 element_id_to_refocus = $( document.activeElement ).prop( 'id' );1182 // @todo IE8 support: http://stackoverflow.com/a/4207763/935791183 try {1184 active_input_selection_start = document.activeElement.selectionStart;1185 active_input_selection_end = document.activeElement.selectionEnd;1186 }1187 catch( e ) {} // catch InvalidStateError in case of checkboxes1188 }1189 1190 1176 control.container.addClass( 'widget-form-loading' ); 1191 1177 control.container.addClass( 'previewer-loading' ); 1192 1178 processing = wp.customize.state( 'processing' ); 1193 1179 processing( processing() + 1 ); 1194 1180 1181 if ( ! control.live_update_mode ) { 1182 control.container.addClass( 'widget-form-disabled' ); 1183 } 1184 1195 1185 params = {}; 1196 1186 params.action = self.update_widget_ajax_action; 1197 1187 params.wp_customize = 'on'; … … var WidgetCustomizer = ( function ($) { 1221 1211 sanitized_form, 1222 1212 sanitized_inputs, 1223 1213 has_same_inputs_in_response, 1224 is_instance_identical; 1214 no_setting_change, 1215 is_live_update_aborted = false, 1216 event_data; 1225 1217 1226 1218 // Check if the user is logged out. 1227 1219 if ( '0' === r ) { … … var WidgetCustomizer = ( function ($) { 1241 1233 1242 1234 if ( r.success ) { 1243 1235 sanitized_form = $( '<div>' + r.data.form + '</div>' ); 1244 1245 control.hook( 'formUpdate', sanitized_form );1246 1247 1236 sanitized_inputs = sanitized_form.find( ':input, option' ); 1248 1237 has_same_inputs_in_response = control._getInputsSignature( inputs ) === control._getInputsSignature( sanitized_inputs ); 1249 1238 1250 if ( has_same_inputs_in_response ) {1239 if ( has_same_inputs_in_response && control.live_update_mode ) { 1251 1240 inputs.each( function ( i ) { 1252 1241 var input = $( this ), 1253 1242 sanitized_input = $( sanitized_inputs[i] ), 1254 1243 property = control._getInputStatePropertyName( this ), 1255 s tate,1244 submitted_state, 1256 1245 sanitized_state; 1257 1246 1258 s tate = input.data( 'state' + update_number );1247 submitted_state = input.data( 'state' + update_number ); 1259 1248 sanitized_state = sanitized_input.prop( property ); 1260 1249 input.data( 'sanitized', sanitized_state ); 1250 event_data = { 1251 'sanitized_state': sanitized_state, 1252 'submitted_state': submitted_state, 1253 'customize_control': control 1254 }; 1261 1255 1262 if ( s tate !== sanitized_state ) {1256 if ( submitted_state !== sanitized_state ) { 1263 1257 1264 1258 // Only update now if not currently focused on it, 1265 1259 // so that we don't cause the cursor 1266 1260 // it will be updated upon the change event 1267 1261 if ( args.ignore_active_element || ! input.is( document.activeElement ) ) { 1268 1262 input.prop( property, sanitized_state ); 1263 input.trigger( 'widget-sanitary-field', [ event_data ] ); 1264 } else { 1265 input.trigger( 'widget-unsanitary-field', [ event_data ] ); 1269 1266 } 1270 control.hook( 'unsanitaryField', input, sanitized_state, state );1271 1267 1272 1268 } else { 1273 control.hook( 'sanitaryField', input, state);1269 input.trigger( 'widget-sanitary-field', [ event_data ] ); 1274 1270 } 1275 1271 } ); 1276 control.hook( 'formUpdated', sanitized_form ); 1272 1273 } else if ( control.live_update_mode ) { 1274 control.live_update_mode = false; 1275 control.container.find( 'input[name="savewidget"]' ).show(); 1276 is_live_update_aborted = true; 1277 1277 } else { 1278 widget_content.html( sanitized_form.html() ); 1279 if ( element_id_to_refocus ) { 1280 // not using jQuery selector so we don't have to worry about escaping IDs with brackets and other characters 1281 $( document.getElementById( element_id_to_refocus ) ) 1282 .prop( { 1283 selectionStart: active_input_selection_start, 1284 selectionEnd: active_input_selection_end 1285 } ) 1286 .focus(); 1287 } 1288 control.hook( 'formRefreshed' ); 1278 widget_content.html( r.data.form ); 1279 control.container.removeClass( 'widget-form-disabled' ); 1280 } 1281 1282 if ( ! is_live_update_aborted ) { 1283 event_data = { 1284 'widget_id': control.params.widget_id, 1285 'widget_id_base': control.params.widget_id_base, 1286 'new_form': r.data.form, 1287 'hard': ! control.live_update_mode, // dynamic fields may need to be re-initialized (e.g. Chosen) 1288 'customize_control': control 1289 }; 1290 widget_root.trigger( 'widget-form-update', [ event_data ] ); // @todo THIS IS NOT GETTING LISTENED TO 1289 1291 } 1290 1292 1291 1293 /** … … var WidgetCustomizer = ( function ($) { 1293 1295 * needing to be rendered, and so we can preempt the event for the 1294 1296 * preview finishing loading. 1295 1297 */ 1296 is_instance_identical =_( control.setting() ).isEqual( r.data.instance );1297 if ( ! is_instance_identical) {1298 no_setting_change = is_live_update_aborted || _( control.setting() ).isEqual( r.data.instance ); 1299 if ( no_setting_change ) { 1298 1300 control.is_widget_updating = true; // suppress triggering another updateWidget 1299 1301 control.setting( r.data.instance ); 1300 1302 control.is_widget_updating = false; 1301 1303 } 1302 1304 1303 1305 if ( complete_callback ) { 1304 complete_callback.call( control, null, { no_change: is_instance_identical, ajax_finished: true } );1306 complete_callback.call( control, null, { no_change: no_setting_change, ajax_finished: true } ); 1305 1307 } 1306 1308 } else { 1307 1309 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 ) {