UNPKG

@ideal-postcodes/postcode-lookup

Version:
418 lines (247 loc) 20.9 kB
<h1 align="center"> <img src="https://img.ideal-postcodes.co.uk/Postcode%20Lookup%20Logo@3x.png" alt="Ideal Postcodes Postcode Lookup"> </h1> > Add UK Postcode Lookup and address search to a webpage in moments [![npm version](https://badge.fury.io/js/%40ideal-postcodes%2Fpostcode-lookup.svg)](https://badge.fury.io/js/%40ideal-postcodes%2Fpostcode-lookup) [![npm bundle size](https://img.shields.io/bundlephobia/minzip/@ideal-postcodes/postcode-lookup)](https://bundlephobia.com/result?p=@ideal-postcodes/postcode-lookup) `@ideal-postcodes/postcode-lookup` is a JavaScript library that delivers Postcode Lookup and address search functionality on a webpage. This package should be consumed by a bundler or transpiler (e.g. webpack, parcel, rollup) for minification, module resolution and specific browser support. For a pre-bundled version of `postcode-lookup` (minified, transpiled, polyfilled, etc) that can immediately be dropped on a webpage, use [postcode-lookup-bundled](https://github.com/ideal-postcodes/postcode-lookup-bundled). ![Postcode Lookup Demo](https://img.ideal-postcodes.co.uk/postcode-lookup.gif) ## Links - [How it Works](https://github.com/ideal-postcodes/postcode-lookup#how-it-works) - [Documentation](https://github.com/ideal-postcodes/postcode-lookup#documentation) - [Library Documentation](https://postcode-lookup.ideal-postcodes.dev) - [npm](https://www.npmjs.com/package/@ideal-postcodes/postcode-lookup) - [GitHub](https://github.com/ideal-postcodes/postcode-lookup) - [About](https://ideal-postcodes.co.uk/postcode-lookup) - [Demos](https://ideal-postcodes.co.uk/postcode-lookup-demo) - [Changelog](https://cdn.jsdelivr.net/npm/@ideal-postcodes/postcode-lookup/CHANGELOG.md) ## How it Works 1. [Add the library to your project](#install). Your page should have pre-existing address input fields as well as a parent container for Postcode Lookup 2. [Run initialisation code](#instantiate) providing a reference to a parent container and [any other configuration](interfaces/controller.controllerconfig.html) 3. By default, Postcode Lookup will check if your key is [usable](https://ideal-postcodes.co.uk/documentation/keys#key). If not, setup will halt and Postcode Lookup will not bind. Set `checkKey` to `false` to disable this step. Use the `onFailedCheck` callback to update your page if the check fails. 4. Postcode Lookup then creates an input field and button to perform postcode and address lookups in the parent container 5. If a matching postcode or address is found, a dropdown `<select>` menu is created in the parent container and the selected address is piped into the form 6. If no matching postcode/address is found or an error occurred, Postcode Lookup will append an appropriate message ## Documentation - [Configuration & Usage](#configuration-amp-usage) - [Populating your Address Fields](#populating-your-address-fields) - [Setup Options](#setup-options) - [Required Config](#required-config) - [Styling](#styling) - [Custom Elements](#custom-elements) - [Lifecyle Callbacks](#lifecycle-callbacks) ### Configuration & Usage - [Install](#install) - [Instantiate](#instantiate) - [Detach](#detach) #### Install Add postcode-lookup to your project via npm ```bash npm install @ideal-postcodes/postcode-lookup ``` #### Instantiate Create postcode search tools using [`PostcodeLookup.setup`](globals.html#clearall). ```javascript import { PostcodeLookup } from "@ideal-postcodes/postcode-lookup"; PostcodeLookup.setup({ // *Required* Insert your API Key apiKey: "iddqd", // *Required* Specify the target element with ID `postcode_lookup` to house the search tools context: "#postcode_lookup", // Configures how address results are sent to inputs with IDs `line_1`, `line_2`, `line_3`, `post_town` and `postcode`. outputFields: { line_1: "#line_1", line_2: "#line_2", line_3: "#line_3", post_town: "#post_town", postcode: "#postcode", }, }); ``` [Configuration options](interfaces/controller.controllerconfig.html) #### Detach Remove all search tools created via `PostcodeLookup.controllers` and [`#removeAll()`](classes/controller.controller-1.html#removeall). ```javascript PostcodeLookup.controllers.forEach((c) => c.removeAll()); ``` Or store a reference to Postcode Lookup and `removeAll()`. ```javascript PostcodeLookup.removeAll(); ``` ### Populating your Address Fields Postcode Lookup expects you to have your own address inputs on the page ready to be populated. When an address is select, the addressing data will be piped to those address inputs designated in `outputFields`. For instance `line_1: "#line_1"` will write Address Line One data to a HTML element with ID `line_1`. Assigning the 3 address line, post town and postcode fields, is all addressing information required to identify a UK premise. You may extract more data for an address by passing more properties into the `outputFields` configuration object. The configuration attributes for `outputFields` matches the Address response object. E.g. street name can be populated can be populated using the [`thoroughfare`](https://api-typings.ideal-postcodes.dev/interfaces/address.html#thoroughfare) attribute. A list of address attributes provided by the API can be found at [@ideal-postcodes/api-typings](https://api-typings.ideal-postcodes.dev/interfaces/address.html). [More information on addressing data can be found on our data documentation](https://ideal-postcodes.co.uk/documentation/paf-data). For more sophistated behaviour when a user selects an address, you can hook into the `onAddressSelected` callback and implement customised behaviour there. ### Setup Options The Postcode Lookup configuration object is passed in as the first argument when calling [`setup()`](globals.html#setup). Below is a list of the primary, mainly optional, parameters you can use to style or modify the postcode and address search elements generated by the library. A complete list of configuration options can be found [in the library documentation](interfaces/controller.controllerconfig.html). Default values are [documented here](modules/controller.html#defaults). ### Required Config #### [`apiKey`](interfaces/controller.controllerconfig.html#apikey) API Key associated with your account. Typically begins `ak_` #### [`context`](interfaces/controller.controllerconfig.html#context) DOM context in which to inject Postcode Lookup tools. You will need to provide a `HTMLElement`, typically a `<div>` to house the postcode lookup tools. This can be referenced using a query selector (e.g. `"#postcode_lookup"`) or a direct reference to the `HTMLElement` (e.g. `document.getElementById("postcode_lookup")`). #### [`outputFields`](interfaces/controller.controllerconfig.html#outputfields) Specify where to send address data given a selected address. A object which maps an address attribute to the CSS selector of an input field or `HTMLElement` like `HTMLInputElement` or `HTMLTextAreaElement`. ```javascript { line_1: "#line_1", line_2: "#line_2", line_3: "input[name='line_3']", post_town: document.getElementById("post_town"), postcode: document.getElementById("postcode") } ``` The configuration attributes for `outputFields` matches the Address response object. E.g. street name can be populated can be populated using the [`thoroughfare`](https://api-typings.ideal-postcodes.dev/interfaces/address.html#thoroughfare) attribute. A list of address attributes provided by the API can be found at [@ideal-postcodes/api-typings](https://api-typings.ideal-postcodes.dev/interfaces/address.html). More complex, dynamic assignment can be performed using the [`onAddressSelected`](#onaddressselected) callback. Output fields assigned with a query selector are evaluated lazily (i.e. when an address attribute needs to be piped to a field). ### Styling Custom styling can be achieved by applying your own CSS classes to each HTML element created by Postcode Lookup: - [Search button](interfaces/controller.controllerconfig.html#buttonclass) - [Search input](interfaces/controller.controllerconfig.html#inputclass) - [Address select](interfaces/controller.controllerconfig.html#selectclass) - [Message box](interfaces/controller.controllerconfig.html#messageclass) - [Unhide fields trigger](interfaces/controller.controllerconfig.html#unhideclass) You may also inject style attributes into the HTML elements themselves: - [Search button](interfaces/controller.controllerconfig.html#buttonstyle) - [Search input](interfaces/controller.controllerconfig.html#inputstyle) - [Address select](interfaces/controller.controllerconfig.html#selectstyle) - [Message box](interfaces/controller.controllerconfig.html#messagestyle) - [Postcode Lookup container](interfaces/controller.controllerconfig.html#contextStyle) HTML elements created by Postcode Lookup can be configured with their own IDs: - [Search button](interfaces/controller.controllerconfig.html#buttonid) - [Search input](interfaces/controller.controllerconfig.html#inputid) - [Address select](interfaces/controller.controllerconfig.html#selectid) - [Message box](interfaces/controller.controllerconfig.html#messageid) ### WAI-ARIA Postcode Lookup exposes some accessibility settings. - [Search input aria label](interfaces/controller.controllerconfig.html#inputAriaLabel) - [Address select aria label](interfaces/controller.controllerconfig.html#selectAriaLabel) The following WAI-ARIA components of Postcode Lookups have WAI-ARIA attributes enabled - Message box has `aria-role` is set to alert to immediately notify the user - Postcode Lookup container has `aria-live` enabled to alert users to updates in the address dropdown - Search input accepts an Enter/Return key to trigger an address search without submitting the form ### Configure Behaviour #### [`checkKey`](interfaces/controller.controllerconfig.html#checkkey) If enabled, the plugin will check if the key is in a usable state before initialising itself. The check can fail if: - Your key has no remaining lookups - Your key has run into its lookup limit for the day - Your key is requested from a URL which is not on your whitelist - The user seeking to use the key has exceeded their limit for the day If the check fails, the plugin will not initialise. You can use the [`onFailedCheck`](interfaces/controller.controllerconfig.html#onfailedcheck) callback to customise your response to a failed check. Defauts to `true`. #### [`strictlyPostcodes`](interfaces/controller.controllerconfig.html#strictlypostcodes) If enabled, any lookups which do not validate as a standard postcode will be passed to the address search API instead. You can configure address search by passing in a a [configuration object](interfaces/controller.controllerconfig.html#addresssearchformatter). Currently this configuration object only accepts one parameter: limit. Limit determines the maximum number of search results to return. (Default is 10, maximum is 100). Defaults to `true`. #### [`titleizePostTown`](interfaces/controller.controllerconfig.html#titleizeposttown) Title case the post town (`true`) or keep in all caps (`false`). All caps post town is recommended by Royal Mail's good addressing guidelines. If enabled, any lookups which do not validate as a standard postcode will be passed to the address search API instead. Defaults to `true`. #### [`removeOrganisation`](interfaces/controller.controllerconfig.html#removeorganisation) If set to `true`, organisation name will be removed from the address. Note that addresses which are exclusively an organisation name will not result in the organisation name being removed as this will result in no premise identifier. Defaults to `false`. #### [`selectSinglePremise`](interfaces/controller.controllerconfig.html#selectsinglepremise) If set to `true`, the premise will be immediately populated if the result set of an address or postcode search contains a single premise. Note the address selection box will not appear. Note that `onAddressSelected` callback is still invoked in this instance. To detect whether the last address search yielded a single premise, the controller instance data property will have a single element. i.e. `this.data.length === 1`. Defaults to `false`. #### [`hide`](interfaces/controller.controllerconfig.html#hide) Accepts an array of HTMLElements or CSS selectors. E.g. ```javascript { hide: [ "#line_1", document.getElementById("line_2"), document.querySelector("#line_3")], ], } ``` When enabled, the HTMLElements supplied in `hide` are hidden with `display: none;` when Postcode Lookup successfully initialises. These elements will be subsequently unhidden if an address is selected or the user opts to manually input an address. Enabling this feature will also create a clickable element in the Postcode Lookup container, which provides users the option to manually input an address. You may provide your own clickable element with `unhide` or customise the clickable element with `msgUnhide` and `unhideClass`. Defaults to `[]`. #### [`autocomplete`](interfaces/controller.controllerconfig.html#autocomplete) Sets the `autocomplete=` attribute of the input element. Setting this attribute aims to prevent some browsers (particularly Chrome) from providing a clashing autofill overlay. The best practice for this attribute breaks over time (see https://stackoverflow.com/questions/15738259/disabling-chrome-autofill) and is specific to different forms. If you are observing chrome's autofill clashing on your form, update this attribute to the best practice du jour. Defaults to `"none"`. ### Message Customisation #### [`placeholder`](interfaces/controller.controllerconfig.html#placeholder) Sets the default placeholder label on input field. Defaults to `"Search your postcode"`. #### [`buttonLabel`](interfaces/controller.controllerconfig.html#buttonlabel) Sets the label on the button. Defaults to `"Find my Address"`. #### [`msgSelect`](interfaces/controller.controllerconfig.html#msgselect) Sets the topline message for the dropdown menu. Defaults to `"Please select your address"`. #### [`msgUnhide`](interfaces/controller.controllerconfig.html#msgunhide) Sets the message on the clickable HTMLElement that unhides any fields defined in `hide`. Defaults to `"Enter address manually"`. ### Custom Elements If you wish to bring your own HTML elements to function as the postcode input, button, etc. #### [`input`](interfaces/controller.controllerconfig.html#input) If you wish to use your own input field, you can specify the unique css selector for that field here. E.g. `"#myCustomPostcodeLookupField"`. Please note that all input field parameters like `inputClass` and `placeholder` will be ignored. It will be up to you to implement styling and any desired behaviours in your input field. #### [`button`](interfaces/controller.controllerconfig.html#button) If you wish to use your own lookup button, you can specify the unique css selector for that field here. E.g. "#customLookupTrigger". Any "clickable" DOM element will work as a valid "button" to trigger a lookup. Please note that all other parameters like `button_disabled_message` will be ignored. It will be up to you to implement styling and any desired behaviours for your lookup button. #### [`selectContainer`](interfaces/controller.controllerconfig.html#selectcontainer) Specify a query selector (`string`) or (`HTMLElement`) custom container for the `HTMLSelectElement` which will display address suggestions. The default select container is hidden using `display: none;` and unhidden by setting display to `""`. A custom `selectContainer` will not have `display: none;` initially applied but it will be unhidden by setting display to `""`. To hide your `selectContainer` to also be initially hidden apply `style.display = "none"` or `style="display: none;"` to your container element. #### [`message`](interfaces/controller.controllerconfig.html#message) Specify a query selector (`string`) or (`HTMLParagraphElement`) as a custom container for messages. If a message or error prompt needs to be shown (e.g. postcode not found) a &lt;p&gt;, the message is inserted into the specified container. This container is hidden and unhidden using `display: none`. However it is not initially hidden. To hide your message container, apply `style.display = "none"` or `style="display: none;"` to your container element. #### [`unhide`](interfaces/controller.controllerconfig.html#unhide) Specify a query selector (`string`) or (`HTMLElement`) as a custom clickable element to unhide and form fields configured with `hide`. ### Lifecycle Callbacks Postcode Lookup also provides callbacks which let you hook into specific events in the Controller lifecyle. #### [`onLoaded`](interfaces/controller.controllerconfig.html#onloaded) A function invoked once the plugin has initialised. #### [`onRemove`](interfaces/controller.controllerconfig.html#onRemove) A function invoked when a plugin instance is detatched using `removeAll`. #### [`onButtonTrigger`](interfaces/controller.controllerconfig.html#onButtonTrigger) A function invoked when the search button is triggered (i.e. clicked, pressed). #### [`onFailedCheck`](interfaces/controller.controllerconfig.html#onfailedcheck) A function invoked if `checkKey` is enabled and the API Key check fails. #### [`onSearchCompleted`](interfaces/controller.controllerconfig.html#onsearchcompleted) A function invoked as soon as an address search successfully completes. Note, this is also invoked on all errors including: - 404-type errors such as "postcode not found" returning `[]` as the list of addresses. - Other 4XX and 5XX errors where the `error` argument will be available #### [`onAddressesRetrieved`](interfaces/controller.controllerconfig.html#onaddressesretrieved) A function invoked when a successful API request is made and at least 1 address is returned. This property takes a function, which accepts an `addresses` argument representing the addresses returned by the API. #### [`onAddressSelected`](interfaces/controller.controllerconfig.html#onaddressselected) A function invoked when the user selects an address option on the plugin's dropdown menu. This property takes a function, which accepts a `address` argument representing the full details of the selected address. #### [`onAddressPopulated`](interfaces/controller.controllerconfig.html#onaddresspopulated) A function invoked after a selected address has been applied to output fields. #### [`onSelectCreated`](interfaces/controller.controllerconfig.html#onselectcreated) A function invoked when addresses have been retrieved and the dropdown has been inserted into the DOM. #### [`onSelectRemoved`](interfaces/controller.controllerconfig.html#onselectremoved) A function invoked when select element is removed from the DOM as user attempts to search another address or postcode. #### [`onLookupTriggered`](interfaces/controller.controllerconfig.html#onlookuptriggered) A function invoked when the user triggers a lookup (e.g. by clicking the button). This callback is invoked before any request is made to the API. #### [`onSearchError`](interfaces/controller.controllerconfig.html#onsearcherror) A function invoked when the API returns an error. This property takes a function, which accepts an `error` argument representing the error returned by the API. Examples of errors includes "lookup balance exhausted" and "lookup limit reached" errors. #### [`onUnhide`](interfaces/controller.controllerconfig.html#onunhide) A function invoked when fields defined in `hide` are unhidden. Useful for further customisation when address fields are finally presented to the user. This function must be idempotent as it can be invoked multiple times during both hidden and unhidden states. #### [`shouldLookupTrigger`](interfaces/controller.controllerconfig.html#shouldlookuptrigger) A function invoked just before the plugin triggers a lookup when the search button is clicked. If `false` is returned, the search API request is aborted. ### Scoping It is possible to narrow the scope in which the Postcode Lookup Controller can operate. For instance, if you wish for a Controller to just operate on a billing address form and another Controller to operate only on a shipping address form, you can use the `scope` or `outputScope` options to do this. #### [`scope`](interfaces/controller.controllerconfig.html#scope) Scopes the operable area of the DOM using a query selector or HTMLElement. By assigning a scope, the Controller will only attempt to resolve for `HTMLElement`s within that scope. Defaults to `window.document`. #### [`outputScope`](interfaces/controller.controllerconfig.html#outputscope) Scopes the operable area of the DOM using a query selector or HTMLElement when resolving output fields. Defaults to the scope of the Controller.