Make WordPress Core

Changeset 26426


Ignore:
Timestamp:
11/27/2013 01:29:49 AM (11 years ago)
Author:
azaozz
Message:

Widgets: drop onto closed sidebars.

  • Make dropping a widget easier by preventing the source sidebar from resizing while the widget is being dragged.
  • Move widgets dropped on closed sidebars to the top. UI Sortable places them randomly near the bottom.
  • Fix possible regression in wp_list_widget_controls(), add an optional argument to output the sidebar name inside the sortable container.
  • Updated styles for sidebar description and widget-hover class.

Part props shaunandrews, fixes #25952.

Location:
trunk/src/wp-admin
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/css/wp-admin.css

    r26424 r26426  
    1001310013
    1001410014
    10015 /* General Widget Styles */
     10015/* General Widgets Styles */
    1001610016
    1001710017.widget {
    10018     margin: 10px auto;
    10019     /* min-width: 50%; Not sure if this is needed */
     10018    margin: 0 auto 10px;
    1002010019    position: relative;
    1002110020    box-sizing: border-box;
    10022     -moz-box-sizing:border-box;
    10023     -webkit-box-sizing:border-box;
     10021    -moz-box-sizing: border-box;
     10022    -webkit-box-sizing: border-box;
    1002410023}
    1002510024
     
    1005410053
    1005510054/* Widget Dragging Helpers */
    10056 
    1005710055.widget.ui-draggable-dragging {
    10058     width: 280px !important;
    10059     min-width: 280px !important;
     10056    min-width: 100%;
    1006010057}
    1006110058
     
    1006710064.widget-placeholder {
    1006810065    border: 1px dashed #bbb;
    10069     margin: 10px 0;
     10066    margin: 0 auto 10px;
    1007010067    height: 45px;
    1007110068    width: 100%;
     
    1007710074#widgets-right .widget-placeholder {
    1007810075    margin-top: 0;
     10076}
     10077
     10078#widgets-right .closed .widget-placeholder {
     10079    height: 0;
     10080    border: 0;
     10081    margin-top: -10px;
    1007910082}
    1008010083
     
    1010710110
    1010810111.widgets-holder-wrap .description {
    10109     padding: 0;
     10112    padding: 0 0 15px;
    1011010113    margin: 0;
    1011110114    font-style: normal;
     
    1011310116}
    1011410117
    10115 #available-widgets.widgets-holder-wrap .description {
    10116     padding-bottom: 10px;
     10118#widgets-right .widgets-holder-wrap .description {
     10119    padding-left: 7px;
     10120    padding-right: 7px;
    1011710121}
    1011810122
     
    1017210176    padding: 10px 15px;
    1017310177    font-size: 12px;
     10178}
     10179
     10180#available-widgets #widget-list {
     10181    position: relative;
    1017410182}
    1017510183
     
    1022810236}
    1022910237
    10230 div#widgets-right .widget {
    10231     margin: 0 auto;
    10232     margin-bottom: 10px;
    10233 }
    10234 
    1023510238div#widgets-right .sidebar-description {
    10236     border-top: 1px solid #eeeeee;
    10237     padding: 10px 15px;
    10238 }
    10239 
    10240 div#widgets-right .closed .sidebar-description {
    10241     display: none;
     10239    min-height: 20px;
     10240    margin-top: -5px;
    1024210241}
    1024310242
    1024410243div#widgets-right .sidebar-name h3 {
    10245     padding: 15px 15px;
     10244    padding: 15px 7px;
    1024610245}
    1024710246
     
    1025910258    margin-bottom: 9px;
    1026010259    position: relative;
    10261     min-height: 45px;
    10262 }
    10263 
    10264 div#widgets-right .widgets-sortables:after {
    10265     display: block;
    10266     content: '';
    10267     position: absolute;
    10268         bottom: -10px;
    10269         left: 8px;
    10270         right: 8px;
    10271     z-index: 1; /* Required so that widgets hide the default dropzone indicator (.widgets-sortables:after) */
    10272     border: 1px dashed #bbb;
    10273     margin: 10px 0;
    10274     height: 45px;
    10275     -webkit-box-sizing: border-box;
    10276     -moz-box-sizing: border-box;
    10277     box-sizing: border-box;
    10278 }
    10279 
    10280 div#widgets-right .widgets-sortables .widget {
    10281     z-index: 2; /* Required so that widgets hide the default dropzone indicator (.widgets-sortables:after) */
     10260    min-height: 123px;
     10261}
     10262
     10263div#widgets-right .closed .widgets-sortables {
     10264    min-height: 0;
     10265    margin-bottom: 0;
    1028210266}
    1028310267
     
    1028710271}
    1028810272
     10273/* Dragging a widget over a closed sidebar */
     10274#widgets-right .widgets-holder-wrap.closed.widget-hover {
     10275    border-color: #777;
     10276    box-shadow: 0 1px 2px rgba(0,0,0,0.3);
     10277    opacity: 0.6;
     10278}
     10279
    1028910280/* Accessibility Mode */
    1029010281#available-widgets .widget-control-edit .edit {
    1029110282    display :none;
    1029210283}
     10284
    1029310285#available-widgets .widget-control-edit .add {
    1029410286    display: block;
     
    1030910301    border-left: 1px solid #DDD;
    1031010302}
     10303
    1031110304#widgets-right .widget-control-edit .add {
    1031210305    display: none;
    1031310306}
     10307
    1031410308#widgets-right .widget-control-edit:hover {
    1031510309    background: #444;
    1031610310}
     10311
    1031710312#widgets-right .widget-control-edit:before {
    1031810313    content: '\f111';
     
    1032710322}
    1032810323
     10324.widgets-holder-wrap .sidebar-name,
     10325.widgets-holder-wrap .sidebar-description {
     10326    -webkit-user-select: none;
     10327    -moz-user-select: none;
     10328    user-select: none;
     10329}
     10330
    1032910331.editwidget {
    1033010332    margin: 0 auto;
     
    1033410336}
    1033510337
    10336 .js .closed .widgets-sortables,
    10337 .js .closed .widget-holder,
     10338.js .widgets-holder-wrap.closed .widget,
     10339.js .widgets-holder-wrap.closed .sidebar-description,
    1033810340.js .closed br.clear {
    1033910341    display: none;
    1034010342}
     10343
    1034110344.nav-menus-php .item-edit:before,
    1034210345.widget-top a.widget-action:after,
     
    1073810741    }
    1073910742
     10743    .widget.ui-draggable-dragging {
     10744        min-width: 49%;
     10745    }
     10746
    1074010747    #widgets-left #available-widgets .widget:nth-child(even) {
    1074110748        float: right;
  • trunk/src/wp-admin/includes/widgets.php

    r26140 r26426  
    6464 *
    6565 * @param string $sidebar id slug of the sidebar
    66  */
    67 function wp_list_widget_controls( $sidebar ) {
     66 * @param string optional $sidebar_name Include the HTML for the sidebar name
     67 */
     68function wp_list_widget_controls( $sidebar, $sidebar_name = '' ) {
    6869    add_filter( 'dynamic_sidebar_params', 'wp_list_widget_controls_dynamic_sidebar' );
    6970
    7071    $description = wp_sidebar_description( $sidebar );
    7172
    72     if ( !empty( $description ) ) {
    73         echo "<div class='sidebar-description'>\n";
    74         echo "\t<p class='description'>$description</p>";
    75         echo "</div>\n";
    76     }
    77 
    78     echo "<div id='$sidebar' class='widgets-sortables'>\n";
     73    echo '<div id="' . esc_attr( $sidebar ) . '" class="widgets-sortables">';
     74
     75    if ( $sidebar_name ) {
     76        ?>
     77        <div class="sidebar-name">
     78            <div class="sidebar-name-arrow"><br /></div>
     79            <h3><?php echo esc_html( $sidebar_name ); ?> <span class="spinner"></span></h3>
     80        </div>
     81        <?php
     82    }
     83
     84    echo '<div class="sidebar-description">';
     85
     86    if ( ! empty( $description ) ) {
     87        echo '<p class="description">' . $description . '</p>';
     88    }
     89
     90    echo '</div>';
     91
    7992    dynamic_sidebar( $sidebar );
    80     echo "</div>\n";
     93
     94    echo '</div>';
    8195}
    8296
  • trunk/src/wp-admin/js/widgets.js

    r26366 r26426  
    1414
    1515        $('#widgets-right .sidebar-name').click( function() {
    16             var $this = $(this), wrap = $this.closest('.widgets-holder-wrap');
    17 
    18             if ( wrap.hasClass('closed') ) {
    19                 wrap.removeClass('closed');
    20                 $this.siblings('.widgets-sortables').sortable('refresh');
     16            var $this = $(this),
     17                $wrap = $this.closest('.widgets-holder-wrap');
     18
     19            if ( $wrap.hasClass('closed') ) {
     20                $wrap.removeClass('closed');
     21                $this.parent().sortable('refresh');
    2122            } else {
    22                 wrap.addClass('closed');
    23             }
    24         });
    25 
    26         $('#widgets-left').children('.widgets-holder-wrap').children('.sidebar-name').click(function() {
    27             $(this).parent().toggleClass('closed');
    28         });
    29 
    30         $(document.body).bind('click.widgets-toggle', function(e){
     23                $wrap.addClass('closed');
     24            }
     25        });
     26
     27        $('#widgets-left .sidebar-name').click( function() {
     28            $(this).closest('.widgets-holder-wrap').toggleClass('closed');
     29        });
     30
     31        $(document.body).bind('click.widgets-toggle', function(e) {
    3132            var target = $(e.target),
    3233                css = { 'z-index': 100 },
     
    3738                inside = widget.children('.widget-inside');
    3839                targetWidth = parseInt( widget.find('input.widget-width').val(), 10 ),
    39                 widgetWidth = widget.width();
     40                widgetWidth = widget.parent().width();
    4041
    4142                if ( inside.is(':hidden') ) {
     
    6970        });
    7071
    71         sidebars.children('.widget').each(function() {
    72             wpWidgets.appendTitle(this);
    73             if ( $('p.widget-error', this).length ) {
    74                 $('a.widget-action', this).click();
     72        sidebars.children('.widget').each( function() {
     73            var $this = $(this);
     74
     75            wpWidgets.appendTitle( this );
     76
     77            if ( $this.find( 'p.widget-error' ).length ) {
     78                $this.find( 'a.widget-action' ).trigger('click');
    7579            }
    7680        });
     
    113117            distance: 2,
    114118            containment: 'document',
    115             start: function(e,ui) {
    116                 var inside = ui.item.children('.widget-inside');
    117 
     119            start: function( event, ui ) {
     120                var $this = $(this),
     121                    $wrap = $this.parent(),
     122                    inside = ui.item.children('.widget-inside');
     123                   
     124
     125
     126
     127
     128//console.log(this);console.log(ui);
     129               
     130               
     131               
     132               
    118133                if ( inside.css('display') === 'block' ) {
    119134                    inside.hide();
    120135                    $(this).sortable('refreshPositions');
    121136                }
    122             },
    123             stop: function(e,ui) {
    124                 if ( ui.item.hasClass('ui-draggable') && ui.item.data('draggable') ) {
    125                     ui.item.draggable('destroy');
    126                 }
    127 
    128                 if ( ui.item.hasClass('deleting') ) {
    129                     wpWidgets.save( ui.item, 1, 0, 1 ); // delete widget
    130                     ui.item.remove();
     137
     138                if ( $wrap.hasClass('closed') ) {
     139                    // There is a bug in UI Sortable that prevents firing of "over" when dragging a connected Draggable.
     140                    // This won't be needed when the bug is fixed.
     141                    $wrap.addClass('widget-hover');
     142                } else {
     143                    // Lock all open sidebars min-height when starting to drag.
     144                    // Prevents jumping when dragging a widget from an open sidebar to a closed sidebar below.
     145                    $wrap.css( 'min-height', $wrap.height() + 'px' );
     146                    $this.css( 'min-height', $this.height() - 2 + 'px' );
     147                }
     148            },
     149
     150            stop: function( event, ui ) {
     151                var addNew, widgetNumber, $sidebar, $children, child, item,
     152                    $widget = ui.item,
     153                    id = the_id;
     154
     155                if ( $widget.hasClass('deleting') ) {
     156                    wpWidgets.save( $widget, 1, 0, 1 ); // delete widget
     157                    $widget.remove();
    131158                    return;
    132159                }
    133160
    134                 var add = ui.item.find('input.add_new').val(),
    135                     n = ui.item.find('input.multi_number').val(),
    136                     id = the_id,
    137                     sb = $(this).attr('id');
    138 
    139                 ui.item.attr( 'style', '' );
     161                addNew = $widget.find('input.add_new').val();
     162                widgetNumber = $widget.find('input.multi_number').val();
     163
     164                $widget.attr( 'style', '' );
    140165                the_id = '';
    141166
    142                 if ( add ) {
    143                     if ( 'multi' === add ) {
    144                         ui.item.html( ui.item.html().replace(/<[^<>]+>/g, function(m){ return m.replace(/__i__|%i%/g, n); }) );
    145                         ui.item.attr( 'id', id.replace('__i__', n) );
    146                         n++;
    147                         $('div#' + id).find('input.multi_number').val(n);
    148                     } else if ( 'single' === add ) {
    149                         ui.item.attr( 'id', 'new-' + id );
     167                if ( addNew ) {
     168                    if ( 'multi' === addNew ) {
     169                        $widget.html(
     170                            $widget.html().replace( /<[^<>]+>/g, function( tag ) {
     171                                return tag.replace( /__i__|%i%/g, widgetNumber );
     172                            })
     173                        );
     174
     175                        $widget.attr( 'id', id.replace( '__i__', widgetNumber ) );
     176                        widgetNumber++;
     177
     178                        $( 'div#' + id ).find( 'input.multi_number' ).val( widgetNumber );
     179                    } else if ( 'single' === addNew ) {
     180                        $widget.attr( 'id', 'new-' + id );
    150181                        rem = 'div#' + id;
    151182                    }
    152                     wpWidgets.save( ui.item, 0, 0, 1 );
    153                     ui.item.find('input.add_new').val('');
    154                     ui.item.find('a.widget-action').click();
     183
     184                    wpWidgets.save( $widget, 0, 0, 1 );
     185                    $widget.find('input.add_new').val('');
     186                }
     187
     188                $sidebar = $widget.parent();
     189
     190                if ( $sidebar.parent().hasClass('closed') ) {
     191                    $sidebar.parent().removeClass('widget-hover closed jump-open');
     192                    $children = $sidebar.children('.widget');
     193
     194                    // Make sure the dropped widget is at the top
     195                    if ( $children.length > 1 ) {
     196                        child = $children.get(0);
     197                        item = $widget.get(0);
     198
     199                        if ( child.id && item.id && child.id !== item.id ) {
     200                            $( child ).before( $widget );
     201                        }
     202                    }
     203                }
     204
     205                if ( addNew ) {
     206                    $widget.find( 'a.widget-action' ).trigger('click');
     207                } else {
     208                    wpWidgets.saveOrder( $sidebar.attr('id') );
     209                }
     210            },
     211
     212            over: function( event, ui ) {
     213                var $wrap = $(this).parent();
     214
     215                if ( $wrap.hasClass('closed') ) {
     216                    $wrap.addClass('widget-hover');
     217                }
     218            },
     219
     220            out: function( event, ui ) {
     221                $(this).parent().removeClass('widget-hover');
     222            },
     223
     224            deactivate: function( event, ui ) {
     225                // Remove all min-height added on "start"
     226                $(this).css( 'min-height', '' ).parent().css( 'min-height', '' );
     227            },
     228
     229            receive: function( event, ui ) {
     230                var $sender = $( ui.sender );
     231
     232                // Don't add more widgets to orphaned sidebars
     233                if ( this.id.indexOf('orphaned_widgets') > -1 ) {
     234                    $sender.sortable('cancel');
    155235                    return;
    156236                }
    157                 wpWidgets.saveOrder(sb);
    158             },
    159             receive: function(e, ui) {
    160                 var sender = $(ui.sender);
    161 
    162                 if ( ! $(this).is(':visible') || this.id.indexOf('orphaned_widgets') > -1 ) {
    163                     sender.sortable('cancel');
    164                 }
    165 
    166                 if ( sender.attr('id').indexOf('orphaned_widgets') > -1 && !sender.children('.widget').length ) {
    167                     sender.parents('.orphan-sidebar').slideUp(400, function(){ $(this).remove(); });
    168                 }
    169             }
    170         }).sortable('option', 'connectWith', 'div.widgets-sortables');
     237
     238                // If the last widget was moved out of an orphaned sidebar, close and remove it.
     239                if ( $sender.attr('id').indexOf('orphaned_widgets') > -1 && ! $sender.children('.widget').length ) {
     240                    $sender.parents('.orphan-sidebar').slideUp( 400, function(){ $(this).remove(); } );
     241                }
     242            }
     243        }).sortable( 'option', 'connectWith', 'div.widgets-sortables' );
    171244
    172245        $('#available-widgets').droppable({
     
    211284
    212285        $( '#available-widgets .widget .widget-title' ).on( 'click.widgets-chooser', function() {
    213             var widget = $(this).closest( '.widget' );
    214 
    215             if ( widget.hasClass( 'widget-in-question' ) || ( $( '#widgets-left' ).hasClass( 'chooser' ) ) ) {
     286            var $widget = $(this).closest( '.widget' );
     287
     288            if ( $widget.hasClass( 'widget-in-question' ) || $( '#widgets-left' ).hasClass( 'chooser' ) ) {
    216289                self.closeChooser();
    217290            } else {
     
    219292                self.clearWidgetSelection();
    220293                $( '#widgets-left' ).addClass( 'chooser' );
    221                 widget.addClass( 'widget-in-question' );
    222 
    223                 widget.find( '.widget-description' ).after( chooser );
     294                $widget.addClass( 'widget-in-question' ).children( '.widget-description' ).after( chooser );
     295
    224296                chooser.slideDown( 300, function() {
    225297                    selectSidebar.find('.widgets-chooser-selected').focus();
     
    258330    },
    259331
    260     saveOrder : function(sb) {
    261         if ( sb ) {
    262             $('#' + sb).closest('div.widgets-holder-wrap').find('.spinner:first').css('display', 'inline-block');
    263         }
    264 
    265         var a = {
     332    saveOrder : function( sidebarId ) {
     333        var data = {
    266334            action: 'widgets-order',
    267335            savewidgets: $('#_wpnonce_widgets').val(),
     
    269337        };
    270338
     339        if ( sidebarId ) {
     340            $( '#' + sidebarId ).find('.spinner:first').css('display', 'inline-block');
     341        }
     342
    271343        $('div.widgets-sortables').each( function() {
    272344            if ( $(this).sortable ) {
    273                 a['sidebars[' + $(this).attr('id') + ']'] = $(this).sortable('toArray').join(',');
    274             }
    275         });
    276 
    277         $.post( ajaxurl, a, function() {
     345                data['sidebars[' + $(this).attr('id') + ']'] = $(this).sortable('toArray').join(',');
     346            }
     347        });
     348
     349        $.post( ajaxurl, data, function() {
    278350            $('.spinner').hide();
    279351        });
    280352    },
    281353
    282     save : function(widget, del, animate, order) {
    283         var sb = widget.closest('div.widgets-sortables').attr('id'), data = widget.find('form').serialize(), a;
     354    save : function( widget, del, animate, order ) {
     355        var sidebarId = widget.closest('div.widgets-sortables').attr('id'),
     356            data = widget.find('form').serialize(), a;
     357       
    284358        widget = $(widget);
    285359        $('.spinner', widget).show();
     
    288362            action: 'save-widget',
    289363            savewidgets: $('#_wpnonce_widgets').val(),
    290             sidebar: sb
     364            sidebar: sidebarId
    291365        };
    292366
     
    297371        data += '&' + $.param(a);
    298372
    299         $.post( ajaxurl, data, function(r){
     373        $.post( ajaxurl, data, function(r) {
    300374            var id;
    301375
     
    322396                $('.spinner').hide();
    323397                if ( r && r.length > 2 ) {
    324                     $('div.widget-content', widget).html(r);
    325                     wpWidgets.appendTitle(widget);
     398                    $( 'div.widget-content', widget ).html(r);
     399                    wpWidgets.appendTitle( widget );
    326400                }
    327401            }
     
    380454        // Open the widgets container
    381455        sidebar.closest( '.widgets-holder-wrap' ).removeClass('closed');
     456
     457        sidebar.find('.sidebar-description').after( widget );
    382458        sidebar.sortable('refresh');
    383 
    384         widget.prependTo( sidebar );
    385459
    386460        wpWidgets.save( widget, 0, 0, 1 );
  • trunk/src/wp-admin/widgets.php

    r26366 r26426  
    333333    <div id="available-widgets" class="widgets-holder-wrap">
    334334        <div class="sidebar-name">
    335         <div class="sidebar-name-arrow"><br /></div>
    336         <h3><?php _e('Available Widgets'); ?> <span id="removing-widget"><?php _ex('Deactivate', 'removing-widget'); ?> <span></span></span></h3></div>
     335            <div class="sidebar-name-arrow"><br /></div>
     336            <h3><?php _e('Available Widgets'); ?> <span id="removing-widget"><?php _ex('Deactivate', 'removing-widget'); ?> <span></span></span></h3>
     337        </div>
    337338        <div class="widget-holder">
    338         <p class="description"><?php _e('Drag widgets from here to a sidebar on the right to activate them. Drag widgets back here to deactivate them and delete their settings.'); ?></p>
    339         <div id="widget-list">
    340         <?php wp_list_widgets(); ?>
    341         </div>
    342         <br class='clear' />
     339            <div class="sidebar-description">
     340                <p class="description"><?php _e('Drag widgets from here to a sidebar on the right to activate them. Drag widgets back here to deactivate them and delete their settings.'); ?></p>
     341            </div>
     342            <div id="widget-list">
     343                <?php wp_list_widgets(); ?>
     344            </div>
     345            <br class='clear' />
    343346        </div>
    344347        <br class="clear" />
     
    356359        ?>
    357360        <div class="<?php echo esc_attr( $wrap_class ); ?>">
    358             <div class="sidebar-name">
    359                 <div class="sidebar-name-arrow"><br /></div>
    360                 <h3><?php echo esc_html( $registered_sidebar['name'] ); ?> <span class="spinner"></span></h3>
    361             </div>
    362361            <div class="widget-holder inactive">
    363                 <?php wp_list_widget_controls( $registered_sidebar['id'] ); ?>
     362                <?php wp_list_widget_controls( $registered_sidebar['id'], $registered_sidebar['name'] ); ?>
    364363                <div class="clear"></div>
    365364            </div>
    366365        </div>
    367366        <?php
     367
    368368    } else {
    369369        $theme_sidebars[$sidebar] = $registered_sidebar;
     
    408408    ?>
    409409    <div class="<?php echo esc_attr( $wrap_class ); ?>">
    410         <div class="sidebar-name">
    411             <div class="sidebar-name-arrow"><br /></div>
    412             <h3><?php echo esc_html( $registered_sidebar['name'] ); ?>  <span class="spinner"></span></h3>
    413         </div>
    414         <?php wp_list_widget_controls( $sidebar ); // Show the control forms for each of the widgets in this sidebar ?>
     410        <?php wp_list_widget_controls( $sidebar, $registered_sidebar['name'] ); // Show the control forms for each of the widgets in this sidebar ?>
    415411    </div>
    416412    <?php
Note: See TracChangeset for help on using the changeset viewer.