Autocomplete JS for searching through a HubDB

SOLVE
piersg
Key Advisor

I wrote this to have autocomplete on search for a HubDB.

 

Suggestions/feedback welcome!

 

HTML:

 

<form class="form" name="your-form" class="search-form" id="autocomplete-container" autocomplete="off">
  <input type="text" class="search-input" name="title" aria-label="Search" placeholder="Search" id="autocomplete-input">
  <ul id="autocomplete-results">
  </ul>
  <input class="hide" type="submit" name="submit">
</form>

 

JS:

 

// variables
var input = document.getElementById('autocomplete-input');
// this will be the list of names to compare against user input
var list = [];
// this will be an object array that will have the path (if you want it, remove if you just want names)
var namePathArr = [];


//Ajax call to HubDB
var request = new XMLHttpRequest();
request.open('GET', "https://api.hubapi.com/hubdb/api/v2/tables/[DB ID]/rows?portalId=[PORTAL ID]", true);

request.onload = function() {
  if (this.status >= 200 && this.status < 400) {
    // Success!
    var data = JSON.parse(this.response);
    var tableArr = data.objects;
    tableArr.forEach(function(obj) {
      if(obj.path !== null && obj.path !== '') {
        var name = obj.values['2'];
        // remove path and object variables if you just want names
        var path = obj.path;
        var object = {
          "name" : name,
          "path" : path
        };
        // push to names array
        list.push(name);
        // push name and path to namePathArr (remove if you want)
        namePathArr.push(object);
      }
    });
  } else {
    // We reached our target server, but it returned an error
    console.log(this.response);
  }
};

request.onerror = function(status, error) {
    console.log(error);
};

request.send();

// autocomplete function to compare value against the list and return an array of matches
function autocomplete(val) {
  var autocomplete_return = [];
  for (i = 0; i < list.length; i++) {
    if (val === list[i].toLowerCase().slice(0, val.length)) {
      autocomplete_return.push(list[i]);
    }
  }
  return autocomplete_return;
}

// input event to give value for the autocomplete match function
input.onkeyup = function(e) {
  input_val = this.value; // updates the variable on each ocurrence
  input_val = input_val.toLowerCase();
  
  if (input_val.length > 0) {
    var suggestions = [];

    autocomplete_results = document.getElementById("autocomplete-results");
    autocomplete_results.innerHTML = '';

    suggestions = autocomplete(input_val);

    //get current url without query or hash in path
    var url = window.location.href.split('?')[0];
    url = url.split('#')[0];
    for (i = 0; i < suggestions.length; i++) {
      // additional step to look up the suggestion in namePathArr to get the path, again remove this and the href if you just want names
      let name = namePathArr.find(o => o.name === suggestions[i]);
      // adds the suggestions as links with the href to the autocomplete results list
      autocomplete_results.innerHTML += '<a href="'+url+'/'+name.path+'"><li>' + suggestions[i] + '</li></a>';
    }
    
    autocomplete_results.style.display = 'flex';
  } else {
    suggestions = [];
    autocomplete_results.innerHTML = '';
  }
}

 

 

You could probably get rid of the 'list' array and just use namePathArr to get both name and path, but I've had a long day haha.

 

CSS if you want it:

 

#automcomplete-container {
  position: relative;
}
#autocomplete-input {
  margin-bottom: 0;
}
#autocomplete-results {
	display: none;
  flex-direction: column;
	width: 100%;
	list-style: none;
	margin-left: 0;
	box-shadow: 0px 4px 7px -1px rgba(45,62,80,.2);
	position: absolute;
  background-color: white;
  z-index: 1;
}
#autocomplete-results a {
	width: 100%;
	padding: 10px 15px;
	color: black;
}
#autocomplete-results a:hover {
	background: #eee;
}

 

1 Accepted solution

Accepted Solutions
piersg
Solution
Key Advisor

I edited this slightly to make it more reusable . I added an id data attribute to the script tag, which has the HubL variable for the hubdb table id as a value

<script src="{{ get_asset_url('[autocomplete_js_file_path]') }}" id="autoScript" data-id="{{dynamic_page_hubdb_table_id}}"></script>

 

//add this
var dbID = document.getElementById("autoScript").getAttribute( "data-id" );

//make this a function
function getHubDB(id) {
  var request = new XMLHttpRequest();
  request.open('GET', "https://api.hubapi.com/hubdb/api/v2/tables/"+id+"/rows?portalId=5255565", true);

  request.onload = function() {
    if (this.status >= 200 && this.status < 400) {
      // Success!
      var data = JSON.parse(this.response);
      var tableArr = data.objects;
      tableArr.forEach(function(obj) {
        if(obj.path !== null && obj.path !== '') {
          var name = obj.values['2'];
          if (name != undefined) {
            var path = obj.path;
            var object = {
              "name" : name,
              "path" : path
            };
            // push to names array
            list.push(name);
            // push name and path to namePathArr 
            namePathArr.push(object);
          }
        }
      });
    } else {
      // We reached our target server, but it returned an error
      console.log(this.response);
    }
  };

  request.onerror = function(status, error) {
      console.log(error);
  };

  request.send();
}

getHubDB(dbID);

 

 

View solution in original post

4 Replies 4
natsumimori
Community Manager

Hi @piersg , thanks for sharing!

@stefen , @Kevin-C , @Chris-M , @BootstrapC , you guys might be interested in this:)

0 Upvotes
stefen
Key Advisor | Partner

@piersg cool! Do you have a live demo by chance?

Stefen Phelps, Community Champion, Kelp Web Developer
0 Upvotes
piersg
Key Advisor

Thanks @stefen 🙂

 

Yeah sure: http://www-mews-com.sandbox.hs-sites.com/en/products/marketplace

 

I'm still messing around with the HubDB HubL for this so some of the other functionality may be a bit broken but the autocomplete is fully functional (including clicking on a suggestion to go to the page)

piersg
Solution
Key Advisor

I edited this slightly to make it more reusable . I added an id data attribute to the script tag, which has the HubL variable for the hubdb table id as a value

<script src="{{ get_asset_url('[autocomplete_js_file_path]') }}" id="autoScript" data-id="{{dynamic_page_hubdb_table_id}}"></script>

 

//add this
var dbID = document.getElementById("autoScript").getAttribute( "data-id" );

//make this a function
function getHubDB(id) {
  var request = new XMLHttpRequest();
  request.open('GET', "https://api.hubapi.com/hubdb/api/v2/tables/"+id+"/rows?portalId=5255565", true);

  request.onload = function() {
    if (this.status >= 200 && this.status < 400) {
      // Success!
      var data = JSON.parse(this.response);
      var tableArr = data.objects;
      tableArr.forEach(function(obj) {
        if(obj.path !== null && obj.path !== '') {
          var name = obj.values['2'];
          if (name != undefined) {
            var path = obj.path;
            var object = {
              "name" : name,
              "path" : path
            };
            // push to names array
            list.push(name);
            // push name and path to namePathArr 
            namePathArr.push(object);
          }
        }
      });
    } else {
      // We reached our target server, but it returned an error
      console.log(this.response);
    }
  };

  request.onerror = function(status, error) {
      console.log(error);
  };

  request.send();
}

getHubDB(dbID);

 

 

View solution in original post