[General] [ANN] HTML Layout and Rendering Engine and a Form Editor for Morphic
ALT Mobile DEV
dev at altmobile.com
Tue Jan 29 13:22:10 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
(morphicContainer)
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
transformations.
*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.
--Zaid
http://altmobile.com/Home.html
More information about the lively-kernel
mailing list