Category Archives: SPJS Charts for SharePoint v4

Build a Site Map for SPJS Charts for SharePoint

Change log
January 1. 2014
v1.2 has these changes:
Fixed bug where the string representing the “tile” in the org chart exceeds 255 characters and thus halting the script. This is fixes by using a multiline text field in stead of the Title field in the list “SPJS-SiteMap”.

You find the updated code below.

Updating from a previous version?
Please note that you must delete the existing list and rerun the script to recreate it with the new fields. When the script has recreated the list, you must enter setup of your chart to reselect the list and fields for your SiteMap chart. See image below for changes in the chart setup (new field used in stead of the Title field).

I got a request from Stacy Draper ‏@stacyDraper on Twitter:

@SPJavaScripts do you have something that makes a site map? Using the logged in perms instead of having to be a site col admin would be nice

Unfortunately I do not know of a method of doing this without Site collection Administrator (SCA) rights, but thought I should post a solution anyways. This solution iterates trough all sites in the site collection and writes to a custom list in a format that can be rendered as a clickable organization chart using SPJS Charts for SharePoint.
The map must be created or updates by a SCA, but can be read by all users.

How to set it up
  1. Set up SPJS Charts for SharePoint v4 as described here. Please note that you need v4.03 or later.
  2. Download spjs-utility.js from here and save it in a document library or a folder created in SPD.
  3. Create a Web Part Page and add a HTML Form Web part to it. Add the code from the code block below in the source editor.

    You can also use a CEWP if you use the content link option to link to the code. Do not add the code directly in the source editor of the CEWP.

  4. Download jQuery from here.

When you reload the page, you will see a button named “Add or update site map”. Click this to set up the list. You should get a confirmation message when the list has been created. You need appropriate permissions to add a list. If you are a SCA, go ahead and populate the list with information about all sites in the site collection. This is done by clicking the same button again.

You will get a confirmation message with the count of items added, updated and removed. The information in the list SPJS-SiteMap is now static and will not reflect changes in the site structure live. To update the site map when a site has been added / updated or removed, an SCA must click the button “Add or update site map” again.


You must update the script src to point to your local files.

<div id="siteMapBtn"></div>
<script type="text/javascript" src="/Scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="/Scripts/spjs-utility/spjs-utility.js"></script>
<script type="text/javascript">

var spjs = spjs || {};

spjs.siteMap = {
		"listBaseUrl":typeof _spPageContextInfo !== "undefined" ? _spPageContextInfo.siteServerRelativeUrl !== "/" ? _spPageContextInfo.siteServerRelativeUrl : "" : L_Menu_BaseUrl,
		"listDescription":"SPJS-SiteMap for SharePoint by Alexander Bautz / SharePoint JavaScripts: This list is used as datasource for SPJS Charts for SharePoint."
		$("#siteMapBtn").html("<input type='button' onclick='spjs.siteMap.update()' value='Add or update site map' />");
		if(!confirm("You must be Site Collection Administrator to add or update the site map. Click OK to continue.")){
		var b, webs, thisBaseUrl, p, currItems, currItemsObj, newList, uList, data, res, noChangeCount, uCount, nCount, dCount, error;
		b = '<GetAllSubWebCollection xmlns="" />';
		webs = {};
		spjs_wrapSoapRequest('/_vti_bin/webs.asmx', '', b, function(data){
			$('Web', data).each(function(i,o){
				thisBaseUrl = $(o).attr("Url").replace(location.protocol+"//","");
				if(thisBaseUrl === ""){
					thisBaseUrl = "/";
				p = $(o).attr("Url").replace(location.protocol+"//","");
				p = p.substring(0,p.lastIndexOf("/"));
				if(p === ""){
					p = "/";		
				webs[thisBaseUrl] = {"title":$(o).attr("Title"),"parent":p};
		// Get current items
		currItems = spjs_QueryItems({"listName","listBaseUrl","query":"<Where><IsNotNull><FieldRef Name='ID' /></IsNotNull></Where>","viewFields":["ID","CurrentSite","Parent","URL"]});
		if(currItems.count === -1){
			if(confirm("It looks like the list named "" does not exist.\n\nCreate it now?")){
				newList = spjs_AddList(,,;
					uList = spjs_UpdateList(,L_Menu_BaseUrl,[{'Type':'Note','DisplayName':'CurrentSite'},{'Type':'Note','DisplayName':'Parent'},{'Type':'Note','DisplayName':'URL'}],[]);
						if(confirm("The list was created successfully. Click OK to populate the list.")){
		currItemsObj = {};
		noChangeCount = 0;
		uCount = 0;
		nCount = 0;
		dCount = 0;
			currItemsObj[item.URL === null ? "" : item.URL] = {"ID":item.ID,"CurrentSite":item.CurrentSite,"Parent":item.Parent,"URL":item.URL};
		error = false;
			data = {"Title":"[...]","CurrentSite":"{\"v\":\""+url+"\",\"f\":\"<a href='"+url+"' target='_blank'>"+o.title+"</a>\"}","URL":url,"Parent":o.parent}
			if(currItemsObj[url] !== undefined){			
				if(currItemsObj[url].CurrentSite === data.CurrentSite && currItemsObj[url].Parent === o.parent && currItemsObj[url].URL === url){
					delete currItemsObj[url];
					noChangeCount += 1;
				res = spjs_updateItem({"listName","listBaseUrl","id":currItemsObj[url].ID,"data":data});
				delete currItemsObj[url];
					error = {"errorText":res.errorText,"code":res.errorCode};
					return false;
					uCount += 1;
				res = spjs_addItem({"listName","listBaseUrl","data":data});
					error = {"errorText":res.errorText,"code":res.errorCode};
					return false;
					nCount += 1;
		if(error !== false){
			alert("SPJS-SiteMap: An error occurred\n---------------------------------------\nAre you updating from a previous version? If the below error message tells you that one or more field types are not installed correctly, please delete the list \"SPJS-SiteMap\" and rerun this script. The list will be recreated with the missing fields.\n\nPlease note that you must edit the SiteMap chart to reselect the list and fields.\n\nError message\n---------------------------------------\n"+error.errorText);
			res = spjs_deleteItem({"listName","listBaseUrl","id":obj.ID});
				return false;
				dCount += 1;
		alert("SPJS-SiteMap\n\nUpdated: "+uCount+"\nAdded: "+nCount+"\nRemoved: "+dCount);
		location.href = location.href;

How to configure the chart

Refer the SPJS Charts for SharePoint v4 article for setup instructions, and select the list “SPJS-SiteMap” as data source. Add an option “allowHtml = true” to render the links as HTML. Here is a screenshot of the Edit Chart GUI:

Let me know what you think of this solution in the comments section below.


SPJS Charts for SharePoint: date range filter

In this article I will show you how to add a date range filter to a chart created using SPJS Charts for SharePoint v4. The code demonstrated below will query the list and get the highest and lowest date in the field specified in the query. It will then create the filter dropdowns based on the interval you select. Currently you can use “m” for month, or “y” for year.


How to set it up

To use this method for filtering a chart, you must set the variable “allowEval” to true in the CEWP code like this:

// Set this to true to allow for the use of variables in the "Filter setup textarea"
var allowEval = true;

Then you add this code to the same CEWP:

function spjs_getDateRangeFilter(list,field,interval,format){
	var q, res, start, end, split, startDate, endDate, b, d, m, y;
	// Find the start date
	q = "<Where><IsNotNull><FieldRef Name='"+field+"' /></IsNotNull></Where><OrderBy><FieldRef Name='"+field+"' Ascending='TRUE' /></OrderBy>";
	res = spjs.charts.qItems({"listName":list,"query":q,"viewFields":[field],"rowLimit":1});
	start = res.items[0][field];
	// Find the end date
	q = "<Where><IsNotNull><FieldRef Name='ID' /></IsNotNull></Where><OrderBy><FieldRef Name='"+field+"' Ascending='FALSE' /></OrderBy>";
	res = spjs.charts.qItems({"listName":list,"query":q,"viewFields":[field],"rowLimit":1});
	end = res.items[0][field];
	split = start.split(/-| |:/);
	startDate = new Date(split[0],parseInt(split[1],10)-1,split[2]);	
	split = end.split(/-| |:/);
	endDate = new Date(split[0],parseInt(split[1],10)-1,split[2]);
	b = [];
		case "m":	
		case "y":
			alert("The interval \""+interval+"\" is not supported. Use \"m\" for month or \"y\" for year.");
			return [{"f":"","v":""}];	
		d = startDate.getDate();
		d = d < 10 ? "0"+d : d;
		m = startDate.getMonth()+1;
		m = m < 10 ? "0"+m : m;
		y = startDate.getFullYear();
		b.push({"f":format.replace("yyyy",y).replace("MM",m).replace("dd",d),"v":String(startDate.getFullYear()+"-"+(startDate.getMonth()+1)+"-"+startDate.getDate()+" 12:00:00")});
			case "m":					
			case "y":
	return b;

var myCustomFilterOptions = spjs_getDateRangeFilter("ListNameOrListGuid","FieldInternalName","m","MM/dd/yyyy");

The variable “myCustomFilterOptions” is used in the filter textarea in the chart. You can name it anything you like, preferably something that identifies the filter.

The arguments to the function “spjs_getDateRangeFilter” is as follows:
list: The DisplayName or the list GUID of the list you are querying.
field: The field internal name of the field – must be type “Date and time”.
interval: The date interval for the filter. Use “m” for month, or “y” for year.
format: The format of the visible date in the dropdown. Use any combination of dd (for day), MM (for month) and yyyy (for year).

Look her to learn how to find the list GUID and the FieldInternaleName.

This is the setup for the chart shown in the top of this article:

The text in the filter textare is this:

[{"label":"Date from","urlKey":"date1","multiselect":false,"size":5,"options":myCustomFilterOptions},{"label":"Date to","urlKey":"date2","multiselect":false,"size":5,"options":myCustomFilterOptions}]

Please note the name of the variable “myCustomFilterOptions” from the CEWP code.

And the text from the Custom CAML-query textarea is this:

<Where><And><Geq><FieldRef Name='Date' /><Value Type='DateTime'>{filter:date1}</Value></Geq><Leq><FieldRef Name='Date' /><Value Type='DateTime'>{filter:date2}</Value></Leq></And></Where>

You must change the name of the filed to match the FieldInternalName of the field in your list.

Leave a comment below if you like it, or you need help setting it up.


SPJS Charts for SharePoint v4: Web Part Templates

To be able to easily add a chart to any page without the knowledge of JavaScript, you can create “Web Parts” in the “Web Part Gallery”. Follow these steps to be able to add a chart as you would any other web part:

First you must add two Content Editor Web Parts to a page using the “Master code”, and the “Slave code” from the setup instructions. Edit the Web Part and update these settings:
The master:
Under “Appearance”, change “Title” to “SPJS Charts for SharePoint: Master”.
Under “Advanced”, change the “Description” to “Use this Web Part to start building charts in the page. Use only one Master Web Part in each page. To load additional charts, use SPJS Charts for SharePoint: Slave.”.

The “Slave”:
Under “Appearance”, change “Title” to “SPJS Charts for SharePoint: Slave”.
Under “Advanced”, change the “Description” to “You must first add a SPJS Charts for SharePoint: Master web part to the page. Use this Web Part to load additional charts.”.

Save the changes to the web parts, and export them like this:

Save them locally, and then upload then to the “Web Part Gallery” by going to “Site settings” and selecting “Web parts” under “Galleries”. Upload them and add them under a custom Group named “SPJS”.
Now you can add the chart web parts as any other web parts to any page within the site collection.

Ask if anything is unclear,

SPJS Charts for SharePoint v4: Generate filter values with a function

This post will describe how you can generate the filter values for a chart dynamically in SPJS Charts for SharePoint v4 using a function in the Master Web Part CEWP code.

This is something you will have to do if you want to filter a chart based on a column value that has dynamic contents and you therefore cannot use a static filter set in the chart options.

Step 1
Go to the SPJS Charts for SharePoint v4: Master Web Part, and set the variable “allowEval” to true:

<div class="spjs_chartPlaceholder_master"></div>
<script type="text/javascript">
// Load the Google Visualization API release candidate
var loadRC = false;
// Set this to true to allow for the use of variables in the "Filter setup textarea"
var allowEval = true;

var spjs_chart_license = "XXXX-XXXXXXXXXXXXXXXXXXX";

Step 2
Add the code for creating the filter to the same CEWP:

<script type="text/javascript">
function spjs_getFilterValue(list,field){
	var q = "<Where><IsNotNull><FieldRef Name='ID' /></IsNotNull></Where><OrderBy><FieldRef Name='"+field+"' /></OrderBy>";
	var res = spjs.charts.qItems({"listName":list,"query":q,"viewFields":[field]});
	var b = [];
	var fObj = {};
		if(fObj[item[field]] === undefined){
			fObj[item[field]] = 1;
	return b;
var myCustomFilterOptions = spjs_getFilterValue("Poll","Answer");

This example queries the list “Poll” for the unique values in the column “Answer”. You can use any code you like to obtain these values, as long as the result is formatted like an array with this syntax:

[{"f":"Value 1","v":"Value 1"},{"f":"Value 2","v":"Value 2"}]

The “f” property is the “friendly name” that is shown in the dropdown select. This can be modified to make sense for the user. The “v” property is the value you expect to find in the database. For further instructions look at the “instructions” above the filter textarea in the “Edit chart GUI”.

Step 3
Use the variable “myCustomFilterOptions” in the filter textarea in the “Edit chart GUI”:


And use this CAML:

<Where><Eq><FieldRef Name='Answer' /><Value Type='Text'>{filter:Answer}</Value></Eq></Where>

Ask if anything is unclear.

SPJS Charts for SharePoint v4: chartOptionOverride

This function is used in SPJS Charts for SharePoint v4 to override / intercept the chart options before the chart is drawn. You must inset this function in the Master CEWP code for it to be available when the chart is about to be drawn.

This example shows how you can color the series based on the values.

First without spjs_chartOptionOverride:

The override code:

function spjs_chartOptionOverride(chartId,data,options){
	// Color code the series based on the value
	if(chartId === "2ad99c9f-affd-4583-8146-54b03af7fa45"){
		var red = '#ff0000', green = '#00ff00', yellow = '#ffff00', value, i, j;
		options.colors = [];	
		for(i = 1; i < data.getNumberOfColumns(); i++){
			value = 0;
			for(j = 0; j < data.getNumberOfRows(); j++){
				if(data.getValue(j, i) !== null){
					value += data.getValue(j, i);
			options.colors.push(value > 10 ? red : (value > 5 ? yellow : green));
	return options;

Please note that this override will only affect the chart with ID “2ad99c9f-affd-4583-8146-54b03af7fa45”.


Ask if anything is unclear,

SPJS Charts for SharePoint v4

SPJS Charts for SharePoint v5 is finally here

Change log
February 06. 2014
Another fix for scenarios where you have an initial filter that returns data for these columns:
“apples”, “oranges”, “bananas”You then filter the chart and get data in these columns only:
“apples”, “bananas”

You will then get an error
“Invalid column index 3. Should be an integer in the range [0-2]”

January 26. 2014

  • Removed the “pageId” prefix for charts stored in the configuration list. This means you now can rename web part pages containing charts without “loosing the chart”. There will be no problems with existing charts.
  • Bugfix for the following scenario: You have a chart with a filter, and you load the chart initially with a filter that returns no items. You then change the filter and select “all”. You may end up with data plotted in the wrong column / series.
  • Fixed the “Visible columns” for table charts.
  • Added option to show the data label in the column (you find it under advanced options):
  • Minified the code.

December 7. 2013

  • Fixed “Consume filter from list view” where the filter value had & in it.
  • Fixed the L_Menu_BaseUrl override in SP2013 as this came out wrong in the root site.

November 7. 2013

  • Fixed small bug where”No items found” is repeated if you filter the chart and you get 0 items returned two or more consecutive queries.
  • Org chart now supports this format in the first column:
    {"v":"Alexander","f":"Alexander<div style='color:red;font-style:italic;'>SharePoint JavaScripts</div>"}

October 8. 2013
v4.01: Fixes small bug with the “Filtering…” overlay when using “filterAdditionalCharts”.

October 5. 2013
Updated the CEWP code for the Master Web Part as some users had problems loading the solution. One of the closing script tags had disappeared from the code, and this is most likely the cause. I have also moved jQuery above the JSAPI as some users fixed the problems this way.

This is v4 of SPJS Charts for SharePoint. You find the previous articles here, but please note that examples and techniques may have changed in v4.

This version, as the previous ones, lets you create charts from data stored in any lists in the site collection, and add them to any SharePoint page. The charts are created using Google Visualization API.

I have redone the script in v4, and added some improvements like support for animations, automatic refresh of the chart when the datasource is updated, and more. You find a full change log below.

This solution is still entirely client side – nothing is installed on the server.
  • Major overhaul of the code.
  • Changed how the chart containers are named. Previously you had to name them in the CEWP, but now this is done automatically.
  • Its now much easier to add multiple charts to a page as you do not have to edit the code, just add another web part to the page.
  • Bypassed rowlimit for list views to overcome the “paging limit” when using a SharePoint view (and not Custom CAML).
  • Added timeline chart. Please note that there are some bugs in this charts tooltip in IE 10. Hopefully this will be fixed by Google in the next release.
  • Fixed preselecting multiple filter values.
  • Added support for automatically setting up filter for all single line of text columns, calculated columns, choice columns and single choice people picker columns.
  • Added support for animations when loading and filtering.
  • Added support for auto refresh of the chart when the datasource is updates.
  • The last good configuration is automatically stored. You can revert to this if there are errors in the config preventing you from loading it.
  • Added support for password protection of individual charts.
  • Added support for copying, importing and exporting chart configuration (requires licensed version).
  • Added support for setting the series color by label. Like “In progress” = green, “Deferred” = yellow and “Not started” = red. Click “Custom options” at bottom of the Options sections in Edit Chart GUI for instructions.
  • And lots of small fixes.
Deprecated features
  • The “chartOptionOverride” object has been replaced with the function “spjs_chartOptionOverride”. See details on the new function in a separate post.
  • The “prefix” for “sum”, “count” and “average” has been removed. Use numberformat: prefix in stead.
Upgrading from previous version

This solution is NOT directly compatible with previous versions (1.x, 2.x and 3.x). You must set up a new configuration list and modify all existing chart containers with the new code. When this is done, you can import your chart one-by-one from the old configuration list.

Please note that the import feature require a licensed version of SPJS Charts for SharePoint. Click here to buy a license code to unlock the import / export and copy features.

Why is it not compatible with previous versions?

The reason for not making this version backwards compatible has to do with the completely different way the configuration is stored in the configuration list, and the fact that the chart containers are no longer named in the CEWP code. The chart containers now get their unique id assigned automatically. This is done to make putting multiple charts in one page as easy as adding another web part.

Follow these steps to set up the solution
  1. Download jQuery 1.10.x from here. You can use v1.6.4 and up, but you should stay with the 1.x version as 2.x is NOT compatible with Internet Explorer 6, 7 and 8.
  2. Download spjs-charts-v4.js from here.
  3. Create a document library to hold the scripts. You must ensure all users have read access to this library. You can also create a folder using SharePoint designer.
  4. Upload the files to this library / folder.
  5. Create a text file and add this code – ensure you modify the script “src” for “jquery-1.10.2.min.js” and “spjs-charts-v4.js” to point to the location you put your files:
    <div class="spjs_chartPlaceholder_master"></div>
    <script type="text/javascript">
    // Set this to true to load the Google Visualization API release candidate
    var loadRC = false;
    // Set this to true to allow for the use of variables in the "Filter setup textarea"
    var allowEval = false;
    <script type="text/javascript" src="/Scripts/jquery-1.10.2.min.js"></script>
    <script type="text/javascript" src=""></script>
    <script type="text/javascript" src="/Scripts/Charts/spjs-charts-v4.js"></script>
  6. Upload the text file to the same location you put the other files.
  7. Add a CEWP to the page where you want the chart to appear, and use the “Content link” option to link to the text file with the CEWP code from step 5. You can skip step 6 and use a HTML Form Web Part and add the code in the Source editor, but I recommend using the CEWP and content link option to be able to update the code for all charts in one centralized location.
    Please note that you can NOT add the “master code” directly to a CEWP source editor. Either use the content link option in the CEWP to link to a file with the code, or use a HTML form web part. This is necessary because SharePoint messes with the code by appending the script generated contents to the CEWP when you edit the page.
  8. Reload the page and click OK on these two dialogs:
  9. Finished!

If you want to override the loading animation, the filtering label or the “No items found” label, add these variables to the CEWP code:

var spjs_charts_loadingOverlayLabel = "Loading chart...";
var spjs_charts_filteringLabel = "Filtering, please wait...";
var spjs_charts_noItemsFoundLabel = "No items match this filter...";
Configuring your first chart

The placeholder for the chart is indicated with a little gray downarrow where you put the CEWP. Click this image to load the configuration GUI. Here is an example chart with the configuration:

Multiple charts in the same page

In this version you basically have two different “Web parts”: The MASTER with the code referred in step 5 above, which calls the script resources, and the SLAVE which is simply any HTML DOM element with the class “spjs_chartPlaceholder”. This element can be for example a div, span or td. You can add it inline in the text, or set it up in a table structure.

The CEWP code for a SLAVE chart

<div class="spjs_chartPlaceholder"></div>
Please note that you can NOT add the “slave code” directly to a CEWP source editor. Either use the content link option in the CEWP to link to a file with the code, or use a HTML form web part. This is necessary because SharePoint messes with the code by appending the script generated contents to the CEWP when you edit the page.

You can add one Master Web Part to a page, and unlimited number of Slave Web Parts (in theory, buy your page will load slowly if you have to many charts in one page).

See separate article for instructions on how to create Web Part templates in the Web Part Gallery.

Placeholders in edit page mode

When entering edit page mode, the placeholders are highlighted like this:

Copy an existing chart

If you have the licensed version, you can copy existing charts (from v4) in two ways.
Method 1

Method 2:
Go to the chart you want to copy, select “Export configuration as text”:

Copy the text and then use “Import configuration from text” and paste it back in the new location.

Import charts from v3

If you have the licensed version, you can import existing charts (from v3) like this:

You find other articles in this series here:

Do you want to buy a license code?

Click here to to learn how to obtain a license code

Ask if anything is unclear,