hybris 6.2 frontend updates

This article is focused on the storefront-related changes in hybris 6.2, specifically in HTML templates, styles and javascripts. If you are considering an update to 6.2 from the previous versions (especially, hybris 6.1), this information should be useful.

Some of the updates listed below have not been documented yet on official hybris documentation.

Summary

In short, there are the following main updates in hybris 6.2:

  • minor changes in CSS style names
  • grouping variants in search results
  • supporting new target price discount
  • gift coupon (the promotion action result) on the thank-you-for-the-order page
  • new device breakpoints (resolution tiers) used for the responsive mode
  • minor changes in in-page navigation
  • new CMS components are used for the navigation
  • cart page uses AJAX for vouchers (apply/remove)
  • for configurable products the URL has been changed (/p/XXX/configure -> /p/XXX/configuratorPage)

Top level templates

page.tag

  • Skip to content, Skip to Navigation was added
  • card restoration was added
<main class="page-margin" data-currency-iso-code="${currentCurrency.isocode}">

			<header:header hideHeaderLinks="${hideHeaderLinks}" />

				<common:globalMessages />
				<jsp:doBody />

			<footer:footer />
		</main>

was replaced with:

<div class="branding-mobile hidden-md hidden-lg">
<div class="js-mobile-logo">
				<%--populated by JS acc.navigation--%></div>
</div>
<main data-currency-iso-code="${currentCurrency.isocode}">
			<spring:theme code="text.skipToContent" var="skipToContent" />
			<a href="#skip-to-content" class="skiptocontent" data-role="none">${skipToContent}</a>
			<spring:theme code="text.skipToNavigation" var="skipToNavigation" />
			<a href="#skiptonavigation" class="skiptonavigation" data-role="none">${skipToNavigation}</a>
			<header:header hideHeaderLinks="${hideHeaderLinks}" />
			<a id="skip-to-content"></a>
<div>
				<common:globalMessages />
				<cart:cartRestoration />
				<jsp:doBody /></div>
<footer:footer />
		</main>

Javascripts

ACC.cart (acc.cart.js)

  • handleApplyVoucher and bindToReleaseVoucher , appendAppliedVoucherCodes

ACC.common (acc.common.js)

in hybris 6.1 the currentCurrency was hard-coded (“USD”). The new fragment looks as following: currentCurrency: $("main").data('currencyIsoCode') || "USD"

ACC.productDetail (acc.productDetail.js)

  • checkQtySelector: a bug with disabling “+” button was fixed.

ACC.quickOrder (acc.quickOrder.js)

        clearQuickOrderRow: function () {
            var quickOrderMinRows = ACC.quickorder.$quickOrderMinRows;
            var parentLi = ACC.quickorder.getCurrentParentLi(this);
            if ($('.js-ul-container li.js-li-container').length > quickOrderMinRows) {
                parentLi.remove();
                ACC.quickorder.bindClearQuickOrderRow();
            }
            else {

ACC.ratingstars (acc.ratingstars.js)

Significantly refactored, 90% of the code was changed.

Styles

the CSS class names were slightly changed. For example, item-price became item__price , cart__list, became item__list__car, item-sku-input became item__sku__input

Product

reviewsTab.jsp

Original fragment from hybris 6.1:

<div class="rating js-ratingCalc" 				data-rating='{"rating":"${review.rating}","total":5}'>
<div class="rating-stars">
					<span class="js-ratingIcon glyphicon glyphicon-star"></span></div>
</div>

was replaced with

<div class="rating">
<div class="rating-stars pull-left js-ratingCalc " data-rating='{"rating":"${review.rating}","total":5}' >
<div class="greyStars">
                        <c:forEach  begin="1" end="5">
                            <span class="glyphicon glyphicon-star"></span>
                        </c:forEach></div>
<div class="greenStars js-greenStars">
                        <c:forEach  begin="1" end="5">
                            <span class="glyphicon glyphicon-star active"></span>
                        </c:forEach></div>
</div>
</div>

productListerGridItem.tag

the following fragment was added in 6.2:

<c:forEach var="variantOption" items="${product.variantOptions}">
				<c:forEach items="${variantOption.variantOptionQualifiers}" var="variantOptionQualifier">
					<c:if test="${variantOptionQualifier.qualifier eq 'rollupProperty'}">
	                    <c:set var="rollupProperty" value="${variantOptionQualifier.value}"/>
	                </c:if>
					<c:if test="${variantOptionQualifier.qualifier eq 'thumbnail'}">
	                    <c:set var="imageUrl" value="${variantOptionQualifier.value}"/>
	                </c:if>
	                <c:if test="${variantOptionQualifier.qualifier eq rollupProperty}">
	                    <c:set var="variantName" value="${variantOptionQualifier.value}"/>
	                </c:if>
				</c:forEach>
				<img style="width: 32px; height: 32px;" src="${imageUrl}" title="${variantName}" alt="${variantName}"/>
			</c:forEach>

productPageReviews.tag

This fragment

<div class="rating rating-set js-ratingCalcSet" 					data-rating='{"total":5}'>
<div class="rating-stars">
						<span class="js-ratingIcon js-rationIconSet glyphicon glyphicon-star"></span>

was replaced with

<div class="rating rating-set js-ratingCalcSet">
<div class="rating-stars js-writeReviewStars">
                        <c:forEach  begin="1" end="10" varStatus="loop">
                            <span class="js-ratingIcon glyphicon glyphicon-star ${loop.index % 2 == 0 ? 'lh' : 'fh'}"></span>
                        </c:forEach>

productPricePanel.tag

Some style names were changed (see the Styles section)

productReviewsSummary.tag

The following fragment from 6.1

<div class="rating js-ratingCalc ${starsClass}" data-rating='{"rating":"${product.averageRating}","total":5}'>
<div class="rating-stars">
		<span class="js-ratingIcon glyphicon glyphicon-star"></span></div>
...</div>

was replaced with

<div class="rating">
<div class="rating-stars pull-left js-ratingCalc ${starsClass}" data-rating='{"rating":"${product.averageRating}","total":5}' >
<div class="greyStars">
            <c:forEach  begin="1" end="5">
                <span class="glyphicon glyphicon-star"></span>
            </c:forEach></div>
<div class="greenStars js-greenStars">
            <c:forEach  begin="1" end="5">
                <span class="glyphicon glyphicon-star active"></span>
            </c:forEach></div>
</div>
...</div>

Order

accountOrderDetailsItem.tag

Small changes in CSS styles (like “item-info” -> “item__info”)

orderEntryDetails.tag

Small changes in CSS styles (like “item-list-item” -> “item__list–item”)

orderTotalsItem.tag

order.orderDiscounts was replaced with order.TotalDiscounts:

<c:if test="${order.totalDiscounts.value > 0}">
...
                    <ycommerce:testId code="orderTotal_discount_label">
                        -<format:price priceData="${order.totalDiscounts}" displayFreeForZero="false"/>
                    </ycommerce:testId>
...
</c:if>

Previously order.totalDiscounts should be positive to show order total taxes section. Now this section doesn’t depend on totalDiscounts.

OrderUnconsignedEntries.tag

Some style names were changed (see the Styles section)

giftCoupon.tag

This file is a brand-new in hybris 6.2.

<%@ tag body-content="empty" trimDirectiveWhitespaces="true" %>
<%@ attribute name="giftCoupon" required="true" type="de.hybris.platform.commercefacades.coupon.data.CouponData" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="ycommerce" uri="http://hybris.com/tld/ycommercetags" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

<spring:htmlEscape defaultHtmlEscape="true" />

<c:if test="${not empty giftCoupon}">
<div class="gift__coupon">
		<ycommerce:testId code="checkout_orderConfirmation_giftCoupon">

			<span class="gift__coupon--title">
                <spring:theme code="checkout.orderConfirmation.get.coupon"/>
            </span>
			<span class="gift__coupon--name">
			    ${fn:escapeXml(giftCoupon.name)}
            </span>
			<span class="gift__coupon--code">
                <spring:theme code="checkout.orderConfirmation.coupon.code" arguments="${giftCoupon.couponCode}"/>
            </span>

		</ycommerce:testId></div>
</c:if>

Common

globalMessages.tag

Global Alerts are now enclosed in div class=container:

<div class="container">
<div class="global-alerts">
...</div>
</div>

ConfigurationInfos.tag

<c:forEach items="${entry.configurationInfos}" var="configurationInfo">
<div>${configurationInfo.configurationLabel}: ${configurationInfo.configurationValue}</div>
</c:forEach>

was replaced with

<c:forEach items="${entry.configurationInfos}" var="configurationInfo">
<div>
          ${configurationInfo.configurationLabel}
          <c:if test="${not empty configurationInfo.configurationLabel}">: </c:if>
          ${configurationInfo.configurationValue}</div>
</c:forEach>

header.tag

The security conditions are “upgraded”:

<sec:authorize ifNotGranted="ROLE_ANONYMOUS">

with the new version:

<sec:authorize access="!hasAnyRole('ROLE_ANONYMOUS')">

Cart

cartDisplay.jsp

 <sec:authorize access="!hasAnyRole('ROLE_ANONYMOUS')"> .. </sec:authorize>

was replaced with

 <sec:authorize ifNotGranted="ROLE_ANONYMOUS"> .. </sec:authorize>

cartItems.tag

Small changes in CSS style names (see Styles section)

cartVoucher.tag

A number of significant changes.

<div class="form-group js-voucher-respond">

was replaced with:

<spring:url value="/cart/voucher/apply" var="applyVoucherAction"/>
<spring:url value="/cart/voucher/remove" var="removeVoucherAction"/>

<c:set var="containerClass">
    <c:choose>
        <c:when test="${not empty errorMsg}">has-error</c:when>
        <c:when test="${not empty successMsg}">has-success</c:when>
        <c:otherwise></c:otherwise>
    </c:choose>
</c:set>

the Form became comprehensive:

<div class="form-group js-voucher-respond ${containerClass}">
    <spring:theme code="text.voucher.apply.input.placeholder" var="voucherInputPlaceholder"/>
    <label class="control-label cart-voucher__label" for="voucher-code"><spring:theme             code="text.voucher.apply.input.label"/></label>
    <form:form id="applyVoucherForm" action="${applyVoucherAction}" method="post" commandName="voucherForm">
        <form:input cssClass="js-voucher-code cart-voucher__input form-control input-sm" name="voucher-code"                     id="js-voucher-code-text" maxlength="100" placeholder="${voucherInputPlaceholder}"                     path="voucherCode"/>
        <button type="button" id="js-voucher-apply-btn" class="btn btn-primary btn-small cart-voucher__btn">
            <spring:theme code="text.voucher.apply.button.label"/></button>
    </form:form>
<div class="js-voucher-validation-container help-block cart-voucher__help-block">
        ${errorMsg}
        ${successMsg}</div>
</div>
<ul id="js-applied-vouchers" class="selected_product_ids clearfix voucher-list">
    <c:forEach items="${cartData.appliedVouchers}" var="voucher" varStatus="loop">
	<li class="voucher-list__item">
            <form:form id="removeVoucherForm${loop.index}" action="${removeVoucherAction}" method="post"                        commandName="voucherForm">
                <span class="js-release-voucher voucher-list__item-box" id="voucher-code-${voucher}">
                     ${voucher}
                     <form:input hidden="hidden" value="${voucher}" path="voucherCode"/>
                    <span class="glyphicon glyphicon-remove js-release-voucher-remove-btn voucher-list__item-remove"/>
                </span>
            </form:form></li>
</c:forEach></ul>

Ugly javascript code was removed.

Checkout

guestLogin.jsp

the same changes as in cartDisplay.jsp.

addPaymentMethodPage.jsp

the same changes as in cartDisplay.jsp.

silentOrderPostPage.jsp

the same changes as in cartDisplay.jsp.

checkoutConfirmationThankMessage.jsp

...
<order:giftCoupon giftCoupon="${giftCoupon}"/>
...

checkoutOrderSummary.tag

Small changes in CSS style names (see Styles section)

pickupCartItems

<div class="details">
...
<common:configurationInfos entry="${entry}"/></div>

Address

addressFormSelector.tag

The same changes as in header.tag.

Variables

Constants for the responsive behavior were also changed:

The version from 6.1:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="screenXs" value="480px" scope="session"/>
<c:set var="screenSm" value="768px" scope="session"/>
<c:set var="screenMd" value="992px" scope="session"/>
<c:set var="screenLg" value="1200px" scope="session"/>

<c:set var="screenXsMin" value="480px" scope="session"/>
<c:set var="screenSmMin" value="768px" scope="session"/>
<c:set var="screenMdMin" value="992px" scope="session"/>
<c:set var="screenLgMin" value="1200px" scope="session"/>

<c:set var="screenXsMax" value="767px" scope="session"/>
<c:set var="screenSmMax" value="991px" scope="session"/>
<c:set var="screenMdMax" value="1199px" scope="session"/>

A new version:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="screenXs" value="480px" scope="session"/>
<c:set var="screenSm" value="640px" scope="session"/>
<c:set var="screenMd" value="1024px" scope="session"/>
<c:set var="screenLg" value="1400px" scope="session"/>

<c:set var="screenXsMin" value="480px" scope="session"/>
<c:set var="screenSmMin" value="640px" scope="session"/>
<c:set var="screenMdMin" value="1024px" scope="session"/>
<c:set var="screenLgMin" value="1400px" scope="session"/>

<c:set var="screenXsMax" value="639px" scope="session"/>
<c:set var="screenSmMax" value="1023px" scope="session"/>
<c:set var="screenMdMax" value="1399px" scope="session"/>

Error pages

serverError.jsp

A brand-new template for displaying server errors.

<%@ page trimDirectiveWhitespaces="true" %>
<!DOCTYPE html>
<html>
    <head>
        <title>Server Error</title>
    </head>
    <body>

Server Error

    </body>
</html>

Account

accountLayoutPage.jsp

Restructured. Some fragments were moved to components.
The version of the template from 6.1:

..
<div class="container">
<div class="col-xs-12 col-sm-9">
<h2 class="h2">My Profile</h2>
<cms:pageSlot position="TopContent" var="feature" element="div" class="accountPageTopContent">
<div class="panel panel-primary panel-list">
<div class="panel-heading">
						<cms:component component="${feature}" /></div>
</div>
</cms:pageSlot>
			<cms:pageSlot position="TopInfoContent" var="feature" element="div">
				<cms:component component="${feature}" />
			</cms:pageSlot>
			<cms:pageSlot position="BodyContent" var="feature" element="div" class="accountPageBodyContent">
<div class="panel panel-primary panel-list">
					<cms:component component="${feature}" /></div>
</cms:pageSlot>
			<cms:pageSlot position="BottomContent" var="feature" element="div" class="accountPageBottomContent">
<div class="panel panel-primary panel-list">
<div class="panel-heading">
						<cms:component component="${feature}" /></div>
</div>
</cms:pageSlot></div>
<div class="col-xs-12 col-sm-3 side-to-top">
<aside id="sidebar">
<div class="promotions hidden-xs">
					<cms:pageSlot position="SideContent" var="feature" class="accountPageSideContent">
						<cms:component component="${feature}" element="section" />
					</cms:pageSlot></div>
</aside></div>
</div>
..

The version from 6.2:

		<cms:pageSlot position="SideContent" var="feature" class="accountPageSideContent">
			<cms:component component="${feature}" />
		</cms:pageSlot>
		<cms:pageSlot position="TopContent" var="feature" element="div" class="accountPageTopContent">
		        <cms:component component="${feature}" />
		</cms:pageSlot>
<div class="account-section">
                        <cms:pageSlot position="BodyContent" var="feature" element="div" class="account-section-content">
                           <cms:component component="${feature}" />
                        </cms:pageSlot></div>
<cms:pageSlot position="BottomContent" var="feature" element="div" class="accountPageBottomContent">
		          <cms:component component="${feature}" />
		</cms:pageSlot>

accountLoginPage.jsp

The version from 6.1:

<div class="container login-page">
<div class="row">
<div class="col-xs-12 col-sm-offset-1 col-sm-10 login-form-wrap">
<div class="col-xs-12">
<h2 class="h2"><spring:message code="login.title" text="Login / Register" /></h2>
</div>
<div class="col-sm-5 clearfix divide">
					<cms:pageSlot position="LeftContentSlot" var="feature">
						<cms:component component="${feature}" />
					</cms:pageSlot></div>
<div class="col-sm-offset-2 col-sm-5 clearfix">
					<cms:pageSlot position="RightContentSlot" var="feature">
						<cms:component component="${feature}" />
					</cms:pageSlot></div>
</div>
</div>
</div>

The version from 6.2:

<div class="row">
<div class="col-md-6">
			<cms:pageSlot position="LeftContentSlot" var="feature" element="div" class="login-left-content-slot">
				<cms:component component="${feature}"  element="div" class="login-left-content-component"/>
			</cms:pageSlot></div>
<div class="col-md-6">
			<cms:pageSlot position="RightContentSlot" var="feature" element="div" class="login-right-content-slot">
				<cms:component component="${feature}"  element="div" class="login-right-content-component"/>
			</cms:pageSlot></div>
</div>

accountNewCustomerLogin.jsp

Minor changes in the names of CSS styles.

accountPaymentInfoPage.jsp

A number of changes, too long to list them all. The new version of the file is below.

<c:set var="noBorder" value=""/>
<c:if test="${not empty paymentInfoData}">
    <c:set var="noBorder" value="no-border"/>
</c:if>
<div class="account-section-header ${noBorder}">
    <spring:theme code="text.account.paymentDetails" /></div>
<c:choose>
    <c:when test="${not empty paymentInfoData}">
<div class="account-paymentdetails account-list">
<div class="account-cards card-select">
<div class="row">
                	<c:forEach items="${paymentInfoData}" var="paymentInfo">
<div class="col-xs-12 col-sm-6 col-md-4 card">
<ul class="pull-left">
	<li>
                                    <c:if test="${paymentInfo.defaultPaymentInfo}">
                                    	<strong>
                                    </c:if>
                                    	${fn:escapeXml(paymentInfo.accountHolderName)}<c:if test="${paymentInfo.defaultPaymentInfo}" >&nbsp;(<spring:theme code="text.default" />)</c:if>
                                    <c:if test="${paymentInfo.defaultPaymentInfo}" ></strong></c:if></li>
	<li>${fn:escapeXml(paymentInfo.cardTypeData.name)}</li>
	<li>
                                    <ycommerce:testId code="paymentDetails_item_cardNumber_text" >${fn:escapeXml(paymentInfo.cardNumber)}</ycommerce:testId></li>
	<li>
                                    <c:if test="${paymentInfo.expiryMonth lt 10}">0</c:if>
                                        ${fn:escapeXml(paymentInfo.expiryMonth)}&nbsp;/&nbsp;${fn:escapeXml(paymentInfo.expiryYear)}</li>
<c:if test="${paymentInfo.billingAddress ne null}">
	<li>${fn:escapeXml(paymentInfo.billingAddress.line1)}</li>
	<li>${fn:escapeXml(paymentInfo.billingAddress.town)}&nbsp;${fn:escapeXml(paymentInfo.billingAddress.region.isocodeShort)}</li>
	<li>${fn:escapeXml(paymentInfo.billingAddress.country.name)}&nbsp;${fn:escapeXml(paymentInfo.billingAddress.postalCode)}</li>
</c:if></ul>
<div class="account-cards-actions pull-left">
                                <ycommerce:testId code="paymentDetails_deletePayment_button" >
                                    <a class="action-links removePaymentDetailsButton" href="#" data-payment-id="${paymentInfo.id}" data-popup-title="<spring:theme code="text.account.paymentDetails.delete.popup.title"/>">
                                        <span class="glyphicon glyphicon-remove"></span>
                                    </a>
                                </ycommerce:testId></div>
<c:if test="${not paymentInfo.defaultPaymentInfo}" >
                                <c:url value="/my-account/set-default-payment-details" var="setDefaultPaymentActionUrl"/>
                                <form:form id="setDefaultPaymentDetails${paymentInfo.id}" action="${setDefaultPaymentActionUrl}" method="post">
                                    <input type="hidden" name="paymentInfoId" value="${paymentInfo.id}"/>
                                    <ycommerce:testId code="paymentDetails_setAsDefault_button" >
                                        <button type="submit" class="account-set-default-address">
                                            <spring:theme code="text.setDefault" text="Set as Default" />
                                        </button>
                                    </ycommerce:testId>
                                </form:form>
                            </c:if></div>
<div class="display-none">
<div id="popup_confirm_payment_removal_${paymentInfo.id}" class="account-address-removal-popup">
	                            <spring:theme code="text.account.paymentDetails.delete.following"/>
<div class="address">
	                                <strong>
	                                ${fn:escapeXml(paymentInfo.accountHolderName)}
	                                </strong>

${fn:escapeXml(paymentInfo.cardTypeData.name)}

${fn:escapeXml(paymentInfo.cardNumber)}

	                                <c:if test="${paymentInfo.expiryMonth lt 10}">0</c:if>
	                                ${fn:escapeXml(paymentInfo.expiryMonth)}&nbsp;/&nbsp;${fn:escapeXml(paymentInfo.expiryYear)}
	                                <c:if test="${paymentInfo.billingAddress ne null}">

${fn:escapeXml(paymentInfo.billingAddress.line1)}

${fn:escapeXml(paymentInfo.billingAddress.town)}&nbsp;${fn:escapeXml(paymentInfo.billingAddress.region.isocodeShort)}

${fn:escapeXml(paymentInfo.billingAddress.country.name)}&nbsp;${fn:escapeXml(paymentInfo.billingAddress.postalCode)}
	                                </c:if></div>
<c:url value="/my-account/remove-payment-method" var="removePaymentActionUrl"/>
	                            <form:form id="removePaymentDetails${paymentInfo.id}" action="${removePaymentActionUrl}" method="post">
	                                <input type="hidden" name="paymentInfoId" value="${paymentInfo.id}"/>
<div class="modal-actions">
<div class="row">
	                                        <ycommerce:testId code="paymentDetailsDelete_delete_button" >
<div class="col-xs-12 col-sm-6 col-sm-push-6">
	                                                <button type="submit" class="btn btn-default btn-primary btn-block paymentsDeleteBtn">
	                                                    <spring:theme code="text.account.paymentDetails.delete"/>
	                                                </button></div>
</ycommerce:testId>
<div class="col-xs-12 col-sm-6 col-sm-pull-6">
	                                            <a class="btn btn-default closeColorBox paymentsDeleteBtn btn-block" data-payment-id="${paymentInfo.id}">
	                                                <spring:theme code="text.button.cancel" />
	                                            </a></div>
</div>
</div>
</form:form></div>
</div>
</c:forEach></div>
</div>
</div>
</c:when>
    <c:otherwise>
<div class="account-section-content content-empty">
            <spring:theme code="text.account.paymentDetails.noPaymentInformation" /></div>
</c:otherwise>
</c:choose>

accountSavedCartDetailsItem.jsp

Minor changes in the names of CSS styles.

Search

searchEmptyPage.jsp

Minor changes in the names of CSS styles.

CMS Components

Language Currency Component

the component itself and the template languagecurrencycomponent.jsp NO LONGER EXIST.

Category Navigation Component

A brand new component, so a new template categorynavigationcomponent.jsp is introduced.

<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="cms" uri="http://hybris.com/tld/cmstags"%>

<c:if test="${component.visible}">
<nav class="navigation navigation--bottom js_navigation--bottom js-enquire-offcanvas-navigation" role="navigation">
<ul class="sticky-nav-top hidden-lg hidden-md js-sticky-user-group hidden-md hidden-lg">
                <%--Dynamically generated by 'acc.navigation.js"--%></ul>
<div class="navigation__overflow">
<ul data-trigger="#signedInUserOptionsToggle" class="nav__links nav__links--products nav__links--mobile js-userAccount-Links js-nav-collapse-body offcanvasGroup1 collapse in hidden-md hidden-lg">
                   <%--Dynamically generated by 'acc.navigation.js"--%></ul>
<ul class="nav__links nav__links--products js-offcanvas-links">
				<c:forEach items="${component.navigationNode.children}" var="childLevel1">
	<li class="auto nav__links--primary <c:if test="${not empty childLevel1.children}">nav__links--primary-has__sub js-enquire-has-sub</c:if>">
						<c:forEach items="${childLevel1.entries}" var="childlink1">
							<cms:component component="${childlink1.item}" evaluateRestriction="true" element="span" class="nav__link js_nav__link" />
						</c:forEach>

						<%-- Calculate how many sub columns are needed -- Start --%>
						<c:set var="totalSubNavigationColumns" value="${0}"/>
						<c:set var="hasSubChild" value="false"/>
						<c:forEach items="${childLevel1.children}" var="childLevel2">
							<c:if test="${not empty childLevel2.children}">
								<c:set var="hasSubChild" value="true"/>
								<c:set var="subSectionColumns" value="${fn:length(childLevel2.children)/component.wrapAfter}"/>
								<c:if test="${subSectionColumns > 1 && fn:length(childLevel2.children)%component.wrapAfter > 0}">
									<c:set var="subSectionColumns" value="${subSectionColumns + 1}"/>
								</c:if>
								<c:choose>
									<c:when test="${subSectionColumns > 1}">
										<c:set var="totalSubNavigationColumns" value="${totalSubNavigationColumns + subSectionColumns}" />
									</c:when>

									<c:when test="${subSectionColumns < 1}">
										<c:set var="totalSubNavigationColumns" value="${totalSubNavigationColumns + 1}" />
									</c:when>
								</c:choose>
							</c:if>
						</c:forEach>
						<%-- Calculate how many sub columns are needed -- End --%>

						<%-- Decide which class to use -- Start --%>
						<c:choose>
							<c:when test="${!hasSubChild || (totalSubNavigationColumns > 0 && totalSubNavigationColumns <= 1)}">
								<c:set value="col-md-3 col-lg-2" var="subNavigationClass"/>
								<c:set value="col-md-12" var="subNavigationItemClass"/>
							</c:when>

							<c:when test="${totalSubNavigationColumns == 2}">
								<c:set value="col-md-6 col-lg-4" var="subNavigationClass"/>
								<c:set value="col-md-6" var="subNavigationItemClass"/>
							</c:when>

							<c:when test="${totalSubNavigationColumns == 3}">
								<c:set value="col-md-9 col-lg-6" var="subNavigationClass"/>
								<c:set value="col-md-4" var="subNavigationItemClass"/>
							</c:when>

							<c:when test="${totalSubNavigationColumns == 4}">
								<c:set value="col-md-12 col-lg-8" var="subNavigationClass"/>
								<c:set value="col-md-3" var="subNavigationItemClass"/>
							</c:when>

							<c:when test="${totalSubNavigationColumns == 5}">
								<c:set value="col-md-12" var="subNavigationClass"/>
								<%--custom grid class required because 1/5th columns aren't supported by bootstrap--%>
								<c:set value="column-20-percent" var="subNavigationItemClass"/>
							</c:when>

							<c:when test="${totalSubNavigationColumns > 5}">
								<c:set value="col-md-12" var="subNavigationClass"/>
								<c:set value="col-md-2" var="subNavigationItemClass"/>
							</c:when>
						</c:choose>
						<%-- Decide which class to use -- End --%>

						<c:if test="${not empty childLevel1.children}"><span class="glyphicon  glyphicon-chevron-right hidden-md hidden-lg nav__link--drill__down js_nav__link--drill__down"></span>
<div class="sub__navigation js_sub__navigation ${subNavigationClass}">
								<a class="sm-back js-enquire-sub-close hidden-md hidden-lg" href="#">Back</a>
<div class="row">
									<c:choose>
									    <c:when test="${hasSubChild}">
									        <c:forEach items="${childLevel1.children}" var="childLevel2">
<div class="sub-navigation-section ${subNavigationItemClass}">
													<c:if test="${not empty childLevel2.title}">
<div class="title">${childLevel2.title}</div>
</c:if>
<ul class="sub-navigation-list <c:if test="${not empty childLevel2.title}">has-title</c:if>">
														<c:forEach items="${childLevel2.children}" var="childLevel3" step="${component.wrapAfter}" varStatus="i">
															<%-- wrap if more than 'component.wrapAfter' rows in one sub column --%>
															<c:if test="${i.index>=component.wrapAfter}">
																<c:if test="${!i.first}"></ul>
</div>
</c:if>
<div class="sub-navigation-section ${subNavigationItemClass}">
<ul class="sub-navigation-list <c:if test="${not empty childLevel2.title}">has-title</c:if>">
															</c:if>
															<c:forEach items="${childLevel2.children}" var="childLevel3" begin="${i.index}" end="${i.index + component.wrapAfter - 1}">
																<c:forEach items="${childLevel3.entries}" var="childlink3" >
																	<cms:component component="${childlink3.item}" evaluateRestriction="true" element="li" class="nav__link--secondary" />
																</c:forEach>
															</c:forEach>
														</c:forEach></ul>
</div>
</c:forEach>
									    </c:when>
									    <c:otherwise>
<div class="sub-navigation-section ${subNavigationItemClass}">
<ul class="sub-navigation-list <c:if test="${not empty childLevel2.title}">has-title</c:if>">
										        	<c:forEach items="${childLevel1.children}" var="childLevel2">
														<c:forEach items="${childLevel2.entries}" var="childlink2">
															<cms:component component="${childlink2.item}" evaluateRestriction="true" element="li" class="nav__link--secondary" />
														</c:forEach>
													</c:forEach></ul>
</div>
</c:otherwise>
									</c:choose></div>
</div>
</c:if></li>
</c:forEach></ul>
</div>
</nav>

</c:if>

Footer Navigation Component

A brand new component, so a new template footernavigationcomponent.jsp is introduced.

<%@ page trimDirectiveWhitespaces="true"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="cms" uri="http://hybris.com/tld/cmstags"%>
<%@ taglib prefix="footer" tagdir="/WEB-INF/tags/responsive/common/footer"  %>

<c:if test="${component.visible}">
<div class="container-fluid">
<div class="footer__top">
<div class="row">
<div class="footer__left col-xs-12 col-sm-12 col-md-9">
<div class="row">
	                	<c:forEach items="${component.navigationNode.children}" var="childLevel1">
		                	<c:forEach items="${childLevel1.children}" step="${component.wrapAfter}" varStatus="i">
<div class="footer__nav--container col-xs-12 col-sm-3">
		                	       <c:if test="${component.wrapAfter > i.index}">
<div class="title">${childLevel1.title}</div>
</c:if>
<ul class="footer__nav--links">
	                                   <c:forEach items="${childLevel1.children}" var="childLevel2" begin="${i.index}" end="${i.index + component.wrapAfter - 1}">
	                                        <c:forEach items="${childLevel2.entries}" var="childlink" >
		                                        <cms:component component="${childlink.item}" evaluateRestriction="true" element="li" class="footer__link"/>
	                                        </c:forEach>
	                                   </c:forEach></ul>
</div>
</c:forEach>
	                	</c:forEach></div>
</div>
<div class="footer__right col-xs-12 col-md-3">
	               <c:if test="${showLanguageCurrency}">
<div class="row">
<div class="col-xs-6 col-md-6 footer__dropdown">
	                           <footer:languageSelector languages="${languages}" currentLanguage="${currentLanguage}" /></div>
<div class="col-xs-6 col-md-6 footer__dropdown">
	                           <footer:currencySelector currencies="${currencies}" currentCurrency="${currentCurrency}" /></div>
</div>
</c:if></div>
</div>
</div>
</div>
<div class="footer__bottom">
<div class="footer__copyright">
<div class="container">${notice}</div>
</div>
</div>
</c:if>

addToCartAction.jsp

...
<c:url value="${product.url}/configuratorPage/${configuratorType}" var="configureProductUrl"/>
...
<form:form method="post" id="configureForm" class="configure_form" action="${configureProductUrl}">
...
  	    <c:when test="${fn:contains(buttonType, 'button')}">
            ...
	    <button id="configureProduct" type="button" class="btn btn-primary btn-block js-enable-btn outOfStock" disabled="disabled">
            ...
            </c:when>
            <c:otherwise>
            <c:if test="${product.configurable}">
                <button id="configureProduct" type="${buttonType}" class="btn btn-primary btn-block js-enable-btn" disabled="disabled"                         name="configure">
                    <spring:theme code="basket.configure.product"/>
                </button>
            </c:if>
            </c:otherwise>
...
</form:form>
<form:form method="post" id="addToCartForm" class="add_to_cart_form" action="${addToCartUrl}">
<c:if test="${product.purchasable}">
	<input type="hidden" maxlength="3" size="1" id="qty" name="qty" class="qty js-qty-selector-input" value="1">
</c:if>
<input type="hidden" name="productCodePost" value="${product.code}"/>

<c:if test="${empty showAddToCart ? true : showAddToCart}">
	<c:set var="buttonType">button</c:set>
	<c:if test="${product.purchasable and product.stock.stockLevelStatus.code ne 'outOfStock' }">
		<c:set var="buttonType">submit</c:set>
	</c:if>
	<c:choose>
		<c:when test="${fn:contains(buttonType, 'button')}">
                   ...
                </c:when>
        </c:choose>
</c:if>
</form:form>

navigationBarCollectionComponent.jsp

version from 6.1:

<ul class="y_navbar nav navbar-nav">
		<c:forEach items="${components}" var="component">
			<c:if test="${component.navigationNode.visible}">
				<cms:component component="${component}" evaluateRestriction="true" navigationType="offcanvas" />
			</c:if>
		</c:forEach></ul>

new version:

<nav class="navigation navigation--bottom js_navigation--bottom js-enquire-offcanvas-navigation" role="navigation">
<ul class="sticky-nav-top hidden-lg hidden-md js-sticky-user-group hidden-md hidden-lg">
                <%--Dynamically generated by 'acc.navigation.js"--%></ul>
<div class="navigation__overflow">
<ul data-trigger="#signedInUserOptionsToggle" class="nav__links nav__links--products nav__links--mobile js-userAccount-Links js-nav-collapse-body offcanvasGroup1 collapse in hidden-md hidden-lg">
                   <%--Dynamically generated by 'acc.navigation.js"--%></ul>
<ul class="nav__links nav__links--products js-offcanvas-links">
               <c:forEach items="${components}" var="component">
                   <c:if test="${component.navigationNode.visible}">
                       <cms:component component="${component}" evaluateRestriction="true" class="nav__links--primary" element="li"                                       navigationType="offcanvas" />
                   </c:if>
               </c:forEach></ul>
</div>
</nav>

navigationBarComponent.jsp

Seriously refactored and reworked.
Version from 6.1:

	<li class="<c:if test="${not empty component.navigationNode.children}">dropdown</c:if>">
	<cms:component component="${component.link}" evaluateRestriction="true" />
	<c:if test="${not empty component.navigationNode.children}">
		<c:forEach items="${component.navigationNode.children}" var="child">
			<c:if test="${child.visible}">
<ul class="dropdown-menu">
					<c:forEach items="${child.links}" var="childlink" varStatus="i">
						<cms:component component="${childlink}" evaluateRestriction="true" element="li" />
					</c:forEach></ul>
</c:if>
		</c:forEach>

Version from 6.2:

<c:set value="${component.styleClass} ${dropDownLayout}" var="bannerClasses"/>
	<li class="${bannerClasses} nav__links--primary <c:if test="${not empty component.navigationNode.children}">nav__links--primary-has__sub js-enquire-has-sub</c:if>">

			<cms:component component="${component.link}" evaluateRestriction="true" element="span" class="nav__link js_nav__link"/>
			<c:if test="${not empty component.navigationNode.children}">

				<c:set var="totalSubNavigationColumns" value="${0}"/>

				<c:forEach items="${component.navigationNode.children}" var="subSection" varStatus="loop">
					<c:set value="${fn:length(subSection.links)/component.wrapAfter}" var="subSectionColumns"/>
					<c:choose>
						<c:when test="${subSectionColumns > 1}">
							<c:set var="totalSubNavigationColumns" value="${totalSubNavigationColumns + subSectionColumns}" />
						</c:when>

						<c:when test="${subSectionColumns < 1}">
							<c:set var="totalSubNavigationColumns" value="${totalSubNavigationColumns + 1}" />
						</c:when>
					</c:choose>

					<c:if test="${not empty subSection.title}">
						<c:set var="hasTitleClass" value="has-title"/>
					</c:if>
				</c:forEach>

				<c:choose>
					<c:when test="${totalSubNavigationColumns > 0 && totalSubNavigationColumns <= 1}">
						<c:set value="col-md-3 col-lg-2" var="subNavigationClass"/>
						<c:set value="col-md-12" var="subNavigationItemClass"/>
					</c:when>

					<c:when test="${totalSubNavigationColumns == 2}">
						<c:set value="col-md-6 col-lg-4" var="subNavigationClass"/>
						<c:set value="col-md-6" var="subNavigationItemClass"/>
					</c:when>

					<c:when test="${totalSubNavigationColumns == 3}">
						<c:set value="col-md-9 col-lg-6" var="subNavigationClass"/>
						<c:set value="col-md-4" var="subNavigationItemClass"/>
					</c:when>

					<c:when test="${totalSubNavigationColumns == 4}">
						<c:set value="col-md-12 col-lg-8" var="subNavigationClass"/>
						<c:set value="col-md-3" var="subNavigationItemClass"/>
					</c:when>

					<c:when test="${totalSubNavigationColumns == 5}">
						<c:set value="col-md-12" var="subNavigationClass"/>
						<%--custom grid class required because 1/5th columns aren't supported by bootstrap--%>
						<c:set value="column-20-percent" var="subNavigationItemClass"/>
					</c:when>

					<c:when test="${totalSubNavigationColumns > 5}">
						<c:set value="col-md-12" var="subNavigationClass"/>
						<c:set value="col-md-2" var="subNavigationItemClass"/>
					</c:when>
				</c:choose>
				<c:if test="${not empty component.navigationNode.children}"><span class="glyphicon  glyphicon-chevron-right hidden-md hidden-lg nav__link--drill__down js_nav__link--drill__down"></span></c:if>
<div class="sub__navigation js_sub__navigation ${subNavigationClass}">
					<a class="sm-back js-enquire-sub-close hidden-md hidden-lg" href="#">Back</a>
<div class="row">
					<c:forEach items="${component.navigationNode.children}" var="child">
						<c:if test="${child.visible}">
							<c:forEach items="${child.links}" step="${component.wrapAfter}" var="childlink" varStatus="i">
								<%-- for a large amount of links (depending on what wrapAfter is set to) that would exceed 6 columns, insert a clearfix div to have the next row properly aligned --%>
								<c:if test="${i.index != 0 && i.index % (6*component.wrapAfter) == 0}">
<div class="clearfix hidden-sm-down"></div>
</c:if>
<div class="sub-navigation-section ${subNavigationItemClass}">
									<%--only add title on first loop for each sub-section--%>
									<c:if test="${i.index == 0 && not empty child.title}">
<div class="title">${child.title}</div>
</c:if>
<ul class="sub-navigation-list ${hasTitleClass}">
										<c:forEach items="${child.links}" var="childlink" begin="${i.index}" end="${i.index + component.wrapAfter - 1}">
											<c:if test="${fn:contains(childlink.uid, 'BrowseAll')}">
												<span class="text-uppercase">
											</c:if>
											<cms:component component="${childlink}" evaluateRestriction="true" element="li" class="nav__link--secondary" />
											<c:if test="${fn:contains(childlink.uid, 'BrowseAll')}">
												</span>
											</c:if>
										</c:forEach></ul>
</div>
</c:forEach>
						</c:if>
					</c:forEach></div>
</div>
</c:if></li>

productAddToCartComponent.jsp

<c:set var="qtyMinus" value="1" />
...
			<span class="input-group-btn">
				<button class="btn btn-default
                                js-qty-selector-minus" type="button"
                                   <c:if test="${qtyMinus <= 1}">
                                      <c:out value="disabled='disabled'"/>
                                   </c:if> ><span                                  class="glyphicon glyphicon-minus"                                  aria-hidden="true" ></span></button>
			</span>
				<input type="text"                                  maxlength="3" class="form-control                                  js-qty-selector-input" size="1"                                  value="${qtyMinus}" data-max="${maxQty}"                                  data-min="1" name="pdpAddtoCartInput"                                  id="pdpAddtoCartInput" />
			<span class="input-group-btn">
				<button class="btn btn-default                                  js-qty-selector-plus" type="button">
                                <span class="glyphicon glyphicon-plus"                                  aria-hidden="true"></span></button>
			</span>

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: