Rapid UI Examples

Standard Rapid UI

Description

This demo highlights the basic capabilities of HawkSearch's Rapid UI framework. There is an example for basic search with options for Smart Search Features as well as a Smart Search example with keyword, concept and image search all working together.

📘

Reference Use Only

Keep in mind that this demo is pointing to an index with it's own fields/names. This example can be used, but the section for FieldMapping will need to be changed to match your index.

You can see a working version of standard Rapid UI demo here.

Code Example

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>HawkSearch Rapid UI Demo</title>
    <meta name="description" content="This is a demo of the HawkSearch Handlebars UI" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link href="https://uploads-ssl.webflow.com/616ef101d9f2a3350a5daaf5/617a70019e3990dcdc313a53_favico%2032x32px.png" rel="shortcut icon" type="image/x-icon" />
    <link href="https://uploads-ssl.webflow.com/616ef101d9f2a3350a5daaf5/617a7005e122ca51ac06961e_webclip%20256x256px.png" rel="apple-touch-icon" />
    <script type="module" src="https://cdn.jsdelivr.net/npm/@bridgeline-digital/[email protected]/dist/hawksearch-handlebars-ui.min.js"></script>
    <script type="text/javascript">
      addEventListener('hawksearch:loaded', () => {
          HawkSearch.init({
            clientId: "a92ec662de2847fd90d13a78fe8878ed",
            search: {
              url: window.location.pathname,
              endpointUrl: "https://searchapi-dev.hawksearch.net"
            },
            urlPrefixes: {
              assets: "https://dev.hawksearch.net",
              content: "https://preview-dev.hawksearch.net/developerportalsandbox",
            }
        	});
        });
    </script>
    <style type="text/css">
      body {
        font-family: Arial, Helvetica, sans-serif;
        font-size: 16px;
      }

      .layout-container {
        margin: 0 auto;
        min-width: 340px;
        max-width: 1280px;
      }

      hawksearch-search-field {
        display: block;
        margin: 0 0 30px 0;
      }
    </style>
  </head>

  <body>
    <div class="layout-container">
      <h1>HawkSearch Rapid UI Demo</h1>
      <hawksearch-search-field></hawksearch-search-field>
      <hawksearch-search-results></hawksearch-search-results>
    </div>
  </body>
</html>

Smart Search Options

You can use the following to support additional Smart Search Features to replace/use where <hawksearch-search-field></hawksearch-search-field>

is in the sample above :

Concept Search: <hawksearch-conceptsearch-field style="flex: 1;"></hawksearch-conceptsearch-field> (Allows users to search by phrases or sentences)

Visual Search: <hawksearch-visualsearch-field style="flex: 1;"></hawksearch-visualsearch-field> (Allows users to search using images to find other similar images)

Image Search: <hawksearch-imagesearch-field></hawksearch-imagesearch-field>(Takes a text-based query and finds the most relevant images based on the text provided)

Smart Search Example

In order to see keyword, concept, visual and image search all working together in an example, use the code below.

Smart Search Rapid UI Code Example with custom templates and styles

<html lang="en">
  <head>
    <title>Rapid UI Smart Search Example</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <!-- CUSTOM STYLES - ADDED FOR DEMO PURPOSE -->
    <style type="text/css">
      body{font-family:Arial,Helvetica,sans-serif;font-size:16px;}
      .smartsearchdemo__container {margin: 0 auto;min-width: 340px;max-width: 1280px;}
      .smartsearchdemo__container .search-field__container,.smartsearchdemo__container .conceptsearch-field__container {display: flex;justify-content: space-around;gap: 12px;}
      .smartsearchdemo__container .search-field__bar{display: flex;justify-content: space-around;background-color: #f5f7fa;padding: 0px 16px;align-items: center;flex: 1 0 0;border-radius: 100px;border: 1px solid #e6e9ed;transition: all .25s ease-in-out;}
      .smartsearchdemo__container .search-field__bar:focus,.smartsearchdemo__container .search-field__bar:hover,.smartsearchdemo__container .search-field__bar:focus-within,.smartsearchdemo__container .search-field__bar:target,.smartsearchdemo__container .search-field__bar:focus-visible,
      .smartsearchdemo__container .search-field__actions .search-field__actions__button:focus,.smartsearchdemo__container .search-field__actions .search-field__actions__button:hover,.smartsearchdemo__container .search-field__actions .search-field__actions-button:focus-within,
      .smartsearchdemo__container .search-field__actions .search-field__actions__button:target,.smartsearchdemo__container .search-field__actions .search-field__actions__button:focus-visible {border: 1px solid #119FF7;background: #FFF;}
      .smartsearchdemo__container .search-field__bar .search-field__bar__icon {display: flex;align-items: center;justify-content: center;width: 40px;height: 40px;margin: 0;max-width: 7.5rem;vertical-align: top;}
      .smartsearchdemo__container .search-field__bar .search-field__bar__link {color: #656D78;padding: 16px 24px;cursor: pointer;}
      .smartsearchdemo__container .search-field__bar .search-field__bar__divider{display: flex;border-left: 1px solid #e6e9ed;height: 100%;}
      .smartsearchdemo__container .search-field__actions .search-field__actions__button {display: flex;padding: 16px;align-items: center;align-self: stretch;border-radius: 100px;border: 1px solid #e6e9ed;background: #f5f7fa;transition: all .25s ease-in-out;cursor: pointer;}
      .smartsearchdemo__container .search-field__actions .search-field__actions__icon {width: 20px;height: 20px;}
      .smartsearchdemo__container .visualsearch-field__dialog {display: flex;position: relative;box-sizing: border-box;max-width: 1280px;padding: 32px;flex-direction: column;justify-content: center;align-items: flex-start;gap: 32px;border-radius: 25px;border: 1px solid #119ff7;background: #fff;}
      .smartsearchdemo__container .visualsearch-field__dialog .visualsearch-field__dialog__title {display: flex;justify-content: space-between;width: 100%;}
      .smartsearchdemo__container .visualsearch-field__dialog .visualsearch-field__dialog__title > h2 {display: block;margin: 0;color: #353b48 !important;font-size: 18px;font-style: normal;font-weight: 700;line-height: 100%;letter-spacing: .2px;}
      .smartsearchdemo__container .visualsearch-field__dialog .visualsearch-field__dialog__body {display: flex;width: 100%;flex-direction: column;}
      .smartsearchdemo__container .visualsearch-field__close {display: flex;align-items: center;justify-content: center;width: 56px;height: 56px;margin: 0;position: absolute;top: 1px;right: 1px;box-sizing: border-box;vertical-align: top;border: none;background: #fff;border-radius: 50%;cursor: pointer;}
      .smartsearchdemo__container .visualsearch-field__close:hover {background-color: #F5F7FA }
    </style>
    <!-- CUSTOM JAVASCRIPT TO HANDLE TABS - ADDED FOR DEMO PURPOSE -->
    <script>function getRequestTypeIndex(e){const t=e.get("requestType");return t?"ConceptSearch"===t?1:"ImageSearch"===t?2:0:0}document.addEventListener("DOMContentLoaded",(function(){let e=getRequestTypeIndex(new URL(document.location).searchParams)||0;function t(t){if(t.preventDefault(),"keypress"===t.type&&13===t.which||"click"===t.type){let t=parseInt(this.dataset.tabIndex);t!==e&&document.querySelectorAll(".smartsearchdemo__container .tab-container").forEach((function(n){if(parseInt(n.dataset.tabIndex)===t)return document.querySelectorAll(".tab-container").forEach((function(e){e.style.display="none"})),n.style.display="block",void(e=parseInt(n.dataset.tabIndex))}))}}document.querySelectorAll(".tab-container").forEach((function(t){parseInt(t.dataset.tabIndex)===e?t.style.display="block":t.style.display="none"})),document.querySelectorAll(".tab-switcher").forEach((function(e){e.addEventListener("click",t),e.addEventListener("keypress",t)}))}));</script>
    <!-- Rapid UI LIBRARY -->
    <script type="module" src="https://cdn.jsdelivr.net/npm/@bridgeline-digital/[email protected]/dist/hawksearch-handlebars-ui.min.js"></script>
    <!-- HAWKSEARCH CONFIGURATION -->
    <script type="text/javascript">
      addEventListener('hawksearch:loaded', () => {
        HawkSearch.init({
            clientId: "59d7b9ce967d4fdf8262d1a49392b8be",
            components: {
              'search-field': {
                strings: {
                  placeholder: 'Search by Keyword'
                }
              },
              'conceptsearch-field': {
                strings: {
                  placeholder: 'Search by a Concept'
                }
              },
              'imagesearch-field': {
                strings: {
                  placeholder: 'Describe an image'
                }
              },
              'visualsearch-field': {
                template: 'visualsearch-field__template',
                strings: {
                  dragImageMessage: 'Search By Image',
                  dropImageMessage: 'Drop an image here'
                }
              },
              'search-results-item': {
                  template: 'search-results-item__template'
              }
            },
            search: {
              url: window.location.pathname,
              endpointUrl: "https://searchapi-dev.hawksearch.net"
            },
            urlPrefixes: {
              assets: "https://dev.hawksearch.net",
              content: "https://preview-dev.hawksearch.net/developerportalsandbox",
            },
            css: {
              customStyles: 'custom-styles__template'
            },
            debug: true
        });
      });
    </script>
  </head>
  <body>
    <div class="smartsearchdemo__container">
      <!-- CSS TEMPLATE USED TO CUSTOMIZE HANDLEBAR-UI NATIVE STYLES -->
      <template id="custom-styles__template">
        <style type="text/css">
          input[type="text"]:not(.facet__search) {border: none;background-color: transparent;}
          input[type="text"]:not(.facet__search):focus,
          input[type="text"]:not(.facet__search):hover,
          input[type="text"]:not(.facet__search):focus-within,
          input[type="text"]:not(.facet__search):target,
          input[type="text"]:not(.facet__search):focus-visible {outline: none;border: none;background-color: transparent;}
          .visualsearch-field__drop-area {display:flex;padding:40px 24px;flex-direction:column;align-items:center;gap: 24px;align-self:stretch;border-radius:8px;border:1px solid #e6e9ed;}
          .visualsearch-field__drop-area.dragging-state {border: 1px dashed #119ff7;background: #f2faff;}
          .visualsearch-field__drop-area.dragging-state > .visualsearch-field__drop-area__prompt-msg,
          .visualsearch-field__drop-area.dragging-state > .visualsearch-field__drop-area__upload-button,
          .visualsearch-field__drop-area.dragging-state > .visualsearch-field__drop-area__icon {pointer-events: none;visibility: hidden;}
          .visualsearch-field__drop-area__upload-button {display:flex;padding:12px 40px 12px 32px;align-items:center;gap:10px;color:#fff !important;background-color:#000;cursor:pointer;}
          .visualsearch-field__drop-area__prompt-msg {color:#000;text-align:center;font-size:18px;font-style:normal;font-weight:700;line-height:100%;letter-spacing:.2px;}
          .visualsearch-field__drop-area__drop-msg {pointer-events: none;color: #119ff7 !important;text-align:center;font-size:18px;font-style:normal;font-weight:700;line-height:100%;letter-spacing:.2px;}
        </style>
      </template>
    
      <!-- CUSTOM TEMPLATE TO MODIFY THE VISUALS OF <visualsearch-field /> COMPONENT -->
      <template id="visualsearch-field__template">
        <div class="visualsearch-field">
          <div class="visualsearch-field__drop-area" hawksearch-visualsearch-droparea>
            <hawksearch-icon name="drop-image" size="100"></hawksearch-icon>
            <p class="visualsearch-field__drop-area__prompt-msg">{{strings.dragImageMessage}}</p>
            <p class="visualsearch-field__drop-area__drop-msg">{{strings.dropImageMessage}}</p>
            <label class="visualsearch-field__drop-area__upload-button">
              <input hawksearch-visualsearch-fileinput type="file" accept="image/*" capture="environment">
              <hawksearch-icon name="upload" size="20"></hawksearch-icon>
              {{strings.uploadImageMessage}}
            </label>
            <div class="visualsearch-field__drop-area__image-display" hawksearch-visualsearch-display></div>
          </div>
        </div>
      </template>
      
      <!-- CUSTOM TEMPLATE TO MODIFY THE VISUALS OF <search-results-item__template-field /> COMPONENT -->
      <template id="search-results-item__template">
        <div class="search-results-list__item search-results-list__item--{{type}}">
            {{#if pinned}}
            <span class="search-results-list__item__pin">
                <hawksearch-icon name="star"></hawksearch-icon>
            </span>
            {{/if}}
            {{#if (lt salePrice price)}}
            <span class="search-results-list__item__sale-indicator">{{strings.sale}}</span>
            {{/if}}
            <a hawksearch-link href="{{url}}" class="search-results-list__item__image" aria-label="{{title}}">
                <img hawksearch-image src="{{imageUrl}}" alt="">
            </a>
            <div class="search-results-list__item__title">
                <a hawksearch-link href="{{url}}">{{title}}</a>
            </div>
            {{#if rating}}
            <hawksearch-rating rating="{{rating}}"></hawksearch-rating>
            {{/if}}
            {{#unless (eq price undefined)}}
            <div class="search-results-list__item__price" itemprop="offers" itemtype="http://schema.org/Offer" itemscope>
                {{#if (lt salePrice price)}}
                <span class="search-results-list__item__price__original">{{currency price}}</span>
                <span class="search-results-list__item__price__current" itemprop="price">{{currency salePrice}}</span>
                {{else}}
                <span class="search-results-list__item__price-__current" itemprop="price">{{currency price}}</span>
                {{/if}}
            </div>
            {{/unless}}
            <hawksearch-variant-selector></hawksearch-variant-selector>
        </div>
      </template>
      
      <!-- KEYWORD SEARCH TAB -->
      <div class="tab-container" data-tab-index="0">
        <div class="search-field__container">
          <div class="search-field__bar">
            <span class="search-field__bar__icon">
              <hawksearch-icon name="search" size="20"></hawksearch-icon>
            </span>
            <hawksearch-search-field style="flex: 1;"></hawksearch-search-field>
            <div class="search-field__bar__divider"></div>
            <a class="search-field__bar__link tab-switcher" data-tab-index="1">or Concepts</a>
          </div>
          <div class="search-field__actions">
            <a class="search-field__actions__button tab-switcher" data-tab-index="2">
              <hawksearch-icon name="image" size="20"></hawksearch-icon>
            </a>
          </div>
        </div>
      </div>

      <!-- CONCEPT SEARCH TAB -->
      <div class="tab-container" data-tab-index="1">
        <div class="search-field__container">
          <div class="search-field__bar">
            <span class="search-field__bar__icon">
              <hawksearch-icon name="search" size="20"></hawksearch-icon>
            </span>
            <hawksearch-conceptsearch-field style="flex: 1;"></hawksearch-conceptsearch-field>
            <div class="search-field__bar__divider"></div>
            <a class="search-field__bar__link tab-switcher" data-tab-index="0">or Keywords</a>
          </div>
          <div class="search-field__actions">
            <a class="search-field__actions__button tab-switcher" data-tab-index="2">
              <hawksearch-icon name="image" size="20"></hawksearch-icon>
            </a>
          </div>
        </div>
      </div>

      <!-- VISUAL SEARCH TAB -->
      <div class="tab-container" data-tab-index="2">
        <div class="visualsearch-field__dialog">
          <a class="visualsearch-field__close tab-switcher" data-tab-index="1" tabindex="0">
            <hawksearch-icon name="cross" size="20"></hawksearch-icon>
          </a>
          <div class="visualsearch-field__dialog__title">
            <h2>Visual Search</h2>
          </div>
          <div class="visualsearch-field__dialog__body">
            <hawksearch-visualsearch-field></hawksearch-visualsearch-field>
            <div class="search-field__bar">
              <span class="search-field__bar__icon">
                <hawksearch-icon name="search" size="20"></hawksearch-icon>
              </span>
              <hawksearch-imagesearch-field style="flex: 1;"></hawksearch-imagesearch-field>
            </div>
          </div>
        </div>
      </div>
      <div style="margin-top: 16px;">
        <hawksearch-search-results></hawksearch-search-results>
      </div>
    </div>
  </body>
</html>

Production Updates

📘

Note: Above example is pointing to Dev - changes required for Production

When you move to production, you will need to add these variables to point your Rapid UI to the production account. You can add this code after urlPrefixes:

search: {
  endpointUrl: 'https://essearchapi-na.hawksearch.com',
  url: '/search'
},
tracking: {
  endpointUrl: 'https://tracking-na.hawksearch.com'
},
recommendations: {
  endpointUrl: 'https://recs-na.hawksearch.com'
}