I am in the process of creating a custom tooltip using Microsoft Chart Controls. These controls provide support for using keywords to automate the data you want to display.
For instance,
string toolTip = string.Format("<div> {0}: {1} {3} ({2}) </div>", seriesName, "#VALY", "#VALX", "<br>");
series.MapAreaAttributes = "onfocus=\"if(this.blur)this.blur();\" onmouseover=\"DisplayTooltip('" + JavaScriptStringLiteral(toolTip) + "');\" onmouseout=\"DisplayTooltip('');\"";
In the code above, " #VALY" and " #VALX" serve as keywords. These keywords are replaced with actual values at runtime. In my case, #VALY represents a double value and #VALX represents a date-time.
Take a look:
This method works well when using the data series' tooltip property. However, Firefox and Opera do not easily support multi-line tooltips. To address this, I am trying to implement Custom Tooltips.
Therefore, I have included the onmouseover and onmouseout code - these are JavaScript functions responsible for the tooltip.
The issue arises when #VALX is evaluated and contains illegal JavaScript characters. This triggers the error message "Uncaught SyntaxError: Unexpected token ILLEGAL".
It's important to note that the tooltip is enclosed within the JavaScriptStringLiteral method. Here is the utility function:
private static readonly Regex scriptTagRegex = new Regex("script", RegexOptions.IgnoreCase | RegexOptions.Multiline);
/// <summary>
/// Processes the provided string, creating a quoted JavaScript string literal.
/// </summary>
/// <param name="str">The string to process</param>
/// <returns>A string containing a quoted JavaScript string literal</returns>
public static string JavaScriptStringLiteral(string str)
{
var sb = new StringBuilder();
sb.Append("\"");
foreach (char c in str)
{
switch (c)
{
case '\"':
sb.Append("\\\"");
break;
case '\\':
sb.Append("\\\\");
break;
case '\b':
sb.Append("\\b");
break;
case '\f':
sb.Append("\\f");
break;
case '\n':
sb.Append("\\n");
break;
case '\r':
sb.Append("\\r");
break;
case '\t':
sb.Append("\\t");
break;
default:
int i = (int)c;
if (i < 32 || i > 127)
{
sb.AppendFormat("\\u{0:X04}", i);
}
else
{
sb.Append(c);
}
break;
}
}
sb.Append("\"");
return scriptTagRegex.Replace(
sb.ToString(),
m => (m.Value[0] == 's' ? "\\u0073" : "\\u0053") + m.Value.Substring(1));
}
If #VALX is not evaluated at runtime, this utility method should resolve the issue. However, since #VALX is evaluated, the utility function treats it as a string literal. Subsequently, after removing illegal characters, #VALX is evaluated and introduces illegal characters into my JavaScript.
Is there a way to prevent this problem? Is there an equivalent to the "@" character for file paths in C#?
I found a solution to the problem, which is quite simple.
foreach (HistoricalDataValue value in data)
{
series.Points.AddXY(string.Format("{0:d}{1}{0:T}", value.TimeStamp, "\\n"), value.AttributeValue);
}
Note that it is specified as "\\n". Initially, it was Environment.NewLine, but that did not work. Moreover, if you use Environment.NewLine or "\n", you won't be able to edit "#VALX" later due to runtime evaluation. Therefore, you need to use an escaped newline when adding the X value, so that when #VALX retrieves it, it is already formatted correctly.