[General] [ANN] HTML Layout and Rendering Engine and a Form Editor for Morphic

ALT Mobile DEV dev at altmobile.com
Sun Jan 27 22:41:45 CET 2008

Hi and thanks for making programming fun again.

I wanted to announce that over the holiday I wrote a layout and  
rendering engine for both HTML and XML content. Well it was really on  
Christmas day and it's not a WYSWYG tool but, it does enable some cool  
stuff. The background to this is that my company builds Web 2.0 mash- 
up tools and servers and we wanted to support Lively Kernel as a  
deployment client much as we support Apple Dashboard Widgets,  
Microsoft Vista Gadgets, Adobe AIR, Opera Widgets, etc.

So this is what's done so far:

1. Transform HTML to Morphic widgets. It seems that a goal of Morphic  
is to create a unified object environment hosted in a browser without  
using HTML UIs. Unfortunately, outside of the enterprise all of the  
useful data comes from the web in the form of HTML. Even RSS feeds  
contain HTML payloads. So unless we are going to shun the web as a  
primary data source or just asString/toString()/textContent() these  
data sources, we need to be able to intelligently and dynamically  
transform HTML elements such as paragraphs, lists, images, and tables  
to Morphic widgets. And of course, once they're in Morphic users/ 
developers can create magic.

With this as the underlying justification/premise, I created a simple  
to use API:

* Node.prototype.renderInMorphic = function(morphicContainer)

This is the entry point for rendering HTML elements in Morphic.  
Implemented in the XML DOM, the assumption is that users will use XHR  
to retrieve snippets of HTML and not hugely complex web pages. Our  
Dynamic Mashup Server can dynamically fix broken HTML and serve it up  
as XML. Nonetheless, there's some sample code on how to import HTML  
into this function to deal with raw HTML elements.

Once again, my goal is to enable snippets of HTML to be renderable in  
Morphic and not reimplement an HTML browser in Morphic. Web 2.0-type  
widgets is what I'm supporting even though, the code can be expanded  
to support full HTML pages.

* Element.prototype.renderXMLElementInMorphic = function  

This is the entry point for rendering fill-in-the-blank forms.  
Implemented in the XML DOM, the assumption is that users will use XHR  
to retrieve XML data and want to display and perhaps edit it. For  
example, let's say you have an address book generated from your  
corporate database or IM system and you wanted to display the XML  
content in a structured form. Or, you just have XML data that your  
want to edit. Currently, I haven't built support for flipping through  
collections of XML elements but that's not too hard.

It currently supports both attribute centric document (such as <name  
first='Joe' last='Public'/>) as well as element centric documents  
(such as <name><first>Joe</first><last>Public</last></name>) as well  
as a "Submit" button that is attached to an XHR to post back to the  
origin server. It's _not_ hooked into Morphic models as I needed more  
documentation on it and wanted to get the developers/community feedback.

The following are the supporting functions used by the  
renderInMorphic() function:

*Element.prototype.renderTABLE = function (morphicContainer)

Though Morphic does not implement a native table widget, this function  
will transform the HTML elements or text contained in the TDs of each  
TR row. The HTML layout engine will line up the Morphic wdgets  into  
corresponding rows. Rather than adopt the standard layout algorithm  
used in HTML, I implemented a layout more representative of how  
developers think heterogeneous widgets should align in a row.

I tested this against homogenous (eg. table of images from a remote  
web site) as well as heterogeneous table data.

*Element.prototype.renderIMG = function (morphicContainer)

This function transforms an IMG into an ImageButtonMorph. The HTML  
attributes SRC, WIDTH, HEIGHT, ALT, and TITLE are implements but  
BORDER is not yet. Since BORDER can be set by CSS or HTML, I wanted to  
comprehensively address CSS parsing but didn't want to use 3rd party  
JS libraries yet so that there was no conflict with the LK.

ALT and TITLE use the unsupported Morphic caption property.

If this IMG is contained by an A link, then an onMouseDown() event  
handler is attached to spawn a new window. This is typical with  
thumbnail image galleries. You should ensure that your browser allows  
popups. I did an alternative implementation that uses a popup DIV  
"window" to circumvent the external window but I wanted to see what  
the developers/community view as appropriate Morphic approach.

*Element.prototype.renderBR = function (morphicContainer)

This function creates a new row in the layout

*Element.prototype.renderEMBED = function (morphicContainer)

This function is implemented to support sound and perhaps other media.  
Our Dynamic Mashup Server can generate text-to-speech for any mash-up  
and it's implemented with HTML EMBED so that's the background. There's  
all these rules about the requirement for sound controls to be visible  
in HTML before being played. I took the easy approach and just launch  
a new window until the developers/community decided on a technique.

*Element.prototype.renderOL = function (morphicContainer)

This function supports both UL and OL element transformations to a  
CheapListMorph iff LI elements contain text and not IMG or other HTML  
elements such as other OL/UL, TABLE, etc. Currently there's no support  
for highly nested lists but a list of images or list of text content  
is supported. Stylized text LI elements will be striped and the text  
will be rendered as TextMorph. Other things such as a list of A links  
is also supported.

*Element.prototype.renderP = function (morphicContainer)

This function transforms HTML text containers such as P, B, H1 to a  
TextMorph. This function uses the helper function isTextContainer().  
The text content is extracted using the DOM's textContent and no style  
information (CSS or HTML) are used since I didn't see a rich text morph.

*Element.prototype.renderA = function (morphicContainer)

This function renders both text and IMG links by transforming to a  
label TextMorph or ImageButtonMorph as appropriate. Of course, style  
information is excluded from the TextMorph. A cute "external" icon is  
placed adjacent to the label since all links spawn a new window.

*Element.prototype.isTextContainer = function()

Used to determine if we should use a TextMorph during transformation.

*Element.prototype.isHTMLElement = function()

This function is used to determine if we perform HTML or XML  

*Element.prototype.isBlockLevelElement = function()

This function will be used in the future to by the layout engine

*Element.prototype.isInlineElement = function()

The opposite of isBlockLevelElement()

*Element.prototype.definesCSSDisplayAsBlockLevel = function()

This function will be used in the future to by the layout engine


The layout engine is called HTMLLayout in the code even though it's  
really a Morphic layout engine for HTML and XML elements. It defines  
the following functions:

* createNewRow: function ()

* addMorph: function (morph)

* addMorphToRow: function (morph, rowNumber)

* isFirstMorphInCurrentRow: function()

* isFirstMorphInRow: function(rowNumber)

* isFirstMorphInLayout: function()

* getTallestMorphInCurrentRow: function()

* getTallestMorphInRow: function(rowNumber)

* getFirstMorphPostionInNewRow: function()

* getFirstMorphPostionInRow: function(rowNumber)

* getNextMorphPostionInCurrentRow: function()

* getNextMorphPostionInRow: function(rowNumber)

* getNextPositionForElement: function (element)

* getWidestMorphInAllRows: function(morphPosition)

* computeWidthDifference: function (srcMorph, targetMorph)

* shiftMorphsInRow: function (rowNumber, units, xOrY)

* alignMorphInEachRow: function(morphPosition, eastOrWest)


As all pre-announcements disappoint, I built this against LK v.7 and  
don't want to delay shipping our commercial products with a port to  
the latest LK v .8 release, if it's needed. So hopefully in next few  
days/weeks all this stuff will be available for general use.



More information about the lively-kernel mailing list