JSP自定义标签(二) 联想查询


一、效果图

JSP自定义标签(二) 联想查询_第1张图片

下拉框中的内容为查询结果


二、标签定义代码


package com.moonNigh.tagSupport;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

/**
 *
 * @author HHB
 *
 *  联想查询自定义标签标签处理类
 *
 */
public class AssociateQueryTag extends TagSupport {

    private static final long serialVersionUID = 1164199147616542853L;
    // 标签name树形
    private String name;
    //引用JavaScript代码的路径
    private String scriptPaht;
    //引用的CSS的路径
    private String cssPath;
    //项目根路径
    private String rootPath;
    
    //标签value属性
    private String value;
    private String text;
    
    /*
     * 标签的actionUrl属性
     * 联想查询结果数据通过向actionUrl属性指定的url请求得到
     */
    private String actionUrl;
    private int startLeng;
    
    public int getStartLeng() {
        return startLeng;
    }
    public void setStartLeng(int startLeng) {
        this.startLeng = startLeng;
    }
    private HttpServletRequest request=null;
    
    
    public String getActionUrl() {
        return actionUrl;
    }
    public void setActionUrl(String actionUrl) {
        this.actionUrl = actionUrl;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
    public String getScriptPaht() {
        return scriptPaht;
    }
    
    public void setScriptPaht(String scriptPaht) {
        this.scriptPaht = scriptPaht;
    }
    public String getCssPath() {
        return cssPath;
    }
    
    public void setCssPath(String cssPath) {
        this.cssPath = cssPath;
    }
    
    
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public AssociateQueryTag()
    {
        
    }
    
    
    /**
     * 初始化变量
     */
    private void initAbttributes()
    {
        request=(HttpServletRequest)this.pageContext.getRequest();
        rootPath=request.getContextPath();
        this.scriptPaht="/js/";
        this.cssPath="/css/";
        
    }
    @Override
    public int doStartTag() throws JspException {
        initAbttributes();
        JspWriter out=pageContext.getOut();
        try {
            String tName=name;
            //引入javascript文件
            //<script type='text/javascript' src='../../js/jquery/jquery-1.4.2.min.js'></script>
            out.println("<script type='text/javascript' charset='UTF-8' src='"+rootPath+"/js/"+"jquery-1.3.2.js'></script>");
            out.println("<script type='text/javascript' charset='UTF-8' src='"+rootPath+scriptPaht+"associater.js'></script>");
            out.println("<script type='text/javascript' charset='UTF-8' src='"+rootPath+scriptPaht+"autoComplete.js'></script>");
            //引入css文件
            out.println("<link rel='stylesheet' href='"+rootPath+cssPath+"selector.css' type='text/css' />");
            //文本输入框
            StringBuilder tag=new StringBuilder("<input type='text' ");
            tag.append("id='").append(id).append("'");
            tag.append(" value='").append(text==null?"":text).append("' autocomplete='off'");
            tag.append(" onkeyup='return queryInfo(").append(startLeng).append(",\"");
            //tag.append(id).append("\",\"").append(path).append("\")'>");
            tag.append(id).append("\",\"").append(actionUrl).append("\")'>");
            //隐藏的用于保存选择结果值的标签
            tag.append("<input type='hidden' name='")
            .append(tName).append("' id='").append(id).append("_value")
            .append("' value='").append(value==null?"":value).append("'>");
            out.println(tag.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return SKIP_BODY;
    }
    
    
}



三、JS代码:associater.js


function closeHandler(cal) {
  cal.hide();                        // hide the selector
}
/*
function selected(cal, date) {
 
}
*/

/*
 * 联想查询文本框输入时触发事件
 */
function queryInfo(starLen,id,path)
{
    var t = '';
    clearTimeout(t);
    t = setTimeout("query("+starLen+",'"+id+"','"+path+"')",500);
    return null;
}
function query(starLen,id,path)
{
    var selector=null;
    var textBox=document.getElementById(id);
    var text=textBox.value;
    if(text.length>=starLen)
    {
        showAssociater(id,path);
        var selector=window["asso_"+id];
        $.get(path,{"para":text}, function(data,status){
            var parentNode=selector.element;
            while(parentNode.hasChildNodes())
            {
                parentNode.removeChild(parentNode.firstChild);
            }
            assoXmlParser(data,parentNode,id);
        });
    }
}
/*
 * 显示下拉框
 */
function showAssociater(id,path) {
  var selector=window["asso_"+id];
  var el = document.getElementById(id);
  if (selector) {
    // we already have some selector created
    //selector.hide();                 // so we hide it first.
  } else {
    // first-time call, create the selector.
    var selec = new Associater();
    selec.textId=id;
    selec.id="asso_"+id;
    selec.valueId=id+"_value";
    selec.path=path;
    // uncomment the following line to hide the week numbers
    // cal.weekNumbers = false;
    selector = selec;                  // remember it in the global var
    selec.create();
  }
  selector.sel = el;                 // inform it what input field we use

  // the reference element that we pass to showAtElement is the button that
  // triggers the selector.  In this example we align the selector bottom-right
  // to the button.
  selector.showAtElement(el, "Bl");        // show the selector
  return false;
}

Associater = function () {
    // member variables
    this.activeDiv = null;
    this.timeout = null;
    this.dragging = false;
    this.hidden = false;
    this.isPopup = true;
    // HTML elements
    this.element = null;
    this.containFrame=null;
    this.textId=null;
    this.id=null;
    this.valueId=null;
    this.path=null;
}
Associater.is_ie = ( /msie/i.test(navigator.userAgent) &&!/opera/i.test(navigator.userAgent) );
Associater.getAbsolutePos = function(el) {
    var r = { x: el.offsetLeft, y: el.offsetTop };
    if (el.offsetParent) {
        var tmp = Associater.getAbsolutePos(el.offsetParent);
        r.x += tmp.x;
        r.y += tmp.y;
    }
    //alert(r.x+":"+r.y);
    
    return r;
};
Associater.isRelated = function (el, evt) {
    var related = evt.relatedTarget;
    if (!related) {
        var type = evt.type;
        if (type == "mouseover") {
            related = evt.fromElement;
        } else if (type == "mouseout") {
            related = evt.toElement;
        }
    }
    while (related) {
        if (related == el) {
            return true;
        }
        related = related.parentNode;
    }
    return false;
};
Associater.removeClass = function(el, className) {
    if (!(el && el.className)) {
        return;
    }
    var cls = el.className.split(" ");
    var ar = new Array();
    for (var i = cls.length; i > 0;) {
        if (cls[--i] != className) {
            ar[ar.length] = cls[i];
        }
    }
    el.className = ar.join(" ");
};
Associater.addClass = function(el, className) {
    Associater.removeClass(el, className);
    el.className += " " + className;
};
Associater.createElement = function(type, parent) {
    var el = null;
    if (document.createElementNS) {
        // use the XHTML namespace; IE won't normally get here unless
        // _they_ "fix" the DOM2 implementation.
        el = document.createElementNS("http://www.w3.org/1999/xhtml", type);
    } else {
        el = document.createElement(type);
    }
    if (typeof parent != "undefined") {
        parent.appendChild(el);
    }
    return el;
};
/** Calls the second user handler (closeHandler).
 * 添加事件
 *  */

Associater.addEvent = function(el, evname, func) {
    if (el.attachEvent) { // IE
        el.attachEvent("on" + evname, func);
    } else if (el.addEventListener) { // Gecko / W3C
        el.addEventListener(evname, func, true);
    } else { // Opera (or old browsers)
        el["on" + evname] = func;
    }
};
Associater.stopEvent = function(ev) {
    if (Associater.is_ie) {
        window.event.cancelBubble = true;
        window.event.returnValue = false;
    } else {
        ev.preventDefault();
        ev.stopPropagation();
    }
    return false;
};
/*
 * 删除事件
 */
Associater.removeEvent = function(el, evname, func) {
    //alert(el.detachEvent);
    if (el.detachEvent) { // IE
        el.detachEvent("on" + evname, func);
    } else if (el.removeEventListener) { // Gecko / W3C
        el.removeEventListener(evname, func, true);
    } else { // Opera (or old browsers)
        el["on" + evname] = null;
    }
};
Associater.prototype.create = function (_par) {
    var parent = null;
    if (! _par) {
        // default parent is the document body, in which case we create
        // a popup selector.
        parent = document.getElementsByTagName("body")[0];
        this.isPopup = true;
    } else {
        parent = _par;
        this.isPopup = false;
    }
    var div = document.createElement("div");
    /*
    var selectIframe = Associater.createElement("iframe");
    selectIframe.style.width="100%";
    selectIframe.style.height="100%";
    selectIframe.style.display="block";
    selectIframe.scrolling="auto";
    selectIframe.style.border="0px";
    selectIframe.id=this.textId+"_frm";
    this.containFrame=selectIframe;
    //selectIframe.style.border="1px";
    selectIframe.src=this.path;
    var span=document.createElement("span");
    span.innerHTML="test";
    //div.appendChild(span);
    this.frame=selectIframe;
    div.appendChild(selectIframe);
    */
    this.element = div;
    div.className = "selector";
    if (this.isPopup) {
        div.style.position = "absolute";
        div.style.display = "none";
    }
    parent.appendChild(this.element);
};
Associater.prototype.destroy = function () {
    var el = this.element.parentNode;
    el.removeChild(this.element);
    Associater._C = null;
};

/**
 *  Hides the Associater.  Also removes any "hilite" from the class of any TD
 *  element.
 *  隐藏下拉框
 */
Associater.prototype.hide = function () {
    if (this.isPopup) {
        var obj=this;
        //Associater.removeEvent(document, "keydown", Associater._keyEvent);
        //Associater.removeEvent(document, "keypress", Associater._keyEvent);
        Associater.removeEvent(document, "click", function(){obj.hide();});
    }
    this.element.style.display = "none";
    this.hidden = true;
    this.hideShowCovered();
};

Associater.prototype.showAt = function (x, y) {
    var s = this.element.style;
    s.left = x + "px";
    s.top = y + "px";
    this.show();
};
/** 下拉框相对指定控件的显示位置. */
Associater.prototype.showAtElement = function (el, opts) {
    var p = Associater.getAbsolutePos(el);
    //alert(p.x+'-'+p.y);
    if (!opts || typeof opts != "string") {
        this.showAt(p.x, p.y + el.offsetHeight);
        return true;
    }
    this.show();
    var w = this.element.offsetWidth;
    var h = this.element.offsetHeight;
    this.hide();
    var valign = opts.substr(0, 1);
    var halign = "l";
    if (opts.length > 1) {
        halign = opts.substr(1, 1);
    }
    // 垂直对齐方式
        switch (valign) {
        case "T": p.y -= h; break;
        case "B": p.y += el.offsetHeight; break;
        case "C": p.y += (el.offsetHeight - h) / 2; break;
        case "t": p.y += el.offsetHeight - h; break;
        case "b": break; // already there
        }
    // 水平对齐方式
    switch (halign) {
        case "L": p.x -= w; break;
        case "R": p.x += el.offsetWidth; break;
        case "C": p.x += (el.offsetWidth - w) / 2; break;
        case "r": p.x += el.offsetWidth - w; break;
        case "l": break; // already there
    }
    this.showAt(p.x, p.y);
};

Associater.prototype.show = function () {
    this.element.style.display = "block";
    this.hidden = false;
    
    if (this.isPopup) {
        window[this.id] = this;
        var tId=this.id;
        //Calendar.addEvent(document, "keydown", Calendar._keyEvent);
        //Calendar.addEvent(document, "keypress", Calendar._keyEvent);
        Associater.addEvent(document, "click", function(){window[tId].hide();});
    }
    this.hideShowCovered();
};
Associater._Click=function(ev,mid,srcObj)
{
    var sel=window[mid];
    if(!sel)
    {
        return false;
    }
    var obj=null;
    obj=ev.srcElement?ev.srcElement:srcObj;
    var el=obj.parentNode;
    while(el!=null&&el!=sel.element)
    {
        el=el.parentNode;
    }
    if(el==null)
    {
        sel.hide();
        Associater.stopEvent(ev);
    }
};
Associater.prototype.hideShowCovered = function () {
    function getStyleProp(obj, style){
        var value = obj.style[style];
        if (!value) {
            if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C
                value = document.defaultView.
                    getComputedStyle(obj, "").getPropertyValue(style);
            } else if (obj.currentStyle) { // IE
                value = obj.currentStyle[style];
            } else {
                value = obj.style[style];
            }
        }
        return value;
    };

    var tags = new Array("applet", "select");
    var el = this.element;

    var p = Associater.getAbsolutePos(el);
    var EX1 = p.x;
    var EX2 = el.offsetWidth + EX1;
    var EY1 = p.y;
    var EY2 = el.offsetHeight + EY1;

    for (var k = tags.length; k > 0; ) {
        var ar = document.getElementsByTagName(tags[--k]);
        var cc = null;

        for (var i = ar.length; i > 0;) {
            cc = ar[--i];

            p = Associater.getAbsolutePos(cc);
            var CX1 = p.x;
            var CX2 = cc.offsetWidth + CX1;
            var CY1 = p.y;
            var CY2 = cc.offsetHeight + CY1;

            if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
                if (!cc.__msh_save_visibility) {
                    cc.__msh_save_visibility = getStyleProp(cc, "visibility");
                }
                cc.style.visibility = cc.__msh_save_visibility;
            } else {
                if (!cc.__msh_save_visibility) {
                    cc.__msh_save_visibility = getStyleProp(cc, "visibility");
                }
                cc.style.visibility = "hidden";
            }
        }
    }
};



四、CSS代码:selector.css

.selector {
  position: relative;
  display: none;
  border:2px solid #C9D7F1;
  font-size: 11px;
  color: #666;
  cursor: default;
 background:white;
/*  font-family:tahoma,verdana,sans-serif;*/
  font-family:arial;
  margin-top:2px;
  width: 150px;
  height: 200px;
}


五、tld定义

<!-- 联想查询标签 -->
  <tag>
      <name>associate</name>
      <tag-class>com.moonNigh.tagSupport.AssociateQueryTag</tag-class>
      <body-content>empty</body-content>
      <small-icon></small-icon>
      <large-icon></large-icon>
      <description></description>
      <attribute>
          <name>id</name>
          <required>true</required>
      </attribute>
      <attribute>
          <name>name</name>
          <required>true</required>
      </attribute>
      <attribute>
          <name>text</name>
          <required>false</required>
          <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
          <name>value</name>
          <required>false</required>
          <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
          <name>actionUrl</name>
          <required>false</required>
          <rtexprvalue>true</rtexprvalue>
      </attribute>
      <attribute>
          <name>startLeng</name>
          <required>false</required>
          <rtexprvalue>true</rtexprvalue>
          <type>java.lang.Integer</type>
      </attribute>
      <example></example>
  </tag>

  六、测试标签

<c:associate name="ca" id="ca" actionUrl="getTreeXml" startLeng="2"/>


你可能感兴趣的:(JSP自定义标签(二) 联想查询)