Bootstrap Tabs
Below is a screenshot of the homepage of one of the default Portal Themes. It contains two boxes; one showing the "Available Publications" or top-level documents, and another showing the "Recently Updated Topics" or components of the top-level documents.
Below is a screenshot of the same page but using tabs instead of individual boxes:
To accomplish this, create a new theme based on one of the existing default themes
and delete the following from
/pages/portal-home.ftl
:
<@harp.search query="*" sortBy="lastModified" sortDirection="DESC" var="pubs" limit=0 cacheSecs=60 cacheKey="homepagePubs"/> <#assign hasAssembly = isAuthenticated && portal.hasFeature('customAssemblies')> <#if pubs?size > 0> <div class="row"> <div id="homepage-pub-links" class="${hasAssembly?string('col-sm-4','col-sm-6')} col-xs-12"> <div class="homepage-box col-xs-12"> <h4>Available Publications</h4> <ul> <#list pubs as pub> <li><@searchResultLink searchResult=pub title=pub.title/> <#if pub.metadata.draft_md?? && pub.metadata.draft_md?seq_contains('true')> (DRAFT) </#if> </li> </#list> </ul> </div><#-- Container box --> </div><#-- homepage-pub-links wrapper --> <@harp.groupSearch resultsPerGroup=1 query="*" highlightSize=0 sortBy="lastModified createDate" sortDirection="DESC" var="topics" limit=10 cacheSecs=60 cacheKey="homepageTopics"/> <div id="homepage-topics-links" class="${hasAssembly?string('col-sm-4','col-sm-6')} col-xs-12"> <div class="homepage-box col-xs-12"> <h4>Recently Updated Topics</h4> <ul> <#list topics as topic> <li><@searchResultLink searchResult=topic.firstResult title=topic.firstResult.title/></a> </#list> </ul> </div> </div> <#if hasAssembly> <div class="col-sm-4 col-xs-12"> <div class="homepage-box col-xs-12"/> <h4>Assemblies</h4> <@harp.assemblies var="assemblies"/> <#if assemblies?size > 0> <ul> <#list assemblies as assembly> <li> <a href="<@harp.assemblyViewerUrl assembly=assembly/>">${assembly.name?html}</a> <span style="font-size: .8em;" class="inline hidden-xs"> <a href="<@harp.assemblyEditorUrl assembly=assembly/>" alt="Edit" title="Edit" target="harp.assemblyEditor"> <span class="glyphicon glyphicon-pencil"></span> </a> <a href="#" alt="Delete" title="Delete" class="text-danger assemblyDeleteButton" data-assemblyKey="${assembly.key?html}" data-assemblyName="${assembly.name?html}"> <span class="glyphicon glyphicon-trash"></span> </a> </span> </li> </#list> </ul> <p class="text-right hidden-xs" style="font-size: .8em;"><a href="<@harp.assemblyEditorUrl/>" target="harp.assemblyEditor"> <span class="glyphicon glyphicon-plus"></span> New</a></p> <#else> <p>No assemblies yet. <a href="<@harp.assemblyEditorUrl/>" target="harp.assemblyEditor">Create one!</a> </#if> </div><#-- homepage-box --> </div><#-- wrapper --> </#if> </div> </#if>
Then, replace the deleted markup with the following:
<#assign hasAssembly = isAuthenticated && portal.hasFeature('customAssemblies')> <div class="row"> <div id="homepage-pub-tabs" class="col-xs-10 col-xs-offset-1"> <ul class="nav nav-tabs"> <li class="active"><a href="#availablePubs" data-toggle="tab">Available Publications</a> <li><a href="#recentlyUpdated" data-toggle="tab">Recently Updated Topics</a> <#if hasAssembly> <li><a href="#assemblies" data-toggle="tab">Assemblies</a> </#if> </ul> <div class="tab-content"> <div id="availablePubs" class="tab-pane active"> <@harp.search query="*" sortBy="lastModified" sortDirection="DESC" var="pubs" limit=0 cacheSecs=60 cacheKey="homepagePubs"/> <#if pubs?size > 0> <ul> <#list pubs as pub> <li><@searchResultLink searchResult=pub title=pub.title/></li> </#list> </ul> </#if> </div> <div id="recentlyUpdated" class="tab-pane"> <@harp.groupSearch resultsPerGroup=1 query="*" highlightSize=0 sortBy="lastModified createDate" sortDirection="DESC" var="topics" limit=10 cacheSecs=60 cacheKey="homepageTopics"/> <ul> <#list topics as topic> <li><@searchResultLink searchResult=topic.firstResult title=topic.firstResult.title/></li> </#list> </ul> </div> <#if hasAssembly> <div id="assemblies" class="tab-pane"> <@harp.assemblies var="assemblies"/> <#if assemblies?size > 0> <ul> <#list assemblies as assembly> <li> <a href="<@harp.assemblyViewerUrl assembly=assembly/>">${assembly.name?html}</a> <span style="font-size: .8em;" class="inline hidden-xs"> <a href="<@harp.assemblyEditorUrl assembly=assembly/>" alt="Edit" title="Edit" target="harp.assemblyEditor"> <span class="glyphicon glyphicon-pencil"></span> </a> <a href="#" alt="Delete" title="Delete" class="text-danger assemblyDeleteButton" data-assemblyKey="${assembly.key?html}" data-assemblyName="${assembly.name?html}"> <span class="glyphicon glyphicon-trash"></span> </a> </span> </li> </#list> </ul> <p class="text-right hidden-xs" style="font-size: .8em;"> <a href="<@harp.assemblyEditorUrl/>" target="harp.assemblyEditor"> <span class="glyphicon glyphicon-plus"></span> New </a> </p> <#else> <p>No assemblies yet. <a href="<@harp.assemblyEditorUrl/>" target="harp.assemblyEditor">Create one!</a> </#if> </div> </#if> </div> </div> </div>
Additionally, in /static/style/site.less
add the following:
#homepage-pub-tabs { margin-top: @grid-gutter-width; .tab-pane { background-color: @harp-background; padding: (@grid-gutter-width / 2); border: 1px solid @harp-accent-2-dark; border-radius: 0 0 @border-radius-large @border-radius-large; } }
Any other styles may also be modified or added to further costomize the look of these tabs
Each time this page is loaded the first tab will be selected by default. This can
be
detrimental to user experience. For example, if a user selects a different tab, clicks
a link
within that tab, then presses the back
button to return to the home page, they
will presumably expect that the same tab will be selected. Instead, the first tab
will be
selected, hiding the content that the user was viewing when they left the page. To
prevent this,
add the following code inside the <head>
tag of the page:
<script> $(document).ready(function() { var activeTab; $('a[data-toggle="tab"]').on('click', function(e) { history.pushState(null, null, $(this).attr('href')); }); if (location.hash) { var activeTab = $('[href=' + location.hash + ']'); if (activeTab.length) { activeTab.tab('show'); } else { $('.nav-tabs a:first').tab('show'); } } }); </script>