Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

If I use a custom widgetized area (for example footer) where there is only a limited number of spots for widgets (by design), can I limit the number of widgets the user may include in that specific widgetized area? It doesn't matter if the solution is at the backend or the front end. Thank you.

share|improve this question
add comment

4 Answers

I solved this in Javascript. If you want to completely prevent it you should also do it server-side, because you can edit the widgets with Javascript disabled (try it out!).

The different sidebars are checked when you drop widgets to them or away from them. If they become full, the background color changes and you can no longer drop items on them. If, on startup, the sidebar is already more than full (because you tightened the restriction), the background color becomes red. You can still drag widgets away from full widgets to make them empty again.

One full and one more than full sidebar

Please test out this code, to find ways to add or remove widgets that I missed. The "magic" in the jQuery code comes from Aman, who answered a Stack Overflow question I posted about it.

Javascript:

jQuery( function( $ ) {
    var sidebarLimits = {
        'sidebar-1': 2,
        'sidebar-2': 2,
    };
    var realSidebars = $( '#widgets-right div.widgets-sortables' );
    var availableWidgets = $( '#widget-list' ).children( '.widget' );

    var checkLength = function( sidebar, delta ) {
        var sidebarId = sidebar.id;
        if ( undefined === sidebarLimits[sidebarId] ) {
            return;
        }

        // This is a limited sidebar
        // Find out how many widgets it already has
        var widgets = $( sidebar ).sortable( 'toArray' );
        $( sidebar ).toggleClass( 'sidebar-full', sidebarLimits[sidebarId] <= widgets.length + (delta || 0) );
        $( sidebar ).toggleClass( 'sidebar-morethanfull', sidebarLimits[sidebarId] < widgets.length + (delta || 0) );

        var notFullSidebars = $( 'div.widgets-sortables' ).not( '.sidebar-full' );
        availableWidgets.draggable( 'option', 'connectToSortable', notFullSidebars );
        realSidebars.sortable( 'option', 'connectWith', notFullSidebars );
    }

    // Check existing sidebars on startup
    realSidebars.map( function() {
        checkLength( this );
    } );

    // Update when dragging to this (sort-receive)
    // and away to another sortable (sort-remove)
    realSidebars.bind( 'sortreceive sortremove', function( event, ui ) {
        checkLength( this );
    } );

    // Update when dragging back to the "Available widgets" stack
    realSidebars.bind( 'sortstop', function( event, ui ) {
        if ( ui.item.hasClass( 'deleting' ) ) {
            checkLength( this, -1 );
        }
    } );

    // Update when the "Delete" link is clicked
    $( 'a.widget-control-remove' ).live( 'click', function() {
        checkLength( $( this ).closest( 'div.widgets-sortables' )[0], -1 );
    } );
} );

CSS:

.sidebar-full
{
    background-color: #cfe1ef !important;
}

.sidebar-morethanfull
{
    background-color: #c43 !important;
}

PHP to load them:

$wpse19907_file = $plugin;
add_action( 'admin_enqueue_scripts', 'wpse19907_admin_enqueue_scripts' );
function wpse19907_admin_enqueue_scripts( $hook_suffix )
{
    if ( 'widgets.php' == $hook_suffix ) {
        wp_enqueue_script( 'wpse-19907', plugins_url( 'wpse-19907.js', $GLOBALS['wpse19907_file'] ), array(), false, true );
        wp_enqueue_style( 'wpse-19907', plugins_url( 'wpse-19907.css', $GLOBALS['wpse19907_file'] ) );
    }
}

An attempt at a server-side check (probably not complete yet):

$wpse19907_sidebars_max_widgets = array(
    'sidebar-1' => 2,
);

add_action( 'sidebar_admin_setup', 'wpse19907_sidebar_admin_setup' );
function wpse19907_sidebar_admin_setup()
{
    if ( ! isset( $_POST['action'] ) || 'save-widget' != $_POST['action'] || empty( $_POST['add_new'] ) ) {
        return;
    }

    // We're adding a new widget to a sidebar
    global $wpse19907_sidebars_max_widgets;
    $sidebar_id = $_POST['sidebar'];

    if ( ! array_key_exists( $sidebar_id, $wpse19907_sidebars_max_widgets ) ) {
        return;
    }

    $sidebar = wp_get_sidebars_widgets();
    $sidebar = isset( $sidebars[$sidebar_id] ) ? $sidebars[$sidebar_id] : array();

    if ( count( $sidebar ) <= $wpse19907_sidebars_max_widgets[$sidebar_id] ) {
        die( 'mx' ); // Length must be shorter than 2, and unique
    }
}
share|improve this answer
    
wow +1 ... what's missing with the server side function? Didn't try it out, but interessted. –  kaiser Sep 19 '11 at 0:07
    
I wanted something more of a server side, but when I think of it, maybe you are right. this needs to be limited by JS. I'll try to think of a more robust solution, maybe disallowing drops of widgets altogether via JS –  Jukov Nov 6 '11 at 14:28
    
There is a question about your code at Limit number of Widgets in Sidebars - bug. –  Charles Clarkson Sep 15 '13 at 6:02
add comment

to help you with your question, I have a suggestion. Let's use the first-footer-widget-area present in the default Twenty Ten template sidebar-footer.php file like an example.

As a good practice and secure, firstly backup it to avoid headaches.

The original Twenty Ten template code for presenting first footer widget is:

<?php if ( is_active_sidebar( 'first-footer-widget-area' ) ) : ?>
       <div id="first" class="widget-area">
        <ul class="xoxo">
            <?php dynamic_sidebar( 'first-footer-widget-area' ); ?>
        </ul>
       </div><!-- #first .widget-area -->
<?php endif; ?>

Let's change, adding some code with conditionals to limit the number of widgets allowed in that area.

<?php if ( is_active_sidebar( 'first-footer-widget-area' ) ) : ?>
    <div id="first" class="widget-area">
    <?php
           $mysidebars = wp_get_sidebars_widgets();
           $total_widgets = count( $mysidebars['first-footer-widget-area'] );
           $limit_allowed=2;
    ?>
        <ul class="xoxo">
            <?php  if ($total_widgets > $limit_allowed) {
                echo 'Your '.$total_widgets.' added widgets goes over the allowed limit: <strong>'.$limit_allowed.'</trong>';
                } else { ?>
            <?php dynamic_sidebar( 'first-footer-widget-area' ); ?>
          <?php }; ?>
        </ul>

        </div><!-- #first .widget-area -->
<?php endif; ?>

What this modified code does:

$mysidebars = wp_get_sidebars_widgets();
$total_widgets = count( $mysidebars['first-footer-widget-area'] );
$limit_allowed=2;

count the number of widgets in that side bar and stablish some allowed limit (setten by you).

...
<?php  if ($total_widgets > $limit_allowed) {
            echo 'Your '.$total_widgets.' added widgets goes over the allowed limit: <strong>'.$limit_allowed.'</trong>';
       } else { ?>
            <?php dynamic_sidebar( 'first-footer-widget-area' ); ?>
<?php }; ?>
...

If the the limit allowed for widgets in that area was reached then it will be show a message warning that limit else the widget will be shown.

So I hope I have helped with your question.

share|improve this answer
add comment

Interessting Q. Didn't find out much at a brief look, but here's a guess: print_r( $GLOBALS['wp_registered_sidebars'] ); or print_r( $GLOBALS['sidebars'] ); or print_r( $GLOBALS['sidebars_widgets'] ); ...

share|improve this answer
add comment

You can do below stuff in order to determine the count of widgets.

Function:

$mysidebars = wp_get_sidebars_widgets() - will give you the list of sidebars and widgets used on that sidebars.

$total_widgets = count( $mysidebars['my-sidebar-id'] ); - will give you the count of total widgets in my-sidebar-id

I hope this will solve your doubts.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.