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.

#customize, #gsoc, #gsoc2014, #menu-customizer, #menus

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).

#customize, #gsoc, #gsoc2014, #menu-customizer, #menus

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.

#customize, #gsoc, #gsoc2014, #menu-customizer, #menus

GSoC: Editor Experiments #2

I meant to do a post last week, so this one is a bit late, but here it is anyway. I’ve mostly been working on the extendibility of views in TinyMCE and little improvements to the views themselves.

Registration

I’m trying to find a way to make it as easy as possible for plugins to create a view for their shortcode (though it doesn’t necesarily have to be a shortcode). At the moment the biggest challenge is the handling of scripts for those views. Views with scripts are sandboxed in an iframe, but while this is great for a view that just displays external content (like a map or tweet), it’s not so great for normal content because the iframe doesn’t inherit the styles of its parent. Sure, we could “detect” some styles, but that’s not good enough. We could also put editor-style.css in each iframe, but that will break once you switch formats or categories, unless we change every iframe’s body class simultaneously. I wish all major browsers supported “seamless” frames. 🙁

On the front-end, however, we wouldn’t have this problem. The content is not wrapped in an iframe, so scripts can be added where they normally would.

The current registation of a shortcode and view looks like this. It will change a lot though.

register_shortcode( 'my_shortcode', array(
	'__FILE__' => __FILE__,
	'content' => '',
	'block' => true,
	'attributes' => array(
		'my_attribute' => array(
			'title' => __( 'My Title' ),
			'defaults' => ''
		),
		...
	),
	'scripts' => array( 'script-handle', ... ),
) );

Notice that all the attributes must be defined here, unlike add_shortcode(). Now you’ll need to create a directory my_shortcode in the directory of __FILE__.

__FILE__
/myshortcode
	/template.php
	/register.js
	/preview.js
	/edit.php

template.php

This is what the shortcode will output on the front-end. This file receives the variables $attributes, $content and $tag.

register.js

This file registers the view for the TinyMCE editor.

( function( $, views ) {
	'use strict';

	views.register( 'my_shortcode', {
		getHTML: function( attributes, content, tag ) {
			// Content goes here.
		},
		edit: function( shortcode, attributes, content, tag, node ) {
			// This function is run when the user clicks on the edit icon.
			// E.g. you could create a default modal (or create your own).

			// This modal will display the `edit.php` template. You can provide a callback to do some crazy stuff.
			// If edit.php is set up correctly, all the attributes will be filled in for you.
			this.modal( node, callback );
			
			// OR
			
			// While the modal above will handle the update automatically when the user clicks on <input type="sumbit">,
			// you can also do it manually.
			this.refresh( attributes_or_shortcode, node );
		}
	} );

} )( jQuery, wp.mce.views );

preview.js

A script to run with the view’s content. This could also go in a <script> tag inside the content. Both will trigger an iframe.

edit.php

An html template to display the input fields. This will be optional, by default it would just display input fields for all the attributes you registered. You can hide certain attributes and set up your own controls by providing a custom edit.php template and add JavaScript using the modal callback.

The name attributes that match the registered shortcode attributes will be filled in automatically with the old shortcode attributes and the defaults when using this.modal().

<input type="text" name="my_attribute" value"">
<input type="submit" class="button button-primary">

An example

Eventually I’ll create several examples to illustrate all this. So far I’ve made an example for a map (a Google map). The code can be found in a child plugin: https://github.com/avryl/editor-experiments/tree/master/google-maps-block. You can see all the files I described when you enter the map directory.

In the editor, it just looks like this.

Screen Shot 2014-06-20 at 09.55.34

The edit view looks like this. You can search, add a marker, drag and drop it, move the map, change it to satellite and save it all.

Screen Shot 2014-06-20 at 09.59.06

View for embed

I’ve also been working a bit on the embed view for core. You can now paste an embeddable URL and it will automatically create a view for it. See #28195.

View improvements

I experimented a bit with the views themselves to make navigation and editing around them easier. Right now you can’t put your cursor right before or after a view. But with the Editor Experiments plugin you can! This is done by creating a fake cursor next to the view and detecting when the cursor enters and leaves the view. The cursor behaves exactly like a normal cursor (though the height is equal to the view), you can’t see the difference.

Screen Shot 2014-06-19 at 14.54.34

#editor, #gsoc

GSoC: Editor Experiments

I’ve not posted on /core before, so, hello everyone! 🙂 I’m Janneke and I’m currently working on my GSoC project. I’m from Belgium, but I currently live in Scotland and study philosophy at the University of Glasgow. This is something different entirely, but I started playing with WordPress a bit last year and enjoyed it a lot. 🙂

The original proposal was focussed on the front-end editor and content blocks, but that has changed a bit. I’ll focus on the back-end editor first instead, though the work will likely be reusable for a front-end editor. I’ll also focus on a bit more than just “content blocks”, so that’s why I’ve titled this “Editor Experiments”.

My general goals are to try to simplify and visualise the editor more, and to improve the workflow by providing as many tools as possible inline, at the right place and time. A lot of these ideas are not new, of course, and can be found in other editors and Joen‘s and Mel‘s mockups from last year. In order to visualise the editor more, I’ll try to make it easy for plugins to register shortcodes with previews for them, like there are now previews for a couple of media shortcodes such as galleries.

I’ll post an update on this blog every Friday with the progress I’ve made. I meant to publish a post last Friday, but didn’t have access to this blog yet, so here’s one for both weeks. I’ve set up a GitHub repo, and for now that’s the only place where you can download the plugin.

Sooo.

I’ve empty the TinyMCE toolbar, leaving only the most general tools, undo/redo, paste as plain text, remove format and help. On the other side we can control the the screen: switch between visual and text mode and activate fullscreen mode.

Screen Shot 2014-05-30 at 13.35.31

Instead of putting the title in a tiny box, I moved it to the editor as a first heading so it looks the same as on the front-end. Themes can style it appropriately.

Screen Shot 2014-05-30 at 13.41.37

Whenever you move the focus to an empty paragraph, a suggestion pops up to insert a “content block”.

Screen Shot 2014-05-30 at 13.46.29

To insert aligned images, you can put your cursor at the start of a paragraph.

Screen Shot 2014-05-30 at 13.58.42

Clicking on it gives you some kind of modal, where you can choose a block to add to your post. Of course, in the future plugins will be able to add their own blocks by registering shortcodes. So blocks can be block level HTML elements and block level shortcodes.

Screen Shot 2014-05-30 at 13.49.21

What happens after clicking on one of the blocks will depend on the block. Clicking on any of the media blocks will forward you to the media modal. Plugins can have a custom modal to configure the shortcode, which will likely also be used to edit it. Of course, blocks that require no configuration are added immediately (like a horizontal rule).

To format text, you should select it, and a toolbar will pop up.

Screen Shot 2014-05-30 at 14.03.56

And let’s add a link.

Screen Shot 2014-05-30 at 14.06.06

That’s it for now. 🙂

In the next two weeks I’ll work on the registration of views for shortcodes.

Now I’d love to hear what you think! I really value your opinion and brilliant ideas. Please do try it, and file issues on GitHub.

#editor, #gsoc

GSoC students announced http make wordpress org community…

GSoC students announced! https://make.wordpress.org/community/2014/04/21/gsoc-students-accepted/

(core projects are the minority this year, which is why I posted over on the community site under mentorship programs)

#gsoc, #gsoc2014

GSoC Chat Tomorrow

For those interested in Google Summer of Code, we’ll be holding a chat tomorrow on IRC in #wordpress-gsoc, March 20, at 18:00 UTC (2pm EDT, 11am PDT). Bring your proposal along and you’ll have five minutes to talk through your proposal with mentors. We’ll try to fit everyone.

If you haven’t already, be sure to submit your proposal as soon as possible. There’s not much time left to get feedback prior to the submission deadline! Keep in mind that you can modify your proposal up until the deadline.

See you all tomorrow!

#gsoc, #gsoc2014

GSoC IRC Chats

The application period opens today and closes on March 21. Between now and then, we’ll set up a handful of IRC chats starting this Wednesday (We’ll use #wordpress-gsoc so as not to distract from the beta work in -dev, and won’t get too close to the dev chat time-wise) to allow some real-time chatting with potential students about their project ideas.

All mentors should sign up for at least one time slot so the students will know which chat time will have appropriate mentors in the room. Everyone is welcome to attend these chats, not just mentors.

I’d like to pick 2 times of day and do the chats on Thursday the 13th, Saturday the 15th, Tuesday the 18th, and Thursday the 20th. 21:00 UTC seems to work well for dev chat, so I’m thinking that could be one of the times, but would like a 2nd time that we could do at least once or twice to make it easier on anyone on Australia/Russia side of the world.

Mentors: Please leave a comment with which days/times you can be available for chats in IRC. If anyone has an idea for a good 2nd chat time, suggestions welcome.

Thanks!

#gsoc, #gsoc2014

We’ve been accepted as a mentoring organization for…

We’ve been accepted as a mentoring organization for GSoC! Now comes the work of interacting with potential students on wp-hackers (let’s try to be responsive, and nice) and in #wordpress-dev and #wordpress-gsoc (I’ll set up a few scheduled chats soon, but idle in the channel if you can to field questions) during the application period. Mentors, I’ll contact you within the next couple of days to set up chat times and discuss the application review process.

Thanks to everyone who helped get our Ideas page filled!

#gsoc, #gsoc2014

GSoC 2014 Application Status

I’ve submitted our GSoC application. If anyone is interested in seeing the essay/short-answer questions they ask and how I answered them, I posted that part of the application over at https://make.wordpress.org/community/2014/02/13/gsoc-2014-application/

If you haven’t posted an idea to the codex page https://codex.wordpress.org/GSoC2014 but have time now, go ahead and add it. More ideas = more possible students applying for something that grabs their attention. Also, Google will be reviewing applications Feb 17-21, so adding more ideas (don’t forget to use the template and provide description) between now and the 17th is especially helpful. Not having enough ideas is why we didn’t get accepted in 2012.

Google will announce participating organizations on February 24.

#gsoc, #gsoc2014