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.
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.
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
}
}
-
wow +1 ... what's missing with the server side function? Didn't try it out, but interessted.– kaiserCommented Sep 19, 2011 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– JukovCommented Nov 6, 2011 at 14:28
-
There is a question about your code at Limit number of Widgets in Sidebars - bug. Commented Sep 15, 2013 at 6:02
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.
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'] );
...
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.