Today we worked on the client side/browser hook code. We paid close attention to making sure it wouldn't block the browser. We're preparing a ready version to link to the main Engineering.com system (or at least a dev version of it) completely cloud-hosted, so we wanted to code these best practices ahead of time to make sure what we create is good enough to use in production.

I specifically worked on creating client side event handles that would log when a user begins to fill out a form, and also would log when that user submits the form. One thing we have to be careful about is treating each group of form inputs as their own entity. If they have more than form on the page (perhaps an email sign up, and a comment area), we want to track when they start to fill these out and/or submit them separately. See the example below. We set the event handle for "click" for radio buttons and checkboxes, and "onkey" for text inputs, so that it's able to track them all:

// Find all form elements
const forms = document.getElementsByTagName('form');

// For each of them...
for (let i = 0; i < forms.length; i++) {
    // Each set of inputs get their own group of event handles
    // (inputs for one form don't interfere with inputs of another form)
    // ...prepare an array of child input elements
    const children = forms[i].children;

    // filter for just inputs
    const inputs = [];
    for (let i = 0; i < children.length; i++) {
        const child = children[i];
 
        if (child.tagName.toLowerCase() === 'input') {
            inputs.push(child);
        }
    }

    // Listener only fires for first form element changing
    let triggered = false;

    // For each of them, assign an onchange event listener
    inputs.forEach(input => {
        switch (input.type) {

            case 'text':
                input.addEventListener('keydown', () => {
                    if (!triggered) {
                        triggered = true;

                        // log the data
                        });
                    }
                });
                break;

            case 'checkbox':
            case 'radio':
                input.addEventListener('click', () => {
                    if (!triggered) {
                        triggered = true;

                        // log the data
                        });
                    }
                });
                break;
        }
    });
}

Note: This was originally posted on the blog I used for my co-op term while at Seneca College (mswelke.wordpress.com) before being imported here.