(first posted: Jul 06, 2006)
(1370 Reads)
keywords: blocks tabs
Permalink
Tabbed Blockgroups - How It Works
Overview
Tabbled blocks consist of the tabs, and the blocks. Tabs are created using the Xaraya tabnavs styles, each tab containing the name of a block. The blocks are displayed below the tabs. All the blocks are hidden (display:none) except the open one. Javascript is used in the tabs buttons to display the current block.
ID's are dynamically generated based on the block name, so we can identify each tab and corresponding block. The naming convention is xar-tabblocks-BLKNAME for the block div, and xar-tabblocks-BLKNAME-tab for the block's tab.
The resulting structure of document object is as follows:
<div class="xar-tabblocks"><div class="xar-tabblocks-tabs">
<dl class="xar-tabs">
for each block in the blockgroup:
<dd id="xar-tabblocks-BLKNAME-tab"> block title </dd>
...
</dl>
</div>
<!-- blockgroup name="tabbed" -->
for each block in the blockgroup:
<div id="xar-tabblocks-BLKNAME" class="xar-tabblocks-block">
<div class="xar-block-head">
<div class="xar-block-title"> block title </div>
</div>
<div class="xar-block-body">
#$content#
</div>
<div class="xar-block-footer"></div>
</div>
</div>
...
</div>
Blockgroups use the tabbed.xt Outer Template
The template "tabbled.xt" goes in you theme's mytheme/blocks/ directory, and will be used as the "outer" template for each block in the blockgroup.
In the template, we surround the block with a div with class="xar-tabblocks-block" so each block in the group can be styled similarly.
We'll also ensure that each block is given a unique ID, in the form "xar-tabblocks-NAME" where NAME is the name of that block. Thus, the wrapper div looks like:
<xar:set name="divid">"xar-tabblocks-" . $name</xar:set>
<div id="#$divid#" class="xar-tabblocks-block">
...
</div>
Specifically, as an example, here's my full template, mytheme/blocks/tabblocks.xt
<xar:set name="divid">"xar-tabblocks-" . $name</xar:set>
<div id="#$divid#" class="xar-tabblocks-block">
<xar:if id="title_condition" condition="!empty($title)">
<div class="xar-block-head">
<div class="xar-block-title">
<xar:var name="title"/>
</div>
</div>
</xar:if>
<div class="xar-block-body">
<xar:var name="content"/>
</div>
<div class="xar-block-foot"></div>
</div>
3. Create an include template to render the blockgroup, "tabblocks.xt"
The blockgroup will be included in your page using <xar:template type="theme" file="tabblocks" />. Now we'll create this template, mytheme/includes/tabblocks.xt
This is the meat of how this works. There are several parts to this file.
3.A. Link exernal files
First, we'll make sure the javascript and stylesheets will be inserted into the page
<!-- <xar:base-include-javascript module="base" filename="tabblocks.js" position="head" /> -->
<xar:style scope="module" module="base" file="navtabs" />
<xar:style scope="module" module="base" file="tabblocks" />
Bug alert: the xar:base-include-javascript doesnt actually work here (not sure why), so it should be included in the template that calls this template (as shown later on).
The navtabs.css is a standard Xaraya file. You can make your own version, and/or override specific styles specific to the tabbed block groups in the optional tabblocks.css file.
3.B. Generate the tabs
The second section generates the tabs themselves. We're usomg the same navtabs used by Xaraya, which uses <dl> and <dd> tags for each tab. All the tabs are wrapped in a div class="xar-tabblocks-tabs". Each tab is given a unique ID, in the form "xar-tabblocks-NAME-tab". Thus, the tabs are created with the following code:
<xar:set name="grp">xarModApiFunc('blocks','user','groupgetinfo',array('name'=>'tabbed'))</xar:set>
<div class="xar-tabblocks-tabs">
<dl class="xar-tabs">
<xar:foreach in="$grp['instances']" value="$blk">
<xar:set name="b_nam">$blk['name']</xar:set>
<xar:set name="b_id">"xar-tabblocks-" . $b_nam . "-tab"</xar:set>
<dd id="#$b_id#"><a href="javascript:void()" onclick="return tabblocksDisplay('xar-tabblocks', '#$b_nam#');">#$blk['title']#</a></dd>
</xar:foreach>
</dl>
</div>
Note, when you click on a tab, a javascript function is called, tabblocksDisplay, with arguments for the prefix of the tabbed block class, and the name of the block that's been selected. (see below). This function hides all the tab blocks (display:none) except the selected one. And it gives the current tab a class of "active" so it can be highlighted.
3.C Insert the blockgroup
The next step inserts the blockgroup itself:
<xar:blockgroup name="tabbed" />
3.D Make the first tab block visible
Finally, we want to hide all the blocks except the first one using some javascript.
<xar:set name="first">reset($grp['instances'])</xar:set>
<script type="text/javascript">
tabblocksDisplay('xar-tabblocks','" . $first['name'] . "');
</script>
Actually, we want to enclose the js in html comments to accomodate non-js browsers, in which case php doesnt see the commented out variable , so we do it this way,
<xar:set name="first">reset($grp['instances'])</xar:set>
<xar:set name="js">"<script type=\"text/javascript\">\r\n <!-- \r\ntabblocksDisplay('xar-tabblocks','" . $first['name'] . "');\r\n //--> \r\n</script>"
</xar:set>
#$js#
Further fanciness, if you wanted/needed to open this tab via a URL GET var, you could pass the block name as a variable, say ?tab=BLKNAME, then
<xar:set name="tabname">xarRequestGetVar('tab')</xar:set>
<xar:if condition="empty($tabname)">
<xar:set name="first">reset($grp['instances'])</xar:set>
<xar:set name="tabname">$first['name']</xar:set>
</xar:if>
<script type="text/javascript">
tabblocksDisplay('xar-tabblocks','" . $tabname . "');
</script>
3.E Disable tabs in preview
Note, if you want to disable the tabbed view , for example , when the page is viewed during an admin function such as previews, you can disable it in the template wit h the following code:
<xar:set name="requestInfo">xarRequestGetInfo()</xar:set>
<xar:if condition="$requestInfo[1] eq 'admin'">
<xar:blockgroup name="tabbed" />
<xar:else />
... normal template ...
</xar:if>
The javascript file, tabblocks.js
A little bit of javascript handles the onclick on the tabs. It defines two functions
- tabblocksClearAll - hides all the block divs y setting display:none, and no tabs are active
-
tabblocksDisplay - shows the selected block by setting it to display:block , and gives the current tab a class="active"
This file, tabblocks.js should be placed in mytheme/modules/base/includes/tabblocks.js
// looks for block div with id=tabpre-xxx and tabs with id=tabpr-xxx-tab
// hide all blocks with id=tabpre-xxx and unstyle it's tab
function tabblocksClearAll(blockpre)
{
var divs = document.getElementsByTagName("div");
for (i=0; i<divs.length; i++) {
var div = divs;
var id = div.id;
if (id.indexOf(blockpre) != -1) {
div.style.display = 'none';
elem = document.getElementById(id + '-tab');
elem.setAttribute("class","");
elem.setAttribute("className","");
}
}
return false;
}
// display block named id (id=blocpre-id) and active style its tab
function tabblocksDisplay(blockpre, id)
{
tabblocksClearAll(blockpre);
elem = document.getElementById(blockpre + '-' + id);
elem.style.display = 'block';
elem = document.getElementById(blockpre + '-' + id + '-tab');
elem.setAttribute("class","active");
elem.setAttribute("className","active");
return false;
}
Define our styles
You could run this without overriding any of the styles, but you'll see some adjustments will be necessary. Here's what I see as a good starting place to put in your themes style.css file
/* === tabblocks === */
.xar-tabblocks { /* contains entire includes/tabblocks.xt */
margin: 1em;
background-color: white;
}
.xar-tabblocks-tabs { /* contains the tabs */
width:90%; /* for ie, tabs were pushing width>100% */
margin:0 1em;
}
.xar-tabblocks-tabs .xar-tabs { /* override the xar defaults */
margin-bottom:0;
padding-bottom:0;
background-color: white;
}
.xar-tabblocks-block {
margin-top: 0;
background-color: #ccc;
border: solid #aaa 1px;
}
.xar-tabblocks-block .xar-block-body h2 {
margin-top: 0;
}
/* override base/navtabs.css */
.xar-tabs a:link, .xar-tabs a:visited {
color: green;
font-weight: bold;
}
.xar-tabs a:hover {
color: green;
text-decoration: underline;
background-color: transparent;
}
* html dl.xar-tabs dd.active {
margin-bottom:3px;
}
dl.xar-tabs dd.active a {
color: red;
border-color: red;
font-weight: bold;
}
dl.xar-tabs dd.active a:hover {
text-decoration: underline;
}
Add the Tabbed Blockgroup to your Page Template
For example, if this is a home page and you have the base module as the default module, then add the following lines to your file mytheme/modules/base/user-main.xt
<xar:base-include-javascript module="base" filename="tabblocks.js" position="head" />
<xar:template type="theme" file="tabblocks" />
Note, the base-include-javascript is called here rather than inside tabblocks.xt because it doesnt seem to work inside there.
There are no comments attached to this item.



