<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Rohland de Charmoy &#187; microsoft chart control</title>
	<atom:link href="http://www.rohland.co.za/index.php/tag/microsoft-chart-control/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.rohland.co.za</link>
	<description>Pushing buttons...</description>
	<lastBuildDate>Sat, 04 Feb 2012 16:01:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Custom tooltips and Microsoft’s chart control</title>
		<link>http://www.rohland.co.za/index.php/2009/06/21/custom-tooltips-and-microsoft-chart-control/</link>
		<comments>http://www.rohland.co.za/index.php/2009/06/21/custom-tooltips-and-microsoft-chart-control/#comments</comments>
		<pubDate>Sun, 21 Jun 2009 21:12:16 +0000</pubDate>
		<dc:creator>Rohland</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[asp dotnet]]></category>
		<category><![CDATA[microsoft chart control]]></category>

		<guid isPermaLink="false">http://www.rohland.co.za/?p=28</guid>
		<description><![CDATA[I have been meaning to blog about this topic for a while now because I am interested to find out if anyone else has picked up performance issues when using the Microsoft Chart Controls and the “MapAreaAttributes” property to create custom tooltips. Before going into the mechanics of creating a custom tooltip as suggested by [...]]]></description>
			<content:encoded><![CDATA[<p>I have been meaning to blog about this topic for a while now because I am interested to find out if anyone else has picked up performance issues when using the Microsoft Chart Controls and the “MapAreaAttributes” property to create custom tooltips.</p>
<p>Before going into the mechanics of creating a custom tooltip as suggested by the documentation provided with the charting framework, I thought I would simply outline how you would create an instance of the default styled tooltip:</p>
<div class="code" style="PADDING-BOTTOM: 8px; PADDING-LEFT: 8px; PADDING-RIGHT: 8px; FONT-FAMILY: consolas; BACKGROUND: black; COLOR: white; FONT-SIZE: 10pt; FONT-WEIGHT: bold; PADDING-TOP: 8px">
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">1</span> series.Points.DataBind(data,<span style="COLOR: #a5c25c">&#8220;X&#8221;</span>,<span style="COLOR: #a5c25c">&#8220;Y&#8221;</span>,<span style="COLOR: #a5c25c">&#8220;Tooltip=MyTooltipProperty&#8221;</span>);</p>
</div>
<p> </p>
<p>The code above illustrates the databinding capabilities of the charting control. The <em>data</em> array is made up of a list of objects that are of type <em>Point </em>which is a simple class I created:</p>
<div class="code" style="PADDING-BOTTOM: 5px; PADDING-LEFT: 5px; PADDING-RIGHT: 5px; FONT-FAMILY: consolas; BACKGROUND: black; COLOR: white; FONT-SIZE: 10pt; FONT-WEIGHT: bold; PADDING-TOP: 5px">
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    1</span>     <span style="COLOR: #cc7832">public</span> <span style="COLOR: #cc7832">class</span> <span style="COLOR: #ffc66d">Point</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    2</span>     {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    3</span>         <span style="COLOR: #cc7832">public</span> <span style="COLOR: #cc7832">double</span> X {<span style="COLOR: #cc7832">get</span>;<span style="COLOR: #cc7832">set</span>;}</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    4</span>         <span style="COLOR: #cc7832">public</span> <span style="COLOR: #cc7832">double</span> Y { <span style="COLOR: #cc7832">get</span>; <span style="COLOR: #cc7832">set</span>; }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    5</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    6</span>         <span style="COLOR: #cc7832">public</span> <span style="COLOR: #cc7832">string</span> MyTooltipProperty { <span style="COLOR: #cc7832">get</span>; <span style="COLOR: #cc7832">set</span>; }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    7</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    8</span>         <span style="COLOR: #cc7832">public</span> Point()</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    9</span>         {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   10</span>             <span style="COLOR: #cc7832">this</span><span style="FONT-WEIGHT: normal">.MyTooltipProperty = </span><span style="COLOR: #a5c25c">&#8220;Hello!&#8221;</span>;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   11</span>         }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   12</span>     }</p>
</div>
<p> </p>
<p>From the above it is obvious that each data point’s tooltip will look like something like this:</p>
<p><img class="alignleft size-full wp-image-33" title="Normal tooltip" src="http://www.rohland.co.za/wp-content/uploads/2009/06/NormalTooltip.jpg" alt="Normal tooltip" width="244" height="236" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>The tooltip is simply rendered using the relevant browser’s default implementation for elements.</p>
<p><strong>Custom Tooltips:</strong></p>
<p>You may be aware of the charting framework’s capability for creating rich HTML tooltips using the <em>MapAreaAttributes</em> property. As illustrated in an example provided with the framework you could create an HTML tooltip using code similar to that shown below:</p>
<div class="code" style="PADDING-BOTTOM: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px; FONT-FAMILY: consolas; BACKGROUND: black; COLOR: white; FONT-SIZE: 10pt; FONT-WEIGHT: bold; PADDING-TOP: 3px">
<p style="MARGIN: 0px">series.Points[j].MapAreaAttributes = <span style="COLOR: #a5c25c">&#8220;onmouseover=\&#8221;DisplayToolTip(&#8216;&lt;strong&gt;Hello From an HTML tooltip&lt;/strong&gt;&#8217;);\&#8221; onmouseout=\&#8221;HideToo</span><span style="COLOR: #a5c25c">ltip();\&#8221;"</span></p>
</div>
<p> </p>
<p>The <em>DisplayTooltip </em>method referenced is a JavaScript method which essentially displays an absolutely positioned element which tracks your mouse position. The method is fired as you hover over the data point area (which is defined by an image area map). The parameter passed to the method is injected into the element as HTML. As you mouse out of the area (the relevant data point) the <em>Hidetooltip </em>method fires and hides the element displaying the custom tooltip. Using this methodology your tooltip could look something like this:</p>
<p> <img class="alignleft size-full wp-image-38" title="HTML tooltip" src="http://www.rohland.co.za/wp-content/uploads/2009/06/htmltooltip.png" alt="HTML tooltip" width="244" height="187" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>This looks promising because it illustrates the capability to extend our tooltips to include images, links etc. however, there is a caveat. I picked up an issue when you have a chart with a large number of data points, or a number of charts on a single page that utilise this feature. I started noticing that page loads took longer than usual. I put together a test page that rendered 40 instances of the same chart as shown above using the default tooltip. With tracing turned on the page took roughly 270ms to render:</p>
<p> <img class="alignleft size-full wp-image-39" title="Default performance" src="http://www.rohland.co.za/wp-content/uploads/2009/06/defaultperf.jpg" alt="Default performance" width="488" height="313" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>By implementing one extra line of code to implement my rich HTML tooltip using the <em>MapAreaAttributes</em> property as outlined earlier, the page took almost 5 seconds to render!</p>
<p> <img class="alignleft size-full wp-image-41" title="Poor performance" src="http://www.rohland.co.za/wp-content/uploads/2009/06/customperf.jpg" alt="Poor performance" width="491" height="316" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>It turns out anyone who dares to use the MapAreaAttributes property is severely penalised! Clearly we can’t put a page into production that takes 5 seconds just to render our charts, so we either need to revert to our dull looking tooltips or look for other ways to achieve rich HTML tooltip functionality.</p>
<p>Now, we know that setting the tooltip property doesn’t seem to have any performance impact but that it doesn’t result in a pretty looking tooltip either, but what if we could use the tooltip property to store the HTML tooltip markup. I know what your thinking:</p>
<p><img class="alignleft size-full wp-image-42" title="Ugly tooltip" src="http://www.rohland.co.za/wp-content/uploads/2009/06/Uglytooltip.jpg" alt="Ugly tooltip" width="244" height="112" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>Yuck. That will certainly have your users scratching their heads. So, what next? So far we know that using the example as provided by the charting documentation has an adverse affect on rendering times so that’s not ideal. Default tooltip styles work without performance issues but don’t allow us to render rich tooltips. Injecting HTML into the default tooltip property means our users need to slap on their XHTML goggles.</p>
<p>Well, there is an option available which I will outline here.  Essentially, it relies on the ability to interpret the default tooltip property and project it into a custom tooltip that we control. If we look at the HTML rendered by the chart control, you will notice an associated image map that looks something like this:</p>
<p><img class="alignleft size-full wp-image-43" title="Image map" src="http://www.rohland.co.za/wp-content/uploads/2009/06/markup.png" alt="Image map" width="514" height="244" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>As you can see, our HTML tooltip detail is sitting inside the title property, encoded of course. If we leave the mark-up untouched and hover over any element on the chart, the default tooltip is rendered with unparsed HTML. Thankfully, we can access this image map using JavaScript to rebuild the image map with mouseover/out events to render our custom tooltip. While this is exactly what setting the <em>MapAreaAttributes</em> property is supposed to do, modifying the rendered HTML to do the same thing bypasses the performance issue noted. I have provided the JavaScript method below which rebuilds the image map. All that is required, from a server side scripting point of view, is the registration of a start-up script to process any chart you wish to load with custom tooltips.</p>
<div class="code" style="PADDING-BOTTOM: 8px; PADDING-LEFT: 8px; PADDING-RIGHT: 8px; FONT-FAMILY: consolas; BACKGROUND: black; COLOR: white; FONT-SIZE: 10pt; FONT-WEIGHT: bold; PADDING-TOP: 8px">
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    1</span> RebuildImageMap: <span style="COLOR: #cc7832">function</span>(id) {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    2</span>     <span style="COLOR: gray">// Fetch the image and grab the imagemap ID</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    3</span>     <span style="COLOR: #cc7832">var</span> map = $(<span style="COLOR: #a5c25c">&#8220;#&#8221;</span> + id).attr(<span style="COLOR: #a5c25c">&#8220;usemap&#8221;</span>);</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    4</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    5</span>     <span style="COLOR: gray">// If the map ID is null, then perhaps there </span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    6</span>     <span style="COLOR: gray">// were no datapoints. Don&#8217;t bother </span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    7</span>     <span style="COLOR: gray">// processing an empty set</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    8</span>     <span style="COLOR: #cc7832">if</span> (map == <span style="COLOR: #cc7832">null</span>)</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">    9</span>         <span style="COLOR: #cc7832">return</span>;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   10</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   11</span>     <span style="COLOR: gray">// Fetch the map element using jQuery and </span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   12</span>     <span style="COLOR: gray">// return the raw HTML element</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   13</span>     <span style="COLOR: #cc7832">var</span> areaMap = $(map)[<span style="COLOR: #6897bb">0</span>];</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   14</span>     <span style="COLOR: #cc7832">if</span> (areaMap == <span style="COLOR: #cc7832">null</span>) {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   15</span>         <span style="COLOR: #cc7832">return</span>;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   16</span>     }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   17</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   18</span>     <span style="COLOR: gray">// Create an empty array to store our new elements</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   19</span>     <span style="COLOR: #cc7832">var</span> elementArray = [];</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   20</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   21</span>     <span style="COLOR: gray">// Iterate over existing map elements and create a new </span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   22</span>     <span style="COLOR: gray">// set with our mouseover/out events</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   23</span>     <span style="COLOR: #cc7832">for</span> (<span style="COLOR: #cc7832">var</span> i = <span style="COLOR: #6897bb">0</span>; i &lt; areaMap.areas.length; i++) {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   24</span>         <span style="COLOR: #cc7832">var</span> oldAreaElement = areaMap.areas[i];</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   25</span>         <span style="COLOR: #cc7832">var</span> element = document.createElement(<span style="COLOR: #a5c25c">&#8220;AREA&#8221;</span>);</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   26</span>         element.shape = oldAreaElement.shape;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   27</span>         element.coords = oldAreaElement.coords;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   28</span>        </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   29</span>         element.tooltip = oldAreaElement.title;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   30</span>         element.onmouseover =</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   31</span>             <span style="COLOR: #cc7832">function</span>() { DisplayTooltip(<span style="COLOR: #cc7832">this</span>.tooltip); };</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   32</span>         element.onmouseout =</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   33</span>             <span style="COLOR: #cc7832">function</span>() { HideTooltip(); };</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   34</span>         element.href = oldAreaElement.href;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   35</span>         elementArray[elementArray.length] = element;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   36</span>     }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   37</span>     <span style="COLOR: gray">// Get rid of the old map elements</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   38</span>     areaMap.innerHTML = <span style="COLOR: #a5c25c">&#8221;</span>;</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   39</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   40</span>     <span style="COLOR: gray">// Add our new elements back in</span></p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   41</span>     <span style="COLOR: #cc7832">for</span> (<span style="COLOR: #cc7832">var</span> i = <span style="COLOR: #6897bb">0</span>; i &lt; elementArray.length; i++) {</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   42</span>         areaMap.appendChild(elementArray[i]);</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   43</span>     }</p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   44</span> </p>
<p style="MARGIN: 0px"><span style="COLOR: #2b91af; FONT-WEIGHT: normal">   45</span> }</p>
</div>
<p> </p>
<p>The code above utilises jQuery which is useful, but not required to get the job done. If you are going to use another framework, just note that the map attribute (which contains the map’s ID) is prefixed with a #. You may want to get rid of that. The code above is a modified<br />
snippet of an existing class. The <em>DisplayTooltip</em> method simply takes the tooltip HTML and loads it into a custom hidden element on the page. It then displays the element and tracks the mouse position so the element moves as the user’s cursor does. The <em>HideTooltip </em>method simply hides the tooltip and resets the HTML content. Using this technique, our HTML tooltip is rendered correctly without using the <em>MapAreaAttributes</em>  property.</p>
<p> <img class="alignleft size-full wp-image-38" title="HTML tooltip" src="http://www.rohland.co.za/wp-content/uploads/2009/06/htmltooltip.png" alt="HTML tooltip" width="244" height="187" /></p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p> </p>
<p>So far I have tested this method of rendering custom tooltips in Firefox, IE 7/8 and Chrome. Its a pity that this was required in the first place. I am really not sure why setting the <em>MapAreaAttributes</em>  property has such a huge impact on rendering times. If anyone could shed light on the matter, please feel free to post the detail! For now, the implementation above will suffice. Since the image map processing is performed on the client side, there is no effect on the server side processing time.</p>
<p>Hope this helps someone out there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.rohland.co.za/index.php/2009/06/21/custom-tooltips-and-microsoft-chart-control/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

