Skip to content

Menu and Triggers

This page documents the add-on menu, its lifecycle, the triggers that power automation, and the core workflow functions defined in src/v3Legacy/Code.js, src/v3Legacy/Code_helper_functions.js, and src/v3Legacy/v3/.

The add-on menu

The menu is built by createAddonMenus_() and finished by the shared helper addMenuToUi() (src/sheetUiMenu.ts), which appends a common footer to every menu variant:

  • 🚂 Send to A11ytrainshowSidebar
  • about: v\<app version> → inert version label (doNothing)

Which menu the user sees depends on authorization state.

Before the workflow is started

When the add-on is installed but the user has not yet started the workflow in the current spreadsheet, the simple onOpen trigger (defined in src/main.ts) draws a single item:

Label Function
Start workflow runMenuStartWorkflow

If the per-user workflowStarted property already exists, a placeholder "Wait. May be loading..." item is shown instead. It is expected to be overwritten moments later by the full menu drawn by the installable trigger.

When updates are pending

If the spreadsheet has pending updates that require confirmation, the full menu is suppressed and replaced by a lock menu: an inert "Updates pending. Contact [tech support] if you keep seeing this." item plus Cancel workflow. While this lock is active, all onEdit automation is also disabled.

Full menu

Menu item Function
📏 Preview results → 🖥️ Large view previewOpenLargeView
📏 Preview results → 📌 Sidebar view runMenuPreviewReport
🎯 Internal quality checks.. runMenuQualityCheck
📄 Create reports.. runMenuCreateReports
🐞 Report third party vendor bug runMenuThirdPartyVendorBugReport
Fill "Image / Video" and "Fixed Image / Video" fillImagesLinks
Additional → Add n issues addIssuesRowsV3
Additional → Reset sheets resetSheetsUiV3
Additional → Copy sheets from template copySheetsUi
Additional → Go to Template spreadsheet.. runMenuOpenTemplateSpreadsheet
Additional → Cancel workflow runMenuCancelWorkflow
🏁 Finalize startFinalizeFromUI
lab: check EN style → Review results reviewLanguageStyle
lab: check EN style → Apply changes applySuggestionsToAuditTab
🚂 Send to A11ytrain showSidebar

Role-based visibility

The menu itself has no role checks; every authorized user sees the same items. Role differentiation only exists inside the HTML app: the Create reports screen filters report options by the roles defined in src/v3Legacy/v3/Users.js (ISSUE_LIST_USER_ROLES).

Triggers

Simple triggers

  • onOpen(e) (src/main.ts) runs in AuthMode NONE/LIMITED and only draws the one-item "Start workflow" (or "Wait. May be loading...") menu.
  • There is deliberately no simple onEdit. The edit handler is named onEditTriggerFunction precisely so Apps Script does not auto-fire it as a simple trigger.

Install trigger

  • onInstall(e) fires when the add-on is installed. It intentionally re-invokes onOpen with AuthMode.NONE so the user must still click "Start workflow" before the document is treated as an audit. This prevents a non-audit spreadsheet from being marked as an audit at install time.

Installable triggers (per user, per spreadsheet)

Created by runMenuStartWorkflowresetTriggers_(ssId) and removed by runMenuCancelWorkflowdeleteTriggers_(ssId).

  1. ON_OPEN → onOpenTriggerFunction - guards with isUserAtKeyboardCreatorOfTrigger(), sleeps 4 seconds so it wins the race against the simple onOpen menu, then builds the full menu and applies any spreadsheet updates that do not need confirmation.
  2. ON_EDIT → onEditTriggerFunction - delegates to onEditSheetCallback(ssId, e).

onEditSheetCallback routes by the edited sheet:

  • Results sheet: loads audit and template data, then runs onEditSheetCallbackResults (row reset plus Date Logged / Logged by / Date Fixed-Closed automation).
  • Scenarios sheet: onEditSheetCallbackScenarios (re-triggers validation refresh on the Results "Scenario / URL" column and resets the "Report: NA or Support - v3" sheet), then fillScenariosInReviewReportSheet.
  • Report: NA or Support - v3 sheet: onEditSheetCallbackReportNaOrSupportV3 (refreshes the remarks Preview column).

Automation aborts entirely if the effective user is not the user at the keyboard, or if confirmation-required spreadsheet updates are pending.

Per-user triggers

Triggers are created per user, so each collaborator must run Start workflow once per spreadsheet. Cancel workflow only affects the person who runs it.

Custom spreadsheet function

  • PREVIEW_REMARKS(range) (Code_helper_functions.js) - a custom formula usable directly in a cell. For each row (Criteria, Conformance Level, Details) it recomputes the NA/Support data and returns the exact Conformance Level: ... / Remarks: ... text that will appear in reports.

Workflow functions (Code.js)

User-facing functions:

Function Description
runMenuStartWorkflow() The authorization entry point. Installs the per-user onOpen/onEdit triggers, sets the workflowStarted user property, rebuilds the menus, and shows a confirmation toast.
runMenuCancelWorkflow() Deletes the user's triggers for this spreadsheet, clears the workflowStarted property, reverts to the one-item menu, and shows a toast.
runMenuOpenTemplateSpreadsheet() Opens a small modal with a link to the master Template spreadsheet.
copySheetsUi() Opens the "Copy sheets from template spreadsheet" modal, listing every sheet in the template for the user to pick.
doReplaceSheets(copySheetIds) Called from the copy-sheets dialog. Copies each selected template sheet into the current spreadsheet, replaces same-named old sheets, and restores position and hidden state.
resetSheetsUiV3() Menu wrapper that calls resetSheets(ssIdCurrent) to rebuild and repair all audit sheets.
fillImagesLinks() Loads audit and template data and runs a full Results-sheet row reset, which fills the "Image / Video" and "Fixed Image / Video" columns from the Assets folder.
addIssuesRowsV3(ssId?) Prompts for a count N, inserts N blank rows after the last numbered issue, assigns sequential IDs and default column values, then resets the Results sheet formatting and refreshes the sheet filter.
onInstall(e) Add-on install trigger (see above).
onOpenTriggerFunction() Installable on-open handler (see above).

Key internal helpers:

Function Description
createAddonMenus_() Builds the add-on menu (full or lock variant, see above).
onOpenSheetCallback() Shared "document opened and authorized" routine: builds the menus and applies non-confirmation spreadsheet updates.
isUserAtKeyboardCreatorOfTrigger() True only when the active user equals the effective user; prevents duplicate per-user triggers from all firing at once.
getAssetFiles() Lazily loads and caches every file in the Assets subfolder next to the spreadsheet's report folder.
getImageUrlByIssueId(issueId, isFixed) Finds the asset file whose name matches the issue number, makes it public-view, and returns its Drive URL. isFixed selects files containing "FIX".
createNewResultsRowData_(data, newId, cols) Builds one blank Results row with the ID and default values (Featured = FALSE, Issue Owner = Client Issue).
getEEFormattedDate(date) Formats a date in Equal Entry prose, e.g. March 3rd, 2026.
getConfigVal(name, new_data) / setConfigVal(key, value) Read (cached) and write values on the Configuration sheet.
getFormulaHyperlinkParsed(formula, richText) Extracts {url, text} from a =HYPERLINK(...) formula or a cell's rich-text link.
getAssetInfoByDriveFileURL(driveFileURL) Classifies a linked Drive file as image / video / other and returns its ID, preview URL, and pixel dimensions. Rejects images over 1 MB.
getGoogleDriveFileIdFromUrl(url) Pulls the file ID out of a Drive URL.
sendEmail_(to, subject, body) Thin wrapper over GmailApp.sendEmail.
_getSS() / _getSheetByName(name) / _getSheetByNameV3(sheets, name) Cached spreadsheet and sheet lookups.
_getCurSSReportsFolder() Returns (creating if needed) the <Product Name> Report subfolder beside the spreadsheet.

Code.js also holds the global configuration constants: sheet names (sheetNames), column names (colNames), configuration keys (configKeys), status values (statusObj, statusEnum, vpatSupportedStatuses), issue owners (issueOwnerEnum), default values, VPAT boilerplate (reportNotesFields), menu labels (menuOptions), Drive folder IDs, and the template spreadsheet ID.

Helper functions (Code_helper_functions.js)

Function Description
resetSheetFilter(sheet) Re-applies a basic filter over the sheet's full used range so newly inserted rows are included.
openSidebar_(html) Shows HTML output in the Sheets sidebar.
openPopup_(html, title) Shows HTML output as a large modal dialog.
getAppHTML_(data) Builds the single-page HTML app used by the preview, quality check, and create-reports screens, injecting screen data and globals.
computeKeysForAllWCAGVersions_(...) Expands compute keys into per-WCAG-version suffixed keys (2.0 and 2.1).

Trigger management (v3/Triggers.js)

All internal; reached via Start/Cancel workflow.

Function Description
resetTriggers_(ssId) / deleteTriggers_(ssId) Recreate or delete both installable triggers for the spreadsheet.
resetTriggerOnOpen(ssId) / deleteTriggerOnOpen(ssId) Delete-then-create (or just delete) the ON_OPEN trigger. Creation errors in add-on test mode are caught and logged.
resetTriggerOnEdit(ssId) / deleteTriggerOnEdit(ssId) Same pattern for the ON_EDIT trigger.
getUserTrigger_(ssId, eventType, triggerSource) Finds the current user's installable trigger matching event type, source, and spreadsheet.
logCreatedTriggers() / logCreatedTrigger(trigger) Debug logging for project triggers.

Users (v3/Users.js)

Function Description
getUser() Looks up the active user's email in the hard-coded user list and returns their record (with roles), or null. Feeds role info into the HTML app.
isUserInRole(role) Whether the user at the keyboard holds a given role; throws on unknown roles.
isValidUserRole_(role) True if the role is one of ISSUE_LIST_USER_ROLES.

Edit-time automation (v3/Code_on_edit.js)

Function Description
onEditTriggerFunction(e) Installable onEdit handler; forwards to onEditSheetCallback.
onEditSheetCallback(ssId, e) Main edit dispatcher (see Installable triggers).
onEditSheetCallbackResults(e, ...) Resets edited Results rows; stamps Date Logged / Logged by when empty, sets Date Fixed/Closed when the status becomes Fixed or Closed, and clears it otherwise.
onEditSheetCallbackScenarios(ssId, e) Refreshes Results "Scenario / URL" validations and resets the "Report: NA or Support - v3" scenario dropdowns.
onEditSheetCallbackReportNaOrSupportV3(e, data) Regenerates the remarks Preview column.
fillScenariosInReviewReportSheet(ssId) Extracts every unique URL per scenario from the Scenarios sheet and rewrites the "Review Report Output" sheet's Scenarios List / URL columns.
getTutorialForCriteria_(criteriaName, commonData) Returns the first tutorial {url, title} registered for a success criterion.
getHyperlinkFormula_(title, url) Builds a =HYPERLINK(...) formula string, escaping quotes.
TEST_ON_EDIT() Developer harness for manually invoking the edit callback (installable onEdit triggers do not fire in add-on test mode).

Common data and shared functions

v3/Common.js - template reference data

Loads reference data from the master Template spreadsheet (not the audit at hand). All internal.

Function Description
commonData_(currentSheetData, config) Opens the template spreadsheet and dispatches to the requested loaders (criterias, tutorials, files, vpat_table_added_text).
getCriteriasV3_(...) / getCriteriaDataFromSheetV3(...) Read the "Issue Titles - v3" template sheet column-wise: source, criteria name (with URL), severity, then issue titles.
getTutorials_(...) Builds a criteria-name → tutorials map.
getVPATTableAddedTextV3_(...) Composes the "Revised Section 508" and "EN 301 549 Criteria" HTML blurbs used in VPAT tables.

v3/Common_functions.js - shared utilities

Notable entries (all internal unless noted):

Function Description
runInspectEntityById(type, id) User-facing (HTML UI). "Jump to this thing in the sheet": resolves an issue, scenario_step, report_na_or_support_record, or configuration_record to a range and activates it.
include(filename) HtmlService templating helper that inlines another HTML file (used heavily by the app shell).
getIssueRange_ / getScenarioStepRange_ / getReportNaOrSupportRecordRange_ / getConfigurationRecordRange_ Resolve entity IDs to sheet ranges for the inspector.
getURLValueForScenarioStep_(step, scenario) Determines the URL a scenario step applies to, walking backwards through preceding steps for ordered scenarios.
extractURLFromString(str) / getUrlsFromText(text) Extract URLs from markdown/free text (Cheerio-based and regex-based respectively).
dataValidationForList_ / dataValidationForRange_ / dataValidationForFormula_ / dataValidationForCheckbox_ Builders for Sheets data-validation rules.
searchAuditFiles_(scope) / searchAuditFilesInFolders_(folders, version) / searchAuditFile_(ssId) / searchPreV3AuditFiles_() Drive searches for audit spreadsheets, using public Drive file properties to identify v3 audits.
insertDriveFileProperty / getDriveFileProperty Read/write public custom Drive properties (version and audit markers).
setUserPropertyForDocument / getUserPropertyForDocument / deleteUserPropertyForDocument Per-user properties namespaced by spreadsheet ID (e.g. workflowStarted).
isImageSizeLessThanLimit(file) True if the file is not an image or is under the 1 MB limit.
runActivateRange_, onlyUnique, _columnToLetter, escapeRegExpText, getStepId_, getScenarioNumAndStepNumByStepId_, getIssueByRowNum_, getRefIdByCriteriaName_, getScenarioByName_ Small general-purpose helpers.