Constructor Of User interfaces LIbrary. Library for creating webcomponents that automatically change their appearance depending on the inner state as well as execute user-defined logic on DOM and life-cycle events.
The project is pretty small and raw but already seems to be performanceful.
Install the library through
npm install couli
then include with
var Couli = require('couli')
or
import Couli from 'couli'
in your script file.
couli.js
file also can be included on the client through script
tag, and resides at /dist/
folder of the project.
You can fiddle with the code for the library yourself and generate your own version of the library file with npm run-script build
For developing and learning process to become easier, start webpack-web-server
with npm start
command, and check out mini example apps at the /dist/
folder.
Documentation for the library is quite terse and is recommended to be read along with examining examples from /dist/
folder. Hopefully, that will be enough to understand main API concepts.
Components are created with the call to Could.define
function.
With such signagure:
CouliComponent component = Couli.define (
// string representing component markup. Must have a single root element.
String markup,
// entities describing the behavior of parts of the component. May or may not point to markup elements.
Object bindings,
// styles to be applied to a given component
Object styles
// tag to component mapping for inserting child components
Object childCompnents
)
All arguments except markup
are optional.
Bindings describe the appearance and behavior of parts of a component. They can point to HTML elements within markup through x-b
and x-lb
(the difference is described below) attributes or they can just be used for some internal work calculations.
Bindings are defined inside the bidings
hash with keys as binding names and values as binding options.
Binding can have the following options:
{
value: ReactiveFunction (BindingsValues, ComponentInterface),
html: ReactiveFunction (BindingsValues, ComponentInterface),
style: ReactiveFunction (BindingsValues, ComponentInterface),
class: ReactiveFunction (BindingsValues, ComponentInterface),
attrs: ReactiveFunction (BindingsValues, ComponentInterface)
events: {
[domEventName]: EventHandler (Event, ComponentInterface),
...
},
hooks: {
[lifeCycleEventName]: EventHandler (ComponentValues, ComponentInterface),
...
}
}
Binding with the name of ''
(empty string) is considered to be a component binding. Its configuration will be applied to the whole component.
value
, html
, style
, class
and attrs
functions will reevaluate each time values of bindings they listen to change
all of them have the following common signature:
ReactiveFunction (Object bindingsValues, ComponentInterface ci)
Where:
bindingsValues
- values of all bindings in the component.
ci
- entity allowing to get access to the underlying component, get and set values, move up and down in components hierarchy tree. More on what and how to use ComponentInterface
see below.
Reactive functions differ in what they return and where they apply:
Returns value of the binding. The return value can be of any type. value
itself is not applied to the markup unless you don't define html
function.
Returns what will be innerHTML
of the binding.
Must return an object with keys as class names and booleans as values expressing whether show or hide each class.
Must return an object with keys and values expressing what styles to apply to HTML markup.
Must return an object with keys and values expressing what attributes to change in HTML markup.
events
object contains event handlers for a piece of markup you assign a binding to.
Keys in events
object are any valid event names (mouseup
, blur
, keyup
etc.).
Signature for all event handlers is:
EventHandler (Event e, ComponentInterface ci)
Where:
e
- Event object.
ci
- entity allowing to get access to the underlying component, get and set values, move up and down in components hierarchy tree. More on what and how to use ComponentInterface
see below.
These functions will be called at different binding's life events.
For now:
mount
event works only for a whole component (binding name - ''
) and is called when a component is created and attached to DOM
update
events work for whole components as well as individual bindings, called when a value in a component is updated.
remove
events work for list items, for now, called after list item was removed from DOM
Signature for all component life-cycle handlers is:
LifeCycleHandler (ComponentValues, ComponentInterface ci)
Where
value
- values of the whole component or value of a specific binding.
ci
- entity allowing to get access to the underlying component, get and set values, move up and down in components hierarchy tree. More on what and how to use ci
see below.
An object containing styles to be applied to a given component. Where the keys are any valid selectors, and values are objects describing styles for these selectors. To point to binding markup just use the binding name as a selector.
If childComponents
argument is added to Couli.define
function, the library will search for tags corresponding to the keys in this object and replace them with the corresponding components.
Signature for defining child components:
{
tagName: [ CouliComponent component, Links { childBindingName: bindingName } ]
}
where:
tagName
- tags in the component being defined you want to replace to components
component
- component for replacement
Links
- optional object to declare direct dependence of bindings of the component and child components, where childBindingName
- binding name in a child component and bindingName
- binding name in the component.
ComponentInterface
is a thing that allows getting and setting binding values on the component, getting component and binding markups as well as moving from one component to another.
Methods:
Returns value of the binding with key
name. Or if no argument is given, returns an object of all values of the component.
If you are trying to get the value of a list binding, then instead of receiving the value itself, you will get another interface ArrayInterface
for working with this list of values through which you will be able to efficiently add, remove, change and get values of the list. More on ArrayInterface
see below.
Sets values of the component's bindings to values of changeHash
where keys are binding names.
If no argument is given, returns ComponentInterface
of the parent component.
If a numeric argument is given, returns ComponentInterface
of the parent component num
levels higher.
If a string argument is given, returns ComponentInterface
of the parent component with the name that corresponds to the string argument value. See below on how to give a component a custom name.
Returns HTMLElement binding with bindingName
is assigned to.
If a binding you want to .get()
value from is of list type, then ArrayInterface
is what you will get instead and here's methods that you can call on it.
Get ComponentInterface
of list item at num
position.
Add newItem
to the end of the list.
Add newItem
to the begining of the list.
Add newItem
at num
postion of the list.
Instead of passing only one Object
, .push
, .unshift
and .add
methods can as well receive an array of items instead.
Remove num
last elements from the list. num
defaults to 1 if omitted.
Remove num
first elements from the list. num
defaults to 1 if omitted.
Remove num
elements from the list starting from start
position.
Get raw values of the list.
Iterates over the values of the list and call cb
function with arguments (Object item, Number index)
on each of the items.
Returns a new list with items from the initial list for which cb
function with arguments (Object item, Number index)
returns a true
value
Returns a new array with items being results of calling cb
function with arguments (Object item, Number index)
on each item of the initial list.
x-b
attribute points to HTMLElement for the binding
x-lb
attribute is assigned to HTMLElements that will have the role of list containers.
Such list bindings receive additional logic for rendering and mutating arrays of data.
HTMLElement with x-lb
attribute must have one child element which will be considered as a template for list item.
Finally to apply created components to markup call Couli.apply(HTMLElement container, CouliComponent component)
where container
is a HTMLElement on the page where you wish to place your component
.
To save the time and effort of writing and reading various binding options in full length, one can use shortened keys that will correspond to full option keys.
Short key | Full key |
---|---|
_s |
style |
_c |
class |
_v |
value |
_a |
attrs |
_h |
html |
_eab |
events.abort |
_eld |
events.load |
_eer |
events.error |
_ef |
events.focus |
_efi |
events.focusin |
_efo |
events.focusout |
_eb |
events.blur |
_eas |
events.animationstart |
_eac |
events.animationcanceled |
_eae |
events.animationend |
_eai |
events.animationiteration |
_ets |
events.transitionstart |
_etc |
events.transitioncancel |
_ete |
events.transitionend |
_etr |
events.transitionrun |
_efr |
events.reset |
_efs |
events.submit |
_ech |
events.change |
_ekd |
events.keydown |
_ekp |
events.keypress |
_eku |
events.keyup |
_emc |
events.click |
_emx |
events.contextmenu |
_emd |
events.mousedown |
_eme |
events.mouseenter |
_eml |
events.mouseleave |
_emm |
events.mousemove |
_emo |
events.mouseover |
_emt |
events.mouseout |
_emu |
events.mouseup |
_empc |
events.pointerlockchange |
_empe |
events.pointerlockerror |
_emw |
events.wheel |
_ems |
events.select |
_ed |
events.drag |
_ede |
events.dragend |
_edr |
events.dragenter |
_eds |
events.dragstart |
_edl |
events.dragleave |
_edo |
events.dragover |
_edd |
events.drop |
_emcp |
events.canplay |
_emcpt |
events.canplaythrough |
_emdc |
events.duractionchange |
_emet |
events.emptied |
_emnd |
events.ended |
_emld |
events.loadeddata |
_emlmd |
events.loadedmetadata |
_emps |
events.pause |
_empl |
events.play |
_emplg |
events.playing |
_emrc |
events.ratechange |
_emsk |
events.seeked |
_emskg |
events.seeking |
_emst |
events.stalled |
_emsd |
events.suspend |
_emtu |
events.timeupdate |
_emvc |
events.volumechange |
_emwt |
events.waiting |
_hu |
hooks.update |
_hm |
hooks.mount |
_hr |
hooks.remove |