【问题标题】:Generating Google Chart on the fly with JSP使用 JSP 即时生成 Google 图表
【发布时间】:2011-10-01 10:26:30
【问题描述】:

我正在使用 Google 折线图来绘制使用 JSP 从数据库中提取的值。我目前有它的工作。 data.addColumn 语句是在页面加载时从数据库查询中生成的。

我的问题是我还想要几个组合框,可以用来选择 x 轴的最小值和最大值,然后更新图表。目前我能想到的唯一方法是使用新的获取参数刷新页面。

我宁愿以某种方式只刷新图表本身而不重新加载整个页面。这可能吗?有没有办法覆盖脚本标签然后重新加载图表?还是有其他方法?

编辑:我无法弄清楚如何将数据从数据库传递到加载页面。这是我的代码:

loader.html(包含图表和日期字段的页面):

<!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>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">
        google.load('visualization', '1', {packages: ['corechart']});
    </script>
    <script type="text/javascript">
        function loadChart()
        {
            var xmlhttp;            
            var minDate = document.getElementById('startDate').value;
            var maxDate = document.getElementById('endDate').value;

            if (!minDate)
                minDate = 'none';
            if (!maxDate)
                maxDate = 'none';

            if (window.XMLHttpRequest)
            {// code for IE7+, Firefox, Chrome, Opera, Safari
                xmlhttp = new XMLHttpRequest();
            }
            else
            {// code for IE6, IE5
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.onreadystatechange=function()
            {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
                {
                    document.getElementById('lineChart').innerHTML = xmlhttp.responseText;
                }
            }
            xmlhttp.open("GET", "chart-loader.jsp?min=" + minDate + '&max=' + maxDate, true);
            xmlhttp.send();
        }
    </script>
</head>

<body>
    <div id="container">

        <div id="lineChart"></div>

        <div id="startDateBox">
            <label for="startDate">Min Date:</label>
            <input id="startDate" type="text" />
        </div>
        <div id="endDateBox">
            <label for="endDate">Max Date:</label>
            <input id="endDate" type="text" />
        </div>
        <input type="button" value="Update" id="updateBtn" onclick="loadChart()" />

    </div> <!-- End container -->
</body>
</html>

chart-loader.jsp(用于获取数据并加载图表)

<%@ page import="java.sql.*, java.util.ArrayList" %>
<%      
    Connection conn;

    try {
        Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
        conn = DriverManager.getConnection("jdbc:microsoft:sqlserver://...", "user", "pass");
    }
    catch(SQLException e) 
    {
        out.println("SQLException: " + e.getMessage() + "<br/>");
        while((e = e.getNextException()) != null)
            out.println(e.getMessage() + "<br/>");
        throw new UnavailableException(this, "Cannot connect with the specified database.");
    }

    String data = "";
    String minDate = (String)request.getParameter("min");
    String maxDate = (String)request.getParameter("max");
    try
    {
        ResultSet rs;
        Statement stmt = conn.createStatement();
        if (minDate.equals("none") || maxDate.equals("none")) // First load, use whole table
        {
            rs = stmt.executeQuery("SELECT ...");
        }
        // ... more possible queries

        ArrayList<String> ptVals = new ArrayList<String>();
        ArrayList<String> colDates = new ArrayList<String>();

        while (rs.next())
        {
            ptVals.add(rs.getString("avgvalue"));
            colDates.add(rs.getString("collectiondate"));
        }           
        // ptVals.size()
        for (int i = 0; i < 5; i++)
            data += "\t\t\tdata.addRow(['" + colDates.get(i) + "'," + ptVals.get(i) + "]);\n";  

        // ... Use out.print to spit out script. 
    }
    catch(SQLException e)
    {
        data = "SQLException: " + e.getMessage() + "<br/>";
        while((e = e.getNextException()) != null)
            data += e.getMessage() + "<br/>";           
    }       
    finally
    {   // Clean up resources, close the connection.
        if(conn != null)
        {
            try { conn.close(); }
            catch (Exception ignored) {}
        }
    }
%>

加载图表的原始脚本

<script type="text/javascript">
    function drawVisualization() 
    {
        // Create and populate the data table.
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Date');
        data.addColumn('number', 'Temperature');
        data.addRow(["01/01/11", 70.2]);
        data.addRow(["01/02/11", 70.0]);
        data.addRow(["01/03/11", 69.8]);
        data.addRow(["01/04/11", 70.1]);
        // Create and draw the visualization.
        new google.visualization.LineChart(document.getElementById('lineChart')).
            draw(data, {backgroundColor: 'transparent',
                        width: 700, height: 400,
                        legend: 'none',
                        hAxis: {title: 'Dates', titleTextStyle: {color: 'black', fontSize: 12, fontName: 'Verdana, Arial'}},
                        vAxis: {title: 'Temperature', titleTextStyle: {color: 'black', fontSize: 12, fontName: 'Verdana, Arial'}},
                        chartArea: {left: 80, top: 20}
                    }
                );
    }

    google.setOnLoadCallback(drawVisualization);
</script> 

谢谢, 瑞恩

【问题讨论】:

    标签: javascript ajax jsp code-generation google-visualization


    【解决方案1】:

    我们正是在我工作的地方做的(我的意思是刷新谷歌图表)。我们所做的是在没有图表的情况下加载页面,只需 Ajax 将其加载到它需要的任何容器中。然后,当您更改其上的任何内容时,让 ajax 重新加载它,发送您需要的任何参数到 JSP(获取新图表)。

    编辑:如果这没有意义,图表本身实际上是在它自己的 JSP 上,它独立地注入到页面中(并刷新)。

    所以我们的流程是这样的:

    渲染主页(图表尚未渲染)。在这个页面上,我们输入了这样的内容:

    &lt;div id="chartForData1"&gt;&lt;/div&gt;

    &lt;script&gt;Ajax_inject('chartForData1', 'pageThatGeneratesData1');&lt;/script&gt;

    Ajax_inject 只是我们为将数据加载到元素中的 Ajax 调用的包装器。现在,当页面在用户计算机上呈现时,Ajax_inject(以及所有其他)将执行,从而将相应的呈现 JSP 加载到相关的div。这些 JSP 的唯一目的是采用几个参数(或无参数并使用默认值)并为我们呈现一个漂亮漂亮的谷歌图表。

    这样更有意义吗?

    【讨论】:

    • 你是否使用include语句来注入JSP文件?
    • @Ryan:不,我们所做的不是将图表数据直接输出到带有包含的主页面,而是将 Javascript 写入页面以进行 Ajax 调用。加载的图表/页面中包含 Javascript 以侦听更改并重新加载。
    • 我不认为我很关注。当您说 Ajax 调用时,您指的是 Google 的 google.setOnLoadCallback() 还是 google.load()?或者你在谈论定制的东西?你知道任何例子吗?
    • @Ryan:我没有可以分享的例子,但也许我编辑的答案有更清晰的解释......(如果它没有改变,我现在就改变它)
    • 修改后,我有更多的问题。 Ajax_inject 如何加载图表?据我所知,我只能在进行数据库查询后将 JSP 页面中的文本返回到加载页面(假设您使用的是XMLHttpRequest)。您是否返回创建图表的&lt;script&gt;?我在原始帖子中添加了示例代码。再次感谢您迄今为止的所有帮助。
    【解决方案2】:

    我能够让它与 Google Visualization API 一起使用。方法如下:

    我有一个 HTML 页面,其中有一个容器 div 用于图表。 &lt;div id="lineChart"&gt;&lt;/div&gt;

    接下来我在 HTML 页面中有两个 JavaScript 函数。 getChartData() 函数是一个 AJAX 函数,它从两个输入字段中获取日期范围并将它们发送到 JSP 页面。 JSP 页面使用日期在数据库中查询该范围内的记录,将它们格式化为 JavaScript 对象,然后使用 out.print() 将其发送回 HTML 页面。

    一旦 HTML 页面接收到数据,它会使用eval() 将接收到的文本设置为 JavaScript 对象。最后,数据对象被发送到第二个 JavaScript 函数 loadChart(),它使用数据调用 Google 函数并将图表加载到 div

    注意:使用eval()responseText 设置为JavaScript 对象才是真正让这一切正常工作的原因。这使您可以传回许多数据。回到 HTML 页面后,您只需将它们从 JS 对象中拉出即可。您甚至可以在彼此内部传递多个 JS 对象。

    var paramsObj;
    var dataObj;
    eval('paramsObj = ' + xmlhttp.responseText + ";");
    eval('dataObj = paramsObj.data;');
    loadChart(dataObj, paramsObj.title, paramsObj.xLabel);
    

    在这种情况下,我在一个 JS 对象中传递三个参数。 paramsObj.data 是图表数据,它以嵌套对象的形式出现,根据 Google Visualization API 格式化。我不得不再次使用eval() 将嵌套的JS 对象设置为单独的变量,否则它不会正确传递给loadChart() 函数。 paramsObj.titleparamsObj.xLabel 只是字符串。

    【讨论】:

      猜你喜欢
      • 2015-05-28
      • 1970-01-01
      • 2010-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-05
      • 2023-03-15
      相关资源
      最近更新 更多