WordPress.org

Ready to get started?Download WordPress

Make WordPress Core

Tagged: menu-customizer Toggle Comment Threads | Keyboard Shortcuts

  • Nick Halsey 12:20 am on August 8, 2014 Permalink | Log in to leave a Comment
    Tags: , menu-customizer,   

    GSoC Menu Customizer Update: Live-previewing Menus 

    I’ve finished implementing menu-previewing in the Menu Customizer plugin, building on the scalable approach to saving menus that I discussed in my last update. The entire Menus experience is now consolidated into a Menus panel in the Customizer, where you can preview your menus as you make changes. It’s really nice to have Menus easily accessible alongside the rest of the site-appearance-management tools in the Customizer.

    I only have about a week and a half left in my GSoC project, and I’m hoping to focus on improving the add-new-menu-item panel in my remaining time, making it scale and implementing the search functionality. I’m also planning on cleaning up the codebase and implementing the ability to manage menu hierarchy (submenus).

    If you’re interested in testing the Menu Customizer, and live-previewing changes to your menus, you can get the plugin here. Please note that it currently requires PHP 5.3+, but it’s getting less and less alpha by the day.

    Post-GSoC Plans

    After the GSoC coding period is over, I’m planning on transitioning Menu Customizer development to the feature-plugin format, gathering a group of interested contributors and holding weekly meetings to coordinate our efforts. While it won’t be ready for core consideration by 4.1, and requires some more core Customizer infrastructure to really work well, we’ll continue working on the plugin until menus in the Customizer really shine, and are ready for core.

     
  • Nick Halsey 3:15 pm on July 15, 2014 Permalink | Log in to leave a Comment
    Tags: , menu-customizer,   

    GSoC Menu Customizer Update: Scalable Menus 

    Since my last GSoC update, I’ve spent a fair amount of time helping prepare the Customizer for 4.0 beta 1. But I’ve also continued working on the Menu Customizer and have a lot of progress to report.

    Add & Delete Menus

    You can now add new menus, via the “+ New Menu” section. Added menus currently have some issues, though; you’ll probably need to reload the page before adding items works. The problems stem from the lack of a proper JS API for adding, deleting, and managing Sections and Settings (and Panels), and the incompleteness of the existing Control JS API. This will probably need to be resolved in core before the Menu Customizer can be considered for core integration, see #28709.

    I’ve also implemented a menu-deletion mode, which can be toggled from the add-menu section. It’s too easy to delete menus otherwise, even with an AYS confirming the delete, because deleted menus cannot be restored, and are not “previewed” before being published to the db (added menus aren’t either). It’s probably worth augmenting the AYS to state the menu name being deleted, and to add an extra warning if it’s active in a theme location or a widget.

    Saving Menus and Menu Item Data in a Scalable Way

    In core, menus do not scale well at all. You don’t have to look very deep into the code to see why – massive amounts of data for each item are hidden on the admin screens (much of which never changes) and then must be updated every time a change is made.

    Since one of the goals of this project is to experiment with new approaches, I’ve begun implementing a new approach for saving menu data, which is currently in use in the plugin. Thanks to my mentors @ethitter and @obenland for guiding me on the best approach to take here, and @westonruter for the way he implemented the Widget Customizer UI, which inspired this exact approach. Here’s how it works:

    • Each menu has a nav_menu Customizer control that contains an ordered array of numerical menu item ids (known throughout the core menus codebase as their db ids).
    • When an item is added, it is created as an orphaned draft via ajax, and its id is added to the nav_menu setting’s array.
    • When an item is deleted, its id is removed from the nav_menu setting’s array.
    • When menu items are reordered, the order of ids in the nav_menu id is updated to match.
    • When menu items are moved into and out of sub-menus, the parent menu item id is updated in the individual item’s data (not yet implemented).
    • When a menu item field is changed (by default, this would mean changing the label or, for custom items, url fileds; there are screen options for several others), the original item is cloned and the copy is updated with the new data, using a wrapper for wp_update_nav_menu_item() that doesn’t require passing all existing (unchanged) menu item data. The cloned item’s id is returned and replaces the original id in the nav_menu setting (thereby marking the original item for deletion). Additional changes are saved to the cloned item until the settings are saved, at which point all items are marked for a new clone to be created if changes are made (not yet implemented).
    • When the user saves their changes from the Customizer (via the customize_update_nav_menu action), the array of ids is compared to the currently-published menu’s items. If there are items that are no longer present, those are marked for deletion. For each of the new ids, the corresponding menu item (which already exists) is updated to be published, assigned to the corresponding menu (for the new items created as orphaned drafts), and the item’s menu_order is set to the id’s position in the nav_menus setting array. Finally, all of the removed items are deleted.

    While menu previewing in the customizer is not yet implemented, it will also be able to use the nav_menu setting’s array of ids to display an augmented set of menu items. I’m also still working on ensuring that menu item data is not posted during the customize-save ajax, but the data isn’t needed so we’re most of the way there already.

    UI Aside

    customize-header-bigflat-buttons-close

    Quick aside: @DrewAPicture pointed out in IRC that the new Customizer close and panel-back icons don’t really match the save button. I’ve done some rough explorations of potential alternatives; if anyone’s interested in discussing them and possibly implementing a change here, feel free to ping me in IRC (@celloexpressions) and/or create a ticket and/or comment here.

    Finally, I’m hoping to finish implementing menu previewing by the end of this week, fully utilizing the Customizer. Once this is done, I’ll essentially be at feature-complete stage (other than some little details and several known bugs) and ready to iterate (I’m already planning on working on the add-menu-items backend, as it currently doesn’t scale).

     
    • michalzuber 5:30 pm on July 17, 2014 Permalink | Log in to Reply

      I’m figuring out why is `@todo: Remove choices` in the `wp-includes/class-wp-customize-control.php` ? Couldn’t get it.

      • Nick Halsey 5:43 pm on July 17, 2014 Permalink | Log in to Reply

        That’s more related to the Customizer post, but I think that’s leftover from the initial customizer development in 3.4. We can remove the todo, since removing $choices is no longer an option due to back-compat.

    • Weston Ruter 8:26 pm on July 22, 2014 Permalink | Log in to Reply

      When an item is added, it is created as an orphaned draft via ajax, and its id is added to the nav_menu setting’s array.

      Something that I’ve been exploring with Customize Posts is the addition and deletion of postmeta. Instead of actually mutating the database, when creating new meta I’m creating faux post meta IDs and then referring to them in the preview filter. When saving the Customizer settings, these posts meta are then inserted at that time. It’s not quite done yet, as I need to now gather the post meta IDs that were inserted at the time of saving, and update the setting to refer to them.

      Generating a virtual post meta ID: https://github.com/x-team/wp-customize-posts/blob/85dc4e562ea806c17480899f5d94f93d42297de1/js/customize-posts.js#L611-L618

      Sanitizing a setting that includes virtual post meta ID: https://github.com/x-team/wp-customize-posts/blob/develop/php/class-wp-customize-posts.php#L303-L310

      It would be ideal if Menu Customizer could add new menu items virtually without touching the DB.

      • Nick Halsey 10:12 pm on July 22, 2014 Permalink | Log in to Reply

        I’m not sure if it would be possible to add items without touching the DB in a scalable way. The primary reason for doing that is so that menu item data doesn’t need to be sent to the server all at once when saving, which causes scaling problems currently (for example, imagine if 100+ menu items were added to several different menus upon initial setup of a site – that data would all go up together).

        In the existing menus system, items are similarly added to the db via ajax before being made available for manipulation in the UI. So, the concept of orphaned draft menu item posts is existing and currently being leveraged here.

  • Nick Halsey 2:44 am on June 28, 2014 Permalink | Log in to leave a Comment
    Tags: , menu-customizer   

    GSoC Menu Customizer Update 

    Since this is my first post here, a quick introduction. I’m a student at the University of Southern California studying Civil Engineering, Architecture, and Music Composition. I’ve been contributing to WordPress Core for just over a year and this summer I’m pleased to be working on WordPress full-time for my Google Summer of Code project.

    Overview

    The goal of the Menu Customizer project is to add Custom Menu management to the Customizer. Ideally, the project should be able to replace the existing Menus screen, with full feature parity, but that’s obviously a bigger discussion that would take place later. For more details, check out my initial proposal.

    Current Status

    I started six weeks ago and have built out most of the plugin’s UI and structure. However, I still need to build the menu-item previewing and saving components of the project. The UI closely resembles the Widgets-in-customizer UI, with sections for each menu and controls for each item. New menu items are added via a slide-out panel, where they’re currently grouped by post type/taxonomy, custom links, and a global search feature. The existing “Navigation” Customizer section has been re-branded to “Theme Locations,” and emphasizes the ability to add menus to widgets. Development is being done on the plugin repo, and you can download and play with it from there, but note that adding items creates orphaned draft menu items that are never published currently. Here’s a demo of the current plugin:

    (If the embedded video doesn’t play for you, try this link: https://cloudup.com/cVJbk3u32QV)

    The add-menu-item UI and implementation will be getting a lot of attention throughout the rest of my project. Items are added immediately, rather than the existing two-step checkboxes and adding several at once process, and menu items can now be deleted without having to open their settings, making deletion and addition more streamlined.

    When editing menu items, changing the navigation label of an item instantly updates its drag-and-drop handle, and updating a menu name updates the corresponding Customizer section. Items can be reordered or moved into sub-menus via either drag-and-drop or a reordering mode similar to that of the Widget Customizer.

    To minimalize the UI, given the limited space in the customizer, the “Title Attribute” field has been turned off by default, and all of the existing menu-item-field screen options are available, syncing with the existing Menus screen. I might look into building a core API for customizer screen options now that #27406 is in trunk, time permitting.

    A good amount of my time in the past couple weeks has been dedicated to #27406, which is a prerequisite for the Menu Customizer to be realistic given the need to allow users to create new menus (and in turn, new Customizer sections). Committed to trunk yesterday, it introduces a “Panels” API to the Customizer. Panels are a way to group sections, adding a new layer of hierarchy to the Customizer. In the Widget Customizer, all widget areas are added to the Widgets panel, allowing widgets to take over the entire Customizer as needed. The Menu Customizer plugin does the same thing with Menus, and requires trunk accordingly.

    Upcoming Work

    My next steps are to implement menu-adding and deleting, to implement reorderability/sortability, and then to spend quite a bit of time developing a saving/previewing system that scales well (see #14134  and related). This will most likely involve creating clones of changed menu items (posts) and menus (taxonomy terms). Once all of that’s finished, the plugin should be feature-complete, and ready for iteration.

    Core Patches

    I’ve also taken the opportunity to spend a fair amount of time working on core patches related to either Menus or the Customizer, as this project is widely expanding my knowledge of both areas. A couple of examples that have made it into core include #27406 – Customizer Panels, and #23076 – which adds live menu-item label-updating to the existing Menu screen. I’m planning on continuing to work on Menus and the Customizer via tickets/patches throughout my project as time allows.

     
    • helgatheviking 3:00 am on June 28, 2014 Permalink | Log in to Reply

      The video is pretty sweet!, great work! I’m definitely interested in seeing #14134 get fixed because it has been holding up the addition of an [18584: action hook for custom menu item meta](https://core.trac.wordpress.org/ticket/18584), which is causing all menu modifying plugins (and themes) to not be compatible with each other.

      • Nick Halsey 3:21 am on June 28, 2014 Permalink | Log in to Reply

        Thanks! I’m hoping to both fix the scaling issues and add some hooks in the new interface. The addition of a hook would really open up the possibilities for what menus can do, as your plugin and others already demonstrate.

        That being said I’m thinking that an API for custom menu fields might be even better than a hook, as that would make it easier to work with and match other core patterns for this type of structure. We’re essentially looking at custom post fields here given the way menus work. I’ll definitely look into this more once I get to the initial feature-completion stage. The ongoing Metadata UI API project might be able to be integrated here in some form, too.

    • nikeo 8:28 am on June 28, 2014 Permalink | Log in to Reply

      Great work! The plugin’s code is really clean and well commented.
      Thanks for sharing

    • Rami Yushuvaev 5:05 pm on June 28, 2014 Permalink | Log in to Reply

      Have you tested this in RTL mode?

      • Nick Halsey 5:54 pm on June 29, 2014 Permalink | Log in to Reply

        Not yet, that’ll come once we’re ready to test on different devices & environments after the basic functionality is complete. That being said, I’m guessing that the core build process will handle most of it automatically.

    • Graham Armfield 10:24 am on July 8, 2014 Permalink | Log in to Reply

      I think some accessibility testing needs to be done on this to ensure that anyone not using a mouse, and screen reader users are catered for here.

c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
shift + esc
cancel