|
|
2/4/2008 extjs 在 2.0 之後針對資料擷取的部份,做了大幅度的改善 透過很直覺的定義方式,可以很快的建構出以Grid為base的資料呈現方式 底下要示範的是,如何透過.Net的Web Service以及Ext.data.JsonStore將資料庫中的已完成簽核紀錄快速讀取出來 首先我們先建構.Net的Web Service qryfinished.asmx 他會在 App_Code下產生一個 qryfinished.aspx 在這邊我們還會需要使用一個 Audits class 來建構我們所需的 Json Array | Imports Microsoft.VisualBasic Public Class Audits Public sno As Integer Public InstanceID As String Public ReferenceNo As String Public Version As String Public FTime As String Public StartTime As String Public SignTime As String Public UserID As String Public UserName As String Public ApproverID As String Public ApproverName As String Public Actions As String Public Diff As String Public vendor As String Public dept As String End Class | 上述的class就是我們要產生的Json Array的格式 | Imports System.Web Imports System.Web.Services Imports System.Web.Services.Protocols Imports Newtonsoft.Json Imports CommonModule Imports Audits ' define一個Json Array所需的 class <WebService(Namespace:="http://xxx/webservices")> _ <WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _ <Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _ Public Class qryfinished Inherits System.Web.Services.WebService <WebMethod()> _ Public Function ToJSONString(ByVal uid As String) As String Dim strSQL As String Dim connWorkFlow1 As System.Data.SqlClient.SqlConnection = Nothing Dim sqlCommand As System.Data.SqlClient.SqlCommand, sqlCommand1 As System.Data.SqlClient.SqlCommand Dim drWorkflow As System.Data.SqlClient.SqlDataReader = Nothing, drWorkflow1 As System.Data.SqlClient.SqlDataReader = Nothing Dim cmdWMS As System.Data.SqlClient.SqlCommand Dim drWMS As System.Data.SqlClient.SqlDataReader = Nothing Dim iCount As Integer = 1 Dim WF_UserID As String = uid Dim starttime As String = "", signtime As String = Now().ToString Dim oAudits() As Audits ' define Json Array Dim pb_no As String = "" ReDim oAudits(0) Try strSQL = "select distinct SLIP_NO from CELL_TMP_TB where status='C' order by SLIP_NO" If connWMS Is Nothing Then Connection(False, True, False) End If If connWorkFlow Is Nothing Then Connection(False, False, True) End If If connWMS.State <> Data.ConnectionState.Open Then connWMS.Open() End If cmdWMS = New System.Data.SqlClient.SqlCommand(strSQL, connWMS) drWMS = cmdWMS.ExecuteReader() Do While drWMS.Read() pb_no = drWMS.GetString(drWMS.GetOrdinal("SLIP_NO")) strSQL = "select top 1 * from Audits NOLOCK where ReferenceNo='" + pb_no + "' order by StartTime" If connWorkFlow.State <> Data.ConnectionState.Open Then connWorkFlow.Open() End If sqlCommand = New System.Data.SqlClient.SqlCommand(strSQL, connWorkFlow) drWorkflow = sqlCommand.ExecuteReader() If drWorkflow.Read() Then ReDim Preserve oAudits(iCount - 1) starttime = drWorkflow.GetDateTime(drWorkflow.GetOrdinal("StartTime")).ToString() oAudits(iCount - 1) = New Audits() oAudits(iCount - 1).sno = iCount oAudits(iCount - 1).UserID = WF_UserID oAudits(iCount - 1).StartTime = starttime oAudits(iCount - 1).UserName = drWorkflow.GetString(drWorkflow.GetOrdinal("UserName")) GetERP(oAudits(iCount - 1), pb_no) strSQL = "select top 1 * from Audits NOLOCK where ReferenceNo='" + pb_no + "' order by SignTime desc" connWorkFlow1 = getSqlConnection("cnnWorkFlow") sqlCommand1 = New System.Data.SqlClient.SqlCommand(strSQL, connWorkFlow1) connWorkFlow1.Open() drWorkflow1 = sqlCommand1.ExecuteReader() If drWorkflow1.Read() Then oAudits(iCount - 1).InstanceID = drWorkflow1.GetString(drWorkflow1.GetOrdinal("InstanceID")) oAudits(iCount - 1).ReferenceNo = drWorkflow1.GetString(drWorkflow1.GetOrdinal("ReferenceNo")) signtime = drWorkflow1.GetDateTime(drWorkflow1.GetOrdinal("SignTime")).ToString() oAudits(iCount - 1).SignTime = signtime oAudits(iCount - 1).Actions = drWorkflow1.GetString(drWorkflow1.GetOrdinal("Actions")) End If drWorkflow1.Close() connWorkFlow1.Close() oAudits(iCount - 1).Diff = getSignTime(CDate(starttime), CDate(signtime)) End If iCount += 1 drWorkflow.Close() Loop drWMS.Close() Catch ex As System.Data.Odbc.OdbcException My.ErrorHandling.ExceptionHandler(ex, Resources.Settings.smtphost, Resources.Settings.From, Resources.Settings.CopyTo) Finally If Not drWorkflow Is Nothing Then drWorkflow = Nothing If Not drWorkflow1 Is Nothing Then drWorkflow1 = Nothing If Not drWMS Is Nothing Then drWMS = Nothing If Not connWorkFlow1 Is Nothing Then connWorkFl ow1 = Nothing End Try ' 將 Json Array 透過 JavaScriptConvert.SerializeObject 轉換成序列化的String資料以利Internet傳輸 Return "{""totalCount"":" + CStr(iCount - 1) + ",""data"":" + JavaScriptConvert.SerializeObject(oAudits) + "}" End Function End Class | 回傳的 Json String | {"totalCount":1,"data":[{"sno":1,"InstanceID":"7C038193C70EBC50482573C500328A3B","ReferenceNo":"XX -7C0358","Version":null,"FTime":null,"StartTime":"2008/1/3 下午 05:12:02","SignTime":"2008/1/3 下午 05:52:00","UserID":"nnnnnn","UserName":"AAA","ApproverID":null,"ApproverName":null,"Actions":"確認","Diff":"39分58秒","vendor":"XXXX","dept":"XXX"}]} | 由於JasonStore要回傳的是一個格式化過的Json Array資料 所以我們要另外建構一個qryfinished2.aspx透過它來呼叫qryfinished這個Web Service 並透過Web Service中的ToJSONString將Json Array以序列化的方式回傳到前端網頁中 | Partial Class qryfinished2 Inherits System.Web.UI.Page Public JSONString As String Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim myJSONObject As New qryfinished ' 呼叫 Web Service Dim uid As String = Request.QueryString("uid") JSONString = myJSONObject.ToJSONString(uid) End Sub End Class | qryfinished2.aspx, 只呈現 Json String | <%@ Page Language="VB" AutoEventWireup="false" CodeFile="qryfinished2.aspx.vb" Inherits="qryfinished2" %> <%=JSONString%> | 建構好Web Service及呈現Json String的網頁後,接下來我們要建構 extjs 的UI部分 | /* * Ext JS Library 2.0 * Copyright(c) 2006-2007, Ext JS, LLC. * licensing@extjs.com * * http://extjs.com/license */ Ext.onReady(function(){ Ext.QuickTips.init(); // turn on validation errors beside the field globally Ext.form.Field.prototype.msgTarget = 'side'; // create the Data Store // 透過qryfinished2.aspx去讀取qryfinished.asmx這個Web Service抓出已簽核完成的資料 // 作為 Grid 的資料來源 var store = new Ext.data.JsonStore({ url: 'http://xxx/DateCode/qryfinished2.aspx?uid='+WF_UserID, root: 'data', id: 'InstanceID', fields: [ 'sno','ReferenceNo', 'UserName', 'Actions', 'StartTime', 'SignTime', 'Diff', 'dept', 'vendor' ] }); // 呼叫 define 在 HTML 中的 Javascript 讓第一個欄位可以點擊後開啟資料頁 function renderReferenceNo(value, p, record){ return String.format( '<a href="javascript:void(0);" onclick="doSign(\'{0}\',\'{1}\',\'{2}\',\'worklist\');" title="點此開啟入庫單">{2}</a>', record.id, WF_UserID, value); } // define 一個 FormPanel 上面擺 Grid var fs = new Ext.FormPanel({ collapsible:true, frame: true, title:'Date Code 逾期簽核-'+dcTitle, labelAlign: 'right', labelWidth: 85, width:800, waitMsgTarget: true, tbar: [''], // 顯示在FormPanel上的元件 items: [new Ext.form.FieldSet({ title: '查詢條件', collapsible: true, animCollapse: true, autoHeight: true, defaultType: 'textfield'/*, contentEl: 'pb_master'*/ }),new Ext.grid.GridPanel({ store: store, frame: true, //autoHeight: true, autoScroll: true, loadMask: true, sm: new Ext.grid.RowSelectionModel({singleSelect:true}), stripeRows: true, columns: [ { header: '', dataIndex: 'sno', width: 30, align: 'right' }, { id: 'ReferenceNo', header: '入庫單號', dataIndex: 'ReferenceNo', width: 80, renderer: renderReferenceNo, align: 'center', sortable: true }, { header: '部門', dataIndex: 'dept', width: 50, align: 'center', sortable: true }, { header: '申請者', dataIndex: 'UserName', width: 50, align: 'center', sortable: true }, { header: '廠商', dataIndex: 'vendor', width: 80, align: 'center', sortable: true }, { header: '簽核結果', dataIndex: 'Actions', width: 70, align: 'center', sortable: true }, { header: '申請時間', dataIndex: 'StartTime', width: 150, align: 'center', sortable: true }, { header: '完成時間', dataIndex: 'SignTime', width: 150, align: 'center', sortable: true }, { header: '簽核歷時', dataIndex: 'Diff', width: 150, sortable: true } ], width: 788, height: 400 })] }); fs.render('form-ct'); // 將 FormPanel render 在 "form-ct" 這個 div tag 中 store.load(); // 讀取資料 fs.getTopToolbar().add('->', { text: '', tooltip: '重新整理', iconCls: 'breload', handler: function(){ location.reload(); } }); }); | 在給前端查詢的頁面中,我們只要將 define 好的 pgfinished.js include 進來即可 | <%@ Page Language="VB" MasterPageFile="~/qryMasterPage.master" AutoEventWireup="false" CodeFile="dc_finished.aspx.vb" Inherits="dc_finished" %> <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server"> <script type="text/javascript"> var WF_UserID="<%=WF_UserID %>"; var dcTitle="已完成簽核查詢"; </script> <script src="pgfinished.js" type="text/javascript"></script> </asp:Content> | 部份程式在Master Page 中 | <%@ Master CodeFile="qryMasterPage.master.vb" Inherits="qryMasterPage" Language="VB" %> <!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"> <!--<meta content="30" http-equiv="refresh" />--> <head id="Head1" runat="server"> <title>Date Code逾期簽核系統</title> <link href="js/ext-2.0/resources/css/ext-all.css" rel="stylesheet" type="text/css" /> <link href="js/ext-2.0/resources/css/xtheme-gray.css" rel="stylesheet" type="text/css" /> <script src="js/ext-2.0/adapter/ext/ext-base.js" type="text/javascript"></script> <script src="js/ext-2.0/ext-all.js" type="text/javascript"></script> <link href="menus.css" rel="stylesheet" type="text/css" /> <link href="forms.css" rel="stylesheet" type="text/css" /> <!-- Common Styles for the examples --> <link href="js/ext-2.0/examples/examples.css" rel="stylesheet" type="text/css" /> <style type="text/css"> html, body { font:normal 12px verdana; margin:0; padding:0; border:0 none; overflow:hidden; height:100%; } </style> <script type="text/javascript"> function doSign(unid,uid,pb_no,s){ s=(typeof(s)=="undefined") ? s="":s; if (s=="finished") window.open("dc_read.aspx?unid="+unid+"&stage="+s+"&pb_no="+pb_no+"&uid="+uid,"DC",""); else window.open("dc_check.aspx?unid="+unid+"&stage="+s+"&pb_no="+pb_no+"&uid="+uid,"DC",""); } </script> </head> <body class="x-aero"> <script src="js/ext-2.0/examples/examples.js" type="text/javascript"></script> <br /> <form id="form1" class="x-form"> <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server"> </asp:ContentPlaceHolder> </form> <table align="center" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <div id="form-ct"> <div id="pb_master"> </div> </div> </td> </tr> </table> </body> </html> | 完成圖
建構 extjs 的 Application 也是符合 MVC 的規範 Model: Web Service View: HTML Controller: extjs 以這樣的方式去思考,就比較容易清楚掌握該如何撰寫 extjs 的 Application 了 1/4/2008 趕在去年底用一個禮拜的時間將一個系統以 extjs 2.0 的 library 建構起來
由於有之前 1.1 的開發經驗,在學習與習慣 2.0 的API確實節省了許多時間
就整個 framework 來看,2.0 的物件功能更為精簡與直覺
以Container為基礎,在上面去建構新的Component元件或是Container
這樣就組合出多樣化的Web UI,在資料的展現上更為快速與便利(開發的時間也大幅降低)
以下是 1.1 與 2.0 所開發出來的畫面,供參考
10/5/2007
從1.0版之前就開始接觸,到現在已到了2.0 Alpha Release
將Web UI發揮到極致的一套Library就屬extjs莫屬
最近的一個專案,套用了extjs 1.1.1的版本就快結案了
誰知他2.0版超炫目的豋場,等上線run一陣再改用2.0的Library吧
過幾天再將成果Post上來
今天建仔輸球,給他很芭樂的說,洋基挺著點 2/9/2007 New features of Ajax Domino Controller version 0.5.0 (NTF):
- getAllEntriesByKey
- runAgent
- getDocumentByUNID
- RaiseError - XML error handling
- DocumentToXML - unified the XML output for each Function
You can get the error message raised on Domino server, by parsing the returned XML document with the tagName "ajax-error", to see what happened on server. And it is more convinient to out put XML by put your result in the variable xml, after you assembly your xml output, just call DocumentToXML(xml) It will format your xml result to a formal XML document.
Try it. :) 1/23/2007 Ajax Domino Controller is a Domino web development framework by using AJAX javascript and Domino Agent.
It provides web developers to retirve Domino data with no COM object nor CORBA framework, just javascript function call and XML for communication.
<script src="path/to/prototype.js" type="text/javascript"></script> <script src="path/to/ajaxdomino.js" type="text/javascript"></script>
In ajaxdomino.js, you can use dblookup to retrive XML data like Formula @DBLookup does.
You provide server,database,view,key,field and onComplete function to handle the XML data with your page.
In the parameter field, you can provide ColumnNumer or fieldName to do with, and not only one column or one field can do,
you can retrive two or more field value by useing comma with it.
e.g. dblookup('myserver','mydb','myview','mykey','field1,field2,field3','myCompletefunction');
// Change the bold block to your Domino IP/domain name
function dblookup(server,database,view,key,field,onComplete){ var pars='action=dblookup'+ '&server='+escape(server)+ '&database='+escape(database)+ '&view='+escape(view)+ '&key='+escape(key)+ '&field='+escape(field); //alert(pars); var myAjax=new Ajax.Request(ajaxdominocontrollerurl, { method: 'get', parameters: pars, asynchronous: true, onComplete: eval(onComplete), onSuccess: function(resp) { //alert("The response from the server is: " + resp.responseText); }, onFailure: function(resp) { alert('Sorry. There was an error.'); }, onException: function(resp, exception) { var description = ''; for (var property in exception) { description += property + '=' + exception[property] + '\n'; } alert('Exception: ' + exception + '\n' + description); } }); }
The prototype AJAX object will take handle with the Ajax Domino Controller agent "ActionListener" and pass the parameters through Domino web container.
As the ActionListener agent received the request, it will parse the action field and switch to the properly function to do with.
The Ajax Domino Controller also provide an error handling function call to send email on the error raised event.
You should also change the constant variable "Administrator" in the ErrorHandling script library to your desired email,
and testing the agent on your Domino server.
Be remided, you should create a new Database with the template "AjaxDominoController.ntf" on your Domino server,
sign the database you created with your Adminstration account and change the ACL of "default" from Administrator to Reader.
After the responsed XML returned, it will call the onComplete function you provided with dblookup function call, it will look like this
function showResponse(resp) { //alert(resp.responseText); var xmlDoc=resp.responseXML; var x x=xmlDoc.getElementsByTagName(Field); $('Result').innerHTML="<select id='lst'><option></option></select>"; for (var i=0;i<x.length;i++) { var value = x[i].childNodes[0].text; $('lst').options[i]=new Option(value,value); } }
.....
<div id="Result"></id>
Very straight forward, enjoy it. 
5/24/2006 忙了一陣子, 終於把客戶信用評等查詢系統的操作說明文件給生出來了
這個使用 Ajax 技術開發的系統(後端是 JSP+Informix DB<-Tiptop ERP), 在概念上
除了 non postback 的操作方式之外
最重要的是前端介面與後端資料的切割可以更容易與釐清
讓 User 在操作上有如操作一般的 Windows AP
並且省去傳輸一大堆 HTML tag 的作法與限制
是 Ajax 的主要內涵
也因此帶來了網頁技術的革命里程碑
邁向 Web 2.0 的時代
讓意念可以更自由的發揮 5/16/2006 今天在 Google Group 裡, 有一篇名為 50个和AJAX有关的工具和框架
介紹了許多跟 Ajax 開發有關的網站與 framework
蠻值得收藏的!!
3/28/2006 我們在撰寫網頁時常常會因為資料量的關係使得網頁會超過一個檢視頁,
導致需要使用 scroll bar 將網頁網下捲才能看到全部的資料
有沒有辦法將 HTML Table 作成像 Excel 凍結視窗的方式進行資料的捲動?
有的直接對 DOM 操作, 有的透過 iframe 方式來模擬
美美的 CSS
|
<style type="text/css"> DIV{ scrollbar-DarkShadow-Color:#9FB7D7; scrollbar-Track-Color:#F7F7F7; scrollbar-Face-Color:#C7CFFF; scrollbar-Shadow-Color:#FFFFFF; scrollbar-Highlight-Color:#FFFFFF; scrollbar-3dLight-Color:#C7CFF7; scrollbar-Arrow-Color:#4F5F87; } </style> |
表格的部份, 首先將標題的部分獨立出來
|
<table border="0" cellpadding="0" cellspacing="0" style="border: solid 1px; border-collapse: collapse" width="950"> <tr> <td valign="top"> <table border="1" cellpadding="0" cellspacing="0" style="border: solid 1px; border-collapse: collapse" width="950"> <tr class="Header"> <td nowrap="nowrap" align="center" width="40">序號<br /> </td> <td nowrap="nowrap" align="center" width="80">客戶名稱<br /> </td> <td nowrap="nowrap" align="center" width="50">業務員<br /> </td> <td nowrap="nowrap" align="center" width="50">客戶<br />類別</td> <td nowrap="nowrap" align="center" width="70">放款天數<br /></td> <td nowrap="nowrap" align="center" width="80">A/R 合計<br />(萬元)</td> <td nowrap="nowrap" align="center" width="90">銷售淨額<br />(萬元)</td> <td nowrap="nowrap" align="center" width="80">銷售毛利<br />(%)</td> <td nowrap="nowrap" align="center" width="80">信用額度<br />(萬元)</td> <td nowrap="nowrap" align="center" width="99">信用評等</td> <td nowrap="nowrap" align="center" width="99">EPS</td> <td nowrap="nowrap" align="center" width="60">每股<br />淨值</td> <td nowrap="nowrap" align="center" width="72">目前<br />股價</td> </tr> </table> </td> </tr>
|
再來將內容的 table 部份包裝在 Contain 的<div></div>之中, 將 <div> style 中的 overflow 功能 on 起來,
x 表示水平捲軸, y 表示垂直捲軸
scroll 表示強迫出現捲軸
auto 表示當內容超過現訂範圍時, scroll bar才會出現
<tr> <td width="*" valign="top"> <div id="Contain" style="height:290px; overflow-y:scroll; overflow-x:auto; margin-top:-1px;"> <table id="ContentTable" border="1" cellpadding="0" cellspacing="0" style="border: solid 1px;border-collapse: collapse" width="936"> <tr> <td align="center" width="40"> </td> <td align="left" width="80"> </td> <td align="center" width="50"> </td> <td align="right" width="50"> </td> <td align="right" width="70"> </td> <td align="right" width="80"> </td> <td align="right" width="90"> </td> <td align="right" width="80"> </td> <td align="right" width="80"> </td> <td align="center" width="100"> </td> <td align="right" width="100"> </td> <td align="right" width="60"> </td> <td align="right" width="56"> </td> </tr> </table> </div> </td> </tr> </table>
|
這樣就可以捲動 HTML 的 table 囉!! 
要注意的是由於標題列與內容列是兩個獨立的表格
所以再頁面的呈現上要自行調整每一個 td 的 width 這樣才不會發生上下寬度不一致的窘境
多試幾次就可以調成美美的網頁了
這邊就示範垂直捲軸的作法, 水平捲軸的部份就留給大家自己 try 吧. 3/22/2006 昨天晚上收到了來自 Google Page 的邀請函

真是令人興奮, 等了一陣子了
據說這是一個大量使用 Ajax 技術的 Web Application, 也被說因此造成 performance 不好
這是 default page 醜醜的, Anyway 快點將首頁建起來並把操作心得 post 上來唄
 3/9/2006 完成了進階查詢的畫面了
這個畫面跟之前的那一個是在同一個 page 喔
並沒有 reload 過
只是運用了 javascript + css 的技巧將查詢條件的 block 作顯示跟隱藏
基本的架構還是一樣 透過 XHTTP 去要後端的資料
只不過這次的資料是經過繁複計算的
但是只要你查過的資料就會被 cache 住, 這樣別人再查時
資料就是即時出現囉
同時在 XHTTP 去要資料時, 可以在 Client 端作一些像 progress bar 等的動態顯示
讓 user 不致以為沒有在運作
如果你有仔細看圖片 可以發現 這些資料是 scrollable 的
就像 Excel 凍結視窗一樣
而且在一個 browser 的可是範圍內就可以將所有的資料展現出來
不會破壞掉畫面的結構
關於 scrollable table 的作法 下次再介紹囉!! 3/2/2006 Ajax 真的令人著迷
為了方便使用者的輸入, 提供了類似 Google Suggest & Gmail/Yahoo Mail 所提供的功能
讓使用者輸入一個字及可帶出相關的選項供選擇
其做法也是在 Page 中定義一個 <div> Tag 來供 XHttpRequest 將回傳的 responseText
加入其 innerHTML 屬性中, 再透過 Javascript 與 DOM 的操作來控制該 <div> Tag 顯示的位置
後端要注意的是, 輸出的 HTML (目前我還是習慣用 HTML 的方式輸出, 因為 XML 還需搭配 XSLT 來呈現
還沒學到那邊), 要能與原先的 Page 互動. (可以在主 Page 上 define 一個 JS Function 供呼叫)
程式片段:
CSS 與 DIV
|
<style type="text/css"> DIV{ scrollbar-DarkShadow-Color:#9FB7D7; scrollbar-Track-Color:#F7F7F7; scrollbar-Face-Color:#C7CFFF; scrollbar-Shadow-Color:#FFFFFF; scrollbar-Highlight-Color:#FFFFFF; scrollbar-3dLight-Color:#C7CFF7; scrollbar-Arrow-Color:#4F5F87; } .autocomplete { background:#E0E0E0; position: absolute; border: solid 1px; overflow-y:scroll; overflow-x:auto; height:100px; display: none; }
</style> <div id="autocomplete" class="autocomplete"></div>
|
Script
|
<script type="text/javascript"> var oauto=new AjaxService(); oauto.callback=autoCompleteResponse;
function autoCompleteField(cust_code) { event.cancelBubble=true; var key=window.event.keyCode; switch (key){ case 9,13,27: // Tab, Enter, Esc 鍵 return; } var querystring="cust_code="+encodeURI(cust_code); var url = "/Authority/autoComplete.jsp?"+querystring; oauto.loadXMLDoc(url); return false; } function autoCompleteResponse() { // only if req shows "loaded" if (oauto.xhttp.readyState == 4) { // only if "OK" if (oauto.xhttp.status == 200) { $('autocomplete').innerHTML = oauto.xhttp.responseText; $('autocomplete').style.display="block"; $('autocomplete').style.width=$('cust_code').offsetWidth; var point = fGetXY($('cust_code')); $('autocomplete').style.top=point.y+$('cust_code').offsetHeight+15; $('autocomplete').style.left=point.x+10; } else { alert(errormsg + oauto.xhttp.statusText); } } }
function Point(iX, iY){ this.x = iX; this.y = iY; } function fGetXY(aTag){ var oTmp = aTag; var pt = new Point(0,0); do { pt.x += oTmp.offsetLeft; pt.y += oTmp.offsetTop; oTmp = oTmp.offsetParent; } while(oTmp.tagName!="BODY"); return pt; } function ChangeSelect(){ event.cancelBubble=true; var key=window.event.keyCode; switch (key){ case 9,13,27: // Tab, Enter, Esc 鍵 $('autocomplete').style.display="none"; } } function setValue(v){ $('cust_code').value=v; $('autocomplete').style.display="none"; query(1,v); } </script> |
控制項
|
<input autocomplete="off" type="text" name="cust_code" id="cust_code" size="20" onkeyup="if (frmQuery.chkAutoComplete.checked) autoCompleteField(this.value);" onkeydown="return ChangeSelect();" /> <input type="checkbox" value="1" name="chkAutoComplete" checked="checked" />啟用自動完成 |
在控制項的 onkeyup event 中去呼叫 autoCompleteField() 與後端 autoComplete.jsp 進行 Ajax 互動
encodeURI 是為了中文碼(雙位元碼)在 XMLHTTP 傳輸中 Unicode 轉換問題
在後端的 jsp 程式需使用
|
String cust_code=new String(request.getParameter("cust_code").getBytes("ISO-8859-1"),"UTF8"); |
來讀取 QueryString 中傳遞的參數.
主頁面編碼設為
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
這樣就不會有編碼的問題
後端 jsp 輸出
|
while (rs.next()){ out.print("<a href='#' onclick='setValue(\""+rs.getString("occ01").trim()+"\")' style='cursor:default'>"+rs.getString("occ01").trim()+" ("+rs.getString("occ02").trim()+")</a><br />"); } |
透過呼叫主頁面 setValue() 將選取的值回存至控制項中, 即大功告成. :)
可以將 script 的部份 define 成 .js 並修改參數的傳遞 及可當作 library 來使用囉. |  |
2/10/2006 終於練功練成
我的第一支以 Ajax 方式寫的程式可以上線了!!
透過 XMLHttpRequest 這個好幫手 (Firefox 內建物件, IE 則要透過 ActiveXObject("Microsoft.XMLHTTP"))
就可以以非同步的方式去將後端查到的資料 Show 在使用者查詢的文件上
並且透過 Cache 的機制, 可以快速的與後端進行溝通
Ajax(Asynchronous JavaScript+CSS+DOM+XMLHttpRequest) 不是一項新的技術, 而是一種 Web 2.0 時代的新的開發方式, 由 Jesse James Garrett 於 2005 年2 月所提出的一個新的名詞.
如果您使用過 Google Suggests 或 Google Maps, 您一定對於網頁可以這樣使用的方式眼睛為之一亮.
根據 Jesse 的定義
Ajax isn’t a technology. It’s really several technologies, each flourishing in its own right, coming together in powerful new ways. Ajax incorporates:
· standards-based presentation using XHTML and CSS;
· dynamic display and interaction using the Document Object Model;
· data interchange and manipulation using XML and XSLT;
· asynchronous data retrieval using XMLHttpRequest;
· and JavaScript binding everything together.
XHTML 是以 XML 的撰寫方式來編寫 HTML 網頁(也就是 Tag 的寫法要求比較嚴謹)
CSS 是美化網頁所不可或缺的東西
DOM(Document Object Model) 則是 Browser 解析網頁的物件模型, 也就是 DHTML(Dynamic HTML)的核心
新的東西只有 XMLHttpRequest 這一個物件, 伴隨 IE 5.x 之後所提供的一個物件呼叫模式(其實就是 Microsoft.XMLHTTP 這個 Dll), Firefox 則是內建在 Browser 物件中
所有上述的東西, 最後透過 Javascript 把它組合在一起
讓你瀏覽網頁時, 不再需要不斷的 refresh 以取得最新的資料, 而是類似 Windows Application 一般以一個畫面就可以完成所有的事.
Gmail 就是一個很好的例子.
我的第一支程式就是讓 Sales 能夠查詢客戶的信用評等資料, 以判斷是否爭取客戶的信用額度.
公司的徵信人員定期將上市/櫃公司的財報資料鍵入後端系統
業務人員在網頁上輸入客戶代號/客戶名稱, 即可取得各季的徵信資訊
在網頁瀏覽上, 完全沒有 refresh 的動作
只有一個簡單的輸入欄位與查詢按鈕
使用者按下查詢鈕後, XMLHttpRequest 去 request 相對應的 JSP 程式, 透過後端 JSP 分頁技術將資料處理好時, 會將資料以 XML Data Stream 的方式傳回前端(此動作是背景處理, 使用者感覺不出來)
前端透過 DOM 將資料展示在所設定的位置, 並且將資料 Cache
這樣使用者就可以很快速的更新資料(幾乎沒有停頓)
原始碼
<!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="PRAGMA" CONTENT="NO-CACHE"> <meta http-equiv="Content-Type" content="text/html; charset=big5" /> <meta http-equiv="Content-Language" content="zh-tw" /> <script type="text/javascript" src="/js/util.js"></script> <script type="text/javascript" src="/js/AjaxService.js"></script> <title>公司信用評等查詢系統</title> <script type="text/javascript"> var ajaxobj=new AjaxService();
function query(page,cust_code) { // This demo uses simple Html/JS only, so we load a static html page $('result').innerHTML="載入中..."; var url = "/Authority/auth_all.jsp?page="+page; var url1 = "/Authority/auth_cust.jsp?cust_code="+cust_code; //var callback = processAjaxResponse; ajaxobj.executeXhr((cust_code=="") ? url : url1); } </script> </head> <link rel="stylesheet" href="/css/styles.css" type="text/css"> <body> <form name="frmQuery" method="post"> <table width="100%" border="0" cellspacing="2" cellpadding="2" style="border: solid 1px; padding-left:10px;"> <tr> <td>請輸入客戶代碼/客戶簡稱</td> <td><input type="text" name="cust_code" size="20" /></td> <td><input type="button" value="查詢" onclick="query(1,frmQuery.cust_code.value)" /></td> </tr> </table> </form> <p> <div id="result"> </div> </p>
</body> </html>
藍色字 <div id="result"></div> 即是資料顯示的地方 |  |
|