A reference catalogue of every element in the wonder-slim Ajax framework, grouped by role. Each entry carries two independent badges.
Ajax/docs/ASSESSMENT.md.The canonical pattern for new work: dependency-free custom elements that survive DOM morphing with zero re-init.
A drop-in WOPopUpButton subclass that renders a searchable, morph-native single-select (the wonder-select custom element) instead of a bare <select>; reach for it when a long option list needs type-to-filter.
Usage. Same bindings as WOPopUpButton (list/item/selection/displayString/noSelectionString). It merges marker class "ajax-popup-button" onto the rendered <select> and injects wonder-select.js/.css. Sketch: <wo:AjaxPopUpButton list="$items" item="$item" selection="$sel" displayString="$item.name"/> — or equivalently a plain WOPopUpButton with class="ajax-popup-button".
Client deps. Vanilla/custom element only — ships wonder-select.js + wonder-select.css. NO Prototype, NO Scriptaculous. Auto-enhances via MutationObserver and is morph-safe by design.
The multi-select companion to AjaxPopUpButton: a WOBrowser subclass that renders the same searchable wonder-select widget with removable tags instead of a bare multi-select.
Usage. Same bindings as WOBrowser (list/item/selections/multiple). It merges marker class "ajax-popup-button" and maps noSelectionString to a data-placeholder attribute (since a multi-select has no no-selection option) for the widget's placeholder. Sketch: <wo:AjaxBrowser list="$items" item="$item" selections="$selected" displayString="$item.name" noSelectionString="Pick some"/>.
Client deps. Vanilla/custom element only — shares wonder-select.js + wonder-select.css with AjaxPopUpButton. NO Prototype, NO Scriptaculous. Morph-safe.
The load-bearing spine — partial page updates and Ajax form submission. The capabilities here are fundamental; most are slated for a fetch()+morph client rewrite (morph is already the default).
Why rewrite. The server contract (named region carrying data-updateUrl + data-morph, re-rendered via component action) is exactly what should be preserved, and idiomorph is already wired in for the content-reconciliation step. But the client driver is still Prototype's Ajax.Updater plus AUC.* helpers in wonder.js, periodic mode uses Prototype's PeriodicalExecuter, and insertion shortcuts map to Scriptaculous Effect.PAIRS. Keep the element and its contract; move the client off Prototype/Scriptaculous onto fetch()+idiomorph (morph already half-done).
Renders a named DOM region (a div by default) that can be re-rendered in place via an Ajax round-trip, optionally on a timer or driven by an observed field; the foundational element every other Ajax partial-update component targets.
Usage. Bindings: id, action, elementName, frequency/decay/stopped (periodic), observeFieldID/fullSubmit, insertion + *Duration (Scriptaculous effects), onRefreshComplete, optional, and morph ($true/$false). Sketch: <wo:AjaxUpdateContainer id="detail" action="$refresh"> ...content... </wo:AjaxUpdateContainer>, then refresh from elsewhere with updateContainerID="detail" or server-side AjaxUpdateContainer.updateContainerWithID("detail", context).
Client deps. Ships/requires prototype.js, effects.js (Scriptaculous), idiomorph.js, wonder.js. Client side is Prototype's Ajax.Updater plus the AUC.* helpers in wonder.js; periodic mode uses Prototype's PeriodicalExecuter; insertion shortcuts map to Scriptaculous Effect.PAIRS.
Why rewrite. Keep the element and its server action contract, but the emitted onclick is Prototype: AUL.update(...) fast path, or raw new Ajax.Request / new Ajax.Updater, with Scriptaculous new Effect.Xxx for effects/insertion. The client must move to fetch()+idiomorph; the effect bindings should be dropped or re-expressed in CSS during the rewrite.
Renders an anchor (or button/JS function) whose click fires an Ajax action and refreshes a target AjaxUpdateContainer (or replaceID region), i.e. the standard 'click to update part of the page' link.
Usage. Bindings: action/directActionName, updateContainerID, replaceID, onClick/onClickBefore/onClickServer, function/functionName, button, elementName, asynchronous, accesskey, plus effect/beforeEffect/afterEffect (+IDs/durations) and insertion (all Scriptaculous). Sketch: <wo:AjaxUpdateLink action="$edit" updateContainerID="detail" string="Edit"/>.
Client deps. Requires prototype.js, effects.js (Scriptaculous), wonder.js. Emits inline onclick of either AUL.update(...) (fast path) or raw new Ajax.Updater/new Ajax.Request; effects emit new Effect.Xxx(...) Scriptaculous calls.
Why rewrite. The server-side capability (emit a directive that re-fetches a list of containers by reading each target's data-updateUrl) is worth keeping and is already morph-aware via the overridden Ajax.Updater. But the emitted script still calls new Ajax.Updater(...) and the $wi() helper from wonder.js, so it depends on Prototype. Rewrite the emitted client to drive the same data-updateUrl re-fetch via fetch()+idiomorph.
Server-side element with no UI of its own that, when rendered into an Ajax response, forces one or more named update containers elsewhere on the page to refresh themselves — used to update sibling regions from a central controller (e.g. exit edit mode in all rows but one).
Usage. Bindings: updateContainerID (single), updateContainerIDs (array), resetAfterUpdate, evalScripts. Sketch: place <wo:AjaxUpdateTrigger updateContainerIDs="$idsToRefresh"/> inside a container that is itself being Ajax-updated; on render it emits script to refresh each listed container.
Client deps. No addRequiredWebResources of its own, but the script it emits calls new Ajax.Updater(...) and the $wi() helper from wonder.js, so it transitively depends on prototype.js + wonder.js (and whatever the target containers loaded). Reads each target's data-updateUrl attribute and lets the (morph-aware) Ajax.Updater override drive morphing.
Why rewrite. Keep the capability and its submit-name/partial-submit server contract, but the client emits ASB.observeField / ASB.observeDescendentFields in wonder.js, which wrap Prototype's Form.Element.Observer and reuse the ASB submit machinery and Form.serialize. Move to native input/change event listeners + fetch()+idiomorph (the platform's change event plus FormData replaces the Prototype observer).
Watches a form field (or all descendant fields) for value changes and fires an Ajax partial submit + optional container update, i.e. live/auto-submit-on-change without a visible button.
Usage. Bindings: observeFieldID (or omit to observe all descendants and render a wrapper div), updateContainerID, action, fullSubmit, observeFieldFrequency, observeDelay, onBeforeSubmit, onCreate. Sketch: <wo:WOTextField id="q"/> <wo:AjaxObserveField observeFieldID="q" updateContainerID="results" action="$search"/>.
Client deps. Requires prototype.js + wonder.js. Emits ASB.observeField / ASB.observeDescendentFields (wonder.js), which wrap Prototype's Form.Element.Observer / event observation and reuse the AjaxSubmitButton (ASB) submit machinery and Form.serialize.
Why rewrite. Keep the element and its ERXAjaxApplication coordination (AJAX_SUBMIT_BUTTON_NAME, partial-sender key, replaceID/updateContainerID contract). But the client is Prototype: ASB.update/ASB.request in wonder.js built on Ajax.Request and Form.serializeWithoutSubmits, with Scriptaculous Effect.* for effects. Rewrite onto FormData + fetch()+idiomorph; drop the effect bindings.
A WOSubmitButton replacement that submits its form in the background via Ajax (serializing the form, optionally partial-submit) and updates a container/replace region with the result; the workhorse for Ajax form submission.
Usage. Bindings: action, name/value, updateContainerID, replaceID, button (link vs button), useButtonTag, functionName, formName, formSerializer, onClick/onClickBefore/onClickServer/onComplete/onSuccess/onFailure, disabled, plus the full effect/insertion Scriptaculous set. Sketch: <wo:AjaxSubmitButton action="$save" updateContainerID="detail" value="Save"/>.
Client deps. Requires prototype.js, effects.js (Scriptaculous), wonder.js. Emits ASB.update(...) / ASB.request(...) (wonder.js) which build on Prototype Ajax.Request and Form.serializeWithoutSubmits; effects emit Scriptaculous Effect.* calls. Coordinates with ERXAjaxApplication via the AJAX_SUBMIT_BUTTON_NAME form key.
Why rewrite. Keep the default-button capability, but it inherits the full Prototype ASB stack (ASB.update/ASB.request, effects.js) and additionally emits a legacy IE<9 keypress workaround using Prototype's Event.observe, $$(), and the non-standard fireEvent(). Rewrite onto fetch()+idiomorph alongside AjaxSubmitButton, and delete the IE<9 workaround block outright as part of that rewrite.
An invisible (off-screen) Ajax submit button placed first in a form so that pressing Enter triggers a specific Ajax action — the 'default button' for Ajax forms.
Usage. Subclass of AjaxSubmitButton; same submit bindings (action, updateContainerID, formName, on*, effects). Sketch: put <wo:AjaxDefaultSubmitButton action="$search" updateContainerID="results"/> as the first element inside the form; it renders a hidden input positioned at left:-10000px and submits on Enter.
Client deps. Inherits prototype.js + effects.js + wonder.js from AjaxSubmitButton; emits ASB.update/ASB.request (Prototype). Additionally emits a legacy IE<9 keypress workaround using Prototype's Event.observe, $$(), and the non-standard fireEvent().
Why rewrite. Client emits `new Ajax.Request(...)` and force-loads prototype.js + effects.js in addRequiredWebResources; the server action contract is worth keeping but the onClick generation must move from Prototype's Ajax.Request to fetch()+idiomorph.
An anchor (or arbitrary element) that fires a background Ajax.Request to a server action on click and runs JS callbacks (onSuccess/onFailure/onComplete) with the response, optionally rendering itself as a named JS function instead of a link.
Usage. Bindings: action, onSuccess/onFailure/onComplete/onLoading (JS), onClickBefore (for confirm() gating), onClick, onClickServer (script returned from server), evalScripts, functionName, plus title/string/id/class/style/disabled/elementName. Minimal: <wo:AjaxHyperlink action="$doThing" string="Do it" onSuccess="alert('ok')"/>. With functionName set it emits a global JS function instead of an <a>.
Client deps. Prototype.js (emits `new Ajax.Request(...)`) plus Scriptaculous effects.js — both force-added in addRequiredWebResources(). No own .js/.css shipped.
A button that does a pure client-side reset of a form's fields — either back to original values or cleared to blank — without a server round-trip.
Usage. Stateless WOComponent (not a dynamic element). Bindings: formId (required), clear (true = blank, false = reset to original), value (label), id/class/style. Sketch: <wo:AjaxResetButton formId="editForm" clear="$true" value="Clear"/>. Renders a WOInput whose onClick is Form.reset(...)/Form.clear(...).
Client deps. Loads prototype.js, effects.js, wonder.js, but the only real dependency is Prototype's Form.reset / Form.clear. effects.js is loaded but unused — pure dead weight.
Server-action links and function-call buttons.
Why rewrite. It emits only a plain onclick string calling <id>Edit/Save/etc. globals; it has no Prototype of its own, but those globals are generated by the Prototype-based container. Keep the element and its contract, but the named functions it targets must be regenerated when the container is rewritten onto fetch()+morph.
A thin <a> wrapper that wires an onclick to call the JS function an enclosing AjaxUpdateContainer/AjaxInPlace publishes (Edit/Cancel/Save/Update), so links inside an in-place-edit block can switch modes without naming the container.
Usage. Bindings: action ("edit"/"cancel"/"save"/"update"), updateContainerID (optional inside a container), onclick/onClick (mutually exclusive with action), disabled. Minimal: <wo:AjaxFunctionLink action="edit">Edit</wo:AjaxFunctionLink> inside an AjaxInPlace. Emits <a href="javascript:void(0)" onclick="<containerID>Edit()">.
Client deps. No direct Prototype/Scriptaculous of its own — it just emits an onclick string. But the functions it calls (<id>Edit/Save/etc.) are generated by AjaxUpdateContainer/AjaxInPlace, which are Prototype-based. No own .js/.css.
Why rewrite. Shares AjaxFunctionLink._appendAttributesToResponse and emits only an onclick targeting the container's generated globals; no Prototype of its own, but the target functions move to fetch()+morph when the container is rewritten. Same verdict as its sibling.
Identical convenience to AjaxFunctionLink but renders an <input type="button"> instead of an anchor, for triggering an enclosing container's Edit/Cancel/Save/Update action.
Usage. Bindings: action, updateContainerID, onclick, disabled, value (button text). Minimal: <wo:AjaxFunctionButton action="save" value="Save"/> inside an AjaxUpdateContainer. Reuses AjaxFunctionLink._appendAttributesToResponse to emit the onclick; renders `disabled` attribute when disabled.
Client deps. Same as AjaxFunctionLink — no Prototype/Scriptaculous of its own, but the onclick targets globals generated by the Prototype-based AjaxUpdateContainer/AjaxInPlace. No own .js/.css.
An <a> whose onclick calls Scriptaculous Effect.toggle to show/hide a target element with a visual effect (default "blind"), i.e. a one-line expand/collapse trigger.
Usage. Bindings: toggleID (required, element to toggle), effect (default "blind"), duration, disabled; binding onclick is rejected. Minimal: <wo:AjaxToggleLink toggleID="details">More</wo:AjaxToggleLink>. Emits onclick="Effect.toggle($wi('details'), 'blind', {duration:...})".
Client deps. Prototype.js ($wi element lookup) AND Scriptaculous effects.js (Effect.toggle / Effect.Blind) — both confirmed shipped in webserver-resources. Hard dependency on the 2007-era script.aculo.us effects library.
A no-render helper element that just declares a script dependency (e.g. prototype.js, effects.js) into the page head, so custom hand-written Ajax JS can reuse the exact library versions shipped in Ajax.framework.
Usage. Bindings: name (required JS file name), framework (defaults to "Ajax"). Minimal: <wo:AjaxIncludeScript name="prototype.js"/>. handleRequest returns null; addRequiredWebResources adds the script to <head>.
Client deps. No library of its own; it is a generic script-injector. In practice its reason to exist is to pull in Ajax.framework's Prototype/Scriptaculous bundle for custom code.
Enhanced inputs. The wonder-select pair is the modern path; the rest are legacy reimplementations of native inputs.
Why rewrite. Client is Scriptaculous Ajax.Autocompleter / Autocompleter.Local on the full Prototype + effects + controls + wonder.js stack, and emits raw new Ajax.Request strings. The capability and its server handleRequest contract are worth keeping; the client must move to fetch()+idiomorph.
A Google-suggest-style autocompleting combo box: a text field that fetches (or filters locally) a list of suggestions as the user types and offers a dropdown of matches.
Usage. Bindings: list/value/item/displayString plus a large pass-through set (frequency, minChars, tokens, fullSearch, isLocal, afterUpdateElement, etc.). Generates new Ajax.Autocompleter or Autocompleter.Local. Sketch: <wo:AjaxAutoComplete value="$q" list="$matches" item="$item" displayString="$item.name"/>.
Client deps. Scriptaculous controls.js (Ajax.Autocompleter / Autocompleter.Local) on top of Prototype.js + effects.js + wonder.js — the ~2008 Prototype/Scriptaculous stack. Server-roundtrip variant emits raw new Ajax.Request strings.
Why rewrite. Hard Prototype dependency — ships prototype.js plus its own AjaxSelectionList.js (uses Prototype $/$wi helpers) and CSS. The rich-renderer list capability and its index-based form contract are worth keeping; rewrite the client off Prototype onto vanilla JS + morph.
A form-field-like single-select list (ul/ol/table) that uses component content as the per-row renderer and adds keyboard navigation plus change/select(enter,dblclick)/delete events; reach for it when WOPopUpButton's plain displayString isn't rich enough.
Usage. Bindings: list/item/selection, mandatory, onchange/onselect/ondelete, focus, elementName. Renders a hidden field holding the selected index and a JS new AjaxSelectionList(containerId) wiring the callbacks. Sketch: <wo:AjaxSelectionList list="$rows" item="$row" selection="$sel" onselect="doEdit()">...row template...</wo:AjaxSelectionList>.
Client deps. Prototype.js + its own AjaxSelectionList.js + AjaxSelectionList.css. Uses Prototype's $wi/$ helpers in the template script. NO Scriptaculous, but a hard Prototype dependency.
A wrapper element that turns an input's `default` binding into ghosted placeholder text, and re-registers forms/inputs after an Ajax refresh so the hints persist inside AjaxUpdateContainers.
Usage. Bindings: form (id of the form to hint). Emits AjaxHintedText.register/registerForm calls, guarded by Event.observe(window,'load',...) on full loads. Sketch: wrap a form/input and add <wo:AjaxTextHinter form="myform"/>, with default="Login name" on the fields.
Client deps. Prototype.js + wonder.js (uses Prototype's Event.observe and the AjaxHintedText helper in wonder.js). Hard Prototype dependency.
A draggable horizontal/vertical slider control that binds a numeric value, with optional snap-to-integer values and server-side onChange/onSlide callbacks.
Usage. Bindings: minimum/maximum, value, orientation, snap, increment/step, onChange/onSlide (+ ...Server variants for Ajax callbacks). Renders a tracker/handle div (marked data-morph-ignore) and a new Control.Slider(...) init. Sketch: <wo:AjaxSlider minimum="0" maximum="100" value="$pct" snap="true"/>.
Client deps. Scriptaculous Control.Slider from slider.js, on top of Prototype.js + effects.js + controls.js — full Prototype/Scriptaculous stack. Uses Prototype's $R() range. Handle position is client-mutated inline style, requiring a data-morph-ignore guard.
A text input with a pop-up calendar (ported from Rails Date Kit) for choosing a date, with localized day/month names, configurable format/formatter, and server-side validation of the typed value.
Usage. Bindings: value (required), format/formatter, startDay, dayNames/monthNames, locale, onDateSelect, manualInput, showYearControls, calendarCSS. Input wires onFocus/onClick to calendar_open(...). Sketch: <wo:AjaxDatePicker value="$date" format="%m %d %Y"/>.
Client deps. Prototype.js + wonder.js + calendar.js + date.js + calendar.css. The calendar (calendar.js/date.js) is Prototype-based; doc explicitly warns of a Prototype init conflict with AjaxModalDialogOpener. Hard Prototype dependency.
A server-side helper (plain Java class, not a UI element) that serializes Java/Foundation objects into JavaScript-literal strings with type hinting via AjaxOption.Type, including JS string escaping.
Usage. No bindings — used in code by the other Ajax components when building option dictionaries. Sketch: new AjaxValue(AjaxOption.ARRAY, anNSArray).javascriptValue(); or AjaxValue.javaScriptEscaped(obj) for a quoted, escaped JS string.
Client deps. None — pure server-side Java, emits no client resources and depends on no client library.
Modals, tabs, accordions, expansion, in-place editing.
A heavier modal dialog (based on the ModalBox library) that, unlike AjaxModalContainer, can host forms, submit via Ajax, refresh its own contents, and fetch content from an action/pageName/inline template.
Usage. Place outside any form; open via the generated openAMD_<id>() JS, an onclick, or AjaxModalDialogOpener. Server helpers: AjaxModalDialog.close(context), AjaxModalDialog.update(context, title). Key bindings: action/pageName/inline content, title, width/height, locked, overlayClose, onOpen/onClose (server), beforeLoad/afterLoad/afterHide (client), closeUpdateContainerID. Minimal: <wo:AjaxModalDialog id="edit" title="Edit" action="$editForm"/>.
Client deps. Prototype.js + Scriptaculous (effects.js for transitions, dragdrop.js for movable) + the third-party ModalBox library (modalbox.js, ~2007 wildbit.com) + wonder.js. Uses Ajax.Request, AUL, Modalbox.show throughout.
Renders a standalone clickable element (link/button) that opens a separately-declared AjaxModalDialog, used to decouple the trigger from the dialog (e.g. opener inside a repetition or inside another form).
Usage. <wo:AjaxModalDialogOpener dialogId="edit" label="Edit" action="$prepare"/> paired with a <wo:AjaxModalDialog id="edit" showOpener="false"/>. Key bindings: dialogId (required), elementName, label/linkTitle, action (synchronous prep), enabled, onFailure. Click fires a synchronous Ajax.Request, then onSuccess calls openAMD_<dialogId>().
Client deps. No resources of its own (addRequiredWebResources is empty) but emits Prototype Ajax.Request inline and depends on AjaxModalDialog's openAMD_<id>() global, so it is transitively bound to the same Prototype/ModalBox stack.
Renders a link that opens wrapped inline content (or a fetched URL/direct-action/iframe) in a lightbox-style modal overlay via the bundled iBox library.
Usage. Inline content mode: <wo:AjaxModalContainer label="Details" ajax="true" id="detailsBox">...content...</wo:AjaxModalContainer>. Key bindings: label, id (required when ajax=true), href/directActionName (iframe fetch), action (div fetch), open, locked, skin (lightbox|darkbox), height/width/closeLabel. Emits an <a rel="ibox&..."> and calls iBox.init(); inline content is moved to <body> by iBox at open time.
Client deps. Prototype.js (hard dependency: $wi, Event.observe, .bind, iBox.handleTag) plus the ~2008 iBox 2.2 library (ibox/ibox.js) and ibox.css/skins. No jQuery despite the stale link comment pointing at jQuery ThickBox.
Why rewrite. Valuable capability with a real server contract (on-demand pane fetch) worth keeping, but the client is hard-bound to Prototype ($, $A, .each, addClassName/removeClassName, .down) via custom switchtabs.js. There is no fully native tab element, so keep the element and rewrite its tab-switch + lazy-load wiring onto fetch()+idiomorph.
Renders a UL of tabs whose panes load on demand via Ajax, so only the selected tab's content is rendered initially; the dev reaches for it for lazy-loaded tabbed sections.
Usage. Wrap AjaxTabbedPanelTab children. Key bindings: id (required), busyDiv, onLoad, onSelect. Minimal: <wo:AjaxTabbedPanel id="tabs"><wo:AjaxTabbedPanelTab name="One" isSelected="$first">...</wo:AjaxTabbedPanelTab>...</wo:AjaxTabbedPanel>. Tabs emit onclick handlers calling AjaxTabbedPanel.loadPanel/selectPanel/selectTab from switchtabs.js.
Client deps. Prototype.js (hard: $, $A, .each, removeClassName/addClassName, .down throughout switchtabs.js) plus wonder.js and the custom switchtabs.js. No Scriptaculous. switchtabs.js is custom-but-Prototype-bound.
Why rewrite. Ships no client resources itself but its rendered onclick wiring and pane-swap depend entirely on the parent's Prototype + switchtabs.js, and its handleRequest serves the lazy pane content. Keep the server-side pane-fetch contract and rewrite the client alongside AjaxTabbedPanel onto fetch()+morph; sibling consistency with the panel.
Declares a single tab/pane within an AjaxTabbedPanel — its title, selected state, visibility, and the (lazily server-rendered) pane content.
Usage. Child of AjaxTabbedPanel only. Key bindings: name (required, tab label), isSelected (settable), refreshOnSelect, isVisible, onLoad, accesskey, id. Renders an <li data-updateUrl=...> pane; content is appended only when selected, and re-fetched on click via the parent's switchtabs.js.
Client deps. Ships no resources itself (empty addRequiredWebResources); its rendered onclick wiring and pane-swap behavior depend entirely on the parent's Prototype + switchtabs.js.
Renders an accordion container (a stack of collapsible AjaxAccordionTab sections where opening one collapses the others), driven by the Rico library's Rico.Accordion.
Usage. Wrap AjaxAccordionTab children. Key bindings are pure styling/animation options: expandedBg, hoverBg, collapsedBg, expandedTextColor, panelHeight, onShowTab/onHideTab/onLoadShowTab. Minimal: <wo:AjaxAccordion id="acc"><wo:AjaxAccordionTab title="A">...</wo:AjaxAccordionTab>...</wo:AjaxAccordion>. The template emits new Rico.Accordion($wi(id), options).
Client deps. Prototype.js + Rico (rico.js, ~90KB, itself a Prototype-based 2005-era effects/widget library with 167 prototype/Effect references). The whole behavior is Rico.Accordion. Also needs data-morph-ignore because Rico rewrites the DOM.
Declares one collapsible section (title bar + content box) inside an AjaxAccordion; a plain WOComponent that just supplies stable header/content/tab DOM ids for Rico to wire up.
Usage. Child of AjaxAccordion only. Key bindings: title (the header text), id (optional). Renders nested divs (accordionTab > accordionTabTitleBar + accordionTabContentBox) that Rico.Accordion attaches collapse behavior to.
Client deps. No client resources of its own; it is inert markup whose behavior comes entirely from the parent AjaxAccordion's Prototype + Rico. (Note: it is the one element here not extending an Ajax base class — plain WOComponent.)
Why rewrite. Although a pure client-side disclosure is now native <details>/<summary>, this element's real value is the server action fired on toggle plus the partial content update; it is composed of AjaxUpdateLink/AjaxUpdateContainer and carries Prototype + Scriptaculous (effects.js for the blind animation) + wonder.js. Keep the action+partial-update contract and rewrite the client onto fetch()+idiomorph (animation via CSS).
A single disclosure/expander: a toggle link that Ajax-updates an inline content area open/closed and adds an 'expanded' CSS class to the link, with optional animation that affects only the contents (not the link).
Usage. Key bindings: id, string (or openedLabel/closedLabel), action (fires on toggle), expanded/initiallyExpanded, insertion/insertionDuration (effect), linkClass, accesskey, onExpansionComplete. Minimal: <wo:AjaxExpansion id="contact" string="Contact">...content...</wo:AjaxExpansion>. Built from an AjaxUpdateLink toggling an AjaxUpdateContainer.
Client deps. Prototype.js + Scriptaculous (effects.js, for the Effect.blind-style insertion animation) + wonder.js. Composed of AjaxUpdateLink/AjaxUpdateContainer, so it transitively carries the whole Ajax/Prototype update stack.
Why rewrite. Pure server-side composite that delegates to AjaxUpdateContainer + AjaxUpdateLink + AjaxSubmitButton, all of which transitively load prototype.js + wonder.js; its *Insertion / *InsertionDuration bindings are explicitly Scriptaculous Effect animations. The capability and its server contract are worth keeping, but the underlying client (and the Effect-based insertion bindings) must move off Prototype/Scriptaculous onto fetch()+idiomorph. Already morph-aware (hardcodes morph=false to protect unsaved edit input), so it is well-positioned for the rewrite.
A server-side component that renders a region twice — a "view" template and an "edit" template — and swaps between them in an AjaxUpdateContainer, giving click-to-edit / save / cancel behavior driven entirely by WO Ajax round-trips rather than client widgets.
Usage. Wrap an AjaxInPlaceViewTemplate (named "view") and AjaxInPlaceEditTemplate (named "edit") inside it; bindings: id, class, saveAction, cancelAction, editAction, canEdit, canSave, editOnly, button, submitOnSave, plus per-mode JS hooks (onSaveSuccess, onEditClick, etc.). Sketch (wod): `IP : AjaxInPlace { id="x"; saveAction=save; }` with `View : AjaxInPlaceViewTemplate {}` and `Edit : AjaxInPlaceEditTemplate {}` in the html, each containing the read-only WOString and the WOTextField respectively.
Client deps. No direct Prototype/Scriptaculous load in this class; it composes AjaxUpdateContainer + AjaxUpdateLink + AjaxSubmitButton (which transitively pull in prototype.js + wonder.js). However it exposes a large family of *Insertion / *InsertionDuration bindings explicitly documented as "PROTOTYPE FUNCTIONS" — i.e. Scriptaculous Effect insertion animations. Already morph-aware: its .wod hardcodes morph=false on its own container with a comment that morphing would reconcile away unsaved edit input.
Why rewrite. Hard dependency on Scriptaculous controls.js: instantiates new Ajax.InPlaceEditorWithEmptyText (a wonder_inplace.js subclass of Ajax.InPlaceEditor) and addRequiredWebResources loads prototype.js, builder.js, effects.js, controls.js, wonder.js, wonder_inplace.js. The inline-edit capability plus the server-side formatter/parse round-trip is worth keeping, but the entire client must be reimplemented on fetch()+idiomorph (or a morph-native custom element) to retire Prototype/Scriptaculous. The browser has no native click-to-edit-with-server-formatter equivalent, so this is a rewrite rather than REPLACE_WITH_PLATFORM.
A dynamic element that renders a value inside a div/span and attaches script.aculo.us's `Ajax.InPlaceEditor` so the user can click the text, edit it inline in a generated form field, and POST the new value back via an Ajax component action with server-side formatter/parse support.
Usage. Bindings: value (required, the keypath edited), id, elementName, class, formatter/dateformat/numberformat, useDecimalNumber, escapeHTML, action, plus Scriptaculous passthrough options (okButton, okText, cancelLink, savingText, clickToEditText, highlightcolor, submitOnBlur, rows/cols, valueWhenEmpty, onComplete, onFailure). Sketch (wod): `Name : AjaxInPlaceEditor { value = person.name; clickToEditText = "click to edit"; }`.
Client deps. Hard Prototype + Scriptaculous dependency. addRequiredWebResources explicitly loads prototype.js, builder.js, effects.js, controls.js, wonder.js, wonder_inplace.js. It instantiates `new Ajax.InPlaceEditorWithEmptyText`, a wonder_inplace.js subclass of script.aculo.us controls.js `Ajax.InPlaceEditor` (controls.js v1.9.0, 2010).
A one-line convenience subclass of ERXWOTemplate that hardcodes templateName="edit", used to mark the edit-mode content inside an AjaxInPlace.
Usage. No bindings of its own; just wrap the edit-mode markup. Sketch (html): `<wo:AjaxInPlaceEditTemplate> <wo:WOTextField value="$value"/> </wo:AjaxInPlaceEditTemplate>`. Equivalent to `ERXWOTemplate { templateName = "edit"; }`.
Client deps. None — pure server-side; subclasses ERXWOTemplate and ships no client JS/CSS.
A one-line convenience subclass of ERXWOTemplate that hardcodes templateName="view", used to mark the read-only view-mode content inside an AjaxInPlace.
Usage. No bindings of its own; wrap the view-mode markup. Sketch (html): `<wo:AjaxInPlaceViewTemplate> <wo:WOString value="$value"/> </wo:AjaxInPlaceViewTemplate>`. Equivalent to `ERXWOTemplate { templateName = "view"; }`.
Client deps. None — pure server-side; subclasses ERXWOTemplate and ships no client JS/CSS.
Hierarchical and reorderable/selectable lists.
Why rewrite. The server contract (AjaxTreeModel, WOComponentContent node renderer, expand/collapse actions returning partial updates) is worth preserving, but the client is pure Prototype: the inline toggle script in AjaxTree.html builds 'new Ajax.Updater(...)' and the node toggles ride AjaxUpdateContainer/AjaxUpdateLink. Keep the element and its server side; rewrite the node-toggle client off Ajax.Updater onto fetch()+idiomorph.
Renders a server-driven, Ajax-refreshing tree as nested <ul>/<li> using your component content as the per-node renderer, expanding/collapsing nodes via partial updates without a full page reload.
Usage. Bindings: root, item, parentKeyPath/childrenKeyPath (or delegate), isLeafKeyPath, showRoot, allExpanded/rootExpanded, collapsed/expanded/leafImage(+Framework), treeModel, cache, id/class. Sketch: <wo:AjaxTree root="$rootNode" item="$node" childrenKeyPath="children" parentKeyPath="parent">$node.name</wo:AjaxTree>. Expand/collapse links are AjaxUpdateLinks that re-render the AjaxUpdateContainer wrapping the tree.
Client deps. Server: AjaxTreeModel, AjaxUpdateContainer, AjaxUpdateLink, WOComponentContent. Client: Prototype.js (inline toggle uses new Ajax.Updater). No Scriptaculous. Ships expand/collapse/leaf GIF icons; no own .js/.css. Relies on the morph-aware AjaxUpdateContainer machinery.
Pure server-side Java model behind AjaxTree that tracks expanded/collapsed state and walks the node graph via key paths or a delegate, with helpers for leaf detection, level, depth-first enumeration and a WrapperNode for graph-shaped data.
Usage. No bindings/template of its own. Configure via setRootTreeNode, setParentTreeNodeKeyPath/setChildrenTreeNodesKeyPath (or setDelegate implementing AjaxTreeModel.Delegate), setAllExpanded/setRootExpanded; query isExpanded/setExpanded, isLeaf, level, childrenTreeNodes, rootDepthFirstEnumeration. Normally instantiated automatically by AjaxTree; pass your own via the treeModel binding to share state.
Client deps. None on the client — plain Java over com.webobjects.foundation (NSArray/NSMutableSet/NSKeyValueCodingAdditions/_NSDelegate). No Prototype, Scriptaculous, jQuery, JS or CSS shipped.
Wraps a WORepetition in a Scriptaculous drag-and-drop Sortable so users can reorder a list, posting the new order back to the server to re-sort the bound array.
Usage. Bindings: list, item, listItemIDKeyPath, id (all required), plus drag tuning (handle, ghosting, constraint, hoverclass, movingClass, starteffect/reverteffect/endeffect, scroll), onChange/onUpdate, action. Sketch: <wo:AjaxSortableList list="$items" item="$item" listItemIDKeyPath="id" id="sortable">$item.name</wo:AjaxSortableList>. Emits Sortable.create(...) and on drop posts Sortable.serialize back to the component action.
Client deps. Hard dependency on Prototype.js AND Scriptaculous — addRequiredWebResources injects prototype.js, effects.js and dragdrop.js, and the template calls Sortable.create / Sortable.serialize / Ajax.Request. effect bindings map directly to Scriptaculous Effect.* functions.
Scriptaculous-based dragging and drop targets.
Why rewrite. Client is a hard Prototype.js + Scriptaculous binding: addRequiredWebResources injects prototype.js/effects.js/dragdrop.js, and wonder.js wraps Scriptaculous's global Draggable constructor (ADG, wonder.js:763). The capability and its server contract (the session draggableObject map, draggableObjectForPage) are worth keeping, but the native HTML5 Drag-and-Drop / Pointer Events API doesn't replicate the server round-trip, so it's not a clean platform retirement — the client must be rewritten onto native DnD/pointer events while preserving the Java-object dispatch. Sibling-consistent with AjaxDroppable.
Wraps its component content (or an existing DOM element by id) in a Scriptaculous Draggable so the user can drag it around, optionally carrying a server-side Java object to a matching AjaxDroppable.
Usage. Bindings: id, omitContainer, elementName, class/style, draggableObject (server object handed to the droppable), draggableID, plus Scriptaculous pass-through options (starteffect/reverteffect/endeffect, zindex, revert, snap, ghosting, handle, change, keyPress, scroll). Minimal sketch: wrap content in `<wo:AjaxDraggable draggableObject="$item">...</wo:AjaxDraggable>`; template renders a WOGenericContainer (default div) and emits `ADG.register(id, options)`. The draggableObject is stashed in a per-page WeakHashMap on the session for retrieval by the drop target.
Client deps. Hard dependency on Prototype.js + Scriptaculous: addRequiredWebResources injects prototype.js, effects.js, dragdrop.js (script.aculo.us v1.9.0) and wonder.js. Client behavior is Scriptaculous's Draggable; ADG is a Wonder helper in wonder.js.
Why rewrite. Hard Prototype.js + Scriptaculous dependency: addRequiredWebResources injects prototype.js/effects.js/dragdrop.js and the drop dispatch runs through wonder.js's Scriptaculous Droppables wrapper (ADP, wonder.js:840-848) plus AjaxSubmitButton/AjaxOptions plumbing. The drop-to-server contract (draggableID form value, droppedObject resolution in handleRequest, updateContainerID refresh) is valuable and should be kept, but the client must move off Scriptaculous onto native drag/pointer events + fetch()+idiomorph. Native DnD doesn't cover the server object resolution, so this is a rewrite, not a platform replacement. Sibling-consistent with AjaxDraggable.
Wraps content in a Scriptaculous Droppables zone that accepts AjaxDraggables, then on drop notifies the server (Ajax action or form submit) and resolves the dropped item back to its server-side Java object.
Usage. Bindings: id, elementName, accept/containment/hoverclass/overlap/greedy/onHover (Scriptaculous pass-through), onBeforeDrop/onDrop/onComplete JS hooks, submit + formName for form submission, confirmMessage for a confirm() guard, updateContainerID to refresh an AUC, action, droppedDraggableID, droppedObject, disabled, evalScripts. Minimal sketch: `<wo:AjaxDroppable droppedObject="$target" action="$handleDrop" updateContainerID="list">...</wo:AjaxDroppable>`; emits `ADP.register(id, options)` and an onDrop that calls `ADP.droppedFunc(...)` to round-trip to handleRequest, where droppedObject is looked up via AjaxDraggable.draggableObjectForPage.
Client deps. Hard dependency on Prototype.js + Scriptaculous: addRequiredWebResources injects prototype.js, effects.js, dragdrop.js (script.aculo.us Droppables) and wonder.js. Drop dispatch uses ADP helpers in wonder.js plus AjaxSubmitButton/AjaxOptions plumbing.
Long-running-task feedback and periodic server polling.
Server-side Java model object (no template) that holds the state of a long-running operation (value, maximum, done/canceled/failed/status) and is driven by an AjaxProgressBar; a dev reaches for it to track an upload or batch job's progress in the session.
Usage. Pure POJO, no bindings. Instantiate `new AjaxProgress(id, maximum)`, register with `AjaxProgress.registerProgress(session, p)`, then `p.incrementValue(n)` / `p.setDone(true)` from the worker (or use `copyAndTrack(in,out,maxSize)` for streams). An AjaxProgressBar bound to the same id/registry polls and renders it.
Client deps. None — server-side only, ships no client JS/CSS. Depends only on er.extensions (ERXUnitAwareDecimalFormat).
Why rewrite. Capability and its server-side polling/registry contract are worth keeping, but the client is table-based markup that explicitly loads prototype.js + effects.js + wonder.js and polls via an AjaxUpdateContainer. Move the client to fetch()+idiomorph (or a native <progress> element) while preserving the AjaxProgress server contract.
A polling progress-bar component that renders an AjaxProgress model as an HTML table that refreshes itself on a timer via an update container, firing JS/action callbacks on start/cancel/success/failure; a dev reaches for it to show upload or batch-job progress.
Usage. Bindings: progress/progressID, started, refreshTime, allowCancel, visibleBeforeStart/AfterDone, cancelText, startedFunction/succeededFunction/failedFunction/finishedFunction, finishedAction/succeededAction/canceledAction/failedAction. Sketch: `<wo:AjaxProgressBar progress="$uploadProgress" succeededAction="$done" allowCancel="true"/>`. Self-polls via `setTimeout("<id>Update()", refreshTime)`.
Client deps. Prototype.js + Scriptaculous effects.js + wonder.js (explicitly added in appendToResponse). Renders via an AjaxUpdateContainer and table-based markup. Heavy legacy 2008-era stack.
Why rewrite. Wholly Prototype-dependent: the AjaxBusy.register helper installs a global Ajax.Responder keyed to Prototype request start/end (prototype.js + effects.js + wonder.js). Keep the busy-feedback capability but rebind it to fetch() lifecycle events / a morph-aware request tracker.
Shows/hides a 'busy' div (or applies a CSS class) globally or per-update-container while any Ajax request is in flight, optionally auto-generating a div wrapping a spinner GIF; a dev reaches for it to give visual feedback during AjaxUpdateContainer requests.
Usage. Bindings: busyClass, divID, busyImage/busyImageFramework, watchContainerID, onCreate/onComplete, id/class/style. Sketch: `<wo:AjaxBusyIndicator busyImage="spinner.gif" watchContainerID="myAUC"/>`. Emits `<script>AjaxBusy.register(busyClass, divID, watchContainerID, onCreate, onComplete)</script>` which hooks a global Ajax.Responder.
Client deps. Prototype.js + Scriptaculous effects.js + wonder.js. The AjaxBusy.register helper in wonder.js installs a global Ajax.Responder (Prototype) keyed to request start/end — wholly Prototype-dependent. Ships a busyBigSpinner.gif.
Why rewrite. Same Prototype Ajax.Responder mechanism as AjaxBusyIndicator (prototype.js + effects.js + wonder.js) plus the ~2011 spin.js library. Keep the capability, rewrite the client off Prototype; the spin.js animation can be replaced with a CSS spinner, but the request-lifecycle hookup is the real rewrite.
Same role as AjaxBusyIndicator but renders the busy animation with the JS spin.js library instead of a GIF, exposing spinner styling bindings; a dev reaches for it for a configurable vector spinner during Ajax requests.
Usage. Bindings: busyClass, divID, watchContainerID, onCreate/onComplete, plus spin.js options lines/length/width/radius/color/speed/trail/shadow/spinOpts. Sketch: `<wo:AjaxBusySpinner watchContainerID="myAUC" color="#39f" lines="12"/>`. Emits `AjaxBusy.register(..., true, spinOpts)`.
Client deps. Prototype.js + Scriptaculous effects.js + wonder.js + spin.js (fgnass spin.js v1.2.6, ~2011). Same Prototype Ajax.Responder mechanism as AjaxBusyIndicator, just with a spin.js renderer.
Why rewrite. Rides the Prototype/wonder.js Ajax stack via the AjaxUpdateContainer it renders into and the AUC.update/<id>Update() polling JS. Keep the lightweight-poll-then-refresh capability and its cacheKey server contract; rewrite the polling client onto fetch()+idiomorph.
Cheaply polls the server on a timer with a small cache-key payload and, when the key changes, triggers a full refresh of a separate (larger) AjaxUpdateContainer; a dev reaches for it to keep a heavy content area live without re-fetching it every cycle.
Usage. Bindings: frequency (ms, default 3000), targetContainerID, cacheKey, onBeforeUpdate, id, stop. Sketch: `<wo:AjaxPing targetContainerID="entriesAUC" cacheKey="$entries.count" frequency="5000"/>`. Wraps its body in its own update container that re-arms via `setTimeout("<id>Update()", frequency)`; on cacheKey change calls `AUC.update(targetContainerID)`.
Client deps. Prototype.js + wonder.js (via the AjaxUpdateContainer it renders into and the AUC.update/<id>Update() JS). No Scriptaculous of its own, but transitively rides the Prototype Ajax stack.
Why rewrite. Emits inline script that calls AUC.update (the Prototype/wonder update-container call); transitively rides the Prototype Ajax stack. Keep the multi-container fan-out capability and cacheKey contract, rewrite the emitted update calls onto fetch()+idiomorph alongside AjaxPing.
A child of AjaxPing that lets one ping request conditionally refresh additional update containers, each with its own cacheKey; a dev reaches for it to fan a single ping out to several target containers.
Usage. Bindings: targetContainerID, cacheKey, onBeforeUpdate. Sketch: nest inside AjaxPing — `<wo:AjaxPing ...><wo:AjaxPingUpdate targetContainerID="sidebarAUC" cacheKey="$sidebar.hash"/></wo:AjaxPing>`. Emits `if(onBeforeUpdate()){ AUC.update('targetContainerID'); }` only when its cacheKey changed.
Client deps. Prototype.js + wonder.js transitively (AUC.update is the Prototype/wonder update-container call). No client resources of its own; emits inline script only.
Why rewrite. Directly instantiates Ajax.ActivePeriodicalUpdater (a Prototype/wonder class in wonder.js) in inline script and loads prototype.js + wonder.js; the core mechanism is wholly Prototype-dependent. The server direct-action contract (pingSession / pingSessionAndKeepAlive) is worth keeping — rewrite the client polling onto fetch()/setInterval with status-code handling.
A dynamic element that periodically pings a direct action in the background to detect session expiry (running onFailure, default window.close()) and optionally to keep the session alive; a dev reaches for it to react to / prevent session timeout on a page.
Usage. Bindings: frequency (default 60s), keepSessionAlive, parameters, onFailure, asynchronous, evalScripts, method. Sketch: `<wo:AjaxSessionPing keepSessionAlive="true" frequency="30"/>`. Emits `new Ajax.ActivePeriodicalUpdater('AjaxSessionPinger', url, options)` pointing at its inner WODirectAction (returns 200 if session exists, 300 if not).
Client deps. Prototype.js + wonder.js. Directly instantiates Ajax.ActivePeriodicalUpdater (a Prototype/wonder class defined in wonder.js) in inline script — core mechanism is wholly Prototype-dependent.
Why rewrite. Client side hangs entirely on Prototype: the embedded AjaxUpdateContainer drives a `<id>PeriodicalUpdater` global built on Ajax.PeriodicalUpdater/Ajax.Request. The polling capability and server contract are worth keeping but the client must move to setInterval/fetch()+idiomorph once the update container itself is rewritten.
A stateless component that keeps the user on the current page while a long-running server task executes, polling an embedded AjaxUpdateContainer on a timer until the task signals it is done.
Usage. Bindings: id (required), isRunning (required, drives start/stop), elementName (default div), frequency (poll seconds, default 1), stopped (start in stopped mode). Sketch: wrap progress markup in <wo:AjaxLongResponse id="lr" isRunning="$taskRunning" frequency="2">...progress...</wo:AjaxLongResponse>; the parent kicks off the task and toggles isRunning to stop the polling.
Client deps. Depends on Prototype.js: the .html emits inline JS referencing a `<id>PeriodicalUpdater` global created by wonder.js, which is built on Ajax.PeriodicalUpdater / Ajax.Request from Prototype. No jQuery, no vanilla path.
Server-side subclass of AjaxProgress that adds file-upload metadata (temp file, file name, content type) and a Delegate.uploadFinished callback, deleting the temp file on dispose; a dev reaches for it when tracking an Ajax file upload's byte progress.
Usage. Pure POJO, no template/bindings. `new AjaxUploadProgress(id, tempFile, fileName, streamLength)`, register like an AjaxProgress, feed bytes via copyAndTrack/incrementValue, render with an AjaxProgressBar; dispose() deletes the temp file. Used by the file-upload machinery (e.g. AjaxFileUpload).
Client deps. None — server-side only, ships no client JS/CSS. Extends AjaxProgress; only java.io.File and the parent model.
Background uploads with progress + the server-side streaming core.
Why rewrite. The server contract is worth keeping (out-of-band multipart handler, temp-file streaming, progress tracking, the action/JS completion hooks), but the client is hard-bound to prototype.js + Scriptaculous effects.js + wonder.js and uses a hidden-iframe transport with inline-script Ajax updates. That whole transport should move to fetch() with XMLHttpRequest/upload-progress events and idiomorph-driven partial updates while preserving the AjaxFileUploadRequestHandler contract.
A self-contained file-upload component that renders its own form and a hidden iframe, autosubmits when a file is picked, runs the upload in the background, and fires action/JS hooks (succeeded/failed/canceled/finished) plus a progress bar without blocking the page.
Usage. Bindings: data/inputStream/outputStream/streamToFilePath/finalFilePath/filePath for capturing the upload; succeededAction/failedAction/canceledAction/finishedAction and *Function JS hooks; uploadLabel, allowCancel, refreshTime, keepTempFile, mimeType, uploadFunctionName, onFileSelected. Minimal sketch: <wo:AjaxFileUpload data="$uploadedData" filePath="$fileName" succeededAction="done"/>. It self-registers the 'upload' request handler in its constructor and writes the temp file there.
Client deps. Loads prototype.js (Prototype, ~2008), effects.js (Scriptaculous Effects), and wonder.js in appendToResponse. Upload transport is a hidden iframe + the self-registered AjaxFileUploadRequestHandler. No jQuery. Hard Prototype/Scriptaculous dependency.
A WORequestHandler registered under the 'upload' key that consumes the multipart upload request out-of-band, streams the body to a temp file while tracking progress (AjaxUploadProgress), enforces a max-upload-size, and restores the session by id so the upload can run without blocking the session lock.
Usage. Not a component; auto-registered by AjaxFileUpload's constructor. Configured via properties er.ajax.AjaxFileRequestHandler.tempFileFolder and .maxUploadSize. Reads the multipart iterator, pulls sessionId/id/file form-data, registers an AjaxUploadProgress, and copyAndTrack()s the stream to a temp file; subclasses can override downloadFinished(progress).
Client deps. Pure server-side Java (WOMultipartIterator, ERXUnitAwareDecimalFormat, ERXProperties, AjaxUploadProgress). No client JS, no Prototype/Scriptaculous. The only coupling is that it is driven by the iframe upload from the two components above.
Highlight, hover, rounded corners, behaviour binding.
Why rewrite. The server-side contract (AjaxHighlight.highlight(obj) queues into the context dictionary, value-match drives a flash on next render) is worth keeping, but the client is pure Scriptaculous: hard-codes prototype.js + effects.js and emits AH.highlight() which chains Effect.Highlight/Appear/Fade. Reimplement the flash as a CSS animation/transition (keyframed yellow-fade) applied after morph; no native element replaces the queue-and-match logic.
A WODynamicGroup that flashes a Scriptaculous 'Highlight' (yellow-fade) effect on a wrapped container when its bound value matches an object a prior action queued via the static AjaxHighlight.highlight(obj); devs reach for it to draw the eye to a row/record that was just created or updated after a page reload.
Usage. Server side: call AjaxHighlight.highlight(eo) (or highlightNew/highlightUpdate) in the action before returning the page. Template: wrap the markup in AjaxHighlight bound to value=eo. Key bindings: value (required), id, elementName (default div), effect/newEffect/updateEffect (default 'Highlight', 'none' to suppress), duration, hidden, delay, showEffect/hideEffect with durations. Minimal: <wo:AjaxHighlight value="$item" class="row">...row markup...</wo:AjaxHighlight> emits a div plus an inline AH.highlight(...) script when the item was flagged.
Client deps. Prototype.js + Scriptaculous effects.js (script.aculo.us) + wonder.js. Hard-codes addScriptResourceInHead for prototype.js and effects.js; the runtime call is AH.highlight() which chains scriptaculous Effect.Highlight / Effect.Appear / Effect.Fade. Squarely a 2008-era Prototype/Scriptaculous stack.
A WOComponent that wraps content in a hover area and shows a styled tooltip/popover (image or text) on mouseover, with extensive positioning bindings (drop above/below/corners or advanced top/left/right/bottom); devs reach for it to attach a rich hover tooltip to arbitrary content.
Usage. Bindings: hoverableWidth, showHoverable, toolTipWidth/Height, toolTipAutoScroll, toolTipDrop{Above,Below,TopRight,...}, advancedToolTip{Left,Right,Top,Bottom}, useJavascriptForHoverEffect (default true), useJavascriptOffsetX/Y, additionalClass/Style for hover area and tooltip. Minimal: <wo:AjaxHoverable toolTipWidth="200px">visible content<wo:ToolTip>...hover content...</wo:ToolTip></wo:AjaxHoverable> (tooltip content supplied via the component's content sections). With useJavascriptForHoverEffect it wires erxToolTip.show/hide on mouseover/mouseout; otherwise it is pure CSS :hover.
Client deps. Ships ajaxHoverable.css + ajaxHoverable.js (custom erxToolTip object, Michael-Leigeber-derived). The JS path depends on Prototype.js: Element.observe, $(), .up('.erxHoverArea'), new Element(), clonePosition, addClassName, Event.observe(window,'dom:loaded',...) are all Prototype API used in the .html. So: custom tooltip code on a Prototype.js substrate.
An AjaxDynamicElement that applies the Rico library's Rico.Effect.Round to give an element CSS-less rounded corners by drawing them in JavaScript; devs reached for it in the pre-border-radius era to round box corners.
Usage. Bindings: class (required), elementName (default div), generateTags (default false), id, plus corner-styling options corners/color/bgColor/blend/border/compact. Minimal: <wo:AjaxRoundEffect class="myBox" generateTags="true">...</wo:AjaxRoundEffect> emits the wrapper and an inline new Rico.Effect.Round('div','myBox', {...}) script. Already marked @Deprecated in source.
Client deps. Prototype.js + rico.js (Rico, an early Prototype-based UI library; grep shows ~55 prototype/Effect references in rico.js). Pure 2006-2008 Prototype/Rico stack.
An AjaxDynamicElement that writes out a Behaviour.register(...) call wrapping its template content, letting you attach JS event handlers to elements by CSS selector (unobtrusive JS) without manually emitting the script tag; devs reached for it to bind behaviors to server-rendered markup by selector.
Usage. Binding: includeScriptTag (default true). Minimal: <wo:AjaxBehaviour>{ '#save' : function(e){ e.onclick = ... } }</wo:AjaxBehaviour> emits <script>Behaviour.register({...});</script>. The content between the tags is the literal JS rules object passed to Behaviour.register.
Client deps. behaviour.js (Behaviour v1.1, Ben Nolan, June 2005), which is built on top of Prototype's $$/CSS-selector engine. So: Prototype-era unobtrusive-JS micro-library.
Select-option models and field-focus helpers.
A pure server-side Java helper that maps a single WO binding (by name, with optional default and a type tag) to one JavaScript/JSON key-value pair, used by Ajax dynamic elements to assemble the options object passed to a client-side JS widget.
Usage. Not a WOD element; instantiated in Java. Minimal sketch: new AjaxOption("frequency", AjaxOption.NUMBER); then AjaxOption.createAjaxOptionsDictionary(arrayOfOptions, component, associations()) yields an NSMutableDictionary of JS-formatted strings. Type constants: DEFAULT/STRING/SCRIPT/NUMBER/ARRAY/STRING_ARRAY/BOOLEAN/STRING_OR_ARRAY/DICTIONARY/FUNCTION.
Client deps. None on the client. Pure Java; delegates JS value formatting to AjaxValue. No Prototype/Scriptaculous/jQuery. (It exists to feed Prototype-era widgets, but carries no client code itself.)
A WODynamicElement (and set of static helpers) that emits a JSON/JS object literal from a dictionary of bindings, wrapping the output in { } for inclusion in a generated client-side call.
Usage. Inline WOD: AjaxOptions { method = "get"; options = createAjaxOptions; } emits {method:'get', ...}. More commonly used statically from Java: AjaxOptions.appendToResponse(optionsDict, response, context). The element renders its children between the braces, so it can wrap literal JS too.
Client deps. None on the client. Pure server-side response generation. Javadoc explicitly targets Prototype's Ajax.Request options argument, but the class emits generic JSON and ships no JS. No jQuery.
A trivial AjaxOption subclass that ignores the bound value and always emits a fixed constant, used when an options key must be hard-coded rather than read from a component binding.
Usage. Java only: new AjaxConstantOption("evalScripts", Boolean.TRUE, AjaxOption.BOOLEAN); then include it in the array passed to AjaxOption.createAjaxOptionsDictionary(...). Overrides both valueInComponent(...) variants to return the constant.
Client deps. None on the client. Pure Java, 34 lines. No Prototype/Scriptaculous/jQuery.
A convenience subclass of ERXWOText (a textarea) that auto-grabs keyboard focus, optionally selects all text, and optionally runs JS on the Enter key, via injected client script.
Usage. WOD: FocusText { value = someText; focus = true; selectAll = true; onEnter = "doSubmit()"; }. Bindings: id, selectAll, focus (default true), onEnter, plus passed-through onkeypress. Emits an inline <script> calling Field.focus/Field.select inside a setTimeout, and an idSubmitOnEnter handler wired to onkeypress.
Client deps. Hard dependency on Prototype.js — it calls AjaxUtils.addScriptResourceInHead(context, response, "prototype.js") and the generated JS uses Prototype's Field.focus, Field.select, Event.keyValue, and Event.stop. No Scriptaculous, no jQuery.
A convenience subclass of ERXWOTextField (an <input type=text>) that auto-grabs focus, optionally selects all text, and optionally runs JS on Enter via injected client script; also the shared static helper that FocusText delegates its script emission to.
Usage. WOD: FocusTextField { value = name; focus = true; selectAll = true; onEnter = "login()"; }. Same bindings as FocusText (id, selectAll, focus, onEnter, onkeypress). Static appendJavascriptToResponse(...) emits the Field.focus/Field.select/setTimeout block and the Prototype-based idSubmitOnEnter(event) handler reused by FocusText.
Client deps. Hard dependency on Prototype.js — injects prototype.js into <head> and the emitted JS uses Prototype's Field.focus, Field.select, Event.keyValue, Event.stop (comment in source literally says 'PROTOTYPE FUNCTIONS'). No Scriptaculous, no jQuery.
The framework's internals — base classes, response/request handling, utilities. Architecturally sound and morph-neutral.
Framework principal that boots the Ajax framework at app launch, registering the AjaxRequestHandler, the comet/push handler, and the AjaxResponse delegate.
Usage. No bindings; it is an ERXFrameworkPrincipal subclass loaded automatically. finishInitialization() registers request handlers and, for ERXAjaxApplication apps, installs AjaxResponse.AjaxResponseDelegate. Developers never instantiate it directly.
Client deps. Server-side only; no client JS. Indirectly governs the whole Ajax JS stack (Prototype/Scriptaculous bundled in the framework).
Why rewrite. The server-side dispatch contract is worth keeping, but its resource-injection helpers exist to push the Prototype-based Ajax JS into the head, and its whole reason for being is the legacy Ajax client model. As the client moves to fetch()+morph, the base class's resource/dispatch plumbing must be reworked to emit/serve the new client rather than the Prototype stack. Keep the contract, rewrite the client coupling.
Abstract WOComponent base for stateful (.wo) Ajax components, wiring up request handling, binding helpers, and resource-injection convenience methods.
Usage. Subclass it; implement addRequiredWebResources(WOResponse) and handleRequest(request, context). Provides valueForBinding-with-default, booleanValueForBinding, safeElementID(), and invokeAction() that routes Ajax requests to handleRequest via AjaxUtils.shouldHandleRequest.
Client deps. Server-side base class; ships no client JS directly. Resource helpers delegate to AjaxUtils/ERXResponseRewriter.
Why rewrite. Same situation as AjaxComponent: keep the server-side dispatch/handleRequest contract, but the addRequiredWebResources/resource-injection plumbing exists to wire up the Prototype client and must be reworked for the fetch()+idiomorph client. Scored identically to its sibling.
Abstract WODynamicElement base for stateless Ajax elements (most er.ajax elements extend this), providing the same request-dispatch and resource-injection contract as AjaxComponent.
Usage. Subclass it; implement addRequiredWebResources(response, context) and handleRequest(request, context). invokeAction() checks shouldHandleRequest(), calls handleRequest, guards against accidentally returning the full page, and falls back to AjaxUtils.createResponse. Extends ERXDynamicElement.
Client deps. Server-side base class; no client JS of its own. Subclasses pull in their own JS via addRequiredWebResources.
Tiny interface unifying AjaxComponent and AjaxDynamicElement so callers can treat stateful and stateless Ajax elements uniformly for binding access and request handling.
Usage. Implemented by AjaxComponent and AjaxDynamicElement. Declares valueForBinding(name, component), valueForBinding(name, default, component), and handleRequest(request, context). Rarely referenced by application code directly.
Client deps. None; pure server-side interface.
Why rewrite. Mostly platform-neutral server plumbing, but it is the framework's seam to the Prototype client: updateDomElement emits Prototype's Element.update(), jsSafeIdentifier must stay in lockstep with ajaxSafeName() in wonder.js, and the script header/footer + resource injection serve the Prototype stack. The DOM-emission and client-coupled helpers must be rewritten to target idiomorph; the routing/response helpers can largely stay. Keep the class, rewrite the Prototype-emitting parts.
Central static utility grab-bag for the Ajax framework: building AjaxResponses, injecting script/CSS resources, JS-string quoting/escaping, request-routing decisions, array/JSON coercion, and DOM-update JS emission.
Usage. All-static. Common calls: AjaxUtils.createResponse(request, context), addScriptResourceInHead/addStylesheetResourceInHead, appendScript/appendScriptHeaderIfNecessary, shouldHandleRequest, ajaxComponentActionUrl, jsSafeIdentifier, and updateDomElement (emits Prototype's Element.update(...)).
Client deps. Mixed. Most methods are server-side plumbing. updateDomElement emits Prototype's Element.update() JS, and jsSafeIdentifier is documented to mirror ajaxSafeName() in wonder.js. Uses org.json (JSONArray) for array coercion.
Why rewrite. The update-pass mechanism and the null-result/double-click recovery are valuable server-side contract worth preserving, but updateDomElement emits Prototype's Element.update() and the response is shaped for the Prototype client (script header/footer, content-type juggling). The client-facing emission must move to fetch()+idiomorph while the update-pass machinery is retained.
WOResponse subclass that runs a second 'update pass' so an Ajax action can render one or more AjaxUpdateContainers in the same response, plus a delegate that recovers from double-click/null-result race conditions.
Usage. Usually obtained via AjaxUtils.createResponse rather than constructed directly. Offers updateDomElement(id, value[, formats]) and appendScriptHeader/FooterIfNecessary convenience methods. addAjaxResponseAppender registers global appenders (e.g. a notifications-area updater) onto every Ajax response.
Client deps. Server-side; emits JS that relies on the client Ajax stack. updateDomElement convenience method emits Prototype's Element.update().
WOComponentRequestHandler subclass registered under the 'ajax' key so Ajax component actions get a dedicated URL namespace and page-storage is suppressed for them.
Usage. Registered automatically by the Ajax principal under key 'ajax'. AjaxUtils.ajaxComponentActionUrl rewrites normal component-action URLs to this handler when useAjaxRequestHandler() is true. handleRequest() calls enableShouldNotStorePage() then defers to the standard component handler.
Client deps. None; pure server-side request handler.
A tiny abstract server-side hook (single appendToResponse method) whose subclasses get a chance to append extra markup/JS to the tail of every AjaxResponse, registered globally via AjaxResponse.addAjaxResponseAppender.
Usage. No bindings, no template — pure Java SPI. Subclass it, implement appendToResponse(WOResponse, WOContext), and register once at startup: AjaxResponse.addAjaxResponseAppender(new MyAppender()). Each registered appender runs at the end of every AjaxResponse, typically to inject a shared JS block so callers need not repeat it.
Client deps. None — pure server-side Java abstraction; ships no client JS or resources.
Elements that existed in the original framework and have since been deleted, kept here as a record of what went and why. Their code lives on in git history.
A JSON-RPC bridge that exposed a server-side Java object's public methods to client JavaScript (call Java by name over JSON, via the jabsorb library).
Why removed. A security liability: by default it published every public method of the proxied object to the browser (the parent component if no proxy was bound), making things like application.terminate() reachable from client JS. Built on jabsorb 1.2.2 — unmaintained since ~2008 and not in Maven Central. Its entire in-framework use was the (also-removed) AjaxFlexibleFileUpload's progress polling. The whole jabsorb / er.ajax.json stack went with it.
Replacement. For browser→server calls, use a normal direct action (or component action) returning JSON and call it with fetch(). No standing RPC bridge, no reflective method exposure.
A styled, form-independent file-upload variant of AjaxFileUpload, driven by a hidden iframe (Valums' ajaxupload.js) plus AjaxProxy/JSON-RPC progress polling on a refreshTime interval.
Why removed. Its rich client UX was the only consumer of the AjaxProxy/jabsorb stack, and that whole transport is obsolete: native XMLHttpRequest gives continuous upload progress (xhr.upload.onprogress) and cancel (xhr.abort()) with no server polling, no iframe, and no Prototype/Scriptaculous. Single-file, click-to-select only (it never supported multi-file or drag-and-drop — the "flexible" referred to its flexible server-side data sink).
Replacement. A native-XHR reimplementation (same binding signature, inherits AjaxFileUpload's data sink) exists on the flexible-file-upload-experiment branch, validated end-to-end. The plain AjaxFileUpload remains for no-frills uploads.
A server-side registry of ~19 hardcoded social-bookmarking sites, each building a "submit this URL+title" share link, plus AjaxSocialNetworkLink which rendered an icon-link to one.
Why removed. The data was a fossil: del.icio.us, Furl, StumbleUpon, Newsvine, Netscape, Ma.gnolia, Rawsugar, Spurl, Squidoo, Tagtooga — nearly all of these are dead websites, not just dead APIs. All links were plain http://, and one (ttp://technorati.com, missing the "h") was a never-corrected typo — proof it had never been exercised. Nothing in the framework referenced it. Shipped 19 icon images of defunct services.
Replacement. None needed. Modern sharing is navigator.share() (the Web Share API) or a couple of per-platform intent URLs — not a curated registry of 2007 bookmarking sites.