Jquery.parcel
A jQuery plugin designed to simplify and guide the OO encapsulation of client side Javascript code and more...
Install / Use
/learn @luning/Jquery.parcelREADME
jQuery.parcel is a jQuery plugin designed to simplify working with complex forms. It provides an Object-Oriented encapsulation of forms and their field groups using a straighforward declarative syntax. It enables some very powerful ways for decomposing forms into conceptual parcels, and provides meaningful abstractions for these parcels.
"Two Minute Tour":#quickTour
** "Build a Parcel":#quickTour_buildParcel ** "Simple Operations":#quickTour_simpleOp ** "Bind Events":#quickTour_event
"Learn More":#more
** "Mixin Behaviours":#more_behav ** "Build Composite Parcel":#more_compositeParcel ** "Add/Remove DOM elements Dynamically":#more_sync ** "Virtual Field":#more_virtual
"API Reference":#api
** "Parcel":#api_parcel *** "Build Parcel":#api_parcel_build *** "Parcel Operations":#api_parcel_op ** "Field":#api_field *** "Field Operations":#api_field_op *** "Field Events":#api_field_event ** "Form Inputs":#api_input ** "Extend Parcel":#api_ext ** "Utility":#api_util
"Q&A":#qa
<h1><a name="quickTour">Two Minute Tour</a></h1> <h2><a name="quickTour_buildParcel">Build a Parcel</a></h2>Given a HTML snippet:
<pre> <div id="person"> <select name="title"> <option>Mr</option> <option checked="checked">Mrs</option> </select> <input type="text" name="firstname" value="Jane"/> <input type="text" name="lastname" value="Doe"/> </div> </pre>You create a parcel like this:
<pre> var person = $("#person").parcel(); </pre>This builds a parcel representing @person@ with all fields set up automatically from their name attribute of the input field.
(The fields are actually jQuery wrappers of each form field element in the specified parcel)
<pre> person.title; person.firstname; person.lastname; </pre> <h2><a name="quickTour_simpleOp">Simple Operations</a></h2>@firstname@ is a person field and calling @state()@ will simply return the field value, just like @val()@ on a jQuery object.
<pre> person.firstname.state(); #=> "Jane" </pre>To change @firstname@ to new value, just pass the value into the @state()@ method.
<pre> person.firstname.state("John"); </pre>This is just like @person.firstname.val("John")@ in jQuery, but with the appropriate events are fired as if a real user typed the value into the field.
Setting the values of the entire person parcel is just as easy!
<pre> person.state({ title: "Mr", firstname: "John", lastname: "Smith"}); </pre>Remember that all the user events get fired (ie. change, blur, click, etc).
Calling @state()@ on the person parcel simply returns the current state of the parcel as an object:
<pre> person.state(); #=> { title: "Mr", firstname: "John", lastname: "Smith"} </pre>You can tell if the state has changed with @isDirty()@:
<pre> person.isDirty(); #=> true </pre>Person is flagged as dirty, since the state of person has been changed since initialization.
Set the original state to the parcel with @resetState()@
<pre> person.resetState(); #=> { title: "Mrs", firstname: "Jane", lastname: "Doe"} </pre> <h2><a name="quickTour_event">Bind Events</a></h2>Let's say you want to have a @label@ element update with changes in the value of a field. Use the @bindState()@ method passing in the CSS selector:
<pre> person.firstname.bindState("#first_name_label"); </pre>Now any change of @firstname@ will update the value of the label you specified.
But what if you wanted a single label to reflect all of the fields? Simply pass a transformation function as the second argument to @bindState()@ like so. The state will be passed in as a parameter to this function so you can easily extract what you need.
<pre> person.bindState("#id_of_summary_span", function(s) { return s.title + " " + s.firstname + " " + s.lastname; }); </pre>Any changes to person fields will now update the summary span using the specified transformation function.
<pre> person.firstname.stateChange(function(state) { /* custom logic */}); person.stateChange(function(state) { /* custom logic */}); </pre>State change of the @firstname@ field or @person@ parcel will trigger the custom handlers and pass in the latest state object.
<h1><a name="more">Learn More</a></h1> <h2><a name="more_behav">Mixin Behaviours</a></h2>You can extend a parcel by mixing in new behaviour.
<pre> function Person() { this.summary = function() { var s = this.state(); return s.title + " " + s.firstname + " " + s.lastname; } } var person = $("#person").parcel(Person); person.summary(); </pre>Define behaviour @Person@ as a function, build parcel with the behaviour, and the @summary()@ method will be mixed into the parcel.
Behaviour mixins are the recommended way to include custom logic for a specific parcel.
You can also specify the behaviour function in the containing DOM element by supplying a @parcel@ attribute:
<pre> <div id="person" parcel="Person"> ... </div> </pre>Then:
<pre> var person = $("#person").parcel(); person.summary(); </pre>jQuery.parcel will mixin the @Person@ behaviour for you automatically.
<h2><a name="more_compositeParcel">Build Composite Parcel</a></h2>You can build a composite parcel with another parcel as field by setting up @parcel@ property on any DOM element which can be used as a container (typically _div_s, _fieldset_s, etc).
With this HTML:
<pre> <div id="person"> ... <div parcel name="contact"> <input type="text" name="number" value="+61 2 9555 0123" /> <input type="text" name="type" value="work" /> </div> </div> </pre>Then:
<pre> var person = $("#person").parcel(); person.state(); #=> { title: "Mr", firstname: "John", lastname: "Smith", contact: { number: "+61 2 9555 0123", type: "work" } } person.contact.state(); #=> { number: "+61 2 9555 0123", type: "work" } person.contact.number.state(); #=> "+61 2 9555 0123" </pre>Build a parcel with a field containing an array of sub-fields with the same name (e.g. person may have multiple emails) by setting @parcel@ property to @[sub_field_name]@ on the container DOM element.
Given this HTML:
<pre> <div id="person"> ... <div parcel="[email]"> <input type="text" name="email" value="a@my.com" /> <input type="text" name="email" value="b@my.com" /> <div> </div> </pre>Then:
<pre> var person = $("#person").parcel(); person.state(); #=> { title: "Mr", firstname: "John", lastname: "Smith", email: ["a@my.com", "b@my.com"] } person.email.state(); #=> ["a@my.com", "b@my.com"] person.email.items[0].state(); #=> "a@my.com" </pre> <h2><a name="more_sync">Add/Remove DOM elements Dynamically</a></h2>Adding a new DOM element dynamically will add the corresponding field. Any event registered on a parcel works for the newly added field too. (Pretty much like jQuery live events).
Given two emails in the DOM already, then:
<pre> var person = $("#person").parcel(); var newEmail = $("<input type="text" name="email"></input>"); person.container.append(newEmail); newEmail.sync(); var emailCount = person.emails.length; </pre>@emailCount@ is @3@, reflects the added email.
jQuery.parcel extends jQuery with the @sync()@ method. Just call it after the new elements are added.
The same thing happens when removing DOM elements, the fields will be removed.
Say we have two emails in the DOM already, and we remove the last one:
<pre> var person = $("#person").parcel(); person.container.find("input[name=email]:last").remove(); person.sync(); var emailCount = person.emails.length; </pre>@emailCount@ is now @1@, reflecting the removal.
Call @sync()@ on a parcel after removing DOM elements.
<h2><a name="more_virtual">Virtual Field</a></h2>A virtual field in jQuery.parcel is a jQuery object of a div, fieldset or other container like dom element, which contains fields in it's scope.
It represents a virtual part of parcel. You can treat a virtual field as a normal Field, that means you can call @state()@, @isDirty()@, @resetState()@, and do event operations like @bindState()@, @stateChange()@ on it.
Given this HTML:
<pre> <div id="person"> <div id="basicInfo"> <input type="text" name="firstname" value="Jane"/> <input type="text" name="lastname" value="Doe"/> ... </div> ... </div> </pre>Then:
<pre> var person = $("#person").parcel(); var basicInfo = $("#basicInfo"); basicInfo.state(); #=> { firstname: "Jane", lastname: "Doe", ... } basicInfo.state({ firstname: "Mary" }); #=> { firstname: "Mary", lastname: "Doe", ... } basicInfo.resetState(); #=> { firstname: "Jane", lastname: "Doe", ... } basicInfo.bindState("#id_of_some_label", function(state){ /* compose a string from state */ }); basicInfo.stateChange(function(state){ /* play with the new state */ }); ... </pre>The flexibility of virtual field makes the event wiring up much more expressive and easier.
<h1><a name="api">API Reference</a></h1> <h2><a name="api_parcel">Parcel</a></h2> <h3><a name="api_parcel_build">Build Parcel</a></h3> <p style="color:DarkCyan;font-size:18px;margin:10px">parcel([behaviour], [state])</p>Returns: Parcel/array
For each element in jQuery, create a parcel and return the set of created parcels, return single parcel if only one element in jQuery object.
behaviour - optional, a function which will be mixed in after the parcel is created.
state - optional, the initial state of the parcel.
Common logic
Build with normal jQuery field
Build with array field
Build with Parcel as field
Build with virtual field
Build with behaviour
Build with initial state
Build multiple Parcels at once
<h3><a name="api_parcel_op">Parcel Operations</a></h3>h4. sync([dom]) Returns: Parcel
create field(s) with the DOM element passed in or remove field(s) reflecting some DOM element is removed if DOM element is not provided.
dom - optional, newly cre
Related Skills
clearshot
Structured screenshot analysis for UI implementation and critique. Analyzes every UI screenshot with a 5×5 spatial grid, full element inventory, and design system extraction — facts and taste together, every time. Escalates to full implementation blueprint when building. Trigger on any digital interface image file (png, jpg, gif, webp — websites, apps, dashboards, mockups, wireframes) or commands like 'analyse this screenshot,' 'rebuild this,' 'match this design,' 'clone this.' Skip for non-UI images (photos, memes, charts) unless the user explicitly wants to build a UI from them. Does NOT trigger on HTML source code, CSS, SVGs, or any code pasted as text.
ui-ux-pro-max-skill
61.7kAn AI SKILL that provide design intelligence for building professional UI/UX multiple platforms
ui-ux-pro-max-skill
61.7kAn AI SKILL that provide design intelligence for building professional UI/UX multiple platforms
onlook
25.1kThe Cursor for Designers • An Open-Source AI-First Design tool • Visually build, style, and edit your React App with AI
