search-lookup
Search lookup module
This is a search input module with autosuggest. At its heart, it lets you search by name, but optionally you can make a call to the Location Services API and enable search by full or partial postcode.
- Name: e.g. "Acton", "John Smith", "Oranges"
- Partial postcode: up to 5 of the nearest matched locations are suggested
- Full postcode: 1 result is suggested
Dependencies
news-vj-search-lookup
has 2 hard dependencies, which are automatically included in the module:
- jQuery
- jQuery-Autocomplete
Usage
JavaScript
import SearchLookup from '@bbc/news-vj-search-lookup';
import data from './data.json';
new SearchLookup({
input: '#news-vj-search-lookup__input', // id of the input field
data: data, // local lookup data - see next section
minChars: 2, // the minimum number of chars to enter before the autocomplete suggestions list appears
vocab: { // internationalised interface text
language: 'english',
search_error: "Sorry, we don't recognise this location. Please enter a UK postcode, council name or NI constituency",
search_screenreader_autosuggest_help: " results are available, use up and down arrow keys to navigate.",
},
searchForPostcodes: true, // should be able to search by full postcode
searchForPartialPostcodes: true, // should be able to search by partial postcode. Note that `searchForPostcodes` can't be false if this is true!
fullPostcodeLimit: 3, //sets the number of autosuggest results for full postcode searches to 3, default value is 1
partialPostcodeLimit: 5, //sets the number of autosuggest results for partial postcode searches to 5, default value is 5
searchType: 'gss-health', // default: 'gss-council', other options: 'gss-seat', etc. This can either take a string or callback function
clearInput : false, // defaults to true, automatically clears the input element after submission
/**
* Function called once result is chosen.
* @optional
*/
onSelect: function (gssid, data) {
document.getElementById('results').innerHTML = `Results for ${data.name}`;
},
/**
* Manipulate results before they're displayed to the user. Add/remove/rename etc.
* @optional
*/
overrideResults: function (results, query) {
return results;
},
/**
* Function called after Ajax response is processed.
* You may want to resize your iframe or something here
* Suggestions is an array containing the results.
* @optional
*/
onSearchComplete: function (query, suggestions) {},
/**
* Function called when input is altered after selection has been made. Useful for resetting.
* @optional
*/
onInvalidateSelection: function () {},
/**
* Determines whether or not to apply `op=intersect` to the Location Services request.
* Bespoke endpoints (e.g. `nhs-trust`) can have strange behaviour if `op=intersect` is applied.
* Defaults to `true` (no checking)
* @param postcode: string
* @return boolean
* @optional
*/
intersectCallback: function (postcode) {
return true;
},
/**
* Location Services sometimes return an array of results, only one of which is the type of thing we want. So we can run a check against the GSSID.
* Defaults to `true` (no checking)
* @param entityCode: string
* @return boolean
* @optional
*/
entityCodeValidates: function (entityCode) {
return true;
},
});
news-vj-search-lookup
requires that you provide local lookup data in the following format (it won't work independently of this):
{
"E07000223": {
"name": "Adur",
// you can have as many other properties as you like,
// but you NEED the GSSID and the name
}
}
CSS
Include the SASS in your main SASS file, i.e.:
@import '../../node_modules/@bbc/news-vj-search-lookup/lookup/lookup';
HTML
Include the Handlebars template in your HTML, and optionally, a label. i.e.:
{{>search-lookup
label="Enter your search in the field below"
standalone-form=true
search_placeholder="Start typing to search"
search_submit_text="Search for counties"
id="news-vj-search-lookup__input"
}}
The label
property is optional. If you omit it, you must create a label outside the module, and make sure its for
attribute matches the id
property you used for the lookup, e.g.
<label for="news-vj-search-lookup__input">SearchLookup</label>
Using Synonyms
In order to use synonyms in the lookup module, you would need to include a synonyms column in your dataset (e.g. search_alternative).
{
"E07000223": {
"name": "Adur",
"search_alternative": "USA"
//does not have to be straight after the name property
}
}
The example below shows how you can incorporate the synonyms column into the lookup.
function prepareSynonyms(data) {
const keys = Object.keys(data); // returns an array of keys for the data object
for (let i = 0; i < keys.length; i++) {
const val = data[keys[i]];
const separator = ',';
if (val.search_alternative) {
val.synonyms = val.search_alternative.split(separator);
delete val.search_alternative;
}
}
return data;
}
Changing searchType
To change the default searchType you would need to create a function that passes the user input. An example of this is shown in the code below.
new SearchLookup({
input: '#news-vj-search-lookup__input',
data: data,
searchType: function (query) {
var query = query.toUpperCase(); //the regex only recognises uppercase characters
if (query.match(/^BT/)) { // query is compared to the regex for a NI postcode
return 'gss-seat';
}
else {
return 'gss-council';
}
},
});
Run the tests
Install dev dependencies:
npm i
You'll also need Phantom installed:
brew install phantomjs
And bundler:
gem install bundler
Install gems:
bundle install
Compile CSS/HTML:
grunt
Run the server:
npm start
(You can now visit http://www.local.bbc.co.uk:8080)
Not all functionality has been implemented yet (i.e. if we run all of our scenarios, some will fail) - so we only want to run the scenarios for which we have completed the functionality:
npm test
, which is an alias for: bundle exec cucumber --tags ~@todo
You can of course run individual features:
bundle exec cucumber features/Lookup_Postcode.feature --tags ~@todo
Or individual scenarios:
bundle exec cucumber features/Lookup_Postcode.feature:33