Some time has passed since the creation of sviperll_navigation. I've
updated the plugin following the Michael Snoyman's
post
about yesod. And things started to be more interesting. I have
removed tags from sviperll_navigation. Tags were used to filter nodes on menu generation.
Here is the
description
of current plugin
version.
I've used the following code in the layout to show left menu in my application.
<% navigator.children(:left).each do |node| %>
<%= link_to node.title, node.path, node.options %>
<% end %>
The description of pages in configuration file looked like
user.node :left, 'Orders', user_orders_path, :class => 'orders'
user.node :left, 'Lists', user_lists_path, :class => 'lists'
When I needed tabbed navigation, I used the following in the layout
<% navigator.siblings(:tab).each do |node| %>
<%= link_to node.title, node.path, node.options %>
<% end %>
The following snippet described pages in the configuration file
user.vnode :left, 'Orders', :class => 'orders' do |orders|
orders.node :tab, 'New order', new_user_order_path
orders.node :tab, 'Previous orders', user_orders_path
end
Tabs at the top of the page were encoded with the :tab tag in the
navigation config-file.
But this information is redundant, since parent page for the tabs is
always virtual page.
:tab tag is totally useless in this respect.
:left tag is useless too, since left menu is the main navigation
element and :left is
used almost everywhere, It is better to encode exceptions. So I've
removed tags from
navigation plugin entirely and navigation config-file started to look like this
user.vnode 'Orders', :css_class => 'orders' do |orders|
orders.node 'New order', new_user_order_path
orders.node 'Previous orders', user_orders_path
end
user.node 'Lists', user_lists_path, :css_class => 'lists'
user.node 'Transactions', user_transactions_path, :css_class => 'transactions', :menu => :right
Wich seems much clearer for me.
I've needed to change layout code to generate navigation elements after this change.
Left menu generation has become
<% navigator.children.each do |node| %>
<% if node.options[:menu].nil? || node.options[:menu] == :left %>
<%= link_to node.title, node.path, :class => node.options[:css_class] %>
<% end %>
<% end %>
Tabs generation has become
<% if !navigator.parent.nil? && navigator.parent.virtual? %>
<% navigator.siblings.each do |node| %>
<%= link_to node.title, node.path %>
<% end %>
<% end %>
Tabs are shown only if parent page is virtual page. Being virtual means that it is totally impossible
to be shown. Virtual pages serves the purpose to group some pages together, to organize pages' structure.
When you click on a virtual element in the menu you get not to the virtual page but to the first not-virtual
one in the hierarchy. Tabs are used to support navigation in this case.
Code that generate navigation elements become more smart with the removal of tags. Now it is possible to express in code some ideas of how good UI must be organized.
For example it is good to show "back" link on the pages. But it it not so good for the pages that are shown in tabs. User may arrive to the page by clicking on the tab and not by choosing this page from left menu, in this case "back" link is counter-intuitive. We can express this concerns in the layout code, and It will be used on all pages of application.
<% if !navigator.parent.nil? && navigator.parent.virtual? %>
<%= link_to 'Back', navigator.parent.path %>
<% end %>
So the main contribution of the plugin is an ability to express properties of UI. In common practice
UI properties are stated in some design document. UI is implemented as lots of navigation elements scattered across application pages. Consistency and conformance of implemented UI to design principles in documentation can't be automatically verified. With the abstraction provided by sviperll_navigation plugin, some properties of UI can be expressed with the code within application and UI elements can be consistently used all over the application.
I'm going to publish the plugin on the GitHub under BSD license with one major change. I'm going to change plugin's name. Sviperll navigation is cool but sviperll is my nickname and it is very strong connection to myself. I'm thinking about some name mentioning Magellan or some other great sailor and being a new word not overloaded with any meaning.