Event Hooks

Event Hooks give you basic control over certain aspects of the Tether widget by emitting and receiving javascript browser events. At the moment, we offer hooks for toggling visibility of the Tether floating action button, slide-out panel, and responding to feedback submissions - but we will continue rolling out additional hooks to provide you with more control over the Tether widget.

Quick Start Template

If you're looking for a drop-in solution, you can use this snippet to get started. This is a great option for users that want to quickly customize the button that toggles the Tether widget. We've prepared the button below with some basic styles, which you're free to use or edit to your liking. In fact, you can use any button or link, as long as the Tether widget is mounted on the page and the button/link is capable of emitting the tether.panel.toggle event.

  1. Create a new project
  2. Navigate to your project's settings page
  3. Select the "Widget" tab
  4. Under the "Event Hooks" section, make sure the "Widget visible by default" switch is unchecked
  5. Paste the snippet below into your application's HTML
<button
    onclick="window.dispatchEvent(new CustomEvent('tether.panel.toggle'))"
    id="tether-toggle-btn"
>
    <span>Submit Feedback</span> 
    <img style="margin-left: 7px;" src="https://assets.tethered.dev/tether-logo-gray-filled.png" width="16" alt="Tether Logo" />
</button>

<style>
    #tether-toggle-btn {
        color: rgba(55, 65, 81, 1);
        font-size: 13px;
        background-color: #ffffff;
        border-width: 0;
        border-radius: 7px;
        outline: none;
        padding: 5px 8px 5px 8px;
        display: flex;
        align-content: center;
        align-items: center;
        justify-content: center;
        filter: drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) drop-shadow(0 1px 1px rgb(0 0 0 / 0.06));
        transition: all 150ms ease-in-out;
        cursor: pointer;
    }

    #tether-toggle-btn:hover {
        transform: scale(1.03);
        filter: drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06));
    }

    #tether-toggle-btn:active {
        transform: scale(1.01);
        filter: drop-shadow(0 4px 3px rgb(0 0 0 / 0.06)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.05));
    }
</style>


Available Event Hooks

Hook Key Description Code Sample
tether.fab.show Show the Tether floating action button
window.dispatchEvent(new CustomEvent('tether.fab.show'))
tether.fab.hide Hide the Tether floating action button
window.dispatchEvent(new CustomEvent('tether.fab.hide'))
tether.fab.toggle Toggle the visibility of the Tether floating action button
window.dispatchEvent(new CustomEvent('tether.fab.toggle'))
tether.panel.show Open the Tether slide-out panel
window.dispatchEvent(new CustomEvent('tether.panel.show'))
tether.panel.hide Hide the Tether slide-out panel
window.dispatchEvent(new CustomEvent('tether.panel.hide'))
tether.panel.toggle Toggle the Tether slide-out panel
window.dispatchEvent(new CustomEvent('tether.panel.toggle'))
tether.feedback.submitted Event emitted by Tether when feedback is successfully submitted
window.addEventListener('tether.feedback.submitted', (event) => { 
    /* Do some stuff here */
    console.log('Feedback Submitted: ', event.detail);
})
tether.initialized Event emitted by Tether when it successfully mounts
window.addEventListener('tether.initialized', () => { 
    /* Do some stuff here */
    console.log('Tether Mounted');
})


Event Hook Aliases

We've also added some aliases for the most common use cases. These are just wrappers around the event hooks that are a bit easier to implement.

{info.fa-exclamation-circle} These aliases are not available until the Tether script has finished loading. To ensure Tether is mounted before using them, you can use the tether.initialized event hook, or bind a function to the window.tetherSettings.onInitialized alias like in the example below.

Shortcut Key Description Code Sample
tether.initialized Listen for initialized events fired when Tether finished mounting
window.tetherSettings = {
    onInitialized: () => {
         console.log('Tether Mounted!');
    }
};
tether.feedback.submitted Listen for Tether feedback submitted events
window.tetherSettings.hooks.feedbackSubmitted.startListening(
    (event) => console.log('Feedback Submitted:', event.detail)
)
tether.fab.show Show the Tether floating action button
window.tetherSettings.hooks.showFAB()
tether.fab.hide Hide the Tether floating action button
window.tetherSettings.hooks.hideFAB()
tether.fab.toggle Toggle the visibility of the Tether floating action button
window.tetherSettings.hooks.toggleFAB()
tether.panel.show Show the Tether feedback panel
window.tetherSettings.hooks.showPanel()
tether.panel.hide Hide the Tether feedback panel
window.tetherSettings.hooks.hidePanel()
tether.panel.toggle Toggle the visibility of the Tether feedback panel
window.tetherSettings.hooks.togglePanel()

Usage Examples

Using Tether event hooks is very simple, but may be unfamiliar to you if you don't have much experience with javascript browser events. I'll outline below a basic use-case case for event hooks in a scenario in which I want the Tether widget to be invisible unless toggled on by a button in my web app's nav bar.

{info.fa-info-circle} Before we continue, let's go to our Tether project settings and toggle off the "Widget visible by default" option. This will ensure that the Tether widget is only visible when we dispatch our tether.panel.show browser event.


Here's my web app - a simple job board. But it seems to have some pretty glaring bugs; there are broken images, mismatched buttons, and overlooked font colors. We'll report these issues using Tether, but as you can see the floating action button that is normally always visible, is nowhere to be found. That's because we only want the widget to be visible when our users are actually reporting feedback. Let's wire up that "Report Issue" button in the nav bar to emit a tether.panel.show event when clicked to reveal the Tether feedback panel.



Let's modify the page's HTML to dispatch our event hook when the button is clicked.



Before:

...
<nav role="navigation" class="nav-menu w-nav-menu">
    <a href="/favorites" class="favorite-navbar-link w-inline-block">
        <div>Favorite Jobs</div>
        <div class="favorites-count jetboost-user-total-favorites-9o2r">2</div>
    </a>
    <a id="button-tether" class="navbar-button report-issue w-button">Report Issue</a> <!-- Here's our button -->
    <a href="/submit-job" class="navbar-button w-button">Submit a Job</a>
</nav>
...


After:

...
<nav role="navigation" class="nav-menu w-nav-menu">
    <a href="/favorites" class="favorite-navbar-link w-inline-block">
        <div>Favorite Jobs</div>
        <div class="favorites-count jetboost-user-total-favorites-9o2r">2</div>
    </a>
    <a
        id="button-tether"
        onclick="window.dispatchEvent(new CustomEvent('tether.panel.show')) //Now we dispatch a tether.panel.show event on click"
        class="navbar-button report-issue w-button"
    >
        Report Issue
    </a>
    <a href="/submit-job" class="navbar-button w-button">Submit a Job</a>
</nav>
...



There are other ways we can trigger this javascript event when the button is clicked though. Which one you use depends on the constraints of your development environment, application, and just your personal preferences. The code below achieves the same effect using declarative javascript.

If you're unable to use the onclick attribute for your trigger, here's another method of dispatching our event hook using a click listener on our button:


<script>
    (function emitTetherShowOnClick() {
        const button = document.querySelector('#button-tether');

        button.addEventListener('click', () => {
            window.dispatchEvent(new CustomEvent('tether.panel.show'))
        });
    })();
</script>

{alert.fa-info-circle} Depending on where you place this code snippet, you may encounter DOM-loading race conditions. In order for our document.querySelector('#button-tether') to find the button, we need to make sure the DOM has finished loading. We can account for this by wrapping the code from above inside a DOMContentLoaded listener:

document.addEventListener('DOMContentLoaded', (
event)
=> {
    const button = document.querySelector('#button-tether');

    button.addEventListener('click', () => {         window.dispatchEvent(new CustomEvent('tether.panel.show'))     }); });


After implementing one of the changes outlined above, what we now expect to happen is for a tether.panel.show event to be dispatched when we click the "Report Issue" button. Let's give that a try:



Awesome! :tada:


The Tether widget is now visible so our user or team member can report a problem or suggest a change!