This module can be used to create a filterable library on a HubSpot page of externally linked resources.
Created by: Katelyn
Tags: Lists, Grids and content blocks, Pagination, HubDB
After receiving a minimum of 25 recommendations, an entry earns the "Community Approved" badge.
Please keep in mind, all entries are community created and may not be fully supported by HubSpot.
View on:
{% if module.hubdb_table %}
<div class="row-fluid resources-container">
<!-- FILTERS SIDEBAR -->
<div class="span3 widget-span resources-sidebar-container">
<div class="sidebar-filters">
<aside class="filters-content">
<h2>
Filter resources
</h2>
<div class="filter-group">
<h3>
Search
</h3>
<div class="filter-search">
<form id="form_id" method="get">
<input name="name" type="text" id="search-by" class="autocomplete" placeholder="Search by title">
<button type="submit" class="search-button"></button>
</form>
</div>
</div>
<div class="filter-group">
<h3>
Content Types
</h3>
<form id="form_id" method="get">
<select name="content_type" form="form_id" onChange="this.form.submit()">
<option value="show-all">Show All</option>
{% set types = hubdb_table_column(module.hubdb_table, "content_type").options %}
{% for choice in types %}
{% set type_list = type_list~choice.id|list%}
{% if choice.id == request.query_dict.content_type%}
<option selected="selected" value="{{ choice.id }}">{{ choice.name }}</option>
{% else %}
<option value="{{ choice.id }}">{{ choice.name }}</option>
{% endif %}
{% endfor %}
</select>
</form>
</div>
<input name="page" type="hidden" id="page" class="autocomplete" placeholder="page">
</aside>
</div>
</div>
{% set page_size = 10 %}
{% set rowCount = hubdb_table(module.hubdb_table).row_count %}
{% set pageCount =(rowCount/page_size)|round(0, 'ceil') %}
{% if request.query_dict.page %}
{% set page_num = request.query_dict.page|int %}
{% else %}
{% set page_num = 1 %}
{% endif %}
{% if page_num == "" or page_num == "1"%}
{% set offsetNum = page_size %}
{% else %}
{% set offsetNum = (page_num)*page_size %}
{% endif %}
{% set queryparam = "" %}
{% if request.query_dict.content_type in ["1", "2", "3", "4", "5", "6", "7", "8", "9"] %}
{% set queryparam = queryparam ~ "&content_type="~request.query_dict.content_type|urlencode %}
{% endif %}
{% if request.query_dict.content_type in ["1", "2", "3", "4", "5", "6", "7", "8", "9"] and request.query_dict.name != "" %}
{% set queryparam = queryparam~"&content_type="~request.query_dict.content_type|urlencode~"&name__icontains="~request.query_dict.name|urlencode %}
{% endif %}
{% if request.query_dict.content_type == "show-all" and request.query_dict.name != "" %}
{% set queryparam = queryparam~"&name__icontains="~request.query_dict.name|urlencode %}
{% endif %}
{% set count = hubdb_table_rows(module.hubdb_table, queryparam) %}
{% set pageCount3 = count|length %}
{% set pageCount4 =(pageCount3/page_size)|round(0, 'ceil') %}
{% if offsetNum =="0" %}
{% set queryparam = queryparam~"&limit=" + page_size %}
{% else %}
{% set queryparam = queryparam~"&limit="~offsetNum %}
{% endif %}
{% set table = hubdb_table_rows(module.hubdb_table, queryparam) %}
{% if table == [] %}
<div class="page-center"><div class="no-results">No matching results</div></div>
{% else %}
<!-- RESOURCES RESULTS -->
<div class="resources-results-container">
<div class="resource-items-container">
{% for row in table %}
{% if row.featured == "1" %}
<div class="resource-item featured">
<div class="item-content">
<h2>
<a href="{{ row.link }}" target="_blank">{{ row.name }}</a>
</h2>
<div class="tags">
<span class="tag">{{ row.content_type.name }}</span>
</div>
</div>
<figure class="item-image">
<a class="item-link" target="_blank" href="{{ row.link }}">
<img src="{{ row.image.url }}" />
</a>
<figcaption>
<strong>{{ row.name }}</strong>
{{ row.description }}
<a class="item-cta" href="{{ row.link }}" target="_blank">View Details</a>
</figcaption>
</figure>
<div class="featured-ribbon">
<span class="featured-star"></span>
</div>
</div>
{% endif %}
{% endfor %}
</div>
<div class="resource-items-container">
{% for row in table %}
<div class="resource-item" {% if row.featured == "1" %} style="display: none;" {% endif %}>
<div class="item-content">
<h2>
<a href="{{ row.link }}" target="_blank">{{ row.name }}</a>
</h2>
<div class="tags">
<span class="tag">{{ row.content_type.name }}</span>
</div>
</div>
<figure class="item-image">
<a class="item-link" target="_blank" href="{{ row.link }}">
<img src="{{ row.image.url }}" />
</a>
<figcaption>
<strong>{{ row.name }}</strong>
{{ row.description }}
<a class="item-cta" href="{{ row.link }}" target="_blank">View Details</a>
</figcaption>
</figure>
</div>
{% endfor %}
</div>
<!-- PAGINATION -->
{% set page_num = page_num + 1 %}
{% if page_num <= pageCount4 %}
{% if request.query_dict %}
{% set paginationPath = request.path + "?topics="+ request.query_dict.topics|urlencode +"&content_type=" + request.query_dict.content_type|urlencode + "&Name=" + "&page=" + page_num %}
{% else %}
{% set paginationPath = request.path + "?&page=" + page_num %}
{% endif %}
<div class="resources-pagination">
<a class="next-link resources-load-more" id="loadm" data-total-page-count="{{ pageCount4 }}" href="{{ paginationPath }}">Load More</a>
</div>
{% endif %}
</div>
{% endif %}
</div>
{% endif %}
body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #33475b;
background-color: rgb(245, 248, 250);
font-family: "AvenirNext","Helvetica Neue",Helvetica,Arial,sans-serif;
line-height: 1.625;
margin: 0;
padding: 0;
}
body .resources-container {
max-width: 1141px;
margin: 0 auto;
display: flex;
justify-content: space-between;
}
.resources-sidebar-container {
width: 28%;
}
.sidebar-filters {
padding: 34px 22px;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 0 11px rgba(33,33,33,.2);
}
.sidebar-filters h2 {
font-size: 19.5px;
font-weight: 400;
letter-spacing: 0;
margin: 0;
padding-bottom: 10px;
border-bottom: 2px solid #e8e8e8;
color: #475761;
}
.sidebar-filters .filter-group {
border: none;
border-bottom: 2px solid #e8e8e8;
padding: 30px 0;
margin: 2px 0;
}
.sidebar-filters .filter-group h3 {
font-size: 15px;
font-weight: 400;
margin: 0 0 4px;
color: #475761;
}
.filter-group .filter-search {
display: -webkit-flex;
display: flex;
width: 100%;
margin: 3px 0;
}
.filter-search form {
position: relative;
}
.filter-group input#search-by {
flex: 1 0 auto;
font-size: 14px;
padding: 0 8px;
min-height: 34px;
letter-spacing: .1px;
line-height: 2.5;
border: 1px solid #dbe2eb;
border-radius: 3px 0 0 3px;
border-right: none;
max-width: calc(100% - 30px);
-webkit-appearance: none;
}
.filter-group .search-button {
position: absolute;
top: 0px;
right: 0px;
height: 34px;
background-color: transparent;
border: 1px solid #dbe2eb;
border-radius: 0 3px 3px 0;
border-left: none;
width: 30px;
padding: 0;
-webkit-appearance: none;
}
.search-button:before {
content: "";
position: absolute;
top: 17px;
left: 16px;
height: 6px;
width: 2px;
background-color: #00769b;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
}
.search-button:after {
content: " ";
color: #00769b;
position: absolute;
top: 10px;
left: 7px;
width: 10px;
height: 10px;
border: 2px solid currentColor;
border-radius: 100%;
}
.filter-group a {
display: block;
line-height: 1.2;
font-size: 14.5px;
padding: 4.5px 0;
color: #0091ae;
font-weight: 500;
text-decoration: none;
}
.filter-group a:hover {
color: #007a8c;
text-decoration: underline;
}
.sidebar-social {
margin-bottom: 20px;
}
.sidebar-social h3 {
font-size: 15.25px;
font-weight: 400;
text-align: center;
text-transform: uppercase;
margin: 23px 0 11px;
letter-spacing: 0;
color: #475761;
}
.sidebar-social-icons {
text-align: center;
}
.sidebar-social a {
text-decoration: none;
}
.resources-results-container {
width: 70%;
}
.resource-items-container {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: row;
-webkit-flex-wrap: wrap;
flex-flow: row wrap;
-webkit-justify-content: space-between;
justify-content: space-between;
}
.resource-items-container .resource-item {
background-color: #fff;
border-radius: 4px;
box-shadow: 0 0 11px rgba(33,33,33,.2);
background-color: #f7f7f7;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-align-content: center;
align-content: center;
position: relative;
transition: box-shadow .3s;
width: 31.5%;
margin-bottom: 25px;
}
.resource-items-container .resource-item:hover {
box-shadow: 0 10px 50px -5px rgba(0,0,0,.15);
}
.resource-items-container .resource-item .item-content {
padding: 19px;
-webkit-order: 2;
order: 2;
transition: filter .3s;
}
.resource-item h2 {
font-size: 1.24em;
font-weight: 400;
line-height: 1.3;
letter-spacing: .02em;
margin: 0;
color: #475761;
}
.resource-item h2 a {
color: #000;
font-weight: 500;
text-decoration: none;
}
.resource-item .tag {
color: #a7a9ac;
font-size: 14px;
}
.resource-items-container .resource-item .item-image {
height: 163px;
background-color: #fff;
margin: 0;
overflow: hidden;
-webkit-order: 1;
order: 1;
transition: filter .3s;
}
.resource-item .item-image .item-link {
position: relative;
width: 100%;
display: block;
height: 100%;
}
.resource-item .item-image .item-link img {
max-height: 100%;
position: absolute;
top: -100%;
bottom: -100%;
left: -100%;
right: -100%;
margin: auto;
max-width: 100%;
}
.resource-items-container .resource-item figcaption {
padding: 19px;
border-radius: 4px;
color: #fff;
position: absolute;
z-index: 1;
width: 100%;
height: 100%;
top: 0;
left: 0;
opacity: 0;
transition: background-color .3s,opacity .3s;
}
.resource-items-container .resource-item:hover figcaption {
background-color: rgba(81,111,144,.85);
opacity: 1;
}
.resource-items-container .resource-item figcaption strong {
letter-spacing: .02em;
line-height: 1.25em;
display: block;
}
.resource-item .item-cta {
position: absolute;
text-align: center;
left: 19px;
bottom: 19px;
right: 19px;
z-index: 2;
display: inline-block;
background-color: #ff7a59;
color: #fff;
font-size: 14px;
font-weight: 600;
padding: 8px 25px;
border-radius: 4px;
font-family: proxima-nova,Helvetica Neue,Helvetica,Arial,sans-serif;
transition: background-color .5s;
}
.item-cta:hover {
text-decoration: none;
color: #fff;
background-color: #ff8f73;
}
.resource-item.featured {
width: 100%;
flex-direction: row;
}
.resource-item.featured .item-content {
padding: 88px 9px 65px 19px;
width: 63%;
align-self: center;
}
.resource-item.featured .item-content h2 {
font-size: 1.79em;
max-width: 415px;
}
.resource-item.featured .item-image {
height: auto;
width: 37%;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.resource-item.featured .item-image img {
max-width: none;
min-height: 100%;
min-width: 100%;
object-fit: cover;
}
.featured-ribbon {
position: absolute;
top: 0;
right: 12px;
height: 42px;
width: 32px;
transition: filter .3s;
}
.featured-ribbon:before {
content: "";
height: 32px;
display: block;
background-color: #f8cd9c;
}
.featured-ribbon:after {
border-left: 16px solid #f8cd9c;
border-right: 16px solid #f8cd9c;
border-bottom: 10px solid transparent;
bottom: 0;
content: "";
height: 0;
left: 0;
position: absolute;
width: 0;
}
.featured-ribbon .featured-star {
z-index: 1;
position: absolute;
top: 8px;
left: 9px;
display: block;
background: url(https://cdn2.hubspot.net/hubfs/53/assets/hubspot.com/marketing-library/ml-sprite.png) 0 0;
width: 15px;
height: 15px;
overflow: hidden;
}
// js
This module is intended to be used with HubSpot's HubDB tool to create a library section for external resources. The list of available resources can be filtered by search or content type and a 'Featured' resource can also be chosen.
Before using this module you must create a HubDB table first to store your resources listing information. Instructions on how to create and edit a HubDB table can be found here.
In order for the HubL contained within this module to work correctly the HubDB table must contain the following columns, column names must match exactly:
| Column Label | Column Name | Column Type | | ------------------- |:---------------------:| ------------: | | Name | name | text | | Content Type | content_type | select | | Image | image | image | | Description | description | rich text | | Download Link | link | URL | | Featured Resource | featured | checkbox |
Once you have your table created and this module downloaded into your design manager you can place the module on any HubSpot template or page. Choose the HubDB table data you wish to use within the module by selecting the 'HubDB Table' module field.
A modern framework for accelerating build times on the HubSpot CMS. Based on a modified Bootstrap 4 framework.
Lead developers: Jon McLaren
Chrome/Chromium extension for HubSpot CMS Developers that adds a developer menu, dark theme and useful shortcuts to commonly used HubSpot query parameters, resources, and tools for making HubSpot Development easier and more enjoyable.
Lead developers: Jon McLaren , William Spiro , Gonzalo Torreras
This extension enables super fast local development of CMS pages, and is a great compliment to using the new local HubL server. It contains comprehensive HubL tag, function, filter and expression test auto-complete snippets, as well as their documentation.
Lead developers: William Spiro
Find an entry with an issue, bug, or abuse?
Please complete the below information in detail and we will investigate.
Reporting as Luke Summerfield