A dynamically controlled channel
I have often been disappointed in how the typical custom channel is handled within Luminis. Well the server is chugging away at obtaining the content for display it is holding up the rendering of the tab that they channel is on.
As such I have over the past many months looked at ways that I could develop channels that were more dynamic. The channel would quickly come up and then fetch the required data to display to the user.
To this end I have developed a new custom channel that I am for now calling the AJAX channel (hope to soon work out how to add it as a new channel type to Luminis). This channel is a very basic one that takes one channel parameter called js_url. The value of this parameter is the path to what I am terming 'a control javascript'.
This control javascript will then get dynamically added to the DOM in the browser. The channel will also append to the URL to parameters c and d. Parameter c will contain the subscribed id of the channel on the tab, while parameter d will contain the id of the DIV that should get updated by the javascript.
The URl to the controlling javascript should really be to a JSP, PHP, or PERL script that outputs the required javascript. This way those languages can pick up the two parameters supplied and use them when producing the javascript the browser will use.
Going forward the channel development we will do here at the U of M will primarily consist of servlets ran from within the Luminis session scope (so that we have access to user details) and output the controlling javascript as well as various JSON objects used by the javascript to produce the display for the user.
I'll try and put together a simple Hello World type example for this next week. Also as we move forward a number of existing channel we have posted here will be switched to this style (announcement channel, group activity, etc).
You can find the source code here:
http://svn.lumdev.net/Luminis/Channel%20Repository/ca.umanitoba.channel.ajax/
Install
- Copy um_ajax.car to $CP_WEBINF/cars and restart the server
- Define a new custom channel setting the class path to ca.umanitoba.luminis.channels.ajax.AjaxRequests and on the channel parameters screen add a parameter called js_url with a value of the path to your controlling javascript
Change log
- July 30, 2008
- The XSL was referencing an animated GIF on the server while the JavaScript was initially fetching information. I have moved this graphic into the car so that you do not need to add a graphic to your server
- July 25, 2008
- Initial upload

Implementation
Got it working! The missing piece for me is what the remote URL needed to contain. After some playing around, I did a quick test of:
document.getElementById('<?php echo $_REQUEST['d'] ?>').innerHTML = 'test';
on a PHP server we have laying around. As promised, your car file inserted a DIV with an id containing the same value. The next step would be for this car file to automatically pass the username, as well as a session token, or some lockdown mechanism to prevent someone from just directly accessing another user's possibly sensitive data.
Nice! We did something similar in pure Javascript:
//Get the channel instance
var handle = new Date().getTime();
document.write('<span style="display:none;" id="' + handle + '"></span>');
var channel_id = document.getElementById(handle).parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.parentNode.firstChild.firstChild.nextSibling.innerHTML
channel_id = channel_id.substring(channel_id.indexOf('uP_root=')+8,channel_id.indexOf('&'));
//Draw the inline frame
document.write('<iframe frameborder="0" onload="resizeFrame(this);" id="' + handle + '_i" src="http://made_up_url%3FchannelInstance=' + channel_id + '"></iframe>');
All of that ugly parentNode stuff is procedurally grabbing the channel ID from the channel controls (maximize, minimize, delete) and passes it to a remote URL. We got stuck at passing the username part because this information cannot be accessed in pure Javascript. Your channel looks promising though.
PS: I am offended that you didn't list Ruby as a backend option :)
RUBY?!? :)
I have been trying to think of a way to pass a username or other details in a secure fashion to the remote script. To date I have not come up with a means to do that, but fortunately for us most of our channels are Java based ones ran within the Luminis session scope where we can query the Luminis internals for user data and therefore restrict the data the user has access to.
I think Todd at USask has done some work allowing services to run on non Luminis machines but read data from the Luminis session however I have not had time to look into this yet, but perhaps combining that with this is possible.
PS: I am offended that you didn't list Ruby as a backend option :)
At least you didn't say Python ;)
Reading from another websites session
Interesting, I didn't think this was possible for security reasons. The more I think about it, the more I am convinced that the only way is to create a GCF connector for the external system, and check the browser's referer for a match to our production DNS.
A new remote app channel soon to arrive...
I have in the works a new channel type that behaves like Facebook does in terms of loading remote applications. Essentially what happens is the channel code (which could be ported easily to portlet code for LP5) renders an IFrame where the source URL points to your web application. Included in the URL is a number of parameters to represent the user's request including their userid and a checksum key.
As mentioned the idea was taken from how Facebook passes you to a remote application server to render the app you wish to use (i.e. Farmville). I have yet to bundle this up in such a way to share with everyone here but if you want to read up a bit on it you can check the documentation I did up for our local developers by heading over to here:
https://wiki.cc.umanitoba.ca/tw/tiki-index.php?page=Remote_Web_Application_Integration%28JUMP%29&structure=Jump
Javascript multiline string
I have been working with this AJAX channel a little more over the last few days. When I create my channels, I develop all of the HTML first, then when it is ready for production, I remove all of the html, head, body tags, and replace with this:
var v = ""+<r><![CDATA[ ...html output... ]]></r>; $('channel_id').innerHTML = v;The first line creates a Javascript variable (since with output is rendered inside a script tag) and uses the CDATA object to create a special Javascript multiline string.
Next the original HTML output goes inside, completely unaltered (you don't even have to escape quotes!)
Next, I finish the CDATA object by closing the brackets.
Finially, I grab the value passed in for "D" (server side), and using Prototype.js, I get this object using the special notation "$()" and replace the innerHTML with the new variable "v".
Very neat
Had not thought of doing something like that. This makes things easier for some of the developers we have over here that are not quite ready to use JS to dynamically modify the DOM.
Thanks for the idea. :)