<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[data visualizations - Alexander Development]]></title><description><![CDATA[data visualizations - Alexander Development]]></description><link>https://alexanderdevelopment.net/</link><image><url>https://alexanderdevelopment.net/favicon.png</url><title>data visualizations - Alexander Development</title><link>https://alexanderdevelopment.net/</link></image><generator>Ghost 1.20</generator><lastBuildDate>Fri, 24 Apr 2026 12:09:51 GMT</lastBuildDate><atom:link href="https://alexanderdevelopment.net/tag/data-visualizations/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Better line charts in Dynamics CRM 2011 - part II]]></title><description><![CDATA[<div class="kg-card-markdown"><p>In <a href="https://alexanderdevelopment.net/post/2013/01/24/Better-Line-Charts-in-Dynamics-CRM-2011-part-I.aspx">part I</a> of this series, I showed how to query Microsoft Dynamics CRM for aggregate data using FetchXML and then pass the results to <a href="http://www.flotcharts.org">Flot</a> to generate a line chart. In this second part, I will expand on that to show how to query for and chart multi-series data.</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/01/26/better-line-charts-in-dynamics-crm-2011-part-ii/</link><guid isPermaLink="false">5a5837216636a30001b97697</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[data visualizations]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[jQuery]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Sun, 27 Jan 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>In <a href="https://alexanderdevelopment.net/post/2013/01/24/Better-Line-Charts-in-Dynamics-CRM-2011-part-I.aspx">part I</a> of this series, I showed how to query Microsoft Dynamics CRM for aggregate data using FetchXML and then pass the results to <a href="http://www.flotcharts.org">Flot</a> to generate a line chart. In this second part, I will expand on that to show how to query for and chart multi-series data. For my example today, I will be creating a chart that shows the number of contacts created by date and state (address, not statecode). In my CRM instance, I have created a set of contacts using characters from Cohen brothers movies. (Please, hold your &quot;Big Lebowski&quot; quotes.)</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/01/contacts.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/01/contacts.PNG#img-thumbnail" alt="Contacts"></a></p>
<p><strong>Changes to the previous approach</strong></p>
<p>There are three main things we have to do differently here than before:</p>
<ol>
<li>Update the FetchXML query to include an additional group-by field</li>
<li>Update the results parser to handle the additional group-by field</li>
<li>Send Flot an array of data series instead of just one</li>
</ol>
<p>In addition to that, I have improved the original code in two more ways:</p>
<ol>
<li>Fill in missing date values with 0 so the shape of the line better reflects reality</li>
<li>Shade weekend days in gray on the chart grid to help break up the weeks and highlight areas in which we might logically expect no activity to occur</li>
</ol>
<p><strong>Updated FetchXML</strong></p>
<p>Changing the FetchXML query is easy. We just have to add the address1_stateorprovince field:</p>
<pre><code>&lt;fetch distinct='false' mapping='logical' aggregate='true'&gt;  
&lt;entity name='contact'&gt;  
&lt;attribute name='fullname' alias='plotValue' aggregate='count' /&gt;  
&lt;attribute name='address1_stateorprovince' groupby='true' alias='seriesLabel' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='day' alias='day' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='month' alias='month' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='year' alias='year' /&gt;  
&lt;/entity&gt;  
&lt;/fetch&gt;
</code></pre>
<p>The field we will use to create the data series is aliased as &quot;seriesLabel&quot; so we can have as generic a results parsing method as possible.</p>
<p><strong>Updated results parser</strong></p>
<p>The manner in which I wrote the getKeyValPairs function in part I won't return the seriesLabel field as part of the return object because only the numeric values come back in the a:FormattedValues element. The seriesLabel field is available via the a:Attributes element, so this required a minor change to my XML find logic. If you have downloaded my previous charting sample, you should be able to update the getKeyValPairs function in it with the newer version here without any issues.</p>
<pre><code>function getKeyValPairs(entity, valuefield) {  
/// &lt;summary&gt;  
/// extracts an aggregate value and grouping components from a FetchXML response entity element and returns them in an array  
/// &lt;/summary&gt;  
var outputArray = new Array();  
  
//first, get the aggregate value using its alias (&quot;plotValue&quot; in the original example)  
var pointValue = parseFloat(entity.find(&quot;a\\:KeyValuePairOfstringstring&quot;).filter(function() {  
return $(this).find('b\\:key').text() == valuefield;  
}).find(&quot;b\\:value&quot;).text().replace(/,/g,''));  
var groupingArray = [];  
  
//second, get the values for the group-by fields  
//unlike previous example, this uses the a:KeyValuePairOfstringanyType element   
//so we go down an extra &quot;value&quot; level when populating the value variable  
entity.find(&quot;a\\:KeyValuePairOfstringanyType&quot;).each(function() {  
return $(this).find('b\\:key').text() != valuefield;  
}).each(function() {  
var xmlElement = $(this);  
var key = xmlElement.find(&quot;b\\:key&quot;).text();  
var value = xmlElement.find(&quot;b\\:value&quot;).find(&quot;a\\:Value&quot;).text();  
var groupingText = '&quot;' + key + '&quot;:&quot;' + value + '&quot;';  
groupingArray.push(groupingText);  
});  
var stringToEval = groupingArray.join();  
var dateFields = eval(&quot;({&quot;+stringToEval+&quot;})&quot;);  
outputArray.push(pointValue);  
outputArray.push(dateFields);  
  
return outputArray;  
}
</code></pre>
<p><strong>Sending Flot the data</strong></p>
<p>Flot expects data to be passed as an array of objects like this:</p>
<pre><code>{   
label: &quot;Series Label&quot;,   
data: [[x1,y1],[x2,y2]...   
}
</code></pre>
<p>In our example, we would have a separate object for each state's data. To build the array of data objects, we do the following:</p>
<ol>
<li>Get a list of unique series labels (states)</li>
<li>Create a holding array for each series' data points</li>
<li>Assign each data point to its correct series in the holding array</li>
<li>Build the data array Flot expects from the holding array</li>
</ol>
<p>As part of building the data array for Flot, we also do some date manipulation to fill in missing dates with 0 values.</p>
<p>Here are the functions that do all of this:</p>
<pre><code>function processData(xml) {  
/// &lt;summary&gt;  
/// charts data returned in a FetchXML response using Flot  
/// &lt;/summary&gt;  
  
alert(&quot;Charting started&quot;);  
  
//array to hold series labels  
var seriesList = [];  
  
//array to hold the series data before we get it ready for flot  
var pointSeries = [];  
  
//array to hold data to pass to flot  
var dataSeries = [];  
  
//array to hold all each unique date in our data set   
//this is so we can show dates with no data between the start and finish dates as 0  
var dateArray = [];  
  
//loop through xml and extract data from each &quot;entity&quot; element  
$(&quot;#chartdiv&quot;).append(&quot;Starting XML parsing . . . &lt;br /&gt;&quot;);  
$(xml).find(&quot;a\\:Entity&quot;).each(function() {  
//pass the element to a function that extracts the aggregate value and the &quot;group by&quot; values  
//&quot;plotValue&quot; is the FetchXML alias for the data we want to display  
var pointData = getKeyValPairs($(this),&quot;plotValue&quot;);   
  
//for each unique series label value  
if(seriesList.indexOf(pointData[1].seriesLabel) == -1) {  
//add label to array of labels  
seriesList.push(pointData[1].seriesLabel);  
  
//instantiate a new array to hold data for this series  
pointSeries.push(new Array());  
}  
  
//Flot requires datetimes to be passed as timestamp values  
var pointDate = new Date(pointData[1].year, pointData[1].month-1, pointData[1].day);  
var timestamp = pointDate.getTime();  
  
//for each unique date value  
if(dateArray.indexOf(timestamp) == -1) {  
//add date timestamp to array of dates  
dateArray.push(timestamp);  
}  
  
//get the index of the series to which this particular value corresponds  
var seriesNumber = seriesList.indexOf(pointData[1].seriesLabel);  
  
//add this particular data value to the correct array in the point series array  
pointSeries[seriesNumber].push([timestamp, pointData[0]]);  
  
});  
  
//sort the unique dates so we can find the min and max dates later  
dateArray.sort(function(a,b){return a-b;});  
  
//we have a function that fills in missing dates with 0 values  
//so to make sure all series have the same set of data, we will add a dummy date to both ends of the range with 0 values  
//after we have &quot;filled out&quot; any missing values in the series, we will remove the dummy dates  
//get milliseconds per day so we can just add/subtract the value of the &quot;day&quot; variable later  
var minute = 1000 * 60;  
var hour = minute * 60;  
var day = hour * 24;  
  
//for each series  
for(var i=0; i&lt;seriesList.length; i++) {  
//the label we pass to Flot is the value from the series label array  
var seriesLabel = seriesList[i];  
  
//get a time series data variable from the correct array in the pointseries aray  
var tsData = pointSeries[i];  
  
//add a day with a 0 value to the beginning of the series  
tsData.push([dateArray[0]-day,0]);  
  
//add a day with a 0 value to the end of the series  
tsData.push([dateArray[dateArray.length-1]+day,0]);  
  
//sort the data points by date  
tsData.sort(function(a,b){return a[0]-b[0];});  
  
//fill in missing dates with 0-value points  
tsData = newDataArray(tsData);  
  
//remove the first &quot;dummy&quot; date  
tsData.shift();  
  
//remove the last &quot;dummy&quot; date  
tsData.pop();  
  
//create a new object to represent this series  
var seriesObj = new Object();  
  
//set a label property  
seriesObj.label = seriesLabel;  
  
//set a data property  
seriesObj.data = tsData;  
  
//add this object to the dataseries array that will be passed to Flot  
dataSeries.push(seriesObj);  
}  
  
//plot the data with some display options  
//see examples and API documentation at http://www.flotcharts.org/  
$.plot($(&quot;#chartdiv&quot;),   
dataSeries, {   
series: {  
lines: { show: true },  
points: { show: true }  
},   
grid: {   
hoverable: true ,  
markings: weekendAreas //calls the weekendAreas function to shade weekend days in gray  
},  
xaxis: {   
tickLength: 5,  
mode: &quot;time&quot;,  
timeformat: &quot;%m/%d/%y&quot;  
},  
yaxis: {  
tickDecimals: 0,  
min: 0  
}  
}  
);  
  
alert(&quot;Charting complete&quot;);  
}  
  
//this function is used to fill in the missing date values with 0 values  
//taken from http://stackoverflow.com/questions/14522667/how-to-configure-flot-to-draw-missing-time-series-on-y-axis-at-point-zero  
function newDataArray(data) {  
var startDay = data[0][0],  
newData = [data[0]];  
  
for (i = 1; i &lt; data.length; i++) {  
var diff = dateDiff(data[i - 1][0], data[i][0]);  
var startDate = new Date(data[i - 1][0]);  
if (diff &gt; 1) {  
for (j = 0; j &lt; diff - 1; j++) {  
var fillDate = new Date(startDate).setDate(startDate.getDate() + (j + 1));  
newData.push([fillDate, 0]);  
}  
}  
newData.push(data[i]);  
}  
return newData;  
}  
  
  
/* helper function to find date differences*/  
function dateDiff(d1, d2) {  
return Math.floor((d2 - d1) / (1000 * 60 * 60 * 24));  
}
</code></pre>
<p><strong>Format for the weekends</strong></p>
<p>The final difference from part I is calling a custom function to format the weekends on the chart. This is done in this part of the processData function above:</p>
<pre><code>grid: {   
hoverable: true ,  
markings: weekendAreas //calls the weekendAreas function to shade weekend days in gray  
},
</code></pre>
<p>The weekendAreas function:</p>
<pre><code>//helper for returning the weekends in a period  
//taken from http://www.flotcharts.org/flot/examples/visitors/index.html  
function weekendAreas(axes) {  
var markings = [];  
var d = new Date(axes.xaxis.min);  
// go to the first Saturday  
d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 1) % 7))  
d.setUTCSeconds(0);  
d.setUTCMinutes(0);  
d.setUTCHours(0);  
var i = d.getTime();  
do {  
// when we don't set yaxis, the rectangle automatically  
// extends to infinity upwards and downwards  
markings.push({ xaxis: { from: i, to: i + 2 * 24 * 60 * 60 * 1000 } });  
i += 7 * 24 * 60 * 60 * 1000;  
} while (i &lt; axes.xaxis.max);  
  
return markings;  
}
</code></pre>
<p><strong>Trying it out</strong></p>
<p>Here is a complete web page with the code for you to download and try out in your own CRM instance <a href="https://alexanderdevelopment.net/content/images/2013/01/chart_example2.htm">chart_example2.htm (12.34 kb)</a>. Just upload it as you would any other web resource, publish and open.</p>
<p>When I run it in my CRM instance, this chart is generated.</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/01/contact_state_chart.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/01/contact_state_chart.PNG#img-thumbnail" alt="Generated chart"></a></p>
<p>As you can see, the chart gets a little busy, and it's hard to differentiate between the different series where they overlap, but there's a lot more you can do with Flot formatting options to make it look better. Also, I haven't covered everything Flot can do, so I encourage you to look at the Flot <a href="http://www.flotcharts.org/flot/examples/">examples page</a> to see some other possibilities like bar charts, stacked charts, panning/zooming, etc.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Better line charts in Dynamics CRM 2011 - part I]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Earlier this week I posted an <a href="https://alexanderdevelopment.net/post/2013/01/21/FetchXML-JQuery-in-a-Dynamics-CRM-2011-web-resource.aspx">entry</a> about using FetchXML and JQuery in a Dynamics CRM 2011 web resource. The reason I first started looking at those two together was that I wanted to see if I could generate better looking line charts than are available out of the box</p></div>]]></description><link>https://alexanderdevelopment.net/post/2013/01/23/better-line-charts-in-dynamics-crm-2011-part-i/</link><guid isPermaLink="false">5a5837216636a30001b97671</guid><category><![CDATA[Microsoft Dynamics CRM]]></category><category><![CDATA[CRM 2011]]></category><category><![CDATA[programming]]></category><category><![CDATA[data visualizations]]></category><category><![CDATA[FetchXML]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[jQuery]]></category><dc:creator><![CDATA[Lucas Alexander]]></dc:creator><pubDate>Thu, 24 Jan 2013 00:00:00 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Earlier this week I posted an <a href="https://alexanderdevelopment.net/post/2013/01/21/FetchXML-JQuery-in-a-Dynamics-CRM-2011-web-resource.aspx">entry</a> about using FetchXML and JQuery in a Dynamics CRM 2011 web resource. The reason I first started looking at those two together was that I wanted to see if I could generate better looking line charts than are available out of the box (spoiler alert: I did). In this post I will show how to combine FetchXML and JQuery with the <a href="http://www.flotcharts.org/">Flot</a> plotting library to produce line charts from CRM data aggregations.</p>
<p>In my career, one of the data visualizations I have encountered the most is to plot some value over unit time. For example, we can try to measure an agent's productivity by counting the number of phone calls per day. Because of the way Dynamics CRM stores data, if we restrict our queries to its database instead of a data warehouse, generally we can report on actions taken per unit time, but we can't report on how things change over time. We can say Agent X created 100 phone call records last week, but we can't tell how many overdue phone call records Agent X had in the queue yesterday. In my example here, I will show how to plot number of contacts created per day.</p>
<p><strong>Top of the page stuff</strong></p>
<p>Charting with Flot requires jQuery, Flot (obviously) and Excanvas in Internet Explorer. Here is how I pull those libraries in from CDNs, but if your CRM instance is accessed over a LAN, you should host them locally.</p>
<pre><code>&lt;!--[if lte IE 8]&gt;&lt;script language=&quot;javascript&quot; type=&quot;text/javascript&quot; src=&quot;https://cdnjs.cloudflare.com/ajax/libs/flot/0.7/excanvas.min.js&quot;&gt;&lt;/script&gt;&lt;![endif]--&gt;  
&lt;script src=&quot;https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.0.min.js&quot;&gt;&lt;/script&gt;  
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/flot/0.7/jquery.flot.min.js&quot;&gt;&lt;/script&gt;
</code></pre>
<p>Also, Flot doesn't work so well in Internet Explorer quirks mode, so make sure you set the page to display in standards mode by declaring an HTML doctype like so in the first line: <!DOCTYPE html></p>
<p><strong>Writing the query</strong></p>
<p>As I explained previously, if you want to query aggregate data from inside JavaScript, you have to use FetchXML. While researching this topic, the examples I found weren't necessarily the clearest, but MSDN has a good overview <a href="http://msdn.microsoft.com/en-us/library/gg309565">here</a>.</p>
<p>Once you get the hang of the FetchXML syntax, if you can write your query in SQL group-by syntax, it shouldn't be too difficult to translate it to FetchXML. Here is the query we will use to count contacts by their createdon date:</p>
<pre><code>&lt;fetch distinct='false' mapping='logical' aggregate='true'&gt;  
&lt;entity name='contact'&gt;  
&lt;attribute name='fullname' alias='plotValue' aggregate='count' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='day' alias='day' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='month' alias='month' /&gt;  
&lt;attribute name='createdon' groupby='true' dategrouping='year' alias='year' /&gt;  
&lt;/entity&gt;  
&lt;/fetch&gt;
</code></pre>
<p>We have a single data field aliased as plotValue that is equivalent to SQL's count(fullname) as plotValue, and then there are three groupby fields that are based on the createdon field. They have each been given an alias that corresponds to the specific datepart.</p>
<p><strong>Executing the query</strong></p>
<p>To execute the FetchXML and retrieve the results, we will use the same basic technique I showed in my previous post.</p>
<ol>
<li>Get FetchXML query from a textarea field.</li>
<li>Build a SOAP message.</li>
<li>Send the SOAP message to CRM and register a callback function to process the data.</li>
</ol>
<p>To do this, we will use the same function executeFetchCommand, buildFetchRequest and sendQuery methods from my previous post. We will be using a different processData method, though the name will stay the same.</p>
<p><strong>Charting the data</strong></p>
<p>Once the data is returned by CRM, we can generate the chart. To do that, we will do the following:</p>
<ol start="2">
<li>Loop through XML to extract count for each date.</li>
<li>Convert the count and date values to an array of X and Y values for Flot to plot.</li>
<li>Call the Flot plotting method.</li>
<li>Bind an event to our chart to display tooltip messages that show the X and Y values when the user mouses over a specific point.</li>
</ol>
<p>First, our new processData callback function looks like this:</p>
<pre><code>function processData(xml) {  
/// &lt;summary&gt;  
/// charts data returned in a FetchXML response using Flot  
/// &lt;/summary&gt;  
  
alert(&quot;Charting started&quot;);  
  
//create a label for the chart points  
var yLabel = &quot;Contacts created&quot;;  
  
//create an array to hold the plot data  
var series1 = [];  
  
//loop through xml and extract data from each &quot;entity&quot; element  
$(&quot;#chartdiv&quot;).append(&quot;Starting XML parsing . . . &lt;br /&gt;&quot;);  
$(xml).find(&quot;a\\:Entity&quot;).each(function() {  
//pass the element to a function that extracts the aggregate value and the &quot;group by&quot; values  
//&quot;plotValue&quot; is the FetchXML alias for the data we want to display  
var pointData = getKeyValPairs($(this),&quot;plotValue&quot;);   
  
//Flot requires datetimes to be passed as timestamp values  
var dateString = (pointData[1].year + &quot;-&quot; + pointData[1].month + &quot;-&quot; + pointData[1].day).replace(/,/g,'');  
var timestamp = new Date(pointData[1].year.replace(/,/g,''), parseInt(pointData[1].month)-1, pointData[1].day).getTime();  
  
//add x (timestamp) and y (aggregate data value) values to the data series array  
series1.push([timestamp, pointData[0]]);  
});  
  
//sort series array by date - Flot plots in order, so line can look wrong if we don't do this  
series1.sort(function(a,b){return a[0]-b[0];});  
  
//plot the data with some display options  
//see examples and API documentation at http://www.flotcharts.org/  
$.plot($(&quot;#chartdiv&quot;),   
[ { data: series1, label: yLabel} ], {   
series: {  
lines: { show: true },  
points: { show: true }  
},   
grid: { hoverable: true },  
xaxis: {   
tickSize: [1, &quot;day&quot;],  
mode: &quot;time&quot;,  
timeformat: &quot;%m/%d/%y&quot;  
}  
}  
);  
  
alert(&quot;Charting complete&quot;);  
}
</code></pre>
<p>In this method first we loop through the data and pass each element to a getKeyValPairs helper function to extract the necessary fields. It returns an array with the Y value to plot as element 0 and a JSON object containing all other fields as element 1. It looks like this:</p>
<pre><code>function getKeyValPairs(entity, valuefield) {  
/// &lt;summary&gt;  
/// extracts an aggregate value and grouping components from a FetchXML response entity element and returns them in an array  
/// &lt;/summary&gt;  
var outputArray = new Array();  
  
//first get the aggregate value using its alias (&quot;plotValue&quot; in the original example)  
var pointValue = parseFloat(entity.find(&quot;a\\:KeyValuePairOfstringstring&quot;).filter(function() {  
return $(this).find('b\\:key').text() == valuefield;  
}).find(&quot;b\\:value&quot;).text().replace(/,/g,''));  
var groupingArray = [];  
entity.find(&quot;a\\:KeyValuePairOfstringstring&quot;).filter(function() {  
return $(this).find('b\\:key').text() != valuefield;  
}).each(function() {  
var xmlElement = $(this);  
var key = xmlElement.find(&quot;b\\:key&quot;).text();  
var value = xmlElement.find(&quot;b\\:value&quot;).text();  
var groupingText = '&quot;' + key + '&quot;:&quot;' + value + '&quot;';  
groupingArray.push(groupingText);  
});  
var stringToEval = groupingArray.join();  
var dateFields = eval(&quot;({&quot;+stringToEval+&quot;})&quot;);  
outputArray.push(pointValue);  
outputArray.push(dateFields);  
  
return outputArray;  
}
</code></pre>
<p>Once the data fields are returned by they getKeyValPairs method, the processData function creates a timestamp from the supplied month, day and year fields (Flot requires timestamps to plot by datetime), and then adds the timestamp and count to an array.</p>
<p>After the loop is complete, we sort the array by date to make sure the line will be plotted along our points in the correct order. Finally we call the Flot plot function with the data array and some pre-determined options. There are a lot of cool configuration options you can specify for Flot plots, but explaining them is beyond the scope of this point. Please take a look at the Flot <a href="http://people.iola.dk/olau/flot/examples/">examples</a> page for more.</p>
<p>Finally we need some code to do the tooltip display. First we have a generic showTooltip method that will be executed when the mouse moves over a data point. You can customize the style to your liking.</p>
<pre><code>function showTooltip(x, y, contents) {  
/// &lt;summary&gt;  
/// function to show tooltip when user mouses over data points  
/// &lt;/summary&gt;  
$('&lt;div id=&quot;tooltip&quot;&gt;' + contents + '&lt;/div&gt;').css( {  
position: 'absolute',  
display: 'none',  
top: y + 5,  
left: x + 5,  
border: '1px solid #fdd',  
padding: '2px',  
'background-color': '#fee',  
opacity: 0.80  
}).appendTo(&quot;body&quot;).fadeIn(200);  
}
</code></pre>
<p>Then we have code that binds a function to the chart plothover event so that the showTooltip method gets executed at the right time with the right data:</p>
<pre><code>//bind a function to execute the showTooltip function at the appropriate time  
var previousPoint = null;  
$(&quot;#chartdiv&quot;).bind(&quot;plothover&quot;, function (event, pos, item) {  
$(&quot;#x&quot;).text(pos.x.toFixed(2));  
$(&quot;#y&quot;).text(pos.y.toFixed(2));  
  
if (item) {  
if (previousPoint != item.dataIndex) {  
previousPoint = item.dataIndex;  
  
$(&quot;#tooltip&quot;).remove();  
var date = new Date(item.datapoint[0]);  
var x = item.datapoint[0].toFixed(2),  
y = item.datapoint[1];  
  
//call showTooltip with the timestamp converted back to mm/dd/yyyy format  
showTooltip(item.pageX, item.pageY,  
item.series.label + &quot; on &quot; + (parseInt(date.getMonth()+1)) + &quot;/&quot; + date.getDate() + &quot;/&quot; + date.getFullYear() + &quot; = &quot; + y);  
}  
}  
else {  
$(&quot;#tooltip&quot;).remove();  
previousPoint = null;   
}  
  
}); 
</code></pre>
<p><strong>Trying it out</strong></p>
<p>Here is a complete web page with the code for you to download and try out in your own CRM instance <a href="https://alexanderdevelopment.net/content/images/2013/01/chart_example.htm">chart_example.htm (8.30 kb)</a>. Just upload it as you would any other web resource, publish and open. At that point you will be presented with a screen that looks like this:</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/01/chart_fetch_start.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/01/chart_fetch_start.PNG#img-thumbnail" alt="The FetchXML / JQuery / Flot example page"></a></p>
<p>Either leave the pre-populated FetchXML in the textarea or supply your own that does a count by month, day and year. As long as it returns those three group-by fields and a Y value aliased as &quot;plotValue,&quot; it should work. Once you click the &quot;fetch and process&quot; button, you will start to see some output and a couple of status alert windows before the output finally displays. The end result should look like this:</p>
<p><a href="https://alexanderdevelopment.net/content/images/2013/01/chart_fetch_complete.PNG#img-thumbnail"><img src="https://alexanderdevelopment.net/content/images/2013/01/chart_fetch_complete.PNG#img-thumbnail" alt="The FetchXML / JQuery / Flot example page"></a></p>
<p>Of course this chart is actually not that exciting, but once you take a closer look at how you can format the line chart output with Flot, you'll see there are all sorts of interesting things you can do. You can also embed the charts in dashboards as a replacement for the existing Dynamics CRM line chart controls. Stay tuned for my next post when I show how to generate multi-series charts.</p>
</div>]]></content:encoded></item></channel></rss>