سؤال

I am attempting to generate a custom tooltip using Microsoft Chart Controls. Microsoft Chart Controls support the ability to use keywords which helps automate the data you wish to display.

For example,

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 above code, "#VALY" and "#VALX" are keywords. At run-time these keywords are replaced with actual values. In my scenario, #VALY is a double and #VALX is a date-time.

Observe:

enter image description here

Now, this works perfectly fine if I use the data series' tooltip property. Unfortunately, FireFox and Opera do not (easily) support multi-line tooltips. I am attempting to illicit this feature out of them by using Custom Tooltips.

As such, I have the onmouseover and onmouseout code -- this is javascript which is responsible for the tooltip.

The problem is that when #VALX is evaluated it contains illegal javascript characters. This causes the error message "Uncaught SyntaxError: Unexpected token ILLEGAL"

Note that I have wrapped the tooltip with the method JavaScriptStringLiteral. 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("\"");

        // If a Javascript tag contains "</script>", then it terminates a
        // script block.  Start by replacing each 's'/'S' with an escape
        // sequence so it doesn't trigger this.
        return scriptTagRegex.Replace(
            sb.ToString(),
            m => (m.Value[0] == 's' ? "\\u0073" : "\\u0053") + m.Value.Substring(1));
    }

If #VALX was not run-time evaluated, I believe this utility method would solve my issue. But, as such, the utility function evalutes "#VALX" as a string literal. Then, after filtering no illegal characters, #VALX is evaluated and places illegal characters into my javascript.

Is there a way of preventing this issue? Something equivilant to the "@" character for paths in C#?

EDIT: I FIGURED OUT THE SOLUTION AND IT IS DUMB.

foreach (HistoricalDataValue value in data)
{
    series.Points.AddXY(string.Format("{0:d}{1}{0:T}", value.TimeStamp, "\\n"), value.AttributeValue);
}

Note that this says "\\n". This used to say Environment.NewLine, but this does not work. IN ADDITION, if you use Environment.NewLine -OR- "\n" you can't edit "#VALX" later because of run-time evaluation. THUS, you have to use an escaped out newline when adding the X value, so that when #VALX gets it it is already formatted properly.

Thanks

هل كانت مفيدة؟

المحلول

When you call the JavaScriptStringLiteral your code already opened a single-quote string, while that function returns a string already wrapped in double quotes.

You should strip first and last character from what JavaScriptStringLiteral returns.

نصائح أخرى

Why not use the Microsoft.Security.Application.JavaScriptEncode(string input) function in the AntiXss library

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top