Code cleanup to implement the tabs handling (inside web pages) in one place. Added the ability to provide asynchronously loaded tabs (content must come from the same server).

SVN:trunk[3141]
This commit is contained in:
Denis Flaven
2014-05-06 13:42:18 +00:00
parent 678f982024
commit 7459ec4844
3 changed files with 393 additions and 177 deletions

View File

@@ -26,16 +26,14 @@
require_once(APPROOT."/application/webpage.class.inc.php");
class ajax_page extends WebPage
class ajax_page extends WebPage implements iTabbedPage
{
/**
* Jquery style ready script
* @var Hash
*/
protected $m_sReadyScript;
protected $m_sCurrentTab;
protected $m_sCurrentTabContainer;
protected $m_aTabs;
protected $m_oTabs;
private $m_sMenu; // If set, then the menu will be updated
/**
@@ -48,9 +46,7 @@ class ajax_page extends WebPage
$this->m_sReadyScript = "";
//$this->add_header("Content-type: text/html; charset=utf-8");
$this->add_header("Cache-control: no-cache");
$this->m_sCurrentTabContainer = '';
$this->m_sCurrentTab = '';
$this->m_aTabs = array();
$this->m_oTabs = new TabManager();
$this->sContentType = 'text/html';
$this->sContentDisposition = 'inline';
$this->m_sMenu = "";
@@ -58,41 +54,69 @@ class ajax_page extends WebPage
public function AddTabContainer($sTabContainer, $sPrefix = '')
{
$this->m_aTabs[$sTabContainer] = array('content' =>'', 'prefix' => $sPrefix);
$this->add("\$Tabs:$sTabContainer\$");
$this->add($this->m_oTabs->AddTabContainer($sTabContainer, $sPrefix));
}
public function AddToTab($sTabContainer, $sTabLabel, $sHtml)
{
if (!isset($this->m_aTabs[$sTabContainer]['content'][$sTabLabel]))
{
// Set the content of the tab
$this->m_aTabs[$sTabContainer]['content'][$sTabLabel] = $sHtml;
}
else
{
// Append to the content of the tab
$this->m_aTabs[$sTabContainer]['content'][$sTabLabel] .= $sHtml;
}
$this->add($this->m_oTabs->AddToTab($sTabContainer, $sTabLabel, $sHtml));
}
public function SetCurrentTabContainer($sTabContainer = '')
{
$sPreviousTabContainer = $this->m_sCurrentTabContainer;
$this->m_sCurrentTabContainer = $sTabContainer;
return $sPreviousTabContainer;
return $this->m_oTabs->SetCurrentTabContainer($sTabContainer);
}
public function SetCurrentTab($sTabLabel = '')
{
$sPreviousTab = $this->m_sCurrentTab;
$this->m_sCurrentTab = $sTabLabel;
return $sPreviousTab;
return $this->m_oTabs->SetCurrentTab($sTabLabel);
}
/**
* Add a tab which content will be loaded asynchronously via the supplied URL
*
* Limitations:
* Cross site scripting is not not allowed for security reasons. Use a normal tab with an IFRAME if you want to pull content from another server.
* Static content cannot be added inside such tabs.
*
* @param string $sTabLabel The (localised) label of the tab
* @param string $sUrl The URL to load (on the same server)
* @param boolean $bCache Whether or not to cache the content of the tab once it has been loaded. flase will cause the tab to be reloaded upon each activation.
* @since 2.0.3
*/
public function AddAjaxTab($sTabLabel, $sUrl, $bCache = true)
{
$this->add($this->m_oTabs->AddAjaxTab($sTabLabel, $sUrl, $bCache));
}
public function GetCurrentTab()
{
return $this->m_sCurrentTab;
return $this->m_oTabs->GetCurrentTab();
}
public function RemoveTab($sTabLabel, $sTabContainer = null)
{
$this->m_oTabs->RemoveTab($sTabLabel, $sTabContainer);
}
/**
* Finds the tab whose title matches a given pattern
* @return mixed The name of the tab as a string or false if not found
*/
public function FindTab($sPattern, $sTabContainer = null)
{
return $this->m_oTabs->FindTab($sPattern, $sTabContainer);
}
/**
* Make the given tab the active one, as if it were clicked
* DOES NOT WORK: apparently in the *old* version of jquery
* that we are using this is not supported... TO DO upgrade
* the whole jquery bundle...
*/
public function SelectTab($sTabContainer, $sTabLabel)
{
$this->add_ready_script($this->m_oTabs->SelectTab($sTabContainer, $sTabLabel));
}
public function AddToMenu($sHtml)
@@ -118,7 +142,7 @@ class ajax_page extends WebPage
{
header($s_header);
}
if (count($this->m_aTabs) > 0)
if ($this->m_oTabs->TabsContainerCount() > 0)
{
$this->add_ready_script(
<<<EOF
@@ -173,36 +197,7 @@ EOF
);
}
// Render the tabs in the page (if any)
foreach($this->m_aTabs as $sTabContainerName => $aTabContainer)
{
$sTabs = '';
$m_aTabs = $aTabContainer['content'];
$sPrefix = $aTabContainer['prefix'];
$container_index = 0;
if (count($m_aTabs) > 0)
{
$sTabs = "<!-- tabs -->\n<div id=\"tabbedContent_{$sPrefix}{$sTabContainerName}\" class=\"light\">\n";
$sTabs .= "<ul>\n";
// Display the unordered list that will be rendered as the tabs
$i = 0;
foreach($m_aTabs as $sTabName => $sTabContent)
{
$sTabs .= "<li><a href=\"#tab_{$sPrefix}{$sTabContainerName}$i\" class=\"tab\"><span>".htmlentities($sTabName, ENT_QUOTES, 'UTF-8')."</span></a></li>\n";
$i++;
}
$sTabs .= "</ul>\n";
// Now add the content of the tabs themselves
$i = 0;
foreach($m_aTabs as $sTabName => $sTabContent)
{
$sTabs .= "<div id=\"tab_{$sPrefix}{$sTabContainerName}$i\">".$sTabContent."</div>\n";
$i++;
}
$sTabs .= "</div>\n<!-- end of tabs-->\n";
}
$this->s_content = str_replace("\$Tabs:$sTabContainerName\$", $sTabs, $this->s_content);
$container_index++;
}
$this->s_content = $this->m_oTabs->RenderIntoContent($this->s_content);
// Additional UI widgets to be activated inside the ajax fragment ??
if (($this->sContentType == 'text/html') && (preg_match('/class="date-pick"/', $this->s_content) || preg_match('/class="datetime-pick"/', $this->s_content)) )

View File

@@ -1,5 +1,5 @@
<?php
// Copyright (C) 2010-2013 Combodo SARL
// Copyright (C) 2010-2014 Combodo SARL
//
// This file is part of iTop.
//
@@ -30,25 +30,21 @@ require_once(APPROOT."/application/user.preferences.class.inc.php");
/**
* Web page with some associated CSS and scripts (jquery) for a fancier display
*/
class iTopWebPage extends NiceWebPage
class iTopWebPage extends NiceWebPage implements iTabbedPage
{
private $m_sMenu;
// private $m_currentOrganization;
private $m_aTabs;
private $m_sCurrentTabContainer;
private $m_sCurrentTab;
private $m_sMessage;
private $m_sInitScript;
protected $m_oTabs;
public function __construct($sTitle)
{
parent::__construct($sTitle);
$this->m_oTabs = new TabManager();
ApplicationContext::SetUrlMakerClass('iTopStandardURLMaker');
$this->m_sCurrentTabContainer = '';
$this->m_sCurrentTab = '';
$this->m_aTabs = array();
$this->m_sMenu = "";
$this->m_sMessage = '';
$this->SetRootUrl(utils::GetAbsoluteUrlAppRoot());
@@ -203,16 +199,31 @@ EOF;
// unless their URL is equal to the URL of the page...
$('div[id^=tabbedContent] > ul > li > a').each(function() {
var sHash = location.hash;
var sCleanLocation = location.href.toString().replace(sHash, '').replace(/#$/, '');
$(this).attr("href", sCleanLocation+$(this).attr("href"));
var sHref = $(this).attr("href");
if (sHref.match(/^#/))
{
var sCleanLocation = location.href.toString().replace(sHash, '').replace(/#$/, '');
$(this).attr("href", sCleanLocation+$(this).attr("href"));
}
});
// Enable tabs on all tab widgets. The `event` property must be overridden so
// that the tabs aren't changed on click, and any custom event name can be
// specified. Note that if you define a callback for the 'select' event, it
// will be executed for the selected tab whenever the hash changes.
tabs.tabs({ event: 'change', 'show': function(event, ui) {
tabs.tabs({
event: 'change', 'show': function(event, ui) {
$('.resizable', ui.panel).resizable(); // Make resizable everything that claims to be resizable !
},
beforeLoad: function( event, ui ) {
if ( ui.tab.data('loaded') && (ui.tab.attr('data-cache') == 'true')) {
event.preventDefault();
return;
}
ui.jqXHR.success(function() {
ui.tab.data( "loaded", true );
});
}
});
@@ -551,7 +562,7 @@ EOF
$sNorthPane .= '<div id="admin-banner"><span style="padding:5px;">'.ExecutionKPI::GetDescription().'<span></div>';
}
$sSouthPane = '';
$sSouthPane = '<p>Peak memory Usage: '.sprintf('%.3f MB', memory_get_peak_usage(true) / (1024*1024)).'</p>';
foreach (MetaModel::EnumPlugins('iPageUIExtension') as $oExtensionInstance)
{
$sSouthPane .= $oExtensionInstance->GetSouthPaneHtml($this);
@@ -674,34 +685,7 @@ EOF
$sOnClick = " onclick=\"this.value='';this.onclick=null;\"";
}
// Render the tabs in the page (if any)
foreach($this->m_aTabs as $sTabContainerName => $m_aTabs)
{
$sTabs = '';
$container_index = 0;
if (count($m_aTabs) > 0)
{
$sTabs = "<!-- tabs -->\n<div id=\"tabbedContent_{$container_index}\" class=\"light\">\n";
$sTabs .= "<ul>\n";
// Display the unordered list that will be rendered as the tabs
$i = 0;
foreach($m_aTabs as $sTabName => $sTabContent)
{
$sTabs .= "<li><a href=\"#tab_{$container_index}$i\" class=\"tab\"><span>".htmlentities($sTabName, ENT_QUOTES, 'UTF-8')."</span></a></li>\n";
$i++;
}
$sTabs .= "</ul>\n";
// Now add the content of the tabs themselves
$i = 0;
foreach($m_aTabs as $sTabName => $sTabContent)
{
$sTabs .= "<div id=\"tab_{$container_index}$i\">".$sTabContent."</div>\n";
$i++;
}
$sTabs .= "</div>\n<!-- end of tabs-->\n";
}
$this->s_content = str_replace("\$Tabs:$sTabContainerName\$", $sTabs, $this->s_content);
$container_index++;
}
$this->s_content = $this->m_oTabs->RenderIntoContent($this->s_content);
if ($this->GetOutputFormat() == 'html')
{
@@ -892,62 +876,51 @@ EOF
ExecutionKPI::ReportStats();
}
public function AddTabContainer($sTabContainer)
public function AddTabContainer($sTabContainer, $sPrefix = '')
{
$this->m_aTabs[$sTabContainer] = array();
$this->add("\$Tabs:$sTabContainer\$");
$this->add($this->m_oTabs->AddTabContainer($sTabContainer, $sPrefix));
}
public function AddToTab($sTabContainer, $sTabLabel, $sHtml)
{
if (!isset($this->m_aTabs[$sTabContainer][$sTabLabel]))
{
// Set the content of the tab
$this->m_aTabs[$sTabContainer][$sTabLabel] = $sHtml;
}
else
{
// Append to the content of the tab
$this->m_aTabs[$sTabContainer][$sTabLabel] .= $sHtml;
}
$this->add($this->m_oTabs->AddToTab($sTabContainer, $sTabLabel, $sHtml));
}
public function SetCurrentTabContainer($sTabContainer = '')
{
$sPreviousTabContainer = $this->m_sCurrentTabContainer;
$this->m_sCurrentTabContainer = $sTabContainer;
return $sPreviousTabContainer;
return $this->m_oTabs->SetCurrentTabContainer($sTabContainer);
}
public function SetCurrentTab($sTabLabel = '')
{
$sPreviousTab = $this->m_sCurrentTab;
$this->m_sCurrentTab = $sTabLabel;
return $sPreviousTab;
return $this->m_oTabs->SetCurrentTab($sTabLabel);
}
/**
* Add a tab which content will be loaded asynchronously via the supplied URL
*
* Limitations:
* Cross site scripting is not not allowed for security reasons. Use a normal tab with an IFRAME if you want to pull content from another server.
* Static content cannot be added inside such tabs.
*
* @param string $sTabLabel The (localised) label of the tab
* @param string $sUrl The URL to load (on the same server)
* @param boolean $bCache Whether or not to cache the content of the tab once it has been loaded. flase will cause the tab to be reloaded upon each activation.
* @since 2.0.3
*/
public function AddAjaxTab($sTabLabel, $sUrl, $bCache = true)
{
$this->add($this->m_oTabs->AddAjaxTab($sTabLabel, $sUrl, $bCache));
}
public function GetCurrentTab()
{
return $this->m_sCurrentTab;
return $this->m_oTabs->GetCurrentTab();
}
public function RemoveTab($sTabLabel, $sTabContainer = null)
{
if ($sTabContainer == null)
{
$sTabContainer = $this->m_sCurrentTabContainer;
}
if (isset($this->m_aTabs[$sTabContainer][$sTabLabel]))
{
// Delete the content of the tab
unset($this->m_aTabs[$sTabContainer][$sTabLabel]);
// If we just removed the active tab, let's reset the active tab
if (($this->m_sCurrentTabContainer == $sTabContainer) && ($this->m_sCurrentTab == $sTabLabel))
{
$this->m_sCurrentTab = '';
}
}
$this->m_oTabs->RemoveTab($sTabLabel, $sTabContainer);
}
/**
@@ -956,20 +929,7 @@ EOF
*/
public function FindTab($sPattern, $sTabContainer = null)
{
$return = false;
if ($sTabContainer == null)
{
$sTabContainer = $this->m_sCurrentTabContainer;
}
foreach($this->m_aTabs[$sTabContainer] as $sTabLabel => $void)
{
if (preg_match($sPattern, $sTabLabel))
{
$result = $sTabLabel;
break;
}
}
return $result;
return $this->m_oTabs->FindTab($sPattern, $sTabContainer);
}
/**
@@ -980,26 +940,7 @@ EOF
*/
public function SelectTab($sTabContainer, $sTabLabel)
{
$container_index = 0;
$tab_index = 0;
foreach($this->m_aTabs as $sCurrentTabContainerName => $aTabs)
{
if ($sTabContainer == $sCurrentTabContainerName)
{
foreach($aTabs as $sCurrentTabLabel => $void)
{
if ($sCurrentTabLabel == $sTabLabel)
{
break;
}
$tab_index++;
}
break;
}
$container_index++;
}
$sSelector = '#tabbedContent_'.$container_index.' > ul';
$this->add_ready_script("window.setTimeout(\"$('$sSelector').tabs('select', $tab_index);\", 100);"); // Let the time to the tabs widget to initialize
$this->add_ready_script($this->m_oTabs->SelectTab($sTabContainer, $sTabLabel));
}
public function StartCollapsibleSection($sSectionLabel, $bOpen = false)
@@ -1033,9 +974,9 @@ EOF
public function add($sHtml)
{
if (!empty($this->m_sCurrentTabContainer) && !empty($this->m_sCurrentTab))
if (!empty($this->m_oTabs->GetCurrentTabContainer()) && !empty($this->m_oTabs->GetCurrentTab()))
{
$this->AddToTab($this->m_sCurrentTabContainer, $this->m_sCurrentTab, $sHtml);
$this->m_oTabs->AddToCurrentTab($sHtml);
}
else
{
@@ -1049,10 +990,13 @@ EOF
*/
public function start_capture()
{
if (!empty($this->m_sCurrentTabContainer) && !empty($this->m_sCurrentTab))
$sCurrentTabContainer = $this->m_oTabs->GetCurrentTabContainer();
$sCurrentTab = $this->m_oTabs->GetCurrentTab();
if (!empty($sCurrentTabContainer) && !empty($sCurrentTab))
{
$iOffset = isset($this->m_aTabs[$this->m_sCurrentTabContainer][$this->m_sCurrentTab]) ? strlen($this->m_aTabs[$this->m_sCurrentTabContainer][$this->m_sCurrentTab]): 0;
return array('tc' => $this->m_sCurrentTabContainer, 'tab' => $this->m_sCurrentTab, 'offset' => $iOffset);
$iOffset = $this->m_oTabs->GetCurrentTabLength();
return array('tc' => $sCurrentTabContainer, 'tab' => $sCurrentTab, 'offset' => $iOffset);
}
else
{
@@ -1070,10 +1014,9 @@ EOF
{
if (is_array($offset))
{
if (isset($this->m_aTabs[$offset['tc']][$offset['tab']]))
if ($this->m_oTabs->TabExists($offset['tc'], $offset['tab']))
{
$sCaptured = substr($this->m_aTabs[$offset['tc']][$offset['tab']], $offset['offset']);
$this->m_aTabs[$offset['tc']][$offset['tab']] = substr($this->m_aTabs[$offset['tc']][$offset['tab']], 0, $offset['offset']);
$sCaptured = $this->m_oTabs->TruncateTab($offset['tc'], $offset['tab'], $offset['offset']);
}
else
{

View File

@@ -718,4 +718,282 @@ class WebPage implements Page
}
}
}
?>
interface iTabbedPage
{
public function AddTabContainer($sTabContainer, $sPrefix = '');
public function AddToTab($sTabContainer, $sTabLabel, $sHtml);
public function SetCurrentTabContainer($sTabContainer = '');
public function SetCurrentTab($sTabLabel = '');
/**
* Add a tab which content will be loaded asynchronously via the supplied URL
*
* Limitations:
* Cross site scripting is not not allowed for security reasons. Use a normal tab with an IFRAME if you want to pull content from another server.
* Static content cannot be added inside such tabs.
*
* @param string $sTabLabel The (localised) label of the tab
* @param string $sUrl The URL to load (on the same server)
* @param boolean $bCache Whether or not to cache the content of the tab once it has been loaded. flase will cause the tab to be reloaded upon each activation.
* @since 2.0.3
*/
public function AddAjaxTab($sTabLabel, $sUrl, $bCache = true);
public function GetCurrentTab();
public function RemoveTab($sTabLabel, $sTabContainer = null);
/**
* Finds the tab whose title matches a given pattern
* @return mixed The name of the tab as a string or false if not found
*/
public function FindTab($sPattern, $sTabContainer = null);
}
/**
* Helper class to implement JQueryUI tabs inside a page
*/
class TabManager
{
protected $m_aTabs;
protected $m_sCurrentTabContainer;
protected $m_sCurrentTab;
public function __construct()
{
$this->m_aTabs = array();
$this->m_sCurrentTabContainer = '';
$this->m_sCurrentTab = '';
}
public function AddTabContainer($sTabContainer, $sPrefix = '')
{
$this->m_aTabs[$sTabContainer] = array('prefix' => $sPrefix, 'tabs' => array());
return "\$Tabs:$sTabContainer\$";
}
public function AddToCurrentTab($sHtml)
{
$this->AddToTab($this->m_sCurrentTabContainer, $this->m_sCurrentTab, $sHtml);
}
public function GetCurrentTabLength($sHtml)
{
$iLength = isset($this->m_aTabs[$this->m_sCurrentTabContainer]['tabs'][$this->m_sCurrentTab]['html']) ? strlen($this->m_aTabs[$this->m_sCurrentTabContainer]['tabs'][$this->m_sCurrentTab]['html']): 0;
return $iLength;
}
public function TruncateTab($sTabContainer, $sTab, $iLength)
{
$this->m_aTabs[$this->m_sCurrentTabContainer]['tabs'][$this->m_sCurrentTab]['html'] = substr($this->m_aTabs[$this->m_sCurrentTabContainer]['tabs'][$this->m_sCurrentTab]['html'], 0, $iLength);
}
public function TabExists($sTabContainer, $sTab)
{
return isset($this->m_aTabs[$sTabContainer]['tabs'][$sTab]);
}
public function TabsContainerCount()
{
return count($this->m_aTabs);
}
public function AddToTab($sTabContainer, $sTabLabel, $sHtml)
{
if (!isset($this->m_aTabs[$sTabContainer]['tabs'][$sTabLabel]))
{
// Set the content of the tab
$this->m_aTabs[$sTabContainer]['tabs'][$sTabLabel] = array(
'type' => 'html',
'html' => $sHtml,
);
}
else
{
if ($this->m_aTabs[$sTabContainer]['tabs'][$sTabLabel]['type'] != 'html')
{
throw new Exception("Cannot add HTML content to the tab '$sTabLabel' of type '{$this->m_aTabs[$sTabContainer]['tabs'][$sTabLabel]['type']}'");
}
// Append to the content of the tab
$this->m_aTabs[$sTabContainer]['tabs'][$sTabLabel]['html'] .= $sHtml;
}
return ''; // Nothing to add to the page for now
}
public function SetCurrentTabContainer($sTabContainer = '')
{
$sPreviousTabContainer = $this->m_sCurrentTabContainer;
$this->m_sCurrentTabContainer = $sTabContainer;
return $sPreviousTabContainer;
}
public function SetCurrentTab($sTabLabel = '')
{
$sPreviousTab = $this->m_sCurrentTab;
$this->m_sCurrentTab = $sTabLabel;
return $sPreviousTab;
}
/**
* Add a tab which content will be loaded asynchronously via the supplied URL
*
* Limitations:
* Cross site scripting is not not allowed for security reasons. Use a normal tab with an IFRAME if you want to pull content from another server.
* Static content cannot be added inside such tabs.
*
* @param string $sTabLabel The (localised) label of the tab
* @param string $sUrl The URL to load (on the same server)
* @param boolean $bCache Whether or not to cache the content of the tab once it has been loaded. flase will cause the tab to be reloaded upon each activation.
* @since 2.0.3
*/
public function AddAjaxTab($sTabLabel, $sUrl, $bCache = true)
{
// Set the content of the tab
$this->m_aTabs[$this->m_sCurrentTabContainer]['tabs'][$sTabLabel] = array(
'type' => 'ajax',
'url' => $sUrl,
'cache' => $bCache,
);
return ''; // Nothing to add to the page for now
}
public function GetCurrentTabContainer()
{
return $this->m_sCurrentTabContainer;
}
public function GetCurrentTab()
{
return $this->m_sCurrentTab;
}
public function RemoveTab($sTabLabel, $sTabContainer = null)
{
if ($sTabContainer == null)
{
$sTabContainer = $this->m_sCurrentTabContainer;
}
if (isset($this->m_aTabs[$sTabContainer]['tabs'][$sTabLabel]))
{
// Delete the content of the tab
unset($this->m_aTabs[$sTabContainer]['tabs'][$sTabLabel]);
// If we just removed the active tab, let's reset the active tab
if (($this->m_sCurrentTabContainer == $sTabContainer) && ($this->m_sCurrentTab == $sTabLabel))
{
$this->m_sCurrentTab = '';
}
}
}
/**
* Finds the tab whose title matches a given pattern
* @return mixed The name of the tab as a string or false if not found
*/
public function FindTab($sPattern, $sTabContainer = null)
{
$return = false;
if ($sTabContainer == null)
{
$sTabContainer = $this->m_sCurrentTabContainer;
}
foreach($this->m_aTabs[$sTabContainer]['tabs'] as $sTabLabel => $void)
{
if (preg_match($sPattern, $sTabLabel))
{
$result = $sTabLabel;
break;
}
}
return $result;
}
/**
* Make the given tab the active one, as if it were clicked
* DOES NOT WORK: apparently in the *old* version of jquery
* that we are using this is not supported... TO DO upgrade
* the whole jquery bundle...
*/
public function SelectTab($sTabContainer, $sTabLabel)
{
$container_index = 0;
$tab_index = 0;
foreach($this->m_aTabs as $sCurrentTabContainerName => $aTabs)
{
if ($sTabContainer == $sCurrentTabContainerName)
{
foreach($aTabs['tabs'] as $sCurrentTabLabel => $void)
{
if ($sCurrentTabLabel == $sTabLabel)
{
break;
}
$tab_index++;
}
break;
}
$container_index++;
}
$sSelector = '#tabbedContent_'.$container_index.' > ul';
return "window.setTimeout(\"$('$sSelector').tabs('select', $tab_index);\", 100);"; // Let the time to the tabs widget to initialize
}
public function RenderIntoContent($sContent)
{
// Render the tabs in the page (if any)
foreach($this->m_aTabs as $sTabContainerName => $aTabs)
{
$sTabs = '';
$sPrefix = $aTabs['prefix'];
$container_index = 0;
if (count($aTabs['tabs']) > 0)
{
$sTabs = "<!-- tabs -->\n<div id=\"tabbedContent_{$sPrefix}{$container_index}\" class=\"light\">\n";
$sTabs .= "<ul>\n";
// Display the unordered list that will be rendered as the tabs
$i = 0;
foreach($aTabs['tabs'] as $sTabName => $aTabData)
{
switch($aTabData['type'])
{
case 'ajax':
$sTabs .= "<li data-cache=\"".($aTabData['cache'] ? 'true' : 'false')."\"><a href=\"{$aTabData['url']}\" class=\"tab\"><span>".htmlentities($sTabName, ENT_QUOTES, 'UTF-8')."</span></a></li>\n";
break;
case 'html':
default:
$sTabs .= "<li><a href=\"#tab_{$sPrefix}{$container_index}$i\" class=\"tab\"><span>".htmlentities($sTabName, ENT_QUOTES, 'UTF-8')."</span></a></li>\n";
}
$i++;
}
$sTabs .= "</ul>\n";
// Now add the content of the tabs themselves
$i = 0;
foreach($aTabs['tabs'] as $sTabName => $aTabData)
{
switch($aTabData['type'])
{
case 'ajax':
// Nothing to add
break;
case 'html':
default:
$sTabs .= "<div id=\"tab_{$sPrefix}{$container_index}$i\">".$aTabData['html']."</div>\n";
}
$i++;
}
$sTabs .= "</div>\n<!-- end of tabs-->\n";
}
$sContent = str_replace("\$Tabs:$sTabContainerName\$", $sTabs, $sContent);
$container_index++;
}
return $sContent;
}
}