README
WaiverForever Waiver Widget
Adding a waiver widget to your website to allow participants to sign without leaving the page.
Usage
- Choose the preferred waiver templates from your templates.
- Go to Template Settings page -> Waiver Widget tab.
- Enable the widgets and configure them.
- Keep the
templateId
s for the next steps. - There are multiple ways of embedding our waiver widget into your website:
Click here to see our tutorial.
Want to add it to your WordPress website?Easy route: reference the widget script from CDN:
We can load the widget automatically or manually.
For automatically loading, append the following HTML snippet into the body
tag of your website:
<script src="https://cdn.waiverforever.com/qs3/ew.js?templateId=${templateId1,templateId2}"></script>
- Widget with its trigger button will be mounted as soon as the script is loaded. It exposes the
widget instance
as a global JavaScript variable namedwaiverWidget
(note: its initial letter is lowercase) andWF_EMBED_WAIVER
(for backward compatibility). - If you need multiple waivers be signed one by one, you can set multiple template IDs by join them with comma.
- The widget instance has a hook method
.onReady
, which you can use to perform extra operations if needed. - If you don't like the default triggering button and want to create your own way to trigger the waiver modal, simply adding a query
sdkMode=yes
to disable it:<script src="https://cdn.waiverforever.com/qs3/ew.js?templateId=${templateId1,templateId2}&sdkMode=yes"></script>
For manually loading, append the following HTML snippet into the body
tag of your website:
<script src="https://cdn.waiverforever.com/qs3/ew.js"></script>
- If the script's
src
doesn't contain a specifiedtemplateId
, the script exposes thewidget constructor
as a global JavaScript variable namedWaiverWidget
(note: its initial letter is uppercase). - You could manually initialize the
widget instance
on demand. Please make sure performing any extra operations after the.onReady
hook is triggered.
You could also load the widget script dynamically, e.g. The AMD way:
require(['https://cdn.waiverforever.com/qs3/ew.js'], function (WaiverWidget) {
const widget = new WaiverWidget({
templateId: `${templateId}`, // You can also pass multiple template ids as an array, they will be displayed one after signing one.
sdkMode: true
})
widget.onReady(function(){
myCustomButton.addEventListener('click', function () {
widget.toggle()
})
})
})
})
Importing the widget into the module system
Install the widget by npm
or yarn
:
# npm
npm i --save @waiverforever/waiver-widget
# yarn
yarn add @waiverforever/waiver-widget
// app.js
const WaiverWidget = require('@waiverforever/waiver-widget')
const widget = new WaiverWidget()
- TypeScript is fully supported.
- Definitions bring TS/JS users the better developing experience.
- Could be used in ES modules or CommonJS standards systems.
- Could be dynamically loaded by third-party bundler's code splitting feature.
Reference
Terms
- widget constructor: In manually loading or dynamically loading scenarios, the script exposes a constructor named
WaiverWidget
as a global variable. In a module system, we couldrequire
orimport
it directly. - widget instance: Instance of widget constructor. We could register events to its hooks and manipulate the instance through its methods.
- SDK mode: Widget without the default triggering button, you need to programmatically trigger the waiver modal.
- window mode: When enabled, instead of showing waiver modal, a new waiver page will be opened. If you passed multiple waiver template ID the window mode will be turn off.
API
WaiverWidget constructor
interface WidgetOption {
templateId: string | string[]; // required, template id, or pass multiple ids
sdkMode?: boolean; // by default is false
windowMode?: boolean; // by default it depends on the useragent (true for mobile devices, false for desktops)
stylesheetURL?: string; // specify the stylesheet URL of the embedded waiver
}
type WaiverWidgetConstructor = new (option?: WidgetOption): IWidget;
usage:
const widget = new WaiverWidget({
templateId: `${templateId}`,
})
WaiverWidget instance
interface IWidget {
closeEmbedWaiverModal: () => void; // Legacy API, for backward compatibility
show: () => void; // Show widget modal and hide trigger button(in non-sdk mode)
close: () => void; // Opposite operation of show()
toggle: () => void; // Toggle between show and close methods
destroy: () => void; // Destroy the current widget instance. After ensuring previous widget instance is destroyed, we can re-initialize another widget instance.
onShowed: (callback: () => void) => void; // Event registry for modal showed hook
onReady: (callback: (widget: IWidget) => void) => void; // Event registry for widget instance ready hook, an interactive widget instance will be passed to the registered hook
onLoad: (callback: (signedCount: number) => void) => void; // Event registry for waiver page loading in the SDK mode
onSigned: (callback: (signedCount: number) => void) => void; // Event registry for waiver signing success hook
onClosed: (callback: (signedCount: number) => void) => void; // Event registry for modal close hook, the registered callback will receives a boolean type argument presents whether the user signed or not
onDestroyed: (callback: () => void) => void; // Event registry for widget destroyed hook
}
Protips
If you get bored of using the callback style .onReady
hook and others, and the async/await
syntax is available in your runtime, here are some tips for you.
All of the widget APIs are thenable/awaitable
! It means you can use the widget instance
, instance methods
and event hooks
in a synchronous-like way.
Thenable/awaitable instance
Awaiting the response of the widget instance, we get a ready state (fully-interactive) instance.
// note: use in async function, or some `top-level await` syntax implemented environment
async function appDidMount () {
const widget = await new WaiverWidget({
templateId: `${templateId}`, // You can also pass multiple template ids as an array, they will be displayed one after signing one.
})
widget.show() // widget is in ready state
}
Thenable/awaitable instance methods
Awaiting a response of a widget method, we receive the callback payload of the method's corresponding event hook.
async function appShowWaiverInstruction () {
// `.onShowed` event has no return value
await widget.show()
sendLog('waiver showed')
}
async function appCloseWaiverInstruction () {
// We get the signed count, which is the `.onClosed` event's callback payload
const signedCount = await widget.close()
sendLog('waiver closed, with signed count: ' + signedCount)
}
Thenable/awaitable event hooks
A registered event handler will be triggered whenever the event occurs. An awaited event hook will only respond to the event payload for once.
async function appDidMount () {
// ... initialize widget instance ...
widget.onSigned(async function () {
// signedCount presents the number you signed successfully
const signedCount = await widget.onClosed
// Log will be sent under the condition that waiver is signed and then the modal is closed
sendLog('waiver closed, with signed count: ' + signedCount)
})
}
Actually, awaiting a response of a event hook is rarely used.