@ideal-postcodes/postcode-lookup
Version:
UK Postcode Lookup plugin from Ideal Postcodes
530 lines (529 loc) • 17.9 kB
TypeScript
/**
* @module Postcode-Lookup Exports
*/
import { Controller, ControllerConfig } from "./controller";
import { watch } from "./watch";
import { GbrAddress } from "@ideal-postcodes/jsutil";
export interface OnLoaded {
(this: Controller): void;
}
/**
* Invoked when a user click search button
*/
export interface OnButtonTrigger {
(this: Controller): void;
}
/**
* Invoked when a search succeeds, E.g. Server responds that Postcode is found or doesn't exist
*/
export interface OnSearchCompleted {
(this: Controller, error: any, addresses: GbrAddress[]): void;
}
/**
* Invokwed when a lookup succeeds with a list of addresses
*/
export interface OnAddressesRetrieved {
(this: Controller, addresses: GbrAddress[]): void;
}
/**
* Invoked when user has clicked an address in select menu
*/
export interface OnAddressSelected {
(this: Controller, address: GbrAddress | void): void;
}
/**
* Invoked when address results are applied to input fields
*/
export interface OnAddressPopulated {
(this: Controller, address: GbrAddress): void;
}
/**
* Invoked when the address select field is inserted to DOM
*/
export interface OnSelectCreated {
(this: Controller, select: HTMLSelectElement): void;
}
/**
* Invoked when the address selection select input is removed (following new search)
*/
export interface OnSelectRemoved {
(this: Controller): void;
}
/**
* Invoked when user clicks the button to trigger a lookup
*/
export interface OnLookupTriggered {
(this: Controller): void;
}
/**
* A function to test whether a lookup should be performed at all
*/
export interface ShouldLookupTrigger {
(this: Controller): boolean;
}
/**
* Invoked when a request succeeds but the API returns an error code
*/
export interface OnSearchError {
(this: Controller, error: any): void;
}
/**
* Invoked when any fields hidden by `hide` are unhidden. Ensure this callback is idempotent as it can be triggered more than once during both hidden and unhidden states
*/
export interface OnUnhide {
(this: Controller): void;
}
/**
* Invoked when `removeAll` is invoked
*/
export interface OnRemove {
(this: Controller): void;
}
/**
* Callback invoked when API Key is enabled but check failes
*/
export interface OnFailedCheck {
/**
* Returns error if API request fails for some reason
*
* Note. not the same as key being unavaialble
*/
(error: any): void;
}
/**
* OutputFields can be identified by the address attributes supported by the API
*
* Typings for the API GbrAddress object can be found at [@ideal-postcodes/jsutil](https://github.com/ideal-postcodes/jsutil/blob/master/lib/types.ts)
*/
export declare type OutputFields = Partial<Record<keyof GbrAddress, SelectorNode>>;
/**
* Represents either a HTMLInputelement or a selector pointing to one
*/
export declare type SelectorNode = string | HTMLInputElement | HTMLTextAreaElement;
/**
* Formats how address objects are presented as address suggestions to the user
*/
export interface GbrAddressFormatter {
(address: GbrAddress): string;
}
export declare type CSSStyle = Partial<Record<keyof CSSStyleDeclaration, string>>;
/**
* Base configuration interface for Controller
*
* @hidden
*/
export interface Config {
/**
* DOM context in which to inject Postcode Lookup tools
*
* @required
*/
context: string | HTMLElement;
/**
* API Key associated with your account. Typically begins `ak_`
*
* @required
*/
apiKey: string;
/**
* Set to `true` to check if key is usable - will not initialise if set to true and key not usable
*
* 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. Use the `onFailedCheck` callback handle a failed check scenario
*/
checkKey?: boolean;
/**
* Scopes the operable area of the DOM
*
* @default `window.document`
*/
scope?: Document | HTMLElement | string;
/**
* Specify the Document to operate on
*
* @default `window.document`
*/
document?: Document;
/**
* 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 HTMLInputElement
*
* 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 GbrAddress Line One data to a HTML entity 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 GbrAddress 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.
*
* Output fields assigned with a query selector are evaluated lazily (i.e. when an address attribute needs to be piped to a field).
*
* @default {}
*
* @example
* ```javascript
* {
* line_1: "#line_1",
* line_2: "#line_2",
* line_3: "#line_3",
* post_town: document.getElementById("post_town"),
* postcode: document.getElementById("postcode")
* }
* ```
*/
outputFields?: OutputFields;
/**
* Specify parent element for output fields to looking for them to narrow search area.
*/
outputScope?: string | HTMLElement | Document | null;
/**
* An optional CSS selector which designates a custom input field provided by you.
*
* @example "#my_custom_input"
*/
input?: string | HTMLInputElement | null;
/**
* Default placeholder message in input field. Inserted as `placeholder` attribute of `input` element.
*
* @default "Search your postcode"
*/
placeholder?: string;
/**
* CSS class to attached to input element.
*
* @default "idpc-input"
*/
inputClass?: string | null;
/**
* Aria Label provided to input field. Identifies to a visually impaired user how to operate postcode lookup.
*
* @default "Search a postcode to retrieve your address"
*/
inputAriaLabel?: string;
/**
* ID of input element.
*
* @default null
*/
inputId?: string | null;
/**
* An optional CSS selector or HTMLSelectElement which designates a custom button provided by you.
*
* @example "#my_custom_button"
*/
button?: string | HTMLButtonElement | null;
/**
* ID of button element.
*
* @default null
*/
buttonId?: string | null;
/**
* Label attached to button.
*
* @default "Find my GbrAddress"
*/
buttonLabel?: string;
/**
* CSS class to attached to button element.
*
* @default "idpc-button"
*/
buttonClass?: string | null;
/**
* Message shown when button is temporarily disabled due to lookup.
*
* @default "Finding addresses..."
*/
msgDisabled?: string;
/**
* Designates ID of `<select>` element which presents address suggestions.
*
* @default null
*/
selectId?: string | null;
/**
* Default message shown at top of `<select>` menu.
*
* @default "Please select your address"
*/
msgSelect?: string;
/**
* CSS class to attached `<select>` input field.
*
* @default "idpc-select"
*/
selectClass?: string | null;
/**
* Aria Label provided to select input. Directs a visually impaired user to select another address on the list.
*
* @default "Select your address"
*/
selectAriaLabel?: string | null;
/**
* An optional CSS selector or HTML Element which designates where the address results `<select>` element should be inserted.
*
* 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.
*
* @example "#my_custom_select_container"
*
* @example document.querySelector("#my_custom_select_container");
*/
selectContainer?: string | HTMLDivElement | null;
/**
* ID of the select container.
*
* @default null
*/
selectContainerId?: string | null;
/**
* Class of the select container.
*
* @default "idpc-select-container"
*/
selectContainerClass?: string | null;
/**
* Specify a clickable element to unhide elements hidden with `hide`.
*
* @default null
*/
unhide?: string | HTMLElement | null;
/**
* Class of clickable unhide element.
*
* @default "idpc-unhide"
*/
unhideClass?: string | null;
/**
* ID of message container element.
*
* @default null
*/
messageId?: string | null;
/**
* Error message presented if invalid postcode.
*
* @default "Your postcode could not be found. Please type in your address"
*/
msgNotFound?: string;
/**
* Error message presented when a freeform address search takes place and no matches are found.
*
* @default "We could not find a match for your address. Please type in your address"
*/
msgAddressNotFound?: string;
/**
* Error message presented when an unknown error occurs
*
* @default "Sorry, we weren't able to get the address you were looking for. Please type in your address"
*/
msgError?: string;
/**
* Message shown to user to unhide address fields if `hide` attribute is configured.
*
* @default "Enter address manually"
*/
msgUnhide?: string;
/**
* CSS class to attached to message container element
*
* @default "idpc-error"
*/
messageClass?: string | null;
/**
* An optional CSS selector which designates where the message container element should be inserted.
*
* Custom message containers are not initially hidden, though they are later unhidden by setting `style.display to `""`. To hide your message container, apply `style.display = "none"` or `style="display: none;"` to your container element.
*
* @example "#my_custom_msg_container"
*/
message?: string | HTMLParagraphElement | null;
/**
* Requires user to enter postcode only.
*
* If set to false, the search term will be searched as a complete address rather than a postcode. So searches such as `SW1A 2AA 10` are possible.
*/
strictlyPostcodes?: boolean;
/**
* Maximum number of addresses to present in select menu following an address search.
*
* Only applies if strictlyPostcodes is `false`.
*
* If strict postcode matching is set to `false`, it's possible to pull down a larger set of address matches. This limit contrains the number of address results that can be presented to the user
*
* @default 10
*/
limit?: number;
/**
* The search button is temporarily disabled upon a click to prevent double presses. `cooloff` attribute sets the number of milliseconds to wait before the search button is active
*
* Set to `0` to disable altogether
*
* @default 500
*/
cooloff?: number;
/**
* 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.
*
* @default "none"
*/
autocomplete?: string;
/**
* Organisation name forms part of the address. Set this to `true` to strip the address line results of organisation name.
*
* Note that this may not be a good idea in a small number of scenarios as some "Large User" addresses consist of just an organisation name, post town and postcode.
*
* @default false
*/
removeOrganisation?: boolean;
/**
* 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`.
*
* @default false
*/
selectSinglePremise?: boolean;
/**
* 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
*
* @default true
*/
titleizePostTown?: boolean;
/**
* Hide a list of HTML elements when Postcode Lookup is instantiated
*
* Specify these elements using query selectors or direct HTMLElement references
*
* @default []
*/
hide?: (string | HTMLElement)[];
/**
* Customise how you wish to present postcode lookup address suggestions in the select box
*
* Converts an address object into a sugestion string presented to user
*/
postcodeSearchFormatter?: GbrAddressFormatter;
/**
* Customise how you wish to present freeform address search suggestions in the select box
*
* Converts an address object into a sugestion string presented to user
*/
addressSearchFormatter?: GbrAddressFormatter;
/**
* Invoked when plugin is initialised
*/
onLoaded?: OnLoaded;
/**
* Invoked when a user click search button
*/
onButtonTrigger?: OnButtonTrigger;
/**
* Invoked when a search succeeds, E.g. Server responds that Postcode is found or doesn't exist
*/
onSearchCompleted?: OnSearchCompleted;
/**
* Invokwed when a lookup succeeds with a list of addresses
*/
onAddressesRetrieved?: OnAddressesRetrieved;
/**
* Invoked when user has clicked an address in select menu
*/
onAddressSelected?: OnAddressSelected;
/**
* Invoked when the address select field is inserted to DOM
*/
onSelectCreated?: OnSelectCreated;
/**
* Invoked when the address selection select input is removed (following new search)
*/
onSelectRemoved?: OnSelectRemoved;
/**
* Invoked when user clicks the button to trigger a lookup
*/
onLookupTriggered?: OnLookupTriggered;
/**
* Invoked when address results are applied to input fields
*/
onAddressPopulated?: OnAddressPopulated;
/**
* Invoked when `removeAll` is invoked
*/
onRemove?: OnRemove;
/**
* A function to test whether a lookup should be performed at all
*/
shouldLookupTrigger?: ShouldLookupTrigger;
/**
* Invoked when a request succeeds but the API returns an error code
*/
onSearchError?: OnSearchError;
/**
* Invoked when any fields hidden by `hide` are unhidden. Ensure this callback is idempotent as it can be triggered more than once during both hidden and unhidden states
*/
onUnhide?: OnUnhide;
/**
* Callback invoked when API Key is enabled and check fails
*/
onFailedCheck?: OnFailedCheck;
/**
* Assign `style` attribute of postcode input
*
* @default {}
*/
inputStyle?: CSSStyle;
/**
* Assign `style` attribute of button
*
* @default {}
*/
buttonStyle?: CSSStyle;
/**
* Assign `style` attribute of message container
*
* @default {}
*/
messageStyle?: CSSStyle;
/**
* Assign `style` attribute of address select
*
* @default {}
*/
selectStyle?: CSSStyle;
/**
* Assign `style` attribute of postcode lookup container
*
* @default {}
*/
contextStyle?: CSSStyle;
/**
* Suppresses `county` from being populated if set to `false`
*
* @default true
*/
populateCounty?: boolean;
}
/**
* Namespace that exports Postcode Lookup methods and classes
*/
export declare const PostcodeLookup: {
controllers: Controller[];
setup: (config: ControllerConfig) => Controller;
Controller: typeof Controller;
defaults: Required<Omit<Config, "document" | "scope">>;
watch: import("./watch").Watch;
};
export { Controller, ControllerConfig, watch };