Developing Portlets and Integration Web Services

Adaptive Portlet Design Patterns: Broadcast-Listener

The Broadcast-Listener design pattern is similar to the Master-Detail pattern. Users can select an item or perform some other action in a "broadcast" portlet, which causes the content in other related "listener" portlets to be redrawn. The major difference is that the Broadcast-Listener pattern relies on the PCC component to raise an event when an action is performed in the "broadcast" portlet. One or more "listener" portlets can respond to this event and update their content accordingly.

Use the Broadcast-Listener adaptive portlet design pattern when there is a loose coupling between portlets. In the example below, the "broadcast' portlet (broadcastlistener_portletA.html) displays a list of prospects. Clicking on a link in the portlet displays information about the prospect in two "listener" portlets (broadcastlistener_portletB.html and broadcastlistener_portletC.html). For more tightly coupled portlet functionality, see the Master-Detail pattern.

To see this design pattern in action, go to the Adaptive Portlets Community on the portal and click Broadcast-Listener.

broadcastlistener_portletA.html

<!-- jsxml includes -->
<a id="imgServerHref" href="pt://images/plumtree" style="display:none"></a>
<script type="text/javascript"
src="pt://images/plumtree/common/private/js/PTLoader.js"></script>
<script type="text/javascript">
var oImgServer = new Object();
oImgServer.location = document.getElementById('imgServerHref').href;
var imageServerURL = document.getElementById('imgServerHref').href;
var imageServerConnectionURL = oImgServer.location;
new PTLoader(imageServerURL, imageServerConnectionURL).include('jsxml','en');
</script>

<!-- Inline JS helper functions -->
<!--
NOTE:
It is standard practice to use namespace tokens
(eg: <pt:nameSpace pt:token="$$TOKEN$$" xmlns:pt="http://www.plumtree.com/xmlschemas/ptui/"/>)
to ensure unique global JavaScript function and object names.
For simplicity, we do not do that here.
-->

<script defer type="text/javascript" id="broadcast-listener-portlet-A-script">

// Function that raises an event through the PCC when a prospect is selected
raiseEventOnSelectedProspect = function(prospectId)

{
document.PCC.RaiseEvent('urn:schemas.plumtree.com:prospect', 'prospectSelected', prospectId);
}

</script>

<!-- The prospect list -->
<b>Select a prospect:</b>
<ul>
<li><a href="#" onclick="raiseEventOnSelectedProspect(1); return false;">Acme Corp.</a></li>
<li><a href="#" onclick="raiseEventOnSelectedProspect(2); return false;">Foo, Bar, and Baz, LLC</a></li>
<li><a href="#" onclick="raiseEventOnSelectedProspect(3); return false;">World Wide Widgets, Inc.</a></li>
</ul>

broadcastlistener_portletB.html

<!-- jsxml includes -->
<a id="imgServerHref" href="pt://images/plumtree" style="display:none"></a>
<script type="text/javascript"
src="pt://images/plumtree/common/private/js/PTLoader.js"></script>
<script type="text/javascript">
var oImgServer = new Object();
oImgServer.location = document.getElementById('imgServerHref').href;
var imageServerURL = document.getElementById('imgServerHref').href;
var imageServerConnectionURL = oImgServer.location;
new PTLoader(imageServerURL, imageServerConnectionURL).include('jsxml','en');
</script>

<!-- Inline JS helper functions -->
<!--
NOTE:
It is standard practice to use namespace tokens
(eg: <pt:nameSpace pt:token="$$TOKEN$$" xmlns:pt="http://www.plumtree.com/xmlschemas/ptui/"/>)
to ensure unique global JavaScript function and object names.
For simplicity, we do not do that here.
-->

<script defer type="text/javascript" id="broadbast-listener-portlet-B-script">

// Function that listens for prospectSelected PCC events and gets
// content for the portlet based on the prospect id

refreshPortletB = function(prospectId)

{
// Specify the detail url

var detailUrl = '<pt:url xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/' pt:href='/cgi-bin/do-item-detail-portlet-B.jsc?prospectId='/>' + prospectId;

// Do the http get

var get = new PTHTTPGETRequest(detailUrl, handlePortletBResponse);
get.invoke();
}

document.PCC.RegisterForEvent('urn:schemas.plumtree.com:prospect', 'prospectSelected', refreshPortletB);

// Function that handles the response and redraws
handlePortletBResponse = function(response)

{
// Get the container whose contents we want to refresh

var container = document.getElementById('portletBContainer');

// Redraw it with the text of the response

container.innerHTML = response.responseText;
}

</script>

<div id="portletBContainer">
No prospect selected.
</div>

broadcastlistener_portletC.html

<!-- jsxml includes -->
<a id="imgServerHref" href="pt://images/plumtree" style="display:none"></a>
<script type="text/javascript"
src="pt://images/plumtree/common/private/js/PTLoader.js"></script>
<script type="text/javascript">
var oImgServer = new Object();
oImgServer.location = document.getElementById('imgServerHref').href;
var imageServerURL = document.getElementById('imgServerHref').href;
var imageServerConnectionURL = oImgServer.location;
new PTLoader(imageServerURL, imageServerConnectionURL).include('jsxml','en');
</script>

<!-- Inline JS helper functions -->
<!--
NOTE:
It is standard practice to use namespace tokens
(eg: <pt:nameSpace pt:token="$$TOKEN$$" xmlns:pt="http://www.plumtree.com/xmlschemas/ptui/"/>)
to ensure unique global JavaScript function and object names.
For simplicity, we do not do that here.
-->

<script defer type="text/javascript" id="broadbast-listener-portlet-C-script">

// Function that listens for prospectSelected PCC events and gets
// content for the portlet based on the prospect id

refreshPortletC = function(prospectId)

{
// Specify the detail url

var detailUrl = '<pt:url xmlns:pt='http://www.plumtree.com/xmlschemas/ptui/' pt:href='/cgi-bin/do-item-detail-portlet-C.jsc?prospectId='/>' + prospectId;

// Do the http get

var get = new PTHTTPGETRequest(detailUrl, handlePortletCResponse);
get.invoke();
}

document.PCC.RegisterForEvent('urn:schemas.plumtree.com:prospect', 'prospectSelected', refreshPortletC);

// Function that handles the response and redraws
handlePortletCResponse = function(response)

{
// Get the container whose contents we want to refresh

var container = document.getElementById('portletCContainer');

// Redraw it with the text of the response

container.innerHTML = response.responseText;
}

</script>

<div id="portletCContainer">
No prospect selected.
</div>

Next: Structured Response