<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    龍行天下

      政 博
    隨筆 - 23, 文章 - 0, 評論 - 12, 引用 - 0
    數據加載中……

    2006年5月3日

    FckEditor中文配置手冊詳細說明

    javascript調用方式:
    ------------------------------------
    <script. type=”text/javascript” src=”FCKeditor/fckeditor.js”></scrīpt>
    <textarea name=”content” cols=”80″ rows=”4″>
    </textarea>
    <script. type=”text/javascript”>
    var FCKeditor = new FCKeditor(”content”);
    oFCKeditor.BasePath = “FCKeditor/”;
    oFCKeditor.Height = 400;
    oFCKeditor.ToolbarSet = “Default”;
    oFCKeditor.ReplaceTextarea();
    </script>
    ------------------------------------
    如果想要使用從數據庫讀來的文本數據或者是后臺來自文件的txt/html文本數據。
    只要在
    ------------------------------------
    <textarea name=”content” cols=”80″ rows=”4″>
    </textarea>
    ------------------------------------
    中加入自己的顯示內容的formbean對應字段即可
    ------------------------------------
    <textarea name=”content” cols=”80″ rows=”4″>
    <c:out value=”${contentData}” />
    </textarea>
    ------------------------------------
    這樣內容就會被顯示在FCKeditor編輯框中了,點擊提交按鈕以后就可以在后臺的相應java action中得到content參數中的內容就是頁面上FCKeditor中的內容數據了。可以在struts/jsf中使用。
    ====================================
    由于給FCKeditor瘦身,所以常會報缺少對象支持等錯誤,只要在FCKeditor/editor/lang中加上相應的js語言文件即可。如果加載頁面失敗(FCKeditor未定義)還有一個可能就是引用FCKeditor/fckeditor.js文件路徑不對!
    關于FCKeditor瘦身要點如下:
    1.將FCKeditor目錄下及子目錄下所有以“_”下劃線開頭的文件夾刪除
    2.FCKeditor根目錄下只保留fckconfig.js, fckeditor.js, fckstyles.xml, fcktemplates.xml,其余全部刪除
    3.將editor/filemanager/upload目錄下文件及文件夾清空
    4.將/editor/filemanager/browser/default/connectors/下的所有文件刪除
    5.還可以將editor/skins目錄下的皮膚文件刪除,只留下default一套皮膚(如果你不需要換皮膚的話)
    6.還可以將editor/lang目錄下文件刪除,只保留en.js, fcklanguagemanager.js, zh-cn.js, zh.js文件
    7.如果你是使用javascrīpt來調用加載FCKeditor,那么就不需要在web.xml中配置fckeditor的tag文件。
    8.還有一個問題剛開始使用FCKeditor的人常會遇到就怎么控制它的toolbar的大小和元素排列,其實很簡單。
    在fckconfig.js中用這樣的標簽[]來劃分每行的元素的多少,這樣就可以控制toolbar的長短和大小了,具體示例參看:fckconfig.js中的toolbarset[”Default”]
    ====================================
    用fckconfig.js中的一些選項來控制toolbarset中控件的功能,實現功能裁剪:
    1):取消超鏈接中的瀏覽服務器和上傳功能,方法如下:
    ------------------------------------
    FCKConfig.LinkBrowser = true;
    FCKConfig.LinkUpload = true;
    改為:
    FCKConfig.LinkBrowser = false;
    FCKConfig.LinkUpload = false;
    ------------------------------------
    2):取消圖片鏈接中的瀏覽服務器和上傳功能,方法如下:
    ------------------------------------
    FCKConfig.ImageUpload = true;
    FCKConfig.ImageBrowser = true;
    改為:
    FCKConfig.ImageUpload = false;
    FCKConfig.ImageBrowser = false;
    ------------------------------------
    3):Dlg Button中取消高級功能,方法如下:
    FCKConfig.LinkDlgHideAdvanced = false ;
    FCKConfig.ImageDlgHideAdvanced = false ;
    改為:
    FCKConfig.ImageDlgHideAdvanced = true ;
    FCKConfig.LinkDlgHideTarget = true ;
    ------------------------------------
    下一篇介紹FCKeditor的上傳和瀏覽服務器功能,以及如何在里面實現動態
    超連接,轉發到servlet經過filter以后去調用服務器的action
    如何實現對應用戶瀏覽自己的圖片的列表實現!
    ====================================
    FCKeditor集成java servlet可以實現文件的上傳和服務器端列表讀取功能FCKeditor自己提供了兩個servlet來分別實現上傳文件功能,和讀取服務器端文件列表功能,這兩個servlet分別為:
    com.fredck.FCKeditor.connector.ConnectorServlet(讀取文件列表)
    com.fredck.FCKeditor.uploader.SimpleUploaderServlet(實現文件上傳)
    1.瀏覽服務器端文件列表
    ------------------------------------
    web.xml文件中,比如:ConnectorServlet中的配置選項:
    <init-param>
    <param-name>baseDir</param-name>
    <param-value>/UserFiles/</param-value>
    </init-param>
    意思是在瀏覽服務器上的baseDir配置指定里面的所有文件及其目錄結構列表。
    如果你的baseDir沒有配置,Connector將會自動創建一個默認的文件夾
    UserFiles,對應的ConnectorServlet中init()方法中代碼如下:
    ------------------------------------
    baseDir = getInitParameter(”baseDir”);
    if (baseDir == null)
    baseDir = “/UserFiles/”;
    ------------------------------------
    還想說一下的是,FCKeditor的client調用server的servlet方法采用的是Ajax思想來實現。當你點擊瀏覽服務器(browser server)的時候就會觸發一個異步的javascrīpt + xmlhttp的調用響應,后臺的servlet會去完成你要請求的事件,然后數據以xml方式返回給client來解析。很明顯,你要實現去數據庫或者其他的文件系統請求列表,你只要修改
    ConnectorServlet中兩個私有方法:getFolders 和 getFiles
    讓它去你指定的地方得到文件列表即可,這樣你的文件可以放在任何你指定目錄下。多說一句,很多人都想知道個人blog系統中怎么實現上傳文件以后對應用戶瀏覽自己的列表的,我的做法很簡單,建立你用戶名的文件夾,你上傳只能上傳到你的目錄夾,瀏覽可以通過程序指定瀏覽對應用戶下的文件夾即可,這個時候你要修改Connectorservlet中的路徑即可!
    ------------------------------------
    2.超連接重定位問題
    ------------------------------------
    FCKeditor可以插入超連接,實現對文件的預覽功能,只要我們稍微改變我們可以使FCKeditor編輯器支持對任意文件系統下的任意文件的客戶端瀏覽和下載保存!FCKeditor本來提供的是相對URL超鏈接,只要我們修改ConnectorServlet中傳遞給客戶端的地址的時候,把它改寫成絕對URL然后再通過我們自己的filter的servlet實現重定向去一個下載/瀏覽文件的struts的action方法就可以實現在客戶端對超連接文件的下載和瀏覽!說一下具體做法吧:
    1):修改ConnectorServlet傳遞給客戶端javascrīpt的路徑,代碼如下:
    String currentUrl = “http://” + request.getserver +request.getServerPort + request.getContextPath + resourcePath;
    以上代碼請在ConnectorServlet的doGet()里面拼裝!在調用CreateCommonXml()私有方法的時候參數傳入:
    myEl.setAttribute(”path”,currentPath);
    myEl.setAttribute(”url”,currentUrl);
    提醒一下resourcePath為在web.xml配置文件中ConnectorServlet中的一個初始化參數配置,等一下利用filter實現對超連接的重定位就提取URL中的這個配置參數來判斷,配置如下:
    <init-param>
    <param-name>resourcePath</param-name>
    <param-value>/fileSystem/</param-value>
    </init-param>
    2):建立你的filter servlet,實現對URL的截獲,對符合要求的URL進行重定位到你的對應action中去即可
    3):實現你的對應action來實現文件的上傳和下載功能即可!
    4):擴展功能-實現對URL的加密,對連接的URL中加上一串字符,最后幾位作為算法校驗,對不符合要求的URL連接,filter將會拒絕重定位到指定action。此外利用自己寫的擴展類還可以實現對超連接的文件類型進行限制,比如你只能超連接JPG|GIF|DOC|TXT|HTML等幾種后綴名的文件,對其他文件即使你指定超連接也讓你瀏覽和下載,這些都可以在web.xml中通過修改對應servlet的配置文件的初始化參數實現。
    3.頁面javascrīpt修改
    ------------------------------------
    瀏覽服務器的功能對應的html/javascrīpt相關的文件為:browser.html和frmresourcelist.html對應你想傳遞的信息你可以append在文件名的字符串后面,在GetFileRowHtml()的javascrīpt函數中實現對文件名的截取,這樣client只會顯示文件名,而你可以得到文件的數據庫唯一標識,任何你想要的信息你都可以通過修改ConnectorServlet中的私有方法getFiles()來實現,只要修改頁面frmresurcelist.html中的GetFileRowHtml()中傳入變量fileName即可。你還可以在點擊選中文件的時候實現一個你自己的Ajax調用,一切取決你的項目需要!
    4.我不是一個javascrīpt高手,其實如果我對javascrīpt了解多一些也許對客戶端的代碼修改以后做出更眩的功能。可以更好的完成對FCKeditor裁剪。
    -------------------------------------
    5.注意點
    -------------------------------------
    無論怎么修改別人的東西,請一定尊重開源精神!
    很多人配置好了FCKeditor的上傳功能以后常會遇到xmlhttp request 404 error,后面是一串路徑,其實就是你的servlet-mapping中的路徑不對,你只要把xmlhttp request errot 404 后面跟的路徑,copy到你的web.xml中對應紅色文字的位置,如下:
    <servlet-mapping>
    <servlet-name>Connector</servlet-name>
    <url-pattern>/FCKeditor/editor/filemanager/browser/default/connectors/jsp/connector</url-pattern>
    </servlet-mapping>
    別忘了SimpleUploader的servlet-mapping也要做同樣的修改!
    還有一個錯誤就是http 500錯誤,這個可能是你的URL請求不對,應該和FCKeditor沒關系的!
    ======================================
    fckconfig.js總配置文件,可用記錄本打開,修改后將文件存為utf-8 編碼格式。找到:
    --------------------------------------
    FCKConfig.TabSpaces = 0;
    改為:
    FCKConfig.TabSpaces = 1;
    即在編輯器域內可以使用Tab鍵。
    如果你的編輯器還用在網站前臺的話,比如說用于留言本或是日記回復時,那就不得不考慮安全了,
    在前臺千萬不要使用Default的toolbar,要么自定義一下功能,要么就用系統已經定義好的Basic,
    也就是基本的toolbar,找到:
    --------------------------------------
    FCKConfig.ToolbarSets[”Basic”] = [
    [’Bold’,'Italic’,'-’,'OrderedList’,'UnorderedList’,'-’,/*’Link’,*/’Unlink’,'-’,'Style’,'FontSize’,'TextColor’,'BGColor’,'-’,
    ‘Smiley’,'SpecialChar’,'Replace’,'Preview’] ];
    這是改過的Basic,把圖像功能去掉,把添加鏈接功能去掉,因為圖像和鏈接和flash和圖像按鈕添加功能都能讓前臺頁直接訪問和上傳文件, fckeditor還支持編輯域內的鼠標右鍵功能。
    FCKConfig.ContextMenu = [’Generic’,/*’Link’,*/’Anchor’,/*’Image’,*/’Flash’,'Select’,'Textarea’,'Checkbox’,'Radio’,'TextField’,'HiddenField’,
    /*’ImageButton’,*/’Button’,'BulletedList’,'NumberedList’,'TableCell’,'Table’,'Form’];
    這也是改過的把鼠標右鍵的“鏈接、圖像,FLASH,圖像按鈕”功能都去掉。
    找到:
    FCKConfig.FontNames = ‘Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana’;
    加上幾種我們常用的字體
    FCKConfig.FontNames = ‘宋體;黑體;隸書;楷體_GB2312;Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana’;
    添加文件 /TestFCKeditor/test.jsp:
    ----------------------------------------
    <%@ page language=”java” import=”com.fredck.FCKeditor.*” %>
    <%@ taglib uri=”/TestFCKeditor” prefix=”FCK” %>
    <script. type=”text/javascript” src=”/TestFCKeditor/FCKeditor/fckeditor.js”></script>
    <%–
    三種方法調用FCKeditor
    1.FCKeditor自定義標簽 (必須加頭文件 <%@ taglib uri=”/TestFCKeditor” prefix=”FCK” %> )
    2.script腳本語言調用 (必須引用 腳本文件 <script. type=”text/javascript” src=”/TestFCKeditor/FCKeditor/fckeditor.js”></script> )
    3.FCKeditor API 調用 (必須加頭文件 <%@ page language=”java” import=”com.fredck.FCKeditor.*” %> )
    –%>
    <%–
    <form. action=”show.jsp” method=”post” target=”_blank”>
    <FCK:editor id=”content” basePath=”/TestFCKeditor/FCKeditor/”
    width=”700″ height=”500″ skinPath=”/TestFCKeditor/FCKeditor/editor/skins/silver/”
    toolbarSet = “Default”>
    內容
    </FCK:editor>
    <input type=”submit” value=”Submit”>
    </form>
    –%>
    <form. action=”show.jsp” method=”post” target=”_blank”>
    <table border=”0″ width=”700″>
    <tr>
    <td>
    <textarea id=”content” name=”content” style=”WIDTH: 100%; HEIGHT: 400px”>input</textarea>
    <script. type=”text/javascript”>
    var FCKeditor = new FCKeditor(’content? ;
    oFCKeditor.BasePath = “/TestFCKeditor/FCKeditor/” ;
    oFCKeditor.Height = 400;
    oFCKeditor.ToolbarSet = “Default” ;
    oFCKeditor.ReplaceTextarea();
    </script>
    <input type=”submit” value=”Submit”>
    </td>
    </tr>
    </table>
    </form>
    <%–
    <form. action=”show.jsp” method=”post” target=”_blank”>
    <%
    FCKeditor oFCKeditor ;
    oFCKeditor = new FCKeditor( request, “content” ) ;
    oFCKeditor.setBasePath( “/TestFCKeditor/FCKeditor/” ) ;
    oFCKeditor.setValue( “input” );
    out.println( oFCKeditor.create() ) ;
    %>
    <br>
    <input type=”submit” value=”Submit”>
    </form>
    –%>
    添加文件/TestFCKeditor/show.jsp:
    <%
    String content = request.getParameter(”content”);
    out.print(content);
    %>
    ====================================
    1、適時打開編輯器
    ------------------------------------
    很多時候,我們在打開頁面的時候不需要直接打開編輯器,而在用到的時候才打開,這樣一來有很好的用戶體驗,另一方面可以消除FCK在加載時對頁面打開速度的影響,點擊“Open Editor”按鈕后才打開編輯器界面。
    實現原理:
    使用JAVASCRIPT版的FCK,在頁面加載時(未打開FCK),創建一個隱藏的TextArea域,這個TextArea
    的name和ID要和創建的FCK實例名稱一致,然后點擊”Open Editor”按鈕時,通過調用一段函數,使用
    FCK的ReplaceTextarea()方法來創建FCKeditor,代碼如下:
    ------------------------------------
    <script. type=”text/javascript”>
    <!–
    function showFCK(){
    var FCKeditor = new FCKeditor( ‘fbContent’ ) ;
    oFCKeditor.BasePath = ‘/FCKeditor/’ ;
    oFCKeditor.ToolbarSet = ‘Basic’ ;
    oFCKeditor.Width = ‘100%’ ;
    oFCKeditor.Height = ‘200′ ;
    oFCKeditor.ReplaceTextarea() ;
    }
    //–>
    </script>
    <textarea name=”fbContent” id=”fbContent”></textarea>
    2、使用FCKeditor 的 API
    -------------------------------------
    FCKeditor編輯器,提供了非常豐富的API,用于給End User實現很多想要定制的功能,比如最基本的數據驗證,如何在提交的時候用JS判斷當前編輯器區域內是否有內容,FCK的API提供了GetLength()方法;
    再比如如何通過腳本向FCK里插入內容,使用InsertHTML()等;
    還有,在用戶定制功能時,中間步驟可能要執行FCK的一些內嵌操作,那就用ExecuteCommand()方法。
    詳細的API列表,請查看FCKeditor的Wiki。而常用的API,請查看FCK壓縮包里的_samples/html/sample08.html。此處就不貼代碼了。
    3、外聯編輯條(多個編輯域共用一個編輯條)
    --------------------------------------
    這個功能是2.3版本才開始提供的,以前版本的FCKeditor要在同一個頁面里用多個編輯器的話,得一個個創建,現在有了這個外聯功能,就不用那么麻煩了,只需要把工具條放在一個適當的位置,后面就可以無限制的創建編輯域了。
    要實現這種功能呢,需要先在頁面中定義一個工具條的容器:<div id=”xToolbar”></div>,然后再根據這個容器的id屬性進行設置。
    JAVASCRIPT實現代碼:
    --------------------------------------
    <div id=”xToolbar”></div>
    FCKeditor 1:
    <script. type=”text/javascript”>
    <!–
    // Automatically calculates the editor base path based on the _samples directory.
    // This is usefull only for these samples. A real application should use something like this:
    // oFCKeditor.BasePath = ‘/fckeditor/’; // ‘/fckeditor/’ is the default value.
    var sBasePath = document.location.pathname.substring(0,document.location.pathname.lastIndexOf(’_samples’));
    var FCKeditor = new FCKeditor( ‘FCKeditor_1′ );
    oFCKeditor.BasePath = sBasePath;
    oFCKeditor.Height = 100;
    oFCKeditor.Config[ ‘ToolbarLocation’ ] = ‘Out:parent(xToolbar)’;
    oFCKeditor.Value = ‘This is some <strong>sample text</strong>. You are using FCKeditor.’;
    oFCKeditor.Create();
    //–>
    </script>
    <br />
    FCKeditor 2:
    <script. type=”text/javascript”>
    <!–
    FCKeditor = new FCKeditor( ‘FCKeditor_2′ );
    oFCKeditor.BasePath = sBasePath;
    oFCKeditor.Height = 100;
    oFCKeditor.Config[ ‘ToolbarLocation’ ] = ‘Out:parent(xToolbar)’;
    oFCKeditor.Value = ‘This is some <strong>sample text</strong>. You are using FCKeditor.’;
    oFCKeditor.Create();
    //–>
    </script>
    -------------------------------------
    此部分的詳細DEMO請參照_samples/html/sample11.html,_samples/html/sample11_frame.html
    4、文件管理功能、文件上傳的權限問題
    -------------------------------------
    一直以來FCKeditor的文件管理部分的安全是個值得注意,但很多人沒注意到的地方,雖然FCKeditor在各個Release版本中一直存在的一個功能就是對上傳文件類型進行過濾,但是她沒考慮過另一個問題:到底允許誰能上傳?到底誰能瀏覽服務器文件?
    之前剛開始用FCKeditor時,我就出現過這個問題,還好NetRube(FCKeditor中文化以及FCKeditor ASP版上傳程序的作者)及時提醒了我,做法是去修改FCK上傳程序,在里面進行權限判斷,并且再在fckconfig.js里把相應的一些功能去掉。但隨之FCK版本的不斷升級,每升一次都要去改一次配置程序fckconfig.js,我發覺厭煩了,就沒什么辦法能更好的控制這種配置么?事實上,是有的。
    在fckconfig.js里面,有關于是否打開上傳和瀏覽服務器的設置,在創建FCKeditor時,通過程序來判斷是否創建有上傳瀏覽功能的編輯器。首先,我先在fckconfig.js里面把所有的上傳和瀏覽設置全設為false,接著我使用的代碼如下:
    JAVASCRIPT版本:
    -------------------------------------
    <script. type=”text/javascript”>
    var FCKeditor = new FCKeditor( ‘fbContent’ );
    <% if power = powercode then %>
    oFCKeditor.Config[’LinkBrowser’] = true;
    oFCKeditor.Config[’ImageBrowser’] = true;
    oFCKeditor.Config[’FlashBrowser’] = true;
    oFCKeditor.Config[’LinkUpload’] = true;
    oFCKeditor.Config[’ImageUpload’] = true;
    oFCKeditor.Config[’FlashUpload’] = true;
    <% end if %>
    oFCKeditor.ToolbarSet = ‘Basic’;
    oFCKeditor.Width = ‘100%’;
    oFCKeditor.Height = ‘200′;
    oFCKeditor.Value = ‘’;
    oFCKeditor.Create();
    </script>
    -------------------------------------
    在按鈕旁邊加文字
    -------------------------------------
    打開 editor/js/ 兩個js文件
    fckeditorcode_gecko.js
    fckeditorcode_ie.js
    第一個是支持非ie瀏覽器的
    第二個文件是支持ie瀏覽器的
    搜索 FCKToolbarButton,可以看到許多類似這樣的語句:
    case ‘Save’:B = new FCKToolbarButton(’Save’, FCKLang.Save, null, null, true, null, 3); break;
    ‘Save’是按鈕英文名字
    FCKToolbarButton 的四個參數分別是:
    按鈕命令名稱,按鈕標簽文字,按鈕工具提示,按鈕樣式,按鈕是否在源代碼模式可見,按鈕下拉菜單其中將第4項參數設置為 FCK_TOOLBARITEM_ICONTEXT 即可使按鈕旁邊出現文字,注意沒有引號。
    例如:
    case ‘Preview’:B = new FCKToolbarButton(’Preview’, FCKLang.Preview, null, FCK_TOOLBARITEM_ICONTEXT, true, null, 5);
    這樣我們就可以將 我們經常用的3種模式源代碼、預覽、全屏編輯按鈕都加上文字了。
    解釋fck樣式的工作原理
    -------------------------------------
    fck的樣式設置涉及到了兩個文件,一個是你定義好的樣式表文件.css,另一個是告訴fck樣式表如何使用的xml文件,兩個文件確一不可。
    css文件的位置是不做要求的,但是需要你在應用的編輯器的頁面上插入樣式表文件的鏈接。這樣才能顯示出來樣式。
    fckstyles.xml 在與editor目錄同級的目錄下。該文件定義了那些樣式可以使用在那些標簽里面。
    這就是fck自帶的樣式xml定義:
    <?xml version=”1.0″ encoding=”utf-8″ ?>
    <Styles>
    <Style name=”Image on Left” element=”img”>
    <Attribute name=”style” value=”padding: 5px; margin-right: 5px” />
    <Attribute name=”border” value=”2″ />
    <Attribute name=”align” value=”left” />
    </Style>
    <Style name=”Image on Right” element=”img”>
    <Attribute name=”style” value=”padding: 5px; margin-left: 5px” />
    <Attribute name=”border” value=”2″ />
    <Attribute name=”align” value=”right” />
    </Style>
    <Style name=”Custom Bold” element=”span”>
    <Attribute name=”style” value=”font-weight: bold;” />
    </Style>
    <Style name=”Custom Italic” element=”em” />
    <Style name=”Title” element=”span”>
    <Attribute name=”class” value=”Title” />
    </Style>
    <Style name=”Code” element=”span”>
    <Attribute name=”class” value=”Code” />
    </Style>
    <Style name=”Title H3″ element=”h3″ />
    <Style name=”Custom Ruler” element=”hr”>
    <Attribute name=”size” value=”1″ />
    <Attribute name=”color” value=”#ff0000″ />
    </Style>
    </Styles>
    每一個<style>將來會生成一個樣式的菜單項。name名稱就是顯示在菜單里的文字;element定義了該樣式可以應用在那種html標簽上,<Attribute>的 name 指定了將會修改標簽的哪個屬性來應用樣式,value則是修改成的值。
    看這個:
    <Style name=”Title” element=”span”>
    <Attribute name=”class” value=”Title” />
    </Style>
    如果你在fck選定了文字 “經典論壇 》 前臺制作與腳本專欄 》 FCKeditor 實戰技巧 - 1 》 編輯帖子” 應用該樣式 則原來文字就會變成<span class=”Title”>經典論壇 》 前臺制作與腳本專欄 》 FCKeditor 實戰技巧 - 1 》 編輯帖子</span>
    注意:如果編輯器呈整頁編輯狀態,那么整頁里面也需要插入樣式表鏈接才能顯示出來樣式。
    ============================================
    FCKeditor JavaScript. API(翻譯整理)
    原文地址:http://wiki.fckeditor.net/Developer%27s_Guide/Javascript_API
    --------------------------------------------
    FCK 編輯器加載后,將會注冊一個全局的 FCKeditorAPI 對象。
    FCKeditorAPI 對象在頁面加載期間是無效的,直到頁面加載完成。如果需要交互式地知道 FCK 編輯器已經加載完成,可使用“FCKeditor_OnComplete”函數。
    <script. type=”text/javascript”>
    function FCKeditor_OnComplete(editorInstance) {
    FCKeditorAPI.GetInstance(’FCKeditor1′).Commands.GetCommand(’FitWindow’).Execute();
    }
    </script>
    在當前頁獲得 FCK 編輯器實例:
    var Editor = FCKeditorAPI.GetInstance(’InstanceName’);
    從 FCK 編輯器的彈出窗口中獲得 FCK 編輯器實例:
    var Editor = window.parent.InnerDialogLoaded().FCK;
    從框架頁面的子框架中獲得其它子框架的 FCK 編輯器實例:
    var Editor = window.FrameName.FCKeditorAPI.GetInstance(’InstanceName’);
    從頁面彈出窗口中獲得父窗口的 FCK 編輯器實例:
    var Editor = opener.FCKeditorAPI.GetInstance(’InstanceName’);
    獲得 FCK 編輯器的內容:
    oEditor.GetXHTML(formatted); // formatted 為:true|false,表示是否按HTML格式取出
    也可用:
    oEditor.GetXHTML();
    設置 FCK 編輯器的內容:
    oEditor.SetHTML(”content”, false); // 第二個參數為:true|false,是否以所見即所得方式設置其內容。此方法常用于“設置初始值”或“表單重置”操作。
    插入內容到 FCK 編輯器:
    oEditor.InsertHtml(”html”); // “html”為HTML文本
    檢查 FCK 編輯器內容是否發生變化:
    oEditor.IsDirty();
    在 FCK 編輯器之外調用 FCK 編輯器工具條命令:
    命令列表如下:
    --------------------------------------------
    DocProps, Templates, Link, Unlink, Anchor, BulletedList, NumberedList, About, Find, Replace, Image, Flash, SpecialChar, Smiley, Table, TableProp, TableCellProp, UniversalKey, Style, FontName, FontSize, FontFormat, Source, Preview, Save, NewPage, PageBreak, TextColor, BGColor, PasteText, PasteWord, TableInsertRow, TableDeleteRows, TableInsertColumn, TableDeleteColumns, TableInsertCell, TableDeleteCells, TableMergeCells, TableSplitCell, TableDelete, Form, Checkbox, Radio, TextField, Textarea, HiddenField, Button, Select, ImageButton, SpellCheck, FitWindow, Undo, Redo
    --------------------------------------------
    使用方法如下:
    --------------------------------------------
    oEditor.Commands.GetCommand(’FitWindow’).Execute();
    --------------------------------------------

    posted @ 2008-01-09 12:52 feingto 閱讀(2996) | 評論 (0)編輯 收藏

    FCKEditor的賦值和取值操作

    1、獲取編輯器中HTML內容

    function getEditorHTMLContents(EditorName)

        
    var oEditor = FCKeditorAPI.GetInstance(EditorName); 
        
    return(oEditor.GetXHTML(true)); 
    }


    2、獲取編輯器中文字內容(在博客發布時獲取無html代碼摘要使用)

    function getEditorTextContents(EditorName)

        
    var oEditor = FCKeditorAPI.GetInstance(EditorName); 
        
    return(oEditor.EditorDocument.body.innerText); 
    }


    3、設置編輯器中內容

    function SetEditorContents(EditorName, ContentStr)

        
    var oEditor = FCKeditorAPI.GetInstance(EditorName) ; 
        oEditor.SetHTML(ContentStr) ; 
    }

    posted @ 2008-01-09 12:51 feingto 閱讀(2084) | 評論 (1)編輯 收藏

    Script.aculo.us開發系列(八):使用DropDrag定義拖拽行為

     

    在不同的瀏覽器上默認的拖拽能解決的問題相當少,所以有很多的框架都能實現這么個功能.使用拖拽行為能很好的改善用戶體驗,尤其是在購物的時候能讓用戶感到很新奇和體面.Script.aculo.us使用了三個類實現拖拽和排序,它們是Draggable,Droppable,Sortable.要實現一個完整的拖拽行為,需要Draggable,和Droppable的配合使用,由于這連個類的方法比較多,我只選取比較實用的幾個方法進行介紹.還是老規矩,先看看Demo:http://www1.qcxy.hb.cn/qphy/Script_Aculo_Us/DragDrop.html

    Draggable

    new Draggable("DraggableId"[,options])

    主要選項

    • snap:推拽的最小單位,默認為false,可以是數組或者函數,將這個屬性設置為[50,50],意味著最小的位移單位是50px,50px,如果設置為一個函數,這個函數的參數為(x,y),這個x,y指示當前的絕對坐標,函數應該返回二維數組,上面的例子中的Drag(UnAcceptable)推拽到頁面的左上角是就會"吸附"上去,就是因為函數的作用,詳細見源碼
    • revert:推拽完畢之后是否回到原來的位置,默認為false,也可以是一個函數,這個函數必須返回true/false
    • handle:"提手",移動整個塊的時候通常不需要在整個塊的區域都可以拖拽,比如移動一個欄目,通常只需要拖拽標題(比如Google的個性化主頁),將該屬性設置為標題的Id
    • ghosting:推拽的過程中是否顯示"影子",默認為false
    • constraint:限制能拖動的方向,默認的兩個方向都可以,可以設置為"vertical","horizontal"的任意
    • zindex:"影子"的z-Index屬性
    • scroll:拖拽出視圖范圍是否顯示自動滾動
    • scrollSensitivity/scrollSpeed:默認值分為為20/15,控制滾動的敏感度和滾動速度
    • delay:拖拽前的延時,開始拖拽后經過這個時間才"回過神來"

    這里需要說明的是并非所有的標簽都支持該行為,詳細的情況請參閱官方文檔

    API

    • onStart:開始拖拽調用該函數,接受兩個參數(obj,oEvent)前者是$(DraggableId),后者是當前事件的event對象
    • onDrag:在拖拽過程中反復的調用該函數,同樣接受兩個參數(obj,oEvent)
    • change:在onDrag后調用,也會反復調用
    • onEnd:拖拽行為結束調用,即鼠標彈起時激發
    • destroy():該方法銷毀元素的拖拽行為

    Droppables

    Droppables(注意是復數形式)是一個抽象類,不能被實例化,只有一些靜態方法,常用的方法有add和move,分別增加可放置元素,和去除可放置元素

    add方法:Dropables.add("ContainerId"[,options]),常用的選項

    • accept: 數組或者字符串,表示該容器接受的元素的className的集合,默認的任何元素都接收
    • hoverclass:當符合接受要求的元素拖至容器上時,其className
    • onDrop():被拖拽的符合要求的元素在這里放置時調用該函數,接受三個參數(draggable,droppable,oEvent),draggable是被拖拽元素,droppable是被放置元素,oEvent當前事件對象

    remove("ContainerId"),該方法去除容器的放置行為

    (上面例子的源代碼)

    Sortable

    Sortable是一組可以通過拖拽交換位置的元素,可以先看看實例(

    serialize(sortable)方法:該方法返回當前容器內元素的次序,但是要求子元素的id必須以"item_"開頭,且返回格式有講究,看下面的例子

    <div id="horizontalSortable" class="item" style="margin-top:20px; height:40px;">
          <div id="item_5">IE</div>
          <div id="item_6">FireFox</div>
          <div id="item_7">Safari</div>
          <div id="item_8">Opera</div>
    </div>

    Sortable.create("horizontalSortable",
    {
         ghosting:true,
         tag:'div',
         constraint:'horizontal',
         hoverclass:'hoverClass2'
    });

    Sortable.serialize('horizontalSortable')
    //-->horizontalSortable[]=5&horizontalSortable[]=6&horizontalSortable[]=7&horizontalSortable[]=8

    最后看一個例子,前面提到的containment選項在某些情況下很有用,比如要實現兩個容器里的元素可以互相交換子元素,即從一個容器拖至令一個容器中.來看下面的例子

    <script type="text/javascript">
      Sortable.create('sortUlLeft',{containment:['sortUlLeft','sortUlRight'], dropOnEmpty:
    true,ghosting:true,constraint:false,hoverclass:'hoverClass'});
      Sortable.create('sortUlRight',{containment:['sortUlLeft','sortUlRight'], dropOnEmpty:
    true,ghosting:true,constraint:false,hoverclass:'hoverClass'});

    </script>

    上面的例子可以實現sortUlLeft,和sortUlRight的子元素互相交換

    posted @ 2008-01-05 14:14 feingto 閱讀(561) | 評論 (0)編輯 收藏

    用script.aculo.us實現像google suggest自動完成功能

     

    實現像google suggest自動完成功能

    首先創建一個jsp

    <%@ page language="java" pageEncoding="UTF-8"%>

    <html>
    <head>
    <script type="text/javascript" src="js/prototype.js"></script>
    <script type="text/javascript" src="js/effects.js"></script>
    <script type="text/javascript" src="js/controls.js"></script>
    <style>
    div.auto_complete {
      width: 350px;
      background: #fff;
    }
    div.auto_complete ul {
      border:1px solid #888;
      margin:0;
      padding:0;
      width:100%;
      list-style-type:none;
    }
    div.auto_complete ul li {
      margin:0;
      padding:3px;
    }
    div.auto_complete ul li.selected {
      background-color: #ffb;
    }
    div.auto_complete ul strong.highlight {
      color: #800;
      margin:0;
      padding:0;
    }
    </style>

    </head>
    <body>
    <input type="text" id="autocomplete"/>
    <div id="results" class="auto_complete"></div>
    <script type="text/javascript">
     new Ajax.Autocompleter(
      "autocomplete",
      "results",
      "list.html", {
       method: "GET"
      }
     );
    </script>
    </body>
    </html>

     

    list.html

    <ul>
    <li>Aria</li>
    <li>Aaaa</li>
    <li>Afdsa</li>
    <li>bsa</li>
    </ul>

    上面list.html采用靜態頁面返回列表,讀者可以使用動態頁面返回結果。

    posted @ 2008-01-03 09:20 feingto 閱讀(1959) | 評論 (3)編輯 收藏

    怎么避免瀏覽器緩存靜態文件

    對于動態文件,比如 index.asp?id=...  或者 index.aspx?id=... 相信有經驗的程序員都知道怎樣禁止瀏覽器緩存數據了.
    但是對于靜態文件(css,jpg,gif等等), 在什么場合下面我們需要禁止瀏覽器緩存他們,怎么做?

    本文討論的主題是如何防緩存, 尤其是如何防止靜態文件被緩存..


    在  RE:對博客園URL的一些調整建議, 二級域名不利于客戶端瀏覽器緩存 一文中,我提到了怎么最大化的
    利用瀏覽器緩存功能,來提高客戶端瀏覽速度, 減輕服務器負擔的.

    但是事物總是一分為二的,并不是所有的場合都要使用緩存的. 有時候我們的數據被緩存了反而會給我們帶來麻煩.

    對于動態數據(從數據庫讀取生成的那些),我們可以通過以下方法來禁止瀏覽器緩存。

    'asp 為例 禁止緩存

    Response.Buffer 
    = True 
    Response.ExpiresAbsolute 
    = Now() - 1 
    Response.Expires 
    = 0 
    Response.CacheControl 
    = "no-cache" 
    Response.AddHeader 
    "Pragma""No-Cache" 

    對于Ajax 的請求(不管是靜態數據還是動態數據):

    //以下三種方法使用其中任何一種方法都可以
    xmlhttp.setRequestHeader("Cache-Control","no-cache");  
    //或者
    xmlhttp.setRequestHeader("If-Modified-Since","0");
    //或者
    xmlhttp.Open(url+'?rnd='+Math.random(),....)

    如果使用 prototype.js  , 用類似這樣的代碼 
    new Ajax.Request(url,{method:"get",requestHeaders:["Cache-Control","no-cache"]})
    或者
    new Ajax.Request(url,{method:"get",requestHeaders:["If-Modified-Since","0"]})
     

    什么情況下,要禁止靜態文件緩存:
    1、經常可能要改動的 js, css.
           比如 一個html 文件, test.html 在 1.0版本中。可能是這樣
         <script src="common.js"></script>
         修改后  v1.1版本:
     <script src="common.js"></script>
     <script src="foo.js"></script>
       新增加了一個foo.js  同時,也改動了common.js , 在common.js 中定義了新的類,并在foo.js 中使用了common.js. 

    在這種情況下如果以前用戶瀏覽過 1.0版本的 html 文件,那么他的瀏覽器自動緩存了 common.js
    當他瀏覽新版本的時候,因為使用的是 v1.1的 foo.js 和 v1.0的 common.js ,這樣將導致腳本出錯。


    解決方法探討:
      因為css,js 是通過 <script src=....> 這種方式加載的,所以,很難使用 asp 的那種服務器端禁止緩存的辦法。也很難使用ajax的通過設置 http請求頭的辦法禁止使用緩存。

    看來隨機數是個好辦法。

    //方法一:
    document.write("<script src='test.js?rnd="+Math.random()+"'></s"+"cript>")

    //方法二:
    var js=document.createElement("script")
    js.src
    ="test.js"+Math.random()
    document.body.appendChild(js)


    但是,如果采用隨機數的話, js文件將永遠得不到緩存,每次都必須重新從服務器加載,即使沒有任何更改。
    大家如果經常上國外網站的話,可以看到他們通常采用這樣的方式來解決:
    <script src="test.js?ver=113"></script>
    其中 ver=113 的 113就是版本號,一般都是采用 CVS 或其他工具生成的開發版本號。

    這樣真正做到了應該緩存的時候緩存靜態文件,當版本有更新的時候從獲取最新的版本,并更新緩存。
    對于圖像 <img src="test.jps?ver=在CVS的版本號"> 來有效利用和更新緩存.


    唉,現在在CSDN的Web版,不知道有多少人在重復問著同一個問題。“怎么通過程序刪除清空客戶端的瀏覽器緩存”.........

     

    未完待續:

    下一篇:  利用瀏覽器緩存來改善用戶體驗。。。。Ajax模式之預先加載

    敬請關注,等我寫完再加上鏈接

    posted @ 2008-01-03 09:19 feingto 閱讀(2567) | 評論 (1)編輯 收藏

    AJAX框架/庫比較和選擇:ECHO2, GWT, DOJO, PROTOTYPE, JQUERY

    看了幾篇中英文的AJAX庫/框架比較文章,為方便選擇使用,特歸納如下:
    首先,要在兩個類別中選擇,一個是編譯類,一個是非編譯類別。
    Echo2/GWT是將JAVA代碼編譯成JAVASCRIPT,乍看很方便,不用掌握JS也能做出炫目界面。但這只適于不會或者不想了解JS的情況,對于還是想完全控制和定制界面的項目就不適合。
    另外,有一種觀點認為JAVA->JS轉換是一種低級語言向高級語言轉換,本身沒有意義。有點像去學匯編,然后再找個工具把匯編語言代碼轉換成C代碼來用。我雖然沒完全想通這個觀點,不過,我一直用C/C++,這幾年才逐漸發現JAVA確實是一種進化。沒準別人說的是對的呢?
    在Echo2和GWT中,GWT大部分工作是在客戶端,盡量少跟SERVER打交道,適合大型網站運用;ECHO2信奉“用到才加載”的信條,所以會有大量向SERVER的訪問,適合企業應用。另外,個人覺得ECHO2是個更全面的的一站式框架,界面也非常炫。但它的開發工具要收費。
    再談非編譯類別,它們包括DOJO、PROTOTYPE、JQEURY,下面一一介紹:
    先說PROTOTYPE,它比較輕量極,能讓你的代碼更加簡化。最經典莫過于“美圓函數”:
    document.getElementById(’elementid’) 變成$(’elementid’)
    它加強了JS語言的可開發性,降低了學習JS的門檻。
    DOJO最吸引人的是它的事件系統和豐富的可定制組件。它可以用形如下面的語句為各種HTML元素加入事件:
    dojo.event.connect(someNode, "onclick", doStuff);
    正由于DOJO提供了強大功能,它分成了許多包,可以分別包含使用。
    JQUERY也提供了美圓函數,它的插件系統也提供象DOJO的組件,但它沒有PROTOTYPE那樣簡潔,也沒有DOJO這么多的組件供使用,但它兼收兩家優點,并且個頭不大,文檔也算完整,所以說它介乎于前述兩者之間。
    所以,如果你需要非常完整的工具組件請用DOJO,如果你想優化你的JS代碼,提高書寫技巧請用PROTOTYPE,如果你想兩者兼顧就用JQUERY。

    posted @ 2007-12-30 20:37 feingto 閱讀(482) | 評論 (0)編輯 收藏

    prototype.js開發筆記

         摘要: Table of Contents 1. Programming Guide 1.1. Prototype是什么? 1.2. 關聯文章 1.3. 通用性方法 1.3.1. 使用 $()方法 1.3.2. 使用$F()方法 1.3.3. 使用$A()方法 1.3.4. 使用$H()方法 1.3.5. 使用$R()方法 1.3.6. 使用Try.these()方...  閱讀全文

    posted @ 2007-12-30 18:07 feingto 閱讀(416) | 評論 (0)編輯 收藏

    Prototype 1.5 Ajax 使用教程

    2.3  Prototype對Ajax的支持

    作為一個Ajax開發框架,Prototype對Ajax開發提供了有力的支持。在Prototype中,與Ajax相關的類和對象包括:Ajax、Ajax.Responsders、Ajax.Base、Ajax.Request、Ajax. PeriodicalUpdater和Ajax.Updater,圖2-3所示為這些類和對象之間的關系及其常用屬性和方法,下面分別對這些類和對象進行介紹。

    圖2-3  Prototype中Ajax相關類和對象關系示意圖

    2.3.1  Ajax對象

    Ajax對象為其他的Ajax功能類提供了最基本的支持,它的實現如2.2.7節中例2-10所示,其中包括一個方法getTransport和一個屬性activeRequestCount。getTransport方法返回一個XMLHttpRequest對象,activeRequestCount屬性代表正在處理中的Ajax請求的個數。

    2.3.2  Ajax.Base類

    Ajax.Base類是Ajax.Request類和Ajax.PeriodicalUpdater類的基類。它提供了3個方法:

    l  setOptions:設置Ajax操作所使用的選項。

    l  responseIsSuccess:判斷Ajax操作是否成功。

    l  responseIsFailure:判斷Ajax操作是否失敗(與responseIsSuccess相反)。

    Ajax.Base類的主要作用是提取出一些公用的方法,其他類通過繼承的方式使用這些方法,實現代碼復用。

    2.3.3  Ajax.Request類

    這是Prototype中最經常使用的一個Ajax相關類。Ajax.Request類的方法通常是內部使用的,因此這里就不一一列舉,有興趣的讀者可以參考Prototype的源代碼。這里重點講講如何使用Ajax.Request類,首先給出一個最簡單的Ajax.Request類的應用示例,如例2-11所示,注意示例中的黑體字。

    例2-11  Ajax.Request類應用示例

    Ajax.Request測試頁面:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html>

        <head>

            <title>chapter 3</title>

            <script type="text/javascript" language="javascript"

             src="prototype.js" ></script>

            <script type="text/javascript" language="javascript">

            function test() {

                // 創建Ajax.Request對象,發起一個Ajax請求

                var myAjax = new Ajax.Request(

                    'data.html', // 請求的URL

                    {

                        method: 'get',  // 使用GET方式發送HTTP請求

                        onComplete: showResponse // 指定請求成功完成時需要執行的方法

                    }

                );

            }

            function showResponse(response) {

                $('divResult').innerHTML = response.responseText;

            }

            </script>

        </head>

        <body>

        <input type="button" value="click" onclick="test()" />

        <div id="divResult" />

        </body>

    </html>

    data.html

    <input type="text" id="name" />

    <input type="button" value="Click Me" onclick="sayHi()">

    Ajax.Request對象在初始化時需要提供兩個參數:第1個參數是將要請求頁面的URL,這里使用的data.html是一個普通的HTML靜態頁面;第2個參數是Ajax操作的選項,在Prototype中并沒有專門為Ajax操作選項定義一個類,通常都是像例2-11這樣,通過匿名對象的方式設置Ajax操作的參數。在例2-11中,Ajax操作選項具有兩個屬性:method表示HTTP請求方式,默認是POST方式;onComplete指定了Ajax操作完成以后(即XMLHttpRequest對象的status屬性為4時),頁面將要執行的函數。當然,Ajax操作還包括很多其他選項,如表2-1所示。

    表2-1  Ajax操作選項屬性含義

    屬性名稱

    含義

    method

    HTTP請求方式(POST/GET/HEAD)。

    parameters

    在HTTP請求中傳入的URL格式的值列表,即URL串中問號之后的部分。

    asynchronous

    是否做異步XMLHttpRequest請求。

    postBody

    在POST請求方式下,傳入請求體中的內容。

    requestHeaders

    和請求一起被傳入的HTTP頭部列表,這個列表必須含有偶數個項目,因為列表中每兩項為一組,分別代表自定義部分的名稱和與之對應的字符串值。

    onXXXXXXXX

    在HTTP請求、響應的過程中,當XMLHttpRequest對象狀態發生變化時調用的響應函數。響應函數有5個:onUninitialized、onLoading、onLoaded、onInteractive和onComplete。傳入這些函數的參數可以有2個,其中第1個參數是執行HTTP請求的XMLHttpRequest對象,第2個參數是包含被執行的X-JSON響應的HTTP頭。

    onSuccess

    Ajax操作成功完成時調用的響應函數,傳入的參數與onXXXXXXXX相同。

    onFailure

    Ajax操作請求完成但出現錯誤時調用的響應函數,傳入的參數與onXXXXXXXX相同。

    onException

    Ajax操作發生異常情況時調用的響應函數,它可以接收2個參數,其中第1個參數是執行HTTP請求的XMLHttpRequest對象,第2個參數是異常對象。

    2.3.4  Ajax.Updater類

    例2-11使用Ajax.Request類實現了頁面的局部刷新效果,而這樣類似的功能在Ajax應用中是經常使用的。因此,為了簡化這種工作,Prototype框架從Ajax.Requet類中派生出一個子類——Ajax.Updater。與Ajax.Request相比,Ajax.Updater的初始化多了一個container參數,該參數代表將要更新的頁面元素的id。例2-11的功能通過Ajax.Updater的實現,會變得更加簡單,如例2-12所示。

    例2-12  Ajax.Updater類的應用示例

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html>

        <head>

            <title>chapter 3</title>

            <script type="text/javascript" language="javascript"

             src="prototype.js" ></script>

            <script type="text/javascript" language="javascript">

            function test() {

                var myAjax = new Ajax.Updater(

                    'divResult', // 更新的頁面元素

                    'data.html', // 請求的URL

                    {

                        method: 'get'

                    }

                );

            }

            </script>

        </head>

        <body>

        <input type="button" value="click" onclick="test()" />

        <div id="divResult" />

        </body>

    </html>

    此外,Ajax.Updater類還有另外一個功能,如果請求的頁面內容中包括JavaScript腳本,Ajax.Updater類可以執行其中的腳本,只需要在Ajax操作選項中增加屬性“evalScripts: true”即可。對例2-11中的data.html進行修改,在其中加入JavaScript腳本,如例2-13所示。

    例2-13  data.html

    <script language="javascript" type="text/javascript">

    sayHi = function() {

        alert("Hello, " + $F('name') + "!");

    }

    </script>

    <input type="text" id="name" />

    <input type="button" value="Click Me" onclick="sayHi()">

    調用Ajax.Updater的JavaScript腳本修改為:

    function test() {

        var myAjax = new Ajax.Updater(

            'divResult', // 更新的頁面元素

            'data.html', // 請求的URL

            {

                method: 'get',

                evalScripts: true

            }

        );

    }

    這樣就可以使用data.html頁面的內容更新當前頁面中的<div>元素divResult,并且執行data.html頁面中包含的JavaScript腳本。

    這里需要注意的是例2-13中sayHi函數的寫法,如果寫成

    function sayHi() {

        alert("Hello, " + $F('name') + "!");

    }

    或者

    var sayHi = function() {

        alert("Hello, " + $F('name') + "!");

    }

    程序是不能正常運行的。這是因為Ajax.Updater執行腳本是通過eval的方式,而不是將腳本內容引入到當前頁面,直接聲明的function sayHi或者用var聲明的sayHi函數,其作用域只是在這段腳本內部,外部的其他腳本不能訪問sayHi函數。而按照例2-13的方式聲明的函數,其作用域是整個window。

    2.3.5  Ajax.PeriodicalUpdater類

    和Ajax.Request類相似,Ajax.PeriodicalUpdater類也繼承自Ajax.Base類。在一些Ajax應用中,需要周期性地更新某些頁面元素,例如天氣預報、即時新聞等等。實現這樣的功能通常要使用JavaScript中的定時器函數setTimeout、clearTimeout等,而有了Ajax.PeriodicalUpdater類可以很好地簡化這類編碼工作。

    新建一個Ajax. PeriodicalUpdater類的實例需要指定3個參數:

    l  container:將要更新的頁面元素id;

    l  url:請求的URL地址;

    l  options:Ajax操作選項。

    和Ajax.Updater類相似,Ajax.PeriodicalUpdater類也支持動態執行JavaScript腳本,只需在Ajax操作選項中增加(evalScripts: true)屬性值即可。

    Ajax.PeriodicalUpdater類支持兩個特殊的Ajax操作選項:frequency和decay。frequency參數很容易理解,既然是定時更新頁面元素,或者定時執行腳本,那么多長時間更新或者執行一次呢?frequency指的就是兩次Ajax操作之間的時間間隔,單位是秒,默認值為2秒。

    如果僅指定frequency參數,程序會按照固定的時間間隔執行Ajax操作。這樣的更新策略合理嗎?答案取決于請求URL中數據的更新頻率。如果請求的數據會很有規律地按照固定頻率改變,那么只要設置一個合適的frequency值,就可以很有效地實現頁面的定時更新。然而實際應用中的數據往往不會那么理想,例如新聞,可能在一天中只有特定的一段時間更新頻率會很高,而在其他時間則幾乎沒有變化。經常遇到這樣的情況該怎么辦呢?Ajax.PeriodicalUpdater類支持的decay屬性就是為了解決這個問題而產生的。當option中帶有decay屬性時,如果請求返回的數據與上次相同,那么下次進行Ajax操作的時間間隔會乘以一個decay的系數。

    為了比較明顯地看到decay屬性的效果,在請求的測試頁面中加入記錄時間的腳本,代碼如例2-14所示。

    例2-14  Ajax.PeriodicalUpdater類應用示例

    ex10.html

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html>

        <head>

            <title>chapter 3</title>

            <script type="text/javascript" language="javascript"

             src="prototype.js" ></script>

            <script type="text/javascript" language="javascript">

            var str='';

            var intcount=0;

            function test() {

                var myAjax = new Ajax.PeriodicalUpdater(

                    'divResult', // 定時更新的頁面元素

                    'script1.html', // 請求的URL

                    {

                        method: 'get', // HTTP請求的方式為GET

                        evalScripts: true, // 是否執行請求頁面中的腳本

                        frequency: 1, // 更新的頻率

                        decay: 1 // 衰減系數

                    }

                );

            }

            </script>

        </head>

        <body>

        <input type="button" value="click" onclick="test()" />

        <div id="divResult" ></div>

        <div id="divResult2" ></div>

        </body>

    </html>

    script1.html:

    <script language="javascript" type="text/javascript">

    // Ajax.PeriodicalUpdater調用函數計數

    // 在<div>元素divResult2中增加一行結果,并記錄當前時間和

    // Ajax.PeriodicalUpdater的調用次數

    intcount++;

    str = $('divResult2').innerHTML;

    $('divResult2').innerHTML = str + "count = " + intcount+ ": " + new Date() + "<br>";

    </script>

    例2-14的運行結果如圖2-4所示。

    圖2-4  Ajax.PeriodicalUpdater類應用示例

    可以看到,由于請求返回的數據一直沒有發生變化,每次請求時間的間隔是上一次的2倍(decay=2)。如果某一次請求返回的數據發生了變化,那么執行請求的時間間隔則恢復到初始值。

    2.3.6  Ajax.Responders對象

    Ajax.Responders對象維護了一個正在運行的Ajax對象列表,在需要實現一些全局的功能時就可以使用它。例如,在Ajax請求發出以后需要提示用戶操作正在執行中,而操作返回以后則取消提示。利用Ajax.Responders對象就可以實現這樣的功能,如例2-15所示。

    例2-15  Ajax.Responders對象應用示例

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html>

        <head>

            <title>chapter 3</title>

            <script type="text/javascript" language="javascript"

             src="prototype.js" ></script>

            <script type="text/javascript" language="javascript">

            function test() {

                var myAjax = new Ajax.Request(

                    'data.html',

                    {

                        method: 'get',

                        onComplete: showResponse

                    }

                );

            }

            function showResponse(response) {

                $('divResult').innerHTML = response.responseText;

            }      

            var handle = {

                onCreate: function() {

                    Element.show('loading'); // 當創建Ajax請求時,顯示loading

                },

                onComplete: function() {

                    // 當請求成功返回時,如果當前沒有其他正在運行中的Ajax請求,隱藏loading

                    if (Ajax.activeRequestCount == 0) {

                        Element.hide('loading');

                    }

                }

            };

            // 將handle注冊到全局的Ajax.Responders對象中,使其生效

            Ajax.Responders.register(handle);

            </script>

        </head>

        <body>

        <input type="button" value="click" onclick="test()" />

        <div id="divResult" ></div>

        <div id='loading' style="display:none">

            <img src="loading.gif">Loading...

        </div>

        </body>

    </html>

    例2-15中定義了一個handle對象,其中包含onCreate和onComplete函數。頁面中發出任何一個Ajax請求時都會調用onCreate方法,而請求完成時都會調用onComplete方法。例2-15的運行結果如圖2-5所示。

    posted @ 2007-12-30 18:03 feingto 閱讀(565) | 評論 (0)編輯 收藏

    對xml進行增、刪、改的很好例子

    rule.hta
    ================

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
    <HTML>
    <HEAD>
    <TITLE>XML Editer</TITLE>
    <HTA:APPLICATION ID="oHTA"
    APPLICATIONNAME="myApp"
    BORDER="thick"
    BORDERSTYLE="normal"
    CAPTION="yes"
    ContextMenu="yes"
    ICON=""
    MAXIMIZEBUTTON="yes"
    MINIMIZEBUTTON="yes"
    scroll="no"
    selection="no"
    SHOWINTASKBAR="yes"
    SINGLEINSTANCE="yes"
    SYSMENU="yes"
    VERSION="1.0"
    WINDOWSTATE="normal"
    >

    <style type="text/css">
    </style>
    </HEAD>

    <script language="javascript">

    // load the xml file
    var xmlDoc = new ActiveXObject("Msxml2.DOMDocument");
    xmlDoc.async = false;
    xmlDoc.resolveExternals = false;
    xmlDoc.load("rule.xml");

    // load the xsl file
    var xslDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument");
    xslDoc.async = false;
    xslDoc.resolveExternals = false;
    xslDoc.load("rule.xsl");

    // create the xslt object
    var xslt = new ActiveXObject("Msxml2.XSLTemplate");
    xslt.stylesheet = xslDoc;
    var xslProc = xslt.createProcessor();
    xslProc.input = xmlDoc;

    var checked_count = 0;
    var cur_page = 1;
    var total_page = 1;

    function OutputDocument(number){
    xslProc.addParameter("ename", number);
    xslProc.addParameter("startno", (cur_page - 1)*10);
    xslProc.addParameter("endno", cur_page*10);
    xslProc.transform();

    return xslProc.output;
    }

    function delete_node(node){
    if( node.hasChildNodes() ) { 
    var kids = node.childNodes; 
    for(var i=0;i<kids.length;i++) { 
    delete_node(kids);
    }
    }
    node.parentNode.removeChild(node);
    }

    function delete_rule(id){
    var node = xmlDoc.selectSingleNode("/rules/rule[event/id="+id+"]");
    delete_node(node);
    }

    function modify_node(node){
    node.selectSingleNode("event/id").text = modify_id.value;
    node.selectSingleNode("event/name").text = modify_name.value;
    if( modify_state.checked ) {
    node.selectSingleNode("enable").text = "true";
    } else {
    node.selectSingleNode("enable").text = "false";
    }
    }

    function modify_rule(id){
    var node = xmlDoc.selectSingleNode("/rules/rule[event/id="+id+"]");
    modify_node(node);
    }

    function add_rule(){
    var id = xmlDoc.createElement("id");
    id.appendChild(xmlDoc.createTextNode(add_id.value));
    var name = xmlDoc.createElement("name");
    name.appendChild(xmlDoc.createTextNode(add_name.value));

    var event = xmlDoc.createElement("event");
    event.appendChild(id);
    event.appendChild(name);

    var enable = xmlDoc.createElement("enable");
    if( add_state.checked ) {
    enable.appendChild(xmlDoc.createTextNode("true"));
    } else {
    enable.appendChild(xmlDoc.createTextNode("false"));
    }

    var rule = xmlDoc.createElement("rule");
    rule.appendChild(event);
    rule.appendChild(enable);

    var parent = xmlDoc.selectSingleNode("/rules");
    if( parent.hasChildNodes() ) {
    parent.insertBefore(rule, parent.firstChild);
    } else {
    parent.appendChild(rule);
    }
    }

    function gotoPage(pageno){
    if( pageno < 1 ) {
    cur_page = 1;
    } else if( pageno >= total_page ) {
    cur_page = total_page;
    } else {
    cur_page = pageno;
    }
    Transform();
    }

    function saveXML(){
    xmlDoc.save("rule.xml");
    }

    function protectsubmit(val){
    if( val == 1 ) { //add
    if( add_id.value < 10000 || add_name.value == "" ) {
    window.alert("事件號必須是5位整數且事件名不能為空");
    } else if( xmlDoc.selectSingleNode("/rules/rule/event/id[. = " + add_id.value + "]") ) {
    window.alert("事件號" + add_id.value + "已經存在");
    } else {
    add_rule();
    saveXML();
    Transform();
    }
    } else if( val == 2 ) { //modify
    var id = viewTable.rows[getFirstCheckedLine()].cells[2].innerText;
    if( modify_id.value < 10000 || modify_name.value == "" ) {
    window.alert("事件號必須是5位整數且事件名不能為空");
    } else if( id != modify_id.value && xmlDoc.selectSingleNode("/rules/rule/event/id[. = " + modify_id.value + "]") ) {
    window.alert("事件號" + modify_id.value + "已經存在");
    } else {
    if( confirm("確認修改?") ) {
    modify_rule(id);
    saveXML();
    Transform();
    }
    }
    } else if( val == 3 ) { //delete
    if( !confirm("確認刪除?") ) {
    return;
    }
    for( var i = 1; i < viewTable.rows.length; i++ ) {
    var id = viewTable.rows.cells[2].innerText;
    if( eval("viewchk_" + id + ".checked") == true ) {
    delete_rule(id)
    }
    }
    saveXML();
    Transform();
    } else if( val == 4 ) { //select all
    checked_count = viewTable.rows.length - 1;
    for( var i = 1; i < viewTable.rows.length; i++ ) {
    var id = viewTable.rows.cells[2].innerText;
    eval("viewchk_" + id + ".checked = true");
    }
    changeState();
    } else if( val == 5 ) { //cancel all
    checked_count = 0;
    for( var i = 1; i < viewTable.rows.length; i++ ) {
    var id = viewTable.rows.cells[2].innerText;
    eval("viewchk_" + id + ".checked = false");
    }
    changeState();
    }
    }

    function getFirstCheckedLine(){
    for( var i = 1; i < viewTable.rows.length; i++ ) {
    var id = viewTable.rows.cells[2].innerText;
    if( eval("viewchk_" + id + ".checked") == true ) {
    return i;
    }
    }
    return 0;
    }

    function checkOVItem(val){
    if( eval("viewchk_" + val+".checked") == true ) {
    checked_count++;
    } else {
    checked_count--;
    }
    changeState();
    }

    function changeState(){
    if( checked_count ) {
    delete_btn.disabled = false;
    cancel_all_btn.disabled = false;
    } else {
    delete_btn.disabled = true;
    cancel_all_btn.disabled = true;
    }
    if( (checked_count + 1) == viewTable.rows.length ) {
    select_all_btn.disabled = true;
    } else {
    select_all_btn.disabled = false;
    }

    if( checked_count == 1 ) {
    modify_btn.disabled = false;
    modify_id.disabled = false;
    modify_name.disabled = false;
    modify_state.disabled = false;
    var id = getFirstCheckedLine();
    modify_id.value = viewTable.rows(id).cells(2).innerText;
    modify_name.value = viewTable.rows(id).cells(3).innerText;
    if( viewTable.rows(id).cells(1).innerText == "有效" ) {
    modify_state.checked = true;
    } else {
    modify_state.checked = false;
    }
    } else {
    modify_btn.disabled = true;
    modify_id.disabled = true;
    modify_name.disabled = true;
    modify_state.disabled = true;
    modify_id.value="請選擇一條規則";
    modify_name.value="請選擇一條規則";
    }
    }

    function showPageInfo(){
    if( total_item.value == 0 ) {
    total_page = 1;
    } else {
    total_page = Math.floor((9 + parseInt(total_item.value)) / 10);
    }
    var txt = " 共"+total_item.value+"條記錄";
    var prev_page = cur_page - 1;
    var next_page = parseInt(cur_page) + 1;
    if( cur_page > 1 ) {
    txt += " <input type='button' value='<' onClick='gotoPage(" + prev_page + ")'/>"
    } else {
    txt += " <input type='button' value='<' onClick='gotoPage(" + prev_page + ")' disabled/>"
    }
    if( cur_page < total_page ) {
    txt += " <input type='button' value='>' onClick='gotoPage(" + next_page + ")'/>"
    } else {
    txt += " <input type='button' value='>' onClick='gotoPage(" + next_page + ")' disabled/>"
    }

    txt += " 第<input type='text' id='page_number' size='4' maxlength='4' value='" + cur_page + "' onBlur='gotoPage(this.value)'/>頁 共" + total_page + "頁";
    page_info.innerHTML = txt;
    // window.alert(txt);
    }

    function Transform(){
    var txt = document.getElementById("ename").value;
    var str = OutputDocument(txt);
    rule_list.innerHTML = str;
    checked_count = 0;
    showPageInfo();
    changeState();
    // window.alert(str);
    }
    </script>

    <BODY onLoad="Transform()">

    <table width="550" border="1" cellpadding="0" cellspacing="0" style="border-collapse:collapse;">
    <tr>
    <td>
    <table width="100%" border="0" cellpadding="0" cellspacing="0" style="border-collapse:collapse;">
    <TR height=5><td colspan=10 style="font-size:0px;"></td></TR>
    <TR height=25>
    <td colspan=3 align=center>事件名包含:</td>
    <td colspan=3 align=center><input type="text" value="" id="ename" size="35" maxlength="16"/></td>
    <td colspan=4><input type="button" value="搜索" onClick="Transform()"/></td>
    </TR>
    <TR height=1><td colspan=10 bgcolor=#2b7297></td></TR>
    <TR height=30>
    <td width=45 align=center><b>添加</b></td>
    <td width=5 align=center><font color=gray>|</font></td>
    <td width=50 align=center>事件號</td>
    <td width=55 align=center><input type="text" name="add_id" value="" size="5" maxlength="5" onkeyup="this.value=this.value.replace(/\D/g,'')" onafterpaste="this.value=this.value.replace(/\D/g,'')"></td>
    <td width=55 align=center>事件名</td>
    <td width=* align=center><input type="text" name="add_name" maxlength="48" value=""></td>
    <td width=70 align=center>是否使用</td>
    <td width=30 align=center>
    <input type='checkbox' name='add_state' checked>
    </td> 
    <td width=5 align=center><font color=gray>|</font></td>
    <td width=70 align=center><input type="button" name="add_btn" value="確定" onClick="protectsubmit(1)"></td>
    </TR>
    <TR height=1><td colspan=10 bgcolor=#2b7297></td></TR>
    <TR height=30>
    <td width=45 align=center><b>修改</b></td>
    <td width=5 align=center><font color=gray>|</font></td>
    <td width=50 align=center>事件號</td>
    <td width=55 align=center>
    <input type="text" name="modify_id" value="<請選擇一條規則>" size="5" maxlength="5" onkeyup="this.value=this.value.replace(/\D/g,'')" onafterpaste="this.value=this.value.replace(/\D/g,'')" disabled></td>
    <td width=55 align=center>事件名</td>
    <td width=* align=center>
    <input type="text" name="modify_name" maxlength="48" value="<請選擇一條規則>" disabled></td>
    <td width=70 align=center>是否使用</td>
    <td width=30 align=center>
    <input type='checkbox' name='modify_state' disabled>
    </td> 
    <td width=5 align=center><font color=gray>|</font></td>
    <td width=70 align=center><input type="button" name="modify_btn" value="確定" onClick="protectsubmit(2)"></td>
    </TR>
    <TR height=1><td colspan=10 bgcolor=#2b7297></td></TR>
    <TR height=30>
    <td colspan=5 align=left class=tablefont></td>
    <td align=right><input type="button" name="select_all_btn" value="全部選擇" onClick="protectsubmit(4)"></td>
    <td colspan=2 align=right><input type="button" name="cancel_all_btn" value="全部不選" onClick="protectsubmit(5)" disabled></td>
    <td align=center></td>
    <td align=center><input type="button" name="delete_btn" value="刪除" onClick="protectsubmit(3)" disabled></td>
    </TR>
    <TR height=30><td colspan=4>規則列表</td><TD colspan=6 align=right><div id="page_info" name="page_info"/></TR>
    <TR>
    <TD colspan=10><div id="rule_list" name="rule_list"/></TD>
    </TR>
    <TR height=5><td colspan=10></td></TR>
    </table>
    </td>
    </tr>
    <tr>
    </tr>
    </table>

    </BODY>
    </HTML>


    rule.xml
    ============
    <?xml version="1.0" encoding="GB2312"?>
    <?xml:stylesheet type="text/xsl" href="rule.xsl"?>
    <rules>
    <rule>
    <event>
    <id>10001</id>
    <name>TFTP下載文件</name>
    </event>
    <enable>false</enable>
    </rule>
    <rule>
    <event>
    <id>10002</id>
    <name>TFTP上傳文件</name>
    </event>
    <enable>false</enable>
    </rule>
    <rule>
    <event>
    <id>10003</id>
    <name>telnet登錄成功</name>
    </event>
    <enable>false</enable>
    </rule>

    </rules>

    rule.xsl
    =============
    <?xml version="1.0" encoding="GB2312"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:output method= "html"/>
    <xsl:param name="ename">undefined</xsl:param>
    <xsl:param name="startno">undefined</xsl:param>
    <xsl:param name="endno">undefined</xsl:param>

    <xsl:template match="/">
    <html>
    <body>
    <xsl:apply-templates select="rules"/>
    </body>
    </html>
    </xsl:template>

    <xsl:template match="rules">
    <input type="hidden" name="total_item">
    <xsl:attribute name="value"><xsl:value-of select="count(rule[contains(event/name, $ename)])"/></xsl:attribute>
    </input>
    <TABLE id="viewTable" name="viewTable" width="100%" border="1" bordercolor="#85979f" cellSpacing="0" cellPadding="0" style="border-collapse:collapse;">
    <tr height="25">
    <TD width="10%" align="center">選擇</TD>
    <TD width="10%" align="center">狀態</TD>
    <TD width="10%" align="center">事件號</TD>
    <TD width="*" align="center">事件名</TD>
    </tr>

    <xsl:for-each select='rule[contains(event/name, $ename)]'>
    <xsl:sort select="event/id"/>
    <xsl:if test="position()> $startno and position()<= $endno">
    <tr>
    <td align="center">
    <input type='checkbox'>
    <xsl:attribute name="name">viewchk_<xsl:value-of select="event/id"/></xsl:attribute>
    <xsl:attribute name="value"><xsl:value-of select="event/id"/></xsl:attribute>
    <xsl:attribute name="onClick">checkOVItem(<xsl:value-of select="event/id"/>)</xsl:attribute>
    </input>
    </td>
    <xsl:choose>
    <xsl:when test="enable[. = 'true']">
    <td align="center">有效</td>
    </xsl:when>
    <xsl:otherwise>
    <td align="center">禁用</td>
    </xsl:otherwise>
    </xsl:choose>
    <td align="center"><xsl:value-of select="event/id"/></td>
    <td><xsl:value-of select="event/name"/></td>
    </tr>
    </xsl:if>
    </xsl:for-each>
    </TABLE>
    </xsl:template>

    </xsl:stylesheet>

    posted @ 2007-12-29 15:44 feingto 閱讀(360) | 評論 (0)編輯 收藏

    prototype.js 1.4版開發者手冊(強烈推薦)

         摘要: .reference table{border:1px dashed darkblue;} .reference th{border:1px dashed darkblue;color:white;background-color:darkblue;} .reference td{border:1px dashed darkblue;corlor:black;background-color:w...  閱讀全文

    posted @ 2007-12-29 14:59 feingto 閱讀(337) | 評論 (0)編輯 收藏

    showModalDialog/showModelessDialog實例,父窗口向子窗口傳遞值,子窗口設置父窗口的值,子窗口關閉的時候返回值到父窗口.關閉刷新父窗口

    下面是showModalDialog/showModelessDialog使用例子,父窗口向子窗口傳遞值,子窗口設置父窗口的值,子窗口關閉的時候返回值到父窗口.關閉刷新父窗口,希望對象我這樣的WEB開發的菜鳥有所幫助.

    (一)showModalDialog使用例子,父窗口向子窗口傳遞值,子窗口設置父窗口的值,子窗口關閉的時候返回值到父窗口.


    farther.html
    ---------------------------
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE> New Document </TITLE>
    <META NAME="Generator" CONTENT="EditPlus">
    <META NAME="Author" CONTENT="">
    <META NAME="Keywords" CONTENT="">
    <META NAME="Description" CONTENT="">
    <script language="javascript">
    <!--
    function openChild(){

    var k = window.showModalDialog("child.html",window,"dialogWidth:335px;status:no;dialogHeight:300px");
    if(k != null)
    document.getElementById("txt11").value = k;
    }
    //-->
    </script>
    </HEAD>

    <BODY>
    <br>傳遞到父窗口的值:<input id="txt9" type="text" value="3333333333333"><br>
    返回的值:<input id="txt11" type="text"><br>
    子窗口設置的值:<input id="txt10" type="text"><br>


    <input type ="button" value="openChild" onclick="openChild()">
    </BODY>
    </HTML>
    ---------------------------------------------------------------
    child.html
    --------
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE> New Document </TITLE>
    <META NAME="Generator" CONTENT="EditPlus">
    <META NAME="Author" CONTENT="">
    <META NAME="Keywords" CONTENT="">
    <META NAME="Description" CONTENT="">
    <meta http-equiv="Expires" CONTENT="0">
    <meta http-equiv="Cache-Control" CONTENT="no-cache">
    <meta http-equiv="Pragma" CONTENT="no-cache">

    </HEAD>

    <BODY>
    <br>父窗口傳遞來的值:<input id="txt0" type="text"><br>
    輸入要設置父窗口的值:<input id="txt1" type="text"><input type ="button" value="設置父窗口的值" onclick="setFather()"><br>
    輸入返回的值:<input id="txt2" type="text"><input type ="button" value="關閉切返回值" onclick="retrunValue()">
    <input type ="button" value="關閉刷新父窗口" onclick="">

    </BODY>
    </HTML>

    <script language=javascript>
    <!--
    var k=window.dialogArguments;
    //獲得父窗口傳遞來的值
    if(k!=null)
     {
     document.getElementById("txt0").value = k.document.getElementById("txt9").value;
     }
     //設置父窗口的值
    function setFather()
    {
     k.document.getElementById("txt10").value = document.getElementById("txt1").value
    }
    //設置返回到父窗口的值
    function retrunValue()
    {
    var s = document.getElementById("txt2").value;
    window.returnValue=s;
    window.close();
    }
    //-->
    </script>

    ----------------------------
    說明:
    由于showModalDialog緩存嚴重,下面是在子窗口取消客戶端緩存的設置.也可以在服務器端取消緩存,參考:
    http://adandelion.cnblogs.com/articles/252137.html
    <meta http-equiv="Expires" CONTENT="0">
    <meta http-equiv="Cache-Control" CONTENT="no-cache">
    <meta http-equiv="Pragma" CONTENT="no-cache">
    ------------------------------------------------------------------------------------------------------------------------
    (二)下面是關閉刷新父窗口的例

    farther.html
    ---------------------------
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE> New Document </TITLE>
    <META NAME="Generator" CONTENT="EditPlus">
    <META NAME="Author" CONTENT="">
    <META NAME="Keywords" CONTENT="">
    <META NAME="Description" CONTENT="">
    <script language="javascript">
    <!--
    function openChild()
    {

     var k = window.showModalDialog("child.html",window,"dialogWidth:335px;status:no;dialogHeight:300px");
     if(k == 1)//判斷是否刷新
     {
      alert('刷新');
      window.location.reload();
     }
    }
    //-->
    </script>
    </HEAD>

    <BODY>
    <br>傳遞到父窗口的值:<input id="txt9" type="text" value="3333333333333"><br>
    <input type ="button" value="openChild" onclick="openChild()">
    </BODY>
    </HTML>
    ----------------------------------------------------
    child.html
    --------
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <HTML>
    <HEAD>
    <TITLE> New Document </TITLE>
    <META NAME="Generator" CONTENT="EditPlus">
    <META NAME="Author" CONTENT="">
    <META NAME="Keywords" CONTENT="">
    <META NAME="Description" CONTENT="">
    <meta http-equiv="Expires" CONTENT="0">
    <meta http-equiv="Cache-Control" CONTENT="no-cache">
    <meta http-equiv="Pragma" CONTENT="no-cache">

    </HEAD>

    <BODY>
    <br>父窗口傳遞來的值:<input id="txt0" type="text"><br>

    <input type ="button" value="關閉刷新父窗口" onclick="winClose(1)">
    <input type ="button" value="關閉不刷新父窗口" onclick="winClose(0)">

    </BODY>
    </HTML>

    <script language=javascript>
    <!--
    var k=window.dialogArguments;
    //獲得父窗口傳遞來的值
    if(k!=null)
     {
     document.getElementById("txt0").value = k.document.getElementById("txt9").value;
     }

    //關閉窗口返回是否刷新的參數.
    function winClose(isRefrash)
    {

    window.returnValue=isRefrash;
    window.close();
    }
    //-->
    </script>

    --------------------------
    說明
    1.下面是取消客戶端緩存的:
    <meta http-equiv="Expires" CONTENT="0">
    <meta http-equiv="Cache-Control" CONTENT="no-cache">
    <meta http-equiv="Pragma" CONTENT="no-cache">
    也可以在服務器端取消緩存,參考:
    http://adandelion.cnblogs.com/articles/252137.html

    2.向父窗口傳遞闡述在ASP.NET中也可以是用aaa.aspx?id=1的方式傳遞.

    3.不刷新父窗口的話在父窗口中直接這樣一來設置可以.
    <script>
    window.showModalDialog("child.html",window,"dialogWidth:335px;status:no;dialogHeight:300px");
    </script>
    4.在子窗口中若要提交頁面的話要加入:,這樣就不會打開新窗口了.
    <head>
    <base target="_self">
    </HEAD>

    本文參考了:http://dev.csdn.net/develop/article/15/15113.shtm ,里面有showModalDialog/showModelessDialog的詳細使用說明

    posted @ 2007-12-29 14:33 feingto 閱讀(1400) | 評論 (0)編輯 收藏

    制作Javascript彈出窗口技巧九則

            經常上網的朋友可能會到過這樣一些網站,一進入首頁立刻會彈出一個窗口,或者按一個連接或按鈕彈出,通常在這個窗口里會顯示一些注意事項、版權信 息、警告、歡迎光顧之類的話或者作者想要特別提示的信息。其實制作這樣的頁面效果非常的容易,只要往該頁面的HTML里加入幾段Javascript代碼 即可實現。下面俺就帶您剖析它的奧秘。

      1、最基本的彈出窗口代碼
      其實代碼非常簡單:
      < SCRIPT LANGUAGE="javascript">
      < !--
      window.open ("page.html")
      -->
      < /SCRIPT>
      因為這是一段Javascript代碼,所以它們應該放在< SCRIPT LANGUAGE="javascript">之間。 < !-- 和 -->是對一些版本低的瀏覽器起作用,在這些老瀏覽器中不會將標簽中的代碼作為文本顯示出來。要養成這個好習慣啊。
      window.open ("page.html") 用于控制彈出新的窗口page.html,如果page.html不與主窗口在同一路徑下,前面應寫明路徑,絕對路徑(http://)和相對路徑(../)均可。
      用單引號和雙引號都可以,只是不要混用。
      這一段代碼可以加入HTML的任意位置,< head>和< /head>之間可以,< body>間< /body>也可以,越前越早執行,尤其是頁面代碼長,又想使頁面早點彈出就盡量往前放。 也可以,越前越早執行,尤其是頁面代碼長,又想使頁面早點彈出就盡量往前放。

      2、經過設置后的彈出窗口
      下面再說一說彈出窗口的設置。只要再往上面的代碼中加一點東西就可以了。我們來定制這個彈出的窗口的外觀,尺寸大小,彈出的位置以適應該頁面的具體情況。
      < SCRIPT LANGUAGE="javascript">
      < !--
      window.open ("page.html", "newwindow", "height=100, width=400, top=0, left=0, toolbar=no, menubar=no, scrollbars=no, resizable=no,location=no, status=no")
      //寫成一行
      -->
      < /SCRIPT>
      參數解釋:
      < SCRIPT LANGUAGE="javascript"> js腳本開始;
      window.open 彈出新窗口的命令;
      "page.html" 彈出窗口的文件名;
      "newwindow" 彈出窗口的名字(不是文件名),非必須,可用空"代替;
      height=100 窗口高度;
      width=400 窗口寬度;
      top=0 窗口距離屏幕上方的象素值;
      left=0 窗口距離屏幕左側的象素值;
      toolbar=no 是否顯示工具欄,yes為顯示;
      menubar,scrollbars 表示菜單欄和滾動欄。
      resizable=no 是否允許改變窗口大小,yes為允許;
      location=no 是否顯示地址欄,yes為允許;
      status=no 是否顯示狀態欄內的信息(通常是文件已經打開),yes為允許;
      < /SCRIPT> js腳本結束

      3、用函數控制彈出窗口
      下面是一個完整的代碼:
      < html>
      < head>
      < script LANGUAGE="JavaScript">
      < !--
      function openwin() {
      window.open ("page.html", "newwindow", "height=100, width=400, toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no")
      //寫成一行
      }
      //-->
      < /script>
      < /head>
      < body onload="openwin()">
      ...任意的頁面內容...
      < /body>
      < /html>
      這里定義了一個函數openwin(),函數內容就是打開一個窗口。在調用它之前沒有任何用途。
      怎么調用呢?
      方法一:< body onload="openwin()"> 瀏覽器讀頁面時彈出窗口;
      方法二:< body onunload="openwin()"> 瀏覽器離開頁面時彈出窗口;
      方法三:用一個連接調用:< a href="#" onclick="openwin()">打開一個窗口< /a>
      注意:使用的"#"是虛連接。
      方法四:用一個按鈕調用:< input type="button" onclick="openwin()" value="打開窗口">

      4、同時彈出2個窗口
      對源代碼稍微改動一下:
      < script LANGUAGE="JavaScript">
      < !--
      function openwin() {
      window.open ("page.html", "newwindow", "height=100, width=100, top=0, left=0,toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no")
      //寫成一行
      window.open ("page2.html", "newwindow2", "height=100, width=100, top=100, left=100,toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, status=no")
      //寫成一行
      }
      //-->
      < /script>
      為避免彈出的2個窗口覆蓋,用top和left控制一下彈出的位置不要相互覆蓋即可。最后用上面說過的四種方法調用即可。
      注意:2個窗口的name(newwindows和newwindow2)不要相同,或者干脆全部為空。OK?

      5、主窗口打開文件1.htm,同時彈出小窗口page.html
      如下代碼加入主窗口< head>區:
      < script language="javascript">
      < !--
      function openwin() {
      window.open("page.html","","width=200,height=200")
      }
      //-->
      < /script>
      加入< body>區:
      < a href="1.htm" onclick="openwin()">open< /a>即可

      6、彈出的窗口之定時關閉控制
      下面我們再對彈出的窗口進行一些控制,效果就更好了。如果我們再將一小段代碼加入彈出的頁面(注意是加入到page.html的HTML中,可不是主頁面中,否則...),讓它10秒后自動關閉是不是更酷了?
      首先,將如下代碼加入page.html文件的< head>區:
      < script language="JavaScript">
      function closeit() {
      setTimeout("self.close()",10000) //毫秒
      }
      < /script>
      然后,再用< body onload="closeit()"> 這一句話代替page.html中原有的< BODY>這一句就可以了。(這一句話千萬不要忘記寫啊!這一句的作用是調用關閉窗口的代碼,10秒鐘后就自行關閉該窗口。)

      7、在彈出窗口中加上一個關閉按鈕
      < FORM>
      < INPUT TYPE="BUTTON" VALUE="關閉" onClick="window.close()">
      < /FORM>
      呵呵,現在更加完美了!

      8、內包含的彈出窗口---一個頁面兩個窗口
      上面的例子都包含兩個窗口,一個是主窗口,另一個是彈出的小窗口。通過下面的例子,你可以在一個頁面內完成上面的效果。
      < html>
      < head>
      < SCRIPT LANGUAGE="JavaScript">
      function openwin()
      {
      OpenWindow=window.open("", "newwin", "height=250, width=250,toolbar=no,scrollbars="+scroll+",menubar=no");
      //寫成一行
      OpenWindow.document.write("< TITLE>例子< /TITLE>")
      OpenWindow.document.write("< BODY BGCOLOR=#ffffff>")
      OpenWindow.document.write("< h1>Hello!< /h1>")
      OpenWindow.document.write("New window opened!")
      OpenWindow.document.write("< /BODY>")
      OpenWindow.document.write("< /HTML>")
      OpenWindow.document.close()
      }
      < /SCRIPT>
      < /head>
      < body>
      < a href="#" onclick="openwin()">打開一個窗口< /a>
      < input type="button" onclick="openwin()" value="打開窗口">
      < /body>
      < /html>
      看看OpenWindow.document.write()里面的代碼不就是標準的HTML嗎?只要按照格式寫更多的行即可。千萬注意多一個標簽或少一個標簽就會出現錯誤。記得用OpenWindow.document.close()結束啊。

      9、終極應用--彈出的窗口之Cookie控制
      回想一下,上面的彈出窗口雖然酷,但是有一點小毛病(沉浸在喜悅之中,一定沒有發現吧?)比如你將上面的腳本放在一個需要頻繁經過的頁面里(例如首頁),那么每次刷新這個頁面,窗口都會彈出一次,是不是非常煩人?:-(
      有解決的辦法嗎?當然有!我們使用cookie來控制一下就可以了。首先,將如下代碼加入主頁面HTML的< HEAD>區:
      < script>
      function openwin(){
      window.open("page.html","","width=200,height=200")
      }
      function get_cookie(Name) {
      var search = Name + "=" var returnvalue = "";
      if (document.cookie.length > 0) {
      offset = document.cookie.indexOf(search)
      if (offset != -1) {
      offset += search.length
      end = document.cookie.indexOf(";", offset);
      if (end == -1)
      end = document.cookie.length;
      returnvalue=unescape(document.cookie.substring(offset, end))
      }
      }
      return returnvalue;
      }
      function loadpopup(){
      if (get_cookie("popped")=="){
      openwin()
      document.cookie="popped=yes"
      }
      }
      < /script>
      然后,用< body onload="loadpopup()">(注意不是openwin而是loadpop啊!)替換主頁面中原有的< BODY>這一句即可。你可以試著刷新一下這個頁面或重新進入該頁面,窗口再也不會彈出了。真正的Pop-Only-Once!
      寫到這里彈出窗口的制作和應用技巧基本上算是完成了,俺也累壞了,一口氣說了這么多,希望對正在制作網頁的朋友有所幫助俺就非常欣慰了。
      需要注意的是,JS腳本中的的大小寫最好前后保持一致。 

    posted @ 2007-12-29 14:24 feingto 閱讀(305) | 評論 (0)編輯 收藏

    jsp中的時間操作

    jsp中的時間操作

    經常看見jsp版里有人問時間操作的問題,這些問題一般包括:取當前時間,把一個指定的字符串時間轉化成時間類型,求兩個時間之間的天數,求一段時間以前的時間,求一段時間以后的時間,在這里就把這些問題匯總一下。
    <%@  page  contentType="text/html;charset=gb2312"%>
    <%@ page import="java.text.*"%>
    <%@ page import="java.util.*"%>
    <%
    //字符串轉化成時間類型(字符串可以是任意類型,只要和SimpleDateFormat中的格式一致即可)
    java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("M/dd/yyyy hh:mm:ss a",java.util.Locale.US);
    java.util.Date d = sdf.parse("5/13/2003 10:31:37 AM"); 
    out.println(d);
    out.println("<br>");
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String mDateTime1=formatter.format(d);
    out.println(mDateTime1);
    out.println("<br>");
    out.println(d.getTime());
    out.println("<br>");
    //當前時間
    Calendar cal  = Calendar.getInstance();
    //  SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss G E D F w W a E F");
    String mDateTime=formatter.format(cal.getTime());
    out.println(mDateTime);
    out.println("<br>");
    //1年前日期
    java.util.Date myDate=new java.util.Date(); 
    long myTime=(myDate.getTime()/1000)-60*60*24*365;
    myDate.setTime(myTime*1000);
    String mDate=formatter.format(myDate);
    out.println(mDate);
    out.println("<br>");
    //明天日期
    myDate=new java.util.Date();
    myTime=(myDate.getTime()/1000)+60*60*24;
    myDate.setTime(myTime*1000);
    mDate=formatter.format(myDate);
    out.println(mDate);
    out.println("<br>");
    //兩個時間之間的天數
    SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM-dd");
    java.util.Date date= myFormatter.parse("2003-05-1");
    java.util.Date mydate= myFormatter.parse("1899-12-30");
    long  day=(date.getTime()-mydate.getTime())/(24*60*60*1000);
    out.println(day);
    out.println("<br>");
    //加半小時
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
    java.util.Date date1 = format.parse("2002-02-28 23:16:00");
    long Time=(date1.getTime()/1000)+60*30;
    date1.setTime(Time*1000);
    String mydate1=formatter.format(date1);
    out.println(mydate1);
    out.println("<br>");
    //年月周求日期
    SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM F E");
    java.util.Date date2= formatter2.parse("2003-05 5 星期五");
    SimpleDateFormat formatter3 = new SimpleDateFormat("yyyy-MM-dd");
    String mydate2=formatter3.format(date2);
    out.println(mydate2);
    out.println("<br>");
    //求是星期幾
    mydate= myFormatter.parse("2001-1-1");
    SimpleDateFormat formatter4 = new SimpleDateFormat("E");
    String mydate3=formatter4.format(mydate);
    out.println(mydate3);
    out.println("<br>");
    %>

    posted @ 2006-05-10 10:41 feingto 閱讀(674) | 評論 (1)編輯 收藏

    hibernate的中文問題的解決方案

    系統配置:win2k3 server,jsdk 1.5.0 rc,mysql 4.0.20a,hibernate 2.1.0 ,elcipse 3.0.1
    問題描述:在使用hibernate作為數據持久層的方案時,照樣會遇到中文問題,具體情況時插入到數據庫中的漢字顯示為??,顯示數據時漢字為??
    探索: 經過試驗發現與漢字編碼有關的地方有以下兩處,一個是數據庫連接url ,一個是編程時獲取Configuration 類的實例的語句的方式。
    方案1:
    ??? * 編程時獲取Configuration 類的實例的語句為
    ??? * new Configuration().addClass(xx.class);
    ??? 必須在hibernate.properties文件里數據庫連接url后加上?characterEncoding=gbk&useUnicode=true
    方案2:
    ??? * 編程時獲取Configuration 類的實例的語句為
    ??? * new Configuration().configure().
    ??? 在hibernate.cfg.xml文件的<session-factory/>塊中設置
    ??????? <property name="connection.useUnicode">true</property>
    ??????? <property name="connection.characterEncoding">UTF-8</property>
    ??? 或編程時寫:
    ????? Properties extraProperties = new Properties();
    ????? extraProperties.put("hibernate.connection.useUnicode", "true");
    ????? extraProperties.put("hibernate.connection.characterEncoding", "UTF-8");
    ????? myConfiguration.addProperties(extraProperties);

    原來懷疑與xml頁面的編碼有關試了一下,好像不起作用。

    posted @ 2006-05-08 14:42 feingto 閱讀(458) | 評論 (2)編輯 收藏

    在Struts框架內實現圖片上傳 (轉載:http://www.tkk7.com/Todayfreeman/)

    這個問題讓我郁悶了兩三天時間,最后才發現問題是在JSP端? <html:form action="/uploadsAction"? enctype="multipart/form-data"? >
    標簽如果少了"? enctype="multipart/form-data" ?服務器就會報錯,
    下面把代碼貼出來.

    JSP端
    ?<html:errors />
    ????????? <html:form action="/uploadsAction"? enctype="multipart/form-data"? >
    ??????????? <html:file property="theFile" />?
    ???????????? <html:radio property="upType" value="a" />CSVFileReader
    ???????????? <html:radio property="upType" value="b" />FileUp??????
    ??????????? <html:submit value="OK"? />
    ????????? </html:form>
    FormBean中將屬性定義為FormFile,geter seter 方法依舊.
    Action 中的代碼如下:實現將圖片上傳至UPLOAD文件夾內 如果文件大于20K或是寬&高超過規定范圍的,會重新勾畫.實現對上傳圖片的控制.
    當然這只是測試Action沒有跳轉頁面..

    package upload;

    import org.apache.struts.action.ActionMapping;
    import org.apache.struts.action.ActionForm;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.struts.action.ActionForward;
    import org.apache.struts.action.Action;
    import org.apache.struts.upload.*;
    import java.io.IOException;
    import java.awt.Image;
    import java.awt.image.BufferedImage;
    import com.sun.image.codec.jpeg.JPEGImageEncoder;
    import com.sun.image.codec.jpeg.JPEGCodec;

    import java.io.File;
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.FileOutputStream;

    public class UploadAction extends Action {
    ??? public ActionForward execute(ActionMapping actionMapping,
    ???????????????????????????????? ActionForm actionForm,
    ???????????????????????????????? HttpServletRequest servletRequest,
    ???????????????????????????????? HttpServletResponse servletResponse)throws Exception {
    ??????? System.out.println("asdasdasdasdasdasd");
    ??????? UploadForm uploadForm = (UploadForm) actionForm;
    ??????? FormFile pic =? uploadForm.getPic();
    ??????? String picname = pic.getFileName();
    ??????? String uploadFileName = servletRequest.getSession()
    ??????????????????????????????? .getServletContext()
    ??????????????????????????????? .getRealPath("upload")+"\\"+picname;
    ??????? File upliadFile = new File(uploadFileName);
    ??????? BufferedInputStream bis = null;
    ??????? Image image = null;
    ??????? BufferedOutputStream bos = null;
    ??????? try{
    ??????? if(pic.getFileSize()<2*1024*1024){
    ??????? bis = new BufferedInputStream(pic.getInputStream());
    ??????? image = javax.imageio.ImageIO.read(bis);
    ??????? int width = image.getWidth(null);
    ??????? int height = image.getHeight(null);
    ??????? int w = 160;
    ??????? int h = 120;
    ??????? if(width>w||height>h){
    ??????? BufferedImage bi = new BufferedImage(w,h,
    ???????????????????????????????????????????? BufferedImage.TYPE_INT_RGB);
    ??????? bi.getGraphics().drawImage(image,0,0,w,h,null);
    ??????? bos = new BufferedOutputStream(new FileOutputStream(
    ???????upliadFile));
    ??????? JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);
    ?????encoder.encode(bi);
    ??????? System.out.println(width * height);
    ??????? }else{
    ??????? bos = new BufferedOutputStream(new FileOutputStream(upliadFile));
    ??????? byte[] date = new byte[5*1024];
    ??????? int len = bis.read(date);
    ??????? while (len!=-1){
    ??????????? bos.write(date);
    ??????????? len = bis.read(date);
    ??????? }
    ??????? }
    ??????? }
    ???????????? return actionMapping.findForward("ok");
    ??????? }catch(Exception e){
    ??????? e.printStackTrace();
    ??? } finally {
    ??????? try {
    ??????????? if (bis != null)
    ??????????????? bis.close();
    ??????? } catch (IOException e1) {

    ??????????? e1.printStackTrace();
    ??????? }
    ??????? try {
    ??????????? if (bos != null)
    ??????????????? bos.close();
    ??????? } catch (IOException e2) {

    ??????????? e2.printStackTrace();
    ??????? }
    ??? }

    ??????? return actionMapping.findForward("ok");
    ??? }
    }

    posted @ 2006-05-03 20:09 feingto 閱讀(968) | 評論 (0)編輯 收藏

    Struts1.2中配置數據源

    軟件環境:Tomcat5.5.15,Eclipse3.1.2,MyEclipse4.1,MySQL5.0.15,Resin3.0.18

    配置過程:

    一、下載必要的jar包。有四個包要下載(網上有貼子說只要下面前三個包就可以了,但我在配置的時候如果沒有第四個包會報錯)。
    http://apache.linuxforum.net/dist/jakarta/commons/dbcp/binaries/commons-dbcp-1.2.zip
    http://apache.linuxforum.net/dist/jakarta/commons/pool/binaries/commons-pool-1.2.zip
    http://apache.linuxforum.net/dist/jakarta/struts/struts-legacy/struts-legacy-1.0.zip
    http://apache.linuxforum.net/dist/jakarta/commons/collections/binaries/commons-collections-3.1.zip
    把這四個jar包放到web應用的WEB-INF/lib目錄下,還有要把MySQL的驅動程序包也放到這里(也可以把數據庫的驅動包放到%Tomcat_Home%/common/lib目錄下或%Resin_Home%/lib目錄下,這樣在啟動Web服務器的時候就會加載這個包,服務器和Web應用都可以使用驅動程序類)

    二、在struts-config.xml中添加Data Source。MyEclipse的Design模式下可以可視化地編輯struts-config.xml和添加Data Source,但它在struts-config.xml中生成的數據源的代碼是錯誤的!就是因為這個耽誤了我很多時間!
    我們手工編輯代碼:

      <data-sources>
        <data-source key="datasource" type="org.apache.commons.dbcp.BasicDataSource">
          <set-property property="password" value="admin" />
          <set-property property="minCount" value="3" />
          <set-property property="maxCount" value="10" />
          <set-property property="username" value="admin" />
          <set-property property="driverClassName" value="com.mysql.jdbc.Driver" />
          <set-property property="description" value="test" />
          <set-property property="url" value="jdbc:mysql://localhost/test" />
          <set-property property="readOnly" value="false" />
          <set-property property="autoCommit" value="true" />
        </data-source>
      </data-sources>

    如果要配置多個data source,可以給每個data source指定不同的key,然后在程序中根據key指定要引用的數據源。

    三、測試數據源。配置好以后就可以在ActionServlet中使用了。

      DataSource ds = getDataSource(request,"datasource");
      Connection conn = ds.getConnection();
      Statement stmt = conn.createStatement();
      ResultSet rs = stmt.executeQuery("SQL String");

    附: Struts1.1中struts-config.xml的配置:

      <data-sources >
        <data-source key="datasource" type="org.apache.struts.util.GenericDataSource">
          <set-property property="password" value="admin" />
          <set-property property="minCount" value="2" />
          <set-property property="maxCount" value="10" />
          <set-property property="user" value="admin" />
          <set-property property="driverClass" value="com.mysql.jdbc.Driver" />
          <set-property property="description" value="test" />
          <set-property property="url" value="jdbc:mysql://localhost/test" />
          <set-property property="readOnly" value="false" />
          <set-property property="autoCommit" value="true" />
        </data-source>
      </data-sources>

    注意:藍色字體的部分是1.1和1.2在配置上不一樣的地方。

    posted @ 2006-05-03 20:05 feingto 閱讀(1903) | 評論 (1)編輯 收藏

    Struts+Hibernate開發實踐 分頁的實現

    在進行web應用開發的時候經常要進行分頁處理,經常看到一些人在問分頁處理的問題,現在我把自己的處理方法寫在這兒,希望能對需要進行分頁處理的朋友有所幫助。

    一、在struts中分頁有兩種結構:
    ??? 1. 在Action中通過DAO查詢出所有的記錄,然后加到session或request對象中,傳到客戶端,由JSP進行分頁。這種方法對于在數據量少的時候很方便,也不影響速度。
    ??? 2.在Action中每次通過DAO只查詢出一頁的記錄,再傳給JSP頁面。這種結構對于數據量大的程序很好,但對于數據量小的情況,會增加對服務器的請求,加大服務器的負載。
    ?????
    二、Hibernate查詢
    ??? 由于在Hibernate中直接提供了對數據庫定點定量的查詢方法,所以我采用的是第2種方法。

    如:
    從第1萬條開始取出100條記錄
    Query q = session.createQuery("from Cat as c");
    q.setFirstResult(10000);
    q.setMaxResults(100);
    List l = q.list();

    三、具體實現

    ?1.Pager類

    package com.jpcf.db.helper;

    import java.math.*;

    public class Pager {
    ? private int totalRows; //總行數
    ? private int pageSize = 10; //每頁顯示的行數
    ? private int currentPage; //當前頁號
    ? private int totalPages; //總頁數
    ? private int startRow; //當前頁在數據庫中的起始行

    ? public Pager() {
    ? }

    ? public Pager(int _totalRows) {
    ??? totalRows = _totalRows;
    ??? totalPages=totalRows/pageSize;
    ??? int mod=totalRows%pageSize;
    ??? if(mod>0){
    ????? totalPages++;
    ??? }
    ??? currentPage = 1;
    ??? startRow = 0;
    ? }

    ? public int getStartRow() {
    ??? return startRow;
    ? }

    ? public int getTotalPages() {
    ??? return totalPages;
    ? }

    ? public int getCurrentPage() {
    ??? return currentPage;
    ? }

    ? public int getPageSize() {
    ??? return pageSize;
    ? }

    ? public void setTotalRows(int totalRows) {
    ??? this.totalRows = totalRows;
    ? }

    ? public void setStartRow(int startRow) {
    ??? this.startRow = startRow;
    ? }

    ? public void setTotalPages(int totalPages) {
    ??? this.totalPages = totalPages;
    ? }

    ? public void setCurrentPage(int currentPage) {
    ??? this.currentPage = currentPage;
    ? }

    ? public void setPageSize(int pageSize) {
    ??? this.pageSize = pageSize;
    ? }

    ? public int getTotalRows() {
    ??? return totalRows;
    ? }

    ? public void first() {
    ??? currentPage = 1;
    ??? startRow = 0;
    ? }

    ? public void previous() {
    ??? if (currentPage == 1) {
    ????? return;
    ??? }
    ??? currentPage--;
    ??? startRow = (currentPage - 1) * pageSize;
    ? }

    ? public void next() {
    ??? if (currentPage < totalPages) {
    ????? currentPage++;
    ??? }
    ??? startRow = (currentPage - 1) * pageSize;
    ? }

    ? public void last() {
    ??? currentPage = totalPages;
    ??? startRow = (currentPage - 1) * pageSize;
    ? }

    ? public void refresh(int _currentPage) {
    ??? currentPage = _currentPage;
    ??? if (currentPage > totalPages) {
    ????? last();
    ??? }
    ? }

    }

    Pager類用于計算首頁、前一頁、下一頁、尾頁的在數據庫中的起始行,當前的頁碼。

    2.PagerHelp類

    package com.jpcf.db.helper;

    import javax.servlet.http.*;

    public class PagerHelper {

    ? public static Pager getPager(HttpServletRequest httpServletRequest,int totalRows) {

    ??? //定義pager對象,用于傳到頁面
    ??? Pager pager = new Pager(totalRows);

    ??? //從Request對象中獲取當前頁號
    ??? String currentPage = httpServletRequest.getParameter("currentPage");

    ??? //如果當前頁號為空,表示為首次查詢該頁
    ??? //如果不為空,則刷新pager對象,輸入當前頁號等信息
    ??? if (currentPage != null) {
    ????? pager.refresh(Integer.parseInt(currentPage));
    ??? }

    ??? //獲取當前執行的方法,首頁,前一頁,后一頁,尾頁。
    ??? String pagerMethod = httpServletRequest.getParameter("pageMethod");

    ??? if (pagerMethod != null) {
    ????? if (pagerMethod.equals("first")) {
    ??????? pager.first();
    ????? } else if (pagerMethod.equals("previous")) {
    ??????? pager.previous();
    ????? } else if (pagerMethod.equals("next")) {
    ??????? pager.next();
    ????? } else if (pagerMethod.equals("last")) {
    ??????? pager.last();
    ????? }
    ??? }
    ??? return pager;
    ? }
    }

    PageHelper這個類,我不用說應該也知道用來干嘛了

    3.DAO類

    package com.jpcf.db.dao;

    import com.jpcf.db.model.*;
    import com.jpcf.db.helper.HibernateUtil;
    import net.sf.hibernate.*;
    import java.util.*;
    import com.jpcf.db.controller.*;

    public class VehiclePropertyDAO {

    ? public Collection findWithPage(int pageSize, int startRow) throws HibernateException {
    ??? Collection vehicleList = null;
    ??? Transaction tx = null;
    ??? try {
    ????? Session session = HibernateUtil.currentSession();
    ????? tx = session.beginTransaction();
    ????? Query q = session.createQuery("from VehicleProperty vp");
    ????? q.setFirstResult(startRow);
    ????? q.setMaxResults(pageSize);
    ????? vehicleList = q.list();
    ????? tx.commit();
    ??? } catch (HibernateException he) {
    ????? if (tx != null) {
    ??????? tx.rollback();
    ????? }
    ????? throw he;
    ??? } finally {
    ????? HibernateUtil.closeSession();
    ??? }
    ??? return vehicleList;
    ? }

    ? public int getRows(String query) throws HibernateException {
    ??? int totalRows = 0;
    ??? Transaction tx = null;
    ??? try {
    ????? Session session = HibernateUtil.currentSession();
    ????? tx = session.beginTransaction();
    ????? totalRows = ((Integer) session.iterate(query).next()).intValue();
    ????? tx.commit();
    ??? } catch (HibernateException he) {
    ????? if (tx != null) {
    ??????? tx.rollback();
    ????? }
    ????? throw he;
    ??? } finally {
    ????? HibernateUtil.closeSession();
    ??? }

    ??? return totalRows;
    ? }

    }
    DAO類我就貼這些分頁需要的代碼了。
    “from VehicleProperty vp”也可以用一個參數傳進來,有興趣的自己改一下吧

    4.Action

    下面是在Action中用到的代碼:
    ? public ActionForward execute(ActionMapping actionMapping,
    ???????????????????????????????????? ActionForm actionForm,
    ???????????????????????????????????? HttpServletRequest httpServletRequest,
    ???????????????????????????????????? HttpServletResponse httpServletresponse) {
    ???? Collection clInfos = null;//用于輸出到頁面的記錄集合
    ???? int totalRows;//記錄總行數
    ???? VehiclePropertyDAO vehicleDAO = new VehiclePropertyDAO();

    ??? //取得當前表中的總行數
    ??? try {
    ????? totalRows = vehicleDAO.getRows("select count(*) from VehicleProperty");
    ??? } catch (Exception ex) {
    ????? servlet.log(ex.toString());
    ????? return actionMapping.findForward(Constants.FAILURE);
    ??? }

    ??? //通過PagerHelper類來獲取用于輸出到頁面的pager對象
    ??? Pager pager=PagerHelper.getPager(httpServletRequest,totalRows);

    ??? //取出從startRow開始的pageSize行記錄
    ??? try {
    ????? clInfos = vehicleDAO.findWithPage(pager.getPageSize(), pager.getStartRow());
    ??? } catch (Exception ex) {
    ????? servlet.log(ex.toString());
    ????? return actionMapping.findForward(Constants.FAILURE);
    ??? }

    ??? //把輸出的記錄集和pager對象保存到request對象中
    ??? httpServletRequest.setAttribute("CLINFOS", clInfos);
    ??? httpServletRequest.setAttribute("PAGER", pager);

    ??? return actionMapping.findForward(Constants.SUCCESS);
    ? }

    ?? 查詢語句select count(*) from VehicleProperty 也可以換成你需要的任意的條件(select count(*)?

    from VehicleProperty where ..)


    5.JSP頁面使用

    下面就是在JSP中的應用了:

    <td colspan="8" align="right" class="head">
    ?? 第<bean:write name="PAGER" property="currentPage"/>頁?
    ?? 共<bean:write name="PAGER" property="totalPages"/>頁?
    ?? <html:link action="/bussiness/clInfo/queryWithPage.do?method=queryWithPage&pageMethod=first"?
    paramName="PAGER" paramProperty="currentPage" paramId="currentPage">首頁</html:link>
    ?? <html:link action="/bussiness/clInfo/queryWithPage.do?method=queryWithPage&pageMethod=previous"?
    paramName="PAGER" paramProperty="currentPage" paramId="currentPage">上一頁</html:link>
    ?? <html:link action="/bussiness/clInfo/queryWithPage.do?method=queryWithPage&pageMethod=next"?
    paramName="PAGER" paramProperty="currentPage" paramId="currentPage">下一頁</html:link>
    ?? <html:link action="/bussiness/clInfo/queryWithPage.do?method=queryWithPage&pageMethod=last"?
    paramName="PAGER" paramProperty="currentPage" paramId="currentPage">尾頁</html:link>
    </td>

    ?? 解釋一下這一行:"/bussiness/clInfo/queryWithPage.do?method=queryWithPage&pageMethod=first
    method=queryWithPage 是由于我的Action繼承的是DispatchAction,需要一個method參數
    pageMethod=first 是用來在PageHelper類中判斷執行哪個操作

    四、總結

    ??? 我做的這個也只是一個借鑒,還有很多沒有實現的,比如還可以加一下 go 直接到第n頁的功能。
    ??? 其實最關鍵的是把當前頁號和要執行的是功能(上一頁,下一頁)的參數從頁面傳進來,在Action中就可以根據這兩個參數去取下一個頁面上要顯示的記錄集了。

    posted @ 2006-05-03 20:04 feingto 閱讀(413) | 評論 (0)編輯 收藏

    struts中的分頁實例

    struts中的分頁實例?
    ??
    ??? 這僅是一個入門實例,簡潔實用,從網上整理而來,供參考。這里僅列出部分文件,其它文件、數據庫及目錄結構請從本站下載。
    一、struts-config.xml配置,主要是配數據庫,這里用access。
    <?xml version="1.0" encoding="ISO-8859-1" ?>

    <!DOCTYPE struts-config PUBLIC
    ????????? "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
    ????????? "


    <struts-config>
    <data-sources>
    ?? <data-source key="dataSource" type="org.apache.commons.dbcp.BasicDataSource">
    ??????????? <set-property property="driverClassName" value="sun.jdbc.odbc.JdbcOdbcDriver" />
    ??????????? <set-property property="url" value="jdbc:odbc:page" />
    ??????????? <set-property property="username" value="admin" />
    ??????????? <set-property property="password" value="" />
    ??????????? <set-property property="maxActive" value="20" />
    ??????????? <set-property property="maxWait" value="5000" />
    ??????????? <set-property property="defaultAutoCommit" value="true" />
    ??????????? <set-property property="defaultReadOnly" value="false" />
    ??????????? <set-property property="validationQuery" value="SELECT 1" />
    ??????????? <set-property property="removeAbandoned" value="true" />
    ??????????? <set-property property="removeAbandonedTimeout" value="120" />????????????
    ??????????? <set-property property="encoding" value="false" />????????????
    ??????? </data-source>

    ?</data-sources>
    ? <form-beans>
    ? </form-beans>
    ? <global-forwards>
    ? </global-forwards>

    ? <action-mappings>
    ? <action path="/page" type="page.DataSourceAction" scope="request">
    ? <forward name="success" path="/pagetest.jsp"/>
    ? </action>
    ? </action-mappings>

    ? <controller>
    ? </controller>
    </struts-config>

    二、Action類
    用 page.do?start=1 來顯示第一個頁面?
    參數說明:?
    ? list:信息列表?
    ? start:開始位置?
    ? page:每頁顯示的信息數目?
    ? pages: 總頁數
    ? previous:上頁開始位置?
    ? next:下頁開始位置?

    package page;
    import org.apache.struts.action.*;
    import javax.servlet.http.*;

    import java.util.*;
    import javax.sql.*;
    import java.sql.*;
    import bean.*;

    public class DataSourceAction extends Action {

    ?public DataSourceAction(){}
    ?
    ?public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
    ?HttpServletResponse response) throws Exception {???
    ? try{
    ????? DataSource ds=this.getDataSource(request,"dataSource");???
    ????? Connection con = ds.getConnection();
    ????? Statement stmt = con.createStatement();
    ????? ResultSet resultSet = stmt.executeQuery("select count(*) from book" );?
    ????? resultSet.next();?
    ????? int data_num=resultSet.getInt(1);?
    ????? int start=1;
    ????? int page = 4; //每頁的記錄數。
    ????? int pages=data_num/page;
    ????? if(data_num%page!=0)
    ???????? pages++;
    ????? if(request.getParameter("start")!=null)
    ????????? start = Integer.parseInt(request.getParameter("start"));?
    ????? if(request.getParameter("go")!=null){
    ??????????????? int go = Integer.parseInt(request.getParameter("go"));?
    ??????????????? if(go<=1)
    ????????????????? start=1;
    ??????????????? else if(go>pages)
    ????????????????? start=(pages-1)*page+1;
    ??????????????? else?
    ?????????????????? start=(go-1)*page+1;
    ?????? }?
    ?????
    ????? String sql = "SELECT * FROM book where id>="+start+" and id<"+(start+page);
    ????? resultSet = stmt.executeQuery(sql);??
    ????? ArrayList list = new java.util.ArrayList();?
    ????? while(resultSet.next())
    ????? {??
    ??????? int id=resultSet.getInt("id");
    ??????? String name = resultSet.getString("name");
    ??????? String author = resultSet.getString("author");
    ??????? String price = resultSet.getString("price");
    ??????? System.out.println("開始數據封裝:name="+name+"author="+author+"price="+price);
    ??????? Book book= new Book(id,name,author,price);???????
    ??????? list.add(book);
    ????? }
    ??? con.close();
    ??? request.setAttribute("pages",new Integer(pages));
    ??? request.setAttribute("list",list);
    ??? //request.setAttribute("start", new Integer(start));?
    ??? request.setAttribute("page", new Integer(page));?

    ??????? // if there is a previous page, set the previous variable?
    ??????? int previous = start-page;?
    ??????? if ( previous>=0 ){?
    ??????????? request.setAttribute("previous", new Integer(previous));?
    ??????????? System.out.println ("previous:" + previous);?
    ??????? }?

    ??????? // if there is a next page, set the next variable?
    ??????? int next = start+page;?
    ??????? if ( next<=data_num ){?
    ??????????? request.setAttribute("next", new Integer(next));?
    ??????????? System.out.println ("next:" + next);?
    ??????? }?

    ?? }catch(SQLException e){
    ????????? e.printStackTrace();
    ????????? System.out.println("數據庫連接出現異常");
    ????? }?
    ???
    ???????????? return (mapping.findForward("success"));
    ? }?
    }


    三、bean類Book.java
    package bean;
    import java.sql.*;
    import java.util.ArrayList;
    public class Book {
    ?int id;
    ?private String bookname; //書名
    ?private String author;?? //作者
    ?private String price;??? //價格
    ?
    public Book(int id,String name,String author,String price){
    ?this.id=id;
    ?this.bookname=name;
    ?this.author=author;
    ?this.price=price;
    }

    public int getId(){?
    ??????? return id;?
    ??? }?

    ?public String getAuthor() {
    ? return author;
    ?}

    ?public void setAuthor(String author) {
    ? this.author = author;
    ?}

    ?public String getBookname() {
    ? return bookname;
    ?}

    ?public void setBookname(String bookname) {
    ? this.bookname = bookname;
    ?}
    ?
    ?public String getPrice(){
    ???? return this.price;?
    ?}
    ?
    ?public void setPrice(String price){
    ???? this.price=price;?
    ?}
    ?
    }
    四、分頁的jsp頁面pagetest.jsp,用了jstl中的c標記。
    <%@ page contentType="text/html; charset=gb2312" language="java"%>
    <%@ page import="java.util.*" %>
    <%@ page import="bean.*" %>
    <%@ taglib prefix="c" uri="
    <%@ taglib uri="/tags/struts-bean" prefix="bean" %>
    <%@ taglib uri="/tags/struts-html" prefix="html" %>
    <%@ taglib uri="/tags/struts-logic" prefix="logic" %>

    <logic:iterate id="book" name="list" type="bean.Book">?
    ??????????? <br><html:link??
    ??????????????????? paramId="id" paramName="book" paramProperty="id"?
    ??????????????????? page="/messagedetail.do">?
    ??????????????????? <bean:write name="book" property="bookname" />?
    ??????????????? </html:link>?
    </logic:iterate>?

    <form action="/TestPage/page.do">
    ?? <logic:present name="previous">?
    ??????????? <html:link??
    ??????????????????? paramId="start" paramName="previous"?
    ??????????????????? page="/page.do">?
    ??????????????????? 上一頁?
    ??????????????? </html:link>?
    ?? </logic:present>?

    ?? <logic:present name="next">?
    ????????????? <html:link??
    ??????????????????? paramId="start" paramName="next"?
    ??????????????????? page="/page.do">?
    ??????????????????? 下一頁?
    ??????????????? </html:link>?
    ?? </logic:present>?

    每頁<c:out value="${page}"/>條記錄,共<c:out value="${pages}"/>頁? 跳到<input type="text"? name="go" size="3" maxlength="30" >
    <input type="submit" value="go" >
    </form>
    ?????????

    ?

    OK!!!!
    五、測試,請下載本實例的目錄結構TestPage,放入tomcat的webapps下,在瀏覽器中輸入:
    ???
    http://127.0.0.1:8080/TestPage/page.do?
    來源: java學習室
    ?

    posted @ 2006-05-03 20:04 feingto 閱讀(631) | 評論 (0)編輯 收藏

    一個高效簡潔的Struts分頁方法

    在網上看了幾個Structs分頁,感覺不是很完善,于是根據自己的經驗,寫了一個相對高效簡潔的分頁方法。由于本人水平有限,如果大家有什么更好的想法,歡迎不吝賜教。
      
      一、 開發環境
      
      我的開發環境是:JBuilder x + Weblogic 8.1 + Oracle 9i + Windows 2003 ,如果朋友們的開發環境不一樣亦無妨。
      
      二、開發思路
      
      既然講的是Struts,那自然離不了MVC,分頁顯示也是如此。
      
      1、 建立數據庫和對應的表,本例的表是TCertificate。
      
      2、 建立適當的模型組件,對應你要查詢數據庫中的表。這部分由DAO數據訪問層來實現,如果有的朋友對DAO不熟悉可以查詢一下相關資料。本例由CertificateDAO.java來實現。
      
      3 、建立分頁所需要的模型組件,由javaBean來充當,并與CertificateDAO實現分離。網上介紹的很多方法,都存在著數據與分頁組件藕合的現象,這也是本方法與其它分頁方法的主要不同之處。
      
      4、建立控制器組件,這部分由Struts 中的Action來實現。主要負責將實例化CertificateDAO,只取要顯示的數據記錄,存入ArrayList對象然后返回,并放到 request中。而分頁部分則根據分頁條件,單獨進行構造,避免了與DAO混在一起的情況發生。網上其它介紹的一些分頁方法中,基本上都是一次性讀出所有查詢的數據,然后再由分頁相關組件進行構造。這樣,如果數據量大的話,很容易形成瓶頸。在本例中由于不是一次性地讀出查詢的所有數據,而只是讀出一個頁面要顯示的數據記錄,這就節省了很多不必要的數據傳輸,提高了效率。本例中為CertificateAction.java。
      
       5、建立視圖組件,這部分由jsp來充當,為了不出現java 代碼,我們使用Struts提供的標簽庫,主要負責從request中取出剛剛放入的對象,通過反復調用CertificateAction以及 action參數,而實現分頁顯示。本例中為listcertificate.jsp。
      
      6、 建立并配置struts-config.xml。
      
      三、實例代碼
      
      確定好上面的開發思路后,代碼的實現就有單可循了。
      
      1、建數據庫和相應的表。
      
      2、數據邏輯層的相關代碼。
      
      1)、通用的DAO類:CommonDAO.java
      
      這是一個很多DAO都要繼承到的通用DAO類,是我根據實踐總結出來的,為了減少篇幅,這里只顯示和本例相關的代碼。
      
      java代碼:
      
      代碼:
      --------------------------------------------------------------------------------
      package com.xindeco.business ;
      import java.io.*;
      import java.sql.*;
      import java.util.*;
      import javax.sql.*;
      import java.lang.IllegalAccessException;
      import java.lang.reflect.InvocationTargetException;
      import org.apache.commons.beanutils.BeanUtils;
      public class DAO
      {
      protected DataSource ds;
      /**
      * 說明:取得當前查詢的總記錄數
      */
      public int getRows ()
      {
      return this.count;
      }
      public void rsHandler (ResultSet rs, int offset, int limit)
      {
      try
      {
      count = 0;
      rs.absolute ( -1) ;
      count = rs.getRow () ;
      if (offset <= 0)
      {
      rs.beforeFirst () ;
      }
      else
      {
      rs.absolute (offset) ;
      }
      }
      catch (Exception e)
      {
      e.printStackTrace () ;
      }
      }
      public DAO(DataSource ds) {
      this.ds = ds;
      }
      
      public void setDataSource(DataSource ds) {
      this.ds = ds;
      }
      
      protected void close(ResultSet rs) {
      if (rs != null) {
      try {
      rs.close();
      } catch (SQLException e) {
      }
      rs = null;
      }
      }
      
      protected void close(PreparedStatement pstmt) {
      if (pstmt != null) {
      try {
      pstmt.close();
      } catch (SQLException e) {
      }
      pstmt = null;
      }
      }
      protected void close(Connection conn) {
      if (conn != null) {
      try {
      conn.close();
      } catch (SQLException e) {
      e.printStackTrace();
      }
      conn = null;
      }
      }
      
      protected void rollback(Connection conn) {
      if (conn != null) {
      try {
      conn.rollback();
      } catch (SQLException e) {
      e.printStackTrace();
      }
      conn = null;
      }
      }
      }
      
      這個類主要是通過子類傳進來的先進結果集,取得查詢的記錄總數,并對數據庫連接進行簡單的管理。
      
      2)、對數據庫進行訪問:CertificateDAO.java
      
      java代碼:
      
      代碼:
      --------------------------------------------------------------------------------
      package com.xindeco.business;
      
      import java.io.*;
      import java.sql.*;
      import java.util.*;
      import javax.sql.*;
      
      import com.xindeco.common.dbconn.DbConn;
      
      public class CertificateDAO extends DAO
      {
      
      public NationDAO(DataSource ds) {
      super(ds);
      }
      
      public List findCertificateList(int offset,int limit) throws SQLException
      {
      int countRows = 0 ;
      ArrayList list = null ;
      Connection conn = null;
      PreparedStatement pstmt = null;
      ResultSet rs = null;
      try
      {
      conn = ds.getConnection();
      String sql =
      "SELECT certificateID, certificateCode,certificateName,photoURL,"
      + "description,graduateID FROM TCertificate " ;
      pstmt = conn.prepareStatement(sql);
      rs = pstmt.executeQuery();
      /*對游標進行處理,rsHandler 方法在父類DAO中*/
      this.rsHandler(rs,offset,limit);
      if (rs != null && rs.next ())
      {
      list = new ArrayList () ;
      do
      {
      countRows++ ;
      list.add (rs2VO (rs)) ;
      }
      while ( (countRows++ < limit) && rs.next ()) ;
      }
      close(rs);
      close(pstmt);
      } catch (SQLException e) {
      close(rs);
      close(pstmt);
      rollback(conn);
      e.printStackTrace();
      }
      finally {
      close(conn);
      }
      return list ;
      }
      
      private CertificateVO rs2VO (ResultSet rs)
      {
      try
      {
      CertificateVO certificateVO = new CertificateVO () ;
      certificateVO.setCertificateID (rs.getInt ("certificateID")) ;
      certificateVO.setCertificateCode (rs.getString ("certificateCode")) ;
      certificateVO.setCertificateName (rs.getString ("certificateName")) ;
      certificateVO.setPhotoURL (rs.getString ("photoURL")) ;
      certificateVO.setDescription (rs.getString ("description")) ;
      certificateVO.setGraduateID (rs.getInt ("graduateID")) ;
      return certificateVO ;
      }
      catch (Exception ex)
      {
      ex.printStackTrace () ;
      return null ;
      }
      }
      }
      
      findCertificateList(int offset,int limit)是查得所有要顯示的數據,并放入ArrayList中。看過網上有些例子,把數據記錄放入ArrayList的動作過程直接在while循環體里完成,如果字段多的話,會造成方法過于寵大,又不美觀。這里,數據記錄放入ArrayList的動作過程由rs2VO方法完成,就比較整潔了。另外,if (rs != null && rs.next ()) 配合while ( (countRows++ < limit) && rs.next ()) 是為了程序的健壯性考慮的,稍分析一下不難得出結論。
      
      3、建立控制器組件:CertificateAction.java
      
      java代碼:
      
      代碼:
      --------------------------------------------------------------------------------
      package com.xindeco.presentation;
      
      import javax.sql.* ;
      import java.util.* ;
      
      import javax.servlet.http.* ;
      import javax.servlet.* ;
      
      import org.apache.struts.action.* ;
      import org.apache.struts.util.* ;
      
      import com.xindeco.common.Pager;
      import com.xindeco.business.graduatedata.CertificateDAO ;
      
      public class CertificateAction
      extends Action
      {
      private static final int PAGE_LENGTH = 5 ; //每頁顯示5條記錄
      public ActionForward execute (ActionMapping mapping, Actionform form,
      HttpServletRequest request,
      HttpServletResponse response)
      {
      ActionForward myforward = null ;
      String myaction = mapping.getParameter () ;
      
      if (isCancelled (request))
      {
      return mapping.findForward ("failure") ;
      }
      if ("".equalsIgnoreCase (myaction))
      {
      myforward = mapping.findForward ("failure") ;
      }
      else if    ("LIST".equalsIgnoreCase (myaction))
      {
      myforward = performList (mapping, form, request, response) ;
      }
      else
      {
      myforward = mapping.findForward ("failure") ;
      }
      return myforward ;
      }
      
      private ActionForward performList (ActionMapping mapping,
      Actionform actionform,
      HttpServletRequest request,
      HttpServletResponse response)
      {
      try
      {
      DataSource ds = (DataSource) servlet.getServletContext().getAttribute(Action.DATA_SOURCE_KEY);
      
      CertificateDAO  certificateDAO = new CertificateDAO (ds) ;
      
      int offset = 0;  //翻頁時的起始記錄所在游標
      int length = PAGE_LENGTH;
      String pageOffset = request.getParameter("pager.offset");
      if (pageOffset == null || pageOffset.equals("")) {
      offset = 0;
      } else {
      offset = Integer.parseInt(pageOffset);
      }
      List certificateList = certificateDAO .findCertificateList (offset,length) ;
      int size = certificateDAO.getRows(); // 取得總記錄數
      String url = request.getContextPath()+"/"+mapping.getPath()+".do";
      String pagerHeader = Pager.generate(offset, size, length, url); //分頁處理
      
      request.setAttribute ("pager", pagerHeader) ;
      request.setAttribute ("list", certificateList) ;
      }
      catch (Exception e)
      {
      e.printStackTrace();
      return mapping.findForward ("error") ;
      }
      return mapping.findForward ("success") ;
      }
      }
      
      CertificateAction.java主要是把數據從DAO中取出,并放入一個ArrayList 中,然后通過配置文件再軟件View的JSP頁。
      
      5、建立視圖listcertificate.jsp文件。
      
      jsp代碼:
      
      代碼:
      --------------------------------------------------------------------------------
      
      <%@ page contentType="text/html; charset=GBK" %>
      <%@ taglib uri="/WEB-INF/struts-template.tld" prefix="template" %>
      <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
      <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
      <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
      
      <table bgcolor="#666666" cellpadding="1" cellspacing="0" border="0" width="500">
      <tr>
      <td>
      <table cellpadding="0" cellspacing="0" border="0" width="500">
      <tr>
      <td bgcolor="#fecc51">&</td>
      </tr>
      </table>
      </td>
      </tr>
      <tr>
      <td>
      <table cellpadding="0" cellspacing="0" border="0" width="500">
      <tr>
      <td bgcolor="#d6e0ed">
      &&<bean:message key="label.list4certificate"/>
      </td>
      </tr>
      <tr bgcolor="#FFFFFF">
      <td width="5%"></td><td width="19%"></td><td width="76%"></td>
      </tr>
      <tr>
      <td>
      <table bgcolor="#f2f2f2" width="500" cellspacing="0" border="0">
      <tr bgcolor="#bacce1">
      <td><b><bean:message key="Certificate.select"/> </b></td>
      <td><b><bean:message key="Certificate.certificateID"/> </b></td>
      <td><b><bean:message key="Certificate.certificateCode"/></b></td>
      <td><b><bean:message key="Certificate.certificateName"/></b></td>
      <td><b><bean:message key="Certificate.view"/></b></td>
      </tr>
      
      <bean:write name="pager" property="description"/>
      <logic:equal name="pager" property="hasPrevious" value="true">
      <a href="/graduatedata/list.do?viewPage=<bean:write name="pager" property="previousPage"/>" class="a02">
      Previous
      </a>
      </logic:equal>
      <logic:equal name="pager" property="hasNext" value="true">
      <a href="/graduatedata/list.do?viewPage=<bean:write name="pager" property="nextPage"/>" class="a02">
      Next
      </a>
      </logic:equal>
      
      <logic:notEmpty name="list" scope="request">
      <logic:iterate id="certificate" name="list" type="com.xindeco.business.graduatedata.CertificateVO"scope="request">
      <tr bgcolor="#FFFFFF">
      <td><html:text property="name" value="<bean:write name="certificate" property="certificateID" scope="page"/>"/>
      </td>
      <td> <bean:write name="certificate" property="certificateID" scope="page"/></td>
      <td> <bean:write name="certificate" property="certificateCode" scope="page"/></td>
      <td> <bean:write name="certificate" property="certificateName" scope="page"/></td>
      <td> <bean:write name="certificate" property="photoURL" scope="page"/></td>
      </tr>
      </logic:iterate>
      </logic:notEmpty>
      </table>
      </td>
      </tr>
      </table>
      </td>
      </tr>
      </table>
      
      6、對應的配置文件struts-config.xml。
      
      java代碼:
      
      代碼:
      --------------------------------------------------------------------------------
      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "  <struts-config>
      <form-beans>
      <form-bean name="certificateform" type="com.xindeco.presentation.graduatedata.Certificateform" />
      </form-beans>
      <global-forwards>
      <forward name="error" path="/error/error.jsp" />
      </global-forwards>
      <action-mappings>
      <action name="certificateform" parameter="LIST" path="/graduatedata/list" scope="request" type="com.xindeco.presentation.graduatedata.CertificateAction" validate="true">
      <forward name="success" path="/graduatedata/listcertificate.jsp" />
      </action>
      </action-mappings>
      ……
      </struts-config>
      
      7、最后當然是最重要的分頁代碼了:Pager.java
      
      java代碼:
      
      代碼:
      --------------------------------------------------------------------------------
      package com.xindeco.common;
      
      import java.util.* ;
      public class Pager {
      private static int MAX_PAGE_INDEX = 10; //頁腳顯示多少頁
      private static String HEADER = "Result page";
      
      public static String generate(int offset, int length, int size, String url) {
      if (length > size) {
      String pref;
      if (url.indexOf("?") > -1) {
      pref = "&";
      } else {
      pref = "?";
      }
      String header = "<font face='Helvetica' size='-1'>"+HEADER+": ";
      if (offset > 0) {
      header += "&<a href=\""+url+pref+"pager.offset="+(offset-size)+"\">[<< Prev]</a>\n";
      }
      int start;
      int radius = MAX_PAGE_INDEX/2*size;
      if (offset < radius) {
      start = 0;
      } else if(offset < length-radius) {
      start = offset - radius;
      } else {
      start = (length/size-MAX_PAGE_INDEX)*size;
      }
      for(int i=start;i<length && i < start + MAX_PAGE_INDEX*size;i+=size) {
      if (i == offset) {
      header += "<b>"+(i/size+1)+"</b>\n";
      } else {
      header += "&<a href=\""+url+pref+"pager.offset="+i+"\">"+(i/size+1)+"</a>\n";
      }
      }
      if(offset < length - size) {
      header += "&<a href=\""+url+pref+"pager.offset="+((int)offset+(int)size)+"\">[Next >>]</a>\n";
      }
      header += "</font>";
      return header;
      } else {
      return "";
      }
      }
      }
      
      這部分代碼的實現相當簡潔,但已經足夠完成所需了。

    posted @ 2006-05-03 20:04 feingto 閱讀(317) | 評論 (0)編輯 收藏

    用struts上傳文件

    用到的類import org.apache.struts.upload.FormFile;

    Jsp上傳頁面:

    ?

    <%@ page contentType="text/html; charset=GBK" %>

    <html>

    <head>

    <title>

    strutsUploadForm

    </title>

    </head>

    <body bgcolor="#ffffff">

    <h1>

    上傳測試

    </h1>

    <form action="uploadTestAction.do" method="post" enctype="multipart/form-data" name="form1">

    ? <p>文本

    ??? <input name="theText" type="text" id="theText">

    </p>

    ? <p>文件

    ??? <input name="theFile" type="file" id="theFile">

    </p>

    ? <p>保存到

    ??? <input name="saveTo" type="text" id="saveTo">

    </p>

    ? <p>

    ??? <input type="submit" name="Submit" value="提交">

    </p>

    </form>

    </body>

    </html>

    ?

    ?

    actionForm

    ?

    package hehe;

    ?

    import org.apache.struts.action.*;

    import javax.servlet.http.*;

    import org.apache.struts.upload.FormFile;

    ?

    public class UploadTestForm extends ActionForm {

    ? private String saveTo;

    ? private String theText;

    ? private org.apache.struts.upload.FormFile theFile;//文件框對應的是formFile類型

    ? public String getSaveTo() {

    ??? return saveTo;

    ? }

    ? public void setSaveTo(String saveTo) {

    ??? this.saveTo = saveTo;

    ? }

    ? public org.apache.struts.upload.FormFile getTheFile() {

    ??? return theFile;

    ? }

    ? public void setTheFile(org.apache.struts.upload.FormFile theFile) {

    ??? this.theFile = theFile;

    ? }

    ? public String getTheText() {

    ??? return theText;

    ? }

    ? public void setTheText(String theText) {

    ??? this.theText = theText;

    ? }

    ? public ActionErrors validate(ActionMapping actionMapping, HttpServletRequest httpServletRequest) {

    ??? /**@todo: finish this method, this is just the skeleton.*/

    ??? if(!this.getTheFile().getContentType().equals("image/pjpeg")){

    ????? System.out.println("不是jpg");

    ??? }//可以判斷類型

    ??? if(this.getTheFile().getFileSize()>100){

    ????? System.out.println("長度大于1000");

    ??? }//可以判斷大小

    ??? return null;

    ? }

    ? public void reset(ActionMapping actionMapping, HttpServletRequest httpServletRequest) {

    ??? saveTo = null;

    ??? theFile = null;

    ??? theText = null;

    ? }

    }

    ?

    ?

    Action

    ?

    package hehe;

    ?

    import org.apache.struts.action.*;

    import org.apache.struts.upload.FormFile;

    import javax.servlet.http.*;

    import java.io.*;

    ?

    public class UploadTestAction

    ??? extends Action {

    ? public ActionForward execute(ActionMapping actionMapping,

    ?????????????????????????????? ActionForm actionForm,

    ?????????????????????????????? HttpServletRequest request,

    ?????????????????????????????? HttpServletResponse response) {

    ??? UploadTestForm uploadForm = (UploadTestForm) actionForm;

    ??? FormFile file = uploadForm.getTheFile();

    ??? String path = uploadForm.getSaveTo();

    ??? String theText = uploadForm.getTheText();

    ??? try {

    ????? InputStream input = file.getInputStream();//能從FormFile中獲得輸入流

    ????? OutputStream output = new FileOutputStream(path);

    ????? int bytesReader = 0;

    ????? byte[] readbuffer = new byte[8192];

    ????? while ( (bytesReader = input.read(readbuffer, 0, 8192)) != -1) {

    ??????? output.write(readbuffer, 0, bytesReader);

    ????? }

    ????? output.close();

    ??? }

    ??? catch (Exception e) {

    ????? e.printStackTrace();

    ??? }

    ??? request.setAttribute("theText", theText);

    ??? request.setAttribute("fileName", file.getFileName());//上傳的文件名

    ??? request.setAttribute("fileSize", new Integer(file.getFileSize()));//文件大小

    ??? request.setAttribute("fileType", file.getContentType());//文件類型

    ??? return actionMapping.findForward("success");

    ? }

    }

    ?

    ?

    結果頁面

    ?

    <%@ page contentType="text/html; charset=GBK" %>

    <html>

    <head>

    <title>

    strutsUploadResult

    </title>

    </head>

    <body bgcolor="#ffffff">

    <h1>

    上傳結果

    </h1>

    文件名:<%=request.getAttribute("fileName")%><br />

    文本:<%=request.getAttribute("theText")%><br />

    文件類型:<%=request.getAttribute("fileType")%><br />

    文件大小:<%=request.getAttribute("fileSize")%><br />

    </body>

    </html>

    posted @ 2006-05-03 20:03 feingto 閱讀(1166) | 評論 (1)編輯 收藏

    Hibernate查詢解決方案

         摘要: 第一部分: Hibernate 提供的查詢接口或其方法 (此部分不做深究,請參考 hibernate 手冊) ????? ?????? 1 。...  閱讀全文

    posted @ 2006-05-03 20:03 feingto 閱讀(429) | 評論 (0)編輯 收藏

    struts在URI后面傳參數的問題

    在struts標簽<html:link>的page屬性指定的URI后面傳遞參數可以有幾種方式:
    1.若明確參數名和參數值則直接在URI后輸出,
    如:<html:link page="/test.do?action=add">add</html:link>

    2.對于參數值不確定的,paramName和paramProperty來輸出,用paramId屬性指定參數名。
    對于paramName指定的對象應該存在于page、request、session、application其中之一。一般來說,是從Action類傳過來的,作為request的屬性之一(requst.setAttribute("name",object))。
    如果paramName指定的對象是action的ActionForm,則無需使用request.setAttribute方法。
    例:<html:link page="/test.do" paramId="userid" paramName="uid">uname</html:link>
    若參數值是一個bean對象的屬性值(比如ActionForm,或者集合中存放的對象)則:
    <html:link page="/test.do" paramId="userid" paramName="user" paramProperty="uid">uname</html:link>

    3.若兩個參數,一個確定一個不確定,則是以上兩種方法的結合,即:
    <html:link page="/test.do?action=modify" paramId="userid" paramName="uid">modify</html:link>

    4.對于多個參數的問題,可以使用一個HashMap集合對象來存放所有的參數名及對應的參數值的方式,paramName屬性值指定為該HashMap集合對象即可。
    舉例:
    <%
    //代碼理想的位置應該是在action中
    //可以在jsp頁面測試
    ? java.util.HashMap pms = new java.util.HashMap();
    ? pms.put("code", "001002");
    ? pms.put("name", "tester");
    ? pms.put("alias", new String[]{"matin","jack"});
    ? request.setAttribute("params", pms);
    %>
    <html:link action="/test.do" name="params" >test</html:link>
    編譯后的結果:<a href="/test.do?code=001002&name=tester&alias=matin&alias=jack">test</a>
    這種方式雖然可以解決傳多參數的問題,但是實現起來也比較麻煩,特別是對記錄集中的數據逐條列出的時候

    5.針對有的網友在<html:link>標簽中嵌入使用jsp腳本(scriptlet)的問題,
    例如:
    <html:link page="/test.do?code=<%=varible%>">add</html:link>,這種寫法是錯誤的,是無法編譯的。
    有的網友認為在struts標簽內是不允許使用jsp腳本的,這種說法也不準確。如果前面的寫法改成:
    <html:link page="<%="/test.do?code="+varible%>">add</html:link>,就可以被執行,但是要注意URL相對路徑的問題。

    雖然在struts標簽中嵌入jsp腳本不是真正意義上的struts應用,但是有時在委曲求全的情況下也只能如此了,除非使用自定義標簽。比如在form表單中可能需要根據具體數據讓某個字段是只讀的,就可以用嵌入jsp腳本來實現:
    <%
    boolean rdonly=false;
    if(2==2) rdonly=true;
    %>
    <html:text property="userid" readonly="<%=rdonly%>" />


    6.另外一種比較變態的方法,既不是真正意義上的struts,也不符合xml規范。那就是在<a>標簽中用<bean:write>標簽輸出參數值。
    如:<a href="test.do?uid=<bean:write name="user" property="userid"/>&name=<bean:write name="user" property="username"/>">test</a>

    posted @ 2006-05-03 20:02 feingto 閱讀(887) | 評論 (0)編輯 收藏

    struts錯誤和信息的處理

    1. 錯誤和信息的處理 .

    首先在資源文件中定義錯誤信息和普通信息 . :MessageResources.properties 中定義如下 :

    java 代碼 :?



    #
    # Resources
    for testing <html:errors> tag.
    #

    errors.header=<table>
    errors.footer=</table>
    errors.prefix=<tr><td>
    errors.suffix=</td></tr>

    property1error1=Property 1,
    Error 1
    property2error1=Property 2,
    Error 1
    property2error2=Property 2,
    Error 2
    property2error3=Property 2,
    Error 3
    property3error1=Property 3,
    Error 1
    property3error2=Property 3,
    Error 2
    globalError=Global
    Error

    #
    # Resources
    for testing <html:messages> tag.
    #

    messages.header=<table>
    messages.footer=</table>

    property1message1=Property 1, Message 1
    property2message1=Property 2, Message 1
    property2message2=Property 2, Message 2
    property2message3=Property 2, Message 3
    property3message1=Property 3, Message 1
    property3message2=Property 3, Message 2
    globalMessage=Global Message

    ?



    在程序中定義錯誤和信息類 , 這個例子寫在 JSP

    java 代碼 :?



    <%
    ? ? ? ActionErrors errors =
    new ActionErrors();
    ? ? ? errors.add("property1",
    new ActionError("property1error1"));
    ? ? ? errors.add("property2",
    new ActionError("property2error1"));
    ? ? ? errors.add("property2",
    new ActionError("property2error2"));
    ? ? ? errors.add("property2",
    new ActionError("property2error3"));
    ? ? ? errors.add("property3",
    new ActionError("property3error1"));
    ? ? ? errors.add("property3",
    new ActionError("property3error2"));
    ? ? ? errors.add(ActionErrors.GLOBAL_ERROR,
    new ActionError("globalError"));
    ? ? ? request.setAttribute(Globals.ERROR_KEY, errors);

    ? ? ? ActionMessages messages =
    new ActionMessages();
    ? ? ? messages.add("property1",
    new ActionMessage("property1message1"));
    ? ? ? messages.add("property2",
    new ActionMessage("property2message1"));
    ? ? ? messages.add("property2",
    new ActionMessage("property2message2"));
    ? ? ? messages.add("property2",
    new ActionMessage("property2message3"));
    ? ? ? messages.add("property3",
    new ActionMessage("property3message1"));
    ? ? ? messages.add("property3",
    new ActionMessage("property3message2"));
    ? ? ? messages.add(ActionMessages.GLOBAL_MESSAGE,
    new ActionMessage("globalMessage"));
    ? ? ? request.setAttribute(Globals.MESSAGE_KEY, messages);
    ? ? %>

    ?





    顯示錯誤 :

    java 代碼 :?



    <html:errors property="property1" />
    <html:errors property="property2" />

    ?


    顯示信息 :

    java 代碼 :?



    <html:messages property="property1" message="
    true " id="msg" header="messages.header" footer="messages.footer">
    ? ? ? ? ? ? <tr>
    ? ? ? ? ? ? ? <td>
    ? ? ? ? ? ? ? ? ? ? ?<%= pageContext.getAttribute("msg") %>
    ? ? ? ? ? ? ? </td>
    ? ? ? ? ? ? </tr>
    ? ? ? ? ? </html:messages>

    <html:messages message="
    true " id="msg" header="messages.header" footer="messages.footer">
    ? ? ? ? ? ? <tr>
    ? ? ? ? ? ? ? <td>
    ? ? ? ? ? ? ? ?<%= pageContext.getAttribute("msg") %>
    ? ? ? ? ? ? ? </td>
    ? ? ? ? ? ? </tr>
    </html:messages>

    ?

    ?

    posted @ 2006-05-03 20:02 feingto 閱讀(1032) | 評論 (0)編輯 收藏

    主站蜘蛛池模板: 亚洲日韩精品无码AV海量| 亚洲精品第一国产综合精品99 | 亚洲欧洲无码AV电影在线观看| 国产jizzjizz免费看jizz| 国产乱子伦精品免费无码专区| 最好免费观看韩国+日本| 在线免费观看污网站| 日韩免费视频播播| 又粗又硬又黄又爽的免费视频| 成人伊人亚洲人综合网站222| 国产成人精品123区免费视频| 国产男女猛烈无遮挡免费视频| 免费女人18毛片a级毛片视频| 亚洲国产精品综合久久网络| 亚洲五月午夜免费在线视频| 国产亚洲色婷婷久久99精品| 亚洲日本一区二区三区| 亚洲最大黄色网站| 亚洲色欲色欱wwW在线| 黄色一级视频免费观看| 成人免费av一区二区三区| 日本一道本不卡免费| 7m凹凸精品分类大全免费| 在线观看免费人成视频色| 日韩免费视频网站| 亚洲乱码精品久久久久..| 久久亚洲AV成人出白浆无码国产| 亚洲av日韩av无码av| 美女被免费视频网站a| 91精品全国免费观看青青| 亚洲精品在线免费观看视频| 免费无码黄动漫在线观看| 亚洲色欲久久久久综合网| 久久亚洲国产成人精品性色| 亚洲成人激情小说| 九九免费观看全部免费视频| 日韩精品极品视频在线观看免费| 精品少妇人妻AV免费久久洗澡| 国产午夜亚洲精品理论片不卡| 老色鬼久久亚洲AV综合| 亚洲avav天堂av在线网毛片|