2009年12月24日 星期四

實作Ext file upload功能

今天心血來潮,試試Ext是否可以作到資料上傳之功能,沒想到竟然作成功了,再此與大家分享。

開發環境:
IDE:MyEclipse6.6GA
Web Server:Tomcat 6.0.20
Database:MySql 5.1.36
MVC:Struts2.1.8
FrameWork:Spring2.0,Hibernate3.2
Client UI:Ext2.3.0

一、建立檔案上傳表單頁面(fileUploadForm.jsp):
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%@ taglib prefix="s" uri="/struts-tags"  %>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <base href="<%=basePath%>">

    

    <title>My JSP 'onReady.jsp' starting page</title>

    

 <meta http-equiv="pragma" content="no-cache">

 <meta http-equiv="cache-control" content="no-cache">

 <meta http-equiv="expires" content="0">    

 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

 <meta http-equiv="description" content="This is my page">

 <!--

 <link rel="stylesheet" type="text/css" href="styles.css">

 -->

 <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">

 <link rel="stylesheet" type="text/css" href="css/onReady.css">

 <script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>

 <script type="text/javascript" src="extjs/ext-all.js"></script>

 <script type="text/javascript" src="extjs/ext-lang-zh_TW.js"></script> 

 <script type="text/javascript">

 <!--

     var index=3;

     function addRow(){

      //插入第一列

   //var x=document.getElementById('fTable').insertRow(0);

   //插入最後一列

   //var x=document.getElementById('fTable').insertRow();

   //抓取表格列數

   var rows = document.getElementById('fTable').rows.length;

   //插入指定的列

   var x = document.getElementById('fTable').insertRow(rows-3);

   var y=x.insertCell(0);

   var z=x.insertCell(1);

   y.innerHTML="檔案名稱:";

   z.innerHTML="<input type=\"file\" name=\"upload\">";

     }

     function delRow(){

      //刪除最後一列

      //var x=document.getElementById('fTable').deleteRow();

   //抓取表格列數

   var rows = document.getElementById('fTable').rows.length;      

      //刪除指定的列

      var x=document.getElementById('fTable').deleteRow(rows-4);

     }

 

  Ext.onReady(function() {

   /*

   var upload_fp = new Ext.FormPanel({

    renderTo:'loading',

               items:[

                   {xtype:'textfield',inputType:'file',name:'upload',fieldLabel:'File'}

               ]

               ,buttons:[{text:'Upload',handler:function(){

                    upload_fp.getForm().submit({

                           url:'multiFileUpload.action',

                           method:'post'

                     });

               }}]

               ,fileUpload:true

   });

   */

   var fileField = new Ext.form.TextField({

    id:'fl1',

    fieldLabel:'檔案名稱',

    inputType:'file',

    name:'upload'

   }); 

   var fieldId = "fl";

   var fieldIdIndex = 1;

   function addField() {

     fieldIdIndex++;

     fieldId = 'fl' + fieldIdIndex;

     var mf = Ext.getCmp("myForm");

     var fa = new Ext.form.TextField(

      {xtype:'textfield',

       id:fieldId,

       fieldLabel:'檔案名稱',

       inputType:'file',

       name:'upload',

       anchor: '90%'});

     mf.add(fa);

     mf.doLayout();

   }

   function deleteField(){   

    var mf = Ext.getCmp("myForm");

    mf.remove(fieldId);

    fieldIdIndex--;

    fieldId = 'fl' + fieldIdIndex;

    mf.doLayout();

   }

   

   function upLoadFile(){

    uploadForm.getForm().submit({

     success:function(form,action){

      Ext.Msg.alert('結果','上傳成功');

      uploadForm.getForm().reset();

     },

     failure:function(form,action){

      Ext.Msg.alert('結果',action.result.errorMsg);     

     }

    });

   }   

    var uploadForm =  new Ext.form.FormPanel({

       //renderTo:'my_id',

       //title:'檔案上傳',

       id:'myForm',

       url:'multiFileUpload.action',

       method:'post',

       fileUpload:true,

       width:450,

       labelWidth:80,

       items : [fileField],

       buttons : [ {text: '新增上傳檔案',handler:addField },

            {text: '刪除列',handler:deleteField},

             {text: '上傳',handler:upLoadFile} ]

     });

     var win = new Ext.Window({

      title:'檔案上傳',

      width:450,

      height:300,

      items:uploadForm

     });     

     win.show();

  });

 //-->

 </script>

  </head>

  

  <body>

  <!-- 

   <br>

   <table align="center">

   <tr>

    <td>

     <div class="fileUpload">

   <div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>  

      <div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc">  

      <font color="red"><s:actionerror/></font>

      <font color="red"><s:fielderror/></font>

       <form action="<%=path%>/multiFileUpload" method="post" enctype="multipart/form-data">

        <table id="fTable">

         <tr>

          <td colspan="2">檔案上傳</td>

         </tr>

         <tr>

          <td>檔案名稱:</td>

          <td><input type="file" name="upload"></td>

         </tr>

         <tr>

          <td>檔案名稱:</td>

          <td><input type="file" name="upload"></td>

         </tr>

         <tr>

          <td>檔案名稱:</td>

          <td><input type="file" name="upload"></td>

         </tr>        

         <tr>

          <td colspan="2" align="left"><input type="button" id="deleteButton" value="冊除列" onclick="delRow()">&nbsp;&nbsp;&nbsp;<input type="button" id="addButton" value="新增上傳檔案" onclick="addRow();"></td>

         </tr>

         <tr>

          <td colspan="2">&nbsp;</td>

         </tr>          

         <tr>

          <td colspan="2" align="left"><input type="submit" value="上傳..."></td>

         </tr>    

         </table>

       </form> 

      </div></div></div>  

   <div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>

   </div>

  </td>

 </tr>

 <tr>

  <td>&nbsp;</td>

 </tr>

 <tr>

  <td><div id="my_id"></div></td>

 </tr>

 </table>

  -->

  <div id="loading"></div>

  </body>

</html>

二、建立fileUpload action及File Info bean:
1.File Info bean(FileInfo.java):
package com.bean.test;



public class FileInfo {

 private String fileName;

 private String contentType;

 private String savePath;

 public String getFileName() {

  return fileName;

 }

 public void setFileName(String fileName) {

  this.fileName = fileName;

 }

 public String getContentType() {

  return contentType;

 }

 public void setContentType(String contentType) {

  this.contentType = contentType;

 }

 public String getSavePath() {

  return savePath;

 }

 public void setSavePath(String savePath) {

  this.savePath = savePath;

 }

 

}


2.fileUpload action(MultiFileUploadAction.java):
package com.action.test;



import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;



import org.apache.struts2.ServletActionContext;



import com.bean.test.FileInfo;

import com.opensymphony.xwork2.ActionContext;

import com.opensymphony.xwork2.ActionSupport;



public class MultiFileUploadAction extends ActionSupport {

 /**

  * 

  */

 private static final long serialVersionUID = 1L;

 private File[] upload;

 private String[] uploadContentType;

 private String[] uploadFileName;

 private String savePath;

 private String targetDir;

 private String jsonString;

 private boolean errorFlag;

  

 public File[] getUpload() {

  return upload;

 }

 public void setUpload(File[] upload) {

  this.upload = upload;

 }

 public String[] getUploadContentType() {

  return uploadContentType;

 }

 public void setUploadContentType(String[] uploadContentType) {

  this.uploadContentType = uploadContentType;

 }

 public String[] getUploadFileName() {

  return uploadFileName;

 }

 public void setUploadFileName(String[] uploadFileName) {

  this.uploadFileName = uploadFileName;

 }

 public String getSavePath() {

  this.savePath = ServletActionContext.getServletContext().getRealPath(getTargetDir());

  return savePath;

 }

 public void setSavePath(String savePath) {

  this.savePath = savePath;

 }

 public String getTargetDir() {

  return targetDir;

 }

 public void setTargetDir(String targetDir) {

  this.targetDir = targetDir;

 }

 public String getJsonString() {

  return jsonString;

 }

 public void setJsonString(String jsonString) {

  this.jsonString = jsonString;

 }

 

 public String execute() throws Exception {

  return doUpload();

 }



 public String doUpload(){

  if(errorFlag){

   return SUCCESS;

  }

  if(upload==null){

   this.addActionError("請選擇檔案!!");

   this.jsonString = "{\"failure\":\"true\",\"errorMsg\":\"請選擇檔案!!\"}";

   return SUCCESS;

  }

  Map request = (Map)ActionContext.getContext().get("request");

  List list = new ArrayList();  

  for(int i=0;i<this.upload.length;i++){

   String path = this.upload[i].getPath();

   try {

    FileInputStream in = new FileInputStream(path);

    FileOutputStream os = new FileOutputStream(this.getSavePath()+"\\"+this.uploadFileName[i]);

    try {

     byte[] b = new byte[1024];

     int len=0;

     while((len=in.read(b))>0){

      os.write(b,0,len);

     }

     os.close();

     in.close();

    } catch (IOException e) {

     e.printStackTrace();

    }   

   } catch (FileNotFoundException e) {

    e.printStackTrace();

   }

   FileInfo fi = new FileInfo();

   fi.setFileName(this.getUploadFileName()[i]);

   fi.setContentType(this.getUploadContentType()[i]);

   fi.setSavePath(this.getSavePath());

   list.add(fi);

  }

  request.put("list", list);

  this.jsonString = "{\"success\":\"true\"}";

  return SUCCESS;  

 }

 

 public void validate() {

  //check upload file field error information(Content-Type not allow,File to large...)

  Map fieldErrors = this.getFieldErrors();

  for(int i=0;i<fieldErrors.size();i++){

   Object[] o = fieldErrors.values().toArray();

   for(int j=0;j<o.length;j++){

    String msg = o[j].toString().substring(1, o[j].toString().length()-1);

    msg = msg.replaceAll(":","").replaceAll("\"", "");

    //System.out.println(msg);

    this.jsonString = "{\"failure\":\"true\",\"errorMsg\":\""+msg+"\"}";

    this.clearFieldErrors();

    errorFlag=true;

    try {

     execute();

    } catch (Exception e) {

     e.printStackTrace();

    }

   }

  }

  

  //check upload file action error information(the request was rejected because its size (13711848) exceeds the configured maximum (10240000))

  Object[] o = this.getActionErrors().toArray();

  for(int i=0;i<o.length;i++){ 

   //System.out.println(o[i].toString());

   String msg = o[i].toString();

   this.jsonString = "{\"failure\":\"true\",\"errorMsg\":\""+msg+"\"}";   

   this.clearActionErrors();

   errorFlag=true;

   try {

    execute();

   } catch (Exception e) {

    e.printStackTrace();

   }   

  }

 }

}


三、config struts.xml:
<?xml version="1.0" encoding="UTF-8"?>

   <!DOCTYPE struts PUBLIC

 "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"

 "http://struts.apache.org/dtds/struts-2.1.dtd">



<struts>

 <constant name="struts.devMode" value="true"></constant> 

 <constant name="struts.configuration.xml.reload" value="true"></constant>

 <constant name="struts.i18n.reload" value="true"></constant>

 <constant name="struts.custom.i18n.resources" value="globalMessages"></constant>


 <!-- temp dir -->

 <constant name="struts.multipart.saveDir" value="C:\\Program Files (x86)\\Apache Software Foundation\\Tomcat 6.0\\webapps\\ExtStudy\\images"></constant>

 <!-- 一次最大上傳之檔案大小 -->

 <constant name="struts.multipart.maxSize" value="10240000"></constant>
  

 <package name="ExtStudy" extends="struts-default">

  <action name="SysMgrJson" class="SysMgrJsonAction">

   <result name="functoinJSON">JsonJSP/functionJSON.jsp</result>

   <result name="titleJSON">JsonJSP/titleJSON.jsp</result>

   <result name="comboFormJSON">JsonJSP/comboFormJSON.jsp</result>

   <result name="outputJSON">JsonJSP/outputJSON.jsp</result>

  </action>

  <action name="multiFileUpload" class="com.action.test.MultiFileUploadAction">

            <interceptor-ref name="fileUpload"> 

             <!-- 可以上傳之檔案格式 -->

                <param name="allowedTypes">

                 image/png,

                 image/gif,

                 image/jpeg,

                 image/jpg,

                </param>

                <!-- 單一檔案之最大可上傳檔案大小 -->

                <param name="maximumSize">4096000</param>

            </interceptor-ref> 

            <interceptor-ref name="defaultStack" />   

   <result>JsonJSP/outputJSON.jsp</result>

   <result name="input">Basic/fileUploadForm.jsp</result>

   <param name="targetDir">\\images</param>

  </action> 

 </package>

</struts>

四、測試結果:
1.http://localhost:8080/ExtStudy/Basic/fileUploadForm.jsp


















2009年12月23日 星期三

實作Ext Layout(七)


接續Ext Layout(一)功能,此練習主要是於Layout(border)南邊加入一張圖作為Layout練習之結束,且此練習亦是一個完整的電影資訊維護小功能。

開發環境:
IDE:MyEclipse6.6GA
Web Server:Tomcat 6.0.20
Database:MySql 5.1.36
MVC:Struts2.1.8
FrameWork:Spring2.0,Hibernate3.2
Client UI:Ext2.3.0

一、Layout頁面(layout8.jsp):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <base href="<%=basePath%>">

    

    <title>My JSP 'combox.jsp' starting page</title>

    

 <meta http-equiv="pragma" content="no-cache">

 <meta http-equiv="cache-control" content="no-cache">

 <meta http-equiv="expires" content="0">    

 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

 <meta http-equiv="description" content="This is my page">

 <!--

 <link rel="stylesheet" type="text/css" href="styles.css">

 -->

 <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">

 <link rel="stylesheet" type="text/css" href="css/onReady.css">

 <script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>

 <script type="text/javascript" src="extjs/ext-all.js"></script>

 <script type="text/javascript" src="extjs/ext-lang-zh_TW.js"></script> 

 <script type="text/javascript">

 <!--

  Ext.onReady(function(){

   var tabCount=5;

   Ext.BLANK_IMAGE_URL='extjs/resources/images/default/s.gif';

   Ext.QuickTips.init();

   /* normal store

   var store = new Ext.data.Store({

    url: 'SysMgrJson!getMovies.action',

    reader: new Ext.data.JsonReader({root:'results',totalProperty:'totals'}, [

     'id',

     'coverthumb',

     'title',

     'director',

     {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

     'genre',

     'tagline',

     {name: 'price', type: 'float'},

     {name: 'active'}

    ])

   });

   */

   //Grouping store

   var store = new Ext.data.GroupingStore({

    url: 'SysMgrJson!getMovies.action',

    sortInfo: {

     field: 'genre',

     direction: "ASC"

    },

    groupField: 'genre',

    reader: new Ext.data.JsonReader({root:'results',totalProperty:'totals'}, [

     'id',

     'coverthumb',

     'title',

     'director',

     {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

     'genre',

     'tagline',

     {name: 'price', type: 'float'},

     {name: 'active'}

    ])

   });

      

   var genres = new Ext.data.Store({

    data: [

     [1,"Comedy"],

     [2,"Drama"],

     [3,"Action"],

     [4,"Mystery"]    

    ],

    reader: new Ext.data.ArrayReader({id:'id'}, [

     'id',

     'genre'])

   }); 

        

   //Combining two columns function

   function title_tagline(val, x, store){

    return '<b>'+val+'</b><br>'+store.data.tagline;

   }

   //Generating HTML and graphics

   function cover_image(val){

    return '<img src="images/'+val+'.jpg" width="50%" height="50%">';

   }

   //for edit field of grid

   var title_edit = new Ext.form.TextField();

   var director_edit = new Ext.form.TextField();

   var tagline_edit = new Ext.form.TextField({

    maxLength: 45

   });

   var price_edit = new Ext.form.TextField();

   var coverthumb_edit = new Ext.form.TextField();

   var released_edit = new Ext.form.DateField();

   var genre_edit = new Ext.form.ComboBox({

    typeAhead: true,

    triggerAction: 'all',

    mode: 'local',

    store: genres,

    displayField:'genre',

    valueField: 'genre'

   });

   

   //for add row to grid

   var ds_model = Ext.data.Record.create([

    'id',  

    'title',

    'director',

    {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

    'genre',

    'tagline',

    'coverthumb',

    {name: 'price', type: 'float'},

    {name: 'active'}

   ]);      

   // add your data store here

   var grid = new Ext.grid.EditorGridPanel({

    //renderTo: document.body,

    //renderTo:'example-grid',

    frame:true,

    title: 'Movie Database',

    id: 'MovieDatabase',

    height:300,

    width:550,

    stripeRows:true,

    store: store,

    //matching Grouping store    

    view: new Ext.grid.GroupingView(),

    //增加grid event for Row Selection mode

    sm: new Ext.grid.RowSelectionModel({

     //singleSelect: true,

     listeners: {

      rowselect: {

       fn: function(sm,index,record) {

        index++;

        Ext.Msg.alert('提示','您選擇了,'+record.data.title+',第 '+index+'筆資料');

        //將grid選擇列之資料Load到Form中。

        //注意grid之欄位名稱需和form之欄位名稱相同,才可以將grid之資料Load到form中。

        movie_form.getForm().loadRecord(record);

       }

      }

     }

    }),

    //Altering the grid at the click of a button 

    tbar: [

     //modify title column of grid

     {

      text: '修改 Title',

      handler: function(){

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        var sel = sm.getSelected();

        Ext.Msg.show({

         title: '修改 Title',

         prompt: true,

         buttons: Ext.MessageBox.OKCANCEL,

         value: sel.data.title,

         fn: function(btn,text){

          if (btn == 'ok'){

           sel.set('title', text);

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲修改Title之列');

       }

      }

     },

     //hidden price column of grid

     {

      text: 'Hide Price',

      handler: function(btn){

       var cm = grid.getColumnModel();

       var pi = cm.getIndexById('price');

       //var pi=5;

       if (cm.isHidden(pi)){

        cm.setHidden(pi,false);

        btn.setText('Hide Price');

       }else{

        cm.setHidden(pi,true);

        btn.setText('Show Price');

       }

       btn.render();

      }

     },

     //add first row to grid

     {

      text: 'Add Movie(First)',

      icon: 'images/RowInsert.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       grid.getStore().insert(0,new ds_model({

        id:'',

        title:'New Movie',

        director:'',

        genre:'Comedy',

        tagline:'',

        active:'1'

        })

       );

       grid.startEditing(0,0);

      }

     },

     //add last row to grid

     {

      text: 'Add Movie(Last)',

      icon: 'images/RowInsert.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       grid.getStore().insert(grid.getStore().getCount(),new ds_model({

        id:'',

        title:'New Movie',

        director:'',

        genre:'Comedy',

        tagline:'',

        active:'1'

        })

       );

       grid.startEditing(grid.getStore().getCount()-1,0);

      }

     },

     //Deleting data from the server

     {

      text: 'Remove Movie',

      icon: 'images/RowDelete.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        //var sel = sm.getSelected();

        var sels = sm.getSelections();

        var len = sels.length;

        var ids = new Array(len);

        for(var i=0;i<len;i++){

         ids[i] = sels[i].data.id;

         if(i==0){

          var msgs = '刪除: '+sels[i].data.title;

         }else{

          msgs = msgs +',\n'+sels[i].data.title; 

         }

        };

        Ext.Msg.show({

        title: '刪除電影',

         buttons: Ext.MessageBox.YESNOCANCEL,

         msg: msgs,

         fn: function(btn){

          if (btn == 'yes'){

           var conn = new Ext.data.Connection();

           conn.request({

            url: 'SysMgrJson!updateMovies.action',

            method:'post',

            params: {

             action: 'delete',

             id: ids

            },

            success: function(resp,opt) {

             //grid.getStore().remove(sel);

             grid.getStore().reload();

            },

            failure: function(resp,opt) {

             Ext.Msg.alert('Error',

             'Unable to delete movie');

            }

           });

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲刪除(多)列之資料');

       }

      }

      },

     //Saving data to the server

     {

      text: 'Save Movie',

      icon: 'images/save-icon.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        var sels = sm.getSelections();

        var len = sels.length;

        var values = new Array(len);

        for(var i=0;i<len;i++){

         values[i] = new Array(9);

         values[i][0] = sels[i].data.id;

         values[i][1] = sels[i].data.title;

         values[i][2] = sels[i].data.director;

         values[i][3] = (sels[i].data.released).format('Y-m-d');

         values[i][4] = sels[i].data.genre;

         values[i][5] = sels[i].data.tagline;

         values[i][6] = sels[i].data.coverthumb;

         values[i][7] = sels[i].data.price;

         values[i][8] = sels[i].data.active;

         if(i==0){

          var msgs = '儲存: '+sels[i].data.title;

         }else{

          msgs = msgs +',\n'+sels[i].data.title; 

         }

        };

        Ext.Msg.show({

        title: '儲存電影',

         buttons: Ext.MessageBox.YESNOCANCEL,

         msg: msgs,

         fn: function(btn){

          if (btn == 'yes'){

           var conn = new Ext.data.Connection();

           conn.request({

            url: 'SysMgrJson!updateMovies.action',

            method:'post',

            params: {

             action: 'update',

             values: values

            },

            success: function(resp,opt) {

             //grid.getStore().remove(sel);

             grid.getStore().reload();

            },

            failure: function(resp,opt) {

             Ext.Msg.alert('Error',

             'Unable to save movie');

            }

           });

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲儲存(多)列之資料');

       }

      }

      }             

    ],

          bbar: new Ext.PagingToolbar({

              pageSize: 5,

              store: store,

              displayInfo: true,

              displayMsg: '第 {0} 筆 - {1} 筆 of {2} 筆',

              emptyMsg: "沒有資料"

          }),       

    //Defining a Grids column model and want to display column

    columns: [

    {header: "Cover", dataIndex: 'coverthumb',renderer:cover_image},

    {header: "CoverThumb", dataIndex: 'coverthumb',editor:coverthumb_edit},

    //Combining two columns

    {header: "Title", dataIndex: 'title',renderer:title_tagline,editor:title_edit},

    {header: "Director", dataIndex: 'director',editor:director_edit},

    //Client-side sorting

    {header: "Released", dataIndex: 'released',sortable:true,

    renderer: Ext.util.Format.dateRenderer('m/d/Y'),editor:released_edit},

    {header: "Genre", dataIndex: 'genre',editor:genre_edit},    

    {header: "Price",dataIndex: 'price',id:'price',editor:price_edit},

    //setup hidden column

    {header: "Tagline", dataIndex: 'tagline',hidden:true,editor:tagline_edit}

    ]

   });

   

   //Load content on menu item click

   var Movies = function() {

    return {

     showHelp : function(btn){

      var helpbody = Ext.get('EastPanel01');

      if (!helpbody) {

       Ext.DomHelper.append(Ext.getBody(),{

        tag:'div',

        id:'EastPanel01'

        });

      }

      Movies.doLoad(btn.helpfile);

     },

     doLoad : function(file){

      Ext.get('EastPanel01').load({

       url: 'html/' + file + '.txt'

      });

     }

    };

   }();

   //

   var TabOper = function(){

    return{

     activeTab:function(btn){

      var tabId = btn.helpfile;

      Ext.Msg.alert('提示','開啟 '+tabId+' Tab');

      Ext.getCmp('movieview').findById('movietabs').activate(tabId);

     },

     addTab:function(){

      var len = ++tabCount;

      var title = 'Tab_'+len;

      var index = len % 4;

      var autoLoadFile;

      if(index==0){

       autoLoadFile = "html/BombaySummer.html";

      }else if(index==1){

       autoLoadFile = "html/NewYorkLove.html";

      }else if(index==2){

       autoLoadFile = "html/SHERLOCKHOLMES.html";

      }else{

       autoLoadFile = "html/Thirst.html";

      }

      Ext.getCmp('movieview').findById('movietabs').add({

       title: title,

       id: title,

       html: title,

       iconCls: 'Microsoft',

       closable:true,

       autoLoad: autoLoadFile,

       autoScroll: true      

      });

      Ext.getCmp('movieview').findById('movietabs').activate(title);      

     },

     removeTab:function(){

      var len = tabCount;

      var title = 'Tab_'+len;

      Ext.getCmp('movieview').findById('movietabs').remove(title);

      len = tabCount--

      title = 'Tab_'+len;

      Ext.getCmp('movieview').findById('movietabs').activate(title);

      if(tabCount<=5){

       tabCount=5;

      }      

     }          

    };

   }();



   //create myToolBar

   var myToolBar = new Ext.Toolbar({

    //renderTo:document.body,

    items:[{xtype:'tbbutton',

         text:'按我',

         //加入Icon

         cls:'x-btn-text-icon',

         icon:'images/forumlink.gif',

         //加入按鈕事件

         handler:function(){Ext.Msg.alert('按我','您按到我了!');}},

        {xtype:'tbbutton',

         text:'Add Tab',

         handler:TabOper.addTab},

         {xtype:'tbbutton',

         text:'Remove Tab',

         handler:TabOper.removeTab},

        {xtype:'tbbutton',

         text:'Acitve Tab',

         //加入群組及checked default value

      menu:[{text:'Movie Database',

            checked:true,

            group:'quality',

            helpfile:'MovieDatabase',

            handler:TabOper.activeTab},

         {text:'Move Descriptions',

            checked:false,

            group:'quality',

            helpfile:'MovieDescriptions',

            handler:TabOper.activeTab},

         {text:'Nested Layout',

            checked:false,

            group:'quality',

            helpfile:'NestedLayout',

            handler:TabOper.activeTab},

           {text:'Microsoft',

            checked:false,

            group:'quality',

            helpfile:'Microsoft',

            handler:TabOper.activeTab},

           {text:'Office Space',

            checked:false,

            group:'quality',

            helpfile:'OfficeSpace',

            handler:TabOper.activeTab}]},

        {xtype:'tbsplit',

         text:'Help',

         menu:[{text:'Genre',

             helpfile:'genre',

             handler:Movies.showHelp},

            {text:'Director',

             helpfile:'director',

             handler:Movies.showHelp},

            {text:'Title',

             helpfile:'title',

             handler:Movies.showHelp}]}

       ]

   });

   

   var genre = new Ext.form.ComboBox({

    typeAhead: true,

    triggerAction: 'all',

    mode: 'local',

    store: genres,

    fieldLabel:'Genre',

    displayField:'genre',

    valueField: 'genre',

    hiddenName: 'genre',

    width:80

   });

      

   //create movie form

   var movie_form = new Ext.form.FormPanel({

    frame:true,

    title:'Movie information form',

    labelAlign:'left',

    items:[{xtype:'textfield',fieldLabel:'Title',name:'title',allowBlank:false,maxLength:45,maxLengthText:45},

        {xtype:'textfield',fieldLabel:'Director',name:'director',allowBlank:false,maxLength:45,maxLengthText:45},

        {xtype:'textfield',fieldLabel:'Coverthumb',name:'coverthumb',maxLength:45},

        {xtype:'datefield',fieldLabel:'Released',name:'released',disabledDays:[0,6]},

        {xtype:'textfield',fieldLabel:'Price',name:'price',maxLength:45},

        {xtype:'checkbox',fieldLabel:'Available?',name:'active'},

        genre,

        {xtype:'textarea',fieldLabel:'Tagline',name:'tagline',autoScroll:true} 

    ],

    buttons: [

     {text: 'Save',

      handler: function(){

       var values = new Array(1);

       values[0] = new Array(9);

       var bf = movie_form.getForm();

       values[0][0] = '';//id

       values[0][1] = bf.findField('title').getValue();//title

       values[0][2] = bf.findField('director').getValue();//director

       values[0][3] = (bf.findField('released').getValue()).format('Y-m-d');//released

       values[0][4] = bf.findField('genre').getValue();//genre

       values[0][5] = bf.findField('tagline').getValue();//tagline

       values[0][6] = bf.findField('coverthumb').getValue();//coverthumb

       values[0][7] = bf.findField('price').getValue();//price

       values[0][8] = (bf.findField('active').getValue()==true)?'1':'0';//active      

       movie_form.getForm().submit({

        url:'SysMgrJson!updateMovies.action',

        method:'post',     

        params:{action: 'update', values:values},

        success: function(f,a){

         grid.getStore().reload();

         Ext.Msg.alert('Success', 'It worked');

        },

        failure: function(f,a){

         Ext.Msg.alert('Warning', 'Error');

        }

       });

      }

     }, 

     {text: 'Reset',

      handler: function(){

       movie_form.getForm().reset();

      }

     }]

   });

                        
   var south_img = '<img src="images/top_002.jpg" 
width="1280">';    

   var viewport = new Ext.Viewport({

    layout: 'border',

    id: 'movieview',

    renderTo: Ext.getBody(),    

    items: [{region: 'north',

      xtype: 'toolbar',

      items:[myToolBar]},

      {region: 'west',

      //xtype: 'panel',

      split: true,

      //open/close panel

      collapsible: true,

      collapseMode: 'mini',

      title: 'Some Info',

      bodyStyle:'padding:5px;',

      width: 250,

      minSize: 200,

      items:movie_form},

      {region: 'center',

      //Adding a tab panel

      xtype: 'tabpanel',

      id: 'movietabs',

      activeTab: 0,

      items: [

      //add grid into tabpanel

      grid,

      //layout accordion into tabpanel

      {title: 'Movie Descriptions',

       id: 'MovieDescriptions',

       layout: 'accordion',       

       items: [{title: 'Bombay Summer',

          autoLoad: 'html/BombaySummer.html',

          autoScroll: true},

         {title: '紐約我愛你',

          autoLoad: 'html/NewYorkLove.html',

          autoScroll: true},

         {title: 'SHERLOCK HOLMES',

          autoLoad: 'html/SHERLOCKHOLMES.html',

          autoScroll: true},

         {title: 'Thirst',

          autoLoad: 'html/Thirst.html',

          autoScroll: true}]

      },

      //Nested layouts

      {title: 'NestedLayout',

       id: 'NestedLayout',

       layout: 'border',

       border: false,

       items: [{region: 'north',

          height: 100,

          split: true,

          html: 'Nested North'

          },

          {region: 'center',

           html: 'Nested Center'

          }]

      },    

      {title: 'Microsoft',

       id: 'Microsoft',

       iconCls: 'Microsoft',

       html: 'Microsoft!'

      }]

      },

      {region: 'east',

      xtype: 'panel',

      split: true,

      title: 'genre information form',

      id: 'moreinfo',

      //open/close panel

      collapsible: true,

      width: 200,

      //html: 'East',

      //指定Div id

      items:[{id: 'EastPanel01'}]      

      },

      {region: 'south',

      xtype: 'panel',

      height:100,


      html: south_img}]

   });

   //需在gridPanel建立後才可以Load資料

   store.load({params:{start:0, limit:5}});

                        //利用程式方式動態將Layout(border)東邊Panel關閉之方法
   var moreinfo = Ext.getCmp('movieview').findById('moreinfo');

   if (moreinfo.isVisible()){

    //moreinfo.expand();

    moreinfo.collapse();

   }

                        //利用程式方式動態將Layout(border)中間加入一個Tab之方法
   Ext.getCmp('movieview').findById('movietabs').add({

    title: 'Office Space',

    id: 'OfficeSpace',

    html: 'Movie Info'

   });      

  });  

 //-->

 </script>

  </head>  

  <body>



  </body>

</html>

二、測試結果:
1.http://localhost:8080/ExtStudy/Basic/layout8.jsp


2009年12月22日 星期二

實作Ext Layout(六)

接續Ext Layout(一)功能,此練習主要是於Layout(border)中間之第三個Tab加入一個layout,稱作Nest layout(北邊及中間)。

開發環境:
IDE:MyEclipse6.6GA
Web Server:Tomcat 6.0.20
Database:MySql 5.1.36
MVC:Struts2.1.8
FrameWork:Spring2.0,Hibernate3.2
Client UI:Ext2.3.0

一、Layout頁面(layout7.jsp):
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <base href="<%=basePath%>">

    

    <title>My JSP 'combox.jsp' starting page</title>

    

 <meta http-equiv="pragma" content="no-cache">

 <meta http-equiv="cache-control" content="no-cache">

 <meta http-equiv="expires" content="0">    

 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

 <meta http-equiv="description" content="This is my page">

 <!--

 <link rel="stylesheet" type="text/css" href="styles.css">

 -->

 <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">

 <link rel="stylesheet" type="text/css" href="css/onReady.css">

 <script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>

 <script type="text/javascript" src="extjs/ext-all.js"></script>

 <script type="text/javascript" src="extjs/ext-lang-zh_TW.js"></script> 

 <script type="text/javascript">

 <!--

  Ext.onReady(function(){

   Ext.BLANK_IMAGE_URL='extjs/resources/images/default/s.gif';

   /* normal store

   var store = new Ext.data.Store({

    url: 'SysMgrJson!getMovies.action',

    reader: new Ext.data.JsonReader({root:'results',totalProperty:'totals'}, [

     'id',

     'coverthumb',

     'title',

     'director',

     {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

     'genre',

     'tagline',

     {name: 'price', type: 'float'},

     {name: 'active'}

    ])

   });

   */

   //Grouping store

   var store = new Ext.data.GroupingStore({

    url: 'SysMgrJson!getMovies.action',

    sortInfo: {

     field: 'genre',

     direction: "ASC"

    },

    groupField: 'genre',

    reader: new Ext.data.JsonReader({root:'results',totalProperty:'totals'}, [

     'id',

     'coverthumb',

     'title',

     'director',

     {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

     'genre',

     'tagline',

     {name: 'price', type: 'float'},

     {name: 'active'}

    ])

   });

      

   var genres = new Ext.data.Store({

    data: [

     [1,"Comedy"],

     [2,"Drama"],

     [3,"Action"],

     [4,"Mystery"]    

    ],

    reader: new Ext.data.ArrayReader({id:'id'}, [

     'id',

     'genre'])

   }); 

        

   //Combining two columns function

   function title_tagline(val, x, store){

    return '<b>'+val+'</b><br>'+store.data.tagline;

   }

   //Generating HTML and graphics

   function cover_image(val){

    return '<img src="images/'+val+'.jpg" width="50%" height="50%">';

   }

   //for edit field of grid

   var title_edit = new Ext.form.TextField();

   var director_edit = new Ext.form.TextField();

   var tagline_edit = new Ext.form.TextField({

    maxLength: 45

   });

   var price_edit = new Ext.form.TextField();

   var coverthumb_edit = new Ext.form.TextField();

   var released_edit = new Ext.form.DateField();

   var genre_edit = new Ext.form.ComboBox({

    typeAhead: true,

    triggerAction: 'all',

    mode: 'local',

    store: genres,

    displayField:'genre',

    valueField: 'genre'

   });

   

   //for add row to grid

   var ds_model = Ext.data.Record.create([

    'id',  

    'title',

    'director',

    {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

    'genre',

    'tagline',

    'coverthumb',

    {name: 'price', type: 'float'},

    {name: 'active'}

   ]);      

   // add your data store here

   var grid = new Ext.grid.EditorGridPanel({

    //renderTo: document.body,

    //renderTo:'example-grid',

    frame:true,

    title: 'Movie Database',

    height:300,

    width:550,

    stripeRows:true,

    store: store,

    //matching Grouping store    

    view: new Ext.grid.GroupingView(),

    //增加grid event for Row Selection mode

    sm: new Ext.grid.RowSelectionModel({

     //singleSelect: true,

     listeners: {

      rowselect: {

       fn: function(sm,index,record) {

        index++;

        Ext.Msg.alert('提示','您選擇了,'+record.data.title+',第 '+index+'筆資料');

       }

      }

     }

    }),

    //Altering the grid at the click of a button 

    tbar: [

     //modify title column of grid

     {

      text: '修改 Title',

      handler: function(){

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        var sel = sm.getSelected();

        Ext.Msg.show({

         title: '修改 Title',

         prompt: true,

         buttons: Ext.MessageBox.OKCANCEL,

         value: sel.data.title,

         fn: function(btn,text){

          if (btn == 'ok'){

           sel.set('title', text);

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲修改Title之列');

       }

      }

     },

     //hidden price column of grid

     {

      text: 'Hide Price',

      handler: function(btn){

       var cm = grid.getColumnModel();

       var pi = cm.getIndexById('price');

       //var pi=5;

       if (cm.isHidden(pi)){

        cm.setHidden(pi,false);

        btn.setText('Hide Price');

       }else{

        cm.setHidden(pi,true);

        btn.setText('Show Price');

       }

       btn.render();

      }

     },

     //add first row to grid

     {

      text: 'Add Movie(First)',

      icon: 'images/RowInsert.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       grid.getStore().insert(0,new ds_model({

        id:'',

        title:'New Movie',

        director:'',

        genre:'Comedy',

        tagline:'',

        active:'1'

        })

       );

       grid.startEditing(0,0);

      }

     },

     //add last row to grid

     {

      text: 'Add Movie(Last)',

      icon: 'images/RowInsert.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       grid.getStore().insert(grid.getStore().getCount(),new ds_model({

        id:'',

        title:'New Movie',

        director:'',

        genre:'Comedy',

        tagline:'',

        active:'1'

        })

       );

       grid.startEditing(grid.getStore().getCount()-1,0);

      }

     },

     //Deleting data from the server

     {

      text: 'Remove Movie',

      icon: 'images/RowDelete.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        //var sel = sm.getSelected();

        var sels = sm.getSelections();

        var len = sels.length;

        var ids = new Array(len);

        for(var i=0;i<len;i++){

         ids[i] = sels[i].data.id;

         if(i==0){

          var msgs = '刪除: '+sels[i].data.title;

         }else{

          msgs = msgs +',\n'+sels[i].data.title; 

         }

        };

        Ext.Msg.show({

        title: '刪除電影',

         buttons: Ext.MessageBox.YESNOCANCEL,

         msg: msgs,

         fn: function(btn){

          if (btn == 'yes'){

           var conn = new Ext.data.Connection();

           conn.request({

            url: 'SysMgrJson!updateMovies.action',

            method:'post',

            params: {

             action: 'delete',

             id: ids

            },

            success: function(resp,opt) {

             //grid.getStore().remove(sel);

             grid.getStore().reload();

            },

            failure: function(resp,opt) {

             Ext.Msg.alert('Error',

             'Unable to delete movie');

            }

           });

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲刪除(多)列之資料');

       }

      }

      },

     //Saving data to the server

     {

      text: 'Save Movie',

      icon: 'images/save-icon.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        var sels = sm.getSelections();

        var len = sels.length;

        var values = new Array(len);

        for(var i=0;i<len;i++){

         values[i] = new Array(9);

         values[i][0] = sels[i].data.id;

         values[i][1] = sels[i].data.title;

         values[i][2] = sels[i].data.director;

         values[i][3] = (sels[i].data.released).format('Y-m-d');

         values[i][4] = sels[i].data.genre;

         values[i][5] = sels[i].data.tagline;

         values[i][6] = sels[i].data.coverthumb;

         values[i][7] = sels[i].data.price;

         values[i][8] = sels[i].data.active;

         if(i==0){

          var msgs = '儲存: '+sels[i].data.title;

         }else{

          msgs = msgs +',\n'+sels[i].data.title; 

         }

        };

        Ext.Msg.show({

        title: '儲存電影',

         buttons: Ext.MessageBox.YESNOCANCEL,

         msg: msgs,

         fn: function(btn){

          if (btn == 'yes'){

           var conn = new Ext.data.Connection();

           conn.request({

            url: 'SysMgrJson!updateMovies.action',

            method:'post',

            params: {

             action: 'update',

             values: values

            },

            success: function(resp,opt) {

             //grid.getStore().remove(sel);

             grid.getStore().reload();

            },

            failure: function(resp,opt) {

             Ext.Msg.alert('Error',

             'Unable to save movie');

            }

           });

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲儲存(多)列之資料');

       }

      }

      }             

    ],

          bbar: new Ext.PagingToolbar({

              pageSize: 5,

              store: store,

              displayInfo: true,

              displayMsg: '第 {0} 筆 - {1} 筆 of {2} 筆',

              emptyMsg: "沒有資料"

          }),       

    //Defining a Grids column model and want to display column

    columns: [

    {header: "Cover", dataIndex: 'coverthumb',renderer:cover_image},

    {header: "CoverThumb", dataIndex: 'coverthumb',editor:coverthumb_edit},

    //Combining two columns

    {header: "Title", dataIndex: 'title',renderer:title_tagline,editor:title_edit},

    {header: "Director", dataIndex: 'director',editor:director_edit},

    //Client-side sorting

    {header: "Released", dataIndex: 'released',sortable:true,

    renderer: Ext.util.Format.dateRenderer('m/d/Y'),editor:released_edit},

    {header: "Genre", dataIndex: 'genre',editor:genre_edit},    

    {header: "Price",dataIndex: 'price',id:'price',editor:price_edit},

    //setup hidden column

    {header: "Tagline", dataIndex: 'tagline',hidden:true,editor:tagline_edit}

    ]

   });

   

   //Load content on menu item click

   var Movies = function() {

    return {

     showHelp : function(btn){

      var helpbody = Ext.get('EastPanel01');

      if (!helpbody) {

       Ext.DomHelper.append(Ext.getBody(),{

        tag:'div',

        id:'EastPanel01'

        });

      }

      Movies.doLoad(btn.helpfile);

     },

     doLoad : function(file){

      Ext.get('EastPanel01').load({

       url: 'html/' + file + '.txt'

      });

     }

    };

   }();

   //create myToolBar

   var myToolBar = new Ext.Toolbar({

    //renderTo:document.body,

    items:[{xtype:'tbbutton',

         text:'Button',

         //加入Icon

         cls:'x-btn-text-icon',

         icon:'images/forumlink.gif',

         //加入按鈕事件

         handler:function(){Ext.Msg.alert('按我','您按到我了!');}},

        {xtype:'tbbutton',

         text:'Menu Button',

         //加入群組及checked default value

      menu:[{text:'Better',

            checked:true,

            group:'quality'},

         {text:'Good',

            checked:false,

            group:'quality'},

         {text:'Best',

            checked:false,

            group:'quality'}]},

        {xtype:'tbsplit',

      text:'Split Button',

      menu:[{text:'Item One'},

         {text:'Item Two'},

         {text:'Item Three'}]

        },

        {xtype:'tbsplit',

         text:'Help',

         menu:[{text:'Genre',

             helpfile:'genre',

             handler:Movies.showHelp},

            {text:'Director',

             helpfile:'director',

             handler:Movies.showHelp},

            {text:'Title',

             helpfile:'title',

             handler:Movies.showHelp}]}

       ]

   });

   

   var genre = new Ext.form.ComboBox({

    typeAhead: true,

    triggerAction: 'all',

    mode: 'local',

    store: genres,

    fieldLabel:'Genre',

    displayField:'genre',

    valueField: 'genre',

    hiddenName: 'genre',

    width:80

   });

      

   //create movie form

   var movie_form = new Ext.form.FormPanel({

    frame:true,

    title:'Movie information form',

    labelAlign:'left',

    items:[{xtype:'textfield',fieldLabel:'Title',name:'title',allowBlank:false,maxLength:45,maxLengthText:45},

        {xtype:'textfield',fieldLabel:'Director',name:'director',allowBlank:false,maxLength:45,maxLengthText:45},

        {xtype:'textfield',fieldLabel:'Coverthumb',name:'coverthumb',maxLength:45},

        {xtype:'datefield',fieldLabel:'Released',name:'released',disabledDays:[0,6]},

        {xtype:'textfield',fieldLabel:'Price',name:'price',maxLength:45},

        {xtype:'checkbox',fieldLabel:'Available?',name:'active'},

        genre,

        {xtype:'textarea',fieldLabel:'Tagline',name:'tagline',autoScroll:true} 

    ],

    buttons: [

     {text: 'Save',

      handler: function(){

       var values = new Array(1);

       values[0] = new Array(9);

       var bf = movie_form.getForm();

       values[0][0] = '';//id

       values[0][1] = bf.findField('title').getValue();//title

       values[0][2] = bf.findField('director').getValue();//director

       values[0][3] = (bf.findField('released').getValue()).format('Y-m-d');//released

       values[0][4] = bf.findField('genre').getValue();//genre

       values[0][5] = bf.findField('tagline').getValue();//tagline

       values[0][6] = bf.findField('coverthumb').getValue();//coverthumb

       values[0][7] = bf.findField('price').getValue();//price

       values[0][8] = (bf.findField('active').getValue()==true)?'1':'0';//active      

       movie_form.getForm().submit({

        url:'SysMgrJson!updateMovies.action',

        method:'post',     

        params:{action: 'update', values:values},

        success: function(f,a){

         grid.getStore().reload();

         Ext.Msg.alert('Success', 'It worked');

        },

        failure: function(f,a){

         Ext.Msg.alert('Warning', 'Error');

        }

       });

      }

     }, 

     {text: 'Reset',

      handler: function(){

       movie_form.getForm().reset();

      }

     }]

   }); 

          

   var viewport = new Ext.Viewport({

    layout: 'border',

    renderTo: Ext.getBody(),    

    items: [{region: 'north',

      xtype: 'toolbar',

      items:[myToolBar]},

      {region: 'west',

      //xtype: 'panel',

      split: true,

      //open/close panel

      collapsible: true,

      collapseMode: 'mini',

      title: 'Some Info',

      bodyStyle:'padding:5px;',

      width: 250,

      minSize: 200,

      items:movie_form},

      {region: 'center',

      //Adding a tab panel

      xtype: 'tabpanel',

      activeTab: 0,

      items: [

      //add grid into tabpanel

      grid,

      //layout accordion into tabpanel

      {title: 'Movie Descriptions',

       layout: 'accordion',       

       items: [{title: 'Bombay Summer',

          autoLoad: 'html/BombaySummer.html',

          autoScroll: true},

         {title: '紐約我愛你',

          autoLoad: 'html/NewYorkLove.html',

          autoScroll: true},

         {title: 'SHERLOCK HOLMES',

          autoLoad: 'html/SHERLOCKHOLMES.html',

          autoScroll: true},

         {title: 'Thirst',

          autoLoad: 'html/Thirst.html',

          autoScroll: true}]

      },

      
      //Nested layouts

      {title: 'Nested Layout',

       layout: 'border',

       border: false,

       items: [{region: 'north',

          height: 100,

          split: true,

          html: 'Nested North'

          },

          {region: 'center',

           html: 'Nested Center'

          }]

      }]

      },

      {region: 'east',

      xtype: 'panel',

      split: true,

      title: 'genre information form',

      //open/close panel

      collapsible: true,

      width: 200,

      //html: 'East',

      //指定Div id

      items:[{id: 'EastPanel01'}]      

      },

      {region: 'south',

      xtype: 'panel',

      html: 'South'}]

   });

   //需在gridPanel建立後才可以Load資料

   store.load({params:{start:0, limit:5}});   

  });  

 //-->

 </script>

  </head>  

  <body>



  </body>

</html>

二、測試結果:
1.http://localhost:8080/ExtStudy/Basic/layout7.jsp





實作Ext Layout(五)

接續Ext Layout(一)功能,此練習主要是於Layout(border)西邊加入一個Form(movie_form)。

開發環境:
IDE:MyEclipse6.6GA
Web Server:Tomcat 6.0.20
Database:MySql 5.1.36
MVC:Struts2.1.8
FrameWork:Spring2.0,Hibernate3.2
Client UI:Ext2.3.0

一、Layout頁面(layout6.jsp):
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <base href="<%=basePath%>">

    

    <title>My JSP 'combox.jsp' starting page</title>

    

 <meta http-equiv="pragma" content="no-cache">

 <meta http-equiv="cache-control" content="no-cache">

 <meta http-equiv="expires" content="0">    

 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

 <meta http-equiv="description" content="This is my page">

 <!--

 <link rel="stylesheet" type="text/css" href="styles.css">

 -->

 <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">

 <link rel="stylesheet" type="text/css" href="css/onReady.css">

 <script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>

 <script type="text/javascript" src="extjs/ext-all.js"></script>

 <script type="text/javascript" src="extjs/ext-lang-zh_TW.js"></script> 

 <script type="text/javascript">

 <!--

  Ext.onReady(function(){

   Ext.BLANK_IMAGE_URL='extjs/resources/images/default/s.gif';

   /* normal store

   var store = new Ext.data.Store({

    url: 'SysMgrJson!getMovies.action',

    reader: new Ext.data.JsonReader({root:'results',totalProperty:'totals'}, [

     'id',

     'coverthumb',

     'title',

     'director',

     {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

     'genre',

     'tagline',

     {name: 'price', type: 'float'},

     {name: 'active'}

    ])

   });

   */

   //Grouping store

   var store = new Ext.data.GroupingStore({

    url: 'SysMgrJson!getMovies.action',

    sortInfo: {

     field: 'genre',

     direction: "ASC"

    },

    groupField: 'genre',

    reader: new Ext.data.JsonReader({root:'results',totalProperty:'totals'}, [

     'id',

     'coverthumb',

     'title',

     'director',

     {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

     'genre',

     'tagline',

     {name: 'price', type: 'float'},

     {name: 'active'}

    ])

   });

      

   var genres = new Ext.data.Store({

    data: [

     [1,"Comedy"],

     [2,"Drama"],

     [3,"Action"],

     [4,"Mystery"]    

    ],

    reader: new Ext.data.ArrayReader({id:'id'}, [

     'id',

     'genre'])

   }); 

        

   //Combining two columns function

   function title_tagline(val, x, store){

    return '<b>'+val+'</b><br>'+store.data.tagline;

   }

   //Generating HTML and graphics

   function cover_image(val){

    return '<img src="images/'+val+'.jpg" width="50%" height="50%">';

   }

   //for edit field of grid

   var title_edit = new Ext.form.TextField();

   var director_edit = new Ext.form.TextField();

   var tagline_edit = new Ext.form.TextField({

    maxLength: 45

   });

   var price_edit = new Ext.form.TextField();

   var coverthumb_edit = new Ext.form.TextField();

   var released_edit = new Ext.form.DateField();

   var genre_edit = new Ext.form.ComboBox({

    typeAhead: true,

    triggerAction: 'all',

    mode: 'local',

    store: genres,

    displayField:'genre',

    valueField: 'genre'

   });

   

   //for add row to grid

   var ds_model = Ext.data.Record.create([

    'id',  

    'title',

    'director',

    {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

    'genre',

    'tagline',

    'coverthumb',

    {name: 'price', type: 'float'},

    {name: 'active'}

   ]);      

   // add your data store here

   var grid = new Ext.grid.EditorGridPanel({

    //renderTo: document.body,

    //renderTo:'example-grid',

    frame:true,

    title: 'Movie Database',

    height:300,

    width:550,

    stripeRows:true,

    store: store,

    //matching Grouping store    

    view: new Ext.grid.GroupingView(),

    //增加grid event for Row Selection mode

    sm: new Ext.grid.RowSelectionModel({

     //singleSelect: true,

     listeners: {

      rowselect: {

       fn: function(sm,index,record) {

        index++;

        Ext.Msg.alert('提示','您選擇了,'+record.data.title+',第 '+index+'筆資料');

       }

      }

     }

    }),

    //Altering the grid at the click of a button 

    tbar: [

     //modify title column of grid

     {

      text: '修改 Title',

      handler: function(){

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        var sel = sm.getSelected();

        Ext.Msg.show({

         title: '修改 Title',

         prompt: true,

         buttons: Ext.MessageBox.OKCANCEL,

         value: sel.data.title,

         fn: function(btn,text){

          if (btn == 'ok'){

           sel.set('title', text);

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲修改Title之列');

       }

      }

     },

     //hidden price column of grid

     {

      text: 'Hide Price',

      handler: function(btn){

       var cm = grid.getColumnModel();

       var pi = cm.getIndexById('price');

       //var pi=5;

       if (cm.isHidden(pi)){

        cm.setHidden(pi,false);

        btn.setText('Hide Price');

       }else{

        cm.setHidden(pi,true);

        btn.setText('Show Price');

       }

       btn.render();

      }

     },

     //add first row to grid

     {

      text: 'Add Movie(First)',

      icon: 'images/RowInsert.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       grid.getStore().insert(0,new ds_model({

        id:'',

        title:'New Movie',

        director:'',

        genre:'Comedy',

        tagline:'',

        active:'1'

        })

       );

       grid.startEditing(0,0);

      }

     },

     //add last row to grid

     {

      text: 'Add Movie(Last)',

      icon: 'images/RowInsert.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       grid.getStore().insert(grid.getStore().getCount(),new ds_model({

        id:'',

        title:'New Movie',

        director:'',

        genre:'Comedy',

        tagline:'',

        active:'1'

        })

       );

       grid.startEditing(grid.getStore().getCount()-1,0);

      }

     },

     //Deleting data from the server

     {

      text: 'Remove Movie',

      icon: 'images/RowDelete.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        //var sel = sm.getSelected();

        var sels = sm.getSelections();

        var len = sels.length;

        var ids = new Array(len);

        for(var i=0;i<len;i++){

         ids[i] = sels[i].data.id;

         if(i==0){

          var msgs = '刪除: '+sels[i].data.title;

         }else{

          msgs = msgs +',\n'+sels[i].data.title; 

         }

        };

        Ext.Msg.show({

        title: '刪除電影',

         buttons: Ext.MessageBox.YESNOCANCEL,

         msg: msgs,

         fn: function(btn){

          if (btn == 'yes'){

           var conn = new Ext.data.Connection();

           conn.request({

            url: 'SysMgrJson!updateMovies.action',

            method:'post',

            params: {

             action: 'delete',

             id: ids

            },

            success: function(resp,opt) {

             //grid.getStore().remove(sel);

             grid.getStore().reload();

            },

            failure: function(resp,opt) {

             Ext.Msg.alert('Error',

             'Unable to delete movie');

            }

           });

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲刪除(多)列之資料');

       }

      }

      },

     //Saving data to the server

     {

      text: 'Save Movie',

      icon: 'images/save-icon.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        var sels = sm.getSelections();

        var len = sels.length;

        var values = new Array(len);

        for(var i=0;i<len;i++){

         values[i] = new Array(9);

         values[i][0] = sels[i].data.id;

         values[i][1] = sels[i].data.title;

         values[i][2] = sels[i].data.director;

         values[i][3] = (sels[i].data.released).format('Y-m-d');

         values[i][4] = sels[i].data.genre;

         values[i][5] = sels[i].data.tagline;

         values[i][6] = sels[i].data.coverthumb;

         values[i][7] = sels[i].data.price;

         values[i][8] = sels[i].data.active;

         if(i==0){

          var msgs = '儲存: '+sels[i].data.title;

         }else{

          msgs = msgs +',\n'+sels[i].data.title; 

         }

        };

        Ext.Msg.show({

        title: '儲存電影',

         buttons: Ext.MessageBox.YESNOCANCEL,

         msg: msgs,

         fn: function(btn){

          if (btn == 'yes'){

           var conn = new Ext.data.Connection();

           conn.request({

            url: 'SysMgrJson!updateMovies.action',

            method:'post',

            params: {

             action: 'update',

             values: values

            },

            success: function(resp,opt) {

             //grid.getStore().remove(sel);

             grid.getStore().reload();

            },

            failure: function(resp,opt) {

             Ext.Msg.alert('Error',

             'Unable to save movie');

            }

           });

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲儲存(多)列之資料');

       }

      }

      }             

    ],

          bbar: new Ext.PagingToolbar({

              pageSize: 5,

              store: store,

              displayInfo: true,

              displayMsg: '第 {0} 筆 - {1} 筆 of {2} 筆',

              emptyMsg: "沒有資料"

          }),       

    //Defining a Grids column model and want to display column

    columns: [

    {header: "Cover", dataIndex: 'coverthumb',renderer:cover_image},

    {header: "CoverThumb", dataIndex: 'coverthumb',editor:coverthumb_edit},

    //Combining two columns

    {header: "Title", dataIndex: 'title',renderer:title_tagline,editor:title_edit},

    {header: "Director", dataIndex: 'director',editor:director_edit},

    //Client-side sorting

    {header: "Released", dataIndex: 'released',sortable:true,

    renderer: Ext.util.Format.dateRenderer('m/d/Y'),editor:released_edit},

    {header: "Genre", dataIndex: 'genre',editor:genre_edit},    

    {header: "Price",dataIndex: 'price',id:'price',editor:price_edit},

    //setup hidden column

    {header: "Tagline", dataIndex: 'tagline',hidden:true,editor:tagline_edit}

    ]

   });

   

   //Load content on menu item click

   var Movies = function() {

    return {

     showHelp : function(btn){

      var helpbody = Ext.get('EastPanel01');

      if (!helpbody) {

       Ext.DomHelper.append(Ext.getBody(),{

        tag:'div',

        id:'EastPanel01'

        });

      }

      Movies.doLoad(btn.helpfile);

     },

     doLoad : function(file){

      Ext.get('EastPanel01').load({

       url: 'html/' + file + '.txt'

      });

     }

    };

   }();

   //create myToolBar

   var myToolBar = new Ext.Toolbar({

    //renderTo:document.body,

    items:[{xtype:'tbbutton',

         text:'Button',

         //加入Icon

         cls:'x-btn-text-icon',

         icon:'images/forumlink.gif',

         //加入按鈕事件

         handler:function(){Ext.Msg.alert('按我','您按到我了!');}},

        {xtype:'tbbutton',

         text:'Menu Button',

         //加入群組及checked default value

      menu:[{text:'Better',

            checked:true,

            group:'quality'},

         {text:'Good',

            checked:false,

            group:'quality'},

         {text:'Best',

            checked:false,

            group:'quality'}]},

        {xtype:'tbsplit',

      text:'Split Button',

      menu:[{text:'Item One'},

         {text:'Item Two'},

         {text:'Item Three'}]

        },

        {xtype:'tbsplit',

         text:'Help',

         menu:[{text:'Genre',

             helpfile:'genre',

             handler:Movies.showHelp},

            {text:'Director',

             helpfile:'director',

             handler:Movies.showHelp},

            {text:'Title',

             helpfile:'title',

             handler:Movies.showHelp}]}

       ]

   });

   

   var genre = new Ext.form.ComboBox({

    typeAhead: true,

    triggerAction: 'all',

    mode: 'local',

    store: genres,

    fieldLabel:'Genre',

    displayField:'genre',

    valueField: 'genre',

    hiddenName: 'genre',

    width:80

   });

      

   
   //create movie form

   var movie_form = new Ext.form.FormPanel({

    frame:true,

    title:'Movie information form',

    labelAlign:'left',

    items:[{xtype:'textfield',fieldLabel:'Title',name:'title',allowBlank:false,maxLength:45,maxLengthText:45},

        {xtype:'textfield',fieldLabel:'Director',name:'director',allowBlank:false,maxLength:45,maxLengthText:45},

        {xtype:'textfield',fieldLabel:'Coverthumb',name:'coverthumb',maxLength:45},

        {xtype:'datefield',fieldLabel:'Released',name:'released',disabledDays:[0,6]},

        {xtype:'textfield',fieldLabel:'Price',name:'price',maxLength:45},

        {xtype:'checkbox',fieldLabel:'Available?',name:'active'},

        genre,

        {xtype:'textarea',fieldLabel:'Tagline',name:'tagline'} 

    ],

    buttons: [

     {text: 'Save',

      handler: function(){

       var values = new Array(1);

       values[0] = new Array(9);

       var bf = movie_form.getForm();

       values[0][0] = '';//id

       values[0][1] = bf.findField('title').getValue();//title

       values[0][2] = bf.findField('director').getValue();//director

       values[0][3] = (bf.findField('released').getValue()).format('Y-m-d');//released

       values[0][4] = bf.findField('genre').getValue();//genre

       values[0][5] = bf.findField('tagline').getValue();//tagline

       values[0][6] = bf.findField('coverthumb').getValue();//coverthumb

       values[0][7] = bf.findField('price').getValue();//price

       values[0][8] = (bf.findField('active').getValue()==true)?'1':'0';//active      

       movie_form.getForm().submit({

        url:'SysMgrJson!updateMovies.action',

        method:'post',     

        params:{action: 'update', values:values},

        success: function(f,a){

         grid.getStore().reload();

         Ext.Msg.alert('Success', 'It worked');

        },

        failure: function(f,a){

         Ext.Msg.alert('Warning', 'Error');

        }

       });

      }

     }, 

     {text: 'Reset',

      handler: function(){

       movie_form.getForm().reset();

      }

     }]

   }); 

          

   var viewport = new Ext.Viewport({

    layout: 'border',

    renderTo: Ext.getBody(),    

    items: [{region: 'north',

      xtype: 'toolbar',

      items:[myToolBar]},

      {region: 'west',

      //xtype: 'panel',

      split: true,

      //open/close panel

      collapsible: true,

      collapseMode: 'mini',

      title: 'Some Info',

      bodyStyle:'padding:5px;',

      width: 250,

      minSize: 200,

      
      items:movie_form},

      {region: 'center',

      //Adding a tab panel

      xtype: 'tabpanel',

      activeTab: 0,

      items: [

      //add grid into tabpanel

      grid,

      //layout accordion into tabpanel

      {title: 'Movie Descriptions',

       layout: 'accordion',       

       items: [{title: 'Bombay Summer',

          autoLoad: 'html/BombaySummer.html',

          autoScroll: true},

         {title: '紐約我愛你',

          autoLoad: 'html/NewYorkLove.html',

          autoScroll: true},

         {title: 'SHERLOCK HOLMES',

          autoLoad: 'html/SHERLOCKHOLMES.html',

          autoScroll: true},

         {title: 'Thirst',

          autoLoad: 'html/Thirst.html',

          autoScroll: true}]

      },

      {title: 'Movie Grid2',

       html:'Center2'}]

      },

      {region: 'east',

      xtype: 'panel',

      split: true,

      title: 'genre information form',

      //open/close panel

      collapsible: true,

      width: 200,

      //html: 'East',

      //指定Div id

      items:[{id: 'EastPanel01'}]      

      },

      {region: 'south',

      xtype: 'panel',

      html: 'South'}]

   });

   //需在gridPanel建立後才可以Load資料

   store.load({params:{start:0, limit:5}});   

  });  

 //-->

 </script>

  </head>  

  <body>



  </body>

</html>

二、測試結果:
1.http://localhost:8080/ExtStudy/Basic/layout6.jsp








2009年12月21日 星期一

實作Ext Layout(四)


接續Ext Layout(一)功能,於Tab Panel上再增加一個Grid。
此作法是先建立一個Grid(注意請不要指定renderTo 屬性值),再建立一個viewport(Border Layout)後,再於viewport之中間區域之Tab panel上加入先前建立之Grid。之後於第二個Tab加入accordion layout。當作電影說明使用。

此練習主要是於Layout(border)北邊加入一個Toolbar。當點選Help選單並點選Genre後,則會到Server Side Load genre.txt到東邊的Panel(EastPanel01)

開發環境:
IDE:MyEclipse6.6GA
Web Server:Tomcat 6.0.20
Database:MySql 5.1.36
MVC:Struts2.1.8
FrameWork:Spring2.0,Hibernate3.2
Client UI:Ext2.3.0

一、Layout頁面(layout5.jsp):
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <base href="<%=basePath%>">

    

    <title>My JSP 'combox.jsp' starting page</title>

    

 <meta http-equiv="pragma" content="no-cache">

 <meta http-equiv="cache-control" content="no-cache">

 <meta http-equiv="expires" content="0">    

 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

 <meta http-equiv="description" content="This is my page">

 <!--

 <link rel="stylesheet" type="text/css" href="styles.css">

 -->

 <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">

 <link rel="stylesheet" type="text/css" href="css/onReady.css">

 <script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>

 <script type="text/javascript" src="extjs/ext-all.js"></script>

 <script type="text/javascript" src="extjs/ext-lang-zh_TW.js"></script> 

 <script type="text/javascript">

 <!--

  Ext.onReady(function(){

   Ext.BLANK_IMAGE_URL='extjs/resources/images/default/s.gif';

   /* normal store

   var store = new Ext.data.Store({

    url: 'SysMgrJson!getMovies.action',

    reader: new Ext.data.JsonReader({root:'results',totalProperty:'totals'}, [

     'id',

     'coverthumb',

     'title',

     'director',

     {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

     'genre',

     'tagline',

     {name: 'price', type: 'float'},

     {name: 'active'}

    ])

   });

   */

   //Grouping store

   var store = new Ext.data.GroupingStore({

    url: 'SysMgrJson!getMovies.action',

    sortInfo: {

     field: 'genre',

     direction: "ASC"

    },

    groupField: 'genre',

    reader: new Ext.data.JsonReader({root:'results',totalProperty:'totals'}, [

     'id',

     'coverthumb',

     'title',

     'director',

     {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

     'genre',

     'tagline',

     {name: 'price', type: 'float'},

     {name: 'active'}

    ])

   });

      

   var genres = new Ext.data.Store({

    data: [

     [1,"Comedy"],

     [2,"Drama"],

     [3,"Action"],

     [4,"Mystery"]    

    ],

    reader: new Ext.data.ArrayReader({id:'id'}, [

     'id',

     'genre'])

   }); 

        

   //Combining two columns function

   function title_tagline(val, x, store){

    return '<b>'+val+'</b><br>'+store.data.tagline;

   }

   //Generating HTML and graphics

   function cover_image(val){

    return '<img src="images/'+val+'.jpg" width="50%" height="50%">';

   }

   //for edit field of grid

   var title_edit = new Ext.form.TextField();

   var director_edit = new Ext.form.TextField();

   var tagline_edit = new Ext.form.TextField({

    maxLength: 45

   });

   var price_edit = new Ext.form.TextField();

   var coverthumb_edit = new Ext.form.TextField();

   var released_edit = new Ext.form.DateField();

   var genre_edit = new Ext.form.ComboBox({

    typeAhead: true,

    triggerAction: 'all',

    mode: 'local',

    store: genres,

    displayField:'genre',

    valueField: 'genre'

   });

   

   //for add row to grid

   var ds_model = Ext.data.Record.create([

    'id',  

    'title',

    'director',

    {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

    'genre',

    'tagline',

    'coverthumb',

    {name: 'price', type: 'float'},

    {name: 'active'}

   ]);      

   // add your data store here

   var grid = new Ext.grid.EditorGridPanel({

    //renderTo: document.body,

    //renderTo:'example-grid',

    frame:true,

    title: 'Movie Database',

    height:300,

    width:550,

    stripeRows:true,

    store: store,

    //matching Grouping store    

    view: new Ext.grid.GroupingView(),

    //增加grid event for Row Selection mode

    sm: new Ext.grid.RowSelectionModel({

     //singleSelect: true,

     listeners: {

      rowselect: {

       fn: function(sm,index,record) {

        index++;

        Ext.Msg.alert('提示','您選擇了,'+record.data.title+',第 '+index+'筆資料');

       }

      }

     }

    }),

    //Altering the grid at the click of a button 

    tbar: [

     //modify title column of grid

     {

      text: '修改 Title',

      handler: function(){

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        var sel = sm.getSelected();

        Ext.Msg.show({

         title: '修改 Title',

         prompt: true,

         buttons: Ext.MessageBox.OKCANCEL,

         value: sel.data.title,

         fn: function(btn,text){

          if (btn == 'ok'){

           sel.set('title', text);

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲修改Title之列');

       }

      }

     },

     //hidden price column of grid

     {

      text: 'Hide Price',

      handler: function(btn){

       var cm = grid.getColumnModel();

       var pi = cm.getIndexById('price');

       //var pi=5;

       if (cm.isHidden(pi)){

        cm.setHidden(pi,false);

        btn.setText('Hide Price');

       }else{

        cm.setHidden(pi,true);

        btn.setText('Show Price');

       }

       btn.render();

      }

     },

     //add first row to grid

     {

      text: 'Add Movie(First)',

      icon: 'images/RowInsert.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       grid.getStore().insert(0,new ds_model({

        id:'',

        title:'New Movie',

        director:'',

        genre:'Comedy',

        tagline:'',

        active:'1'

        })

       );

       grid.startEditing(0,0);

      }

     },

     //add last row to grid

     {

      text: 'Add Movie(Last)',

      icon: 'images/RowInsert.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       grid.getStore().insert(grid.getStore().getCount(),new ds_model({

        id:'',

        title:'New Movie',

        director:'',

        genre:'Comedy',

        tagline:'',

        active:'1'

        })

       );

       grid.startEditing(grid.getStore().getCount()-1,0);

      }

     },

     //Deleting data from the server

     {

      text: 'Remove Movie',

      icon: 'images/RowDelete.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        //var sel = sm.getSelected();

        var sels = sm.getSelections();

        var len = sels.length;

        var ids = new Array(len);

        for(var i=0;i<len;i++){

         ids[i] = sels[i].data.id;

         if(i==0){

          var msgs = '刪除: '+sels[i].data.title;

         }else{

          msgs = msgs +',\n'+sels[i].data.title; 

         }

        };

        Ext.Msg.show({

        title: '刪除電影',

         buttons: Ext.MessageBox.YESNOCANCEL,

         msg: msgs,

         fn: function(btn){

          if (btn == 'yes'){

           var conn = new Ext.data.Connection();

           conn.request({

            url: 'SysMgrJson!updateMovies.action',

            method:'post',

            params: {

             action: 'delete',

             id: ids

            },

            success: function(resp,opt) {

             //grid.getStore().remove(sel);

             grid.getStore().reload();

            },

            failure: function(resp,opt) {

             Ext.Msg.alert('Error',

             'Unable to delete movie');

            }

           });

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲刪除(多)列之資料');

       }

      }

      },

     //Saving data to the server

     {

      text: 'Save Movie',

      icon: 'images/save-icon.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        var sels = sm.getSelections();

        var len = sels.length;

        var values = new Array(len);

        for(var i=0;i<len;i++){

         values[i] = new Array(9);

         values[i][0] = sels[i].data.id;

         values[i][1] = sels[i].data.title;

         values[i][2] = sels[i].data.director;

         values[i][3] = (sels[i].data.released).format('Y-m-d');

         values[i][4] = sels[i].data.genre;

         values[i][5] = sels[i].data.tagline;

         values[i][6] = sels[i].data.coverthumb;

         values[i][7] = sels[i].data.price;

         values[i][8] = sels[i].data.active;

         if(i==0){

          var msgs = '儲存: '+sels[i].data.title;

         }else{

          msgs = msgs +',\n'+sels[i].data.title; 

         }

        };

        Ext.Msg.show({

        title: '儲存電影',

         buttons: Ext.MessageBox.YESNOCANCEL,

         msg: msgs,

         fn: function(btn){

          if (btn == 'yes'){

           var conn = new Ext.data.Connection();

           conn.request({

            url: 'SysMgrJson!updateMovies.action',

            method:'post',

            params: {

             action: 'update',

             values: values

            },

            success: function(resp,opt) {

             //grid.getStore().remove(sel);

             grid.getStore().reload();

            },

            failure: function(resp,opt) {

             Ext.Msg.alert('Error',

             'Unable to save movie');

            }

           });

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲儲存(多)列之資料');

       }

      }

      }             

    ],

          bbar: new Ext.PagingToolbar({

              pageSize: 5,

              store: store,

              displayInfo: true,

              displayMsg: '第 {0} 筆 - {1} 筆 of {2} 筆',

              emptyMsg: "沒有資料"

          }),       

    //Defining a Grids column model and want to display column

    columns: [

    {header: "Cover", dataIndex: 'coverthumb',renderer:cover_image},

    {header: "CoverThumb", dataIndex: 'coverthumb',editor:coverthumb_edit},

    //Combining two columns

    {header: "Title", dataIndex: 'title',renderer:title_tagline,editor:title_edit},

    {header: "Director", dataIndex: 'director',editor:director_edit},

    //Client-side sorting

    {header: "Released", dataIndex: 'released',sortable:true,

    renderer: Ext.util.Format.dateRenderer('m/d/Y'),editor:released_edit},

    {header: "Genre", dataIndex: 'genre',editor:genre_edit},    

    {header: "Price",dataIndex: 'price',id:'price',editor:price_edit},

    //setup hidden column

    {header: "Tagline", dataIndex: 'tagline',hidden:true,editor:tagline_edit}

    ]

   });

   

    
   //Load content on menu item click

   var Movies = function() {

    return {

     showHelp : function(btn){

      var helpbody = Ext.get('EastPanel01');

      if (!helpbody) {

       Ext.DomHelper.append(Ext.getBody(),{

        tag:'div',

        id:'EastPanel01'

        });

      }

      Movies.doLoad(btn.helpfile);

     },

     doLoad : function(file){

      Ext.get('EastPanel01').load({

       url: 'html/' + file + '.txt'

      });

     }

    };

   }();

   //create myToolBar

   var myToolBar = new Ext.Toolbar({

    //renderTo:document.body,

    items:[{xtype:'tbbutton',

         text:'Button',

         //加入Icon

         cls:'x-btn-text-icon',

         icon:'images/forumlink.gif',

         //加入按鈕事件

         handler:function(){Ext.Msg.alert('按我','您按到我了!');}},

        {xtype:'tbbutton',

         text:'Menu Button',

         //加入群組及checked default value

      menu:[{text:'Better',

            checked:true,

            group:'quality'},

         {text:'Good',

            checked:false,

            group:'quality'},

         {text:'Best',

            checked:false,

            group:'quality'}]},

        {xtype:'tbsplit',

      text:'Split Button',

      menu:[{text:'Item One'},

         {text:'Item Two'},

         {text:'Item Three'}]

        },

        {xtype:'tbsplit',

         text:'Help',

         menu:[{text:'Genre',

             helpfile:'genre',

             handler:Movies.showHelp},

            {text:'Director',

             helpfile:'director',

             handler:Movies.showHelp},

            {text:'Title',

             helpfile:'title',

             handler:Movies.showHelp}]}

       ]

   });

       
   var viewport = new Ext.Viewport({

    layout: 'border',

    renderTo: Ext.getBody(),    

    items: [{region: 'north',

        
      xtype: 'toolbar',

      items:[myToolBar]},

      
      {region: 'west',

      xtype: 'panel',

      split: true,

      //open/close panel

      collapsible: true,

      collapseMode: 'mini',

      title: 'Some Info',

      bodyStyle:'padding:5px;',

      width: 200,

      minSize: 200,

      html: 'West'},

      {region: 'center',

      //Adding a tab panel

      xtype: 'tabpanel',

      activeTab: 0,

      items: [

      //add grid into tabpanel

      grid,

      //layout accordion into tabpanel

      {title: 'Movie Descriptions',

       layout: 'accordion',       

       items: [{title: 'Bombay Summer',

          autoLoad: 'html/BombaySummer.html',

          autoScroll: true},

         {title: '紐約我愛你',

          autoLoad: 'html/NewYorkLove.html',

          autoScroll: true},

         {title: 'SHERLOCK HOLMES',

          autoLoad: 'html/SHERLOCKHOLMES.html',

          autoScroll: true},

         {title: 'Thirst',

          autoLoad: 'html/Thirst.html',

          autoScroll: true}]

      },

      {title: 'Movie Grid2',

       html:'Center2'}]

      },

      {region: 'east',

      xtype: 'panel',

      split: true,

      title: 'genre information form',

      //open/close panel

      collapsible: true,

      width: 200,

      html: 'East',

      //指定Div id
      items:[{id: 'EastPanel01'}]
 
      },

      {region: 'south',

      xtype: 'panel',

      html: 'South'}]

   });

   //需在gridPanel建立後才可以Load資料

   store.load({params:{start:0, limit:5}});   

  });  

 //-->

 </script>

  </head>

  

  <body>

  </body>

</html>


二、測試結果:
1.http://localhost:8080/ExtStudy/Basic/layout5.jsp






實作Ext Layout(三)


接續Ext Layout(一)功能,於Tab Panel上再增加一個Grid。
此作法是先建立一個Grid(注意請不要指定renderTo 屬性值),再建立一個viewport(Border Layout)後,再於viewport之中間區域之Tab panel上加入先前建立之Grid。之後於第二個Tab加入accordion layout。當作電影說明使用。


開發環境:
IDE:MyEclipse6.6GA
Web Server:Tomcat 6.0.20
Database:MySql 5.1.36
MVC:Struts2.1.8
FrameWork:Spring2.0,Hibernate3.2
Client UI:Ext2.3.0

一、Layout頁面(layout4.jsp):

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%

String path = request.getContextPath();

String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <base href="<%=basePath%>">

    

    <title>My JSP 'combox.jsp' starting page</title>

    

 <meta http-equiv="pragma" content="no-cache">

 <meta http-equiv="cache-control" content="no-cache">

 <meta http-equiv="expires" content="0">    

 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

 <meta http-equiv="description" content="This is my page">

 <!--

 <link rel="stylesheet" type="text/css" href="styles.css">

 -->

 <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">

 <link rel="stylesheet" type="text/css" href="css/onReady.css">

 <script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>

 <script type="text/javascript" src="extjs/ext-all.js"></script>

 <script type="text/javascript" src="extjs/ext-lang-zh_TW.js"></script> 

 <script type="text/javascript">

 <!--

  Ext.onReady(function(){

   Ext.BLANK_IMAGE_URL='extjs/resources/images/default/s.gif';

   /* normal store

   var store = new Ext.data.Store({

    url: 'SysMgrJson!getMovies.action',

    reader: new Ext.data.JsonReader({root:'results',totalProperty:'totals'}, [

     'id',

     'coverthumb',

     'title',

     'director',

     {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

     'genre',

     'tagline',

     {name: 'price', type: 'float'},

     {name: 'active'}

    ])

   });

   */

   //Grouping store

   var store = new Ext.data.GroupingStore({

    url: 'SysMgrJson!getMovies.action',

    sortInfo: {

     field: 'genre',

     direction: "ASC"

    },

    groupField: 'genre',

    reader: new Ext.data.JsonReader({root:'results',totalProperty:'totals'}, [

     'id',

     'coverthumb',

     'title',

     'director',

     {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

     'genre',

     'tagline',

     {name: 'price', type: 'float'},

     {name: 'active'}

    ])

   });

      

   var genres = new Ext.data.Store({

    data: [

     [1,"Comedy"],

     [2,"Drama"],

     [3,"Action"],

     [4,"Mystery"]    

    ],

    reader: new Ext.data.ArrayReader({id:'id'}, [

     'id',

     'genre'])

   }); 

        

   //Combining two columns function

   function title_tagline(val, x, store){

    return '<b>'+val+'</b><br>'+store.data.tagline;

   }

   //Generating HTML and graphics

   function cover_image(val){

    return '<img src="images/'+val+'.jpg" width="50%" height="50%">';

   }

   //for edit field of grid

   var title_edit = new Ext.form.TextField();

   var director_edit = new Ext.form.TextField();

   var tagline_edit = new Ext.form.TextField({

    maxLength: 45

   });

   var price_edit = new Ext.form.TextField();

   var coverthumb_edit = new Ext.form.TextField();

   var released_edit = new Ext.form.DateField();

   var genre_edit = new Ext.form.ComboBox({

    typeAhead: true,

    triggerAction: 'all',

    mode: 'local',

    store: genres,

    displayField:'genre',

    valueField: 'genre'

   });

   

   //for add row to grid

   var ds_model = Ext.data.Record.create([

    'id',  

    'title',

    'director',

    {name: 'released', type: 'date', dateFormat: 'Y-m-d'},

    'genre',

    'tagline',

    'coverthumb',

    {name: 'price', type: 'float'},

    {name: 'active'}

   ]);      

   // add your data store here

   var grid = new Ext.grid.EditorGridPanel({

    //renderTo: document.body,

    //renderTo:'example-grid',

    frame:true,

    title: 'Movie Database',

    height:300,

    width:550,

    stripeRows:true,

    store: store,

    //matching Grouping store    

    view: new Ext.grid.GroupingView(),

    //增加grid event for Row Selection mode

    sm: new Ext.grid.RowSelectionModel({

     //singleSelect: true,

     listeners: {

      rowselect: {

       fn: function(sm,index,record) {

        index++;

        Ext.Msg.alert('提示','您選擇了,'+record.data.title+',第 '+index+'筆資料');

       }

      }

     }

    }),

    //Altering the grid at the click of a button 

    tbar: [

     //modify title column of grid

     {

      text: '修改 Title',

      handler: function(){

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        var sel = sm.getSelected();

        Ext.Msg.show({

         title: '修改 Title',

         prompt: true,

         buttons: Ext.MessageBox.OKCANCEL,

         value: sel.data.title,

         fn: function(btn,text){

          if (btn == 'ok'){

           sel.set('title', text);

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲修改Title之列');

       }

      }

     },

     //hidden price column of grid

     {

      text: 'Hide Price',

      handler: function(btn){

       var cm = grid.getColumnModel();

       var pi = cm.getIndexById('price');

       //var pi=5;

       if (cm.isHidden(pi)){

        cm.setHidden(pi,false);

        btn.setText('Hide Price');

       }else{

        cm.setHidden(pi,true);

        btn.setText('Show Price');

       }

       btn.render();

      }

     },

     //add first row to grid

     {

      text: 'Add Movie(First)',

      icon: 'images/RowInsert.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       grid.getStore().insert(0,new ds_model({

        id:'',

        title:'New Movie',

        director:'',

        genre:'Comedy',

        tagline:'',

        active:'1'

        })

       );

       grid.startEditing(0,0);

      }

     },

     //add last row to grid

     {

      text: 'Add Movie(Last)',

      icon: 'images/RowInsert.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       grid.getStore().insert(grid.getStore().getCount(),new ds_model({

        id:'',

        title:'New Movie',

        director:'',

        genre:'Comedy',

        tagline:'',

        active:'1'

        })

       );

       grid.startEditing(grid.getStore().getCount()-1,0);

      }

     },

     //Deleting data from the server

     {

      text: 'Remove Movie',

      icon: 'images/RowDelete.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        //var sel = sm.getSelected();

        var sels = sm.getSelections();

        var len = sels.length;

        var ids = new Array(len);

        for(var i=0;i<len;i++){

         ids[i] = sels[i].data.id;

         if(i==0){

          var msgs = '刪除: '+sels[i].data.title;

         }else{

          msgs = msgs +',\n'+sels[i].data.title; 

         }

        };

        Ext.Msg.show({

        title: '刪除電影',

         buttons: Ext.MessageBox.YESNOCANCEL,

         msg: msgs,

         fn: function(btn){

          if (btn == 'yes'){

           var conn = new Ext.data.Connection();

           conn.request({

            url: 'SysMgrJson!updateMovies.action',

            method:'post',

            params: {

             action: 'delete',

             id: ids

            },

            success: function(resp,opt) {

             //grid.getStore().remove(sel);

             grid.getStore().reload();

            },

            failure: function(resp,opt) {

             Ext.Msg.alert('Error',

             'Unable to delete movie');

            }

           });

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲刪除(多)列之資料');

       }

      }

      },

     //Saving data to the server

     {

      text: 'Save Movie',

      icon: 'images/save-icon.png',

      cls: 'x-btn-text-icon',

      handler: function() {

       var sm = grid.getSelectionModel();

       if (sm.hasSelection()){

        var sels = sm.getSelections();

        var len = sels.length;

        var values = new Array(len);

        for(var i=0;i<len;i++){

         values[i] = new Array(9);

         values[i][0] = sels[i].data.id;

         values[i][1] = sels[i].data.title;

         values[i][2] = sels[i].data.director;

         values[i][3] = (sels[i].data.released).format('Y-m-d');

         values[i][4] = sels[i].data.genre;

         values[i][5] = sels[i].data.tagline;

         values[i][6] = sels[i].data.coverthumb;

         values[i][7] = sels[i].data.price;

         values[i][8] = sels[i].data.active;

         if(i==0){

          var msgs = '儲存: '+sels[i].data.title;

         }else{

          msgs = msgs +',\n'+sels[i].data.title; 

         }

        };

        Ext.Msg.show({

        title: '儲存電影',

         buttons: Ext.MessageBox.YESNOCANCEL,

         msg: msgs,

         fn: function(btn){

          if (btn == 'yes'){

           var conn = new Ext.data.Connection();

           conn.request({

            url: 'SysMgrJson!updateMovies.action',

            method:'post',

            params: {

             action: 'update',

             values: values

            },

            success: function(resp,opt) {

             //grid.getStore().remove(sel);

             grid.getStore().reload();

            },

            failure: function(resp,opt) {

             Ext.Msg.alert('Error',

             'Unable to save movie');

            }

           });

          }

         }

        });

       }else{

        Ext.Msg.alert('提示','請選擇欲儲存(多)列之資料');

       }

      }

      }             

    ],

          bbar: new Ext.PagingToolbar({

              pageSize: 5,

              store: store,

              displayInfo: true,

              displayMsg: '第 {0} 筆 - {1} 筆 of {2} 筆',

              emptyMsg: "沒有資料"

          }),       

    //Defining a Grids column model and want to display column

    columns: [

    {header: "Cover", dataIndex: 'coverthumb',renderer:cover_image},

    {header: "CoverThumb", dataIndex: 'coverthumb',editor:coverthumb_edit},

    //Combining two columns

    {header: "Title", dataIndex: 'title',renderer:title_tagline,editor:title_edit},

    {header: "Director", dataIndex: 'director',editor:director_edit},

    //Client-side sorting

    {header: "Released", dataIndex: 'released',sortable:true,

    renderer: Ext.util.Format.dateRenderer('m/d/Y'),editor:released_edit},

    {header: "Genre", dataIndex: 'genre',editor:genre_edit},    

    {header: "Price",dataIndex: 'price',id:'price',editor:price_edit},

    //setup hidden column

    {header: "Tagline", dataIndex: 'tagline',hidden:true,editor:tagline_edit}

    ]

   });   

   var viewport = new Ext.Viewport({

    layout: 'border',

    renderTo: Ext.getBody(),    

    items: [{region: 'north',

      xtype: 'panel',

      html: 'North'},

      {region: 'west',

      xtype: 'panel',

      split: true,

      //open/close panel

      collapsible: true,

      collapseMode: 'mini',

      title: 'Some Info',

      bodyStyle:'padding:5px;',

      width: 200,

      minSize: 200,

      html: 'West'},

      {region: 'center',

      //Adding a tab panel

      xtype: 'tabpanel',

      activeTab: 0,

      items: [

      //add grid into tabpanel

      grid,

      

      //layout accordion into tabpanel

      {title: 'Movie Descriptions',

       layout: 'accordion',       

       items: [{title: 'Bombay Summer',

          autoLoad: 'html/BombaySummer.html',

          autoScroll: true},

         {title: '紐約我愛你',

          autoLoad: 'html/NewYorkLove.html',

          autoScroll: true},

         {title: 'SHERLOCK HOLMES',

          autoLoad: 'html/SHERLOCKHOLMES.html',

          autoScroll: true},

         {title: 'Thirst',

          autoLoad: 'html/Thirst.html',

          autoScroll: true}]

      },

      

      {title: 'Movie Grid2',

       html:'Center2'}]

      },

      {region: 'east',

      xtype: 'panel',

      split: true,

      title: 'genre information form',

      //open/close panel

      collapsible: true,

      width: 200,

      html: 'East'

      },

      {region: 'south',

      xtype: 'panel',

      html: 'South'}]

   });

   //需在gridPanel建立後才可以Load資料

   store.load({params:{start:0, limit:5}});   

  });  

 //-->

 </script>

  </head>

  

  <body>

  </body>

</html>


二、準備電說說明檔(*.html):
1.BombaySummer.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>MyHtml.html</title>

 

    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

    <meta http-equiv="description" content="this is my page">

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    

    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->



  </head>

  

  <body>

    <pre>

媲美楚浮《夏日之戀》,今年最扣人心弦的愛情絮語



在命運面前,我們如何留住幸福?



孟買,寶萊塢的大本營,印度人的逐夢大城,三個截然不同的生命,在此交織出一段刻骨銘心的夏日之戀。現在,他們卻在永恆的交會點上,被未來遺忘……



熱愛當下的潔塔,凡事盡其在我,不錯過任何可能。她擁有一份令人欣羨的工作,還有個貴族男友傑迪。滿懷理想的傑迪,一心只想擺脫顯赫家世的庇陰,靠寫作闖出自己的名堂。表面看似完滿的一對情侶,其實內心空虛落寞。在一次工作機緣,兩人認識了進城打拼的藝術家馬登,其細膩獨到的視野深深觸動了潔塔和傑迪,激盪出前所未有的火花,命運也在此時出現劇烈轉變!案子短缺的馬登,為了寄錢養家,涉險從事非法交易,讓傑迪決心切割這段友誼;潔塔則在不自覺間,對馬登生出一份無法割捨的情懷。三人關係瞬間失衡,感情陷入僵局!



孟買的夏夜依舊閃爍,然而愛情的模樣,在情人的淚光中,卻漸漸模糊起來。



一段令人難忘的愛情



【孟買的夏戀】探討了三個年輕人短暫、微妙的友誼,在面對背叛和個人的損失後,最終解體。故事設置在當代印度,電影巧妙地反映了當印度社會的傳統約束,為了適應快速變遷的現代化所產生的混亂。



從人物背景看社會變遷



三人來自不同背景,但三人因為志趣而結為摯友。他們的生活互相交織成一篇動人的故事。導演將他們的,隨著他們自我探索的旅程,當馬登帶領他們到全新的未竟之地經歷了一些事情。最終他們的友誼受到了考驗,因為馬登的生活方式可能影響並吞沒他們。    

    </pre>

  </body>

</html>


2.NewYorkLove.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>MyHtml.html</title>

 

    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

    <meta http-equiv="description" content="this is my page">

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    

    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->



  </head>

  

  <body>

    <pre>

★多位國際級導演合力創作愛情浪漫劇作

★網羅好萊塢影帝/影后、最受矚目的新生代演員一同演出

★娜塔莉波曼首部執導作品



紐約,不夜城,摩天大樓林立,獨特的人物穿梭其中,愛情發生在屋頂上、地鐵站、街角的咖啡店…,從初戀、短暫的愛到值得珍藏的愛,從被拒絕的愛、渴望被愛到永遠不變的愛,十一位國際級導演用他們獨特的角度和鏡頭來詮釋對紐感的感受、愛情及生命的真諦。電影由眾多好萊塢巨星參與,包括娜塔莉波曼、奧蘭多布魯、伊森霍克、安迪賈西亞、舒淇、Maggie Q…主演,世界各地滿懷熱情的導演們攜手呈現。它描繪的不只是這座城市,還有城市裡每一個人對愛情最深刻的渴望。



自電影問世以來,紐約便一直是電影工業心中的夢幻城市--這裡滿是獨一無二的人物、高聳直入雲霄的摩天大樓、它蓬勃的非主流文化與發生在屋頂上的愛情故事,為各式各樣的動作片、喜劇片、劇情片與詩篇,提供完美的故事背景。這座城市在大銀幕上被成千上百的電影以不同方式化為永恆。如今,出現這麼一個清新、多元且毫不扭捏的浪漫新視野,將完全透過愛的眼神看這座城市--各式各樣的愛,從初戀、嚴苛的愛、短暫的愛到值得珍藏的愛、被拒絕的愛、渴望被愛到永遠不變的愛,由來自世界各地、年輕且滿懷熱情的導演們攜手呈現。



在鑽石區裡,一場跨越文化的浪漫奇想,讓一場追逐轉變地如寶石般光彩奪目;同時在中國城,一名絕望的藝術家追逐著非自願的繆斯女神身影;上東城的飯店內,優雅世故的房客,與神秘的大廳服務生踏上超越時間的旅程;在中央公園裡始料未及的一夜過後,一名年輕人的畢業舞會舞伴,將揭露驚人的事實;兩名愛侶搭乘計程車、地鐵然後步行到格林威治村,在他們認定彼此有過一夜情後,首度相見;在翠貝卡區,一名扒手盯上了一個誘惑人心的女孩,發現自己不再佔上風;在布魯克林區,一對八十幾歲的夫婦在柯尼島遊樂園裡,被喜樂的光景繚繞;這些故事與人物交織在一起,湊成一幅色彩光鮮與愛意十足的拼貼畫,它描繪的不只是這座城市,還有城市裡每一個人對於不可或缺的愛情與人與人的交集,最深刻的渴望。



故事大綱



自電影問世以來,紐約便一直是電影工業心中的夢幻城市--這裡滿是獨一無二的人物、高聳直入雲霄的摩天大樓、它蓬勃的非主流文化與發生在屋頂上的愛情故事,為各式各樣的動作片、喜劇片、劇情片與詩篇,提供完美的故事背景。這座城市在大銀幕上被成千上百的電影以不同方式化為永恆。如今,出現這麼一個清新、多元且毫不扭捏的浪漫新視野,將完全透過愛的眼神看這座城市--各式各樣的愛,從初戀、嚴苛的愛、短暫的愛到值得珍藏的愛、被拒絕的愛、渴望被愛到永遠不變的愛,由來自世界各地、年輕且滿懷熱情的導演們攜手呈現。



為本片掌鏡的是當今最富想像力且類型兼容並蓄的導演群,包括姜文、米拉奈兒(Mira Nair)、岩井俊二、伊凡艾塔(Yvan Attal)、布萊特雷納(Brett Ratner)、艾倫休斯(Allen Hughes)、夏克哈卡帕(Shekhar Khapur)、娜塔莉波曼(Natalie Portman)、法提阿金(Fatih Akin)、約夏馬斯頓(Joshua Marston)與藍帝柏斯梅耶(Randy Balsmeyer)。【紐約我愛你】邀請觀眾進入紐約客的私密生活,和他們一同努力面對、沈醉其中與眾裡尋他千百度的愛情。



在鑽石區裡,一場跨越文化的浪漫奇想,讓一場追逐轉變地如寶石般光彩奪目;同時在中國城,一名絕望的藝術家追逐著非自願的繆斯女神身影;上東城的飯店內,優雅世故的房客,與神秘的大廳服務生踏上超越時間的旅程;在中央公園裡始料未及的一夜過後,一名年輕人的畢業舞會舞伴,將揭露驚人的事實;兩名愛侶搭乘計程車、地鐵然後步行到格林威治村,在他們認定彼此有過一夜情後,首度相見;在翠貝卡區,一名扒手盯上了一個誘惑人心的女孩,發現自己不再佔上風;在布魯克林區,一對八十幾歲的夫婦在柯尼島遊樂園裡,被喜樂的光景繚繞;這些故事與人物交織在一起,湊成一幅色彩光鮮與愛意十足的拼貼畫,它描繪的不只是這座城市,還有城市裡每一個人對於不可或缺的愛情與人與人的交集,最深刻的渴望。



為本片裡每個令人難忘的紐約角色賦予生命的,是星光閃閃的一時之選,包括布萊德利古柏(Bradley Cooper)、賈斯汀巴薩(Justin Bartha)、安迪賈西亞(Andy Garcia)、海登克里斯坦森(Hayden Christensen)、瑞秋比爾森(Rachel Bilson)、娜塔莉波曼、伊凡卡漢(Irrfan Khan)、艾蜜莉歐哈納(Emilie Ohana)、奧蘭多布魯(Orlando Bloom)、克莉絲汀里奇(Christina Ricci)、Maggie Q、伊森霍克(Ethan Hawke)、安東葉爾欽(Anton Yelchin)、詹姆斯肯恩(James Caan)、奧莉薇瑟爾比(Olivia Thirlby)、布蕾克萊佛莉(Blake Lively)、德芮狄馬提歐(Drea de Matteo)、茱莉克莉絲蒂(Julie Christie)、約翰赫特(John Hurt)、西亞李畢福(Shia LaBeouf)、烏格郁索爾(Ugur Yucel)、泰勒吉爾(Taylor Geare)、卡洛斯阿柯斯塔(Carlos Acosta)、賈辛妲貝瑞特(Jacinda Barrett)、舒淇、柏特楊(Burt Young)、克里斯古柏(Chris Cooper)、蘿賓萊特潘(Robin Wright Penn)、伊娃安慕里(Eva Ammuri)、埃里瓦拉赫(Eli Wallach)與克蘿麗絲莉姬曼(Cloris Leachman)。



追隨著佳評如潮的【巴黎我愛你】腳步,本片是埃曼紐班畢伊(Emmanuel Benbihy)構想出的「愛情城市」系列組合式電影第二章,他與瑪莉娜葛萊斯(Marina Grasic,【衝擊效應】)擔任本片製片。



◎中文官方網站:http://www.wretch.cc/blog/nyiloveyou    

    </pre>

  </body>

</html>


3.SHERLOCKHOLMES.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>MyHtml.html</title>

 

    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

    <meta http-equiv="description" content="this is my page">

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    

    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->



  </head>

  

  <body>

    <pre>

★多位國際級導演合力創作愛情浪漫劇作

★網羅好萊塢影帝/影后、最受矚目的新生代演員一同演出

★娜塔莉波曼首部執導作品



紐約,不夜城,摩天大樓林立,獨特的人物穿梭其中,愛情發生在屋頂上、地鐵站、街角的咖啡店…,從初戀、短暫的愛到值得珍藏的愛,從被拒絕的愛、渴望被愛到永遠不變的愛,十一位國際級導演用他們獨特的角度和鏡頭來詮釋對紐感的感受、愛情及生命的真諦。電影由眾多好萊塢巨星參與,包括娜塔莉波曼、奧蘭多布魯、伊森霍克、安迪賈西亞、舒淇、Maggie Q…主演,世界各地滿懷熱情的導演們攜手呈現。它描繪的不只是這座城市,還有城市裡每一個人對愛情最深刻的渴望。



自電影問世以來,紐約便一直是電影工業心中的夢幻城市--這裡滿是獨一無二的人物、高聳直入雲霄的摩天大樓、它蓬勃的非主流文化與發生在屋頂上的愛情故事,為各式各樣的動作片、喜劇片、劇情片與詩篇,提供完美的故事背景。這座城市在大銀幕上被成千上百的電影以不同方式化為永恆。如今,出現這麼一個清新、多元且毫不扭捏的浪漫新視野,將完全透過愛的眼神看這座城市--各式各樣的愛,從初戀、嚴苛的愛、短暫的愛到值得珍藏的愛、被拒絕的愛、渴望被愛到永遠不變的愛,由來自世界各地、年輕且滿懷熱情的導演們攜手呈現。



在鑽石區裡,一場跨越文化的浪漫奇想,讓一場追逐轉變地如寶石般光彩奪目;同時在中國城,一名絕望的藝術家追逐著非自願的繆斯女神身影;上東城的飯店內,優雅世故的房客,與神秘的大廳服務生踏上超越時間的旅程;在中央公園裡始料未及的一夜過後,一名年輕人的畢業舞會舞伴,將揭露驚人的事實;兩名愛侶搭乘計程車、地鐵然後步行到格林威治村,在他們認定彼此有過一夜情後,首度相見;在翠貝卡區,一名扒手盯上了一個誘惑人心的女孩,發現自己不再佔上風;在布魯克林區,一對八十幾歲的夫婦在柯尼島遊樂園裡,被喜樂的光景繚繞;這些故事與人物交織在一起,湊成一幅色彩光鮮與愛意十足的拼貼畫,它描繪的不只是這座城市,還有城市裡每一個人對於不可或缺的愛情與人與人的交集,最深刻的渴望。



故事大綱



自電影問世以來,紐約便一直是電影工業心中的夢幻城市--這裡滿是獨一無二的人物、高聳直入雲霄的摩天大樓、它蓬勃的非主流文化與發生在屋頂上的愛情故事,為各式各樣的動作片、喜劇片、劇情片與詩篇,提供完美的故事背景。這座城市在大銀幕上被成千上百的電影以不同方式化為永恆。如今,出現這麼一個清新、多元且毫不扭捏的浪漫新視野,將完全透過愛的眼神看這座城市--各式各樣的愛,從初戀、嚴苛的愛、短暫的愛到值得珍藏的愛、被拒絕的愛、渴望被愛到永遠不變的愛,由來自世界各地、年輕且滿懷熱情的導演們攜手呈現。



為本片掌鏡的是當今最富想像力且類型兼容並蓄的導演群,包括姜文、米拉奈兒(Mira Nair)、岩井俊二、伊凡艾塔(Yvan Attal)、布萊特雷納(Brett Ratner)、艾倫休斯(Allen Hughes)、夏克哈卡帕(Shekhar Khapur)、娜塔莉波曼(Natalie Portman)、法提阿金(Fatih Akin)、約夏馬斯頓(Joshua Marston)與藍帝柏斯梅耶(Randy Balsmeyer)。【紐約我愛你】邀請觀眾進入紐約客的私密生活,和他們一同努力面對、沈醉其中與眾裡尋他千百度的愛情。



在鑽石區裡,一場跨越文化的浪漫奇想,讓一場追逐轉變地如寶石般光彩奪目;同時在中國城,一名絕望的藝術家追逐著非自願的繆斯女神身影;上東城的飯店內,優雅世故的房客,與神秘的大廳服務生踏上超越時間的旅程;在中央公園裡始料未及的一夜過後,一名年輕人的畢業舞會舞伴,將揭露驚人的事實;兩名愛侶搭乘計程車、地鐵然後步行到格林威治村,在他們認定彼此有過一夜情後,首度相見;在翠貝卡區,一名扒手盯上了一個誘惑人心的女孩,發現自己不再佔上風;在布魯克林區,一對八十幾歲的夫婦在柯尼島遊樂園裡,被喜樂的光景繚繞;這些故事與人物交織在一起,湊成一幅色彩光鮮與愛意十足的拼貼畫,它描繪的不只是這座城市,還有城市裡每一個人對於不可或缺的愛情與人與人的交集,最深刻的渴望。



為本片裡每個令人難忘的紐約角色賦予生命的,是星光閃閃的一時之選,包括布萊德利古柏(Bradley Cooper)、賈斯汀巴薩(Justin Bartha)、安迪賈西亞(Andy Garcia)、海登克里斯坦森(Hayden Christensen)、瑞秋比爾森(Rachel Bilson)、娜塔莉波曼、伊凡卡漢(Irrfan Khan)、艾蜜莉歐哈納(Emilie Ohana)、奧蘭多布魯(Orlando Bloom)、克莉絲汀里奇(Christina Ricci)、Maggie Q、伊森霍克(Ethan Hawke)、安東葉爾欽(Anton Yelchin)、詹姆斯肯恩(James Caan)、奧莉薇瑟爾比(Olivia Thirlby)、布蕾克萊佛莉(Blake Lively)、德芮狄馬提歐(Drea de Matteo)、茱莉克莉絲蒂(Julie Christie)、約翰赫特(John Hurt)、西亞李畢福(Shia LaBeouf)、烏格郁索爾(Ugur Yucel)、泰勒吉爾(Taylor Geare)、卡洛斯阿柯斯塔(Carlos Acosta)、賈辛妲貝瑞特(Jacinda Barrett)、舒淇、柏特楊(Burt Young)、克里斯古柏(Chris Cooper)、蘿賓萊特潘(Robin Wright Penn)、伊娃安慕里(Eva Ammuri)、埃里瓦拉赫(Eli Wallach)與克蘿麗絲莉姬曼(Cloris Leachman)。



追隨著佳評如潮的【巴黎我愛你】腳步,本片是埃曼紐班畢伊(Emmanuel Benbihy)構想出的「愛情城市」系列組合式電影第二章,他與瑪莉娜葛萊斯(Marina Grasic,【衝擊效應】)擔任本片製片。



◎中文官方網站:http://www.wretch.cc/blog/nyiloveyou    

    </pre>

  </body>

</html>


4.Thirst.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

  <head>

    <title>MyHtml.html</title>

 

    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">

    <meta http-equiv="description" content="this is my page">

    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    

    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->



  </head>

  

  <body>

    <pre>

篤信上帝的神父 一夕之間成吸血鬼…



為了上帝奉獻一切的神父(宋康昊飾),參加秘密進行的醫療實驗,試圖研發「夏娃」疫苗拯救人類。過程中神父意外感染猝死,血液裡的不名物體讓他奇蹟獲得重生,不僅開啟了靈魂的七情六慾,更成為了蝙蝠般的吸血鬼!神父需要足夠的鮮血維持性命,又不想抱持殺人的念頭,此時迷戀上散發神秘氣質的朋友之妻(金玉彬飾),他感受到前所未有的悸動。為了愛情,神父拋開神聖的外袍,如蝙蝠張開雙翼,迎向致命的愛…《原罪犯》朴贊郁罕見的恐怖奇幻作品,以荒謬淒美的黑色手法,再次探索信仰與渴望之間的慾望本質。



★危險、異色、陰暗、脆弱 慾念纏身、血性大發

★朴贊郁導演10年計畫,繼《原罪犯》獲坎城影展評審團大獎

★2009韓國春史大賞電影節雙冠 最佳導演、最佳男主角

★百變影帝宋康昊 從影來最大膽演出



◆關於電影



享譽國際導演 朴贊郁十年來最具野心之作!



以探討人性慾望聞名的韓國導演朴贊郁,是韓國影史上唯一入圍世界三大影展(柏林、坎城及威尼斯影展)的導演。在2000年便以《JSA共同警戒區》獲得柏林影展金熊獎提名,享譽國內外的「復仇三部曲」:《原罪犯》、《復仇》、《李英愛之選擇》更將他帶到顛峰境界,是少數商業與藝術兼顧的重量級韓國導演。



朴贊郁從十年前便開始構思拍攝《蝙蝠‧血色情慾》的夢幻計畫,當時他早向宋康昊邀約演出,為了等待宋康昊的磨練和經驗累積,一等就是十年。曾在《殺人回憶》、《駭人怪物》等多部電影中扮演百變角色的宋康昊,這一次挑戰全新的人物。也只有這位當今韓國最具實力的演員,才能將《蝙蝠‧血色情慾》穿梭在神父與吸血鬼間的複雜角色完美詮釋。



朴贊郁選電影女主角的眼光一向獨到,《蝙蝠‧血色情慾》也不例外。在古典中透著現代感氣質的金玉彬,是韓國著名電視演員,此次挑戰女主角,將她清秀脆弱與大膽堅毅的性質表露無遺,金玉彬爆發的能量足以讓演對手戲的宋康昊贊嘆連連,把誘惑的外表與性感的魅力完美展現給大家。



朴贊郁這次透過《蝙蝠‧血色情慾》中神父與吸血鬼相衝突的角色,描述信仰和慾望間的掙扎,尋找刻畫在人性上的終極烙印。愛情、原罪與救贖間的相互拉扯,是朴贊郁電影自始至終聚焦的核心,也是當今影壇最稱此道的佼佼者。



◎中文官網:http://thirst.pixnet.net

    </pre>

  </body>

</html>


三、測試結果:
1.http://localhost:8080/ExtStudy/Basic/layout4.jsp