颠覆软件

关注 : 架构与设计,敏捷,快速开发,项目管理,执行力,SSH,RoR

Archive for May, 2006

整理:web打印

May 26, 2006

key words: IE打印 web打印 页面打印

最近又碰到了页面打印,顺便记录一下,本来下午写完了,可惜最近blogjava最近总是出现问题,提交居然失败,只好再来一次.

function SaveDataSourec(HeadName1, HeadName2, DivName) {
var Div1 = DivName.innerHTML;
var css = ’<style type=text/css media=all>‘ +
‘p { line
-height: 120%}’ +
‘.fhead {   font
-size: 9pt; text-decoration: none; color: 104A7B}’ +
‘.ftitle { line
-height: 120%; font-size: 18px; color: #000000}’ +
‘td { font
-size: 10px; color: #000000}’ +
</style>‘ ;

var body = ’<table width=640 border=0 cellspacing=0 cellpadding=5>‘ +
‘ 
<tr> ’ +
‘ 
<td class=fbody>‘ +
‘ 
<b><div align=center>‘ + ’<font size=+1 class=fhead>‘ + HeadName1 + ’</div>‘ + ’</font></b>‘ +
‘ 
<b><div align=center>‘ + ’<font size=+1 class=fhead>‘ + HeadName2 + ’</div>‘ + ’</font></b>‘ +
‘ 
</td>‘ +
‘ 
</tr>‘ +
‘ 
<tr> ’ +
‘ 
<td class=fbody>‘ +
‘ 
<div align=center class=ftitle>‘ + Div1 + ’</div>‘ +
‘ 
</td>‘ +
‘ 
</tr>‘ +
</table>‘;
document.body.innerHTML 
= ’<center>‘ + css + body + ’<OBJECT classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height=0 id=wb name=wb width=0></OBJECT>‘ + ’</center>‘;
}

function PrintDataSourec(HeadName1, DivName) {
var oldBody = document.body.innerHTML;
var Div1 = DivName.innerHTML;
var css = ’<style type=text/css media=all>‘ +
‘p { line
-height: 120%}’ +
‘.fhead {   font
-size: 40pt; text-decoration: none; color: 104A7B}’ +
‘.ftitle { line
-height: 120%; font-size: 25px; color: #000000}’ +
‘td { font
-size: 25px; color: #000000}’ +
</style>‘ ;

var body =
<table width=100% border=0 cellspacing=0 cellpadding=0>‘ +
‘ 
<tr>‘ +
‘   
<td height=40></td>‘ +
‘ 
</tr>‘ +
</table>‘ +
<table width=640 border=0 cellspacing=0 cellpadding=5>‘ +
‘ 
<tr> ’ +
‘ 
<td class=fbody>‘ +
‘ 
<b><div align=center>‘ + ’<font size=+3 class=fhead>‘ + HeadName1 + ’</div>‘ + ’</font></b>‘ +
‘ 
</td>‘ +
‘ 
</tr>‘ +
‘ 
<tr> ’ +
‘ 
<td class=fbody>‘ +
‘ 
<div align=center class=ftitle>‘ + Div1 + ’</div>‘ +
‘ 
</td>‘ +
‘ 
</tr>‘ +
</table>‘ +
<table width=640 border=0 cellspacing=0 cellpadding=5>‘ +
‘ 
<tr> ’ +
‘ 
<td class=fbody>‘ +
‘ 
</td>‘ +
‘ 
</tr>‘ +
</table>‘;
document.body.innerHTML 
= ’<center>‘ + css + body + ’<OBJECT classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height=0 id=wb name=wb width=0></OBJECT>‘ + ’</center>‘;
try {
wb.execwb(
66);
}
catch(ex) {
alert(
请在IE里设置允许ActiveX);
}
document.body.innerHTML 
= oldBody;
}

function PrintDataSourecWithSetup(HeadName1, HeadName2, DivName) {
var oldBody = document.body.innerHTML;
var Div1 = DivName.innerHTML;
var css = ’<style type=text/css media=all>‘ +
‘p { line
-height: 120%}’ +
‘.fhead {   font
-size: 9pt; text-decoration: none; color: 104A7B}’ +
‘.ftitle { line
-height: 120%; font-size: 18px; color: #000000}’ +
‘td { font
-size: 10px; color: #000000}’ +
</style>‘ ;

var body = ’<table width=640 border=0 cellspacing=0 cellpadding=5>‘ +
‘ 
<tr> ’ +
‘ 
<td class=fbody>‘ +
‘ 
<b><div align=center>‘ + ’<font size=+1 class=fhead>‘ + HeadName1 + ’</div>‘ + ’</font></b>‘ +
‘ 
<b><div align=center>‘ + ’<font size=+1 class=fhead>‘ + HeadName2 + ’</div>‘ + ’</font></b>‘ +
‘ 
</td>‘ +
‘ 
</tr>‘ +
‘ 
<tr> ’ +
‘ 
<td class=fbody>‘ +
‘ 
<div align=center class=ftitle>‘ + Div1 + ’</div>‘ +
‘ 
</td>‘ +
‘ 
</tr>‘ +
</table>‘;
document.body.innerHTML 
= ’<center>‘ + css + body + ’<OBJECT classid=CLSID:8856F961-340A-11D0-A96B-00C04FD705A2 height=0 id=wb name=wb width=0></OBJECT>‘ + ’</center>‘;
wb.execwb(
66);
document.body.innerHTML 
= oldBody;
}

function SetPrintSettings() {
// – advanced features
    factory.printing.SetMarginMeasure(2// measure margins in inches
    factory.SetPageRange(false13// need pages from 1 to 3
    factory.printing.printer = HP DeskJet 870C
factory.printing.copies 
= 2
factory.printing.collate 
= true
factory.printing.paperSize 
= A4
factory.printing.paperSource 
= Manual feed

// – basic features
    factory.printing.header = This is MeadCo
factory.printing.footer 
= Advanced Printing by ScriptX
factory.printing.portrait 
= false
factory.printing.leftMargin 
= 1.0
factory.printing.topMargin 
= 1.0
factory.printing.rightMargin 
= 1.0
factory.printing.bottomMargin 
= 1.0

}

//调用接口
function printit(HeadName1, DivName) {
if (confirm(‘是否确认打印?‘)) {
PrintDataSourec(HeadName1, DivName);
return;
}
}

//带配置的接口
function printitWithSetup(HeadName1, HeadName2, DivName) {
if (confirm(‘是否确认’)) {
PrintDataSourecWithSetup(HeadName1, HeadName2, DivName);
}
}

//另存
function saveas(HeadName1, DivName) {
SaveDataSourec(HeadName1, 
“”, DivName);
//wb.execwb(4,1);
    top.frames(mainFrame).document.execCommand(saveAs);
window.history.back(
0);
}

调用很简单,把要打印的部分直接放在 <div>里就可以了

<div id=”myPrint”>

your content to print

</div>

把div传给printit就可以了

由于本质上是js调用了ActiveX,所以会涉及到安全的问题,如果客户端对ActiveX禁用会出现问题,所以可以在异常处理信息里告诉用户,可以在安全设置里把你的站点的URL放进信任站点

关于打印,还有另一种类型,就是发票套打,可以用Applet实现,也可以用自己写的ActiveX来实现,上一次的一个phs项目里他们就使用vc写的ActiveX,用起来感觉不错,不过依然存在安全上的限制问题,不过如果用Applet的话实际上也是需要客户端安装jre的,从某种角度上来说差不多。话又说回来,做项目不同于做产品,可以对客户有所要求  :)

VN:F [1.6.3_896]
Rating: 0.0/10 (0 votes cast)
VN:F [1.6.3_896]
Rating: 0 (from 0 votes)

javamail整理

May 23, 2006

kew words: javamail

这几天项目里涉及到javamail,顺便看了下.

现在都习惯在blogjava上搜索一番了  XXX in site:blogjava.net是我常用的搜索方式了,呵呵,大多数时候发现blogjava没让我失望,也说明这里的高手很多啊 :)

感觉 Bromon的两篇文章很实用:
JavaMail使用指南(一)Javamail使用指南(二)

还有 morcble的 javamail发送邮件javamail接受邮件

在测试的时候有几个问题值得一提:

  • 第一就是一定要加上activation.jar 库文件,否则会报下面的异常:

NoClassDefFoundError: javax/activation/DataSource

  • 另外,发现用yahoo的smtp会报535的验证错误,把验证的方式换为morcble的下面的内部类的方式验证也不行:

Session session = Session.getDefaultInstance(props,
new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(mymail.username,
mymail.password);
}
});

最后换了个smtp服务器没问题,不知道各位兄弟有没有碰到这样的问题,可以确认的是我的yahoo配置信息应该是正确的,因为我用foxmail收发信件都是可以的.

后来到yahoo中国里面看了一下帮助,里面说

我们目前正在对雅虎邮箱该项服务进行相关的调整,因此我们暂时停止了在页面上POP服务设置的相关介绍。目前雅虎邮箱暂时不提供POP服务,敬请关注雅虎邮箱的近期活动。



应该就是这个原因了   :)

  • 另外,还有一些基于javamail封装的工具类:

可以参考这篇 :  简化JavaMail:小巧 Jakarta Commons-Email 简单教程

VN:F [1.6.3_896]
Rating: 0.0/10 (0 votes cast)
VN:F [1.6.3_896]
Rating: 0 (from 0 votes)

文件上传:用O’Reilly公司的cos实现文件上传

May 22, 2006

出处:codeChina

key words: cos 文件上传 jsp上传

index.html文件:

<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html;charset=gb2312″>
<title>无标题文档</title>
</head>

<body>
<!– enctype的值很重要,upload.jsp为处理上传的jsp–>
<form name=”form1″  method=”post” enctype=”multipart/form-data”
action
=”upload.jsp”>
<p>
<input name=”file1″ type=”file”>
</p>
<p>
<input name=”file2″ type=”file”>
</p>
<p>  <input name=”file3″ type=”file”>
</p>
<p>
<input type=”submit” name=”Submit” value=”上传”>
</p>
</form >

</body>
</html> 
upload.jsp文件 :

<%@page import=java.io.*%>
<%@page import=com.oreilly.servlet.MultipartRequest%>
<%@page import=com.oreilly.servlet.multipart.CoverFileRenamePolicy%>
<%@page contentType=text/html; charset=gb2312 %>
<%
//文件上传后,保存在c:\\upload
String saveDirectory =c:\\upload;
//每个文件最大5m,最多3个文件,所以
int maxPostSize =3 * 5 * 1024 * 1024 ;
//response的编码为gb2312,同时采用缺省的文件名冲突解决策略,实现上传
//就这一句就完成上传了,真是很爽
MultipartRequest multi 
= new MultipartRequest(request, saveDirectory, maxPostSize,gb2312);

//输出反馈信息
Enumeration files 
= multi.getFileNames();
while (files.hasMoreElements()) {
System.err.println(
ccc);
String name = (String)files.nextElement();
File f 
= multi.getFile(name);
if(f!=null){
String fileName = multi.getFilesystemName(name);
String lastFileName= saveDirectory+\\ + fileName;
out.println(
上传的文件:+lastFileName);
out.println(
<hr>);

}
}

%>

相关链接:几种上传方法介绍和比较

VN:F [1.6.3_896]
Rating: 0.0/10 (0 votes cast)
VN:F [1.6.3_896]
Rating: 0 (from 0 votes)

javascript两则:树与eval函数

May 16, 2006

key words: 动态树 eval函数用法

近期项目中需要在ilearning中做开发,用到大量纯jsp模式的开发,当然javaScript也用了很多,看来近期要好好研究javascript了 :)

一.树
这次要做一个树,需要支持展开和放置checkbox,开始的时候打算找一个,后来发现没有适合的,最后自己写,其实也就是用到.style.display=’none’或者.style.display=’block’来支持展开
显示效果如下:
treedemo.gif

<!DOCTYPE HTML PUBLIC ”-//W3C//DTD HTML 4.01 Transitional//EN”
“http://www.w3.org/TR/html4/loose.dtd”
>
<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312″>
<title>Tree</title>
<script language=”javascript”>
function show(IMG,DV)
{
if(DV.style.display==none)
{
DV.style.display
=block;
IMG.src
=manager.gif
}
else
{
DV.style.display
=none;
IMG.src
=manager.gif
}
}
var display=none;
var i;
function showall()
{
var divTags=document.getElementsByTagName(div);
//alert(divTags[10].id.replace(“DV”,”"));
    if( display==none )
{
for(i=0;i<divTags.length;i++)
{
divTags[i].style.display
=block;
eval(
IMG+divTags[i].id.replace(DV,“”)).src=images/btnDel.gif;
display
=block
}
}
else
{
for(i=0;i<divTags.length;i++)
{
divTags[i].style.display
=none;
eval(
IMG+divTags[i].id.replace(DV,“”)).src=images/btnAdd.gif;
display
=none;
}
}
}
</script>

<SCRIPT LANGUAGE=”JavaScript”>
function checkAll(str)
{
var a = document.getElementsByName(str);
var n = a.length;
for (var i=0; i<n; i++)
a[i].checked 
= window.event.srcElement.checked;
}
function checkItem(str)
{
var e = window.event.srcElement;
var all = eval(document.form0.+ str);
if (e.checked)
{
var a = document.getElementsByName(e.name);
all.checked 
= true;
for (var i=0; i<a.length; i++)
{
if (!a[i].checked){ all.checked = falsebreak;}
}
}
else all.checked = false;
}
</SCRIPT>

</head>

<body>
<href=”#” ONCLICK=”show(IMG001,DV001)”>
<img id=”IMG001″ src=”manager.gif” border=”0″></a>
<input type=”Checkbox” name=”All” onclick=”checkAll(‘cb’)”>
第一层

<!–Begin of 2–>
<DIV id=’DV001′ style=’display:none’>
&nbsp;&nbsp;<img id=”IMG0010″ src=”user.gif” border=”0″>
<input type=”checkbox” name=”cb” value=”1″ >
101
<br>
&nbsp;&nbsp;<img id=”IMG0010″ src=”user.gif” border=”0″>
<input type=”checkbox” name=”cb” value=”1″ >
102
<!–End of 2–>
</div>
<br>
<href=”#” ONCLICK=”show(IMG002,DV002)”>
<img id=”IMG002″ src=”manager.gif” border=”0″>
</a>
<input type=”Checkbox” name=”fdasfdsafsd” onclick=”checkAll(‘cbb’)” >
第二层

<!–Begin of 2–>
<DIV id=’DV002′ style=’display:none’>
&nbsp;&nbsp;<img id=”IMG0011″ src=”user.gif” border=”0″>
<input type=”checkbox” name=”cbd” value=”1″ id=”cbb”>
201
<br>
&nbsp;&nbsp;<img id=”IMG0011″ src=”user.gif” border=”0″>
<input type=”checkbox” name=”cbd” value=”1″ id=”cbb”>
202
<!–End of 2–>
</div>
</body>
</html>


2.eval函数用法
这次碰到一个问题,就是动态获取某个id的值,比如document.formX.idX.value,其中idX是动态的,所以直接写无法获得,会提示找不到某变量,这时eval就派上用场了
比如

var myObj = document.formX.+idX;
myObj.value 
= XXValue;
详细信息参考这里
这里再提供几个例子:

function simpleSwap()
{
var the_image = prompt(change parrot or cheese,“”);
var the_image_name = window.document. + the_image;
var the_image_object = eval(the_image_name);
the_image_object.src 
= ant.gif;
}

function tophide(id)    //id indicates menu
{
if (top.topframeset.rows == 31,*)
{
top.topframeset.rows 
= 86,*;
eval(id 
+ _icon.src=/imgs/collapse_up.gif’);
eval(id + 
_icon.alt=‘Collapse The Head’);
head.style.display = 
block
}
else
{
top.topframeset.rows = 
31,*;
eval(id + 
_icon.src=/imgs/collapse_down.gif’);
eval(id 
+ _icon.alt=’Expand The Head’);
head.style.display 
= none
}
}

VN:F [1.6.3_896]
Rating: 0.0/10 (0 votes cast)
VN:F [1.6.3_896]
Rating: 0 (from 0 votes)

[zt]Struts中防止任意形式的重复提交

May 8, 2006

注:这个说的挺全面,考虑到了两种情况,一个是超连接,一个是表单

原文是这里


Struts Token 机制可以解决这个问题。

1.   防止通过超链接重复访问 Struts Action

如果我们要防止 A 的默认页面 J 中指向 K 的超链接重复提交数据,按照下列步骤即可:

a.   如果 J 是从 Struts Action 转发而来,我们要在该 Struts Action execute 方法中添加下面的一行:

    saveToken(request);

b.   如果 J 不是从 Struts Action 转发而来,那么新建一个 Struts Action ,在该 Struts Action excute 方法中增加上面的一行,然后再从该 action 转到 J 页面。

c.   J 页面中使用 Struts 标签生成指向 K 的超链接,如:

   <html:link action=”/deleteLayoutAction?layoutId=0″ transaction=”true” >delete</html:link>

   注意红色字体部分。

d.   <html:link> 标签指向的 action excute 方法中加入下面的代码:

   if (!isTokenValid(request)) {

                     return mapping.findForward(“ 这种情况下就是重复提交,转到相应的页面 “);

              }

e All Done.

2.   防止通过表单重复提交数据。

a.   如果 J 是从 Struts Action 转发而来,我们要在该 Struts Action execute 方法中添加下面的一行:

    saveToken(request);

b.   如果 J 不是从 Struts Action 转发而来,那么新建一个 Struts Action ,在该 Struts Action excute 方法中增加上面的一行,然后再从该 action 转到 J 页面。

c.   J 页面中表单 Action 属性指向的 Struts action excute 方法中加入下面的代码:

   if (!isTokenValid(request)) {

           saveToken(request);

                     return mapping.findForward(“ 这种情况下就是重复提交,转到相应的页面 “);

   saveToken(request);

              }

e All Done.

VN:F [1.6.3_896]
Rating: 0.0/10 (0 votes cast)
VN:F [1.6.3_896]
Rating: 0 (from 0 votes)

分页继续[数据库分页和PageBean的改进]

May 8, 2006

注:本文继续分页的上一篇 关于分页,标签,缓存
hibernate分页有现成的支持:

query.setFirstResult(start);
query.setMaxResults(rowNum); 

MySql如下:

select * from table where  limit start,rowNum;

Oracle如下

select * from table where  and rowid not in(select rowid from t_table where  …. and  rownum<= (pageIndex-1* size)
and rownum <= size;
PageBean以前是设置currentPage,然后在页面里自己判断上一页下一页是什么,后来发现纯粹多余,完全可以把目标页写进去,而且参数也统一了,以前页面传到Action有好几个参数:

if(method.equals(lastPage)){

}else if(method.equals(nextPage)){

}else if(method.equals(targetPage)){
//.
}

现在统一一个参数就是pageIndex,爽多了  :)
PageBean代码如下:

int currentPage = 1;//当前页:Action控制
    int totalPages = 0;//总页数 :自己运算
    public static int pageRecorders = 10//每页记录数,默认为10,可以在初始化的时候修改//总数据数
    int pageStartRow = 0//每页的起始数  [这个字段可以去掉]
    int pageEndRow = 0//每页显示数据的终止数  [这个字段也可以去掉]
    boolean hasNextPage = false//是否有下一页:自己运算
    boolean hasPreviousPage = false//是否有前一页 :自己运算
    List objList = new ArrayList();//存放欲展示的对象列表
    int totalRows;//总记录数,由底层service提供

//增加上一页索引 [directly to target page]
    private int lastPageIndex = 1;
//增加下一页索引 [directly to target page]
    private int nextPageIndex = 1;

public int getLastPageIndex() {
return currentPage - 1;
}

public int getNextPageIndex() {
return currentPage + 1;
}

//是否有上一页
    public boolean isHasPreviousPage() {
return (currentPage > 1 ? true : false);
}

//共有多少页,service只提供有多少条记录,多少页数由PageBean自己运算
    public int getTotalPages() {
if (totalRows <= pageRecorders) return 1;
return (totalRows % pageRecorders == 0 ? totalRows / pageRecorders : totalRows / pageRecorders + 1);
}

public int getCurrentPage() {
return currentPage;
}

public int getPageEndRow() {
return pageEndRow;
}

//是否有下一页
    public boolean isHasNextPage() {
return (currentPage < this.getTotalPages() ? true : false);
}

public int getTotalRows() {
return totalRows;
}

public int getPageStartRow() {
return pageStartRow;
}

public int getPageRecorders() {
return pageRecorders;
}

public void setObjList(List objList) {
this.objList = objList;
}

public void setHasPreviousPage(boolean hasPreviousPage) {
this.hasPreviousPage = hasPreviousPage;
}

public void setTotalPages(int totalPages) {
this.totalPages = totalPages;
}

public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}

public void setPageEndRow(int pageEndRow) {
this.pageEndRow = pageEndRow;
}

public void setHasNextPage(boolean hasNextPage) {
this.hasNextPage = hasNextPage;
}

public void setTotalRows(int totalRows) {
this.totalRows = totalRows;
}

public void setPageStartRow(int pageStartRow) {
this.pageStartRow = pageStartRow;
}

public void setPageRecorders(int pageRecorders) {
this.pageRecorders = pageRecorders;
}

public List getObjList() {
return objList;
}
}

在action中负责把pageIndex传给PageBean,以及通过service得到的记录总数传给pageBean就OK了

补充:另,在IDEA中文站上看到一篇文章  分页,心中的痛?       提到用一个统一的接口来规范:
代码如下:

public interface Page {
boolean isFirstPage();
boolean isLastPage();
boolean hasNextPage();
boolean hasPreviousPage();
int getLastPageNumber();
Object getThisPageElements();
int getTotalNumberOfElements();
int getThisPageFirstElementNumber();
int getThisPageLastElementNumber();
int getNextPageNumber();
int getPreviousPageNumber();
int getPageSize();
int getThisPageNumber ();
}

个人感觉思想挺好,不过我还是喜欢用一个PageBean类就足够了,没必要搞复杂了,在PageBean中其实是currentPage为核心.

一个工具能够在任何地方都能容易的嵌入进去,这就很小巧了,也就够用了.  :)

VN:F [1.6.3_896]
Rating: 0.0/10 (0 votes cast)
VN:F [1.6.3_896]
Rating: 0 (from 0 votes)

用javaScript操作两个页面

May 5, 2006

在新窗口中添加内容到父窗口

代码如下:
父窗口: form.html

<script language=JavaScript>
function addItems()
{
var AWnd=window.open(‘items.htm’,'fwId’,'resizable=yes,scrollbars=yes,width=300,height=400‘);
AWnd.focus();

}
function delItems()
{
var sel=document.menu.fwId;
for(i=0;i<=sel.options.length;i++)
{
if(sel.options[i]!=null)
if(sel.options[i].selected)
{
sel.options[i]
=null;
i
;
}
}
}
</script>

<form method=post name=menu>

<select name=fwId size=5 multiple>
</select>
<input name=item type=button onClick=addItems() value=Ìí¼Ó>
<input name=itemDel type=button onClick=delItems() value=ɾ³ý >
</form>

新开窗口items.html:

<script language=JavaScript>
function doSubmit(value,name)
{
var aa = window.opener.document;
var myop = aa.createElement(OPTION);

for(var j = 0; j < aa.menu.fwId.options.length; j++)
{
if(value == aa.menu.fwId.options[j].value)
{
alert(
ÒѾ­±»Ñ¡Ôñ£¡);
return;
}
}
myop.text 
=name;
myop.value 
=value;
aa.menu.fwId.add(myop);
}
</script>

<form name=items>
<a onclick=javascript:doSubmit(’1′,’test1′); href=#>test1</a><br>
<a onclick=javascript:doSubmit(’2′,’test2′); href=#>test2</a><br>
</form>

VN:F [1.6.3_896]
Rating: 0.0/10 (0 votes cast)
VN:F [1.6.3_896]
Rating: 0 (from 0 votes)