Encompass web form and its js file

 

As encompass is moving from desktop to web so custom form their designs etc are also changing and so its related js files are introduced.

All control access goes through a single confirmed entry point:

const c = await elli.script.getObject(id);

This returns a reactive control object with own properties id, value, visible, disabled, interactive, color, and error — not the getValue()/setValue()/setVisible()/setEnabled() method names a developer might expect from a more conventional UI framework. Each of value, visible, and disabled is itself both a getter and a setter: calling it with no argument reads the current value; calling it with an argument writes a new one. The “disabled” property is the inverse of “enabled” — there is no separate enabled property, so this script’s own setEnabled(id, enabled) helper must negate its argument before calling .disabled().

A checkbox control’s .value() is a JavaScript boolean when read directly — except when several checkboxes share one Encompass field ID as a mutual-exclusion group with 3 or more Choice values (or 2 values that are not literally “Y”/“N”). In that case .value() returns the field’s raw current Choice string (e.g. “ConstructionOnly”), the same string no matter which member of the group you query. This script never compares such a read to true/false; it always goes through the sharedFieldEquals(anyMemberId, expectedValue) helper instead, which reads the raw string and compares it to one specific Choice value being tested for.

3. Shared Helper Functions

Ten small helpers, defined once at the top of the file, are reused by every rule below rather than each rule re-deriving the same control-access pattern:

Function

Signature

Purpose

ctrl

ctrl(id)

Fetches the live control object for a control ID via elli.script.getObject(id).

getVal

getVal(id)

Reads a control’s current value (async .value()).

setVal

setVal(id, value)

Writes a control’s value.

setVisible

setVisible(id, visible)

Shows/hides a control (calls .visible(bool)).

setEnabled

setEnabled(id, enabled)

Enables/disables a control. Internally inverted: calls .disabled(!enabled), since the underlying API exposes “disabled”, not “enabled”.

setVisibleAll

setVisibleAll(ids, visible)

setVisible applied to a list of IDs in one call.

setEnabledAll

setEnabledAll(ids, enabled)

setEnabled applied to a list of IDs in one call.

toNumber

toNumber(v)

parseFloat with a safe 0 fallback for blank/non-numeric input, used before every calculation.

sharedFieldEquals

sharedFieldEquals(anyMemberId, expectedValue)

Reads a shared-field checkbox group’s raw current Choice string and compares it to one expected value. Required because such a group’s .value() returns the field’s raw string, not a per-checkbox boolean.

uncheckOthers

uncheckOthers(clickedId, allIdsInGroup)

Unchecks every other checkbox in a list on script-driven mutual-exclusion groups (checkboxes on separate field IDs, not a native shared field).

4. formLoad() — Re-Synchronizing State on Open

Encompass Web only fires an individual control’s Click/Change event when a user actually interacts with it in the current session — it does not replay those events for values a loan file already had saved before the form was opened. formLoad() is wired to the form’s own load event and exists purely to bring every conditional field back into the correct visible/enabled/calculated state for whatever the loan file already contains, by explicitly calling each section’s own “refresh” function once, up front:

       refreshConstructionState() — gates the Construction Loans / Lot-Land Status panels and Construction Method Type

       refreshManufacturedHousingState() — gates Manufactured Home Width Type

       refreshAduState() — gates the ADU fields and recalculates ADU Net Income

       refreshOtherLoansState() + recalcAdditionalLoansTotals() — gates the 4b grid and its two rollups

       refreshRentalIncomeState() — gates 4c’s fields and recalculates the Net Rental Income

       refreshGiftsState() + recalcGiftsTotal() — gates the 4d grid rows and its total

       refreshDeclCAmountB()/C(), refreshBankruptcyChaptersB()/C(), refreshDeclASubFieldsB()/C(), refreshDeclA1SubFieldsB()/C() — gates every conditional “If YES…” sub-field in Section 5

Every one of these same functions is also individually wired to the Click/Change event of the specific control that drives it, so the same logic runs both on initial load and on every subsequent live edit — there is deliberately no separate “load-only” code path to keep in sync with the interactive one.

5. Business Rules by Section

The remainder of the file is organized into ten numbered blocks (kept as numbered comments in the source itself for easy cross-reference), each covering one section or control group of the form.

1. Construction Loans / Lot-Land Status (Section 4a)

refreshConstructionState() reads Loan Purpose (field 19, a 6-way shared-field checkbox group) via sharedFieldEquals and treats the Construction Loans panel, the Lot/Land Status panel, and the Construction Method Type dropdown as a single unit: enabled only when Purpose is ConstructionOnly or ConstructionToPermanent. Confirmed against a live SmartClient screenshot, these panels stay visible at all times and are only grayed out when inapplicable — they are never hidden. Wired to the Change event of every one of the 6 Loan Purpose checkboxes.

Open item: setEnabled() is called on the GroupBox container itself for these two panels, on the assumption that disabling a container cascades to gray out every control inside it. This cascading behavior has not been independently confirmed live — if it does not cascade, each child control inside the two panels would need to be disabled individually instead.

2. Manufactured Housing → Manufactured Home Width Type (Section 4a)

refreshManufacturedHousingState() enables Manufactured Home Width Type only while the Manufactured Housing checkbox is checked, and clears its value when unchecked. Wired to the Manufactured Housing checkbox’s Click event.

3. Accessory Dwelling Unit (Section 4a)

refreshAduState() enables ADU Count / Gross Income / Expenses / Vacancy Factor only while ADU Present is checked (clearing all four otherwise), then calls recalcAduNetIncome(). That function computes ADU Net Income as Gross Income minus Expenses and writes it to the locked ADU Net Income field. Wired to ADU Present’s Click event and to Change on the Gross Income/Expenses fields.

Open item: this is a best-effort formula. Vacancy Factor is not currently used in the calculation at all — no confirmed formula combining all three inputs was available at build time. Flagged in the test plan’s Open Questions tab for confirmation against Encompass’s own calculated-field definition.

4. Other New Mortgage Loans (Section 4b)

refreshOtherLoansState() enables/disables all 5 loan rows together based on the Does Not Apply checkbox, then calls recalcAdditionalLoansTotals(), which sums each row’s Loan Amount/HELOC Credit Limit into Total Additional Loans Amount and each row’s Applied to Down Payment into Total Applied to Down Payment (both locked, calculated fields). The 5 rows are addressed programmatically via the AL_ROWS (“01”–“05”) and AL_ROW_SUFFIXES arrays rather than 30 individually-named field references.

5. Rental Income (Section 4c)

refreshRentalIncomeState() enables/disables Expected Monthly Rental Income and Occupancy Rate together based on the Does Not Apply checkbox, then calls recalcExpectedNetRentalIncome(), which computes Expected Net Monthly Rental Income as Monthly Rental Income × (Occupancy Rate ÷ 100) × 0.75 — the standard Fannie Mae/Freddie Mac 75% qualifying-rental-income factor.

Open item: this 75% factor is a best-effort industry-standard assumption, not a value read from Encompass’s own calculated-field definition for this specific field — flagged for confirmation before go-live.

6. Gifts or Grants (Section 4d)

refreshGiftsState() evaluates each of the 2 gift/grant rows independently: a row is disabled only when its own Bor/Cob/Both selector matches a side whose Does Not Apply checkbox is checked (a “Both” row requires both sides checked). recalcGiftsTotal() sums Cash or Market Value across both rows into the locked Total of Gifts and Grants field. This mirrors the equivalent Other Assets gating pattern already used on the Part 3 ticket’s rules script.

7. Declarations (Section 5)

Four independent conditional groups, each following the same shape — read a Yes/No dropdown, enable or clear the field(s) it gates:

       Row A → A1: occupying the property as a primary residence gates the “ownership interest in another property” follow-up question.

       Row A1 → A(1)/A(2): having had that ownership interest gates the Property Type and Title Held dropdowns.

       Row C → amount: borrowing undisclosed money gates the “If YES, what is the amount” text field.

       Row M → chapters: having declared bankruptcy gates all 4 Chapter checkboxes on that side — confirmed live to stay visible-but-grayed when the answer is No, not hidden.

Each pair of functions exists once per side (Borrower/Co-Borrower, suffixed B/C) and each is wired to the Change event of its own driving dropdown, in addition to being called once from formLoad().

8. Acknowledgments and Agreements (Section 6) — no script

The Acknowledgments and Agreements button is wired entirely on the schema side as a native controlAction (“urlaack”), confirmed by diffing a hand-corrected re-export of the form against this generator’s own output. An earlier draft of this script called elli.script.getObject(‘application’).openModal(…) to open the screen manually; that function has been removed now that the native action is confirmed, and this script intentionally defines no Click handler for this button.

9. “View All Additional Loans” / “Show all Gifts or Grants” buttons — no script

Both buttons are likewise native controlAction buttons (“voal”/VOAL and “vogg”/VOGG respectively, matching the same VOx-style convention already confirmed on the Part 3 ticket), wired entirely in the schema. No Click handler exists or is needed for either.

10. Demographic Information (Section 8)

The largest single block in the file, duplicated once per side (Bor/CoBor) via a shared set of helper functions parameterized by a prefix string rather than 2 independent copies of the logic:

       Ethnicity: ethnicityMutex() enforces that exactly one of Hispanic or Latino / Not Hispanic or Latino / “I do not wish…” / Information Not Provided / Not Applicable is ever checked (a script-driven mutex across 5 separate field IDs, using uncheckOthers()); refreshHispanicSubFields() then enables Mexican/Puerto Rican/Cuban/Other Hispanic only while Hispanic or Latino is checked, and the free-text origin field only while Other Hispanic is also checked.

       Race: raceMutex() treats the 5 race categories (American Indian, Asian, Black, Native Hawaiian/Pacific Islander, White) as NOT mutually exclusive with each other (an applicant may select more than one), but mutually exclusive as a group against the 3 “special” options (No Wish / Info Not Provided / Not Applicable) — selecting any special option clears every race checkbox, and selecting any race checkbox clears all 3 special options. refreshAsianSubFields(), refreshNativeHawaiianPacificSubFields(), and refreshTribeNameField() each gate their own sub-checkboxes/free-text fields the same way the Ethnicity group does.

       Sex: sexMutex() is a plain 5-way mutual exclusion (Female / Male / No Wish / Info Not Provided / Not Applicable) with no sub-fields to gate.

All demographic mutex logic operates on checkboxes with independent field IDs (not a native Encompass shared field), so it relies entirely on uncheckOthers() plus plain boolean .value() reads — sharedFieldEquals() is not needed anywhere in this block.

 

You may also like...

Popular Posts

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.