[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