<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>BlackBox : Portal/Portlet work continues</title>
    <link>http://www.warneronstine.com/blog/articles/2008/03/29/portal-portlet-work-continues</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Where technology and art disappear</description>
    <item>
      <title>Portal/Portlet work continues</title>
      <description>&lt;p&gt;So I thought I&amp;#8217;d update everyone on my progress so far with the Portal/Portlet component I&amp;#8217;ve been working on, as well as some of the issues I&amp;#8217;ve run into.&lt;/p&gt;

&lt;p&gt;Normally I would have posted this to my &lt;a href="http://jroller.com/warneronstine/"&gt;Tapestry 101&lt;/a&gt; blog but I&amp;#8217;m going to try and consolidate my blogs together and I&amp;#8217;m extremely tired of JRoller&amp;#8217;s broken Textile formatting, such a pain in the ass (I have fallen in love with Markdown and code markup, it rocks!). I&amp;#8217;ll be crossposting this, but soon I will stop updating the JRoller blog.&lt;/p&gt;

&lt;p&gt;I now have a basic implementation of the Portal component complete and it consists of the following classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Portal.java - Stores a TreeSet of columns&lt;/li&gt;
&lt;li&gt;Portal.html - Adds in the portlet controls div and some custom CSS stuff (which I&amp;#8217;ll talk about shortly)&lt;/li&gt;
&lt;li&gt;PortalColumn - Stores a TreeSet of Portlets plus some configuration for viewing (width and background color)&lt;/li&gt;
&lt;li&gt;Portlet - Stores the Portlet title, content and it&amp;#8217;s location&lt;/li&gt;
&lt;li&gt;portal/scripts/
&lt;ul&gt;
&lt;li&gt;Portal.script - includes all the JavaScript files and does some dynamic stuff (coming up shortly)&lt;/li&gt;
&lt;li&gt;prototype/scriptaculous scripts&lt;/li&gt;
&lt;li&gt;portal_hooks.js - the hooks for the portal actions (close, move, etc.)&lt;/li&gt;
&lt;li&gt;portal.js - the actual JavaScript for the portal functionality that can be called by the portal_hooks.js file&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;portal/css - portal.css&lt;/li&gt;
&lt;li&gt;portal/images - all the images for the portal controls and rendering (rounded corners)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ok, so that&amp;#8217;s the basics here are some of the specifics.&lt;/p&gt;

&lt;h2&gt;Portal.script&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;input-symbol key="columns" required="yes" /&amp;gt;
&amp;lt;initialization&amp;gt;
 function init() {    
 portal = new Xilinus.Portal("#portal div", {onOverWidget: onOverWidget, onOutWidget: onOutWidget, onChange: onChange, onUpdate: onUpdate, removeEffect: Effect.SwitchOff}); 
   &amp;lt;foreach key="column" expression="columns"&amp;gt;
    &amp;lt;foreach key="portlet" expression="column.portlets"&amp;gt;
    portal.add(new Xilinus.Widget().setTitle('${portlet.title}').setContent('${portlet.content}'), ${column.index});
    &amp;lt;/foreach&amp;gt;
   &amp;lt;/foreach&amp;gt; 
   // Add controls buttons
   portal.addWidgetControls("control_buttons");
 }
 Event.observe(window, "load", init);
&amp;lt;/initialization&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What I&amp;#8217;m doing here is creating a new Portal (from Xilinus) and then I&amp;#8217;m looping through each column and then each portlet inside of the column to add it&amp;#8217;s content.&lt;/p&gt;

&lt;p&gt;I dive into the hackish parts after the break.&lt;/p&gt;

&lt;h2&gt;Portal.html&lt;/h2&gt;

&lt;p&gt;This part contains some of the CSS hackish-ness I was hoping to avoid.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;span jwcid="@Script" script="Portal.script" columns="ognl:columns"/&amp;gt;
&amp;lt;div id="portal"&amp;gt;
&amp;lt;div jwcid="@For" value="ognl:column" source="ognl:columns"&amp;gt;

    &amp;lt;div jwcid="@Any" id="ognl:'widget_col_' + column.index" /&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This first part just adds in the &lt;code&gt;Portal.script&lt;/code&gt; and then declares the html &lt;code&gt;div&lt;/code&gt; element we want to use (this element is used throughout the CSS and JavaScript files. The next piece loops over the &lt;code&gt;TreeSet&lt;/code&gt; of columns and outputs one specially-named &lt;code&gt;div&lt;/code&gt; for each column.&lt;/p&gt;

&lt;p&gt;&lt;div id="control_buttons" style="display:none;float:left;"&gt;
   &lt;a href="#" id="edit_button"&gt;&lt;/a&gt;
   &lt;a href="#" onclick="removeWidget(this); return false;" id="delete_button"&gt;&lt;/a&gt;
    &lt;div id="toggle"&gt;&lt;a href="#" onclick="minimizeWidget(this);" id="min_button"&gt;&lt;img jwcid="@Any" src="ognl:minimizeButton" alt="Collapse Portlet" border="0"/&gt;&lt;/a&gt;&lt;/div&gt;
 &lt;/div&gt;&lt;/p&gt;

&lt;p&gt;This just creates the HTML for the portlet controls (don&amp;#8217;t know how customizable I&amp;#8217;m going to make this yet).&lt;/p&gt;

&lt;p&gt;Now comes the hack.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;style type="text/css"&amp;gt;
&amp;lt;span jwcid="@For" value="ognl:column" source="ognl:columns" renderTag="false"&amp;gt;
#widget_col_&amp;lt;span jwcid="@Insert" value="ognl:column.index"/&amp;gt; { 
  float:left;
  width: &amp;lt;span jwcid="@Insert" value="ognl:column.width"/&amp;gt;;  
  background:&amp;lt;span jwcid="@Insert" value="ognl:column.backgroundColor"/&amp;gt;;
}
&amp;lt;/span&amp;gt;
#edit_button {
  background: url(&amp;lt;span jwcid="@Insert" value="ognl:editButton.buildURL()"/&amp;gt;);
}
#delete_button {
  background: url(&amp;lt;span jwcid="@Insert" value="ognl:removeButton.buildURL()"/&amp;gt;);
}
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here you see I had to do some inline styles so that I could add in some new attributes for the columns, as well as images for the control buttons. I posted a query to the mailing list about 2 weeks ago, asking if there was anything like RCSS (Ruby CSS) where you could actually use Ruby to generate CSS stylesheets - which is exactly what I need here.&lt;/p&gt;

&lt;p&gt;After talking with Howard there did not appear to be any good way of going about doing this. One solution discussed was to let the user drop in a replacement stylesheet, but to me this seems silly, they don&amp;#8217;t need to recreate the whole style sheet. &lt;/p&gt;

&lt;p&gt;Another solution was to create a Tapestry page that acted like a CSS file. This still holds some promise, but is technically going to be a bear to implement due to the fact that we have to change the mime-type. The kicker in all of this though is that this isn&amp;#8217;t going to be easier in Tapestry 5, at least not right away.&lt;/p&gt;

&lt;p&gt;The other issue that I have with implementing this is what a pain it is to work with JavaScript in this environment and now I completely understand why it wasn&amp;#8217;t really worked with before. Customizing the JavaScript that I need to output is a truly a pain, using XML to do my looping for me feels&amp;#8230;wrong. If there are two areas I would like to contribute to these are it - making JavaScript and CSS more first-class citizens. Outputting HTML isn&amp;#8217;t everything you do in a Web application.&lt;/p&gt;

&lt;h2&gt;What&amp;#8217;s left?&lt;/h2&gt;

&lt;p&gt;Not quite done with this yet. I still have the following items to clear up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Need to make the &lt;code&gt;Portal&lt;/code&gt;, &lt;code&gt;Portlet&lt;/code&gt;, and &lt;code&gt;PortalColumn&lt;/code&gt; classes persistable&lt;/li&gt;
&lt;li&gt;Once that&amp;#8217;s done I need to modify the JavaScript hooks so that some kind of Ajax call happens whenever a user moves a portlet, adds or removes a portlet so that their selected portlets are saved in the database&lt;/li&gt;
&lt;li&gt;Need a new Page so that a user can see all possible portlets to add to their custom page
&lt;ul&gt;
&lt;li&gt;For this page was kind of thinking of doing a slick sliding door effect, dunno yet&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Add in some further customizations&lt;/li&gt;
&lt;li&gt;Replace default button images with ones that are easier to read/understand and fit with our internal scheme a bit better (these are customizable)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I&amp;#8217;m trying to get this code Open-Sourced, so it may take a little bit to get this code available but it shouldn&amp;#8217;t be too much of a problem (and we have some other cool little items we&amp;#8217;re going to release as well - just need to clean them up).&lt;/p&gt;</description>
      <pubDate>Sat, 29 Mar 2008 08:32:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:eb6d7081-01d3-4967-bcc7-9b4a0185e28b</guid>
      <author>Warner Onstine</author>
      <link>http://www.warneronstine.com/blog/articles/2008/03/29/portal-portlet-work-continues</link>
      <category>programming</category>
      <category>tapestry</category>
      <category>portal</category>
      <trackback:ping>http://www.warneronstine.com/blog/articles/trackback/316</trackback:ping>
    </item>
  </channel>
</rss>
