Changeset 34563
- Timestamp:
- 09/25/2015 09:01:46 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-admin/includes/widgets.php
r34017 r34563 182 182 $add_new = isset($sidebar_args['_add']) ? $sidebar_args['_add'] : ''; 183 183 184 $before_form = isset( $sidebar_args['before_form'] ) ? $sidebar_args['before_form'] : '<form method="post">'; 185 $after_form = isset( $sidebar_args['after_form'] ) ? $sidebar_args['after_form'] : '</form>'; 186 $before_widget_content = isset( $sidebar_args['before_widget_content'] ) ? $sidebar_args['before_widget_content'] : '<div class="widget-content">'; 187 $after_widget_content = isset( $sidebar_args['after_widget_content'] ) ? $sidebar_args['after_widget_content'] : '</div>'; 188 184 189 $query_arg = array( 'editwidget' => $widget['id'] ); 185 190 if ( $add_new ) { … … 226 231 227 232 <div class="widget-inside"> 228 < form method="post">229 < div class="widget-content">230 <?php231 if ( isset( $control['callback']) )233 <?php echo $before_form; ?> 234 <?php echo $before_widget_content; ?> 235 <?php 236 if ( isset( $control['callback'] ) ) { 232 237 $has_form = call_user_func_array( $control['callback'], $control['params'] ); 233 else 234 echo "\t\t<p>" . __('There are no options for this widget.') . "</p>\n"; ?> 235 </div> 238 } else { 239 echo "\t\t<p>" . __('There are no options for this widget.') . "</p>\n"; 240 } 241 ?> 242 <?php echo $after_widget_content; ?> 236 243 <input type="hidden" name="widget-id" class="widget-id" value="<?php echo esc_attr($id_format); ?>" /> 237 244 <input type="hidden" name="id_base" class="id_base" value="<?php echo esc_attr($id_base); ?>" /> … … 253 260 <br class="clear" /> 254 261 </div> 255 < /form>262 <?php echo $after_form; ?> 256 263 </div> 257 264 -
trunk/src/wp-admin/js/customize-widgets.js
r33599 r34563 418 418 * @since 4.1.0 419 419 */ 420 initialize: function 420 initialize: function( id, options ) { 421 421 var control = this; 422 api.Control.prototype.initialize.call( control, id, options ); 423 control.expanded = new api.Value(); 422 423 control.widgetControlEmbedded = false; 424 control.widgetContentEmbedded = false; 425 control.expanded = new api.Value( false ); 424 426 control.expandedArgumentsQueue = []; 425 control.expanded.bind( function 427 control.expanded.bind( function( expanded ) { 426 428 var args = control.expandedArgumentsQueue.shift(); 427 429 args = $.extend( {}, control.defaultExpandedArguments, args ); 428 430 control.onChangeExpanded( expanded, args ); 429 431 }); 430 control.expanded.set( false ); 431 }, 432 433 /** 434 * Set up the control 432 433 api.Control.prototype.initialize.call( control, id, options ); 434 }, 435 436 /** 437 * Set up the control. 438 * 439 * @since 3.9.0 435 440 */ 436 441 ready: function() { 437 this._setupModel(); 438 this._setupWideWidget(); 439 this._setupControlToggle(); 440 this._setupWidgetTitle(); 441 this._setupReorderUI(); 442 this._setupHighlightEffects(); 443 this._setupUpdateUI(); 444 this._setupRemoveUI(); 442 var control = this; 443 444 /* 445 * Embed a placeholder once the section is expanded. The full widget 446 * form content will be embedded once the control itself is expanded, 447 * and at this point the widget-added event will be triggered. 448 */ 449 if ( ! control.section() ) { 450 control.embedWidgetControl(); 451 } else { 452 api.section( control.section(), function( section ) { 453 var onExpanded = function( isExpanded ) { 454 if ( isExpanded ) { 455 control.embedWidgetControl(); 456 section.expanded.unbind( onExpanded ); 457 } 458 }; 459 if ( section.expanded() ) { 460 onExpanded( true ); 461 } else { 462 section.expanded.bind( onExpanded ); 463 } 464 } ); 465 } 466 }, 467 468 /** 469 * Embed the .widget element inside the li container. 470 * 471 * @since 4.4.0 472 */ 473 embedWidgetControl: function() { 474 var control = this, widgetControl; 475 476 if ( control.widgetControlEmbedded ) { 477 return; 478 } 479 control.widgetControlEmbedded = true; 480 481 widgetControl = $( control.params.widget_control ); 482 control.container.append( widgetControl ); 483 484 control._setupModel(); 485 control._setupWideWidget(); 486 control._setupControlToggle(); 487 488 control._setupWidgetTitle(); 489 control._setupReorderUI(); 490 control._setupHighlightEffects(); 491 control._setupUpdateUI(); 492 control._setupRemoveUI(); 493 }, 494 495 /** 496 * Embed the actual widget form inside of .widget-content and finally trigger the widget-added event. 497 * 498 * @since 4.4.0 499 */ 500 embedWidgetContent: function() { 501 var control = this, widgetContent; 502 503 control.embedWidgetControl(); 504 if ( control.widgetContentEmbedded ) { 505 return; 506 } 507 control.widgetContentEmbedded = true; 508 509 widgetContent = $( control.params.widget_content ); 510 control.container.find( '.widget-content:first' ).append( widgetContent ); 445 511 446 512 /* … … 448 514 * listeners and dynamic UI elements. 449 515 */ 450 $( document ).trigger( 'widget-added', [ this.container.find( '.widget:first' ) ] ); 516 $( document ).trigger( 'widget-added', [ control.container.find( '.widget:first' ) ] ); 517 451 518 }, 452 519 … … 1009 1076 updateNumber, params, data, $inputs, processing, jqxhr, isChanged; 1010 1077 1078 // The updateWidget logic requires that the form fields to be fully present. 1079 self.embedWidgetContent(); 1080 1011 1081 args = $.extend( { 1012 1082 instance: null, … … 1255 1325 onChangeExpanded: function ( expanded, args ) { 1256 1326 var self = this, $widget, $inside, complete, prevComplete; 1327 1328 self.embedWidgetControl(); // Make sure the outer form is embedded so that the expanded state can be set in the UI. 1329 if ( expanded ) { 1330 self.embedWidgetContent(); 1331 } 1257 1332 1258 1333 // If the expanded state is unchanged only manipulate container expanded states -
trunk/src/wp-includes/class-wp-customize-control.php
r33734 r34563 1488 1488 public $is_wide = false; 1489 1489 1490 /** 1491 * Gather control params for exporting to JavaScript. 1492 * 1493 * @global array $wp_registered_widgets 1494 */ 1490 1495 public function to_json() { 1496 global $wp_registered_widgets; 1497 1491 1498 parent::to_json(); 1492 1499 $exported_properties = array( 'widget_id', 'widget_id_base', 'sidebar_id', 'width', 'height', 'is_wide' ); … … 1494 1501 $this->json[ $key ] = $this->$key; 1495 1502 } 1496 } 1497 1498 /** 1499 * 1500 * @global array $wp_registered_widgets 1501 */ 1502 public function render_content() { 1503 global $wp_registered_widgets; 1503 1504 // Get the widget_control and widget_content. 1504 1505 require_once ABSPATH . '/wp-admin/includes/widgets.php'; 1505 1506 … … 1515 1516 1516 1517 $args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0] ) ); 1517 echo $this->manager->widgets->get_widget_control( $args ); 1518 } 1518 $widget_control_parts = $this->manager->widgets->get_widget_control_parts( $args ); 1519 1520 $this->json['widget_control'] = $widget_control_parts['control']; 1521 $this->json['widget_content'] = $widget_control_parts['content']; 1522 } 1523 1524 /** 1525 * Override render_content to be no-op since content is exported via to_json for deferred embedding. 1526 */ 1527 public function render_content() {} 1519 1528 1520 1529 /** -
trunk/src/wp-includes/class-wp-customize-widgets.php
r33535 r34563 899 899 */ 900 900 public function get_widget_control( $args ) { 901 $args[0]['before_form'] = '<div class="form">'; 902 $args[0]['after_form'] = '</div><!-- .form -->'; 903 $args[0]['before_widget_content'] = '<div class="widget-content">'; 904 $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; 901 905 ob_start(); 902 903 906 call_user_func_array( 'wp_widget_control', $args ); 904 $replacements = array(905 '<form method="post">' => '<div class="form">',906 '</form>' => '</div><!-- .form -->',907 );908 909 907 $control_tpl = ob_get_clean(); 910 911 $control_tpl = str_replace( array_keys( $replacements ), array_values( $replacements ), $control_tpl );912 913 908 return $control_tpl; 909 } 910 911 /** 912 * Get the widget control markup parts. 913 * 914 * @since 4.4.0 915 * @access public 916 * 917 * @param array $args Widget control arguments. 918 * @return array { 919 * @type string $control Markup for widget control wrapping form. 920 * @type string $content The contents of the widget form itself. 921 * } 922 */ 923 public function get_widget_control_parts( $args ) { 924 $args[0]['before_widget_content'] = '<div class="widget-content">'; 925 $args[0]['after_widget_content'] = '</div><!-- .widget-content -->'; 926 $control_markup = $this->get_widget_control( $args ); 927 928 $content_start_pos = strpos( $control_markup, $args[0]['before_widget_content'] ); 929 $content_end_pos = strrpos( $control_markup, $args[0]['after_widget_content'] ); 930 931 $control = substr( $control_markup, 0, $content_start_pos + strlen( $args[0]['before_widget_content'] ) ); 932 $control .= substr( $control_markup, $content_end_pos ); 933 $content = trim( substr( 934 $control_markup, 935 $content_start_pos + strlen( $args[0]['before_widget_content'] ), 936 $content_end_pos - $content_start_pos - strlen( $args[0]['before_widget_content'] ) 937 ) ); 938 939 return compact( 'control', 'content' ); 914 940 } 915 941 -
trunk/tests/phpunit/tests/customize/widgets.php
r31622 r34563 196 196 $this->assertEquals( $unsanitized_from_js, $new_categories_instance ); 197 197 } 198 199 /** 200 * Get the widget control args for tests. 201 * 202 * @return array 203 */ 204 function get_test_widget_control_args() { 205 global $wp_registered_widgets; 206 require_once ABSPATH . '/wp-admin/includes/widgets.php'; 207 $widget_id = 'search-2'; 208 $widget = $wp_registered_widgets[ $widget_id ]; 209 $args = array( 210 'widget_id' => $widget['id'], 211 'widget_name' => $widget['name'], 212 ); 213 $args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $args, 1 => $widget['params'][0] ) ); 214 return $args; 215 } 216 217 /** 218 * @see WP_Customize_Widgets::get_widget_control() 219 */ 220 function test_get_widget_control() { 221 $this->do_customize_boot_actions(); 222 $widget_control = $this->manager->widgets->get_widget_control( $this->get_test_widget_control_args() ); 223 224 $this->assertContains( '<div class="form">', $widget_control ); 225 $this->assertContains( '<div class="widget-content">', $widget_control ); 226 $this->assertContains( '<input type="hidden" name="id_base" class="id_base" value="search"', $widget_control ); 227 $this->assertContains( '<input class="widefat"', $widget_control ); 228 } 229 230 /** 231 * @see WP_Customize_Widgets::get_widget_control_parts() 232 */ 233 function test_get_widget_control_parts() { 234 $this->do_customize_boot_actions(); 235 $widget_control_parts = $this->manager->widgets->get_widget_control_parts( $this->get_test_widget_control_args() ); 236 $this->assertArrayHasKey( 'content', $widget_control_parts ); 237 $this->assertArrayHasKey( 'control', $widget_control_parts ); 238 239 $this->assertContains( '<div class="form">', $widget_control_parts['control'] ); 240 $this->assertContains( '<div class="widget-content">', $widget_control_parts['control'] ); 241 $this->assertContains( '<input type="hidden" name="id_base" class="id_base" value="search"', $widget_control_parts['control'] ); 242 $this->assertNotContains( '<input class="widefat"', $widget_control_parts['control'] ); 243 $this->assertContains( '<input class="widefat"', $widget_control_parts['content'] ); 244 } 245 246 /** 247 * @see WP_Widget_Form_Customize_Control::json() 248 */ 249 function test_wp_widget_form_customize_control_json() { 250 $this->do_customize_boot_actions(); 251 $control = $this->manager->get_control( 'widget_search[2]' ); 252 $params = $control->json(); 253 254 $this->assertEquals( 'widget_form', $params['type'] ); 255 $this->assertRegExp( '#^<li[^>]+>\s+</li>$#', $params['content'] ); 256 $this->assertRegExp( '#^<div[^>]*class=\'widget\'[^>]*#s', $params['widget_control'] ); 257 $this->assertContains( '<div class="widget-content"></div>', $params['widget_control'] ); 258 $this->assertNotContains( '<input class="widefat"', $params['widget_control'] ); 259 $this->assertContains( '<input class="widefat"', $params['widget_content'] ); 260 $this->assertEquals( 'search-2', $params['widget_id'] ); 261 $this->assertEquals( 'search', $params['widget_id_base'] ); 262 $this->assertArrayHasKey( 'sidebar_id', $params ); 263 $this->assertArrayHasKey( 'width', $params ); 264 $this->assertArrayHasKey( 'height', $params ); 265 $this->assertInternalType( 'bool', $params['is_wide'] ); 266 267 } 198 268 } -
trunk/tests/phpunit/tests/widgets.php
r34465 r34563 307 307 $result = dynamic_sidebar( 'Sidebar 1' ); 308 308 ob_end_clean(); 309 309 310 310 $this->assertFalse( $result ); 311 311 } 312 312 313 /** 314 * @see wp_widget_control() 315 */ 316 function test_wp_widget_control() { 317 global $wp_registered_widgets; 318 319 wp_widgets_init(); 320 require_once ABSPATH . '/wp-admin/includes/widgets.php'; 321 $widget_id = 'search-2'; 322 $widget = $wp_registered_widgets[ $widget_id ]; 323 $params = array( 324 'widget_id' => $widget['id'], 325 'widget_name' => $widget['name'], 326 ); 327 $args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $params, 1 => $widget['params'][0] ) ); 328 329 ob_start(); 330 call_user_func_array( 'wp_widget_control', $args ); 331 $control = ob_get_clean(); 332 $this->assertNotEmpty( $control ); 333 334 $this->assertContains( '<div class="widget-top">', $control ); 335 $this->assertContains( '<div class="widget-title-action">', $control ); 336 $this->assertContains( '<div class="widget-title">', $control ); 337 $this->assertContains( '<form method="post">', $control ); 338 $this->assertContains( '<div class="widget-content">', $control ); 339 $this->assertContains( '<input class="widefat"', $control ); 340 $this->assertContains( '<input type="hidden" name="id_base" class="id_base" value="search"', $control ); 341 $this->assertContains( '<div class="widget-control-actions">', $control ); 342 $this->assertContains( '<div class="alignleft">', $control ); 343 $this->assertContains( 'widget-control-remove', $control ); 344 $this->assertContains( 'widget-control-close', $control ); 345 $this->assertContains( '<div class="alignright">', $control ); 346 $this->assertContains( '<input type="submit" name="savewidget"', $control ); 347 348 $param_overrides = array( 349 'before_form' => '<!-- before_form -->', 350 'after_form' => '<!-- after_form -->', 351 'before_widget_content' => '<!-- before_widget_content -->', 352 'after_widget_content' => '<!-- after_widget_content -->', 353 ); 354 $params = array_merge( $params, $param_overrides ); 355 $args = wp_list_widget_controls_dynamic_sidebar( array( 0 => $params, 1 => $widget['params'][0] ) ); 356 357 ob_start(); 358 call_user_func_array( 'wp_widget_control', $args ); 359 $control = ob_get_clean(); 360 $this->assertNotEmpty( $control ); 361 $this->assertNotContains( '<form method="post">', $control ); 362 $this->assertNotContains( '<div class="widget-content">', $control ); 363 364 foreach ( $param_overrides as $contained ) { 365 $this->assertContains( $contained, $control ); 366 } 367 } 313 368 } -
trunk/tests/qunit/fixtures/customize-settings.js
r33528 r34563 1 1 window.wp = window.wp || {}; 2 window.wp.customize = window.wp.customize || { get: function() {}};2 window.wp.customize = window.wp.customize || { get: function() {} }; 3 3 4 4 var customizerRootElement; 5 5 customizerRootElement = jQuery( '<div id="customize-theme-controls"><ul></ul></div>' ); 6 customizerRootElement.css( { position: 'absolute', left: -10000, top: -10000 } ); // remove from view6 customizerRootElement.css( { position: 'absolute', left: -10000, top: -10000 } ); // Remove from view. 7 7 jQuery( document.body ).append( customizerRootElement ); 8 8 -
trunk/tests/qunit/index.html
r33528 r34563 26 26 <script src="fixtures/customize-settings.js"></script> 27 27 <script src="fixtures/customize-menus.js"></script> 28 <script src="fixtures/customize-widgets.js"></script> 28 29 </div> 29 30 <p><a href="editor">TinyMCE tests</a></p> … … 45 46 <script src="../../src/wp-admin/js/nav-menu.js"></script> 46 47 <script src="../../src/wp-admin/js/customize-nav-menus.js"></script> 48 <script src="../../src/wp-admin/js/customize-widgets.js"></script> 47 49 <script src="../../src/wp-admin/js/word-count.js"></script> 48 50 … … 55 57 <script src="wp-admin/js/customize-controls-utils.js"></script> 56 58 <script src="wp-admin/js/customize-nav-menus.js"></script> 59 <script src="wp-admin/js/customize-widgets.js"></script> 57 60 <script src="wp-admin/js/word-count.js"></script> 58 61 … … 268 271 <button type="button" class="menus-move-up">Move up</button><button type="button" class="menus-move-down">Move down</button><button type="button" class="menus-move-left">Move one level up</button><button type="button" class="menus-move-right">Move one level down</button> </div> 269 272 </script> 273 274 <script type="text/html" id="tmpl-customize-section-sidebar"> 275 <li id="accordion-section-{{ data.id }}" class="accordion-section control-section control-section-{{ data.type }}"> 276 <h3 class="accordion-section-title" tabindex="0"> 277 {{ data.title }} 278 <span class="screen-reader-text">Press return or enter to open</span> 279 </h3> 280 <ul class="accordion-section-content"> 281 <li class="customize-section-description-container"> 282 <div class="customize-section-title"> 283 <button class="customize-section-back" tabindex="-1"> 284 <span class="screen-reader-text">Back</span> 285 </button> 286 <h3> 287 <span class="customize-action"> 288 {{{ data.customizeAction }}} 289 </span> 290 {{ data.title }} 291 </h3> 292 </div> 293 <# if ( data.description ) { #> 294 <div class="description customize-section-description"> 295 {{{ data.description }}} 296 </div> 297 <# } #> 298 </li> 299 </ul> 300 </li> 301 </script> 302 270 303 <div hidden> 271 304 <div id="available-menu-items" class="accordion-container"> … … 376 409 </div><!-- end nav menu templates --> 377 410 378 411 <div hidden> 412 <div id="widgets-left"><!-- compatibility with JS which looks for widget templates here --> 413 <div id="available-widgets"> 414 <div class="customize-section-title"> 415 <button class="customize-section-back" tabindex="-1"> 416 <span class="screen-reader-text">Back</span> 417 </button> 418 <h3> 419 <span class="customize-action">Customizing ▸ Widgets</span> 420 Add a Widget </h3> 421 </div> 422 <div id="available-widgets-filter"> 423 <label class="screen-reader-text" for="widgets-search">Search Widgets</label> 424 <input type="search" id="widgets-search" placeholder="Search widgets…" /> 425 </div> 426 <div id="available-widgets-list"> 427 <div id="widget-tpl-search-2" data-widget-id="search-2" class="widget-tpl search-2" tabindex="0"> 428 <div id='widget-11_search-__i__' class='widget'> <div class="widget-top"> 429 <div class="widget-title-action"> 430 <a class="widget-action hide-if-no-js" href="#available-widgets"></a> 431 <a class="widget-control-edit hide-if-js" href="/wp-admin/customize.php?editwidget=search-2&addnew=1&num=3&base=search"> 432 <span class="edit">Edit</span> 433 <span class="add">Add</span> 434 <span class="screen-reader-text">Search</span> 435 </a> 436 </div> 437 <div class="widget-title"><h4>Search<span class="in-widget-title"></span></h4></div> 438 </div> 439 440 <div class="widget-inside"> 441 <div class="form"> 442 <div class="widget-content"> 443 <p><label for="widget-search-__i__-title">Title: <input class="widefat" id="widget-search-__i__-title" name="widget-search[__i__][title]" type="text" value="" /></label></p> 444 </div> 445 <input type="hidden" name="widget-id" class="widget-id" value="search-__i__" /> 446 <input type="hidden" name="id_base" class="id_base" value="search" /> 447 <input type="hidden" name="widget-width" class="widget-width" value="250" /> 448 <input type="hidden" name="widget-height" class="widget-height" value="200" /> 449 <input type="hidden" name="widget_number" class="widget_number" value="2" /> 450 <input type="hidden" name="multi_number" class="multi_number" value="3" /> 451 <input type="hidden" name="add_new" class="add_new" value="multi" /> 452 453 <div class="widget-control-actions"> 454 <div class="alignleft"> 455 <a class="widget-control-remove" href="#remove">Delete</a> | 456 <a class="widget-control-close" href="#close">Close</a> 457 </div> 458 <div class="alignright"> 459 <input type="submit" name="savewidget" id="widget-search-__i__-savewidget" class="button button-primary widget-control-save right" value="Save" /> <span class="spinner"></span> 460 </div> 461 <br class="clear" /> 462 </div> 463 </div><!-- .form --> 464 </div> 465 466 <div class="widget-description"> 467 A search form for your site. 468 </div> 469 </div> </div> 470 </div><!-- #available-widgets-list --> 471 </div><!-- #available-widgets --> 472 </div><!-- #widgets-left --> 473 </div><!-- end widget templates --> 379 474 <script src="../../src/wp-includes/js/tinymce/tinymce.js"></script> 380 475 <script src="editor/js/utils.js"></script>
Note: See TracChangeset
for help on using the changeset viewer.