Nth Level Site Map for SharePoint and Office 365 using Jquery and Rest

Advanced Site Map
Site Map that lists sub-sites and lists for any site until nth level

Site maps or site directory is a road map that lets you travel through your site and locate the contents very easy.

In this article today we will create a dynamic Site map using Jquery and Rest which can be used in any SharePoint environment either on premise or SharePoint online. The solutions will be a complete client side based application which doesn’t require server side access at all.

Features of the SiteMap

  • Site hierarchy starts from the site where you place the code
    • If your code is linked to site collection level then the hierarchy starts from site collection and it drills down all the way until the last sub-site present.
  • It displays the sub-site and lists title of the site with a link to the site and list location
  • Expand and collapse in each site to show and hide contents, sub-sites and lists
  • Works for SharePoint online and On premise

Code

Add an HTML file and save it to a safe location. This html file should be at least read only to all the users inside the site collection.

We use Jquery,Rest api and CSS to write the whole application and save it in the html file.

Put all these code into your html file

Javascript


<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript">
</script><script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="https://code.jquery.com/ui/1.11.1/jquery-ui.min.js"></script>
<script type="text/javascript">
var url = _spPageContextInfo.webServerRelativeUrl;
var webapplicationurl=window.location.protocol + "//" + window.location.host;
var cur_url= webapplicationurl+url;var title= _spPageContextInfo.webTitle;
$(document).ready(function () {
$("#parent_site").attr('href',cur_url);
$("#parent_site").text(title);
/*opens up the site contents that displays links to subsites and lists*/
$(document).on('click', '.expand', function(){
var web_url=$(this).next('.texts').find('a').attr('href');
var randomno= web_url.replace(/[_\W]+/g,"");
$(this).attr("id",randomno);
$(this).removeClass("expand");
$(this).addClass("collapse");
$(this).parent().find('.site_contents').show();
$(this).attr('title','Hide site contents');
$.ajax({
url:web_url+"/_api/web/webinfos?$select=ServerRelativeUrl,Title,LastItemModifiedDate",
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
if (data.d.results.length<1)
{
var html="


<div class='site_contents'>No Subsite Present


<div class='lists_cont' weburl="+web_url+">


<div title='Display Lists' class='lists_expand'></div>


<label class='Title'>Lists</label>


<ul class='ul_lists'></ul>


</div>


</div>


";
$('#'+randomno).parent().append(html);
}
else{
var html="


<div class='site_contents'>


<div class='subsite_cont'>


<div title='Display Subsites' class='subsite_expand'></div>


<label class='Title'>Subsites("+data.d.results.length+")</label>


<ul class='ul_subsite'></ul>


</div>



<div class='lists_cont'>


<div title='Display Lists' class='lists_expand'></div>


<label class='Title'>Lists</label>


<ul class='ul_lists'></ul>


</div>


</div>


";
$('#'+randomno).parent().append(html);
$('#'+randomno).parent().find('.site_contents:first').find('.subsite_cont:first').attr('weburl',web_url);
$('#'+randomno).parent().find('.site_contents:first').find('.lists_cont:first').attr('weburl',web_url);
}
}
});
});

/*add subsites*/
$(document).on('click', '.subsite_expand', function() {
var web_url=$(this).parent().attr('weburl');
var randomno= web_url.replace(/[_\W]+/g,"")+"site";
$(this).attr("id",randomno);
$(this).removeClass("subsite_expand");
$(this).addClass("subsite_collapse");
$(this).attr('title','Hide Subsites');

$.ajax({
url:web_url+"/_api/web/webinfos?$select=ServerRelativeUrl,Title,LastItemModifiedDate",
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data)
{
$.each(data.d.results, function() {
var html="


	<li>


<div class='container' weburl="+this.ServerRelativeUrl+">


<div title='Show site contents' class='expand'></div>



<div class='texts'><a href="+webapplicationurl+this.ServerRelativeUrl+">"+this.Title+"</a>" +"</div>


</div></li>


";
$('#'+randomno).parent().find('ul').append(html);
});
}
});
});

/*add lists*/
$(document).on('click', '.lists_expand', function(){
var web_url=$(this).parent().attr('weburl');
var randomno= web_url.replace(/[_\W]+/g,"")+"lists";
$(this).attr("id",randomno);
$(this).removeClass("lists_expand");
$(this).addClass("lists_collapse");
$(this).attr('title','Hide Lists');
$.ajax({
url:web_url+"/_api/Web/lists?$filter=Hidden eq false",
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {

$.each(data.d.results,function(){
/* You can use a following approach here as well, this link takes you to the list settings page for all lists.
$('#'+randomno).parent().find('ul').append("


	<li><a target='_blank' title='Go to list page' href="+web_url+"_layouts/15/listedit.aspx?List==%7B"+this.Id+"=%7D>"+this.Title +"</a></li>


");
*/
if(this.BaseType==0)
{$('#'+randomno).parent().find('ul').append("


	<li><a target='_blank' title='Go to list page' href="+web_url+"/lists/"+this.EntityTypeName.replace("List","").replace(new RegExp("_x0020_", "g")," ").replace(new RegExp("_x005f_", "g"),"_") +">"+this.Title +"</a></li>


");
}
else{
$('#'+randomno).parent().find('ul').append("


	<li><a target='_blank' title='Go to list page' href=" + web_url+ "/"+this.EntityTypeName.replace(new RegExp("_x0020_", "g")," ").replace(new RegExp("_x005f_", "g"),"_") +">"+this.Title + "</a></li>


");
}
});
}
});
});

/*site contents collapse to hide site contents*/
$(document).on('click', '.collapse', function(){
$(this).removeClass("collapse");
$(this).addClass("expand");
$(this).parent().find('.site_contents').remove();
$(this).attr('title','Show site contents');
});
/*subsite contents hide*/
$(document).on('click', '.subsite_collapse', function(){
$(this).removeClass("subsite_collapse");
$(this).addClass("subsite_expand");
$(this).parent().find('.ul_subsite').empty();
$(this).attr('title','Show Subsites');
});
/*site lists hide*/
$(document).on('click', '.lists_collapse', function(){
$(this).removeClass("lists_collapse");
$(this).addClass("lists_expand");
$(this).parent().find('.ul_lists').empty();
$(this).attr('title','Show Lists');
});
});

</script>

CSS


<style type="text/css">
.subsite_expand{
background-image:URL('/Style%20Library/SiteImages/Plus.jpg');
background-repeat:no-repeat;
height:14px;
width:14px;
padding-right:10px;
float:left;
}
.subsite_collapse{
background-image:URL('/Style%20Library/SiteImages/minus.jpg');
background-repeat:no-repeat;
height:14px;
width:14px;
padding-right:12px;
float:left;
}

.lists_expand{
background-image:URL('/Style%20Library/SiteImages/Plus.jpg');
background-repeat:no-repeat; height:14px; width:14px;
padding-right:10px; float:left;
}
.lists_collapse{
background-image:URL('/Style%20Library/SiteImages/minus.jpg');
background-repeat:no-repeat; height:14px;
width:14px;
padding-right:12px;
float:left;
}
.expand{
background-image:URL('/Style%20Library/SiteImages/Plus.jpg');
background-repeat:no-repeat;
height:14px;
width:14px;
padding-right:10px;
float:left;
margin-top:5px;
}
.collapse{
background-image:URL('/Style%20Library/SiteImages/minus.jpg');
background-repeat:no-repeat;
height:14px;
width:14px;
padding-right:12px;
float:left;
margin-top:5px;
}
li.parentsitcol{
display: flex;
background-color:#0072C6;
padding:5PX;
margin-bottom:4px;
}
.texts{
min-width:350px;
text-align: center;
font-size: 18px;
padding: 2px;
}
.texts a{
text-decoration:none;
color:white;
}

ul.ul_subsite {
padding-left: 0px;
margin-top: 20px;
margin-left: -40px;
background-color:#ebeff3;
}
.ul_subsite li{
display: inline;
float: left;
border: medium;
background-color: #5cabf1;
margin: 5px;
padding: 5px;
}
.subsite_cont {
padding: 10px;
display:flex;
}
.site_contents {
background-color: #9ccaf3;
padding: 10px;
}
label.Title {
height: 25px;
padding-left: 10px;
font-weight: 600;
font-size: 16px;
}
.lists_cont {
display: flex;
margin:10px;
}
.ul_lists li {
display: inline-flex;
margin: 5px;
background-color: #0072c6;
padding: 5px;
}
ul.ul_lists {
list-style: none;
padding-left: 0px;
margin-top: 20px;
background-color: #f1f1f1;
}
.ul_lists li a {
color: white;
font-style: italic;
text-decoration: underline;
color: #fff;
}
.poc {
font-size: 14px;
color: #cbf10b;
font-weight: bold;
padding:4px;
}
.poc>a {
color: #0dfba5;
font-weight: normal;
text-decoration: underline;
}
</style>

Html


<body>
<ul class="sitecol">
	<li id="oone" class="parentsitcol">
<div class="container">
<div class="expand" title="Show site contents"></div>
<div class="texts"><a id="parent_site"></a></div>
</div></li>
</ul>
</body>

add this code to your html file and save,

Add a web part page

AddWebpartPage
Add a web-part page

Edit the Web Part page and add Content Editor Web-part

AddWebparttopage
Add the link to the HTML file in the Content link

Once the file is saved then your site map should be ready as shown in below image.

FinalImage
Site Map using Jquery Rest and HTMLS

As shown in above image the site map will start with the current site and it can go down all way to the last sub-site present. As the map expands it also has the ability to display the lists of the site. You can hide or display any section as you want.

This application can be used for SharePoint online or SharePoint on premises. It has been tested in Office 365 and SharePoint 2013.

I hope it helps you to create a dynamic and intuitive Site map for your users.

4 thoughts on “Nth Level Site Map for SharePoint and Office 365 using Jquery and Rest

  1. This is exactly what I am looking for! Unfortunately, all I get is a blue header after following the steps. Any clues? Thanks for sharing!

    Like

    1. Do F12 and see in console if there is any error. The code is very sensitive try it chunk by chunk. Start with one site only then go for rest. First try to get the first one working and do the rest. Good Luck

      Like

  2. Expands beyond the page in IE 11 but is ok in Chrome. i really need to get working in IE11 due to other environment issues.

    Like

    1. David, i recommend you use F12 to debug in IE11. Flex might not work well in IE11 but table-cell might work. I did have similar problem but the CSS i included should work. Try debugging in IE 11 and change the class or value for the div that expands out of the screen. You should see the difference..

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s