TO DO - Uize.Widget.HtmltCompiler
This is a TO DO document for the Uize.Widget.HtmltCompiler
module.
1. Add Support for Subclassing
Provide a mechanism whereby htmlt templates can extend other htmlt templates.
Consider the following widget classes...
MyNamespace.Widgets.MyWidget.Html | |
MyNamespace.Widgets.MyWidgetSubclass.Html |
SUPERCLASS
<div> <div id="foo"></div> <div id="bar"></div> </div>
SUBCLASS
<extend class="MyNamespace.Widgets.MyWidget.Html"> <inject where="foo" how="outer replace"> <div id="foo"> <div id="qux"/> </div> </inject> </extend>
1.1. Injection Modes
Content can be injected into the DOM of the superclass using any of the following injection modes...
inner bottom (default) | bottom | |
inner top | top | |
outer bottom | after | |
outer top | before | |
inner replace | content | |
outer replace | replace |
1.2. Challenges
Supporting subclassing presents a few challenges, including...
1.2.1. Testability of the Compiler
A special provision needs to be put in place in order for the HtmltCompiler module to be testable in unit tests, since the module can't on its own resolve loading of the superclass htmlt.
An appropriate way needs to be devised to structure the code in order to maintain a clean / clear interface and appropriate demarcation of responsibilities. In a way, this problem is similar to the problem of bindings and class features. The compiler expects the widget class with which the htmlt is associated to be supplied at the time the template is compiled. Therefore, it might be reasonable as well to supply the compiler with the htmlt markup for the superclass' template.
1.2.2. Determining the Template to Extend
The file builder for htmlt templates should ideally be able to determine the superclass htmlt template that is being extended without having to parse or compile an htmlt template.
This requirement is at odds with an approach where the superclass template that is to be extended by an htmlt template is declared inside the markup of the template. For one thing, this would require first parsing the htmlt template, discovering that it extends another htmlt template, then loading that template and proceeding with the compilation. Furthermore, the file builder should be able to determine the dependencies for a template with less computation and ideally without fully parsing the template, for the sake of the currentness determination for the template.
1.2.3. Refactoring Robustness
Theoretically, it should be possible to simply define an htmlt template for a widget class and not be concerned about which class in the inheritance chain actually explicitly defines the htmlt that would be extended.
Furthermore, the subclass should not be affected by changes in the class hierarchy up the inheritance chain.
1.2.4. Multiple Subclassing
It should be possible for an htmlt template to extend an htmlt template that is, itself, extending some other htmlt template.
In other words, it should be possible to have multiple levels of htmlt subclassing.
2. Improve Child Widget Syntax
Provide a more versatile syntax for declaring child widgets that allows the values of state properties to be specified using JSON formatted data...
TYPICAL
<child prop1Name="prop1Value" prop2Name="prop2Value"/>
JSON
<child> { prop1Name:'prop1Value', prop2Name:'prop2Value' } </child>
PROPERTY TAGS
<child> <property name="prop1Name" value="prop1Value"/> <property name="prop2Name" value="prop2Value"/> </child>
PROPERTY TAGS CONTAINING JSON
<child> <property name="prop1Name">"prop1Value"</property> <property name="prop2Name">"prop2Value"</property> </child>
CUSTOM PROPERTY TAGS
<child> <prop1Name value="prop1Value"/> <prop2Name value="prop2Value"/> </child>
CUSTOM PROPERTY TAGS CONTAINING JSON
<child> <prop1Name>"prop1Value"</prop1Name> <prop2Name>"prop2Value"</prop2Name> </child>
3. Achieve Parity for Bindings
Achieve parity for style bindings compiled to template code.
3.1. Implement Support for value Binding
How this binding type is compiled with have to be affected by the node type, since the current runtime binding logic leverages the setNodeValue
method, and this method is an abstraction that provides different handling for different node types.
3.1.1. Nodes Without Value Interface
For nodes without a value interface (such as div
tag or span
tag nodes), the value binding type will be compiled to an innerHTML replacement with literal value display (i.e. entity-escaped HTML delimiters).
3.1.2. Nodes With Value Interface
For some of the node types that can have this binding, it will not be easy to achieve a compiled template equivalent.
One example is a radio button list, where the binding on one node ID is actually affecting multiple nodes in a group of related nodes. Another example is a select tag, where the binding to the select tag would actually need to be compiled to bindings to the select tag's various child option tags. In both such cases, the target of the binding is not a single node, and so replacement expressions would have to be injected into one or more associated nodes.
It may also just be that some runtime bindings will simply have no compiled htmlt equivalent and will not be handled in the compiled templates. This may be ok if the runtime code synchronizes the UI state to the widget's state upon initial update of the UI.
4. Issues
4.1. Improve Style Binding Support for Pre-existing Properties
The current implementation of the style binding type supports pre-existing style properties by concatenating any pre-existing values of style attributes to the style bindings expressions.
If a pre-existing value for a style attribute contains a particular style property and there is also a binding to that property, then the resulting generated HTML from the compiled htmlt template will contain two occurrences of the property - firstly, the pre-existing property value and, secondly, the value from the binding. This works because the second value overrides the first value.
While the current approach works, it is inelegant. A better approach would be to parse the pre-existing style properties from the style attribute of a node to which there is one or more style type bindings. Then, any pre-xisting stype property values for which there are bindings would be removed from the parsed set of style properties. The resulting set would then be re-serialized to be concatenated with the style bindings expressions.
4.2. Fix Encoding Issue
Fix the issue where HTML entities that are being decoded to extended characters are not being re-encoded to HTML entities when the XML is serialized.
Perhaps there should be a few encoding options for the Uize.Util.Html.Encode.encode method...
encode all characters possible to entities | |
encode for attribute value target | |
encode for text node target | |
encoding all extended characters |