HomePortals 3.1 Beta (Part 2)
A couple of days ago I wrote a post talking about the new iteration of the HomePortals framework. Today I want to continue talking about the new features for this release. In the previous article I posted an example template of a sample HomePortals page showcasing the new API, today I want to go over the example of provide more insight into the new objects and methods exposed by the framework.
As a reminder, here is the code from the previous template:
index.cfm
// initalize homePortals
application.homePortals = CreateObject("component","homePortals.Components.homePortals").init("/testPage/");
application.homePortals.getConfig().setContentRenderer("rss","testPage.rss");
// declare modules
feed1 = {
moduleType = "rss",
href="http://www.oscararevalo.com/rss.cfm",
title="Oscar Arevalo's Blog"
};
feed2 = {
moduleType = "rss",
href="http://www.railo.ch/blog/rss.cfm?mode=full",
title="Railo Blog",
maxItems="3"
};
feed3 = {
moduleType = "rss",
href="http://www.dzone.com/links/feed/frontpage/rss.xml",
title="DZone.com",
maxItems="10"
};
// assemble page
oPage = createObject("component","homePortals.Components.pageBean")
.init()
.setTitle("My News Page")
.setSkinID("rounded")
.addLayoutRegion("col1","column")
.addLayoutRegion("col2","column")
.addLayoutRegion("col3","column")
.addModule("mod1","col1",feed1)
.addModule("mod2","col2",feed2)
.addModule("mod3","col3",feed3)
;
// load and render page
oPageRenderer = application.homePortals.loadPageBean(oPage);
html = oPageRenderer.renderPage();
</cfscript>
<!--- output page --->
<cfoutput>#html#</cfoutput>
if you want to see how the final product looks, click here.
Ok, so lets start from the beginning:
Setting Up The Environment
Application.homePortals = CreateObject("component","homePortals.Components.homePortals").init("/testPage/");
This line initializes the homePortals environment as a singleton on the Application scope. This reads all the default configuration settings, initializes and loads a few objects, and leaves everything ready for you to start rendering your homePortals pages.
Each HomePortals instance is bound to a specific path, which is where your application is located. This path can be a directory off the webserver root (like in this example), or even be the webserver root itself. To declare an application at the root level, just call the init method as init("/")
After HomePortals is initialized, we use our instance to call any methods, render pages, modify settings or anything else you want to do.
Now we need to need to start customizing our HomePortals instance to do whatever we want. Since what we want to do in our example is render a few RSS feeds, we need to show HomePortals how to do this. The way we do this is by adding "ContentRenderers". A Content Renderer is a little widget that is responsible for generating some kind of content. This content can be anything: rss feeds, calendars, external HTML content, cfincludes, etc. All content renderers are implemented as CFCs and must extend homePortals.components.contentTagRenderer. The details of their implementation go a bit beyond this example, but basically they just generate whatever output they need and return it using an output buffer.
You can take a look at the rss.cfc component included in the example files to see how a contentRenderer is implemented.
The following line illustrates how we can programmatically tell HomePortals about the content renderer that we want to use:
Here we are declaring a content renderer named "rss" and give the path to the corresponding CFC in dot-notation form. Note that you can define as many content renderers as you want or need.
That's all the environment configuration that we need. Now we can building our page.
Building a Page
HomePortals is all about modular content and reusability. For that purpose, everything that goes into the page is defined outside of the page itself, so that it can be reused multiple times across a site or application. Although our example consists of only one single page, we will define our "modules" or content widgets individually. We already saw that it is the content renderer that is the one responsible for knowing HOW to render the output. So we only need to tell it WHAT to render. In our case we just want three different RSS feeds. Let's use the feeds for this blog, the Railo blog and the DZone blog.
Defining the page content is really simple, we just need to do it declaratively using common structures. We need to create a struct variable for each of the widgets we want to add to our page. There are few keys that are used internally and have special meanings like "moduleType" and "title", but everything else will be considered an "attribute" of the widget and will be available to the content renderer to customize the output. The only required key on the struct is "moduleType", which is how you tell HomePortals which content renderer to use. Since we declared our RSS renderer with to be named "rss", then that's what we need to use for each widget.
feed1 = {
moduleType = "rss",
href="http://www.oscararevalo.com/rss.cfm",
title="Oscar Arevalo's Blog"
};
feed2 = {
moduleType = "rss",
href="http://www.railo.ch/blog/rss.cfm?mode=full",
title="Railo Blog",
maxItems="3"
};
feed3 = {
moduleType = "rss",
href="http://www.dzone.com/links/feed/frontpage/rss.xml",
title="DZone.com",
maxItems="10"
};
In this example we are defining the three widgets to use the same content renderer (rss) but there is no restriction here, you can mix and match module types as long as you tell HomePortals about them.
Now it's time to assemble the final page:
oPage = createObject("component","homePortals.Components.pageBean")
.init()
.setTitle("My News Page")
.setSkinID("rounded")
.addLayoutRegion("col1","column")
.addLayoutRegion("col2","column")
.addLayoutRegion("col3","column")
.addModule("mod1","col1",feed1)
.addModule("mod2","col2",feed2)
.addModule("mod3","col3",feed3)
;
Programmatically, all pages are represented as instances of the pageBean object. All the modifier methods in the CFC return the same instance, that way you can chain all your modifier methods together to form a mini DSL to define a page. I think each of the methods have pretty self-explanatory methods as to what each one does.
First, we are initializing the instance, then setting a page title, and setting a skin (this is a way to determine the look and feel of the entire page). Next we are defining three layout regions of type column, with names col1, col2 and col3. Finally we are assigning our widgets to each of the three columns with addModule(). The first argument is a unique identifier for the widget, the second is the layout region name where we want to place it and the third is the struct containing the widget attributes.
Rendering The Output
Finally is time to send something to the screen. This is done by the following lines:
oPageRenderer = application.homePortals.loadPageBean(oPage);
html = oPageRenderer.renderPage();
</cfscript>
We start by asking HomePortals to process our pageBean instance and prepare it for rendering. Here is where all the magic happens. HomePortals does its thing and the call to loadPageBean() returns an instance of a pageRenderer object. This is the guy responsible for actually spitting the HTML back to us, and HTML is what we get when we call its renderPage() method. Note that homePortals has not actually sent any content to the screen, it just has given us back the HTML for the page we declared, it is up to us to decide how that HTML will be used.
And so we output the generated HTML to our browser for the grand finale...
<cfoutput>#html#</cfoutput>
And here is a screenshot of how this actually looks:

Not bad for a few lines of code, isn't it?
On the next post I'll talk about other new features and fancy tricks.
There are no comments for this entry.
[Add Comment]