HubSpot CMS

HubDB Resource Library

This module can be used to create a filterable library on a HubSpot page of externally linked resources.

Unverified
?

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.

5 Recommendations

View on:

GitHub

HTML + HUBL
          
            {% 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 %}



          
        
CSS
          
            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
          
            // js

          
        
Have Questions?

Ask technical questions in Slack.

HubSpot Developer Slack

Not a member yet? - join here
READ ME (VIEW IN GITHUB)

HubSpot

Code Gallery


Module - HubDB Resources Library w/ Filters

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.

How to use this module

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.

Step 1 - Create HubDB table

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 |

Step 2 - Place module on any HubSpot CMS Page

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.

 
5 Recommendations

Contribute to the Gallery!

We bet you’ve coded some amazing stuff. Showcase them and help the community grow.

Contribute

Other Open Source Projects

Browse all other open source projects

CrankShaft Framework

A modern framework for accelerating build times on the HubSpot CMS. Based on a modified Bootstrap 4 framework.

Lead developers: Jon McLaren

Developer Chrome Extension

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

VS Code HubL Language Extension

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

Not coding on HubSpot CMS yet?

We invite you to explore why thousands of developers LOVE coding with HubSpot!

Contribute
Made with  by community members: InboundLabs.co