用 Pentaho AJAX 创建交互式 Dashboard


用 Pentaho AJAX 创建交互式 Dashboard James, Chief Geek, Pentaho 介绍 这篇文档描述了如何使用 Pentaho Open BI 套件的 AJAX 库创建浏览器端交互的 dashboards。 它使用 Pentaho Pre-Configured Installation (PCI ) 提供的 Google Maps Dashboard sample 来解 释。在讨论技术细节之前,简短解释什么是 AJAX,并逐步运行 Google Maps Dashboard sample,其使用 Pentaho AJAX 组件来创建一个交互式的位置智能 dashboard。 AJAX 确切的说,究竟什么是 AJAX?AJAX 表示 'Asynchronous Javascript and XML'。因此,这究 竟意味着什么呢?AJAX 不是一个产品:它是用于构建网页的技术的集合,和以往的技术相 比,其交互性更强(不用采取插件,applets,或 active/x 组件)。 分别介绍如下: Asynchronous Javascript:这意味着网页内的脚本不用重载网页,即可向服务器发出调用获取 信息。这很大程度上改善了复杂网站的可用性和性能,因为用户可和页面内容进行交互,而 不必重新加载 HTML,style-sheets 和图像,也不用看到那些烦人的滚动条。 XML:这指的是向服务器发出调用的结果是 XML。事实上,它可是任何类型的文本, 如 HTML,或 Javascript object notation (JSON),或仅仅是一条响应消息。 Dynamic HTML:不知何故,这脱离了 'AJAX acronym'。这比 'XML' 部分更重要,因为它允 许网页根据脚本和服务器的对话进行动态改变。这可用于修改图片,添加或删除表的行,隐 藏和显示 tabs,移除或修改页面上的文本。我觉得 AJAD 听起来不够酷。 用 AJAX 构建的网页感觉更像一个应用,而不是一个网页。将 Google Maps 和之前的基 于 web 的 mapping 引擎进行比较,就提供了差异的很好的实例。 Pentaho AJAX 在一个网页中使用 Pentaho 的 AJAX 库,你可动态命令 Pentaho BI 平台的 BI 组件生成页面 上要显示的 charts,dials,和表格。你也可执行其他任务,例如初始化数据转换或报表传送 过程。通过让 Pentaho 来执行一个 Action Sequence 来完成这些工作。一个 Action Sequence 是 一组指令,其定义了使用哪些组件,以及如何在它们之间传送数据。创建 Action Sequences 的 更多信息请参考 Creating Pentaho Solutions 指南。 目标读者 这篇文档的开始部分很平时简单,但后面就越来越技术化了。如果你不是一个使用 过 XML 的 Java 开发人员,在 10 页之后的内容,你可能就不感兴趣了。 Pentaho Google Maps Dashboard 'Pentaho Google Maps Dashboard' 是 Pentaho 提供的 sample dashboard,其显示了如何使 用 AJAX 组件创建交互式的网页。 安装 Pentaho Google Maps Dashboard sample 位于 Pentaho Pre-Configured Installation (PCI)。你可 从 Pentaho (http://www.pentaho.org/download/) 下载。你应该使用版本 1.2 GA。这个指南中使 用的实例假设你已经安装了 PCI,其使用默认端口 8080。如果你在安装或运行 PCI 服务器 时出现了问题,请参考 Getting Started Guide。我们这样开始,使用以下 URL 启动 Google Maps Dashboard sample:http://localhost:8080/pentaho/Map。 概述 Google Maps Dashboard sample 显示了一个 map,其上基于 Total Sales key performance indicator (KPI),用有颜色的针显示了每个客户的位置,并加亮显示了他们的相对性能。你 可立即看见根据区域将客户分成了 2 组。如果直接查看数据库中的客户记录,不会这么立即 的显而易见。 为了方便起见,dashboard 提供了链接,允许用户快速放大和确定 West Coast 或 East Coast 的 中心。Total Sales KPI 的 Thresholds(用于用颜色标识 pins)也可使用简单的下拉框在 fly 上 修改。例如 将 lower threshold 增加到 100,000,会把所有的黄色 pins 变成红色。这个功能是 用 Google Maps API 实现的,当用户执行这些 action 中的任何一个时,不会从服务器重新加 载页面。 如何重新用颜色标识 pins 的详细信息请参考下面的 ‘Adding and removing Google Map Markers’。 如何居中和缩放 Google map 的详细信息请参考下面的 'Centering and Zooming Google Maps'。 当用户点击 map 上的 pin 时: 1. 在 Google Maps info-window 中显示了客户的基本信息(customer number,name, location 和 sales)。 2. side-bar 显示一个 pie chart,其显示了客户购买的产品的 mix。 3. side-bar 显示了客户的购买历史的表格。 如果用户修改了 sales,自动刷新 info-window 中的 thresholds dial 以显示新的 thresholds。如 果用户点击了不同的 marker,info-window 移到那个 marker,并刷新自身,显示新客户的信 息,更新 pie chart 和 sales history 表。显示在 info-window,pie chart,和 sales history table 中 的信息均由 Pentaho 服务器动态生成,使用 Pentaho AJAX 组件和库获取和插入进页面中。 如何定义 dial 的详细信息请参考下面的 ‘AJAX Dial’。 如何定义 pie chart 的详细信息请参考下面的 ‘AJAX Pie Chart’。 如何定义 table 的详细信息请参考下面的 ‘AJAX Embedded Report’。 体系结构 Pentaho Google Maps Dashboard 使用 Java Server Page (JSP),其使用 Pentaho Java API, web-based 服务,以及 AJAX 库生成页面上的 images 和表格。 最初,浏览器从 Pentaho 服务器的 JSP 加载页面。 一旦加载了页面,它不会被再次加载。提供交互性必需的所有额外通信通过 Pentaho AJAX API 完成。 Pentaho 体系结构的更多信息请参考 Pentaho 技术白皮书。 尽管这个 sample 使用 Java Server Page (JSP) 创建网页,任何 web 技术,如 PHP,.NET, Ruby 或 CGI 都可用于创建初始页面。 使用这样一个体系结构,避免了在不同技术间的服务端集成的必要性,允许在网页内集成和 交互。例如如果你有个使用 PHP 创建的基于 web 的客户管理系统(CRM),你可创 建 HTML 和 Javascript,其使用 PHP 显示和控制 Pentaho AJAX 组件。这使得你能 将 Pentaho 组件嵌入进你的 CRM 系统的页面中,通过修改 UI 模板或 PHP 页面。你不必修 改 CRM 系统,以集成进 Penaho 服务器,例如,使用 PHP-Java 桥或使用 web 服务方法。 Pentaho AJAX API Pentaho AJAX API 很简单,允许你执行 action sequences。Action sequences 是 Pentaho Solution Repository 中的文档,其执行一个或多个组件。Action sequences 允许你完成很多工作,包括:  创建 charts 和 dials  创建报表  创建报表并 email 出去  执行数据转换  执行关系(SQL) 查询  指定多维(MDX) 查询 action Sequences 的更多信息请参考 'Creating Pentaho Solutions' 指南。 pentahoAction 有个单一 Javascript 函数(在 pentaho-ajax.js 中),其在服务器上执行 action sequence,并返 回 response。 function pentahoAction( solution, path, action, parameters, callbackFunction ); solution:在其中执行 action sequence 的 solution 的名字。 Path:要执行的 action sequence 在 solution 中的路径。 Action:要执行的 action sequence 的名字。 Parameters:传送给 action sequence 的参数。这是个 2 维数组。里面的数组总有 2 个元素: 第一个是参数名,第二个是参数值。 callbackFunction:当从服务器返回内容时,Pentaho AJAX API 应该调用的 Javascript 函数。 实例 pentahoAction( "samples", "google", "dial.xaction", new Array( new Array( "customer", 1234 ),new Array( "value", 145000 ),new Array( "max", 200000 ),new Ar ray( "low", 100000 ),new Array( "high", 150000 ) ), 'updateInfoWindow' ); 对 pentahoAction 的调用执行一个 action sequence ,其名为 samples/google/dial.xaction,结果 传回到 Javascript 函数 'updateInfoWindow'。这个 action sequence 使用它的输入参数创建一 个 dial image,并返回一个 HTML 'img' tag。传送给 action sequence 的参数是: Customer:客户 id -1234 Value:dial 上要显示的值 -145,000 Max:dial 的最大值 -200,000 Low:dial 上显示的 lower threshold -100,000 High:dial 上显示的 upper threshold -150,000 传送给 action sequence 的参数必须匹配 action sequence 需要的参数。 作出这个调用的脚本必须定义名为 'updateInfoWindow' 的函数。函数必须接收一个单一参数, 其包含从服务器返回的内容。例如: function updateInfoWindow( content ) { // do something with content... // like use DHTML to embed content into web page // we can also execute another action sequence to get more dynamic content pentahoAction( "samples", "google", "chart.xa ction", new Array( new Array( "custom er", 1234 ) ), 'updateProductMix' ); } } 注意上面的 sample 函数执行另一个 action sequence。这使得你能更新网页的多个区域,以响 应用户的 action。 Google Maps Dashboard Explained 使用 Google Maps 创建 AJAX dashboard 的过程中涉及到几个 activities:  Data Determination:确定位于 map 上的数据。这个信息可是地理上分布的任何东西, 例如客户,供应商,vendors,竞争者。通常这个信息由 dashboard 的需求决定。  Geocoding:对要定位的每项,确定它的纬度和经度。这称为 geocoding。有很多方式 完成 Geocoding(见下)。  Dashboard Generation:在 map 上显示项,使用户能 pan 和 zoom map。  Enable Interactivity:添加功能,其定义了当用户点击 dashboard 上的一项时,发生什 么 action。你也可添加功能,允许用户过滤或 sub-select 数据。 Geocoding Geocoding 是将用自然语言表示的位置,例如,国家,城市或地址,转换成用经度和纬度表 示的位置的操作。 一个 process 的不同时间点均可发生 Geocoding:  Data preparation。使用这个技术,在一个批处理过程中 geocoded 数据。存储经纬度(通 常在数据库中)。每项仅 geocoded 一次。如果有任何项不能被 geocoded,数据质 量 processes 可放在适当的位置以解决问题。这通常是生产系统的最优 solution。因为这 需要服务器端 processes,有时它不是原型的最优 solution。  Server-side request。使用这个技术,当从服务器请求数据时,才 geocoded。这 将 geocoding 和 dashboard generation 步骤合并进一个单一步骤中。  Client-side request。Google Maps API 包含客户端 geocoding 库,其用于在浏览器网页中 完成 geocoding。 生成 Dashboard JSP 生成 sample dashboard。一旦网页完成加载,这个 JSP 从数据库加载客户数据, 将 Javascript 函数插入进在 map 上创建 marker pins 的页面上。这个 JSP 也定义了页面的外观 和所有可见元素(标题,threshold panel,customer details panel,Google Map panel)。Google Maps Dashboard sample 的 Map.jsp 位于 pentaho-demo/jboss/server/default/deploy/pentaho.war/jsp/Map.jsp。 这个 JSP 的详细信息,请参考附录 1:Google Map JSP。 交互性 添加和删除 Google Map Markers 你可使用 map API 删除,添加,替换显示在 map 上的 markers。例如当用户修改 thresholds 时, 替换 map 上的一些 markers。使用 map.addOverlay 在 map 上添加一个 marker。例如: geocoder.getLatLng( address, function(point) {var marker = new GMarker(point, icon);map.addOverlay(marker);GEvent.addListener(marker, "click", function() { infoWindow( marker, record ); }); } ); 使用 map.removeOverlay 从 map 删除 marker。你需要告诉 map 删除哪个 marker,因此保留 你添加到 map 上的所有 markers 的引用很重要。例如: map.addOverlay(marker); 点击 Map Markers 一旦你在 map 上添加了 markers,你可添加 listeners,这样当用户点击它们时,你会知道。 例如: // create a new marker with a click listener var marker = new GMarker(point, icon);map.addOverlay(marker);GEvent.addListener(marker, "click", functio n() {infoWindow( marker, record );}); 这个实例为一个 marker 创建一个 'click' listener,并为 listener 提供一个 Javascript 函数,当用 户点击 marker 时,其调用 infoWindow()。 居中和缩放 Google Maps 你可使用 Javascript 居中和缩放显示的 map。你为 map 提供 map 中心的经纬度,以及要使用 的缩放级别。例如: map.setCenter( new GLatLng(41.4263, -73.1799 ), 7) Map Search 一个 'Map Search' 是当用户 pans 或 zooms 显示的 map,这样显示他感兴趣的区域,然后请 求那个位置上的已知项的信息。这是可能的,因为 Google Map API 可用于查找目前显示的 是什么经纬度范围。为了完成 map search,这些经纬度范围必须发送到服务器,用在查询中, 选择要显示的项。当然也可传送额外的 filters。这个 Javascript 显示了如何获取当前显示 的 map 的边界。 // get boundary of currently displayed map var bounds = map.getBounds(); // get location of top right corner var topRight = bounds.getNorthEast(); // get location of bottom left corner var bottomLeft = bounds.getSouthWest(); // get top boundary (north latitude) var northLatitude = topRight.lat(); // get bottom boundary (south latitude) var southLatitude = bottomLeft.lat(); // get right boundary (east longitude) var eastLongitude = topRight.lng(); // get left boundary (west longitude) var westLongitude = bottomLeft.lng(); // now send 4 boundaries to server to be used as a filter ... 内容定义 AJAX Dial 这个 pie chart 定义于 pentaho-demo/pentaho-solutions/samples/google/dial.xaction。 Pentaho 服务器执行这个 action sequence,当 AJAX 库从网页调用它。 这个 action sequence 创建 HTML 内容在 dashboard 中显示 dial。为完成这个功能,action sequence 接收创建 dial 需要的所有数据作为输入: Max:dial 上显示的范围的最大值 low:dial 上显示的 lower threshold(红黄区域的转折点) high:dial 上显示的 upper threshold(黄绿区域的转折点) value:dial 上要显示的值 action sequence 有个单一输出,其包含显示 dial 的 HTML 片段。 action sequence 在 3 步中创建 HTML: 1. Javascript 组件,其创建有一行数据的 data set: 输入:max,value Action: data = new JavaScriptResultSet(); data.setColumnHeaders( new Array( 'actual', 'min', 'max' ) ); data.addRow( new Array( parseInt(value), 0, parseInt(max) ) ); 输出:数据 result set 创建 dial image 的 chart 组件: Inputs:数据 result set,low,high,max,image 类型(.png) Action:使用嵌入在组件定义中的 chart 定义创建 dial。此处没有详细描述 chart 设置。dial 被 写出到一个临时文件中。 输出:chart filename,base URL 另一个 Javascript 组件创建 final HTML 片段,并返回到 dashboard。 输入:chart filename (CHARTOUTPUT),base URL (BASEURL) Action: chart_url = ''; 输出:chart HTML (chart_url) AJAX Pie Chart 这个 pie chart 定义于 pentaho-demo/pentaho-solutions/samples/google/chart.xaction。 Pentaho 服务器执行这个 action sequence,当 AJAX 库从网页中调用它时。 这个 action sequence 创建 HTML 内容,以在 dashboard 中显示 pie chart。 action sequence 接收输入:  Customer:pie chart 需要的客户数量。 action sequence 有单一输出,其包含将显示 dial 的 HTML 片段。 action sequence 在 3 步中创建 HTML: 1. SQL lookup 组件,其获取客户数据的 data set: 输入:customer Action: select DISTINCT PRODUCTLINE, SUM(QUANTITYORDERED * PRICEEACH) as "TOTAL SALES"from PRODUCTS, ORDERDETAILS, CUSTOMERS, ORDERSwhere CUSTOMERS.CUSTOMERNUMBER = {PREPARE:customer} and CUSTOMERS.CUSTOMERNUMBER = ORDERS.CUSTOMERNUMBER and ORDERS.ORDERNUMBER = ORDERDETAILS.ORDERNUMBERand PRODUCTS.PRODUCTCODE = ORDERDETAILS.PRODUCTCODE group by PRODUCTLINE 使用 {PREPARE:customer} ,在查询中嵌入 customer 参数。 输出:数据 result set (chart-data) 2. 创建 pie chart image 的 chart 组件: 输入:数据 result set (chart-data) Action:使用嵌入在组件定义中的 chart 定义创建 pie chart。此处不详细描述 chart 设 置。pie chart image 被写出进一个临时文件。 输出:chart filename,base URL 3. 另一个 Javascript 组件创建要返回给 dashboard 的 final HTML 片段: 输入:chart filename (CHARTOUTPUT),base URL (BASEURL) Action: chart_url = ''; 输出:chart HTML (chart_url) AJAX 嵌入式报表 这个报表定义于 2 个文件中,一个 action sequence: pentaho-demo/pentaho-solutions/samples/google/customer_details.xaction 和一个报表定义:pentaho-demo/pentaho-solutions/samples/google/customer_details_report.xml。 action sequence 加载数据,执行报表,并返回结果。 报表引擎使用报表定义(Pentaho Reporting)设计报表。你可使用 Pentaho Report Wizard 设计报 表定义。 因为报表内容会嵌入进交互式 dashboard 中,报表需要创建 HTML 片段,而不是整个 的 HTML 页面。报表定义的配置中包含一个名为 BodyFragment 的属性来激活它。 true action sequence 接收输入:  customer:pie chart 需要的客户数量。 action sequence 有个单一输出,其包含显示 dial 的 HTML 片段。 action sequence 在 2 步中创建 HTML: 1. SQL lookup 组件获取客户的数据 输入:customer Action: select ORDERDATE as "ORDER DATE", SUM(QUANTITYORDERED * PRICEEACH) as VALUE from CUSTOMERS, ORDERS, ORDERDETAILS where CUSTOMERS.CUSTOMERNUMBER = {PREPARE:customer} and CUSTOMERS.CUSTOMERNUMBER = ORDERS.CUSTOMERNUMBER and ORDERS.ORDERNUMBER = ORDERDETAILS.ORDERNUMBER group by ORDERDATE order by ORDERDATE DESC customer 参数使用 {PREPARE:customer} 嵌入进查询中。 输出:数据 result set (chart-data) 2. 创建 HTML 内容的报表组件: 输入:数据 result set (chart-data) Action:使用 action sequence 资源中定义的报表定义创建一个报表。此处没有详细描 述报表的定义文件。dial 被写出进一个临时文件。 输出:报表内容(report-output) 附录 1:Google Map JSP 可在 Pentaho PCI 中找到这个文件: pentaho-demo/jboss/server/default/deploy/pentaho.war/jsp/Map.jsp。 <%@ page language="java" import="org.pentaho.core.syst em.PentahoSystem, org.pentaho.core.session.IPen tahoSession, org.pentaho.core.util.XmlHel per, org.pentaho.messages.Messag es, org.pentaho.core.util.UIUtil, org.pentaho.messages.util.Loc aleHelper, org.pentaho.util.VersionHelpe r, org.pentaho.ui.component.INa vigationComponent, org.pentaho.ui.component.Na vigationComponentFactory, org.pentaho.core.ui.SimpleUrl Factory, org.pentaho.core.solution.Sim pleParameterProvider, org.dom4j.*, org.pentaho.core.solution.Acti onResource, org.pentaho.core.solution.IAct ionResource, org.pentaho.core.util.IUITem plater, org.pentaho.core.solution.Sim pleOutputHandler, org.pentaho.core.services.Bas eRequestHandler, org.pentaho.core.runtime.IRu ntimeContext, org.pentaho.core.connection.I PentahoResultSet, org.pentaho.ui.ChartHelper, java.io.*, java.util.*" %><% /* * Copyright 2006 Pentaho Corporation. All rights reserved. * This software was developed by Pentaho Corporation and is provided under terms * of Mozilla Public License, Version 1.1, or any later version. You may not use * this file except in compliance with license. If you need a copy of license, * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. Original Code is Pentaho * BI Platform. Initial Developer is Pentaho Corporation. * * Software distributed under Mozilla Public License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to * license for specific language governing your rights and limitations.* * @created Jul 23, 2005 * @author James Dixon * */ /* * This JSP is an example of how to use Pentaho components and AJAX library to build a * Google Maps dashboard. * This file loads customer data and displays it using Google Maps. * script for this file is in js/google-demo.js * Pentaho AJAX library is in js/pentaho-ajax.js * See document 'Pentaho AJAX Guide' for more details */ // Set character encoding e.g. UTF-8 response.setCharacterEncoding(LocaleHelper.getSystemEncoding()); // Get current Pentaho session or create a new one if needed IPentahoSession userSession = UIUtil.getPentahoSession( request ); // Set default thresholds int topthreshold = 100000; int bottomthreshold = 50000; // Get server and port. We use this to check for an invalid Google Maps API key boolean defaultKeyInvalid = false; String serverName = request.getServerName(); int serverPort = request.getServerPort(); // Get a templater object String intro = ""; String footer = ""; IUITemplater templater = PentahoSystem.getUITemplater( userSession ); if( templater != null ) { // Load a template for this web page String template = null; try { ActionResource resource = new ActionResource( "", IActionResource.SOLUTION_FILE_RESOURCE, "text/xml", "system/custom/template-document.html" ); template = PentahoSystem.getSolutionRepository(userSession) .getResourceAsString( resource ); } catch (Throwable t) {} // Check to see if we are using default Google Maps API key but not for localhost:8080 String googleMapsApiKey = PentahoSystem.getSystemSetting( "google/googlesettings.xml", "google_maps_api_key", null); if( ( !serverName.equals( "localh ost" ) || serverPort != 8080 ) && googleMapsApiKey.equals( "AB QIAAAAoGNlMo4FkTb3mcC5 mj5ERRTwM0brOpm All5BF6PoaKBxRWWERR0378 zH4HL9GyjgMMHJmj_viP4PQ" ) ) { // default Google Maps API key is not valid for this server and port defaultKeyInvalid = true; } else { // insert Pentaho AJAX, Google Maps, // and demo script references into document header template = template.replaceAll( "\\{header-content\\}", "\n"+ "\n"+ "\n" ); template = template.replaceAll( "\\{body-tag\\}", "onload =\"load ()\" onunloa d=\"GU nload()\ "" ); } // Break template into header and footer sections String sections[] = templater.breakTemplateString( template, "Pentaho Google Maps Dashboard", userSession ); if( sections != null && sections.length > 0 ) { intro = sections[0]; } if( sections != null && sections.length > 1 ) { footer = sections[1]; } } else { intro = Messages.getString( "UI.ERROR_0002_ BAD_TEMPLATE_ OBJECT" );} // Load customer data. Do this by running an action sequence defined // in pentaho-solutions/samples/google/map1.xaction SimpleParameterProvider parameters = new SimpleParameterProvider(); ArrayList messages = new ArrayList(); // 'results' will store customer data IPentahoResultSet results = null; IRuntimeContext runtime = null; try { // Run action sequence runtime = ChartHelper.doAction( "samples", "google", "map1.xaction", "Map.jsp", parameters, userSession, messages, null ); // See if we have a valid result if( runtime != null ) { if( runtime.getStatus() == IRuntimeContext.RU NTIME_STATUS_S UCCESS ) { if( runtime.getOutput Names().contains("d ata") ) { results = runtime.getOutputPa rameter( "data" ).get ValueAsResultSet(); } } } } finally { if (runtime != null) { // Now clean up r unti me. dis pos e(); } } String customerNum = ""; String customer = ""; String city = ""; String state = ""; String zip = ""; String value = ""; %> <%= intro %> <% if( defaultKeyInvalid ) { // default key is not valid so we put out a nice message about it. %> Google Maps API key that ships with Pentaho Pre-Configured Installation will only work with a server address of 'http://localhost:8080'.

To use Google Maps with this server address ( <%= serverName %>:<%= serverPort %> ) you need to apply to Google for a new key.

Once you have new key you need to add it to Google settings file in Pentaho system (.../pentaho-solutions/system/google/googlesettings.xml)

Click here to get a Google Maps API Key for this server. <% } e l s e { // embed customer data into web page %>

Select Sales Thresholds
&nb sp; View: West Coast | East Coast
 
< < < <
 

<% } %> 附录 2:Pentaho AJAX 库 这个 Javascript 库允许在浏览器中从 Javascript 执行 Pentaho Action Sequences。可在 Pentaho PCI 中找到这个文件:pentaho-demo/jboss/server/default/deploy/pentaho.war/js/pentaho-ajax.js。 // URL to Pentaho servlet 'ViewAction'. // This will default to '/pentaho/' if it is not set. var PentahoURL = null; /* Sets URL to Pentaho servlet 'ViewAction'. This should end in a '/'. */ function setPentahoURL( url ) {PentahoURL = url;} /* This function makes an AJAX call to Pentaho server to execute an Action Sequence. Action Sequence must exist within Pentaho Solution Repository. Once executed content generated by Action Sequence will be passed to named function Parameters: solution:name of solution path: path within solution to Action Sequence action: name of Action Sequence params: An array of arrays with name-value pair parameters for Action Sequence func: function that will be called once Action Sequence has been executed */ function pentahoAction( solution, path, action, params, func ) { var http_request = null; // Create an HTTP Request object if (window.XMLHttpRequest) { // Try Mozilla, Safari, Firefox etc. http_request = new XMLHttpRequest();if (http_request.overrideMimeType) {http_request.overrideMimeType('text/xml'); }} else if (window.ActiveXObject) { // IE try {http_request = new ActiveXObject("Msxml2.XMLHTTP");} catch (e) {try { http_request = new ActiveXObject(" Microsoft.XMLHTTP"); } catch (e) {}}} // Make sure we got a valid HTTP Request object if (http_request == null) {alert('Could not create an AJAX request object');return false; } // Set callback function to 'pentahoResponse' (below) http_request.onreadystatechange = function() { pentahoResponse(http_request, func); }; // Construct URL var url = "";if( PentahoURL != null ) { // PentahoURL has been set so use it url = PentahoURL;} else { // PentahoURL has not been set so use default url = "/pentaho/";} // Add Action Sequence solution, path and name to URL url += "ViewAction?wrapper=false&solution="+solution+"&path="+path+"&action="+action; // Add parameters to URL if( params ) {var idx;for( idx=0; idx lat/long converter // create red icon icon = new GIcon();icon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";icon.iconSize = new GSize(12,20);icon.shadowSize = new GSize(22, 20);icon.iconAnchor = new GPoint(6, 20);icon.infoWindowAnchor = new GPoint(5, 1);redicon = icon; // create yellow icon icon = new GIcon();icon.image = "http://labs.google.com/ridefinder/images/mm_20_yellow.png";icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";icon.iconSize = new GSize(12,20);icon.shadowSize = new GSize(22, 20);icon.iconAnchor = new GPoint(6, 20);icon.infoWindowAnchor = new GPoint(5, 1);yellowicon = icon; // create green marker icon = new GIcon();icon.image = "http://labs.google.com/ridefinder/images/mm_20_green.png";icon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";icon.iconSize = new GSize(12,20);icon.shadowSize = new GSize(22, 20);icon.iconAnchor = new GPoint(6, 20);icon.infoWindowAnchor = new GPoint(5, 1); greenicon = icon; function load() { // this is called then page is loaded // check to see if browser supports Google Map API if (GBrowserIsCompatible()) { // create map object and tell it which div on page to use map = new GMap2(document.getElementById("map")); // set initial center of map map.setCenter(new GLatLng(37.4419, -95), 4); // set controls available to user map.addControl(new GSmallMapControl()); map.addControl(new GMapTypeControl()); // call function in main page that adds customers to map a ddP oint s(); } } function customerClick( ) { // this is called then user clicks on a marker on map // call dial action (sample/google/dial.xaction) and call function // updateInfoWindow with results pentahoAction( "samples", "google", "dial.xaction", new Array( new Array( "customer", currentRecord[7] ),new Array( "value", currentRecord[4] ),new Array( "max", 200000 ),new Array( "low", bottomThreshold ),new Array( "high", topThreshold ) ), 'updateInfoWindow' ); } function updateInfoWindow( content ) { // this is called when server returns HTML content for dial // construct HTML to go in info window and open it currentMarker.openInfoWindowHtml(" topThreshold ) { i con = greenic on;} el se {ico n = yellowi con;} if( icon == oldIcon ) { // this marker has not changed so return old one return oldMarker;} // this marker is new or changed so we need to remove old marker and add this record[5] = icon; // remove old marker map.removeOverlay( oldMarker ); // create a new marker with a click listener var marker = new GMarker(point, icon); // add marker to map map.addOverlay(marker); // add a click listener to marker to call 'infoWindow' function GEvent.addListener(marker, "click", function() { infoWindow( marker, record );});return marker; } var currentMarker = null;var currentRecord = null; function infoWindow( marker, record ) { // this is called by click listener for each marker currentMarker = marker; currentRecord = record; // now update page customerClick( ); } function update(topChange) { // this is called when user changes coloring thresholds var n = points.length; // make sure threshold values don't overlap var idx1 = document.getElementById('topthreshold').selectedIndex;var idx2 = document.getElementById('bottomthreshold').selectedIndex;if( idx1 < idx2 ) { if( topChange ) {document.getElementById('bottomthreshold').sel ectedIndex = idx1;} else {document.getElementById('topthresh old').selectedIndex = idx2;}} // get current threshold values topThreshold = document.getElementById('topthreshold').value;bottomThreshold = document.getElementById('bottomthreshold').value; // update each marker for( idx=0; idx
还剩32页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 2 人已下载

下载pdf

pdf贡献者

xiebin

贡献于2012-07-02

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
"+currentRecord[2]+"
Customer:" + currentRecord[7] +"
Name:" + currentRecord[3] +"
Location:
Current Sales:"+currentRecord[4]+"
"+content+"
0200,000