Page templates
Global layout
The global layout can be used for inner pages on the City of Winnipeg website. It uses the global header, global footer, breadcrumbs, a search bar and sidebar navigation. Inner page content would vary based on need.
Template structure
The global page layout uses the body class of global
along with the following elements for the general page structure.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Page title</title>
</head>
<body class="global">
<!-- Insert global header here -->
<div class="container">
<div class="mt-4 mb-4">
<!-- Insert breadcrumbs here -->
</div>
<div class="row">
<div class="col-12 col-md-12 col-lg-3 col-xl-3">
<div class="sidebar">
<!-- Optional search bar -->
<div class="form-group sm search-group mb-4">
<input type="search" class="form-control form-control-sm google-search" placeholder="Search 311 City Services" aria-label="Search 311 City Services">
<button type="submit" aria-label="Search 311 City Services" class="btn btn-sm btn-search"><i aria-hidden="true" class="far fa-search"></i></button>
</div>
<!-- Insert side navigation here -->
</div>
</div>
<main class="col-12 col-sm-12 col-lg-9 col-xl-9">
<div class="cw-content">
<!-- Page content -->
</div>
</main>
</div>
</div>
<!-- Insert global footer here -->
</body>
</html>
Sample pages
These sample pages have been pre-built including all default design system CSS and JavaScript.
Sample page |
---|
Basic page (contains component examples)Download |
Basic French page (contains component examples)Download |
Basic page 2 (blank template)Download |
Basic French page 2 (blank template)Download |
Basic page for winnipeg.caDownload |
Basic page with no sidenav (blank template)Download |
Basic French page with no sidenav (blank template)Download |
Basic page with no sidenav - full width (blank template)Download |
Basic French page with no sidenav - full width (blank template)Download |
Global alert and typographyDownload |
How it works
The following JavaScript for initializing Bootstrap components and for custom component functionality has also been included (assets/js/global.js
):
- Global header
- Sidebar navigation
- Default and dark tooltips initialized
- Accordion custom add ons (custom dropdown icon toggle, and the ‘Expand all’ and ‘Collapse all’ links)
- Datepickers (single and date range) initialized
$(document).ready(function() {
/* ==================== Global header =================== */
// Search bar
$('#globalSearchInput').keyup(function(){
if($(this).val() === ''){
$('#globalSearchBtn').attr("disabled", true);
}else{
$('#globalSearchBtn').attr("disabled", false);
}
});
// Mobile menu
function openMenu(){
$('html').scrollTop( 0 );
$('.headerGradient').fadeIn(200);
$('.headerGradient').addClass('menuOpen');
$('nav.main-nav').addClass('in');
$('body').css({'position':'fixed','left':0,'right':0, 'top':0});
}
function closeMenu(){
$('.headerGradient').fadeOut(200);
$('.headerGradient').removeClass('menuOpen');
$('nav.main-nav').removeClass('in');
$('body').css({'position':'initial','left':'auto','right':'auto','top':'auto'});
}
$('.menuBtn').click(function() {
openMenu();
})
// Mobile search
function openSearch(){
$('html').scrollTop( 0 );
$('.headerGradient').fadeIn(200);
$('.global-header .search-group-container').addClass('in');
$('.global-header .search-group-container input').focus();
$('body').css({'position':'fixed','left':0,'right':0, 'top':0});
}
function closeSearch(){
$('.headerGradient').fadeOut(200);
$('.global-header .search-group-container').removeClass('in');
$('body').css({'position':'initial','left':'auto','right':'auto','top':'auto'});
}
$('.searchBtn').click(function() {
openSearch();
})
// Close search and menu on gradient click
$('.headerGradient, .headerCloseBtn').click(function() {
closeMenu();
closeSearch();
})
/* ==================== Enable tooltips =================== */
$('[data-toggle="tooltip"]').tooltip();
// Dark styled
$('.dark-tooltip').tooltip({
'template': '<div class="tooltip dark" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>'
});
/* ==================== Datepicker - https://bootstrap-datepicker.readthedocs.io/en/stable/ =================== */
//----- Enable single date picker
$('.datePicker').datepicker({
format: 'mm/dd/yyyy',
startDate: '-3d',
todayHighlight: true,
daysOfWeekDisabled: '0,6'
});
// Single date picker trigger
$('.datePickerTrigger').click(function() {
$(this).closest('.input-group').find('.datePicker').datepicker('show');
})
//----- Enable date range
$('.dateRange').datepicker({
inputs: $('.dateRangeInput')
});
// Date range trigger
$('.dateRangeTrigger').click(function() {
$(this).closest('.input-group').find('.dateRangeInput').datepicker('show');
})
/* ==================== Accordions =================== */
$('.accordion .heading').click(function() {
// Toggle the icon
$(this).find('i').toggleClass('fa-chevron-down fa-chevron-up');
})
$('.collapse').on('hidden.bs.collapse', function() {
// Toggle the icon
$(this).find('i.fa-chevron-up').toggleClass('fa-chevron-down fa-chevron-up');
// Disable the expand all link
var id = $(this).closest('.accordion').attr('id');
$('.expandAll[data-target="#' + id + '"]').removeClass('disabled');
// If all items are hidden then disable the collapse link
if ($(this).closest('.accordion').find('.collapse.show').length == 0) {
$('.collapseAll[data-target="#' + id + '"]').addClass('disabled');
}
})
$('.collapse').on('shown.bs.collapse', function() {
// Toggle the icon
$(this).find('i.fa-chevron-down').toggleClass('fa-chevron-down fa-chevron-up');
// Disable the collapse all link
var id = $(this).closest('.accordion').attr('id');
$('.collapseAll[data-target="#' + id + '"]').removeClass('disabled');
// If all items are shown then disable the expand link
if ($(this).closest('.accordion').find('.collapse:not(.show)').length == 0) {
$('.expandAll[data-target="#' + id + '"]').addClass('disabled');
}
})
$('.expandAll').click(function() {
// Disable the expand all link
var id = $(this).attr('data-target');
$(this).addClass('disabled');
// Enable the collapse all link
$('.collapseAll[data-target="' + id + '"]').removeClass('disabled');
// Show all items
$(id + ' .collapse').collapse('show');
// Toggle the icons
$(id).find('i.fa-chevron-down').toggleClass('fa-chevron-down fa-chevron-up');
})
$('.collapseAll').click(function() {
// Disable the collapse all link
var id = $(this).attr('data-target');
$(this).addClass('disabled');
// Enable the expand all link
$('.expandAll[data-target="' + id + '"]').removeClass('disabled');
// Hide all items
$(id + ' .collapse').collapse('hide');
// Toggle the icons
$(id).find('i.fa-chevron-up').toggleClass('fa-chevron-down fa-chevron-up');
})
/* ==================== Dropdown toggles - Sidebar navigation =================== */
$('.sidebarBtn').click(function() {
$(this).find('i').toggleClass('fa-chevron-up fa-chevron-down');
if($(this).attr('aria-expanded') == true){
$(this).attr({'aria-expanded': false});
}else{
$(this).attr({'aria-expanded': true});
}
$(this).next('ul').slideToggle();
});
})
Vertical header layout
The vertical header layout uses the vertical header and includes a secondary navigation (‘Jump to’ menu on the right) as well as a footer.
Template structure
This template uses a body class of vertical-layout
along with the following elements for the general page layout.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Page title</title>
</head>
<body class="vertical-layout">
<!-- Insert vertical header here -->
<div class="container-fluid">
<main class="clearfix">
<div class="cw-content">
<!-- Page content here -->
</div>
<div class="secondary-nav-container">
<div class="secondary-nav" id="secondaryNav">
<!-- Secondary navigation dynamically generated here -->
</div>
</div>
</main>
</div>
<!-- Footer -->
<footer class="vertical-layout-footer">
<div class="container-fluid">
<div class="guide-footer-inner small">
<p>Copyright or any other important information can be added inside the footer, maybe a link to <a href="#">contact us</a>.</p>
</div>
</div>
</footer>
</body>
</html>
Sample pages
These sample pages have been pre-built including all default design system CSS and JavaScript.
Sample page |
---|
Vertical layout example (contains component examples)Download |
Vertical layout example 2 (blank template)Download |
How it works
The following JavaScript for initializing Bootstrap components and for custom component functionality has also been included (assets/js/vertical-layout.js
):
- Vertical header
- Default and dark tooltips initialized
- Accordion custom add ons (custom dropdown icon toggle, and the ‘Expand all’ and ‘Collapse all’ links)
- Datepickers (single and date range) initialized
- Secondary navigation (‘Jump to’ menu)
Secondary navigation
The secondary sidebar navigation (‘Jump to’ menu) is dynamically inserted into #secondaryNav
using JavaScript based on the h2
and h3
headings within .cw-content
. You must add an id
attribute to each h2
and h3
for the scroll functionality. Add the class no-scroll
to any h2
or h3
headings that you don’t want to appear in the menu.
/* ==========================================================================
Vertical layout JS
========================================================================== */
function makeArray(list) {
return [].slice.call(list)
}
function getUrlParameter(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
var results = regex.exec(location.search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
};
$(document).ready(function() {
/* ==================== Vertical header =================== */
// Search form
// $('#searchInput').keyup(function(){
// if($(this).val() === ''){
// $('#searchBtn').attr("disabled", true);
// }else{
// $('#searchBtn').attr("disabled", false);
// }
// });
// Dropdown toggles
$('.sidebarBtn').click(function() {
$(this).find('i').toggleClass('fa-chevron-up fa-chevron-down');
if($(this).attr('aria-expanded') == true){
$(this).attr({'aria-expanded': false});
}else{
$(this).attr({'aria-expanded': true});
}
$(this).next('ul').slideToggle();
});
// Mobile menu
function openVerticalHeader(){
$('html').scrollTop( 0 );
$('.verticalHeaderGradient').fadeIn(200);
$('header.vertical-header').addClass('in');
$('body').css({'position':'fixed','left':0,'right':0,'top':0});
}
function closeVerticalHeader(){
$('.verticalHeaderGradient').fadeOut(200);
$('header.vertical-header').removeClass('in');
$('body').css({'position':'initial','left':'auto','right':'auto','top':'auto'});
}
$('.verticalHeaderBtn').click(function() {
openVerticalHeader();
})
$('.verticalHeaderGradient, .verticalHeaderCloseBtn').click(function() {
closeVerticalHeader();
})
/* ==================== Dynamic secondary side nav ("Jump to" menu) =================== */
var navContainer = $('#secondaryNav');
function createHashNav() {
var navContainer = $('#secondaryNav');
var navHTML = '';
var count = 0;
$('.cw-content > h2:not(.no-scroll), .cw-content > h3:not(.no-scroll)').each(function(index) {
if ($(this).is("h2")) {
navHTML += '<li><a class="scroll" href="#' + $(this).attr('id') + '">' + $(this).text() + '</a></li>';
} else {
navHTML += '<li class="inner"><a class="scroll" href="#' + $(this).attr('id') + '">' + $(this).text() + '</a></li>';
}
count++;
})
if (count > 1) {
navContainer.html('<div class="title lead">Jump to</div><ul>' + navHTML + '</ul>');
} else {
navContainer.html('');
}
}
if (navContainer.length > 0) {
createHashNav();
}
// Smooth scroll
$('a.scroll').click(function() {
if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
if (target.length) {
var stateObj = {
hash: this.hash,
};
history.pushState(stateObj, '', location.pathname + this.hash);
$('html,body').animate({
scrollTop: target.offset().top
}, 500);
return false;
}
}
});
// On scroll find the first h1 or h2 in the viewport to set as active
$(window).scroll(function() {
var scrollTop = $(window).scrollTop();
var windowHeight = $(window).height();
var first = false;
$("h3, h2, h1").each(function() {
var offset = $(this).offset();
if (scrollTop <= offset.top && ($(this).height() + offset.top) < (scrollTop + windowHeight)) {
$('a.scroll[href="#' + $(this).attr('id') + '"]').parent().siblings().find('a').removeClass('active');
$('a.scroll[href="#' + $(this).attr('id') + '"]').parent().siblings().find('a').blur();
$('a.scroll[href="#' + $(this).attr('id') + '"]').addClass('active');
first = true;
}
if (first == true) {
return false;
}
});
});
/* ==================== Enable tooltips =================== */
$('[data-toggle="tooltip"]').tooltip();
// Dark styled
$('.dark-tooltip').tooltip({
'template': '<div class="tooltip dark" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>'
});
/* ==================== Datepicker - https://bootstrap-datepicker.readthedocs.io/en/stable/ =================== */
//----- Enable single date picker
$('.datePicker').datepicker({
format: 'mm/dd/yyyy',
startDate: '-3d',
todayHighlight: true,
daysOfWeekDisabled: '0,6'
});
// Single date picker trigger
$('.datePickerTrigger').click(function() {
$(this).closest('.input-group').find('.datePicker').datepicker('show');
})
//----- Enable date range
$('.dateRange').datepicker({
inputs: $('.dateRangeInput')
});
// Date range trigger
$('.dateRangeTrigger').click(function() {
$(this).closest('.input-group').find('.dateRangeInput').datepicker('show');
})
/* ==================== Accordions =================== */
$('.accordion .heading').click(function() {
// Toggle the icon
$(this).find('i').toggleClass('fa-chevron-down fa-chevron-up');
})
$('.collapse').on('hidden.bs.collapse', function() {
// Toggle the icon
$(this).find('i.fa-chevron-up').toggleClass('fa-chevron-down fa-chevron-up');
// Disable the expand all link
var id = $(this).closest('.accordion').attr('id');
$('.expandAll[data-target="#' + id + '"]').removeClass('disabled');
// If all items are hidden then disable the collapse link
if ($(this).closest('.accordion').find('.collapse.show').length == 0) {
$('.collapseAll[data-target="#' + id + '"]').addClass('disabled');
}
})
$('.collapse').on('shown.bs.collapse', function() {
// Toggle the icon
$(this).find('i.fa-chevron-down').toggleClass('fa-chevron-down fa-chevron-up');
// Disable the collapse all link
var id = $(this).closest('.accordion').attr('id');
$('.collapseAll[data-target="#' + id + '"]').removeClass('disabled');
// If all items are shown then disable the expand link
if ($(this).closest('.accordion').find('.collapse:not(.show)').length == 0) {
$('.expandAll[data-target="#' + id + '"]').addClass('disabled');
}
})
$('.expandAll').click(function() {
// Disable the expand all link
var id = $(this).attr('data-target');
$(this).addClass('disabled');
// Enable the collapse all link
$('.collapseAll[data-target="' + id + '"]').removeClass('disabled');
// Show all items
$(id + ' .collapse').collapse('show');
// Toggle the icons
$(id).find('i.fa-chevron-down').toggleClass('fa-chevron-down fa-chevron-up');
})
$('.collapseAll').click(function() {
// Disable the collapse all link
var id = $(this).attr('data-target');
$(this).addClass('disabled');
// Enable the expand all link
$('.expandAll[data-target="' + id + '"]').removeClass('disabled');
// Hide all items
$(id + ' .collapse').collapse('hide');
// Toggle the icons
$(id).find('i.fa-chevron-up').toggleClass('fa-chevron-down fa-chevron-up');
})
})