Changeset 41051
- Timestamp:
- 07/14/2017 05:16:43 PM (7 years ago)
- Location:
- branches/4.8
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/4.8
-
branches/4.8/src/wp-admin/js/widgets/media-widgets.js
r40836 r41051 430 430 * @param {Object} options - Options. 431 431 * @param {Backbone.Model} options.model - Model. 432 * @param {jQuery} options.el - Control container element. 432 * @param {jQuery} options.el - Control field container element. 433 * @param {jQuery} options.syncContainer - Container element where fields are synced for the server. 433 434 * @returns {void} 434 435 */ … … 438 439 Backbone.View.prototype.initialize.call( control, options ); 439 440 440 if ( ! control.el ) {441 throw new Error( 'Missing options.el' );442 }443 441 if ( ! ( control.model instanceof component.MediaWidgetModel ) ) { 444 442 throw new Error( 'Missing options.model' ); 445 443 } 444 if ( ! options.el ) { 445 throw new Error( 'Missing options.el' ); 446 } 447 if ( ! options.syncContainer ) { 448 throw new Error( 'Missing options.syncContainer' ); 449 } 450 451 control.syncContainer = options.syncContainer; 452 453 control.$el.addClass( 'media-widget-control' ); 446 454 447 455 // Allow methods to be passed in with control context preserved. … … 548 556 syncModelToInputs: function syncModelToInputs() { 549 557 var control = this; 550 control. $el.next( '.widget-content' ).find( '.media-widget-instance-property' ).each( function() {558 control.syncContainer.find( '.media-widget-instance-property' ).each( function() { 551 559 var input = $( this ), value; 552 560 value = control.model.get( input.data( 'property' ) ); … … 1004 1012 */ 1005 1013 component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) { 1006 var widgetContent, controlContainer, widgetForm, idBase, ControlConstructor, ModelConstructor, modelAttributes, widgetControl, widgetModel, widgetId, widgetInside, animatedCheckDelay = 50, renderWhenAnimationDone;1014 var fieldContainer, syncContainer, widgetForm, idBase, ControlConstructor, ModelConstructor, modelAttributes, widgetControl, widgetModel, widgetId, widgetInside, animatedCheckDelay = 50, renderWhenAnimationDone; 1007 1015 widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen. 1008 widgetContent = widgetForm.find( '> .widget-content' );1009 1016 idBase = widgetForm.find( '> .id_base' ).val(); 1010 1017 widgetId = widgetForm.find( '> .widget-id' ).val(); … … 1033 1040 * container. 1034 1041 */ 1035 controlContainer = $( '<div class="media-widget-control"></div>' ); 1036 widgetContent.before( controlContainer ); 1042 fieldContainer = $( '<div></div>' ); 1043 syncContainer = widgetContainer.find( '.widget-content:first' ); 1044 syncContainer.before( fieldContainer ); 1037 1045 1038 1046 /* … … 1042 1050 */ 1043 1051 modelAttributes = {}; 1044 widgetContent.find( '.media-widget-instance-property' ).each( function() {1052 syncContainer.find( '.media-widget-instance-property' ).each( function() { 1045 1053 var input = $( this ); 1046 1054 modelAttributes[ input.data( 'property' ) ] = input.val(); … … 1051 1059 1052 1060 widgetControl = new ControlConstructor({ 1053 el: controlContainer, 1061 el: fieldContainer, 1062 syncContainer: syncContainer, 1054 1063 model: widgetModel 1055 1064 }); … … 1077 1086 component.modelCollection.add( [ widgetModel ] ); 1078 1087 component.widgetControls[ widgetModel.get( 'widget_id' ) ] = widgetControl; 1088 }; 1089 1090 /** 1091 * Setup widget in accessibility mode. 1092 * 1093 * @returns {void} 1094 */ 1095 component.setupAccessibleMode = function setupAccessibleMode() { 1096 var widgetForm, widgetId, idBase, widgetControl, ControlConstructor, ModelConstructor, modelAttributes, fieldContainer, syncContainer; 1097 widgetForm = $( '.editwidget > form' ); 1098 if ( 0 === widgetForm.length ) { 1099 return; 1100 } 1101 1102 idBase = widgetForm.find( '> .widget-control-actions > .id_base' ).val(); 1103 1104 ControlConstructor = component.controlConstructors[ idBase ]; 1105 if ( ! ControlConstructor ) { 1106 return; 1107 } 1108 1109 widgetId = widgetForm.find( '> .widget-control-actions > .widget-id' ).val(); 1110 1111 ModelConstructor = component.modelConstructors[ idBase ] || component.MediaWidgetModel; 1112 fieldContainer = $( '<div></div>' ); 1113 syncContainer = widgetForm.find( '> .widget-inside' ); 1114 syncContainer.before( fieldContainer ); 1115 1116 modelAttributes = {}; 1117 syncContainer.find( '.media-widget-instance-property' ).each( function() { 1118 var input = $( this ); 1119 modelAttributes[ input.data( 'property' ) ] = input.val(); 1120 }); 1121 modelAttributes.widget_id = widgetId; 1122 1123 widgetControl = new ControlConstructor({ 1124 el: fieldContainer, 1125 syncContainer: syncContainer, 1126 model: new ModelConstructor( modelAttributes ) 1127 }); 1128 1129 component.modelCollection.add( [ widgetControl.model ] ); 1130 component.widgetControls[ widgetControl.model.get( 'widget_id' ) ] = widgetControl; 1131 1132 widgetControl.render(); 1079 1133 }; 1080 1134 … … 1147 1201 component.handleWidgetAdded( new jQuery.Event( 'widget-added' ), widgetContainer ); 1148 1202 }); 1203 1204 // Accessibility mode. 1205 $( window ).on( 'load', function() { 1206 component.setupAccessibleMode(); 1207 }); 1149 1208 }); 1150 1209 }; -
branches/4.8/src/wp-admin/js/widgets/text-widgets.js
r40821 r41051 25 25 * Initialize. 26 26 * 27 * @param {Object} 28 * @param { Backbone.Model} options.model - Model.29 * @param {jQuery} options.el - Control container element.27 * @param {Object} options - Options. 28 * @param {jQuery} options.el - Control field container element. 29 * @param {jQuery} options.syncContainer - Container element where fields are synced for the server. 30 30 * @returns {void} 31 31 */ … … 36 36 throw new Error( 'Missing options.el' ); 37 37 } 38 if ( ! options.syncContainer ) { 39 throw new Error( 'Missing options.syncContainer' ); 40 } 38 41 39 42 Backbone.View.prototype.initialize.call( control, options ); 40 41 /* 42 * Create a container element for the widget control fields. 43 * This is inserted into the DOM immediately before the the .widget-content 44 * element because the contents of this element are essentially "managed" 45 * by PHP, where each widget update cause the entire element to be emptied 46 * and replaced with the rendered output of WP_Widget::form() which is 47 * sent back in Ajax request made to save/update the widget instance. 48 * To prevent a "flash of replaced DOM elements and re-initialized JS 49 * components", the JS template is rendered outside of the normal form 50 * container. 51 */ 52 control.fieldContainer = $( '<div class="text-widget-fields"></div>' ); 53 control.fieldContainer.html( wp.template( 'widget-text-control-fields' ) ); 54 control.widgetContentContainer = control.$el.find( '.widget-content:first' ); 55 control.widgetContentContainer.before( control.fieldContainer ); 43 control.syncContainer = options.syncContainer; 44 45 control.$el.addClass( 'text-widget-fields' ); 46 control.$el.html( wp.template( 'widget-text-control-fields' ) ); 56 47 57 48 control.fields = { 58 title: control. fieldContainer.find( '.title' ),59 text: control. fieldContainer.find( '.text' )49 title: control.$el.find( '.title' ), 50 text: control.$el.find( '.text' ) 60 51 }; 61 52 … … 63 54 _.each( control.fields, function( fieldInput, fieldName ) { 64 55 fieldInput.on( 'input change', function updateSyncField() { 65 var syncInput = control. widgetContentContainer.find( 'input[type=hidden].' + fieldName );56 var syncInput = control.syncContainer.find( 'input[type=hidden].' + fieldName ); 66 57 if ( syncInput.val() !== $( this ).val() ) { 67 58 syncInput.val( $( this ).val() ); … … 71 62 72 63 // Note that syncInput cannot be re-used because it will be destroyed with each widget-updated event. 73 fieldInput.val( control. widgetContentContainer.find( 'input[type=hidden].' + fieldName ).val() );64 fieldInput.val( control.syncContainer.find( 'input[type=hidden].' + fieldName ).val() ); 74 65 }); 75 66 }, … … 88 79 89 80 if ( ! control.fields.title.is( document.activeElement ) ) { 90 syncInput = control. widgetContentContainer.find( 'input[type=hidden].title' );81 syncInput = control.syncContainer.find( 'input[type=hidden].title' ); 91 82 control.fields.title.val( syncInput.val() ); 92 83 } 93 84 94 syncInput = control. widgetContentContainer.find( 'input[type=hidden].text' );85 syncInput = control.syncContainer.find( 'input[type=hidden].text' ); 95 86 if ( control.fields.text.is( ':visible' ) ) { 96 87 if ( ! control.fields.text.is( document.activeElement ) ) { … … 220 211 */ 221 212 component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) { 222 var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, widgetInside, renderWhenAnimationDone ;213 var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, widgetInside, renderWhenAnimationDone, fieldContainer, syncContainer; 223 214 widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen. 224 215 … … 229 220 230 221 // Prevent initializing already-added widgets. 231 widgetId = widgetForm.find( ' >.widget-id' ).val();222 widgetId = widgetForm.find( '.widget-id' ).val(); 232 223 if ( component.widgetControls[ widgetId ] ) { 233 224 return; 234 225 } 235 226 227 /* 228 * Create a container element for the widget control fields. 229 * This is inserted into the DOM immediately before the the .widget-content 230 * element because the contents of this element are essentially "managed" 231 * by PHP, where each widget update cause the entire element to be emptied 232 * and replaced with the rendered output of WP_Widget::form() which is 233 * sent back in Ajax request made to save/update the widget instance. 234 * To prevent a "flash of replaced DOM elements and re-initialized JS 235 * components", the JS template is rendered outside of the normal form 236 * container. 237 */ 238 fieldContainer = $( '<div></div>' ); 239 syncContainer = widgetContainer.find( '.widget-content:first' ); 240 syncContainer.before( fieldContainer ); 241 236 242 widgetControl = new component.TextWidgetControl({ 237 el: widgetContainer 243 el: fieldContainer, 244 syncContainer: syncContainer 238 245 }); 239 246 … … 255 262 }; 256 263 renderWhenAnimationDone(); 264 }; 265 266 /** 267 * Setup widget in accessibility mode. 268 * 269 * @returns {void} 270 */ 271 component.setupAccessibleMode = function setupAccessibleMode() { 272 var widgetForm, idBase, widgetControl, fieldContainer, syncContainer; 273 widgetForm = $( '.editwidget > form' ); 274 if ( 0 === widgetForm.length ) { 275 return; 276 } 277 278 idBase = widgetForm.find( '> .widget-control-actions > .id_base' ).val(); 279 if ( 'text' !== idBase ) { 280 return; 281 } 282 283 fieldContainer = $( '<div></div>' ); 284 syncContainer = widgetForm.find( '> .widget-inside' ); 285 syncContainer.before( fieldContainer ); 286 287 widgetControl = new component.TextWidgetControl({ 288 el: fieldContainer, 289 syncContainer: syncContainer 290 }); 291 292 widgetControl.initializeEditor(); 257 293 }; 258 294 … … 320 356 component.handleWidgetAdded( new jQuery.Event( 'widget-added' ), widgetContainer ); 321 357 }); 358 359 // Accessibility mode. 360 $( window ).on( 'load', function() { 361 component.setupAccessibleMode(); 362 }); 322 363 }); 323 364 }; -
branches/4.8/tests/qunit/wp-admin/js/widgets/test-media-image-widget.js
r40640 r41051 18 18 imageWidgetModelInstance = new wp.mediaWidgets.modelConstructors.media_image(); 19 19 imageWidgetControlInstance = new ImageWidgetControl({ 20 el: jQuery( '<div></div>' ), 21 syncContainer: jQuery( '<div></div>' ), 20 22 model: imageWidgetModelInstance 21 23 }); … … 85 87 imageWidgetModelInstance = new wp.mediaWidgets.modelConstructors.media_image(); 86 88 imageWidgetControlInstance = new wp.mediaWidgets.controlConstructors.media_image({ 89 el: jQuery( '<div></div>' ), 90 syncContainer: jQuery( '<div></div>' ), 87 91 model: imageWidgetModelInstance 88 92 }); -
branches/4.8/tests/qunit/wp-admin/js/widgets/test-media-video-widget.js
r40810 r41051 18 18 videoWidgetModelInstance = new wp.mediaWidgets.modelConstructors.media_video(); 19 19 videoWidgetControlInstance = new VideoWidgetControl({ 20 el: jQuery( '<div></div>' ), 21 syncContainer: jQuery( '<div></div>' ), 20 22 model: videoWidgetModelInstance 21 23 }); … … 47 49 videoWidgetModelInstance = new wp.mediaWidgets.modelConstructors.media_video(); 48 50 videoWidgetControlInstance = new wp.mediaWidgets.controlConstructors.media_video({ 51 el: jQuery( '<div></div>' ), 52 syncContainer: jQuery( '<div></div>' ), 49 53 model: videoWidgetModelInstance 50 54 });
Note: See TracChangeset
for help on using the changeset viewer.