Charting with YUI and MashPoint REST API

In this post I will show you how you can use the YUI Charts control with MashPoint REST API to render a chart from list data. In the previous posts we have used the default XHTML representation but when you write AJAX application you most likely don't want this representation. As we said in the initial post MashPoint REST API supports multiple representations JSON being one of them. JSON is a natural format when working with Javascript so in this example we will request that the resources are returned as JSON streams.
We will build a chart component using YUI charts. The whole application is rendered client side. The only server side component you need is the latest version (1.2.9) of MashPoint REST API which you can download here. If you have downloaded MashPoint REST API before you must download the latest version since it has some bug fixes for the JSON serializer.
We will use a Content Editor Web Part to host our script. We will use the sample that is on Yahoos developer site as a starting point. I won't describe the chart component, you can read all about it here.
The first thing we need to do is reference all YUI scripts needed for the charting. We will use the resources hosted on yui.yahooapis.com.
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/yahoo-dom-event/yahoo-dom-event.js"/> 
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/json/json-min.js"/> 
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/element/element-min.js"/> 
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/datasource/datasource-min.js"/> 
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/datatable/datatable-min.js"/> 
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/swf/swf-min.js"/> 
<script type="text/javascript" src="http://yui.yahooapis.com/2.8.0r4/build/charts/charts-min.js"/> 
 
Next we add some custom styling.
<!--begin custom header content for this example--> 
<style type="text/css"> 
    #chart
    {
        width: 500px;
        height: 350px;
        margin-bottom: 10px;
    }
    .chart_title
    {
        display: block;
        font-size: 1.2em;
        font-weight: bold;
        margin-bottom: 0.4em;
    }
</style> 
<!--end custom header content for this example--> 
Then comes the script that will render the chart.
   1: <!--BEGIN SOURCE CODE FOR EXAMPLE =============================== --> 
   2:  
   3: <div id="chart">Unable to load Flash content. The YUI Charts Control requires Flash Player 9.0.45 or higher. You can download the latest version of Flash Player from the <a href="http://www.adobe.com/go/getflashplayer">Adobe Flash Player Download Center</a>.</p></div> 
   4:  
   5: <script type="text/javascript">
   6:  
   7:     YAHOO.widget.Chart.SWFURL 
   8:        = "http://yui.yahooapis.com/2.8.0r4/build/charts/assets/charts.swf";
   9:  
  10:     //used to format x axis labels
  11:     YAHOO.example.numberToCurrency = function(value) {
  12:         return YAHOO.util.Number.format(Number(value), { prefix: "$", thousandsSeparator: "," });
  13:     }
  14:  
  15:     YAHOO.example.render = function() {
  16:         var incomeData = new YAHOO.util.DataSource(YAHOO.example.annualIncome);
  17:         incomeData.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
  18:         incomeData.responseSchema = { fields: ["year", "revenue", "expense", "income"] };
  19:  
  20:         //--- chart
  21:         var seriesDef =
  22:         [
  23:             {
  24:                 xField: "revenue",
  25:                 displayName: "Revenue"
  26:             },
  27:             {
  28:                 xField: "expense",
  29:                 displayName: "Expense"
  30:             },
  31:             {
  32:                 type: "line",
  33:                 xField: "income",
  34:                 displayName: "Income"
  35:             }
  36:         ];
  37:  
  38:         var currencyAxis = new YAHOO.widget.NumericAxis();
  39:         currencyAxis.labelFunction = "YAHOO.example.numberToCurrency";
  40:  
  41:         var mychart = new YAHOO.widget.BarChart("chart", incomeData,
  42:         {
  43:             series: seriesDef,
  44:             yField: "year",
  45:             xAxis: currencyAxis,
  46:             //only needed for flash player express install
  47:             expressInstall: "assets/expressinstall.swf"
  48:         });
  49:     }
  50:  
  51:  
  60:  
  61:     var JSONP = {
  62:         scriptCounter: 1,
  63:         callbacks: {},
  64:         request: function(fullUrl, callback) {
  65:  
  66:             var ix = this.scriptCounter++;
  67:             var scriptId = 'JscriptId' + ix;
  68:  
  69:             var jsonp = "jsonp=" + encodeURIComponent("JSONP.callbacks[" + ix + "]");
  70:             if (fullUrl.indexOf("?") != -1) {
  71:                 jsonp = "&" + jsonp;
  72:             }
  73:             else {
  74:                 jsonp = "?" + jsonp;
  75:             }
  76:  
  77:             this.buildScriptTag(scriptId, fullUrl + jsonp);
  78:             var captured = this;
  79:             this.callbacks[ix] = function(d) {
  80:                 callback(d);
  81:                 var s = document.getElementById(scriptId);
  82:                 s.parentNode.removeChild(s);
  83:                 captured.callbacks[ix] = null;
  84:             }
  85:         },
  86:         buildScriptTag: function(scriptId, fullUrl) {
  87:             // Keep IE from caching requests
  88:             var noCacheIE = '&noCacheIE=' + (new Date()).getTime();
  89:             var s = document.createElement("script");
  90:  
  91:             // Add script object attributes
  92:             s.setAttribute("type", "text/javascript");
  93:             s.setAttribute("src", fullUrl + noCacheIE);
  94:             s.setAttribute("id", scriptId);
  95:  
  96:             var headLoc = document.getElementsByTagName("head").item(0);
  97:             headLoc.appendChild(s);
  98:         }
  99:     };
 100:  
 101:     YAHOO.example.makeRequest = function() {
 104:         var uri = "http://jndtvbx64/mashpoint/1/$json$/Lists/Financial/AllItems.aspx/$Items$";
 105:         JSONP.request(uri, function(d) {
 106:             YAHOO.example.annualIncome = d.d;
 107:             YAHOO.example.render();
 108:         });
 109:     }
 110:  
 111:    //manipulating the DOM causes problems in ie, so create after window fires "load"
 112:    YAHOO.util.Event.addListener(window, "load", YAHOO.example.makeRequest);
 113:  
 114: </script> 
 115: <!--END SOURCE CODE FOR EXAMPLE =============================== --> 
In the Yahoo sample they are using inline JSON data.
var annualIncome =
[
    { year: 2003, revenue: 1246852, expense: 1123359, income: 123493 },
    { year: 2004, revenue: 2451876, expense: 2084952, income: 366920 },
    { year: 2005, revenue: 2917246, expense: 2587151, income: 330095 },
    { year: 2006, revenue: 3318185, expense: 3087456, income: 230729 }
];
In our sample we will read this data from a SharePoint list using the MashPoint REST API. So let's create a list called Financial with the fields year, revenue, expense and income. You can download a list template with this sample data here.
financial
Now what we have to do is to get all the items from this view as JSON data. The URI to this resource is as follows: http://jndtvbx64/mashpoint/1/$json$/Lists/Financial/AllItems.aspx/$Items$
Let's look at the parts of this URI. What is new here is the $json$ token in the URI. This token can be used to specify the Accept-Type when the client can't modify the Http Headers. The next thing that might confuse you is the access of a property named $Items$. As you know there is no such property on the SPView object. But MashPoint has the ability to add pseudo properties to objects. The reason we have the $Items$ property on the view is so we can access the items of a view. And we don't want the SPListItem back but an object that has all fields of the item as it's properties. Let's take a look at the returned data. As you can see we get back an array of objects. The object represent an item in the list with properties corresponding to the fields of the view we queried.
   1: {
   2:     "d": [
   3:         
   4:         {
   5:             "__metadata": {
   6:                 "uri": "http://jndtvbx64/mashpoint/1/$json$/Lists/Financial/AllItems.aspx/$Items$/1",
   7:                 "type": "Bamboo.Rest.Mappers.SharePoint.Extensions.Item"
   8:             },
   9:             "Attachments": false,
  10:             "expense": 1123359,
  11:             "income": 1123493,
  12:             "LinkTitle": "2003",
  13:             "revenue": 1246852,
  14:             "year": 2003
  15:         },        
  16:         {
  17:             "__metadata": {
  18:                 "uri": "http://jndtvbx64/mashpoint/1/$json$/Lists/Financial/AllItems.aspx/$Items$/2",
  19:                 "type": "Bamboo.Rest.Mappers.SharePoint.Extensions.Item"
  20:             },
  21:             "Attachments": false,
  22:             "expense": 1123359,
  23:             "income": 1123493,
  24:             "LinkTitle": "2004",
  25:             "revenue": 1246852,
  26:             "year": 2004
  27:         }
  28:     ]
  29: }
So this is the data we are going to bind to the chart. Let's look at the code that makes the call to MashPoint.
   1: YAHOO.example.makeRequest = function() {
   2:     var uri = "http://jndtvbx64/mashpoint/1/$json$/Lists/Financial/AllItems.aspx/$Items$";
   3:     JSONP.request(uri, function(d) {
   4:         YAHOO.example.annualIncome = d.d;
   5:         YAHOO.example.render();
   6:     });
   7: }
In this sample we use JSONP to get the data from MashPoint. We have a helper object  called JSONP that handles the construction of the correct uri all we have to call it with is the uri without jsonp extension and a callback method. JSONP takes care of the rest. Below is the code for JSONP.
   1: var JSONP = {
   2:     scriptCounter: 1,
   3:     callbacks: {},
   4:     request: function(fullUrl, callback) {
   5:  
   6:         var ix = this.scriptCounter++;
   7:         var scriptId = 'JscriptId' + ix;
   8:  
   9:         var jsonp = "jsonp=" + encodeURIComponent("JSONP.callbacks[" + ix + "]");
  10:         if (fullUrl.indexOf("?") != -1) {
  11:             jsonp = "&" + jsonp;
  12:         }
  13:         else {
  14:             jsonp = "?" + jsonp;
  15:         }
  16:  
  17:         this.buildScriptTag(scriptId, fullUrl + jsonp);
  18:         var captured = this;
  19:         this.callbacks[ix] = function(d) {
  20:             callback(d);
  21:             var s = document.getElementById(scriptId);
  22:             s.parentNode.removeChild(s);
  23:             captured.callbacks[ix] = null;
  24:         }
  25:     },
  26:     buildScriptTag: function(scriptId, fullUrl) {
  27:         // Keep IE from caching requests
  28:         var noCacheIE = '&noCacheIE=' + (new Date()).getTime();
  29:         var s = document.createElement("script");
  30:  
  31:         // Add script object attributes
  32:         s.setAttribute("type", "text/javascript");
  33:         s.setAttribute("src", fullUrl + noCacheIE);
  34:         s.setAttribute("id", scriptId);
  35:  
  36:         var headLoc = document.getElementsByTagName("head").item(0);
  37:         headLoc.appendChild(s);
  38:     }
  39: };
So let's put all this together by adding a CEWP to the AllItems.aspx page and paste in the Javascript. You can download the complete script here and just modify the URI to match your list.
Open the page in edit mode.
edit.mode
Add the CEWP.
add.cewp
Open the toolpane and click Source Editor. Then paste in the script.
script.cewp
Clicking OK should give you a page like this.
chart.list
I hope you appreciate how easy it is to get SharePoint data in JSON format using the MashPoint REST API.

Posted Sep 21 2009, 01:38 PM by Jonas Nilsson

Blogs

    MashPoint - A Breakthrough in SharePoint Data Integration
  • Home

Jonas Nilsson Q&A

Bamboo Nation Almost Everywhere

Bamboo Solutions on Facebook

Bamboo Solutions on Google+

Bamboo Solutions on LinkedIn

Bamboo Solutions on YouTube

Bamboo Solutions Corporation, 2002-2014