# Navigator [![Gem Version](https://badge.fury.io/rb/navigator.svg)](http://badge.fury.io/rb/navigator) [![Code Climate Maintainability](https://api.codeclimate.com/v1/badges/2f8632ec1f734ea9561a/maintainability)](https://codeclimate.com/github/bkuhlmann/navigator/maintainability) [![Code Climate Test Coverage](https://api.codeclimate.com/v1/badges/2f8632ec1f734ea9561a/test_coverage)](https://codeclimate.com/github/bkuhlmann/navigator/test_coverage) [![Circle CI Status](https://circleci.com/gh/bkuhlmann/navigator.svg?style=svg)](https://circleci.com/gh/bkuhlmann/navigator) Enhances Rails with a DSL for menu navigation. ## Table of Contents - [Features](#features) - [Requirements](#requirements) - [Setup](#setup) - [Usage](#usage) - [Unordered List (simple)](#unordered-list-simple) - [Unordered List (with attributes)](#unordered-list-with-attributes) - [Unordered List (with multiple data attributes)](#unordered-list-with-multiple-data-attributes) - [Nav (with links)](#nav-with-links) - [Foundation Menu](#foundation-menu) - [Bootstrap Dropdown](#bootstrap-dropdown) - [Menu Helpers](#menu-helpers) - [Customization](#customization) - [Tests](#tests) - [Versioning](#versioning) - [Code of Conduct](#code-of-conduct) - [Contributions](#contributions) - [License](#license) - [History](#history) - [Credits](#credits) ## Features - Provides a DSL for building navigation menus. - Supports auto-detection/highlighting of active menu items based on current path (customizable for non-path usage too). - Supports sub-menus, nested tags, HTML attributes, etc. - Supports the following HTML tags: - div - section - header - h1 - h6 - nav - ul - li - a - img - b - em - s - small - span - strong - sub - sup - form - label - select - option - input - button - Provides `link`, `image`, and `item` convenience methods for succinct ways to build commonly used menu elements. ## Requirements 1. [Ruby 2.6.x](https://www.ruby-lang.org). 1. [Ruby on Rails 5.x.x](http://rubyonrails.org). ## Setup Type the following to install: gem install navigator Add the following to your Gemfile: gem "navigator" ## Usage The following are examples using the navigation view helper: ### Unordered List (simple) Code: navigation do item "Dashboard", "/dashboard" item "News", "/posts" end Result: ### Unordered List (with attributes) Code: navigation "ul", attributes: {class: "nav"} do item "Dashboard", "/dashboard", item_attributes: {class: "active"} item "News", "/posts" end Result: ### Unordered List (with multiple data attributes) Code: navigation do item "Home", "/home", item_attributes: {data: {id: 1, type: "public"}} end Result: *TIP: Nested data-- attributes can be applied to any menu item in the same manner as Rails view helpers.* ### Nav (with links) Code: navigation "nav" do a "Dashboard", attributes: {href: "/dashboard"} a "News", attributes: {href: "/posts"} end Result: ### Foundation Menu Code: navigation "nav", attributes: {class: "top-bar", "data-topbar" => nil} do ul attributes: {class: "title-area"} do li attributes: {class: "name"} do h1 do a "Demo", attributes: {href: "/home"} end end end section attributes: {class: "top-bar-section"} do ul attributes: {class: "left"} do item "Home", "/" item "About", "/about" end ul attributes: {class: "right"} do item "v1.0.0", '#' end ul attributes: {class: "right"} do item "Login", "/login", link_attributes: {class: "button tiny round"} end end end Result: ### Bootstrap Dropdown Code: navigation "nav" do item "Dashboard", admin_dashboard_path li attributes: {class: "dropdown"} do a "Manage", attributes: {href: "#", class: "dropdown-toggle", "data-toggle" => "dropdown"} do b attributes: {class: "caret"} end ul attributes: {class: "dropdown-menu"} do item "Dashboard", admin_dashboard_path item "Users", admin_users_path end end end Result: ### Menu Helpers There are several convenience methods, in addition to the standard HTML tags, that can make for shorter lines of code. The following describes each: When building links, the default is: navigation "nav", activator: activator do a "Home", attributes: {href: home_path} end ...but can be written as: navigation "nav", activator: activator do link "Home", home_path end When building images, the default is: navigation "nav", activator: activator do img attributes: {src: "https://placehold.it/50x50", alt: "Example"} end ...but can be written as: navigation "nav", activator: activator do image "https://placehold.it/50x50", "Example" end When building menu items, the default is: navigation "nav", activator: activator do li do a "Home", attributes: {href: home_path} end end ...but can be written as: navigation "nav", activator: activator do item "Home", "/dashboard" end These are just a few, simple, examples of what can be achieved. See the specs for additional usage and customization. ## Customization The `navigation` view helper can accept an optional `Navigator::TagActivator` instance. Example: # Code activator = Navigator::TagActivator.new search_value: request.env["PATH_INFO"] navigation "nav", activator: activator do link "Home", home_path link "About", about_path end This is the default behavior for all navigation menus and is how menu items automaticaly get the "active" class when the item URL (in this case "/home") matches the `request.env[“PATH_INFO"]` to indicate current page/active tab. `Navigator::TagActivator` instances can be configured as follows: - search_key = Optional. The HTML tag attribute to search for. Default: :href. - search_value = Required. The value to match against the search_key value in order to update the value of the target_key. Default: nil. - target_key = Optional. The HTML tag attribute key value to update when the search_value and search_key value match. Default: :class. - target_value = Optional. The value to be applied to the target_key value. If no value exists, then the value is added. Otherwise, if a value exists then the value is appended to the existing value. Default: "active". This customization allows for more sophisticated detection/updating of active HTML tags. For example, the example code (above) could be rewritten to use `data-*` attributes and customized styles as follows: # Code activator = Navigator::TagActivator.new search_key: "data-id", search_value: "123", target_key: "data-style" target_value: "current" navigation "nav", activator: activator do link "Home", home_path, attributes: {data: {id: "123", data-style="info"}} link "About", about_path attributes: {data: {id: "789"}} end Lastly, the search value can be a *regular expression* to make things easier when dealing with complicated routes, sub- menus, etc. Example: # Code profile_activator = Navigator::TagActivator.new search_value: /^profile.+/ navigation do item "Dashboard", dashboard_path li activator: profile_activator do link "Profile", '#' ul do item "Addresses", profile_addresses_path item "Emails", profile_emails_path end end end Assuming either the `Addresses` or `Emails` menu item was clicked, the `Profile` menu item would be active due to the regular expression (i.e. `/^profile.+/`) matching one of the the `profile/*` paths. ## Tests To test, run: bundle exec rake To test the dummy application, run: cd spec/dummy bin/rails server ## Versioning Read [Semantic Versioning](https://semver.org) for details. Briefly, it means: - Major (X.y.z) - Incremented for any backwards incompatible public API changes. - Minor (x.Y.z) - Incremented for new, backwards compatible, public API enhancements/fixes. - Patch (x.y.Z) - Incremented for small, backwards compatible, bug fixes. ## Code of Conduct Please note that this project is released with a [CODE OF CONDUCT](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. ## Contributions Read [CONTRIBUTING](CONTRIBUTING.md) for details. ## License Copyright 2012 [Alchemists](https://www.alchemists.io). Read [LICENSE](LICENSE.md) for details. ## History Read [CHANGES](CHANGES.md) for details. Built with [Gemsmith](https://github.com/bkuhlmann/gemsmith). ## Credits Developed by [Brooke Kuhlmann](https://www.alchemists.io) at [Alchemists](https://www.alchemists.io).