您的位置:首页 > Web前端 > JavaScript

JSP自定义标签(一) 树形下拉选择菜单

2012-04-02 13:24 281 查看
一、效果图:



二、自定义标签JAVA代码:

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 SelectorTag extends TagSupport {

private static final long serialVersionUID = 9878861374414215L;

//标签name属性
private String name;

//所需图片的路径
private String imgPath;

//所需javascript文件的路径
private String scriptPaht;

//所需css文件的路径
private String cssPath;

//项目的根路径
private String rootPath;

//标签的value属性
private String value;
private String text;
private String path;

/*
* 标签的actionUrl属性
* 联想查询结果数据通过向actionUrl属性指定的url请求得到
*/
private String actionUrl;

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 getImgPath() {
return imgPath;
}
public void setImgPath(String imgPath) {
this.imgPath = imgPath;
}
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 SelectorTag()
{

}

/**
* 初始化变量
*/
private void initAbttributes()
{
request=(HttpServletRequest)this.pageContext.getRequest();
rootPath=request.getContextPath();
this.imgPath="/images/";
this.scriptPaht="/js/";
this.cssPath="/css/";

}
@Override
public int doStartTag() throws JspException {
initAbttributes();
path=rootPath+"/jsp/tags/treeSelectorPage.jsp?id="+id+"&actionUrl="+actionUrl;
JspWriter out=pageContext.getOut();
try {
String tName=name;
//引入javascript文件
out.println("<script type='text/javascript' charset='GB2312' src='"+rootPath+scriptPaht+"selector.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("'");
tag.append(" onclick='return showSelector(\"");
tag.append(id).append("\",\"").append(path).append("\")' readonly>");
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;
}

}


三、树形结构所属jsp页面:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<style type="text/css">
.btn-unfold {
BACKGROUND: url(../images/bg10.png) no-repeat; FLOAT: left; WIDTH: 13px; MARGIN-RIGHT: 5px; HEIGHT: 13px
}
.btn-fold {
BACKGROUND: url(../images/bg09.png) no-repeat; FLOAT: left; WIDTH: 13px; MARGIN-RIGHT: 5px; HEIGHT: 13px
}
</style>
<script type='text/javascript' src='../../js/treeCreator.js'></script>
<script type='text/javascript' src='../../js/jquery-1.3.2.js'></script>
</head>
<body style="margin-left: 0px;margin-right: 0px;margin-top: 0px">
<form id="form1" runat="server">
<div>
</div>
</form>
<%
String para="";
String actionUrl="";
para=request.getParameter("id");
actionUrl=request.getParameter("actionUrl");
%>
<script language="javascript">
$.get("<%=(basePath+actionUrl) %>", function(data,status){
xmlParser(data,'<%=para %>');
});
</script>
</body>
</html>


三、js代码:selector.j

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

}
*/

/*
* 显示下拉框
*/
function showSelector(id,path,ref) {
var selector=window["selector_"+id];
var el = document.getElementById(id);
if (selector) {
// we already have some selector created
if(ref&&ref===true)
{
selector.frame.src=path;
}
//selector.hide();                 // so we hide it first.
} else {
// first-time call, create the selector.
var selec = new Selector();
selec.textId=id;
selec.id="selector_"+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;
}

Selector = 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;
this.frame=null;

}
Selector.is_ie = ( /msie/i.test(navigator.userAgent) &&!/opera/i.test(navigator.userAgent) );
Selector.getAbsolutePos = function(el) {
var r = { x: el.offsetLeft, y: el.offsetTop };
if (el.offsetParent) {
var tmp = Selector.getAbsolutePos(el.offsetParent);
r.x += tmp.x;
r.y += tmp.y;
}
//alert(r.x+":"+r.y);

return r;
};
Selector.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;
};
Selector.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(" ");
};
Selector.addClass = function(el, className) {
Selector.removeClass(el, className);
el.className += " " + className;
};
Selector.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).
* 添加事件
*  */

Selector.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;
}
};

/*
* 删除事件
*/
Selector.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;
}
};
Selector.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 = Selector.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);
};
Selector.prototype.destroy = function () {
var el = this.element.parentNode;
el.removeChild(this.element);
Selector._C = null;
};

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

Selector.prototype.showAt = function (x, y) {
var s = this.element.style;
s.left = x + "px";
s.top = y + "px";
this.show();
};
/** 下拉框相对指定控件的显示位置. */
Selector.prototype.showAtElement = function (el, opts) {
var p = Selector.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);
};

Selector.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);
Selector.addEvent(document, "mousedown", function(){window[tId].hide();});
}

this.hideShowCovered();
};

Selector.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 = Selector.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 = Selector.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";
}
}
}
};


四、js代码:treeCreator.js

      

var blank=".   ";
var blankTimes=1;
var blankSize=30;

var idIndex=0;
var totalWidth=0;
var imgpath="/MoonNighTags/images/";
/*
*  加载xml字符串返回XMLDocument对象
*/
function loadXML(xmlStr)
{
if(!window.DOMParser && window.ActiveXObject){   //window.DOMParser ÅöÃÊÇ·ñÊÇ·Çieä¯ÀÀÆ÷
var xmlDomVersions = ['MSXML.2.DOMDocument.6.0','MSXML.2.DOMDocument.3.0','Microsoft.XMLDOM'];
for(var i=0;i<xmlDomVersions.length;i++){
try{
xmlDoc = new ActiveXObject(xmlDomVersions[i]);
xmlDoc.async = false;
xmlDoc.loadXML(xmlStr);
break;
}catch(e){
}
}
}
else if(window.DOMParser && document.implementation && document.implementation.createDocument){
try{
domParser = new DOMParser();
xmlDoc = domParser.parseFromString(xmlStr,"text/xml");
}catch(e){
}
}
else{
return null;
}
return xmlDoc;
}

/*
* 解析xml字符串生成属性结构
*/
function xmlParser(xmlStr,textId)
{
var childs=null;
var root=null;
var xmlDoc=loadXML(xmlStr);
root=xmlDoc.documentElement;
childs=root.childNodes;
var topDiv=document.createElement("div");
topDiv.id='topdiv';
document.body.appendChild(topDiv);
dealWithNode(root,0,topDiv,textId);
topDiv.style.width='100%';

}

/*
* 根据节点及其子节点生成树
*/
function dealWithNode(node,blankTimes,container,textId)
{
var children=null;
var childCount=0;
var isLeaf=false;

var htmlnode=null;
var textnode=null;

var bl_times=blankTimes;
var bl_str="";

var node_value="";
var node_id="";

if(node)
{
isLeaf=isLeafNode(node);
var str="";
var spaceLength=0;
if(idIndex>0)
{
str=getSpaceString(1);
}
if(bl_times>0)
{
spaceLength=bl_times*blankSize;
}
node_id=node_value=getAttributValue(node,"id");
if(!node_id||node_id=="")
{
node_id=idIndex+1;
}
if(isLeaf)
{
if(node.nodeType==3)
{
node_value=node.nodeValue;
}
else
{
node_value=node.firstChild.nodeValue;
}
idIndex++;
node_value=str+node_value;
htmlnode=createItem(node_value,node_id,container,isLeaf,textId);

htmlnode.style.paddingLeft=spaceLength+'px';
}
else
{
node_value=getAttributValue(node,"value");
idIndex++;
node_value=str+node_value;
htmlnode=createItem(node_value,node_id,container,isLeaf,textId);
htmlnode.style.paddingLeft=spaceLength+'px';
var cContainer=createChildContainer("div"+node_id,container);
cContainer.style.paddingLeft=bl_times*blankSize;
cContainer.style.width='100%';
children=node.childNodes;
if(getBrowser()=="MSIE")
{
bl_times=1;
}
else
{
bl_times+=1;
}

if(children&&children.length>0)
{
for(var i=0;i<children.length;i++)
{
dealWithNode(children[i],bl_times,cContainer,textId);
}
}
}

}
}

/*
* 判断节点是否是叶子节点
*/
function isLeafNode(node)
{
var children=null;
if(node)
{
if(node.nodeType==3)
{
return true;
}
else
{
children=node.childNodes;
if(children.length==1&&children[0].nodeType==3)
{
return true;
}
else
{
return false;
}
}
}
return true;
}

/*
* 获取自定节点的指定属性值
*/
function getAttributValue(node,attrName)
{
var attributes=null;
var attr=null;
if(node)
{
attributes=node.attributes;
if(attributes&&attributes.length>0)
{
for(var attrI=0;attrI<attributes.length;attrI++)
{
attr=attributes[attrI];
if(attr&&attr.nodeName==attrName)
{
return attr.nodeValue;
}
}
}
}
return null;
}

/*
* 创建树形结构中每个节点的项
*/
function createItem(itemText,idStr,parentContainer,isLeaf,textId)
{
var htmlnode=null;
var textnode=null;
var imgnode=null;
var titlenode=null;
var imgsrc=imgpath+"bg09.png";
if(isLeaf)
{
imgsrc=imgpath+"bg10.png";
}
htmlnode=document.createElement("div");
htmlnode.id="span"+idStr;
//htmlnode.href="#";
//htmlnode.style.paddingLeft="200";
//htmlnode.expanded="fales";
//图片
imgnode=document.createElement("img");
imgnode.setAttribute("src",imgsrc);
imgnode.setAttribute("flag",isLeaf);
imgnode.setAttribute("isLeaf",isLeaf);
myAttachEvent(imgnode,'click',open_closeClick);
//文字–
titlenode=document.createElement("div");
titlenode.style.display="inline";
titlenode.style.cursor="pointer";
titlenode.id=idStr;
textnode=document.createTextNode(itemText);
titlenode.appendChild(textnode);
myAttachEvent(titlenode,'click',function(){
var srcObj;
if(typeof(event)!="undefined")
{
srcObj=event.srcElement;
}
else
{
srcObj=this;
}
itemClick(srcObj,textId);});

htmlnode.appendChild(imgnode);
htmlnode.appendChild(titlenode);

parentContainer.appendChild(htmlnode);
return htmlnode;
}

/*
* 创建包含节点下子树的容器
*/
function createChildContainer(idStr,parentContainer)
{
var cContainer=null;
cContainer=document.createElement("div");
cContainer.id=idStr;
cContainer.style.display="none";
cContainer.style.whiteSpace='nowrap';
parentContainer.appendChild(cContainer);
return cContainer;
}

/*
* 单击图片时触发的事件
* 展开或收起该节点的子树
*/
function open_closeClick(arg)
{
var srcObj;
if(typeof(event)!="undefined")
{
srcObj=event.srcElement;
}
else
{
srcObj=this;
}
var flag=srcObj.getAttribute("flag");
if(srcObj.getAttribute("isLeaf")=="true")
{
return;
}
if(flag=="true"){
srcObj.src=imgpath+"bg09.png";
srcObj.setAttribute("flag","false")
}else{
srcObj.src=imgpath+"bg10.png";
srcObj.setAttribute("flag","true");
}

var conId=srcObj.parentNode.id.replace("span","div");
//alert(conId);
var container=document.getElementById(conId);
if(container)
{
if(container.style.display=="block")
container.style.display="none";
else
container.style.display="block";
}
}

/*
* 点击树中节点上选项时触发事件时调用该方法
* 关闭下拉框
*/
function itemClick(srcObj,pid)
{

if(window.parent)
{
window.parent.document.getElementById(pid).value=srcObj.innerHTML;
window.parent.document.getElementById(pid+'_value').value=srcObj.id;
if(window.parent["selector_"+pid])
window.parent["selector_"+pid].hide();
}
}

/*
* 绑定事件
*/
var myAttachEvent = function(obj, evt, fn){
if (obj.addEventListener)
obj.addEventListener(evt, fn, false);
else if (obj.attachEvent)
obj.attachEvent("on" + evt, fn);
}

function Integration_InterceptCellEvent(id, evt, func)
{
if (func.constructor == Function)
{
document.write('<scr' + 'ipt for="' + id + '" event="' + evt + '">'
+ 'Array.prototype.push.call(arguments, "' + evt + '");'
+ func.toString().match(/\s*Function\s+(\S*)\s*\(/i)[1]
+ '.apply(this, arguments);'
+ '</sc' + 'ript>');
}
}

function getSpaceString(strlength)
{
var str="";
for(var strIndex=0;strIndex<strlength;strIndex++)
{
str+=" ";
}
return str;
}
function getShortFileName(fileName)
{
var name="";
var index=-1;

}

/*
* 获取浏览器类型
*/
function getBrowser()
{
var OsObject = "";
if(navigator.userAgent.indexOf("MSIE")>0) {
return "MSIE";
}
if(isFirefox=navigator.userAgent.indexOf("Firefox")>0){
return "Firefox";
}
if(isSafari=navigator.userAgent.indexOf("Safari")>0) {
return "Safari";
}
if(isCamino=navigator.userAgent.indexOf("Camino")>0){
return "Camino";
}
if(isMozilla=navigator.userAgent.indexOf("Gecko/")>0){
return "Gecko";
}
return "others";
}


五、tld文件标签定义:

<tag>

      <name>selector</name>

      <tag-class>com.moonNigh.tagSupport.SelectorTag</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>value</name>

          <required>false</required>

          <rtexprvalue>true</rtexprvalue>

      </attribute>

      <attribute>

          <name>text</name>

          <required>false</required>

          <rtexprvalue>true</rtexprvalue>

      </attribute>

      <attribute>

          <name>actionUrl</name>

          <required>false</required>

          <rtexprvalue>true</rtexprvalue>

      </attribute>

      <example></example>

  </tag>

六、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;
}


七、自定义的用于输出生成树形结构的XML的Servlet或Action:

package com.moonNigh.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class GetTreeXML extends HttpServlet {

/**
*
*/
private static final long serialVersionUID = 1L;

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doPost(req, resp);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
resp.setCharacterEncoding("UTF-8");
resp.setContentType("UTF-8");
PrintWriter out=resp.getWriter();
StringBuilder sb=new StringBuilder();
sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
sb.append("<xmlRoot value=\"中国\" id=\"china\">");
sb.append("<child value=\"四川\" id=\"sc\">");
sb.append("<child id=\"ctu\">成都</child>");
sb.append("</child><child id=\"gz\">贵州</child></xmlRoot>");
out.write(sb.toString());
out.flush();
}
}


八、测试JSP标签使用:

<c:selector id="ctest" name="test" actionUrl="getTreeXml"/>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息