UNPKG

@ideal-postcodes/postcode-lookup

Version:
530 lines (529 loc) 17.9 kB
/** * @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 };