[wp-trac] [WordPress Trac] #22070: Deleting menus with no title / slow menu saving
WordPress Trac
wp-trac at lists.automattic.com
Mon Oct 1 12:28:56 UTC 2012
#22070: Deleting menus with no title / slow menu saving
-----------------------------+--------------------------
Reporter: msebel | Type: defect (bug)
Status: new | Priority: normal
Milestone: Awaiting Review | Component: Menus
Version: 3.4.2 | Severity: normal
Keywords: dev-feedback |
-----------------------------+--------------------------
Hello there
I saw that when saving nav menus in wp-admin/nav-menus.php WordPress
executes the following lines, if a menu item is saved (no matter if newly
added or existing) that doesn't have a title:
{{{
if ( empty( $_POST['menu-item-title'][$_key] ) )
continue;
}}}
I changed this to the following to make it work. Problem is, it needs to
be removed from $menu_items, because it's handled like a deleted menu
else.
{{{
if ( empty( $_POST['menu-item-title'][$_key] ) ) {
if (isset($menu_items[$_POST['menu-item-db-id'][$_key]]))
unset($menu_items[$_POST['menu-item-db-id'][$_key]]);
continue;
}
}
}}}
'''Sidenote''':
With that fixed, I was able to solve a major saving bug. Many of our
customers have a lot of menu items in out nav_menu (like 100 - 600), which
without a timeout would take 10 minutes and more to save.
So I created some hotfix jQuery script that does "dirty-handling".
Basically it marks everything that's touched (like changed data, adding a
menu item or moving things around) as "dirty". On submit it doesn't
nothing more than change every "undirty" menu items title to an empty
string so it doesn't get saved.
I think WordPress core developers could integrate something like this with
far less code since I wasn't able to use events - I didn't really had a
lot of time to fix this. So if it helps anyone, this is the jQuery code I
used to create the fix:
{{{
jQuery(function($) {
// the currently displayed menu form
var $form = $('#update-nav-menu');
// Listen to new menus, since we have no possibility to hook
// we have to interval it, because we can't capture an event here
$('.submit-add-to-menu').click(function() {
var $item_count = $form.find('.menu-item-handle').length;
var $interval_id = setInterval(function() {
var $current_item_count = $form.find('.menu-item-handle').length;
if ($item_count < $current_item_count) {
clearInterval($interval_id);
// Add the dirty flag and set it to dirty immediately
add_dirty_flags(1);
// Reassign the mousedown/up events
assign_mouse_events();
}
},200);
});
// add a hidden field, telling if the menu is dirty (by default, it's
not)
function add_dirty_flags($flag) {
$form.find('.menu-item-handle').each(function() {
if ($(this).find('.dirty-handle').length == 0) {
var $html = '<input type="hidden" class="dirty-handle" value="' +
$flag + '" />';
$(this).append($html);
console.log('flag added');
}
});
}
// (re)assigns mouse events to menu items
function assign_mouse_events() {
var $menu_items = $('.menu-item-bar');
// Unbind previously assigned events
$menu_items.unbind('mouseup').unbind('mousedown');
// Dirty Flag handler if a click happens
$menu_items.mousedown(function() {
$(this).find('.dirty-handle').val('1');
});
// if the parent changes on release the mouse handle, change all items
with the new parent to dirty
$menu_items.mouseup(function() {
menu_save_mouseup($(this));
});
}
// The call back for mouseup on menu bars
function menu_save_mouseup($this) {
var $temp_object = $this.parent();
// Mark everything with the same parent dirty
setTimeout(function() {
var $parent_id = $temp_object.find('.menu-item-data-parent-
id').val();
// Go through all fields, dirtying everything that has the same
parent
$('.menu-item-data-parent-id').each(function() {
if ($(this).val() == $parent_id)
$(this).parent().prev().find('.dirty-handle').val('1');
});
},200);
}
// On submit make every undirty menu an empty title, so it won't get
saved
// We're using a hoax in nav-menus.php, line 335 here..
$form.submit(function() {
// Now traverse all handles and make only dirties saveable
$form.find('.menu-item-handle').each(function() {
// Find the dirty flag
var $is_dirty = $(this).find('.dirty-handle').val();
$(this).find('.dirty-handle').remove();
if ($is_dirty == 0) {
// The div containing the menu informations
var $forms = $(this).parent().next();
// Remove the title value so it doesn't get saved
$forms.find('.edit-menu-item-title').val('');
}
});
return true;
});
// Assign mouse events on first load
assign_mouse_events();
// Add all dirty flags (not dirty by default of course)
add_dirty_flags(0);
});
}}}
Since WordPress now only saves the menu's that changed it doesn't matter
how many menu items a customer has, but only how many he want's to save at
one time.
--
Ticket URL: <http://core.trac.wordpress.org/ticket/22070>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software
More information about the wp-trac
mailing list