Component - js-lib-com/wood GitHub Wiki

WOOD component, for short component, is a reusable core unit similar to object from OOP. Component has visual appearance and properties, and behavior described in separated files: mandatory layout (.HTM) file and optional layout style (.CSS), script (.JS), descriptor (.XML) and resources (files - mostly media, and variables definition) files. Anyway, for page components descriptor is mandatory, even if empty; it is used by build tool to recognize a component as page.

All component files are stored in a single directory; by convention directory name is the component name. If component has only layout file there is no need for separated directory and such simplified component is known as widget.

File Pattern Type Description
${compo-name}.htm HTML Layout graphical elements description
${compo-name}.css Layout Style CSS styles regarding component layout
${compo-name}.js JavaScript behavior and dynamic layout manipulations
${compo-name}.xml Descriptor component properties for generated page customization
*.xml Variables variables declared with variable reference, e.g. @string/name
*.* Resources resource files declared with resource references, e.g. @image/icon

First four file types, those with component name as base name are collectively known as component's core files. Core files plus variables definition files are component's source files.

All source files may contain at-meta references:

At-Meta Reference Type Scope
references to variables defined into variables definition files all source files
references to resource files component core files
references to layout parameters component layout files

When processing project file for components, WOOD uses next rules:

  • core files are loaded by file name with exact extension form above table,
  • variables definition files are XML files that have root element tag recognized as a variable,
  • all at-meta references from source files are resolved on the fly, while reading file content - there is a special source file reader for that.

HTML Layout

HTML layout is a core component file, the only one mandatory. Layout merely describes dimension and position of graphical elements whereas visual aspects are defined using CSS styles. Component layout uses pure HTML code.

Note that layout HTML is working closely with CSS layout related styles; HTML code just declares the types of the graphical elements and the overall structure whereas the actual dimensions and positions are declared on CSS file using layout related style.

Layout Relations

Component relations are implemented into layout files. In fact, when we discuss about component relations we are in fact speaking about layout relations.

Relation Description
Component Inclusion The process of inserting a child component into a parent. It can be a recursive process allowing creation of trees of arbitrary complexity.
Template A template component has editable elements acting as placeholders; content components provide layout for template editables. For example, a template for site pages may have navigation bar and footer, that are inherited by all pages, and editable content sections provided by each page.
Template Fragment Simplified template invocation syntax for templates with a single editable element.
Inline Template A template used inside a component with content declared inline. It is a simplified syntax replacing an aggregation and an inheritance.

Layout Operators

All WOOD operators are used on layout files. Operators are declared using well known HTML attributes syntax; there is no programing language mixed in. There are three syntax variants, formally known as operator naming strategy, defined per project:

  • Attribute Name: simple attribute name. Because it does not use prefix it is prone to name collision but is simple to use.
<article>
	<section compo="compo/section" param="title:Section Title"></section>
</article>
  • Custom Attribute Name: uses HTML custom attribute name, that is, prefixed with data-. This naming convention is a trade-off between simplicity to use and avoiding name collisions.
<article>
	<section data-compo="compo/section" data-param="title:Section Title"></section>
</article>
  • XML Namespace: this is default naming strategy and offer a clear separation for WOOD operator name space. Anyway, add complexity because name space should be declared with WOOD URI: xmlns:wood="js-lib.com/wood".
<article xmlns:wood="js-lib.com/wood">
	<section wood:compo="compo/section" wood:param="title:Section Title"></section>
</article>

Layout Parameters

HTML layout supports layout parameters that allows in place component customization. For that it defines named value placeholders using parameter references - @param/name.

Parameter reference is text replaced by build tool and can be defined anywhere XML allows a text to appear.

<!-- child component -->
<div>
	<!-- parameter reference -->
	<h3>@param/title</h3>
	...
</div>

Parent component should define values for all parameter references, using wood:param="name:value;*" operator.

<!-- parent component -->
<body xmlns:wood="js-lib.com/wood">
	...
	<!-- child component reference with parameter -->
	<div wood:compo="compo/dialog" wood:param="title:Dialog Title"></section>
	...
</body>

Layout Style

Component layout file defines overall structure but the actual dimensions and positions of constituent graphical elements is described into component style file.

For pure separation of concerns and avoiding styles conflict, WOOD does not allow to include visual (aspect) CSS styles into component style file. These rules should be managed by theme styles, global per application.

When aggregate components, build tool takes care to also process related style files automatically. Anyway, if working with third party libraries need to explicitly declare third party styles into component descriptor.

Lets consider a page component page/index with a child component compo/list-view. Page component has a layout file page/index/index.htm and a style file page/index/index.css.

  • page/index/index.htm
<body xmlns:wood="js-lib.com/wood">
	<div wood:compo="compo/list-view"></div>
</body>

Page component layout style describe dimensions and positions for its child elements. It is not allowed to use aspect rules into page component style file.

  • page/index/index.css
body { ... }

Child component compo/list-view has a layout file compo/list-view/list-view.htm and a style file compo/list-view/list-view.css.

  • compo/list-view/list-view.htm
<div class="list-view"> ... </div>

Child component layout style describe dimensions and positions for its child elements. It is not allowed to use aspect rules into component style file.

  • compo/list-view/list-view.css
.list-view { ... }

Into generated page - site/index.htm, beside aggregating HTML layout, there are external resource link elements for style file inclusion. Style links are inferred automatically by build tool based on component relations.

  • site/index.htm
<HTML>
	<HEAD>
		<!-- layout styles, child before parent, recursively -->
		<LINK href="style/compo_list-view.css" rel="stylesheet" type="text/css" />
		<LINK href="style/page_index.css" rel="stylesheet" type="text/css" />
	</HEAD>
	<BODY>
		<DIV class="list-view"></DIV>
	</BODY>
</HTML>

See CSS Style for details.

JavaScript

WOOD uses plain ECMA Script to define component behavior and for dynamic manipulation of the component layout. There is no restriction on version as long it is supported by target browsers.

Component behavior is mainly implemented using event handlers registered to browser scripting engine whereas layout manipulation is achieved via the CSS classes. Whenever reasonable, developer is advised to avoid direct assignment of the CSS styles and to refrain from direct DOM manipulation.

JavaScript files are component source files and supports all at-meta references, less layout parameter reference.

this.section.innerHTML = "@text/message";
this.logo.src = "@image/logo";
this.audioPlayer.src = "@audio/beep";
document.title = "@string/app-name";

Core JavaScript file is included automatically into generated page header. Component supports supplementary JavaScript files but they should be declared on component descriptor using syntax <script src="compo/path/script.js" />. For third party JavaScript files replace src value with full URL.

Widget

Widget is a primitive component that has only layout file therefore does not require a separated directory. For this reason we commonly refer widget's layout file as widget file.

For example a select with options initialized and reused in multiple pages. An widget can be used only for inclusion and parent component uses the same wood:compo="component/path" operator as for normal component.

Even if an widget is not reused between multiple parent components, using a widget instead of inline coding helps in HTML code maintainability, e.g. a select with a long list of options. It is recommended to store such 'private' widget inside component directory, although strictly speaking widget is not one of the component files, see Subcomponent.

Subcomponent

It is allowed to store a component directory inside another component. Usually these components are in an aggregation relation but is not mandatory.

Here we have a parent component compo/article. Inside its directory we store a child component compo/article/section.

  • compo/article/article.htm
<!-- parent component -->
<article xmlns:wood="js-lib.com/wood">
	<!-- child reference element -->
	<section wood:compo="compo/article/section"></section>
</article>
  • compo/article/section/section.htm
<!-- child component -->
<section></section>

Subcomponents can be used for widgets too: it is allowed to store the widget file inside a component directory.

Here we have a parent component compo/article. Inside its directory we store a widget file compo/article/select/select.htm, with component path compo/article/select.

  • compo/article/article.htm
<!-- parent component -->
<article xmlns:wood="js-lib.com/wood">
	<!-- child reference element -->
	<section wood:compo="compo/article/select"></section>
</article>
  • compo/article/select/select.htm
<!-- child component -->
<select>
	<option>...</option>
</select>

Using subcomponents allows to 'hide private components' but there is no formal constraint. It is merely a good practice recommendation but not enforced by build tool.

Note that subcomponents, be it component directories or widget files, are not strictly part of component; when searching for component files subcomponents are ignored.


Last updated 9/8/2022.

⚠️ **GitHub.com Fallback** ⚠️