两亩三分地

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  17 随笔 :: 20 文章 :: 2 评论 :: 0 Trackbacks

2009年10月22日 #

     摘要: 之前项目有个模块要求用树形解决,附带要实现checkbox,增删修改以及copy/cut/paste等等功能; 因为之前写的人用了xloadTree,其他功能都实现了,但是客户要求要有cookie功能,实现不了麻烦啊~ 正巧现在在学习用Ext,发现Ext的tree本身就很强大基本的功能都可以实现。 Code highlighting produced by Actipro Cod...  阅读全文
posted @ 2010-08-08 23:17 Chucky 阅读(1950) | 评论 (0)编辑 收藏

Border布局作为Ext中整个框架的布局应该说很普遍,一般North放一个应用的Logo bar,West一般会作为导航栏的放置位置;
而Center(East)往往作为整个应用的核心部分,而South位置也往往放置一些应用的版权等信息。

而导航栏一般会采用的呈现方式一般无非是Treepanel或者根据模块放置多个Panel,而多数会采用的布局方式,往往是
Accordion的布局。比如像这样(偷个懒直接用设计器写的):
MyViewportUi = Ext.extend(Ext.Viewport, {
    layout: 'border',
    initComponent: 
function() {
        
this.items = [
            {
                xtype: 'panel',
                title: 'north',
                region: 'north'
            },
            {
                xtype: 'panel',
                title: 'west',
                region: 'west',
                width: 
201,
                split: 
true,
                layout: 'accordion',
                activeItem: 
0,
                items: [
                    {
                        xtype: 'panel',
                        title: 'panel1',
                        layout: 'column',
                        width: 
180,
                        items: [
                            {
                                xtype: 'button',
                                text: 'Button1',
                                scale: 'large'
                            },
                            {
                                xtype: 'button',
                                text: 'Button2',
                                scale: 'large'
                            },
                            {
                                xtype: 'button',
                                text: 'Button3',
                                scale: 'large'
                            },
                            {
                                xtype: 'button',
                                text: 'Button4',
                                scale: 'large'
                            },
                            {
                                xtype: 'button',
                                text: 'Button5',
                                scale: 'large'
                            },
                            {
                                xtype: 'button',
                                text: 'Button6',
                                scale: 'large'
                            }
                        ]
                    },
                    {
                        xtype: 'panel',
                        title: 'panel2'
                    },
                    {
                        xtype: 'panel',
                        title: 'panel3'
                    }
                ]
            },
            {
                xtype: 'panel',
                title: 'east',
                region: 'center'
            },
            {
                xtype: 'panel',
                title: 'south',
                region: 'south'
            }
        ];
        MyViewportUi.superclass.initComponent.call(
this);
    }
});
一个基本的框架就产生了,而问题也随之而来。最主要的问题是IE和FF显示不一样。应该说FF显示很正常,按键根据导航栏的大小,改变每一行显示的数量;
而IE呢,在第一次导航栏宽带变大的时候,一切正常;而当导航栏宽度缩小的时候,原来每行的按键数却并不变。想想这Ext都3.2了,不会还有这么脑残的bug吧;
google了下,国内似乎对这个问题也没有什么讨论的;于是直接去官网的论坛问。

最初别人的提议是,更改westPanel的属性
layout: {
    type: 'accordion',
    autoWidth: 
false
}
等于禁止westPanel的子栏目自动变化宽度,试了如果westPanel的子栏目只有一个工作正常,但是如果多个的话,又悲剧了~

因为每次只有1个子栏目的宽度在变化,所以产生这个问题也不足为奇了。

最后某个网友提供了一个自己写的补丁,问题解决了。
Ext.layout.AccordionPatch = Ext.extend(Ext.layout.Accordion, {
    
    inactiveItems: [],
//ADDED

    
// private
    onLayout : function(ct, target){//ADDED
        Ext.layout.AccordionPatch.superclass.onLayout.call(this, ct, target);
        
if(this.autoWidth === false) {
            
for(var i = 0; i < this.inactiveItems.length; i++) {
                
var item = this.inactiveItems[i];
                item.setSize(target.getStyleSize());
            }
        }
    },
    
// private
    beforeExpand : function(p, anim){//MODFIED
        var ai = this.activeItem;
        
if(ai){
            
if(this.sequence){
                
delete this.activeItem;
                ai.collapse({callback:
function(){
                    p.expand(anim 
|| true);
                }, scope: 
this});
                
return false;
            }
else{
                ai.collapse(
this.animate);
                
if(this.autoWidth === false && this.inactiveItems.indexOf(ai) == -1)//*****
                    this.inactiveItems.push(ai);//*****
            }
        }
        
this.activeItem = p;
        
if(this.activeOnTop){
            p.el.dom.parentNode.insertBefore(p.el.dom, p.el.dom.parentNode.firstChild);
        }
        
if(this.autoWidth === false && this.inactiveItems.indexOf(this.activeItem) != -1)//*****
            this.inactiveItems.remove(this.activeItem);//*****
        this.layout();
    }
    
});

Ext.Container.LAYOUTS['accordionpatch'] 
= Ext.layout.AccordionPatch; 
配合补丁,westPanel的属性也要有相应的变化
layout: {
    type:
'accordionpatch',
    autoWidth: false
}




posted @ 2010-08-07 13:24 Chucky 阅读(313) | 评论 (0)编辑 收藏

     摘要: 发表,浏览,回复之后,我们将讨论的是删除和编辑留言。 因为这个只是一个简单的留言板,没有用户认证之类繁琐的事情,所以对于编辑和删除留言,必须输入 正确的id号和password;如果在发表或回复留言的时候没有输入密码的话,就不能对留言进行编辑或者删除。 这里将写的EditAction class与之前的有所不同,extends org.apache.struts.actions.Dispat...  阅读全文
posted @ 2009-10-29 17:22 Chucky 阅读(231) | 评论 (0)编辑 收藏

整个项目第二个重点就是回复留言,我的思路是在浏览留言的时候,回复键传送主题的ID,一个Action Class处理这个请求,
将与这个ID相关的留言查询出来,写入ActionForm。
  1. 打开display.jsp文件,找到下面这几行,后面添加一个form,用来提交查询请求。
     1 <table>
     2     <tr>
     3         <td>
     4             <bean:write name="topic" property="post.subject"/> 留言者:<bean:write name="topic" property="post.name" /> 留言日:<bean:write name="topic" property="post.date" format="yyyy/MM/dd(E) HH:mm" />  No.<bean:write name="topic" property="post.id" />
     5         </td>
     6         <td>
     7             <html:form action="read">
     8                 <input type="hidden" name="id" value="<bean:write name='topic' property='post.id'/>"/>
     9               <html:submit value="回复" />
    10             </html:form>
    11       </td>
    12    </tr>
    13   </table>
    6-11行,就是新加入的对id的一个请求,这里我用了普通的html标志来提交请求,当然我们也可以用<html:hidden name="topic" property="post.id"/>,但是在处理请求的时候,相对的request.getParameter("id"),就要换成
    request.getParameter("post.id")了;或者我们可以在那个Topic类里,添加一个id字段,那么在浏览留言的时候(ListAction的execute方法,list.add(new Topic(post,replies)); 改成list.add(new Topic(post,replies,post.getId()));)<html:hidden name="topic" property="id"/>也可以这样用了。

  2. 添加一个ActionForm bean ThreadForm.java,除了记录一段留言外,还包括了行将用以回复的留言的预处理;
     1 public class ThreadForm extends org.apache.struts.action.ActionForm {
     2     
     3     private int id;
     4     private String name;
     5     private String subject;
     6     private String content;
     7     private String url;
     8     private String email;
     9     private int iconId;
    10     private String icon;
    11     private String password;
    12     private int replyId;
    13     private String font;
    14 
    15     private List icons;
    16 
    17     private Topic topic;
    18 
    19     // accessor methods..
    20     
    21 
    22     public ThreadForm() {
    23         super();
    24         // TODO Auto-generated constructor stub
    25         setUrl("http://");
    26         setFont("#800000");
    27         String sql = "select id,name,src from icon order by id";
    28         QueryRunner qr = DbHelper.getQueryRunner();
    29         List list = null;
    30         try {
    31             list = (List) qr.query(sql, new BeanListHandler(Icon.class));
    32             // TODO Auto-generated constructor stub
    33         } catch (SQLException ex) {
    34             Logger.getLogger(ThreadForm.class.getName()).log(Level.SEVERE, null, ex);
    35         }
    36         setIcons(list);
    37     }
    38     
    39   
    40 }
    41
    3-15行是负责对回复的预处理,ThreadForm()方法中主要也是处理图标。

  3. 这个回复过程其实是2部,1.预处理:包括列出与ID相关的留言,预设回复的默认标题以及对应的回复id (replyId);2.回复留言,添加记录。
    a.  PreReplyAction.java
    public class PreReplyAction extends org.apache.struts.action.Action {
        
        
    /* forward name="success" path="" */
        
    private static final String SUCCESS = "bbs.read";
        
        
    /**
         * This is the action called from the Struts framework.
         * 
    @param mapping The ActionMapping used to select this instance.
         * 
    @param form The optional ActionForm bean for this request.
         * 
    @param request The HTTP Request we are processing.
         * 
    @param response The HTTP Response we are processing.
         * 
    @throws java.lang.Exception
         * 
    @return
         
    */
        @Override
        
    public ActionForward execute(ActionMapping mapping, ActionForm form,
                HttpServletRequest request, HttpServletResponse response)
               {
            ThreadForm f 
    = (ThreadForm) form;
            String id 
    = (String) request.getParameter("id");
            String sql;
            QueryRunner qr 
    = DbHelper.getQueryRunner();
            
            List list 
    = null;
            sql 
    = "select * from guestbook where id = " + id;
            
    try {
                list 
    = (List) qr.query(sql, new BeanListHandler(Post.class));
            } 
    catch (SQLException ex) {
                Logger.getLogger(PreReplyAction.
    class.getName()).log(Level.SEVERE, null, ex);
            }
            Post post 
    = null;
            post 
    = (Post)list.get(0);
            List replies 
    = null;
            sql 
    = "select * from guestbook where replyId =" + id + " order by id";
            
    try {
                replies 
    = (List) qr.query(sql, new BeanListHandler(Post.class));
            } 
    catch (SQLException ex) {
                Logger.getLogger(PreReplyAction.
    class.getName()).log(Level.SEVERE, null, ex);
            }
            
            Topic topic 
    = new Topic(post,replies);
            f.setTopic(topic);
            f.setSubject(
    "Re :" + post.getSubject());
            f.setReplyId(post.getId());

            
    return mapping.findForward(SUCCESS);
        }
    }

    b. ReplyAction.java
     1 public class ReplyAction extends org.apache.struts.action.Action {
     2     
     3     /* forward name="success" path="" */
     4     private static final String SUCCESS = "bbs.reply";
     5     
     6     /**
     7      * This is the action called from the Struts framework.
     8      * @param mapping The ActionMapping used to select this instance.
     9      * @param form The optional ActionForm bean for this request.
    10      * @param request The HTTP Request we are processing.
    11      * @param response The HTTP Response we are processing.
    12      * @throws java.lang.Exception
    13      * @return
    14      */
    15     @Override
    16     public ActionForward execute(ActionMapping mapping, ActionForm form,
    17             HttpServletRequest request, HttpServletResponse response)
    18             throws Exception {
    19         ThreadForm f = (ThreadForm)form;
    20         String sql = "insert into guestbook (name,subject,email,url,content,iconId,password,font,replyId,date,lastReplyTime) " +
    21                 "values(?,?,?,?,?,?,?,?,?,now(),now())";
    22         String content = f.getContent();
    23         content = content.replaceAll(" ""&nbsp;");
    24         content = content.replaceAll("\n","<br>");
    25         String params[] = {f.getName(),f.getSubject(),f.getEmail(),f.getUrl(),content,new Integer(f.getIconId()).toString(),f.getPassword(),f.getFont(),new Integer(f.getReplyId()).toString()};
    26 
    27         QueryRunner qr = DbHelper.getQueryRunner();
    28         try {
    29             qr.update(sql, params);
    30         } catch (SQLException ex) {
    31             Logger.getLogger(ReplyAction.class.getName()).log(Level.SEVERE, null, ex);
    32         }
    33        sql = "update guestbook set lastReplyTime= now() where id = " + f.getReplyId();
    34         try {
    35             qr.update(sql);
    36         } catch (SQLException ex) {
    37             Logger.getLogger(ReplyAction.class.getName()).log(Level.SEVERE, null, ex);
    38         }
    39         return mapping.findForward(SUCCESS);
    40     }
    41 }
    这个基本和添加留言的一直,只是在insert回复记录以后,更新主题留言的最近的回复时间,可以保证浏览留言的时候,该主题能在最前端。

  4. reply.jsp 基本和之前写的jsp页面区别不大,省略了。

  5. 添加相应的forwarding信息。
    <global-forwards>
            
    <forward name="bbs.post" path="/result.jsp"/>
            
    <forward name="bbs.list" path="/display.jsp"/>
            
    <forward name="bbs.read" path="/reply.jsp" />
            
    <forward name="bbs.reply" path="/list.do" />
            
    <forward name="welcome"  path="/Welcome.do"/>
    </global-forwards>
    根据forward的指向,我们可以看到在reply.jsp按下回复键以后,直接转向list.do动作。
    至于action-mapping 没有什么要注意的。

  6. 整个回复过程就此完成。

posted @ 2009-10-28 13:14 Chucky 阅读(339) | 评论 (0)编辑 收藏

     摘要: 既然我们已经成功完成了第一个ActionForm Bean和与之相关的Action Class;后面的专题中将不再详细的去写与他们相关的开发步骤了。 现在我们开始写留言板的主体部分,即对整个留言就行浏览。因为每个post都有一个replyId字段,用来对应其所回复的留言id;如果这个 replyId等于-1的话,即该留言没有对应的回复。好了还是先从这个JSP页面写起。 displ...  阅读全文
posted @ 2009-10-23 17:40 Chucky 阅读(257) | 评论 (0)编辑 收藏

PostAction主要是处理留言添加工作。
  1. 和创建NewForm bean一样,点击Source Packages > com.bbs.struts,右键New > Java Package... 创建一个com.bbs.struts.action的package用于存放所有action类;

  2. 右键com.bbs.struts.action, New > Struts Action...如果New菜单里没有的话,选择other...,categories里选择
    Struts,File types一栏里选择Struts Action ...;

  3. 在New Struts Action面板里面,Class Name填PostAction;Action Path 填/post;按Next


  4. 按照下面的设置,完成对Action的设置


  5. 在struts-config.xml的文档中,IDE自动添加了对PostForm的声明。
    <action-mappings>
            
    <action input="/post.jsp" name="NewForm" path="/post" scope="request" type="com.bbs.struts.action.PostAction"/>
            
    <action path="/Welcome" forward="/welcomeStruts.jsp"/>
    </action-mappings>

  6. 右边的Source Editor中,新建的PostAction.java已经打开了;接下来我们要把记录在NewForm bean里的数据保存进数据库,为了测试的需要,在添加数据以后,将添加成功与否的结果显示在result.jsp上面。
     1     public ActionForward execute(ActionMapping mapping, ActionForm form,
     2             HttpServletRequest request, HttpServletResponse response) {
     3         NewForm f = (NewForm) form;
     4         String sql = "insert into guestbook (name,subject,email,url,content,iconId,password,font,replyId,date,lastReplyTime) " +
     5                 " values(?,?,?,?,?,?,?,?,-1,now(),now())";
     6 
     7         String content = f.getContent();
     8         content = content.replaceAll(" ""&nbsp;");
     9         content = content.replaceAll("\n""<br>");
    10 
    11         String params[] = {f.getName(), f.getSubject(), f.getEmail(), f.getUrl(), content, new Integer(f.getIconId()).toString(), f.getPassword(), f.getFont()};
    12 
    13         QueryRunner qr = DbHelper.getQueryRunner();
    14 
    15         String result = null;
    16         try {
    17             if (qr.update(sql, params) == 1){
    18                 result = "更新成功";
    19             }else{
    20                 result = "更新失败";
    21             }
    22         } catch (SQLException ex) {
    23             Logger.getLogger(PostAction.class.getName()).log(Level.SEVERE, null, ex);
    24         }
    25         f.setResult(result);
    26         return mapping.findForward(SUCCESS);
    27     }
    7,8,9行主要是将content里的空格和回车符号转成html中所对应的空格和回车。

  7. 在PostAction.java,IDE自动给我们设置了一个 private static final String SUCCESS = "success"; 这是为action forward所设置的forward标志,success的名称我们可以自己取,比如我们可以把它改成bbs.post。关键是在结束对这个action class的编程以后,我们需要在struts-config.xml中添加forward声明。在source editor中打开struts-config.xml,右键菜单Struts > Add Forward,在Add Forward的面板里如下设置,按Add完成添加。

按F6 运行项目,浏览器输入:http://localhost:8080/BBS/post.jsp对程序进行测试。如果添加成功的话,下一页将有更新成功的字样。
posted @ 2009-10-23 00:31 Chucky 阅读(439) | 评论 (0)编辑 收藏

ActionForm Bean在Struts里用来保存网页request传递之间的数据。比如我们现在写的NewForm Bean用来收集表格内的信息,
类似于servlet的request.getParamenter()的作用;当用户提交以后,数据将保存在bean内,然后再做处理。
  1. 点击Source Packages > com.bbs.struts,右键New > Java Package... 创建一个com.bbs.struts.form的package用于存放
    所有form;

  2. 右键com.bbs.struts.form, New > Struts ActionForm Bean...如果New菜单里没有的话,选择other...,categories里选择
    Struts,File types一栏里选择Struts ActionForm Bean...;

  3. 为这个ActionForm取名叫NewForm,然后按Finish完成。
    IDE将创建一个NewForm bean,并在右边的Source Editor里面打开它。默认的话,IDE将创造2个一个String型的name和int型的number,2个属性;并且定义了它们的accessor方法。另外IDE将在struts-config.xml里面,添加对这个bean的声明;
    <form-beans>
            
    <form-bean name="NewForm" type="com.bbs.struts.form.NewForm"/>
    </form-beans>

  4. 在Source Editor里面,将原来的name,number字段删除,并删除与之相关的accessor方法。然后为NewForm添加以下字段,这些字段与之前的post.jsp所用到的字段一一对应。
        private String name;
        
    private String subject;
        
    private String content;
        
    private String url;
        
    private String email;
        
    private int iconId;
        
    private String password;
        
    private String font;

        
    private List icons;
        
    private String result;
    利用insert code...功能,添加相应的accessor方法。

  5. 考虑到因为图标的列其实在生成这个网页的时候就自动添加的,所以在这个ActionForm bean的Constructor的方法里面,就要处理icon了,还有就是对字色,网络链接做一下预处理:
        public NewForm() {
            
    super();
            
    // TODO Auto-generated constructor stub
            setUrl("http://");
            setFont(
    "#800000");
            String sql 
    = "select id,name,src from icon order by id";
            QueryRunner qr 
    = DbHelper.getQueryRunner();
            List list 
    = null;
            
    try {
                list 
    = (List) qr.query(sql, new BeanListHandler(Icon.class));
                
    // TODO Auto-generated constructor stub
            } catch (SQLException ex) {
                Logger.getLogger(NewForm.
    class.getName()).log(Level.SEVERE, null, ex);
            }
            setIcons(list);
        }

  6. 同样在validate方法里,添加对subject验证,如果subject为空的话,改名“无题”。
       public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
            ActionErrors errors 
    = new ActionErrors();

            
    if (getSubject() == null || getSubject().length() < 1) {
                setSubject(
    "无题");
            }
            
    return errors;
        }

  7. 第一个ActionForm Bean就完成了。

posted @ 2009-10-22 23:15 Chucky 阅读(219) | 评论 (0)编辑 收藏