jquery .ajax,谷歌可视化和让他们一起工作的问题

时间:2022-08-25 18:09:03

I'm trying to use jquery's .ajax(), google visualisation annotated timeline and one of the google datatable helpers together. Ultimately what i'm after is having a link on a page and when the user clicks it data is loaded asynchronously via jquery.ajax(), returned as google visualisation compliant JSON and passed to the charting API to generated the annotated timeline.

我正在尝试使用jquery的.ajax(),谷歌可视化注释时间轴和谷歌数据表助手之一。最终我正在追求的是在页面上有一个链接,当用户点击它时,数据通过jquery.ajax()异步加载,返回谷歌可视化兼容JSON并传递给图表API以生成带注释的时间轴。

Along the lines of the guidance on the datatable helper wiki page, the vanilla version works fine, i.e.

根据数据表助手维基页面上的指导,香草版本工作正常,即

  1. no ajax loading of the data (instead json data is injected into page via a call to Page.ClientScript.RegisterStartupScript() in the Page_Load() code behind method) and
  2. 没有ajax加载数据(而是通过调用Page_Load()代码后面的方法中的Page.ClientScript.RegisterStartupScript()将json数据注入到页面中)

  3. no click event associated with a link on page
  4. 没有与页面上的链接关联的点击事件

Here's the vanilla working code:

这是香草工作代码:

CodeBehind:

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        DataTable dt = PopulateDatatable();
        ConvertToGoogleDatatable(dt);
    }

    private void ConvertToGoogleDatatable(DataTable dt)
    {
        // Use of Bortosky helper class to generated 
        // google visualisation compliant json
        GoogleDataTable gdt = new GoogleDataTable(dt);
        using (MemoryStream memoryStream = new MemoryStream())
        {
            gdt.WriteJson(memoryStream);
            memoryStream.Position = 0;
            StreamReader sr = new StreamReader(memoryStream);
            Page.ClientScript.RegisterStartupScript(this.GetType(), "vis", string.Format("var jsonData = {0}", sr.ReadToEnd()), true);
        }
    }

    private DataTable PopulateDatatable()
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("Date", typeof(System.DateTime));
        dt.Columns.Add("High", typeof(System.Double));
        dt.Columns.Add("Low", typeof(System.Double));
        dt.Columns.Add("Closing Price", typeof(System.Double));

        using (StreamReader sr = new StreamReader(@"data.csv"))
        {
            string line;
            line = sr.ReadLine();

            while ((line = sr.ReadLine()) != null)
            {
                string[] lineParts = line.Split(',');
                dt.Rows.Add(new object[] { Convert.ToDateTime(lineParts[0]), lineParts[2], lineParts[3], lineParts[4] });
            }
        }
        return dt;
    }
}

XHTML:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="GoogleVis._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<script type='text/javascript' src='http://www.google.com/jsapi'></script>
<script type='text/javascript'>

    google.load('visualization', '1', {'packages':['annotatedtimeline']});
    google.setOnLoadCallback(drawChart);

    function drawChart() {
    var data = new google.visualization.DataTable(jsonData, 0.5);
    var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));
    chart.draw(data, {displayAnnotations: true});
    }

</script>
<title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
     <div id='chart_div' style='width: 90%; height: 500px;'></div>
    </div>
    </form>
</body>
</html>

When i then try to refactor in order to wrap the request for data in a PageMethod to be called via .ajax() and attach a click event things fall apart. In particular, debugging i can see that the .ajax() call is working fine and json data is being returned. The json data is also been passed correctly to the drawChart() method but execution doesn't get beyond this line:

当我然后尝试重构以包含要通过.ajax()调用的PageMethod中的数据请求并附加单击事件时,事情就会崩溃。特别是,调试我可以看到.ajax()调用工作正常,并返回json数据。 json数据也已正确传递给drawChart()方法,但执行不会超出此行:

var data = new google.visualization.DataTable(msg.d, 0.5);

The browser just stays at saying "Transferring data from google.com..."

浏览器只是说“从google.com传输数据......”

Here's the non-working code:

这是非工作代码:

CodeBehind:

public partial class _Default : System.Web.UI.Page
{
    [WebMethod]
    public static string AjaxMethod()
    {
        DataTable dt = PopulateDatatable();
        return ConvertToGoogleDatatable(dt);
    }

    private static string ConvertToGoogleDatatable(DataTable dt)
    {
        GoogleDataTable gdt = new GoogleDataTable(dt);
        using (MemoryStream memoryStream = new MemoryStream())
        {
            gdt.WriteJson(memoryStream);
            memoryStream.Position = 0;
            StreamReader sr = new StreamReader(memoryStream);
            // FOLLOWING 3 LINES DIFFERENT FROM VANILLA VERSION ABOVE!
            string returnValue = sr.ReadToEnd();
            sr.Close();
            return returnValue;
        }
    }

    private static DataTable PopulateDatatable()
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("Date", typeof(System.DateTime));
        dt.Columns.Add("High", typeof(System.Double));
        dt.Columns.Add("Low", typeof(System.Double));
        dt.Columns.Add("Closing Price", typeof(System.Double));

        using (StreamReader sr = new StreamReader(@"data.csv"))
        {
            string line;
            line = sr.ReadLine();

            while ((line = sr.ReadLine()) != null)
            {
                string[] lineParts = line.Split(',');
                dt.Rows.Add(new object[] { Convert.ToDateTime(lineParts[0]), lineParts[2], lineParts[3], lineParts[4] });
            }
        }
        return dt;
    }
}

XHTML:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="GoogleVis._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<script type='text/javascript' src='http://www.google.com/jsapi'></script>
<script type='text/javascript' src="jquery-1.3.2.min.js"></script>
<script type='text/javascript'>

    $(document).ready(function() {
        $("#Result").click(function() {
            $.ajax({
                type: "POST",
                url: "Default.aspx/AjaxMethod",
                data: "{}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function(msg) {
                    google.load('visualization', '1', {'packages':['annotatedtimeline']});
                    google.setOnLoadCallback(drawChart(msg));
                }
            });
        });
    });

    function drawChart(msg) {
        var data = new google.visualization.DataTable(msg.d, 0.5);
        var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));
        chart.draw(data, {displayAnnotations: true});
    }

</script>
<title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <div id="Result"><a href="#">Load!</a></div>
     <div id='chart_div' style='width: 90%; height: 500px;'></div>
    </div>
    </form>
</body>
</html>

I've also found that stripping most of the functionality out and modifying the vanilla working version javascript by wrapping it in $(document).ready(function() {} (shown below) has the same damaging effect.

我还发现通过将它包装在$(document).ready(function(){}(如下所示)中来剥离大部分功能并修改vanilla工作版本javascript具有相同的破坏性效果。

<script type='text/javascript'>
    $(document).ready(function() {

        google.load('visualization', '1', {'packages':['annotatedtimeline']});
        google.setOnLoadCallback(drawChart);

        function drawChart() {
        var data = new google.visualization.DataTable(jsonData, 0.5);
        var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));
        chart.draw(data, {displayAnnotations: true});
        }
    }
</script>

So... any ideas about how i should be chaining these calls together to get it to work???

那么......关于我应该如何将这些调用链接在一起以使其工作的任何想法?

Thanks

EDIT:

The following rearranging of the code also doesn't seem to work - In particular the alert message in LoadData() is never displayed!

以下重新排列代码似乎也不起作用 - 特别是LoadData()中的警报消息永远不会显示!

$(document).ready(function() {
  $("#Result").click(function() {
        google.load('visualization', '1', {'packages':['annotatedtimeline']});
        google.setOnLoadCallback(LoadData)
  });
});

function LoadData(){
    alert("breakpoint");
    $.ajax({
      type: "POST",
      url: "Default.aspx/AjaxMethod",
      data: "{}",
      contentType: "application/json; charset=utf-8",
      dataType: "json",
      success: function(msg) {
            var jsonData = msg.d;

            var data = new google.visualization.DataTable(jsonData, 0.5);
            var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));
            chart.draw(data, {displayAnnotations: true});
      }
    });
};

EDIT 2:

Yet another variation that doesn't work!!!

另一种不起作用的变化!!!

The following results in the data being loaded (i.e. .ajax() call works) but i then get a this.t undefined error from the google javascript.

以下结果导致数据被加载(即.ajax()调用工作),但我从谷歌javascript得到一个this.t未定义的错误。

<script type='text/javascript' src="jquery-1.3.2.min.js"></script>
<script type='text/javascript'>

    google.load('visualization', '1', {'packages':['annotatedtimeline']});
    google.setOnLoadCallback(LoadData);

    function LoadData() {
        $.ajax({
            type: "POST",
            url: "Default.aspx/AjaxMethod",
            data: "{}",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function(msg) {
                var data = new google.visualization.DataTable(msg.d, 0.5);
                var chart = new google.visualization.AnnotatedTimeLine(document.getElementById('chart_div'));
                chart.draw(data, {displayAnnotations: true});
            }
        });
    }

</script>

Wrapping the above in $(document).ready(function() {}); gets me back to the previous "Transferring data from google.com" and it just sits there. The ajax call is not made and when i hit stop to stop loading the page i get "$ is not defined, $.ajax({" in firebug.

在$(document).ready(function(){})中包含上述内容;让我回到之前的“从google.com传输数据”,它就在那里。没有进行ajax调用,当我点击停止以停止加载页面时,我得到“$未定义,$ .ajax({”在firebug中。

Frustrating!

Any ideas?

1 个解决方案

#1


jQuery and Google Visualizations will play nicely together if you delay executing the jQuery ready function until google has loaded. This may not be the ideal approach, but it works around the problem of invoking code in either library before it is guaranteed to be loaded.

如果你延迟执行jQuery ready函数直到谷歌加载,jQuery和谷歌可视化将很好地一起玩。这可能不是理想的方法,但它可以解决在保证加载之前在任一库中调用代码的问题。

Example:

google.load('visualization','1',{packages:['piechart']);
function loaded() {
  if (MyLibrary.googleLoaded) {
    MyLibrary.googleLoaded();
  } else {
    setTimeout(loaded, 50);
  }
}
google.setOnLoadCallback(loaded);

and:

$(document).ready(function() {
  MyLibrary.googleLoaded = function() {
    // whatever you would have put in $(document).ready();
  };
});

...which allows both libraries to bind their onLoad handlers independently and delay execution of code depending on both libraries until they are both ready.

...允许两个库独立地绑定其onLoad处理程序,并根据两个库延迟执行代码,直到它们都准备就绪。

#1


jQuery and Google Visualizations will play nicely together if you delay executing the jQuery ready function until google has loaded. This may not be the ideal approach, but it works around the problem of invoking code in either library before it is guaranteed to be loaded.

如果你延迟执行jQuery ready函数直到谷歌加载,jQuery和谷歌可视化将很好地一起玩。这可能不是理想的方法,但它可以解决在保证加载之前在任一库中调用代码的问题。

Example:

google.load('visualization','1',{packages:['piechart']);
function loaded() {
  if (MyLibrary.googleLoaded) {
    MyLibrary.googleLoaded();
  } else {
    setTimeout(loaded, 50);
  }
}
google.setOnLoadCallback(loaded);

and:

$(document).ready(function() {
  MyLibrary.googleLoaded = function() {
    // whatever you would have put in $(document).ready();
  };
});

...which allows both libraries to bind their onLoad handlers independently and delay execution of code depending on both libraries until they are both ready.

...允许两个库独立地绑定其onLoad处理程序,并根据两个库延迟执行代码,直到它们都准备就绪。