Posted on 2006-01-17 23:11 
JavaXP 阅读(4691) 
评论(17)  编辑  收藏  所属分类: 
实战经验 
			
			
		 
		昨天下午突然接到公司通知,以前处理的XX物资系统的部门,班组,工程,供应厂商部分都需要修改成Ajaxtags的autocomplete来完成,用户需要输入查询码来进行索引,于是开始动手研究Ajaxtags.
Ajaxtags是基于prototype.js的简化AJAX开发的组件,可以通过标签来来完成以前非常复杂的事情.
通过DOME和原代码的分析,我感觉,他的简化过于局限,没有非常好扩展性,只能做一些简单的处理,比方他的AjaxXmlBuilder的toString()方法可以返回一种简单的XML格式,而且过于简单:
<?xml version="1.0" encoding="UTF-8"?>
<ajax-response>
  <response>
    <item>
      <name>Record 1</name>
      <value>1</value>
    </item>
    <item>
      <name>Record 2</name>
      <value>2</value>
    </item>
    <item>
      <name>Record 3</name>
      <value>3</value>
    </item>
  </response>
</ajax-response>

他在autocomplete处理时会用到这中XML文件:
以下是在他的JS中解析XML的部分
     var name = items[i].getElementsByTagName("name")[0].firstChild.nodeValue;
      var value = items[i].getElementsByTagName("value")[0].firstChild.nodeValue;由此可以看出他过于简单,如果我有多个属性需要放入自动下拉菜单中怎么办?
好办,我们扩展!
自己造一个AjaxXmlBuilder,继承一下就可以了,把toString()方法重载掉~让他组一个我要的XML文件出来,然后再到页面上自己解吸他`就OK了~
我的类:
package com.kaiwang.mmis.ajax.autoselect;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.ajaxtags.helpers.AjaxXmlBuilder;
import org.apache.commons.beanutils.BeanUtils;


/** *//**
 * 重载ajaxxmlbuilder封装出新的xml文件
 * @author Gary.lee Jan 16, 2006
 */

public class ManufacturerXmlBuilder extends AjaxXmlBuilder implements MisAjaxXmlBuilder  
{
    
    private String encoding = "UTF-8";
    private List items = new ArrayList();
    

    public ManufacturerXmlBuilder addItems(Collection collection, String nameProperty, String valueProperty, String seachCodeProperty) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException 
{

        for (Iterator iter = collection.iterator(); iter.hasNext();) 
{
            Object element = (Object) iter.next();
            String name = BeanUtils.getProperty(element, nameProperty);
            String value = BeanUtils.getProperty(element, valueProperty);
            String seachCode = BeanUtils.getProperty(element, seachCodeProperty);
            items.add(new MisAjaxBaseItem(name, value, seachCode));
          }
        return this;
    }


    /** *//**
     * @see java.lang.Object#toString()
     */

    public String toString() 
{
      StringBuffer xml = new StringBuffer().append("<?xml version=\"1.0\"");

      if (encoding != null) 
{
        xml.append(" encoding=\"");
        xml.append(encoding);
        xml.append("\"");
      }
      xml.append(" ?>");

      xml.append("<ajax-response>");
      xml.append("<response>");

      for (Iterator iter = items.iterator(); iter.hasNext();) 
{
       MisAjaxBaseItem item = (MisAjaxBaseItem) iter.next();
      xml.append("<item>");
      xml.append("<name>"); 
      xml.append("<![CDATA[");
      xml.append(item.getName());
      xml.append("]]>");
      xml.append("</name>");
      xml.append("<value>");
      xml.append("<![CDATA[");
      xml.append(item.getId());
      xml.append("]]>");
      xml.append("</value>");
      xml.append("<searchcode>");
      xml.append("<![CDATA[");
      xml.append(item.getSearchCode());
      xml.append("]]>");
      xml.append("</searchcode>");
        xml.append("</item>"); 
      }
      xml.append("</response>");
      xml.append("</ajax-response>");
      return xml.toString();
    }
}

这样就有了我要的XML文件格式了~再修改JS
      var name = items[i].getElementsByTagName("name")[0].firstChild.nodeValue;
      var value = items[i].getElementsByTagName("value")[0].firstChild.nodeValue;
      
      //新增加一个searchcode部分的解析
      var searchCode = items[i].getElementsByTagName("searchcode")[0].firstChild.nodeValue;
      
      var li = document.createElement("li");
      var liIdAttr = document.createAttribute("id");
      li.setAttribute("id", value);
      //将searchcode部分+name输出到文本区域中
      var liText = document.createTextNode(name+'('+searchCode+')');大家可以看到,我加入了一个
searchCode的东西就是在下拉框中把searchCode打印出来!
效果~~~~~~我抓张图出来看看:

样子还可以吧`!
用过autocomplete的朋友应该知道如果仅仅是鼠标点击以后这个框是不会出来了~
因为他默认的事件是"keyup",也就是当有输入的时候才出来.初始化的部分在JS中:

 setOptions: function(options) 
{

    this.options = 
{
      sourceElem: $(options.source),
      targetElem: $(options.target),
      eventType: options.eventType ? options.eventType : "keyup",
      appendValue: evalBoolean(options.appendValue),
      appendSeparator: options.appendSeparator || " ",
      forceSelection: evalBoolean(options.forceSelection)

    }.extend(options || 
{});而且这里如果换成"force"的话,在下拉框中的上下键和回车就失效了,没关系!解决了!在调用的时候把
eventType:"focus"   加上(这个属性官方文档中并没有说~)然后找到:

 attachBehaviors: function(element, event, listener, obj) 
{

    if (isArray(element)) 
{

      for (var i=0; i<element.length; i++) 
{
        eval("element[i].on"+event+" = listener.bindAsEventListener(obj)");
      }

    } else 
{
      eval("element.on"+event+" = listener.bindAsEventListener(obj)");
      eval("element.onkeyup = listener.bindAsEventListener(obj)");
    }
  }大家可以看到我在下面又追加了一个“keyup”的属性,这样既在得到焦点的时候可以出来,也可以在用上下建的时候选择,还可以做筛选~还有就是我没有实用标签,我读了它的DOME以后发现它仅仅是封装了JS而已,用了标签以后感觉怪怪的,为什么JS的调用也要用标签封装呢?仅仅是可以在标签中实用EL语法·但是又有多少兄弟会用呢?最主要的是它的标签中好想没有“eventType”这个属性~,看看我的调用:
//班站编号

new AjaxJspTag.Autocomplete("<%=request.getContextPath()%>/autoSelectTeam.do", 
{
                                            parameters:"team={team_Name},depId={department_Id}",
                                            progressStyle:"throbbing",
                                            target:"team_Id",
                                            className:"autocomplete",
                                            source:"team_Name",
                                            forceSelection:"yes",
                                            eventType:"focus"            
}); 
要注意的是parameters这里多参数实用了,号隔开,这样到ACTION中就可以用depId接到值了~这个东西在官方文档中也没有说出来,还是同事发现的~
!
本人文采不行``大家见谅,希望文章对用ajaxTags的朋友有写帮助,我的原则就是·能改的我都改·只要我能用就可以了!
我再改~前面说了,我修改了AJAX基本的JS文件``但是他的其他属性就不能用了~~~很痛苦,所以晚上突然想到,我专门为他加一个方法就可以了~
//事件触发(修改增加一个keyup事件auto专用)

  attachBehaviorsAuto: function(element, event, listener, obj) 
{
      eval("element.on"+event+" = listener.bindAsEventListener(obj)");
      eval("element.onkeyup = listener.bindAsEventListener(obj)");
  } 
再改一下`他调用的地方,换成这个方法就好了`噎!