Covers dynamic navigation driven by the content hierarchy and including the Quick Search component in the Header. Composite Components and policy sharing between multiple templates are included. Basics of HTL templating language, and dialogs are also used.

Prerequisites

This is Part 5 of the multi-part tutorial. Part 4 can be found here and an overview can be found here.

You can check out the finished code on GitHub or you can download the solution package:

Download

Content Hierarchy

It is important with any AEM implementation to plan out the content hierarchy as this is the primary mechanism for organizing the content. Site navigation is often heavily influenced by the content hierarchy and well-thought hierarchy can simplify the application. Permissions and support for multiple languages also play a role in content hierarchy planning. 

The fictitious WKND site is a life-style site with articles of things to do in several categories. We will create a content hierarchy that reflects this organization. The navigation will be dynamically populated based on the content hierarchy. We will also set up the site with a language root so that we can use AEM's translation feature in the future.

Top level hierarchy
Top level hierarchy for WKND site structure.

Update Site Hierarchy

 A well populated site hierarchy is needed to see the navigation functioning properly. The Landing Page Template will be used to provide much of that structure.

  1. screen_shot_2018-02-07at44228pm

    Update the Site Hierarchy

    The Navigation component relies on the site hierarchy to function. In order to see it working we will stub out the content hierarchy in advance. Use the Landing Template to create the following series of pages:

    /WKND (wknd)
         /Home (en)
             /Restaurant (restaurant)
             /Bars (bars)
             /Sports (sports)
             /Art (art)
             /Music (music)
             /Shopping (shopping)
    

    Add a new page beneath one of the categories that uses the Article Template. You should end up with something like the following:

    2018-11-16_at_8_44am

Core Components includes a Navigation component that we will leverage to create a header and footer navigation. The Navigation component creates a navigation based on the site structure. It has already been proxied into our project, we will add some styling to match the design. 

Navigation BEM Notation:

BLOCK cmp-navigation
    ELEMENT cmp-navigation__group
    ELEMENT cmp-navigation__item
        MOD cmp-navigation__item--active
        MOD cmp-navigation__item--level-*
    ELEMENT cmp-navigation__item-link

We will implement the Navigation in two different ways for the Header and Footer. The footer navigation will be implemented first using an additional layout container to provide structure.

The ui.apps module will be updated.

  1. Move the Navigation component into structure

    The Navigation component was created by the AEM project archetype beneath /apps/wknd/components/content. This will be just a structural component for this project.

    1. Move the navigation component from /apps/wknd/components/content to /apps/wknd/components/structure
    2. Update the componentGroup to be WKND.Structure
    apr-06-2018_18-27-28
    2018-04-09_at_1034am
  2. Create a footer style for Layout Container

    We will create a style for a new Layout Container which will act as the container for the navigation in the footer.

    Beneath /apps/wknd/clientlibs/clientlib-site/components/layout-container

    1. Beneath the folder named styles
    2. Create a new file beneath styles named footer.less
    screen_shot_2018-02-07at50719pm
  3. Populate footer.less with the following:

    /* WKND Layout Container Footer Style */
     
    @footer-background-color: #000;
    @footer-text-color: #fff;
     
     
    .cmp-layout-container--footer {
        background: @footer-background-color;
        min-height: 365px;
        margin-top: 3em;
        padding: 0 3em;
        
        >.aem-Grid {
            .container-content();
        }
         
        @media (max-width: @screen-medium) {
                min-height:267px; 
        }
         
        p {
               color: @footer-text-color;
               font-size: @font-size-xsmall;
               text-align:center;
           }        
    }

    This will create a black background with white text for the container when the CSS class cmp-layout-container--footer is added to the Layout Container.

  4. Update layout-container.less with the following:

    /* WKND Layout Container Styles */
    
    @import "styles/fixed-width.less";
    @import "styles/footer.less";
    
  5. Create a footer style for Navigation

    We will create a footer style for the Navigation component

    Beneath /apps/wknd/clientlibs/clientlib-site/components

    1. Create a new folder named navigation
    2. Beneath the navigation folder create a new file named navigation.less
    3. Beneath the navigation folder create a new folder named styles
    4. Beneath the styles folder create a new file named nav-footer.less
    screen_shot_2018-02-07at60704pm
  6. Populate nav-footer.less with the following:

    /* WKND Navigation Footer Style */
    
    @footer-color: #fff;
    
    
    .cmp-navigation--footer {
         
          .cmp-navigation {
            width: 100%;
            text-align: center;
            float: left;
            margin-top: 3em;
             
            .cmp-navigation__group {
                 
                margin-top:2em;
                margin-left:2em;
                margin-right: 2em;
             
              .cmp-navigation__item {
                 
                float:left;
                display: block;
                 
                .cmp-navigation__item-link {
                    font-size: @font-size-xsmall;
                    text-transform: uppercase;
                    color: @footer-color;
                    height:6em;
                    width: 10em;
                    text-align: center;
                    text-decoration: none;
                    padding-top: 4em;
                    float:left;
                     
                    &:hover,
                    &:focus {
                        background-color: @brand-primary;
                        color: @text-color;
                    }
                 
                     
                }
                 
            }
             
            li.cmp-navigation__item--active .cmp-navigation__item-link {
                background-color: rgba(255, 233, 0, 0.4);
                color: @brand-primary;
            }
         
             @media (max-width: @screen-medium) {
                margin-top: 2em;    
            }
        }
         
        } 
             
    }
  7. Update navigation.less with the following:

    /* WKND navigation styles */
    
    @import (once) "styles/nav-footer.less";
  8. Update main.less beneath /apps/wknd/clientlibs/clientlib-site to include the navigation styles: 

    /* main.less */
    
    ...
    
    /* Component Styles */
    @import "components/breadcrumb/breadcrumb.less";
    @import "components/contentfragment/contentfragment.less";
    @import "components/header/header.less";
    @import "components/image/image.less";
    @import "components/layout-container/layout-container.less";
    @import "components/list/list.less";
    /* import navigation.less */
    @import "components/navigation/navigation.less";
    @import "components/text/text.less";
    @import "components/title/title.less";
  9. Deploy code to AEM

Next, configure the footer in the Article and Landing page templates.

  1. Create Footer Layout Container on Article Template

    1. Navigate to the Article Template: http://localhost:4502/editor.html/conf/wknd/settings/wcm/templates/article-page-template/structure.html
    2. Drag a new Layout Container as the very last Layout Container (use Component Tree for help, it should be outside of the fixed-width container)
    2018-11-16_at_9_04am
  2. Create a Footer Layout Container Policy

    1. Click the Policy Icon to create a New Policy for the Footer Layout Container
    2. Policy Title = WKND Footer
    3. Allowed Components = Check WKND.Content and WKND.Structure
    4. Styles > Default CSS Classes = cmp-layout-container--footer

     After saving the policy the layout container should stretch full-width and have a black background.

    screen_shot_2018-02-07at62710pm
  3. Create a Navigation Component for the footer

    1. Add a Navigation component to the Footer layout container
    2. Configure the policy for the Navigation Component with the following:
    3. Policy TitleWKND Navigation - Footer
    4. Navigation Root = /content/wknd/en
    5. Check Exclude navigation root
    6. Un-check Collect all child pages
      1. Navigation Structure Dept = 1
    7. Styles > Default CSS Classescmp-navigation--footer
    footer-navpolicy
    2018-11-16_at_1029am
  4. Repeat the above steps using the Landing Template: http://localhost:4502/editor.html/conf/wknd/settings/wcm/templates/landing-page-template/structure.html

    You should be able to re-use the WKND Footer and WKND Navigation - Footer policies on the respective components.

    View one of the content pages. You should now be able to see the footer navigation populated on all the content pages.

    screen_shot_2018-02-07at65417pm

Header Component

The Header Component will include Navigation as well as Search and a Home/Logo link. We could create a Layout Container and follow the same approach as with the Footer. However attempting to resize all the components and getting them to align would be quite complicated for an author.

Instead we will create a "composite" component. The Header component will embed a Navigation and Quick Search component inside of it. When the Header component is dragged onto the page it will bring the other two with it.

Header Component
Header Component with embedded Navigation and Quick Search components
  1. Move the Search component into structure

    The Search component was created by the AEM project archetype beneath /apps/wknd/components/content. This will be a structural component for this project and embedded into the Header component.

    1. Move the Search component from /apps/wknd/components/content to /apps/wknd/components/structure
    2. Update the componentGroup to be WKND.Structure
    apr-09-2018_11-00-44
    2018-04-09_at_1102am
  2. Update Header Dialog

    Dialogs (the Wrench icon) are used by authors to change content. Until now we have just been styling core components and relied on dialogs already defined. This dialog will allow a user to configure the Root Path to link the WKND Logo.

    1. Beneath /apps/wknd/components/structure/header edit the cq:dialog
    2. It is easiest to edit the xml directly so open aem-guides-wkind.ui.apps/src/main/content/jcr_root/apps/wknd/components/structure/header/_cq_dialog/.content.xml
    dialog-header
    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
        jcr:primaryType="nt:unstructured"
        jcr:title="Header"
        sling:resourceType="cq/gui/components/authoring/dialog">
        <content
            jcr:primaryType="nt:unstructured"
            sling:resourceType="granite/ui/components/coral/foundation/container">
            <items jcr:primaryType="nt:unstructured">
                <tabs
                    jcr:primaryType="nt:unstructured"
                    sling:resourceType="granite/ui/components/coral/foundation/tabs"
                    maximized="{Boolean}true">
                    <items jcr:primaryType="nt:unstructured">
                        <header
                            jcr:primaryType="nt:unstructured"
                            jcr:title="Header Settings"
                            sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
                            margin="{Boolean}true">
                            <items jcr:primaryType="nt:unstructured">
                                <column
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/container">
                                    <items jcr:primaryType="nt:unstructured">
                                        <rootpath
                                            jcr:primaryType="nt:unstructured"
                                            sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
                                            fieldDescription="Populate the link of the WKND logo"
                                            fieldLabel="Root Path"
                                            name="./rootPath"
                                            rootPath="/content/wknd"/>
                                    </items>
                                </column>
                            </items>
                        </header>
                    </items>
                </tabs>
            </items>
        </content>
    </jcr:root>
  3. Update Header Design Dialog (Policy)

    Design Dialogs allow a user to update the Policy of a component. When working with structural components that will be re-used across templates it is advantageous to use Policies since the policy can be applied across templates.

    Create a Header Design Dialog to allow a user to configure the Root Path to link the WKND Logo via a Policy:

    1. Beneath /apps/wknd/components/structure/header create a new node named cq:design_dialog of type nt:unstructured
    2. It is easiest to edit the xml directly so open /wknd-sites-guide.ui.apps/src/main/content/jcr_root/apps/wknd/components/structure/header/_cq_design_dialog/.content.xml
    design_dialog-header
    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
        jcr:primaryType="nt:unstructured"
        jcr:title="Navigation"
        sling:resourceType="cq/gui/components/authoring/dialog">
        <content
            granite:class="cmp-navigation__editor"
            jcr:primaryType="nt:unstructured"
            sling:resourceType="granite/ui/components/coral/foundation/container">
            <items jcr:primaryType="nt:unstructured">
                <tabs
                    jcr:primaryType="nt:unstructured"
                    sling:resourceType="granite/ui/components/coral/foundation/tabs"
                    maximized="{Boolean}true">
                    <items jcr:primaryType="nt:unstructured">
                        <properties
                            jcr:primaryType="nt:unstructured"
                            jcr:title="Properties"
                            sling:resourceType="granite/ui/components/coral/foundation/container"
                            margin="{Boolean}true">
                            <items jcr:primaryType="nt:unstructured">
                               <rootpath
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/form/pathfield"
                                    fieldDescription="Populate the link of the WKND logo"
                                    fieldLabel="Root Path"
                                    name="./rootPath"
                                    rootPath="/content/wknd"/>
                            </items>
                        </properties>
                        <styletab
                            jcr:primaryType="nt:unstructured"
                            sling:resourceType="granite/ui/components/coral/foundation/include"
                            path="/mnt/overlay/cq/gui/components/authoring/dialog/style/tab_design/styletab"/>
                    </items>
                </tabs>
            </items>
        </content>
    </jcr:root>

    In the XML note the <rootpath /> node that has an attribute name="./rootPath". This will be the name of the property in which the Authors selection will be made.

    Note the <styletab> node and the path /mnt/overlay/cq/gui/components/authoring/dialog/style/tab_design/styletab. This will include the Style Tab and allow the Header component to leverage the style system.

  4. Update the header.html script to include the navigation and search components

    1. Update /apps/wknd/components/structure/header/header.html
    <!--/* Header Component for WKND Site 
     
    */-->
     
    <header class="wknd-header">
    	<div class="container">
    		<a class="wknd-header-logo" href="${properties.rootPath || currentStyle.rootPath @ extension='html'}">WKND</a>
        	<div class="cmp-search--header" data-sly-resource="${'search' @ resourceType='wknd/components/structure/search'}"></div>
        	<div class="cmp-navigation--header" id="header-navbar" data-sly-resource="${'navigation' @ resourceType='wknd/components/structure/navigation'}"></div>	
    	</div>
    </header>

    The snippet ${properties.rootPath || currentStyle.rootPath @ extension='html'}

    Injects the path selected by the author via the Dialog or Design Dialog. It first looks to see if a properties value of rootPath exists (Dialog) and then falls back to look at the currentStyle (Design Dialog) for the value of the rootPath.

    Both properties and currentStyle are Global Objects made available to all components HTL scripts.

    The snippet data-sly-resource="${'search' @ resourceType='wknd/components/structure/search'}" includes the Search Component and looks for it as a resource beneath the header named search. 

    The Navigation Component is included in the same way: data-sly-resource="${'navigation' @ resourceType='wknd/components/structure/navigation'}"

    This is an example of HTL Block Statements, more information can be found here.

  5. Add a cq:template

    Whenever creating composite components it is a best practice to create a cq:template to ensure that the embedded or sub-components have actual nodes/resources created in the JCR. If there is not a true node that maps to the sub-component odd behavior can occur with the Dialogs and Policies when saving.

    Beneath /apps/wknd/components/structure/header
    1. Create a new node named cq:template of type nt:unstructured
    2. Open the .content.xml for easier editing
    cq-template-header
    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
        jcr:primaryType="nt:unstructured">
        <navigation
            jcr:primaryType="nt:unstructured"
            sling:resourceType="wknd/components/structure/navigation"/>
        <search
            jcr:primaryType="nt:unstructured"
            sling:resourceType="wknd/components/structure/search"/>
    </jcr:root>

    Replace /aem-guides-wknd.ui.apps/src/main/content/jcr_root/apps/wknd/components/structure/header/_cq_template/.content.xml

    with the above snippet. This will ensure that nodes for navigation and search are created when a Header component is added.

  6. Add a new style for Navigation in Header

    Next we will add a new style for the navigation component in the header.

    Beneath /apps/wknd/clientlibs/clientlib-site/components/navigation/styles

    1. Create a new file named nav-header.less
    2. Populate it with the following:
    /* WKND Navigation Header styles */
     
    @mobile-nav-bg-color: #000;
    @mobile-nav-link-color: #fff;
         
    .cmp-navigation--header {
         
        float:right;
        padding-top: .25em;
        min-width: 100px;
        margin-right: 0.25em;
        margin-left: 0.25em;
         
        .cmp-navigation {
            float:right;
             
            .cmp-navigation__group {
                list-style: none;
                margin:0; 
            }
             
            .cmp-navigation__item {
                display: block;
                float: left;
            }
             
            .cmp-navigation__item-link {
                color: @text-color;
                font-size: @font-size-medium;
                text-transform: uppercase;
                font-weight: bolder;
                padding: 15px 17px;
                text-decoration: none;
                 
                &:hover,
                  &:focus {
                    background-color: @brand-primary;
                  }
            }
             
            .cmp-navigation__item--active .cmp-navigation__item-link {
                background-color: @brand-primary;
            }
        }
         
        @media (max-width: @screen-medium) {
             
            display:none;
        }    
    }

    Update /apps/wknd/clientlibs/clientlib-site/components/navigation/navigation.less to included the nav-header.less file: 

    /* WKND navigation styles */
    
    @import (once) "styles/nav-footer.less";
    @import (once) "styles/nav-header.less";
  7. Add a new style for Search in Header

    Next we will add a new style for the search component in the header.

    Beneath /apps/wknd/clientlibs/clientlib-site/components:

    1. Create a new folder named search
    2. Beneath the search folder, create a new file named search.less
    3. Beneath the search folder, create a new folder named styles
    4. Beneath the styles folder, create a new file named search-header.less
    2018-11-16_at_1222pm
  8. Populate search-header.less with the following:

    /* WKND Search Header styles */
     
    @search-width: 165px;
    @search-width-expand: 265px;
    
    @search-width-mobile: @search-width /2;
    @search-width-mobile-expand: @search-width;
    
    .cmp-search--header {
        float: right;
        margin-right: -12px;
        padding-right: @gutter-padding;
     
        .cmp-search {
             
            &__form {
             
            .cmp-search__icon {
                top: 0.7rem;
            }
             
            .cmp-search__clear-icon {
                top: 0.7rem;
            }
                 
            .cmp-search__input {
                background-color: #ebebeb8a;
                color:@text-color;
                font-size: @font-size-medium;
                border-radius: 0px;
                border:none;
                height:40px;
                width:@search-width;
                padding-right: 2rem;
                padding-left: 1.8rem;
                transition: ease-in-out, width .35s ease-in-out;
    
                &:focus {
                    background-color: @body-bg;
                    outline: none !important;
                    border:1px solid @text-color;
                    box-shadow: none;
                    width: @search-width-expand;
                }
                     
                &::placeholder { 
                    text-transform: uppercase;    
                    }
    
                    @media (max-width: @screen-small) {
                        width: @search-width-mobile;
                        &:focus {
                            width: @search-width-mobile-expand;
                             }
                    }
                    
                     
                }
                 
             
        }
             
            .cmp-search__results {
                margin-top: 0.5em;
                background: @gray-dark;
                 
                a.cmp-search__item {
                    color: @brand-third;
                    font-size: @font-size-small;
                    height: 50px;
                    text-overflow: ellipsis;
                    padding: 0.5em;
                    margin-top:0.25em;
                }
                 
                a.cmp-search__item:hover {
                    text-decoration:none;
                    background: @gray-base;
                }
                 
                .cmp-search__item-mark {
                    background: @gray-base;
                    color: @brand-third;
                }    
              }    
            }
             
             @media (max-width: @screen-medium) {
                 .cmp-search__input {
                   height:50px;
                 }
            }
             
            @media (max-width: @screen-small) {
                margin-right: 1em;
                position: absolute;
                right: 0;
                z-index: 100;
                margin-top: 0.25em;
                 
            }    
    }
  9. Populate /apps/wknd/clientlibs/clientlib-site/components/search/search.less to included the search-header.less file: 

    /* WKND Search styles */
    
    @import (once) "styles/search-header.less";
  10. Update main.less beneath /apps/wknd/clientlibs/clientlib-site to include the search styles: 

    /* main.less */
    ...
    
    /* Component Styles */
    @import "components/breadcrumb/breadcrumb.less";
    @import "components/contentfragment/contentfragment.less";
    @import "components/header/header.less";
    @import "components/image/image.less";
    @import "components/layout-container/layout-container.less";
    @import "components/list/list.less";
    @import "components/navigation/navigation.less";
    /* import search styles */
    @import "components/search/search.less";
    @import "components/text/text.less";
    @import "components/title/title.less";
  11. Deploy the code to AEM

Configure Header

After the updated code for the Header, Navigation, and Search components are deployed to AEM,  we will configure the Header component as part of the templates.

You should now see the header component includes a navigation and search on http://localhost:4502/editor.html/conf/wknd/settings/wcm/templates/article-page-template/structure.html

However before we can configure it we must Delete it and re-add it. This is because the Header component is now a "composite" component and embeds a navigation and search component. In order for it to function properly the search and navigation nodes must be added to template structure. The cq:template configured earlier, will ensure that the proper node structure is created. 

The high level steps for configuring the header:

  1. Delete the header node from the Article and Landing page templates via CRXDE-Lite
  2. Re-add the Header component to the Article page template
  3. Configure the embedded Navigation component in the Header component
  4. Configure the embedded Search component in the Header component
  5. Repeat the steps 2-4 for the Landing page template and re-use the Navigation and Search policies

The below video details these high level steps:


Mobile Navigation

At this point we have used the AEM Style System to style the existing markup generated by a core component. LESS and CSS are very powerful tools to change a component visually but depending on the requirements there will be limitations. It is also possible to use JavaScript to manipulate the markup of a core component after it has loaded. In this way we can re-purpose the markup of the component to be used in a different way, but do not need to make any back-end code changes.

For the mobile navigation we would ideally like the navigation to pop out from the left hand-side and "push" the body of the page off screen. Given the nested location of the navigation in the header component it is not really achievable to accomplish this behavior with CSS alone. Instead we will use a little bit of Javascript to create a copy of the Header Navigation markup and append it to the body tag. This will allow us to create that mobile navigation visual effect.

clone-navigationv2
Use JavaScript to clone the Navigation items in the Header to a mobile navigation that will be appended to the HTML body. This will occur on page load or when the header component is added to the page.
  1. Add a new style for Mobile Navigation

    Beneath /apps/wknd/clientlibs/clientlib-site/components/navigation/styles 

    1. Create a new file named nav-mobile.less
    2. Populate it with the following:
    /* WKND Navigation - Mobile */
    
    @nav-item-mobile-top-level-color: #fff;
    @nav-item-mobile-hover-color: @brand-primary;
    @nav-item-mobile-text-color: #888;
    @nav-item-mobile-border : solid 1px rgba(255, 255, 255, 0.05);
     
    .cmp-navigation--mobile {
         
      .cmp-navigation__group {
          list-style: none;
          display: inline-block;
          margin: 0;
          padding: 0;
      }
     
      .cmp-navigation__item {
          display: inline-block;
          float: left;
          width: 100%;
      }
     
      .cmp-navigation__item-link {
        display: block;
        color: @nav-item-mobile-text-color;
        text-decoration: none;
        height: 44px;
        line-height: 44px;
        border-top: @nav-item-mobile-border;
        padding: 0 1em 0 1em;
         
        &:hover {
            color: @nav-item-mobile-hover-color;
        }
      }
     
      .cmp-navigation__item--level-0, .cmp-navigation__item--level-1 {
       
              > .cmp-navigation__item-link {
                  color: @nav-item-mobile-top-level-color;
                   
                  &:hover {
                      color: @nav-item-mobile-hover-color;
                  }
              }
        }
         
        .cmp-navigation__item--level-2 {
            padding-left: 2em;
        }
         
        .cmp-navigation__item--level-3 {
            padding-left: 4em;
        }
    }
     
     
         #mobileNav, #toggleNav {
            display: none;
        }
         
        /*Styles to push mobile nav into view */
         
        @media (max-width: @screen-medium) {
         
        .root.responsivegrid {
                    -moz-backface-visibility: hidden;
                    -webkit-backface-visibility: hidden;
                    -ms-backface-visibility: hidden;
                    backface-visibility: hidden;
                    -moz-transition: -moz-transform 0.5s ease;
                    -webkit-transition: -webkit-transform 0.5s ease;
                    -ms-transition: -ms-transform 0.5s ease;
                    transition: transform 0.5s ease;
                    padding-bottom: 1px;
        }
         
        #toggleNav {
                    -moz-backface-visibility: hidden;
                    -webkit-backface-visibility: hidden;
                    -ms-backface-visibility: hidden;
                    backface-visibility: hidden;
                    -moz-transition: -moz-transform 0.5s ease;
                    -webkit-transition: -webkit-transform 0.5s ease;
                    -ms-transition: -ms-transform 0.5s ease;
                    transition: transform 0.5s ease;
                    display: block;
                    height: 44px;
                    left: 0;
                    position: fixed;
                    top: 6px;
                    width: 40px;
                    z-index: 10001;
                    border-top-right-radius: 2px;
                    border-bottom-right-radius: 2px;
                }
                .scrolly {
                    #toggleNav {
                        background: #edededa8;
                    }
                }
     
                    #toggleNav .toggle {
                        width: 80px;
                        height: 60px;
                        font-size: 40px;
                        color: @text-color;
                         
                        &:hover {
                            text-decoration:none;
                            color: @text-color;
                        }
                         
                    }
     
                #mobileNav {
                    -moz-backface-visibility: hidden;
                    -webkit-backface-visibility: hidden;
                    -ms-backface-visibility: hidden;
                    backface-visibility: hidden;
                    -moz-transform: translateX(-275px);
                    -webkit-transform: translateX(-275px);
                    -ms-transform: translateX(-275px);
                    transform: translateX(-275px);
                    -moz-transition: -moz-transform 0.5s ease;
                    -webkit-transition: -webkit-transform 0.5s ease;
                    -ms-transition: -ms-transform 0.5s ease;
                    transition: transform 0.5s ease;
                    display: block;
                    height: 100%;
                    left: 0;
                    overflow-y: auto;
                    position: fixed;
                    top: 0;
                    width: 275px;
                    z-index: 10002;
                    color: #858484;
                    background: #000;
                    box-shadow: inset -3px 0px 5px 0px rgba(0, 0, 0, 0.35);
                }
                 
                 
                body.navPanel-visible {
                    overflow-x: hidden;
                     
                    .root.responsivegrid {
                        -moz-transform: translateX(290px);
                        -webkit-transform: translateX(290px);
                        -ms-transform: translateX(290px);
                        transform: translateX(290px);
                    }
                     
                     #toggleNav {
                        -moz-transform: translateX(275px);
                        -webkit-transform: translateX(275px);
                        -ms-transform: translateX(275px);
                        transform: translateX(275px);
                    }
                     
                    #mobileNav {
                        -moz-transform: translateX(0);
                        -webkit-transform: translateX(0);
                        -ms-transform: translateX(0);
                        transform: translateX(0);
                    }
                     
            }    
        }

    The mobile nav will be scoped by the .cmp-navigation--mobile class. Several CSS transform rules are used to animate the mobile navigation opening and closing.

    Finally update /apps/wknd/clientlibs/clientlib-site/components/navigation/navigation.less to include the nav-mobile.less file: 

    /* WKND navigation styles */
    
    @import "styles/nav-footer.less";
    @import "styles/nav-header.less";
    @import "styles/nav-mobile.less";
  2. Create JavaScript for the Mobile Navigation

    Beneath /apps/wknd/clientlibs/clientlib-site/components/navigation

    1. Create a new file named navigation.js
    2. Populate it with the following:
    // Wrap bindings in anonymous namespace to prevent collisions
    jQuery(function($) {
        "use strict";
    
     function applyComponentStyles() {
    
      //Top Level Navigation (expected to only be one of these)
      $("#header-navbar .cmp-navigation").not("[data-top-nav-processed='true']").each(function() {
                // Mark the component element as processed to avoid the cyclic processing (see .not(..) above).
                var nav = $(this).attr("data-top-nav-processed", true),
                    $body = $('body');
                
                // Toggle Nav
                $('<div id="toggleNav">' +
                     '<a href="#mobileNav" class="toggle"><i class="wkndicon wkndicon-ico-bm" aria-hidden="true"></i></a>' +
                    '</div>'
                ).appendTo($body);
                
             // Navigation Panel.
                $(
                    '<div id="mobileNav" class="cmp-navigation--mobile">' +
                        '<nav class="cmp-navigation">' +
                            $(this).html() +
                        '</nav>' +
                    '</div>'
                )
                    .appendTo($body)
                    .panel({
                        delay: 500,
                        hideOnClick: true,
                        hideOnSwipe: true,
                        resetScroll: true,
                        resetForms: true,
                        side: 'left',
                        target: $body,
                        visibleClass: 'navPanel-visible'
                    });
            });
        }
    
      applyComponentStyles();
      
      $(".responsivegrid").bind("DOMNodeInserted", applyComponentStyles);
    });

    The above code will get called when the responsivegrid is added to the DOM. The first jQuery selector searches for the navigation in the Header. There is expected to only be one. There is a top-level check to avoid duplicate processing, in the case when the component is added via the AEM editor.

    Next an anchor tag is appended to the body. This is what users will click to toggle the mobile navigation. After that the header navigation is copied into a new div with an id of mobileNav and a class of cmp-navigation--mobile. This is the mobile navigation and is appended to the body.

    Finally a panel function is attached to toggle the mobile navigation visibility. This panel functionality is defined in a 3rd party utility file.

  3. Add 3rd party util.js 

    Next, add a 3rd party javascript file modified from https://html5up.net/ to allow for click and swipe support of the mobile navigation.

    Beneath /apps/wknd/clientlibs/clientlib-site

    1. Create a new folder named js
    2. Beneath the js folder, create a new file named util.js
    3. Populate it with the following util.js 
      (we have included it as a link to GitHub since the code snippet is very long)
    2018-11-16_at_5_28pm
  4. Update js.txt to include new javascript files

    1. Update /apps/wknd/clientlibs/clientlib-site/js.txt to include the navigation.js and util.js files:
    #base=.
    
    js/util.js
    components/page/page.js
    components/navigation/navigation.js
    
  5. Deploy the code to AEM

  6. Final configurations and wrap up can be seen in the below video

Putting It Together


Help!

If you get stuck or have additional questions make sure to check out the Experience League forums for AEM or view existing GitHub issues

Didn't find what you were looking for? Think you found an error? Please file a GitHub issue for the WKND project

Next Steps

Next part in the tutorial: 

Download

Esta obra está licenciada sob uma licença não adaptada da Creative Commons Attribution-Noncommercial-Share Alike 3.0  As publicações do Twitter™ e do Facebook não são cobertas pelos termos do Creative Commons.

Avisos legais   |   Política de privacidade online