接着上一篇 许愿墙(一),这次我们继续谈一下其具体实现。
一、分类选择心情图案
在填写许愿条时,允许用户选择心情图案,供用户选择最能代表许愿心情的图案。例如在填写许愿条时,默认显示“爱之语”类别下的心情图案,如下图所示,如果单击“新品秀”或“小破孩”等,则显示该类别下的心情图案。具体效果的查看可以点击 这里(不过这个网站是用ASP来写的,在这里用jsp 来实现。)
下面将介绍如何实现分类选择心情图案的具体步骤:
(1)在页面的合适位置添加用于显示“爱之语”的类别心情图案的<div> 标签,并且应用 jstl 的标签 <c:forEach> 标签循环输出多张心情图案,具体代码实现如下:
<div id="face_1" style="display:block">
<c:forEach begin="0" end="10" step="1" var="num" varStatus="id">
<img src="images/face/love_${num}.gif" style="color: #006080">"56" height="56" onClick="javascript:faceChoose('${num}');" /> <
/c:forEach>
<c:forEach>标签支持两种不同样式的迭代,一种是数字索引的迭代(与传统的 for 循环类似);另外一种是集合上的迭代(类似于 iterator 或者 foreach 循环)。在知道具体需要循环的次数时,可以应用第一种,其语法格式如下:
<c:forEach begin="begin" end="end" [var="varName"] [varStatus="varStatusName"][step="step"]>
<!-- 标签体 -->
</c:forEach>
在上面的语法中,begin 和 end 属性是必须使用的,分别用于指定迭代索引的初始值和终止值,都是正整数.其他属性都是可选择的。如果指定了 var 属性,那么将会创建一个变量,将每一次迭代的索引值赋值给该变量,该变量的作用域为标签体内。
<c:foreach> 的另外一种集合迭代形式如下:
<c:forEach items="collection" [var="varName"] [varStatus="varStatusName"]
[begin="begin"] [end="end"] [step="step"]>
<!-- 标签体 -->
</c:forEach>
items 指定了要进行迭代的集合,其他的变量的与上文提到的类似,另外补充一下,属性 begin 的默认值是0,step 的默认值是1.
另外在 jstl 还有一个标签具有迭代作用的,那就是<c:forTokens>,各个属性的使用与<c:forEach>一样,不同的是,在<c:fortokens>还有一个分界符属性“delims”,用来指定进行分割的点。下面给出这两种标签的使用的Demo:
<c:forEach var="i" begin="1" end="5">
Item <c:out value="${i}"/>
</c:forEach>
输出如下:
Item 1 Item 2 Item 3 Item 4 Item 5
<c:forTokens items="Zara,nuha,roshy" delims="," var="name">
<c:out value="${name}"/>
</c:forTokens>
输出如下:
Zara nuha roshy
(2)接着继续谈如何完成分类选择心情图案,在步骤(1)中创建<div>标签下再添加几个<div>标签,分别用来显示“新品秀”,“梦幻水晶”和“小破孩”,并使用<c:foreach>标签循环输出各张图片,另外注意此处 style=”display:none”.这里只给出“新品秀”的设计,其它的类似
<div id="face_2" style="display:none">
<c:forEach begin="6" end="11" step="1" var="num" varStatus="id">
<img src="images/face/new_${num}.gif" style="color: #006080">"56" height="56" onClick="javascript:faceChoose('${num}');" />
</c:forEach>
心情图案类别: <a href="#" onClick="face_1.style.display='block';face_2.style.display='none';face_3.style.display='none';face_4.style.display='none';">爱之屋
<a href="#" onClick="face_1.style.display='none';face_2.style.display='block';face_3.style.display='none';face_4.style.display='none';">新品秀
<!-- "物之语"和"小破孩"的代码类似 –>
二、限制字条内容的长度。
在用户填写许愿条时,要限制用户输入文本的长度(英文占一个字符,汉子占两个字符)。在这里通过一个javascript 函数来实现字符输出的限制。注意不能简单通过String对象length属性来控制,因为length属性在处理汉子时,也默认为占一个字符。
效果图如下:
具体步骤如下:
(1)在网页添加恰当位置添加最多允许文本框,已用字节文本框,剩余字节文本框,注意这三个文本框都不许用户编辑。代码如下:
最多允许: <input name="total" type="text" disabled class="noborder" id="total" value="200" size="4"> 个字节
已用字节: <input name="used" type="text" disabled class="noborder" id="used" value="0" size="4">
剩余字节:  <input name="remain" type="text" disabled class="noborder" id="remain" value="200" size="4">
(2)编写javascript 函数 countStrByte(),用于判断用户输入的字符数是否大于最大允许输入的字符数并计算出已用字节数和剩余字节数。
var LastCount = 0;
function CountStrByte(info, Total, Used, Remain) { // 字节统计
var ByteCount = 0;
var StrValue = info.value;
var StrLength = info.value.length;
var MaxValue = Total.value;
if (LastCount != StrLength) { // 在此判断,减少循环次数
for (i = 0; i < StrLength; i++) { // 计算祝福文字个数,英文数字占1个字符,汉字占2个字符
ByteCount = (StrValue.charCodeAt(i) <= 256) ? ByteCount + 1
: ByteCount + 2;
if (ByteCount > MaxValue) {
info.value = StrValue.substring(0, i);
document.getElementById("pContext").innerHTML = info.value; // 重新设置预览字条上的内容
alert("字条内容最多不能超过 " + MaxValue + " 个字节!\n注意:一个汉字为两字节。");
ByteCount = MaxValue;
break;
}
}
Used.value = ByteCount; // 已用字节
Remain.value = MaxValue - ByteCount; // 剩余字节
LastCount = StrLength;
document.getElementById("pContext").innerHTML = StrValue; // 将字条内容实时显示到预览字条上
}
}
附:String 的charCodeAt()方法用于返回字符串中第 n 个字符的Unicode编码,如果返回值小于256,则表示是ANSI,占一个字节,否则占两个字节。
(3)修改字条内容文本域的代码,在onKeyDown 和 onKeyUp 事件中调用countStrByte,代码如下:
<textarea name="content" id="content" rows="6" cols="49" class="wenbenkuang"
onKeyDown="CountStrByte(this,this.form.total,this.form.used,this.form.remain);"
onkeyup="CountStrByte(this,this.form.total,this.form.used,this.form.remain);">
</textarea>
三、自定义 JSP 随机数标签
(1)自定义 JSP 标签,一般来说,需要引入以下两个包:
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
(2)定义一个标签处理类(RandomSupportTag)
public class RandomSupportTag extends TagSupport {
private static final long serialVersionUID=1L;
private int range=0; //生成的随机数的范围
private int base=0; //生成的随机数再加上的固定值,目的是生成一个大于某个值的随机数
public int getRange() {
return range;
}
public void setRange(int range) {
this.range = range;
}
public int getBase() {
return base;
}
public void setBase(int base) {
this.base = base;
}
public int doStartTag() throws JspException{
JspWriter out=this.pageContext.getOut();
try{
Random random = new Random();
int num=random.nextInt(range);
//注意:此处不能应用out.pritnln()实现
out.print(num+base); //输出一个随机数
}catch(Exception e){
System.out.println("生成随机数时出现的异常:"+e.getMessage());
}
return SKIP_BODY; //返回SKIP_BODY常量,表示将不对标签体进行处理
}
}
(3)建立 tld 文件
TLD 是 Tag Library Definition 的缩写,即标签库定义,文件的后缀是 tld,每个 TLD 文件对应一个标签库,一个标签库中可包含多个标签,TLD 文件也称为标签库定义文件。
标签库定义文件的根元素是 taglib,它可以包含多个 tag 子元素,每个 tag 子元素都定义一个标签。通常我们可以到 Web 容器下复制一个标签库定义文件,并在此基础上进行修改即可。例如 Tomcat,在 webapps\examples\WEB-INF\jsp2 路径下包含了一个 jsp2-example-taglib.tld 文件,这就是示范用的标签库定义文件。
将该文件复制到 Web 应用的 WEB-INF/ 路径,或 WEB-INF 的任意子路径下,并对该文件进行简单修改,修改后的 creatRandom.tld 文件代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>random</short-name>
<tag>
<description>create a random number</description>
<name>creatRandom</name>
<tag-class>com.tools.RandomSupportTag</tag-class>
<attribute>
<name>range</name>
<required>true</required>
</attribute>
<attribute>
<name>base</name>
<required>false</required>
</attribute>
<body-content>empty</body-content>
</tag>
</taglib>
(3)在 web.xml 部署 JSP 标签
<tablib>
<taglib-uri>createRandomUri</taglib-uri>
<!—tld文件所在的位置-->
<taglib-location>/WEB-INF/createRandom.tld</taglib-location>
</taglib>