页面载入中...
首页 » 临时分类

十大网络防骗术 帮助你防范网络欺诈

2010年06月16日 10:31:45  来源: 华军软件园

最具威胁的网络安全事件

姜太公钓鱼,愿者上钩。在诈骗者眼中,所有人都是他们要钓的”鱼”,当然钓的不是你本身,而是你口袋中的钞票。网络钓鱼(Phishing)在网络上为你设下圈套,通过处心积虑的技术手段伪造出假可乱真的网站、E-Mail、短信等信息,诱惑你”自愿”交出重要信息(如银行账户密码)。网络钓鱼并不是一种新的入侵方法,但是它的危害范围却在逐渐扩大,成为最具威胁的网络安全事件。

2010年3月30日,中国互联网络信息中心(CNNIC)和国家互联网应急中心
(CNCERT)在京联合发布《2009年中国网民网络信息安全状况调查系列报告》。《报告》数据显示,2009年,52%的网民曾遭遇过网络安全事件,网民处理安全事件所支出的相关服务费用共计153亿元人民币。

中国反钓鱼网站联盟刚刚发布的最新月报显示,联盟受理并暂停域名解析的钓鱼网站为1785个,较3月增长70%,约有4500万网民因网络钓鱼蒙受损失。

图一:2010年4月中国反钓鱼网站联盟处理钓鱼网站的域名分类情况



图二:2010年4月中国反钓鱼网站联盟处理钓鱼网站的行业分类情况


2010年4月29日,EMC信息安全事业部RSA发布的《2010年全球网上消费者安全调查》结果显示:在接受调查的全球22个国家中,中国用户对强网站身份认证最积极,达到96.92%。

许多网络交易就被这一个个以假乱真的交易页面骗走了钱财,这种不愉快的经历让那些上当受骗的用户,对网络购物望而怯步。不仅如此,网络欺诈除了给网民带来经济损失,也给企业带来品牌形象损伤。严重地影响了在线金融服务、电子商务的发展,危害公众利益,影响公众应用互联网的信心。

网络骗术揭秘1:伪造金融网站、电子邮件 守株待兔网上”垂钓”

针对行业:银行业、证券业

【案例重现】

2010年3月11日,小何到公司后打开自己电子邮箱,发现收到”招商银行”为了加强账户安全升级系统的邮件通知,请客户尽快重新设置账户密码,邮件末尾还给出了设置密码的URL链接,小何不敢怠慢,立刻点击进入更改密码,而后泡上一杯咖啡便开始工作,下午下班到家,再次登陆网上银行却发现卡内3200元现金不翼而飞,卡内余额仅剩利息零头。

【骗术揭秘】

骗术揭秘:诈骗者一般都以银行、公安局等名义向公众散发短信、电子邮件等,急切要求你对某些关系到个人切身重大利益的事迅速做判断,很多人下意识地按照对方提示进行操作以致受骗,诈骗者则通过邮件中的”钓鱼网站”窃取受害者隐私。

伪造网站的域名和真正的银行网站差别很小,可能仅仅是一个字母的差别。真正网站的网址是http://www.cmbchina.com/,而伪造的网站域名则为:

http://www.cmbch1na.com/,仅是”i”和”1″的差别。受害者通过伪造网站”更改密码”时账号和密码就发送到了幕后的”垂钓者”手上,然后”垂钓者”登录上真正的网络银行改了受害者设置的密码,并将银行账户里的存款转移走。

网络骗术揭秘2:网络购物”鱼龙混杂” 正规电子商务网站购物也遭黑

针对行业:B2B、B2C等电子商务类网站

【案例重现】

2010年4月9日,接到女友购买陈奕迅演唱会门票的指示,陈先生登录淘宝网找到一家票价低于市场价近一半的卖家,交谈时卖家谎称旺旺有问题,提出通过QQ联络,以此避开了淘宝对交易过程的监控。耐心的帮助陈先生选择座位达成交易后,卖家又称自己另有一家网店并发来商品链接,希望陈先生通过新店的链接拍下门票,帮忙增加信用。陈先生毫无怀疑的支付货款后,卖家借口送票下线。但直到晚上9点,还没收到票,陈先生拨打骗子留下的电话是空号,马上登录淘宝发现账户内钱款已被盗。

【骗术揭秘】

低价骗诱法:诈骗者的商品标价往往比市场价格低将近一半,并以海关罚没、走私、朋友赠送等借口骗取信任。

拒绝安全支付法:以种种理由拒绝使用网站提供的第三方安全支付工具,比如谎称”账户最近出故障”等。

冒充公司销售法:诈骗者称自己是公司经营,然后找来多人多次与买家联系。比如有人打来电话说是该公司的财务,告知公司账号;有人说是经理,谈价格;有人说是公司的发货员,编造产品的发货流程等。其实,这都是为了骗取买家的信任。

伪造网站交易法:伪造与真实网站相似的假冒网站,并在交易中将假网站链接发送给买家,诱导买家在假网站页面输入交易密码,以窃取账户信息及钱财。

收取定金骗钱法:诈骗者要求先付10%左右的”定金或是保证金”,然后发货,之后,还会以种种看似合理的理由,诱使买家追加定金。

网络骗术揭秘3:网页挂马、植入病毒 窃取用户信息及钱财

针对行业:个人用户

【案例重现】

2010年4月29日,网店卖家小韩正往店里上传货品,一个买家通过QQ发来链接,问小韩该款商品有没有货,小韩毫无防备的打开了链接,看到是自己刚刚上传到店内的商品,就告诉买家新到的货,颜色非常齐全,可以放心购买。二十分钟后,见此人还没有拍下商品,小韩为争取做成这笔生意,便询问买家是否需要帮忙,买家留下一句”余额不够,充值后再买”便下线,此后小韩在自己的QQ好友再也找不到该买家的身影。某日因为要从网上进货,小韩习惯性的查看银行卡时发现余额为零。精通电脑的朋友告诉小韩,他的电脑中被植入了木马,时间正是与那个买家交谈的当天。

【骗术揭秘】

目前的网银盗号木马及其变种数以千计,诈骗者针对互联网用户进行特殊的设计,直接将网友访问的页面劫持到伪造的”钓鱼”页面并通过植入木马程序劫持用户访问网银页面时的浏览器数据,并记录键盘操作。一旦诈骗者”记录”下了密码,便可通过大众版网银以小额支付或转账的方式窃取钱财。目前,不法分子盗取网银的诈骗行为特别活跃,很多用户反馈自己被蒙蔽,造成的损失通常在上千元人民币。

网络骗术揭秘4:即时通讯工具散布中奖信息 诈骗高额钱财

针对行业:即时通讯工具用户

【案例重现】
2010年5月13日,周末没课的大二学生小周在宿舍上网,突然收到来自”腾讯客服”的”中奖”信息,被选为二等奖幸运用户,奖金2万元,另有一台数码相机。通过对方发来的网站链接,小周进入了”腾讯官方网站的活动专题页面”,页面醒目位置还链接到了”深圳市公证处”的官方网站,里面还公布了”颁奖照片”。小周按照网站提供的操作步骤,小周输入了验证码、真实姓名、身份证号、银行卡号、详细住址、联系方式等信息。一个月后小周不但没有收到”奖品”,更是连银行卡中的钱也无了踪影。

【骗术揭秘】

诈骗者冒充客服人员,发送大量的中奖通知,骗取网友的银行卡及个人身份信息,达到盗取银行存款的目的,或以个税等各类名义要求汇款,收到汇款后拖延时间要求再次汇款,直至销声匿迹。

诈骗者通过制作各类假冒的官方网站,引诱用户并骗取用户的信任。

诈骗者通过即时通讯工具,花言巧语诱使用户拨打声讯业务电话激活某项服务或听取网友留言,从而诈取用户高额通信费用。

【十大网络防骗术】

一、域名实名制从源头杜绝违法犯罪。域名实名制要求用户注册域名时,填写真实、准确、完整的注册信息。管理机构对域名申请单位的营业执照,法人代表,具体地址,经营规模是否真实可靠进行实质性的审查,并在相关行政机关备案。域名是互联网上的具有唯一性的标识,每一个域名的注册都是独一无二、不可重复的。实施了域名实名制之后,使得对互联网上的违法行为的监管变得更加容易,从源头上有效遏制了网络犯罪。

二、通过第三方网站身份诚信认证辨别网站真实性。目前不少网站已经在网站首页底部安装了第三方网站身份诚信认证,网民应首先通过第三方权威机构的网站资质信息(企业登记信息、网站域名注册信息等)来判断网站的真实身份,以规避网络风险。网民在应用电子商务网站时应养成查看网站身份信息的使用习惯。

三、使用数字证书。金融机构都为网上银行用户开通了数字证书服务,这些数字证书所具备的安全性,可以较好地保护银行用户的安全。这类的网站的网址都是”https”开头的。网民在网站输入自己的身份信息、银行帐号密码时候,如果发现网站地址不是”https”开头的,应谨慎对待,最好终止填写信息。

四、使用安全锁(即U盾)。在登录网上银行时,需将U盾插入电脑USB端口并输入U盾密码,如不小心泄露了网上银行用户名和密码,只要U盾仍然掌握在自己手中,或者连U盾也丢失但U盾的密码仍然掌握在自己手中,他人都无法登录你的网上银行。

五、如果您的网络账户中存在财产或重要的隐私信息,请在输入账号和密码前注意确认所在网站是否为官方网站。

六、对于网上出售的商品价格明显低于市场售价的应多加小心,更不要轻易打开对方发来的链接地址。拍下物品后不要立刻付款,关闭交易窗口,打开”已买到的宝贝”页面,确认购买成功后再付款。网上交易务必使用第三方支付平台,使用中应仔细核对网址是否正确。若实在无法使用第三方支付平台付款,最好选择货到付款。

七、安装正版安全软件,并定期打补丁和查杀,封堵住木马入侵的通道,以确保自己的电脑中没有木马。

八、勿轻信”中奖”消息–利用”中奖”骗取汇款是最常用的网络骗术。

九、不轻易拨打声讯业务的电话号码。如果欺诈者留下手机号码或者电话号码,可通过搜索引擎查询该号码的相关信息:如果号码属地与标示公司地距离太大的,就值得怀疑;如果同一号码的主人在网络上公布信息有天壤之别,就要小心;如果有网友公布的受骗记录中出现该号码,就很可能是网络欺诈。

十、发现受骗,要马上报警。妥善保管交易流水单等物证,为有关部门追查网络诈骗创造最佳时机。

js延时加载js广告代码,有write和writeln情况的复杂分析

js延时加载js广告代码,有write和writeln情况的复杂分析。有很多广告联盟的代码都是使用write和writeln来加载外部js文件的,但由于write和writeln的特殊性,一般的延时加载js并不适用——出现在新的空白页面中只显示广告的图片!在不改动原广告代码的要求下,只能多弯几下了——为了赚钱和更好的广告效果也是值得的:[原创来自] http://ruyice.com/demoblog/2010/10/js延时加载js广告代码,有write和writeln情况的复杂分析/

注意:下面的2个页面必须在同一文件目录下,且编码统一为utf8(gb2312未测);代码已经GG谷歌、FF火狐、IE6 浏览器兼容测试通过

ruyice.html代码

  1. <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
  2. <html xmlns=”http://www.w3.org/1999/xhtml”>
  3. <head>
  4. <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
  5. <meta content=”虚拟主机, 国外空间, PHP空间, 建站系统” name=keywords />
  6. <meta content=”如意盒.国外空间,PHP空间,美国虚拟主机,网站空间,带mysql数据库和企业邮局,像免费空间,更像免费国外空间——但我们跟踪服务,提供技术咨询。支持PHP建站系统,演示网站www.ruyice.com,欢迎大家共同学习建站技术=创造如意 分享如意” name=description />
  7. <title>如意盒</title>
  8. <script>
  9. /***********里面是前辈的成果***********/
  10. ///参考:http://bbs.blueidea.com/viewthread.php?tid=2440594
  11. // http://bbs.blueidea.com/viewthread.php?tid=2440594&page=1#pid2452228
  12. function write(objId,str){
  13. obj=document.getElementById(objId);
  14. obj.innerHTML+=str;
  15. }
  16. function writeln(objId,str){
  17. obj=document.getElementById(objId);
  18. obj.innerHTML+=”<br>”+str;
  19. }
  20. function set_innerHTML(objId, html) {
  21. obj=document.getElementById(objId);
  22. var ie = navigator.appVersion.match(/MSIE/);
  23. var opera = (navigator.userAgent.toLowerCase().indexOf(“opera”) != -1);
  24. if (ie && !opera) {
  25. html = ‘<span style=”display: none”>hack ie</span>’ + html;
  26. }
  27. obj.innerHTML = html;
  28. var scripts = obj.getElementsByTagName(“script”);
  29. if (scripts) {
  30. repstr=”write(‘”+objId+”‘,”
  31. repstr2=”writeln(‘”+objId+”‘,”
  32. for (var i = 0; i < scripts.length; i++) {
  33. script= scripts[i].text.replace(/document.write\(/ig,repstr).replace(/document.writeln\(/ig,repstr2);
  34. eval(script);
  35. }
  36. }
  37. }
  38. /**********外面的才是自己写的**********/
  39. objId = ‘guanggao’; //这个是需要一个id为guanggao的div或节点,必须存在但可以隐藏改节点
  40. //这个数组时放不含src的,如果有多条,类似['value1', 'value2', 'value3']来追加,可以htmls=[];留空,同下
  41. htmls = ['document.writeln("<script type=\"text\/javascript\"> \/*120*270,创建于2010-5-15*\/ alert(\'chenggong!ruyice\');<\/script>")',
  42. 'document.writeln("<script type=\"text\/javascript\"> \/*120*270,创建于2010-5-15*\/ alert(\'成功!如意\');<\/script>")'];
  43. //这个数组时放含js链接的,如果有多条,类似['value1', 'value2', 'value3']来追加
  44. jsurls = ['document.writeln("<script type=\"text\/javascript\" src=\"ruyice.js\"><\/script>")'];
  45. //上一行测试的是本地同一文件夹下的ruyice.js
  46. //jsurls = ['document.writeln("<script type=\"text\/javascript\" src=\"http:\/\/cpro.baidu.com\/cpro\/ui\/f.js\"><\/script>")'];
  47. //上1行是广告代码的示例,换成你自己的才能显示效果
  48. //writeJS函数定义;主要是针对有document.write或document.writeln的情况的广告代码!
  49. function writeJS(htmls, jsurls, objId)
  50. {
  51. if(htmls[0]){//万一没有则不需要执行,同下
  52. for(i=0; i < htmls.length; i++) {
  53. set_innerHTML(objId, htmls[i]);
  54. }
  55. }
  56. if(jsurls[0]){
  57. for(i=0; i < jsurls.length; i++) {
  58. temp1 = jsurls[i].indexOf( ’src=’ );
  59. temp2 = jsurls[i].indexOf( ‘.js’ );
  60. jsurl = jsurls[i].substr( (temp1+5), (temp2-temp1-2) );
  61. //动态添加js//使用 createElement 配合 appendChild 方法来创建新的 script
  62. newDom = document.createElement(“script”);
  63. newDom.setAttribute(‘language’, ‘JavaScript’);
  64. newDom.setAttribute(‘type’, ‘text/javascript’);
  65. newDom.setAttribute(’src’, jsurl);
  66. headDom = document.getElementsByTagName(‘head’)[0];
  67. headDom.appendChild( newDom );
  68. }
  69. }
  70. }
  71. window.onload = function () {
  72. ruyice = function () { writeJS(htmls, jsurls, objId); }
  73. setTimeout(“ruyice()”, “500″);//延时载入并显示广告效果,请修改间隔时间
  74. }
  75. /*
  76. //这个是另一种方案,但没有效果,因为innerHTML加入的script代码是无法立即执行的!!——保留做个见证
  77. //重写document.writeln方法;因为document.writeln不是直接调用的话,会把整个页面的内容变成这个函数的参数值!document是页面的根节点
  78. document.writeln = function(str)
  79. {
  80. //chaRuWeiZhi = document.getElementsByTagName(‘p’)[0];//这个使另一种获取节点的方法
  81. chaRuWeiZhi = document.getElementById(‘guanggao’);//id为guanggao的节点
  82. str = ‘<script type=”text\/javascript”>alert(“ccc”);<\/script>’ + str;
  83. chaRuWeiZhi.innerHTML+= ‘<br>’ + str ;
  84. document.writeln = oldWriteln;  //使用一次后就换回原来默认的函数!!
  85. }
  86. */
  87. </script>
  88. </head>
  89. <body>
  90. <DIV id=”logo”>
  91. <A href=”http://ruyice.com/” >《如意盒》免费PHP空间 国外空间|美国虚拟主机</A>
  92. <h1>《如意盒》免费PHP空间 国外空间|美国虚拟主机</h1>
  93. </DIV>
  94. <div id=”guanggao”>
  95. </div>
  96. <p>
  97. 《js延时加载js广告代码=有write和writeln情况的复杂分析》说明:<br />
  98. 主要修改 objId,htmls,jsurls 三个变量即可(如需改进,可以考虑htmls和jsurls统一成一个变量,后根据是否包含src来分别处理) <br />
  99. 必须存在id为 guanggao(与objId的值相等即可) 的节点,该节点可以隐藏<br />
  100. 本代码适用于绝大多数延迟加载显示浮动广告图片(针对广告联盟的代码有write或writeln的情况),且极少数可能出错——如果不是载入广告js是使用writeln<br />
  101. !其中没有放入广告代码实际来测试,有可能遇到跨域访问的相关问题(如果那样-又需要很多很多兼容代码了,可能还需使用ajax!有money才call我吧)
  102. </p>
  103. </body>
  104. </HTML>

ruyice.js代码;

  1. alert(‘延时加载了外部js,并此js立即执行。看到这你就成功了,可以到《如意盒》免费PHP空间玩玩了~-~’);

PHP操作mysql数据库的基础类,面向对象带注释

PHP操作mysql数据库的基础类,面向对象带注释。其中还另外附加了部分功能:向指定表中插入数据function insertData($dbname,$data)

ServerName,UserName,PassWord,DBName 这几个参数使用
define(“UserName”, “??”); //数据库连接用户名
define(“PassWord”, “??”); //数据库连接密码
define(“ServerName”, “??”); //数据库服务器的名称
define(“DBName”,”??”); //数据库名称

/**
功能:数据库的基础操作类
**/
//include("../config.inc.php");//本系统在每个页面前都调用了此文件,这里不用再次调用
class DB{
private $CONN = ""; //定义数据库连接变量
/**
* 功能:初始化构造函数,连接数据库
* 参数:
* 返回:数据库连接$conn
*/
public function __construct(){
try { //捕获连接错误并显示错误文件
$conn = mysql_connect(ServerName,UserName,PassWord);
}catch (Exception $e)
{
$msg = $e;
include(ERRFILE);
}
try { //捕获数据库选择错误并显示错误文件
mysql_select_db(DBName,$conn);
mysql_query("set names utf8"); //另外限定编码类型!
}catch (Exception $e)
{
$msg = $e;
include(ERRFILE);
}
$this->CONN = $conn;
}
/**
* 功能:数据库查询函数
* 参数:$sql SQL语句
* 返回:键值为字段名的数组或false
*/
public function select($sql = ""){
if (empty($sql)) return false; //如果SQL语句为空则返回FALSE
if (empty($this->CONN)) return false; //如果连接为空则返回FALSE
try{ //捕获数据库选择错误并显示错误文件
$results = mysql_query($sql,$this->CONN);
}catch (Exception $e){
$msg = $e;
include(ERRFILE);
}
if ((!$results) or (empty($results))) { //如果查询结果为空则释放结果并返回FALSE
@mysql_free_result($results);
return false;
}

$count = 0;
$data = array();

while ($row = @mysql_fetch_assoc($results)) { //把查询结果重组成一个键值为字段名的一维数组
$data[$count] = $row;
$count++;
}
@mysql_free_result($results);
return $data;
}
/**
* 功能:数据插入函数
* 参数:$sql SQL语句
* 返回:0或新插入数据的id
*/
public function insert($sql = ""){
if (empty($sql)) return 0; //如果SQL语句为空则返回FALSE
if (empty($this->CONN)) return 0; //如果连接为空则返回FALSE
try{ //捕获数据库选择错误并显示错误文件
$results = mysql_query($sql,$this->CONN);
}catch(Exception $e){
$msg = $e;
include(ERRFILE);
}
if (!$results) //如果插入失败返回0,否则返回当前插入数据id
return 0;
else
return @mysql_insert_id($this->CONN);
}

/**
* 功能:数据更新函数
* 参数:$sql SQL语句
* 返回:TRUE OR FALSE
*/
public function update($sql = ""){
if(empty($sql)) return false; //如果SQL语句为空则返回FALSE
if(empty($this->CONN)) return false; //如果连接为空则返回FALSE
try{ //捕获数据库选择错误并显示错误文件
$result = mysql_query($sql,$this->CONN);
}catch(Exception $e){
$msg = $e;
include(ERRFILE);
}
return $result;
}
/**
* 功能:数据删除函数
* 参数:$sql SQL语句
* 返回:TRUE OR FALSE
*/
public function delete($sql = ""){
if(empty($sql)) return false; //如果SQL语句为空则返回FALSE
if(empty($this->CONN)) return false; //如果连接为空则返回FALSE
try{
$result = mysql_query($sql,$this->CONN);
}catch(Exception $e){
$msg = $e;
include(ERRFILE);
}
return $result;
}

/**
* 功能:定义事务
*/
public function begintransaction()
{
mysql_query("SET AUTOCOMMIT=0"); //设置为不自动提交,因为MYSQL默认立即执行
mysql_query("BEGIN"); //开始事务定义
}
/**
* 功能:回滚
*/
public function rollback()
{
mysql_query("ROOLBACK");
}
/**
* 功能:提交执行
*/
public function commit()
{
mysql_query("COMMIT");
}

/**
* 功能:提取指定表的指定id的记录,默认是比赛表的
* 参数:$id 表id,$dbname 表名称,$where id所对应的字段
* 返回:表中符合条件所有行,只一行则返回一维数组,2行以上返回2维数组{符合条件所有行}
*/
public function getInfo($id,$dbname,$where="bs_id")
{
$sql = "SELECT * FROM " . $dbname . " WHERE $where = '".$id."'";
$r = $this->select($sql);

if (isset($r[1])) {
return $r;
}else{
return $r[0];
}
//return $r[0];
}

/**
* 功能:向指定表中插入数据
* 参数:$dbname 表名称,$data 数组(格式:$data['字段名'] = 值)
* 返回:插入记录id
*/
public function insertData($dbname,$data)
{
$field = implode(',',array_keys($data)); //定义sql语句的字段部分
$i = 0;
foreach($data as $key => $val) //组合sql语句的值部分
{
$value.= "'" . $val . "'";
if($i < count($data) - 1) //判断是否到数组的最后一个值
$value.= ",";
$i++;
}
$sql = "INSERT INTO " . $dbname . " (" . $field . ") VALUES(" . $value . ")";
return $this->insert($sql);
}
/**
* 功能:更新指定表指定id的调查表记录(默认是操作比赛表的,但选手表不适用此函数)
* 参数:$dbname 表名称,$id 表id,$data 数组(格式:$data['字段名'] = 值)
* 返回:TRUE OR FALSE
*/
public function updateData($dbname,$id,$data,$where="bs_id"){
$col = array();
foreach ($data as $key => $value)
{
$col[] = $key . "='" . $value . "'";
}
$sql = "UPDATE " . $dbname . " SET " . implode(',',$col) . " WHERE $where = $id";
return $this->update($sql);
}

/**
* 功能:删除指定id的表记录(默认是操作比赛表的,选手表不适用此函数)
* 参数:$id表id,$dbname 表名称
* 返回:TRUE OR FALSE
*/
public function delData($id,$dbname,$where="bs_id")
{
$sql = "DELETE FROM " . $dbname . " WHERE $where = '".$id."'";
return $this->delete($sql);
}
}

?>

美国空间-建站展示

ruyice_blog.gif ruyice_bbs.gif ruyice_bp.gif

PHP GIF动画生成类

<?
class GifMerge {
var
$ver = '1.1' ;
var
$dly = 50 ;
var
$mod = 'C_FILE' ;
var
$first = true ;
var
$use_loop = false ;
var
$transparent = false ;
var
$use_global_in = false ;
var
$x = 0 ;
var
$y = 0 ;
var
$ch = 0 ;
var
$fin = 0 ;
var
$fout = '' ;
var
$loop = 0 ;
var
$delay = 0 ;
var
$width = 0 ;
var
$height = 0 ;
var
$trans1 = 255 ;
var
$trans2 = 255 ;
var
$trans3 = 255 ;
var
$disposal = 2 ;
var
$out_color_table_size = 0 ;
var
$local_color_table_flag = 0 ;
var
$global_color_table_size = 0 ;
var
$out_color_table_sizecode = 0 ;
var
$global_color_table_sizecode = 0 ;
var
$gif = array( 0x47 , 0x49 , 0x46 );
var
$buffer = array();
var
$local_in = array();
var
$global_in = array();
var
$global_out = array();
var
$logical_screen_descriptor = array();

function
GifMerge ( $images , $t1 , $t2 , $t3 , $loop , $dl , $xpos , $ypos , $model ) {
if(
$model ) {
$this -> mod = $model ;
}
if(
$loop > - 1 ) {
$this -> loop = floor ( $loop - 1 );
$this -> use_loop = true ;
}
if(
$t1 > - 1 && $t2 > - 1 && $t3 > - 1 ) {
$this -> trans1 = $t1 ;
$this -> trans2 = $t2 ;
$this -> trans3 = $t3 ;
$this -> transparent = true ;
}
for(
$i = 0 ; $i < count ( $images ); $i ++) {
$dl [ $i ] ? $this -> delay = $dl [ $i ] : $this -> delay = $this -> dly ;
$xpos [ $i ] ? $this -> x = $xpos [ $i ] : $this -> x = 0 ;
$ypos [ $i ] ? $this -> y = $ypos [ $i ] : $this -> y = 0 ;
$this -> start_gifmerge_process ( $images [ $i ]);
}
$this -> fout .= "\x3b" ;
}

function
start_gifmerge_process ( $fp ) {
if(
$this -> mod == 'C_FILE' ) {
if(!
$this -> fin = fopen ( $fp , 'rb' )) {
return;
}
} elseif(
$this -> mod == 'C_MEMORY' ) {
$this -> ch = 0 ;
$this -> fin = $fp ;
}
$this -> getbytes ( 6 );
if(!
$this -> arrcmp ( $this -> buffer , $this -> gif , 3 )) {
return;
}
$this -> getbytes ( 7 );
if(
$this -> first ) $this -> logical_screen_descriptor = $this -> buffer ;
$this -> global_color_table_sizecode = $this -> buffer [ 4 ] & 0x07 ;
$this -> global_color_table_size = 2 << $this -> global_color_table_sizecode ;
if(
$this -> buffer [ 4 ] & 0x80 ) {
$this -> getbytes (( 3 * $this -> global_color_table_size ));
for(
$i = 0 ; $i < (( 3 * $this -> global_color_table_size )); $i ++) {
$this -> global_in [ $i ] = $this -> buffer [ $i ];
}
if(
$this -> out_color_table_size == 0 ) {
$this -> out_color_table_size = $this -> global_color_table_size ;
$out_color_table_sizecode = $this -> global_color_table_sizecode ;
$this -> global_out = $this -> global_in ;
}
if(
$this -> global_color_table_size != $this -> out_color_table_size || $this -> arrcmp ( $this -> global_out , $this -> global_in , ( 3 * $this -> global_color_table_size ))) {
$this -> use_global_in = true ;
}
}
for(
$loop = true ; $loop ;) {
$this -> getbytes ( 1 );
switch(
$this -> buffer [ 0 ]) {
case
0x21 :
$this -> read_extension ();
break;
case
0x2c :
$this -> read_image_descriptor ();
break;
case
0x3b :
$loop = false ;
break;
default:
$loop = false ;
}
}
if(
$this -> mod == 'C_FILE' ) {
fclose ( $this -> fin );
}
}

function
read_image_descriptor () {
$this -> getbytes ( 9 );
$head = $this -> buffer ;
$this -> local_color_table_flag = ( $this -> buffer [ 8 ] & 0x80 ) ? true : false ;
if(
$this -> local_color_table_flag ) {
$sizecode = $this -> buffer [ 8 ] & 0x07 ;
$size = 2 << $sizecode ;
$this -> getbytes ( 3 * $size );
for(
$i = 0 ; $i < ( 3 * $size ); $i ++) {
$this -> local_in [ $i ] = $this -> buffer [ $i ];
}
if(
$this -> out_color_table_size == 0 ) {
$this -> out_color_table_size = $size ;
$out_color_table_sizecode = $sizecode ;
for(
$i = 0 ; $i < ( 3 * $size ); $i ++)
{
$this -> global_out [ $i ] = $this -> local_in [ $i ];
}
}
}
if(
$this -> first ) {
$this -> first = false ;
$this -> fout .= "\x47\x49\x46\x38\x39\x61" ;
if(
$this -> width && $this -> height ) {
$this -> logical_screen_descriptor [ 0 ] = $this -> width & 0xFF ;
$this -> logical_screen_descriptor [ 1 ] = ( $this -> width & 0xFF00 ) >> 8 ;
$this -> logical_screen_descriptor [ 2 ] = $this -> height & 0xFF ;
$this -> logical_screen_descriptor [ 3 ] = ( $this -> height & 0xFF00 ) >> 8 ;
}
$this -> logical_screen_descriptor [ 4 ] |= 0x80 ;
$this -> logical_screen_descriptor [ 5 ] &= 0xF0 ;
$this -> logical_screen_descriptor [ 6 ] |= $this -> out_color_table_sizecode ;
$this -> putbytes ( $this -> logical_screen_descriptor , 7 );
$this -> putbytes ( $this -> global_out , ( $this -> out_color_table_size * 3 ));
if(
$this -> use_loop ) {
$ns [ 0 ] = 0x21 ;
$ns [ 1 ] = 0xFF ;
$ns [ 2 ] = 0x0B ;
$ns [ 3 ] = 0x4e ;
$ns [ 4 ] = 0x45 ;
$ns [ 5 ] = 0x54 ;
$ns [ 6 ] = 0x53 ;
$ns [ 7 ] = 0x43 ;
$ns [ 8 ] = 0x41 ;
$ns [ 9 ] = 0x50 ;
$ns [ 10 ] = 0x45 ;
$ns [ 11 ] = 0x32 ;
$ns [ 12 ] = 0x2e ;
$ns [ 13 ] = 0x30 ;
$ns [ 14 ] = 0x03 ;
$ns [ 15 ] = 0x01 ;
$ns [ 16 ] = $this -> loop & 255 ;
$ns [ 17 ] = $this -> loop >> 8 ;
$ns [ 18 ] = 0x00 ;
$this -> putbytes ( $ns , 19 );
}
}
if(
$this -> use_global_in ) {
$outtable = $this -> global_in ;
$outsize = $this -> global_color_table_size ;
$outsizecode = $this -> global_color_table_sizecode ;
} else {
$outtable = $this -> global_out ;
$outsize = $this -> out_color_table_size ;
}
if(
$this -> local_color_table_flag ) {
if(
$size == $this -> out_color_table_size && ! $this -> arrcmp ( $this -> local_in , $this -> global_out , $size )) {
$outtable = $global_out ;
$outsize = $this -> out_color_table_size ;
} else {
$outtable = $this -> local_in ;
$outsize = $size ;
$outsizecode = $sizecode ;
}
}
$use_trans = false ;
if(
$this -> transparent ) {
for(
$i = 0 ; $i < $outsize ; $i ++) {
if(
$outtable [ 3 * $i ] == $this -> trans1 && $outtable [ 3 * $i + 1 ] == $this -> trans2 && $outtable [ 3 * $i + 2 ] == $this -> trans3 ) {
break;
}
}
if(
$i < $outsize ) {
$transindex = $i ;
$use_trans = true ;
}
}
if(
$this -> delay || $use_trans ) {
$this -> buffer [ 0 ] = 0x21 ;
$this -> buffer [ 1 ] = 0xf9 ;
$this -> buffer [ 2 ] = 0x04 ;
$this -> buffer [ 3 ] = ( $this -> disposal << 2 ) + ( $use_trans ? 1 : 0 );
$this -> buffer [ 4 ] = $this -> delay & 0xff ;
$this -> buffer [ 5 ] = ( $this -> delay & 0xff00 ) >> 8 ;
$this -> buffer [ 6 ] = $use_trans ? $transindex : 0 ;
$this -> buffer [ 7 ] = 0x00 ;
$this -> putbytes ( $this -> buffer , 8 );
}
$this -> buffer [ 0 ] = 0x2c ;
$this -> putbytes ( $this -> buffer , 1 );
$head [ 0 ] = $this -> x & 0xff ;
$head [ 1 ] = ( $this -> x & 0xff00 ) >> 8 ;
$head [ 2 ] = $this -> y & 0xff ;
$head [ 3 ] = ( $this -> y & 0xff00 ) >> 8 ;
$head [ 8 ] &= 0x40 ;
if(
$outtable != $this -> global_out ) {
$head [ 8 ] |= 0x80 ;
$head [ 8 ] |= $outsizecode ;
}
$this -> putbytes ( $head , 9 );
if(
$outtable != $this -> global_out ) {
$this -> putbytes ( $outtable , ( 3 * $outsize ));
}
$this -> getbytes ( 1 );
$this -> putbytes ( $this -> buffer , 1 );
for(;;) {
$this -> getbytes ( 1 );
$this -> putbytes ( $this -> buffer , 1 );
if((
$u = $this -> buffer [ 0 ]) == 0 ) {
break;
}
$this -> getbytes ( $u );
$this -> putbytes ( $this -> buffer , $u );
}
}

function
read_extension () {
$this -> getbytes ( 1 );
switch(
$this -> buffer [ 0 ]) {
case
0xf9 :
$this -> getbytes ( 6 );
break;
case
0xfe :
for(;;) {
$this -> getbytes ( 1 );
if((
$u = $this -> buffer [ 0 ]) == 0 ) {
break;
}
$this -> getbytes ( $u );
}
break;
case
0x01 :
$this -> getbytes ( 13 );
for(;;) {
$this -> getbytes ( 0 );
if((
$u = $this -> buffer [ 0 ]) == 0 ) {
break;
}
$this -> getbytes ( $u );
}
break;
case
0xff :
$this -> getbytes ( 9 );
$this -> getbytes ( 3 );
for(;;) {
$this -> getbytes ( 1 );
if(!
$this -> buffer [ 0 ]) {
break;
}
$this -> getbytes ( $this -> buffer [ 0 ]);
}
break;
default:
for(;;) {
$this -> getbytes ( 1 );
if(!
$this -> buffer [ 0 ]) {
break;
}
$this -> getbytes ( $this -> buffer [ 0 ]);
}
}
}

function
arrcmp ( $b , $s , $l ) {
for(
$i = 0 ; $i < $l ; $i ++) {
if(
$s { $i } != $b { $i }) {
return
false ;
}
}
return
true ;
}

function
getbytes ( $l ) {
for(
$i = 0 ; $i < $l ; $i ++) {
if(
$this -> mod == 'C_FILE' ) {
$bin = unpack ( 'C*' , fread ( $this -> fin , 1 ));
$this -> buffer [ $i ] = $bin [ 1 ];
} elseif(
$this -> mod == 'C_MEMORY' ) {
$bin = unpack ( 'C*' , substr ( $this -> fin , $this -> ch , 1 ));
$this -> buffer [ $i ] = $bin [ 1 ];
$this -> ch ++;
}
}
return
$this -> buffer ;
}

function
putbytes ( $s , $l ) {
for(
$i = 0 ; $i < $l ; $i ++) {
$this -> fout .= pack ( 'C*' , $s [ $i ]);
}
}

function
getAnimation () {
return
$this -> fout ;
}
}

?>


算法的力量(转李开复)—适合计算机专业新生

算法的力量
2006年5月

算法是计算机科学领域最重要的基石之一,但却受到了国内一些程序员的冷落。许多学生看到一些公司在招聘时要求的编程语言五花八门,就产生了一种误解,认为学计算机就是学各种编程语言,或者认为,学习最新的语言、技术、标准就是最好的铺路方法。其实,大家被这些公司误导了。编程语言虽然该学,但是学习计算机算法和理论更重要,因为计算机语言和开发平台日新月异,但万变不离其宗的是那些算法和理论,例如数据结构、算法、编译原理、计算机体系结构、关系型数据库原理等等。在”开复学生网”上,有位同学生动地把这些基础课程比拟为”内功”,把新的语言、技术、标准比拟为”外功”。整天赶时髦的人最后只懂得招式,没有功力,是不可能成为高手的。

算法与我

当我在1980年转入计算机科学系时,还没有多少人的专业方向是计算机科学。有许多其他系的人嘲笑我们说:”知道为什么只有你们系要加一个’科学’,而没有’物理科学系’或’化学科学系’吗?因为人家是真的科学,不需要画蛇添足,而你们自己心虚,生怕不’科学’,才这样欲盖弥彰。” 其实,这点他们彻底弄错了。真正学懂计算机的人(不只是”编程匠”)都对数学有相当的造诣,既能用科学家的严谨思维来求证,也能用工程师的务实手段来解决问题–而这种思维和手段的最佳演绎就是”算法”。

记得我读博时写的Othello对弈软件获得了世界冠军。当时,得第二名的人认为我是靠侥幸才打赢他,不服气地问我的程序平均每秒能搜索多少步棋,当他发现我的软件在搜索效率上比他快60多倍时,才彻底服输。为什么在同样的机器上,我可以多做60倍的工作呢?这是因为我用了一个最新的算法,能够把一个指数函数转换成四个近似的表,只要用常数时间就可得到近似的答案。在这个例子中,是否用对算法才是能否赢得世界冠军的关键。

还记得1988年贝尔实验室副总裁亲自来访问我的学校,目的就是为了想了解为什么他们的语音识别系统比我开发的慢几十倍,而且,在扩大至大词汇系统后,速度差异更有几百倍之多。他们虽然买了几台超级计算机,勉强让系统跑了起来,但这么贵的计算资源让他们的产品部门很反感,因为”昂贵”的技术是没有应用前景的。在与他们探讨的过程中,我惊讶地发现一个O(n*m)的动态规划(dynamic programming)居然被他们做成了O(n*n*m)。更惊讶的是,他们还为此发表了不少文章,甚至为自己的算法起了一个很特别的名字,并将算法提名到一个科学会议里,希望能得到大奖。当时,贝尔实验室的研究员当然绝顶聪明,但他们全都是学数学、物理或电机出身,从未学过计算机科学或算法,才犯了这么基本的错误。我想那些人以后再也不会嘲笑学计算机科学的人了吧!

网络时代的算法

有人也许会说:”今天计算机这么快,算法还重要吗?”其实永远不会有太快的计算机,因为我们总会想出新的应用。虽然在摩尔定律的作用下,计算机的计算能力每年都在飞快增长,价格也在不断下降。可我们不要忘记,需要处理的信息量更是呈指数级的增长。现在每人每天都会创造出大量数据(照片,视频,语音,文本等等)。日益先进的记录和存储手段使我们每个人的信息量都在爆炸式的增长。互联网的信息流量和日志容量也在飞快增长。在科学研究方面,随着研究手段的进步,数据量更是达到了前所未有的程度。无论是三维图形、海量数据处理、机器学习、语音识别,都需要极大的计算量。在网络时代,越来越多的挑战需要靠卓越的算法来解决。

再举另一个网络时代的例子。在互联网和手机搜索上,如果要找附近的咖啡店,那么搜索引擎该怎么处理这个请求呢?

最简单的办法就是把整个城市的咖啡馆都找出来,然后计算出它们的所在位置与你之间的距离,再进行排序,然后返回最近的结果。但该如何计算距离呢?图论里有不少算法可以解决这个问题。

这么做也许是最直观的,但绝对不是最迅速的。如果一个城市只有为数不多的咖啡馆,那这么做应该没什么问题,反正计算量不大。但如果一个城市里有很多咖啡馆,又有很多用户都需要类似的搜索,那么服务器所承受的压力就大多了。在这种情况下,我们该怎样优化算法呢?

首先,我们可以把整个城市的咖啡馆做一次”预处理”。比如,把一个城市分成若干个”格子(grid)”,然后根据用户所在的位置把他放到某一个格子里,只对格子里的咖啡馆进行距离排序。

问题又来了,如果格子大小一样,那么绝大多数结果都可能出现在市中心的一个格子里,而郊区的格子里只有极少的结果。在这种情况下,我们应该把市中心多分出几个格子。更进一步,格子应该是一个”树结构”,最顶层是一个大格–整个城市,然后逐层下降,格子越来越小,这样有利于用户进行精确搜索–如果在最底层的格子里搜索结果不多,用户可以逐级上升,放大搜索范围。

上述算法对咖啡馆的例子很实用,但是它具有通用性吗?答案是否定的。把咖啡馆抽象一下,它是一个”点”,如果要搜索一个”面”该怎么办呢?比如,用户想去一个水库玩,而一个水库有好几个入口,那么哪一个离用户最近呢?这个时候,上述”树结构”就要改成”r-tree”,因为树中间的每一个节点都是一个范围,一个有边界的范围(参考:http://www.cs.umd.edu/~hjs/rtrees/index.html)。

通过这个小例子,我们看到,应用程序的要求千变万化,很多时候需要把一个复杂的问题分解成若干简单的小问题,然后再选用合适的算法和数据结构。

并行算法:Google的核心优势

上面的例子在Google里就要算是小case了!每天Google的网站要处理十亿个以上的搜索,GMail要储存几千万用户的2G邮箱,Google Earth要让数十万用户同时在整个地球上遨游,并将合适的图片经过互联网提交给每个用户。如果没有好的算法,这些应用都无法成为现实。

在这些的应用中,哪怕是最基本的问题都会给传统的计算带来很大的挑战。例如,每天都有十亿以上的用户访问Google的网站,使用Google的服务,也产生很多很多的日志(Log)。因为Log每分每秒都在飞速增加,我们必须有聪明的办法来进行处理。我曾经在面试中问过关于如何对log进行一些分析处理的问题,有很多面试者的回答虽然在逻辑上正确,但在实际应用中是几乎不可行的。按照他们的算法,即便用上几万台机器,我们的处理速度都跟不上数据产生的速度。

那么Google是如何解决这些问题的呢?

首先,在网络时代,就算有最好的算法,也要能在并行计算的环境下执行。在Google的数据中心,我们使用的是超大的并行计算机。但传统的并行算法运行时,效率会在增加机器数量后迅速降低,也就是说,十台机器如果有五倍的效果,增加到一千台时也许就只有几十倍的效果。这种事倍功半的代价是没有哪家公司可以负担得起的。而且,在许多并行算法中,只要一个结点犯错误,所有计算都会前功尽弃。

那么Google是如何开发出既有效率又能容错的并行计算的呢?

Google最资深的计算机科学家Jeff Dean认识到, Google 所需的绝大部分数据处理都可以归结为一个简单的并行算法:Map and Reduce(http://labs.google.com/papers/mapreduce.html)。 这个算法能够在很多种计算中达到相当高的效率,而且是可扩展的(也就是说,一千台机器就算不能达到一千倍的效果,至少也可以达到几百倍的效果)。Map and Reduce的另外一大特色是它可以利用大批廉价的机器组成功能强大的server farm。最后,它的容错性能异常出色,就算一个server farm里面的机器down掉一半,整个farm依然能够运行。正是因为这个天才的认识,才有了Map and Reduce算法。借助该算法,Google几乎能无限地增加计算量,与日新月异的互联网应用一同成长。

算法并不局限于计算机和网络

举一个计算机领域外的例子:在高能物理研究方面,很多实验每秒钟都产生几个TB的数据量。但因为处理能力和存储能力的不足,科学家不得不把绝大部分未经处理的数据丢弃掉。可大家要知道,新元素的信息很有可能就藏在我们来不及处理的数据里面。同样的,在其他任何领域里,算法都可以改变人类的生活。例如人类基因的研究,就可能因为算法而发明新的医疗方式。在国家安全领域,有效的算法可能避免下一个911的发生。在气象方面,算法可以更好地预测未来天灾的发生,以拯救生命。

所以,如果你把计算机的发展放到应用和数据飞速增长的大环境下,你一定会发现,算法的重要性不是在日益减小,而是在日益加强。

给程序员的七个建议

(1)练内功。不要只花功夫学习各种流行的编程语言和工具,以及某些公司招聘广告上要求的科目。要把数据结构、算法、数据库、操作系统原理、计算机体系结构、计算机网络,离散数学等基础课程学好。大家不妨试试高德纳所著The Art of Computer Programming里的题目,如果你能够解决其中的大部分题目,就说明你在算法方面有一定的功力了。

(2)多实战。通过编程的实战积累经验、巩固知识。很多中国大学毕业生缺乏编程和调试经验;学习C语言,考试过关就算学会了;课题项目中,只要程序能够编译,运行,并且输入输出满足要求就算了事。这些做法是不行的。写程序的时候,大家必须多想想如何把程序写得更加精炼、高效、高质量。建议大家争取在大学四年中积累编写十万行代码的经验。我们必须明白的是:好程序员是写出来的,不是学出来的。

(3)求实干。不要轻视任何实际工作,比如一些看似简单的编码或测试。要不懈追求对细节一丝不苟的实干作风与敬业精神。我发现不少程序员对于知识的掌握很肤浅,不求甚解,没有好奇心,不会刨根问底。比如,学会了C++,是否了解一个对象在编译后,在汇编代码中是如何被初始化的?这个对象的各个成员在内存中是如何存放的?当一个成员函数被调用时,编译器在汇编代码中加入了哪些额外的动作?虚函数的调用是如何实现的? 这些东西恐怕在编程语言或编译原理中都没有详细提到,只有通过踏实的实干才能真正掌握。

(4)重视数学学习。数学是思维的体操,数学无处不在。学计算机至少要学习离散数学、概率论、布尔代数、集合论和数理逻辑。这些知识并不难,但是对你未来的工作帮助会很大。 尤其当你对一些”数学密集型”的领域如视频、图像处理等有兴趣时,这些知识将成为你手中的利器。

(5)培养团队精神,学会与人合作。今天的软件工程早已经不是一个人可以单独操作的,而必须靠团队合作才能成功。不懂得合作的人是不能成大器的。大家要多去寻找可以与人一起做项目的机会。

(6)激励创新意识,培养好奇心,不要死记硬背。没有掌握某种算法技术的根本原理,就不会有应变和创新的能力。想成为一位好程序员(其实从事任何一个行业都是如此),重要的是要养成钻研,好奇,创新,动手,合作的优秀习惯,不满足于填鸭,不满足于考试交差,不满足于表象。这不是学几门课能够一蹴而就的。

(7)有策略地”打工”。在不影响学业的前提下,寻找真正有意义的暑期工作或兼职。去找一个重视技术的公司,在一个好的”老板”指导下完成真正会被用户使用的程序。不要急于去一个要你做”头”而独挡一面的地方,因为向别人学习才是你的目的。找工作也是一样,不要只看待遇和职衔,要挑一个你能够学习的环境,一个愿意培养员工的企业,一个重视你的专业的公司。最后,还要挑一个好老板。

希望大家都能把握机会,养成好的学习习惯,把算法学精学透;希望大家都能有一个美好的未来!

个人标注:纯粹的程序员

一些很常用的JS方法

引用地址:http://www.baseclass.com.cn/article.asp?id=69

简化document.getElementById
用法:
$id(“d”).innerHTML;
(HTMLcode:<div id=”d”>cssrain</div>)
**************/
function $id(id) {
return document.getElementById(id);
}


/**************
函数:getElementsByClassName
使用方法:
获取document内的超链接class是”info-links”的。
getElementsByClassName(document, “a”, “info-links”);
获取container内的div的class是col的.
getElementsByClassName(document.getElementById(“container”), “div”, “col”);
获取document内的所有class是”click-me”的。
getElementsByClassName(document, “*”, “click-me”);
例子:
HTML code:
<a class=”a”>ccc</a>
<a class=”info-links”>aaa</a>
<a class=”info-links”>bbb</a>
<br/><br/>
<div class=”co”>dddd</div>
<div class=”col”>dddd</div>
<div id=”container”>
<div class=”co”>dddd</div>
<div class=”col”>dddd</div>
<div class=”co”>dddd</div>
<div class=”col”>dddd</div>
<a class=”a”>ccc</a>
</div>

JS code:
test 1 :
var a = getElementsByClassName(document,”a”,”info-links”);
alert(a[0].innerHTML +” “+a[1].innerHTML);
for(var i=0;i<a.length;i++){
a[i].style.color=”red”;
}
//test 2 :
var b = getElementsByClassName(document.getElementById(“container”), “div”, “col”);
for(var m=0;m<b.length;m++){
b[m].style.color=”red”;
}
**************/
function getElementsByClassName(oElm, strTagName, strClassName){
var arrElements = (strTagName == “*” && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
var arrReturnElements = new Array();
strClassName = strClassName.replace(/-/g, “\-”);
var oregExp = new RegExp(“(^|\s)” + strClassName + “(\s|$)”);
var oElement;
for(var i=0; i<arrElements.length; i++){
oElement = arrElements[i];
if(oRegExp.test(oElement.className)){
arrReturnElements.push(oElement);
}
}
return (arrReturnElements)
}




/**************
replaceAll:
替换字符串中的字符。
用法:
yourstring.replaceAll(“要替换的字符”, “替换成什么”);
例子:
“cssrain”.replaceAll(“s”, “a”);
” cs sr ai n”.replaceAll(” “, “”);
**************/
String.prototype.replaceAll = function (AFindText,ARepText){
raRegExp = new RegExp(AFindText,”g”);
return this.replace(raRegExp,ARepText);
}


/**************
* 字符串前后空格处理。
* 如果想替换中间的空格,请用replaceAll方法。
* 用法:
* ” cssrain “.trim();
**************/
String.prototype.trim=function()
{
return this.replace(/(^\s*)|(\s*$)/g,”");//将字符串前后空格,用空字符串替代。
}


/**************
* 计算字符串的真正长度
//String有个属性length,但是它不能区分英文字符,
//计算中文字符和全角字符。但是在数据存储的时候中文和全角都是用两个字节来存储的,
//所有需要额外处理一下。自己写了个函数,返回String正真的长度.
用法:
<input type=”text” name=”rain” id=”rain” />
<input type=”button” id=”test” value=”test” onclick=”alert( document.getElementById(‘rain’).value.codeLength() )”/>
**************/
String.prototype.codeLength=function(){
var len=0;
if(this==null||this.length==0)
return 0;
var str=this.replace(/(^\s*)|(\s*$)/g,”");//去掉空格
for(i=0;i<str.length;i++)
if(str.charCodeAt(i)>0&&str.charCodeAt(i)<128)
len++;
else
len+=2;
return len;
}


//JS获取字符串的实际长度,用来代替 String的length属性
String.prototype.length = function(){
return this.replace.(/[\u4e00-\u9fa5]+/g,”**”).length;
}



/**************
//编码HTML 和 解码Html。
//在评论的时候为了防止用户提交带有恶意的脚本,可以先过滤HTML标签,过滤掉双引号,单引号,符号&,符号<,符号
用法:
<input type=”text” name=”rain” id=”rain” />
<input type=”button” value=”test” onclick=” document.getElementById(‘rain2′).value= document.getElementById(‘rain’).value.htmlEncode() “/>
<input type=”text” name=”rain2″ id=”rain2″ />
<input type=”button” value=”test” onclick=” document.getElementById(‘rain’).value= document.getElementById(‘rain2′).value.htmlDecode() “/>
**************/

String.prototype.htmlEncode=function(){
return this.replace(/&/g,”&”).replace(/</g,”<”).replace(/>/g,”>”).replace(/\”/g,”"”).replace(/\’/g,”‘”);
}
String.prototype.htmlDecode=function(){
return this.replace(/\&\;/g, ‘\&’).replace(/\>\;/g, ‘\>’).replace(/\<\;/g, ‘\<’).replace(/\”\;/g, ‘\”).replace(/\&\#39\;/g, ‘\”);
}



/*
当我们想在页面加载之后执行某个函数,肯定会想到onload了
但onload在浏览器看来,就是页面上的东西全部都加载完毕后才能发生,但那就为时已晚了。
如果只需要对DOM进行操作,那么这时就没必要等到页面全部加载了。我们需要更快的方法。
Firefox有DOMContentLoaded事件可以轻松解决,可惜的就是IE没有。
MSDN关于JSCRIPT的一个方法有段不起眼的话,当页面DOM未加载完成时,
调用doScroll方法时,会产生异常。那么我们反过来用,如果不异常,那么就是页面DOM加载完毕了!
跟jquery中的ready功能类似。

用法:
function a(){
alert(1);
}
IEContentLoaded( document.getElementById(“test”) , a );

*/
function IEContentLoaded (w, fn) {
var d = w.document, done = false,
// only fire once
init = function () {
if (!done) {
done = true;
fn();
}
};
// polling for no errors
(function () {
try {
// throws errors until after ondocumentready
d.documentElement.doScroll(‘left’);
} catch (e) {
setTimeout(arguments.callee, 50);
return;
}
// no errors, fire
init();
})();
// trying to always fire before onload
d.onreadystatechange = function() {
if (d.readyState == ‘complete’) {
d.onreadystatechange = null;
init();
}
};
}



/**************
用来window.load 多个函数。
window.onload是不能同时加载多个函数的;
比如:
function t(){
alert(“t”)
}
function b(){
alert(“b”)
}
window.onload =t ;
window.onload =b ;
这样做 ,只会输出 b ;

addLoadEvent()这个函数 就是解决这个问题的。
用法:
addLoadEvent(t);
addLoadEvent(b);
**************/

function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != ‘function’) {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}


//支持 FF的 onmouseenter 和 onmouseleave。
/*
由于ff 不支持 onmouseenter 和 onmouseleave。
下面这个方法 就是为了解决 ff 下的这个问题。
用法:
function init()
{
var theList = document.getElementById(‘theList’);
xb.addEvent(theList, ‘mouseenter’, enter, false);
xb.addEvent(theList, ‘mouseleave’, leave, false);
}

function enter(e)
{
alert(‘mouseenter: ‘ + this.id);
}

function leave(e)
{
alert(‘mouseleave: ‘ + this.id);
}
*/

var xb =
{
evtHash: [],

ieGetUniqueID: function(_elem)
{
if (_elem === window) { return ‘theWindow’; }
else if (_elem === document) { return ‘theDocument’; }
else { return _elem.uniqueID; }
},

addEvent: function(_elem, _evtName, _fn, _useCapture)
{
if (typeof _elem.addEventListener != ‘undefined’)
{
if (_evtName == ‘mouseenter’)
{ _elem.addEventListener(‘mouseover’, xb.mouseEnter(_fn), _useCapture); }
else if (_evtName == ‘mouseleave’)
{ _elem.addEventListener(‘mouseout’, xb.mouseEnter(_fn), _useCapture); }
else
{ _elem.addEventListener(_evtName, _fn, _useCapture); }
}
else if (typeof _elem.attachEvent != ‘undefined’)
{
var key = ‘{FNKEY::obj_’ + xb.ieGetUniqueID(_elem) + ‘::evt_’ + _evtName + ‘::fn_’ + _fn + ‘}’;
var f = xb.evtHash[key];
if (typeof f != ‘undefined’)
{ return; }

f = function()
{
_fn.call(_elem);
};

xb.evtHash[key] = f;
_elem.attachEvent(‘on’ + _evtName, f);

// attach unload event to the window to clean up possibly IE memory leaks
window.attachEvent(‘onunload’, function()
{
_elem.detachEvent(‘on’ + _evtName, f);
});

key = null;
//f = null; /* DON’T null this out, or we won’t be able to detach it */
}
else
{ _elem['on' + _evtName] = _fn; }
},

removeEvent: function(_elem, _evtName, _fn, _useCapture)
{
if (typeof _elem.removeEventListener != ‘undefined’)
{ _elem.removeEventListener(_evtName, _fn, _useCapture); }
else if (typeof _elem.detachEvent != ‘undefined’)
{
var key = ‘{FNKEY::obj_’ + xb.ieGetUniqueID(_elem) + ‘::evt’ + _evtName + ‘::fn_’ + _fn + ‘}’;
var f = xb.evtHash[key];
if (typeof f != ‘undefined’)
{
_elem.detachEvent(‘on’ + _evtName, f);
delete xb.evtHash[key];
}

key = null;
//f = null; /* DON’T null this out, or we won’t be able to detach it */
}
},

mouseEnter: function(_pFn)
{
return function(_evt)
{
var relTarget = _evt.relatedTarget;
if (this == relTarget || xb.isAChildOf(this, relTarget))
{ return; }

_pFn.call(this, _evt);
}
},

isAChildOf: function(_parent, _child)
{
if (_parent == _child) { return false };

while (_child && _child != _parent)
{ _child = _child.parentNode; }

return _child == _parent;
}
};
/* end */

//DOM没有提供insertAfter(),只提供了一个insertBefore()方法。
//在这里,我们自己编写一个 insertAfter().
/**************
用法:
//插入到 div b 的后面
window.onload=function(){
var a =document.createElement(“span”);
var b =document.createTextNode(“cssrain”);
a.appendChild(b);

var mubiao = document.getElementById(“b”);
insertAfter(a,mubiao);
}

<div id=”b”>bbbbbbbbb</div>
<div>dddddd</div>
**************/
function insertAfter(newElement,targetElement) {
var parent = targetElement.parentNode;
if (parent.lastChild == targetElement) {// 如果最后的节点是目标元素,则直接添加。因为默认是最后
parent.appendChild(newElement);
} else {
parent.insertBefore(newElement,targetElement.nextSibling);//如果不是,则插入在目标元素的下一个兄弟节点 的前面。也就是目标元素的后面。
}
}


/**************
解决 style 外嵌样式 用js 获取不到 的问题。
用法:
window.onload = function(){
var e1 = document.getElementById(“exep1″);
alert(getStyle(e1,”fontSize”));
alert(getStyle(e1,”backgroundColor”));
}

<!–
currentStyle 对象返回了元素上的样式表,但是 style 对象只返回通过 STYLE 标签属性应用到元素的内嵌样式。
因此,通过 currentStyle 对象获取的样式值可能与通过 style 对象获取的样式值不同。
例如,如果段落的 color 属性值通过链接或嵌入样式表设置为红色( red ),
而不是内嵌的话,对象.currentStyle.color 将返回正确的颜色,
而对象 style.color 不能返回值。
但是,如果用户指定了 <P STYLE=”color:’red’”>,currentStyle 和 STYLE 对象都将返回值 red。
–>
</head>

<body>
<div id=”exep1″>c</div>
</body>
**************/
function getStyle(elem, name){
if(elem.style[name])
return elem.style[name];
else if(elem.currentStyle)//ie
return elem.currentStyle[name];
else if(document.defaultView && document.defaultView.getComputedStyle){//w3c
name = name.replace(/([A-Z])/g,”-$1″);
name = name.toLowerCase();

var s = document.defaultView.getComputedStyle(elem,”");
return s && s.getPropertyValue(name);
} else
return null
}


/**************
//获取当前元素的 元素节点
如果想获取当前元素的下一个节点。
那么可以扩展下:
比如:
var elem = getNextElement( node.nextSibling );
用法;
var elem = getNextElement( node );
**************/
function getNextElement(node) {//获取当前元素的元素节点
if(node.nodeType == 1) {
return node;
}
if (node.nextSibling) {
return getNextElement(node.nextSibling);//如果不是,继续查询下一个,直到 if(node.nodeType == 1) .
}
return null;
}


/**************
默认的 element.className = “” ;是 替换样式。
如果我们是想追加样式, 那么使用下面的方法
用法;
addClass(element,”classname”);
用了这个函数后:
那么将追加成 :
<p class=”b classname”>aaaaaaaaaaaaaaaaaaa</p>
**************/
function addClass(element,value) { //追加样式,而不是替换样式
if (!element.className) {
element.className = value;
} else {
element.className+= ” “;
element.className+= value;
}
}


/**************
表格隔行变色。
注意:引入 我们自己写的 addClass()函数。
**************/
function stripeTables() {
if (!document.getElementsByTagName) return false;
var tables = document.getElementsByTagName(“table”);
for (var i=0; i<tables.length; i++) {
var odd = false;
var rows = tables[i].getElementsByTagName(“tr”);
for (var j=0; j<rows.length; j++) {
if (odd == true) {
addClass(rows[j],”odd”);//odd为样式名
odd = false;
} else {
odd = true;
}
}
}
}

/**************
表格滑过变色.
注意:引入 我们自己写的 addClass()函数。
**************/
function highlightRows() {
if(!document.getElementsByTagName) return false;
var rows = document.getElementsByTagName(“tr”);
for (var i=0; i<rows.length; i++) {
rows[i].oldClassName = rows[i].className
rows[i].onmouseover = function() {
addClass(this,”highlight”);//highlight为样式名
}
rows[i].onmouseout = function() {
this.className = this.oldClassName
}
}
}



/********************
隔行变色 + 滑过变色
参数设置:
id 为表格的id
class1为奇数行的颜色
class2为偶数行的颜色
class3为鼠标滑过颜色
用法:
sti_table(“cssrain” , “c” , “a” ,”d” );
<style>
.a{
background-color : #eee;
}

.c{
background-color : #96dd33;
}

.d{
background-color : #456577;
}
</style>
<TABLE id=”cssrain” >
<TR>
<TD>1</TD>
</TR>
</table>
*********************/
function sti_table( id , class1 , class2 , class3 ){
var para = document.getElementById(id);
var tr = para.getElementsByTagName(“tr”);
var odd = false;
for(var i=0 ; i < tr.length ; i++ ){
if(odd==true){
tr[i].className = class1;
odd=false;

tr[i].onmouseover =function(){
this.className = class3;
}
tr[i].onmouseout =function(){
this.className = class1;
}
}
else{
tr[i].className = class2;
odd=true;

tr[i].onmouseover =function(){
this.className = class3;
}
tr[i].onmouseout =function(){
this.className = class2;
}
}
}

}


//格式化日期和数字
//用法:
//var date=new Date();
//var dateText = format(“YYYY-MM-DD”,date)
//var numberText=format(“###.#”,5432.545)
//document.write(dateText)
//document.write(“<br />”+numberText)
//like the ISO 8895
//also see Java’s SimpleDateFormat.
//
//Letter Date or Time Component Presentation Examples UserDic
//Y Year Year 1996; 96
//M Month in year Month July; Jul; 07 *
//D Day in month Number 10
//w Day in week Text Tuesday; Tue; 2 *
//h Hour in day (0-23) Number 0
//m Minute in hour Number 30
//s Second in minute Number 55

//Pattern Sample
//YYYY-MM-DD hh:mm:ss 2001-07-04 12:08:56
//YYYY-MM-DDThh:mm:ss 2001-07-04T12:08:56
//YYYY/MM/DDThh:mm:ss 2001/07/04T12:08:56
//YYYY年MM月DD日,周w 2008年12月12日,周3
//hh:mm 12:08


//符号说明:
//0 表示补0 的数字占位
//. 表示小数点
//, 数字分组符号 如123,456.123
//# 表示不补0 的数字占位
//
//Number Pattern Result
//10000000000001124 #,###.### 10,000,000,000,001,124.000
//123.125 ##,#.#,# 1,2,3.1,3
//123.125 ###.# 123.1
//123.125 00000 00123
//123.125 .000 .125
//0.125 0.0000 0.1250
//0.125 00.0000 00.1250
//
//使用代码:
//var numberText = format(“##.#”,123.456)//output 123.45

function format(pattern,data){
if(data instanceof Date){
function dl(data,format){//3
format = format.length;
data = data || 0;
return format = 1 ? data : String(Math.pow(10,format)+data).substr(-format);
}
return pattern.replace(/([YMDhsm])\1*/g,function(format){
switch(format.charAt()){
case ‘Y’ :
return dl(data.getFullYear(),format);
case ‘M’ :
return dl(data.getMonth()+1,format);
case ‘D’ :
return dl(data.getDate(),format);
case ‘w’ :
return data.getDay()+1;
case ‘h’ :
return dl(data.getHours(),format);
case ‘m’ :
return dl(data.getMinutes(),format);
case ’s’ :
return dl(data.getSeconds(),format);
}
});
}else if(‘number’ == typeof data){
//hack:purePattern as floatPurePattern
function trim(data,pattern,purePattern){
if(pattern){
if(purePattern){
if(purePattern.charAt() == ‘0′){
data = data + purePattern.substr(data.length);
}
if(purePattern!=pattern){
var pattern = new RegExp(“(\\d{“+pattern.search(/[^\d#]/)+”})(\\d)”);
while(data.length < (data = data.replace(pattern,’$1,$2′)).length);
}
data = ‘.’ + data
}else{
var purePattern = pattern.replace(/[^\d#]/g,”);
if(purePattern.charAt() == ‘0′){
data = purePattern.substr(data.length) + data;
}
if(purePattern!=pattern){
var pattern = new RegExp(“(\\d)(\\d{“+(pattern.length-pattern.search(/[^\d#]/)-1)+”})\\b”);
while(data.length < (data = data.replace(pattern,’$1,$2′)).length);
}
}
return data;
}else{
return ”;
}
}
return pattern.replace(/([#0,]*)?(?:\.([#0,]+))?/,function(param,intPattern,floatPattern){
var floatPurePattern = floatPattern.replace(/[^\d#]/g,”);
data = data.toFixed(floatPurePattern.length).split(‘.’);
return trim(data[0] ,intPattern) + trim(data[1] || ”,floatPattern,floatPurePattern);
})
}
}


//除法函数,用来得到精确的除法结果
//说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
//调用:accDiv(arg1,arg2)
//返回值:arg1除以arg2的精确结果
function accDiv(arg1,arg2){
var t1=0,t2=0,r1,r2;
try{t1=arg1.toString().split(“.”)[1].length}catch(e){}
try{t2=arg2.toString().split(“.”)[1].length}catch(e){}
with(Math){
r1=Number(arg1.toString().replace(“.”,”"))
r2=Number(arg2.toString().replace(“.”,”"))
return (r1/r2)*pow(10,t2-t1);
}
}
//给Number类型增加一个div方法
//用法: (37).div(3);
Number.prototype.div = function (arg){
return accDiv(this, arg);
}

//乘法函数,用来得到精确的乘法结果
//说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
//调用:accMul(arg1,arg2)
//返回值:arg1乘以arg2的精确结果
function accMul(arg1,arg2)
{
var m=0,s1=arg1.toString(),s2=arg2.toString();
try{m+=s1.split(“.”)[1].length}catch(e){}
try{m+=s2.split(“.”)[1].length}catch(e){}
return Number(s1.replace(“.”,”"))*Number(s2.replace(“.”,”"))/Math.pow(10,m)
}
//给Number类型增加一个mul方法
//用法: (37).mul(3);
Number.prototype.mul = function (arg){
return accMul(arg, this);
}
//加法函数,用来得到精确的加法结果
//说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
//调用:accAdd(arg1,arg2)
//返回值:arg1加上arg2的精确结果
function accAdd(arg1,arg2){
var r1,r2,m;
try{r1=arg1.toString().split(“.”)[1].length}catch(e){r1=0}
try{r2=arg2.toString().split(“.”)[1].length}catch(e){r2=0}
m=Math.pow(10,Math.max(r1,r2))
return (arg1*m+arg2*m)/m
}
//给Number类型增加一个add方法
//用法: (37).add(3);
Number.prototype.add = function (arg){
return accAdd(arg,this);
}

//减法函数,用来得到精确的减法结果
function Subtr(arg1,arg2){
var r1,r2,m,n;
try{r1=arg1.toString().split(“.”)[1].length}catch(e){r1=0}
try{r2=arg2.toString().split(“.”)[1].length}catch(e){r2=0}
m=Math.pow(10,Math.max(r1,r2));
//last modify by deeka
//动态控制精度长度
n=(r1>=r2)?r1:r2;
return ((arg1*m-arg2*m)/m).toFixed(n);
}
//给Number类型增加一个add方法
//用法: (5.5).sub(37.5)
Number.prototype.sub = function (arg){
return Subtr(arg,this);
}


//格式化字符串
/*
用法:
var cls=”redclass”;
var text=”My name is “;
var str=’<div class=”{0}”>{1} {2}</div>’.diy_format(cls, text,”cssrain”);
alert(str);
*/
String.prototype.diy_format=function(){
var args=arguments;
return this.replace(/\{(\d+)\}/g, function(m, i){
return args[i];}
);}


//去掉数组中重复的元素
//用法:
//var arr=["abc",85,"abc",85,8,8,1,2,5,4,7,8];
//alert( arr.strip() );
Array.prototype.strip=function(){
if(this.length<2) return [this[0]]||[];
var arr=[];
for(var i=0;i<this.length;i++){
arr.push(this.splice(i–,1));
for(var j=0;j<this.length;j++){
if(this[j]==arr[arr.length-1]){
this.splice(j–,1);}}}
return arr;
}



//得到l-h下标的数组
//用法:
//var arr=["abc",85,"abc",85,8,8,1,2,5,4,7,8];
//alert( arr.limit(2,4) ); //输出 abc , 85 ,8
Array.prototype.limit = function(l, h) {
var _a = this; var ret = [];
l = l<0?0:l; h = h>_a.length?_a.length:h;
for (var i=0; i<_a.length; i++) {
if (i>=l && i<=h) ret[ret.length] = _a[i];
if (i>h) break;
}; return ret;
}

//指定array是否包含指定的item
//array.exists( item ) 包含true;不包含false;
//用法:
//var array1 = [1,2,3,4,5,"a","b"];
//var b1 = array1.exists(“b”) // 包含true;不包含false;//alert(b1)
function Array.prototype.exists( item )
{
for( var i = 0 ; i < this.length ; i++ )
{
if( item == this[i] )
{
return true;
}
}
return false;
}

//删除指定的item
//array.remove(item) 删除item
//用法:
//var array1 = [1,2,3,4,5,"a","b"];
//array1.remove(“2″);
//alert( array1[1] );
function Array.prototype.remove( item )
{
for( var i = 0 ; i < this.length ; i++ )
{
if( item == this[i] )
{
break;
}
}
if( i == this.length )
{
return;
}
for( var j = i ; j < this.length – 1 ; j++ )
{
this[ j ] = this[ j + 1 ];
}
this.length–;
}


//得到url参数值
// url: http:www.cssrain.cn/article.asp?id=100
// var id = getParameter(“id”);
// alert(id);
function getParameter(key)
{
var parameters = unescape(window.location.search.substr(1)).split(“&”);
for( var i = 0 ; i < parameters.length ; i++ )
{
var paramCell = parameters[i].split(“=”);
if( paramCell.length == 2 && paramCell[0].toUpperCase() == key.toUpperCase() )
{
return paramCell[1];
}
}
return new String();
}



//获取某月有几天 ,月份是从 0开始
//用法:alert( jscomGetMonthDays(2008 , 4) )
function jscomGetMonthDays(year,month)
{
if(month<0 || month>11)
{
return 30;
}
var arrMon = new Array(12);
arrMon[0] = 31;
if(year % 4 == 0)
{
arrMon[ 1] =29;
}else{
arrMon[ 1] =28;
}
arrMon[ 2] = 31; arrMon[ 3] = 30;
arrMon[ 4] = 31; arrMon[ 5] = 30;
arrMon[ 6] = 31; arrMon[ 7] = 31;
arrMon[ 8] = 30; arrMon[ 9] = 31;
arrMon[10] = 30; arrMon[11] = 31;
return arrMon[month];
}

/**
* 以document.write的方式向页面中写入js
* 参数 :
o {
id : id of the created tag,
url : String,
script : String
}
用法: dwScript({id : ‘cssrain’ , url : ‘js/fl.js’ });
*/
function dwScript(o){
o.id = o.id || “”;
o.charset = o.charset || “utf-8″;
if (o.script && o.script != “”){
document.write(“<script id=’” + o.id + “‘>” + o.script + “<\/script>”);
} else if (o.url && o.url != “”){
document.write(“<script id=’” + o.id + “‘ src=’” + o.url + “‘ charset=’” + o.charset + “‘><\/script>”);
} else throw new Error(“no script content or url specified”);
}


/**
* 以document.write的方式向页面中写入css
* @param o {
* id : id of the created tag,
* url : String,
* styles : styles text
* }
用法:dwCSS({ id : ‘cssrain’ , url:’css/default.template.css?’});
*/
function dwCSS(o){
o.id = o.id || “”;
if (o.url){
document.write(‘<link id=”‘ + o.id + ‘” rel=”stylesheet” type=”text/css” href=”‘ + o.url + ‘” />’);
} else if (o.styles){
document.write(‘<style id=”‘ + o.id + ‘” >’+o.styles+’<\/style>’);
}
}


/**
* 把字符串中 的 半角 转换为全角。
用法:
var a = “d’d'd’d()%[]“;
alert(toSafe(a));

当然可以用于表单的值转换。
*/
function toSafe(str)
{
var re;
re = /’/g;
str = str.replace(re,”'”);
re =/\)/g;
str = str.replace(re,”)”);
re = /\(/g;
str = str.replace(re,”(”);
re = /%/g;
str = str.replace(re,”%”);
re = /\[/;
str = str.replace(re,"[");
re = /\]/;
str = str.replace(re,”]”);
return str;
}
function makeToSafe(formName)
{
var i,form;
form = eval(formName);
for(i=0;i<form.elements.length;i++)
{
if(form.elements[i].type==”text” || form.elements[i].type==”textarea”)
{
form.elements[i].value = toSafe(form.elements[i].value);
}
}
}


/*
小数 四舍五入
//Dight 为要转换的数据
//How 要保留的小数位数
用法:
var k = ForDight( 222.5 , 0 ) ;
*/
function ForDight(Dight,How)
{
Dight = Math.round (Dight*Math.pow(10,How))/Math.pow(10,How);
return Dight;
}

/*
计时器。
用法:
<div id=”cssrain”>aaa</div>

<SCRIPT >
var test = document.getElementById(“cssrain”);

//测试一个例子,3秒后隐藏div。
function hideDiv()
{
test.style.color = “red”;
}

var cs = new timerPerActive(3 , hideDiv );
cs.callback();
*/

function timerPerActive(timer,comfunc) //对象
{
this.times=0;//定时器对象 ,初始化为0
this.change=function()
{
this.times++;
test.innerHTML = this.times;//测试用的
if(this.times==timer)
{
clearInterval(times);
this.complete(); //最终要回调的函数
}
}
this.callback=function() //每过1秒,调用
{
var css=this;
times=setInterval(function(){css.change();},1000);
}
this.complete=function() //完成后,调用
{
comfunc();
}
}


// 计算日期为当年的第几周
// 用法:
// 获取 2008-7-5 为当年的第几周
// 返回: 28
// document.write( weekOfYear(2008 , 7 , 5) );
function weekOfYear(year, month, day){
// year 年
// month 月
// day 日
// 每周从周日开始
var date1 = new Date(year, 0, 1);
var date2 = new Date(year, month-1, day, 1);
var dayMS = 24*60*60*1000;
var firstDay = (7-date1.getDay())*dayMS;
var weekMS = 7*dayMS;
date1 = date1.getTime();
date2 = date2.getTime();
return Math.ceil((date2-date1-firstDay)/weekMS)+1;
}

// 通过周数和星期计算日期
// 获取 2005 年第 37 周的周六的日期 。 (0-6, 0代表周日)
// 返回: 2005年9月10号
// alert(dateFromWeek(2005, 37, 6));
function dateFromWeek(year, week, day){
// year 年
// week 周
// day 星期 (0-6, 0代表周日)
var date1 = new Date(year, 0, 1);
var dayMS = 24*60*60*1000;
var firstDay = (7-date1.getDay())*dayMS;
var weekMS = (week-2)*7*dayMS;
var result = date1.getTime()+firstDay+weekMS+day*dayMS;
date1.setTime(result);
return date1.toLocaleDateString();
}


/**************
format:
格式化时间。
用法:
yourdate.format(“你的日期格式”);
例子:
obj0 = new Date(“Sun May 04 2008″).format(“yyyy-MM-dd”);
obj1 = new Date().format(“yyyy-MM-dd hh:mm:ss”);
obj2 = new Date().format(“yyyy-MM-dd”);
obj3 = new Date().format(“yyyy/MM/dd”);
obj4 = new Date().format(“MM/dd/yyyy”);
**************/
Date.prototype.format = function(format)
{
var o = {
“M+” : this.getMonth()+1, //month
“d+” : this.getDate(), //day
“h+” : this.getHours(), //hour
“m+” : this.getMinutes(), //minute
“s+” : this.getSeconds(), //second
“q+” : Math.floor((this.getMonth()+3)/3), //quarter
“S” : this.getMilliseconds() //millisecond
}
if(/(y+)/.test(format)) format=format.replace(RegExp.$1,
(this.getFullYear()+”").substr(4 – RegExp.$1.length));
for(var k in o)if(new RegExp(“(“+ k +”)”).test(format))
format = format.replace(RegExp.$1,
RegExp.$1.length==1 ? o[k] :
(“00″+ o[k]).substr((“”+ o[k]).length));
return format;
}

/**************
日期减去天数 得到 第二个日期 。
例子:
data_sub_day(“12/23/2002″,30)
**************/
function data_sub_day(dd,dadd)
{
//可以加上错误处理
var a = new Date(dd)
a = a.valueOf()
a = a – dadd * 24 * 60 * 60 * 1000
a = new Date(a)
alert(a.getFullYear() + “年” + (a.getMonth() + 1) + “月” + a.getDate() + “日”)
}


/**************
format:
格式化数字.
例子:
var n = format_number( 123456.45656 , 2 ); // .toFixed(2)也可以实现,不过不兼容FF.
alert(n);
**************/
function format_number(str,digit)
{
if(isNaN(str))
{
alert(“您传入的值不是数字!”);
return 0;
}
else if(Math.round(digit)!=digit)
{
alert(“您输入的小数位数不是整数!”);
return 0;
}
else
return Math.round(parseFloat(str)*Math.pow(10,digit))/Math.pow(10,digit);
}



/**************
* 得到单选框选中的值。
* 用法:
*<input type=”radio” value=”1″ name=”cssrain”/>
*<input type=”radio” value=”2″ name=”cssrain” checked/>
*<input type=”radio” value=”3″ name=”cssrain”/>
*<input type=”button” onclick=”alert(getRadioValue(‘cssrain’))” value=”test”/>
**************/
function getRadioValue(radioName){
var obj=document.getElementsByName(radioName);
for(var i=0;i<obj.length;i++){
if(obj[i].checked){
return obj[i].value;
}
}
}

/**************
* 复选框全选/不选/反选
* 用法:
<form id=”form_a”>
<input type=”checkbox” value=”1″ name=”a”/>
<input type=”checkbox” value=”2″ name=”a” checked/>
<input type=”checkbox” value=”3″ name=”a”/>
<input type=”button” value=”全选” onclick=”checkAll(document.getElementById(‘form_a’),’all’)”/>
<input type=”button” value=”不选” onclick=”checkAll(document.getElementById(‘form_a’),’none’)”/>
<input type=”button” value=”反选” onclick=”checkAll(document.getElementById(‘form_a’),”)”/>
</form>
**************/
function checkAll(form, sel) {
for (i = 0, n = form.elements.length; i < n; i++) {
if(form.elements[i].type == “checkbox”) {
if(form.elements[i].checked == true) {
form.elements[i].checked = (sel == “all” ? true : false);
} else {
form.elements[i].checked = (sel == “none” ? false : true);
}
}
}
}
/**************
* 复选框检查是否选中。
* 如果没一个选中,会返回false.
* 用法:
<form id=”form_a” name=”form_a”>
<input type=”checkbox” value=”1″ name=”a”/>
<input type=”checkbox” value=”2″ name=”a” checked/>
<input type=”checkbox” value=”3″ name=”a”/>
<input type=”button” value=”全选” onclick=”alert( SCheckBox(‘form_a’,'a’) )”/>
</form>
**************/
function SCheckBox(_formName,_checkboxName){
var selflag = {‘checked’:0,’cvalues’:[]};
_scheckbox = eval(‘document.’+_formName+’.'+_checkboxName);
if(_scheckbox){
if(eval(_scheckbox.length)){
for(i=0;i<_scheckbox.length;i++){
if(_scheckbox[i].checked){
selflag.checked++;
selflag.cvalues.push(_scheckbox[i].value);
}
};
}else if(_scheckbox.checked){
selflag.checked++;
selflag.cvalues.push(_scheckbox.value);
}
if(selflag.checked){
return selflag;
}
}
return false;
}


/**************
收藏到书签.(兼容IE和FF)。
用法:
<input type=”button” value=”收藏” onclick=”addBookmark(‘cssrain(前端开发)’,’http://www.cssrain.cn‘)”/>
**************/
function addBookmark(title,url) {
if (window.sidebar) {
window.sidebar.addPanel(title, url,”");
} else if( document.all ) {
window.external.AddFavorite( url, title);
} else if( window.opera && window.print ) {
return true;
}
}

/**************
函数 : 文本框得到与失去焦点 操作。
这个方法经常在文本框搜索的时候出现。
文本里显示 ” 搜索 “,然后当用户鼠标点击此文本,
文本框内容清空。如果用户没填写内容,那么文本的值又复原。
如果填写了,就显示用户填写的。
用法:
<input type=”" value=”关键字搜索” name=”a” onfocus=”clearTxt(‘a’,'关键字搜索’)” onblur=”fillTxt(‘a’,'关键字搜索’)”/>
<input type=”text” value=”test” name=”test” />
**************/
function clearTxt(id,txt) {
if (document.getElementById(id).value == txt)
document.getElementById(id).value=”" ;
return ;
}
function fillTxt(id,txt) {
if ( document.getElementById(id).value == “” )
document.getElementById(id).value=txt;
return ;
}
//也可以使用 defaultValue属性 来做:
//例子:
/*
<input type=”text” value=”搜索”/>
<input type=”text” value=”请输入名称”/>
<SCRIPT LANGUAGE=”JavaScript”>
var inputs =document.getElementsByTagName(“input”);
for(var i=0;i<inputs.length;i++){
if (inputs[i].type == “submit”) continue;
if (!inputs[i].defaultValue) continue;
inputs[i].onfocus = function(){
if(this.value == this.defaultValue )
{
this.value = “”;
}
} //end of onfocus
inputs[i].onblur = function(){
if(this.value == “” )
{
this.value = this.defaultValue;
}
} //end of onblur
}
</SCRIPT>
*/




/**************
函数 : 用来判断鼠标按的是左键还是右键。(兼容IE和ff)
用法:
onmousedown=”mouse_keycode(event)”
**************/
function mouse_keycode(event){
var event=event||window.event;
var nav=window.navigator.userAgent;
if (nav.indexOf(“MSIE”)>=1) //如果浏览器为IE.解释:因为 document.all 是 IE 的特有属性,所以通常用这个方法来判断客户端是否是IE浏览器 ,document.all?1:0;
{
if(event.button==1){alert(“左键”)}
else if(event.button==2){alert(“右键”)}
}
else if(nav.indexOf(“Firefox”)>=1) ////如果浏览器为Firefox
{
if(event.button==0){alert(“左键”);}
else if(event.button==2){alert(“右键”);}
}
else{ //如果浏览器为其他
alert(“other”);
}
}


/**************
函数 :触发某个对象的onclick事件。(兼容IE和FF)
用法:
<input type=”button” value=”aaa” id=”a” onclick=” alert(‘cssrain’) ” />
<input type=”button” value=”触发ID为a的onclick事件” onclick=” handerToClick(‘a’) ” />
**************/
function handerToClick(objid){
var obj=document.getElementById(objid);
if(document.all){
obj.fireEvent(“onclick”);
}else{
var e=document.createEvent(‘MouseEvent’);
e.initEvent(‘click’,false,false);
obj.dispatchEvent(e);
}
}


/**************
回车提交。
用法:
<input type=text onkeydown=”keysubmit()”>
**************/
function keysubmit()
{
if(event.keyCode==13)
{
form.submit();
}
}

/**************
实现Ctrl+Enter 提交的效果.(兼容IE和FF)
在做这个效果时,发现一个问题,
当表单中如果只有一个文本框时,
回车会默认提交。(没有提交按钮也一样。)
用法:
<form action=”#” name=”a”>
<input type=”text” />
<input type=”text” onkeydown=”QuickPost( event , document.a )” />
</form>
**************/
function QuickPost(event,form){
var event=event||window.event;
if((event.ctrlKey && event.keyCode == 13)||(event.altKey && event.keyCode == 83)){
// event.srcElement.form.submit();
form.submit();
}
}


/**************
回车自动跳到下一个文本框。
注;此方法不兼容FF,
因为在FF下,event.keycode是只读属性,不能赋值。
用法:
<form action=”#” name=”a” onkeydown=”QuickNext()”>
<input type=”text” />
<input type=”text” />
<input type=”button” value=”test” />
</form>
**************/
function QuickNext()
{
//判断是否为button, 是因为在HTML上会有type=”button”
//判断是否为submit,是因为HTML上会有type=”submit”
//判断是否为reset,是因为HTML上的”重置”应该要被执行
//判断是否为空,是因为对于HTML上的”<a>链接”也应该被执行,
//这种情况发生的情况不多,可以使用”tabindex=-1″的方式来取消链接获得焦点.
if(event.keyCode==13 && event.srcElement.type!=’button’ && event.srcElement.type!=’submit’ && event.srcElement.type!=’reset’ && event.srcElement.type!=’textarea’ && event.srcElement.type!=”)
{ event.keyCode = 9; }
}


/**************
按TAB键移动到下一个输入框时,光标停在文本框文字的最后,方便用户继续输入.
IE默认是全部选中。此方法不兼容FF。
用法:
<input type=’text’ value=’0592′ onfocus=”moveEnd()”>
**************/
function moveEnd()
{
var e=event.srcElement;
var r=e.createTextRange();
r.moveStart(‘character’,e.value.length);
r.collapse(true);
r.select();
}



/**************
TEXTAREA自适应文字的行数 .
注;此方法不兼容FF,(onpropertychange)
参数:当前对象 和 最小高度
用法:
<textarea rows=5 name=s1 cols=27 onpropertychange=”textarea_scroll(this,60)” style=”overflow-y:hidden”>
</textarea>
**************/
function textarea_scroll(obj,min)
{
if(obj.scrollHeight<min){
obj.style.posHeight=min
}else{
obj.style.posHeight=obj.scrollHeight
}
}


/**************
改变下拉框选项后,根据选项的不同弹出不同的窗口.
用法:
<select onchange=”return select_pop(this);” >
<option selected=”selected”>–分公司–</option>
<option value=”http://www.bj.chinaunicom.com“>北京</option>
<option value=”http://www.sh.chinaunicom.com“>上海</option>
</select>
**************/
function select_pop(fileurl){
if (fileurl.options[fileurl.selectedIndex].value != “”)
window.open(fileurl.options[fileurl.selectedIndex].value,”_blank”,”toolbar=yes,location=yes,menubar=yes,scrollbars=yes,resizable=yes,left=50,height=500,width=700″);
return true;
}



/**************
得到字符串的字节数。
用法:
<input type=”text” name=”a” />
<input type=”button” value=”test” onclick=”alert( strlen(document.getElementById(‘a’).value ) )” />
**************/
//
function strlen(string){
var str=”";
str=string;
str=str.replace(/[^\x00-\xff]/g,”**”);
return str.length;
}
//或者
function ByteLength(string){
return string.replace(/[^\x00-\xff]/g,”00″).length;
}


/**************
文本框输入字符控制。
只能输入数字。
用法:
<input onkeyup=”input_shuzi(this)” onbeforepaste=”input_shuzi_before()” />
**************/
function input_shuzi(obj)
{
obj.value=obj.value.replace(/[^\d]/g,”);
}
function input_shuzi_before(){
clipboardData.setData(‘text’,clipboardData.getData(‘text’).replace(/[^\d]/g,”));
}

/**************
文本框输入字符控制。
只能输入数字和英文。
用法:
<input onkeyup=”input_shuziyinwen(this)” onbeforepaste=”input_shuziyinwen_before()” />
**************/
function input_shuziyinwen(obj)
{
obj.value=obj.value.replace(/[\W]/g,”);
}
function input_shuziyinwen_before(){
clipboardData.setData(‘text’,clipboardData.getData(‘text’).replace(/[\W]/g,”));
}

/**************
文本框输入字符控制。
只能输入汉字。
用法:
<input onkeyup=”input_hanzi(this)” onbeforepaste=”input_hanzi_before()” />
**************/
function input_hanzi(obj)
{
obj.value=obj.value.replace(/[^\u4E00-\u9FA5]/g,”);
}
function input_hanzi_before(){
clipboardData.setData(‘text’,clipboardData.getData(‘text’).replace(/[^\u4E00-\u9FA5]/g,”));
}

/**************
文本框输入字符控制。
只能输入全角。
用法:
<input onkeyup=”input_quanjiao(this)” onbeforepaste=”input_quanjiao_before()” />
**************/
function input_quanjiao(obj)
{
obj.value=obj.value.replace(/[^\uFF00-\uFFFF]/g,”);
}
function input_quanjiao_before(){
clipboardData.setData(‘text’,clipboardData.getData(‘text’).replace(/[^\uFF00-\uFFFF]/g,”));
}


/**************
*只允许输入数字和小数点。
*用法:
*<input type=text onkeyup=”clearNoNum(this)”/>
**************/
function clearNoNum(obj)
{
//先把非数字的都替换掉,除了数字和.
obj.value = obj.value.replace(/[^\d.]/g,”");
//必须保证第一个为数字而不是.
obj.value = obj.value.replace(/^\./g,”");
//保证只有出现一个.而没有多个.
obj.value = obj.value.replace(/\.{2,}/g,”.”);
//保证.只出现一次,而不能出现两次以上
obj.value = obj.value.replace(“.”,”$#$”).replace(/\./g,”").replace(“$#$”,”.”);
}

/**************
*把输入的字母转成大写。
*用法:
*<input type=”text” name=”d” onkeyup=”input_to_uppercase(this)” />
**************/
function input_to_uppercase(obj)
{
obj.value=obj.value.toUpperCase();
}
/**************
*把输入的字母转成小写。
*用法:
*<input type=”text” name=”e” onkeyup=”input_to_lowercase(this)” />
**************/
function input_to_lowercase(obj)
{
obj.value=obj.value.toLowerCase();
}


/**************
*判断字符中是否包含有 http:// .
*用法:
<input type=”text” name=”a” />
<input type=”button” value=”test” onclick=” alert( urlcheck(document.getElementById(‘a’).value) )” />
**************/
function urlcheck(string){
var re;
re=new RegExp(“http://“);
return re.test(string.toLowerCase());
}


/**************
从URL地址中提取文件名
*用法:
var a =url_filename(“http://www.cssrain.cn/abc.rar”);
alert( a ) ;// “abc”
**************/
function url_filename(string){
string=string.replace(/(.*\/){0,}([^\.]+).*/ig,”$2″)
return string
}

/**************
*实时检测输入框的字数
*用法:
<input type=”text” name=”explain” id=”explain” onkeyup=”check_input_Length(this)” >
<small>文字最大长度: 20. 还剩: <span id=”chLeft”>20</span>.</small>
**************/
function check_input_Length(which)
{
var maxChars = 20;
if (which.value.length > maxChars)
which.value = which.value.substring(0,maxChars);
var curr = maxChars – which.value.length;
document.getElementById(“chLeft”).innerHTML = curr.toString();
}


/**************
*判断电子邮箱是否符合规范
*用法:
<input type=”text” name=”a” />
<input type=”button” value=”test” onclick=” alert( emailcheck(document.getElementById(‘a’).value) )” />
**************/
function emailcheck(string){
var re;
re=new RegExp(“^[\\w-_\\.]+@([a-z|0-9|-]+\\.)+[a-z]{2,5}$”);
return re.test(string.toLowerCase());
}


/**************
*判断用户名是否符合要求
*用法:
<input type=”text” value=”aaa” id=”a” />
<input type=”button” value=”test” onclick=” alert( usernamecheck(document.getElementById(‘a’).value ) ) ” />
**************/
function usernamecheck(string){
if((string.length<4)||(string.length>20)){return false;}
var re;
re=new RegExp(“^[a-z|A-Z|0-9][a-z|A-Z|0-9|-]+$”);
return re.test(string);
}


/***************
* 用于检验手机号的位数以及检验此手机中是否为中国移动的手机号
* 如果还想判断联通的手机,可以改 GSMPhNo 。
用法 :
<form name=”toptransfer”>
<input type=”text” name=”phone” />
<input type=”button” value=”test” onclick=”checkFetionReg()”/>
</form>
**************/
function checkMBPhone(phone){
var GSMPhNo = /^(13[4-9])|(159)|(158)|(150)|(151)/; //以134(5、6、7、8、9)或159,158,151,150开头;
var num11 = /^\d{11}$/; //11位数字;
if( “” != phone ){
if(num11.exec(phone)){
if(GSMPhNo.exec(phone)){
return true;
}else{
alert(“对不起,请您正确输入中国移动GSM手机号码(以134-139、159、158、151或150开头)!”);
return false;
}
}else{
alert(“请正确输入11位手机号码(数字)!”);
return false;
}
}else{
alert(“对不起,请输入您的手机号码!”);
return false;
}
}
function checkFetionReg(){ //例子
if(checkMBPhone(document.toptransfer.phone.value))
{
alert(“正确”);
//do your things
}
}




//验证日期 yyyy/mm/dd 或 yyyy.mm.dd
//用法:
//<input id=”txtdata” /> <input type=”button” onclick=”dateCheck()” value=”test”/>
function dateCheck()
{
var str = document.getElementById(“txtdata”).value;//我这里写死了,如果需要可以自己抽象化。
var re = new RegExp(“^([0-9]{4})[./]{1}([0-9]{1,2})[./]{1}([0-9]{1,2})$”);

var ar;
var res = true;

if ((ar = re.exec(str)) != null){
var i;
i = parseFloat(ar[3]);
if (i <= 0 || i > 31){
res = false;
}
i = parseFloat(ar[2]);
if (i <= 0 || i > 12){
res = false;
}
}else{
res = false;
}
if (!res){
alert(‘情输入类似格式 : 2000/11/25′);
}
else{
alert(“success”);
}
return res;
}


//检查输入的值,小数点后的位数
//用法: checknumber( ‘22.22′ , 1 , “金额” );
function checknumber(value,num,str){
if(value!=”"){
if(value.indexOf(“.”)>0){
var temp=value.length-(value.indexOf(“.”)+1);
if(temp>num){
alert(str+”的小数点后只能有”+num+”位!”);
return true;
}
}
}
return false;
}




/***************
获取域名.
**************/
function getDomainName(){
var s,siteUrl;
s=document.location+”";
return s.substring(7,s.indexOf(‘/’,7));
}

/***************
判断cookie是否开启
返回 boolean类型
**************/
function open_cookie(){
//判断cookie是否开启
var cookieEnabled=(navigator.cookieEnabled)? true : false;
//如果浏览器不是ie4+或ns6+
if (typeof navigator.cookieEnabled==”undefined” && !cookieEnabled){
document.cookie=”testcookie”;
cookieEnabled=(document.cookie==”testcookie”)? true : falsedocument.cookie=”";
}

if(cookieEnabled){
return true;
}else{
return false;
}
}

/***************
* 写入COOKIE
用法 :
setcookie:<input type=”button” value=”test” onclick=” setCookie(‘a’,'cssrain’);alert(‘设置成功.’) ” />
getcookie:<input type=”button” value=”test” onclick=” alert( getCookie(‘a’) ) ” />
**************/
function setCookie(name, value){
//document.cookie = name+”=”+value
date = new Date();
document.cookie = name +”=” + escape(value) + “;expires=” + new Date(date.getYear()+1, date.getMonth(),date.getDate()).toGMTString() + “;path=/”;
}
/***************
* 简单的读取Cookie
**************/
function getCookie(Name){
var re=new RegExp(Name+”=[^;]+”, “i”);
if (document.cookie.match(re)){
return document.cookie.match(re)[0].split(“=”)[1];
}else{
return “”;
}
}
/*
读取Cookie写法2:
function getCookie(name){
var aCookie = document.cookie.split(“;”);
for(var i=0; i<aCookie.length; i++)
{
var aC = aCookie[i].split(“=”);
var nTemp = aC[0].replace(‘ ‘,”);
if(name == nTemp)
{
return unescape(aC[1]);
}
}
return “”;
}
*/


/*************
//增加Cookie
function addCookie(name,value,expireHours){
var cookieString=name+”=”+escape(value);
//判断是否设置过期时间
if(expireHours>0){
var date=new Date();
date.setTime(date.getTime+expireHours*3600*1000);
cookieString=cookieString+”; expire=”+date.toGMTString();
}
document.cookie=cookieString;
}
//获取Cookie值
function getCookie(name){
var strCookie=document.cookie;
var arrCookie=strCookie.split(“; “);
for(var i=0;i<arrCookie.length;i++){
var arr=arrCookie[i].split(“=”);
if(arr[0]==name){
return unescape(arr[1]);
}
}
return false;
}
//删除Cookie
function deleteCookie(name){
var date=new Date();
date.setTime(date.getTime()-10000);
document.cookie=name+”=; expire=”+date.toGMTString();
}
*************/


/***************
* 子窗口刷新父窗口.(写在子窗口里)
**************/
function opener_reload()
{
window.opener.location.reload();
}
//javascript:this.location.reload()// 刷新本页 window.history.go(0)
//<INPUT TYPE=”button” onclick=window.history.back() value=back> //后退 window.history.go(-1);
//<INPUT TYPE=”button” onclick=window.history.forward() value=forward>//前进 window.history.go(1);



/**************
* 不被浏览器拦截的弹出窗口JS代码:
* 程序弹出的窗口将不会被广告拦截软件拦截,但有一个缺点:你无法象对window.open弹出的窗口那样对外观进行定制。
* 用法:<input type=button onclick=’window.force.open(“a.html”)’ />
* 定义ForceWindow类构造函数
* 无参数
* 无返回值.
* 实例化一个ForceWindow对象并做为window对象的一个子对象以方便调用
* 定义后可以这样来使用:window.force.open(“URL”);
* 你当然也可以在使用前实例化一个ForceWindow对象:
* var myWindow = new ForceWindow();
* 这样来使用:
* myWindow.open(“URL”);
* 本程序测试通过的浏览器:IE 5+、Firefox 1.0、Mozilla 1.7.5、Netscape 7.2、Opera 7.23
**************/
function ForceWindow ()
{
this.r = document.documentElement;
this.f = document.createElement(“FORM”);
this.f.target = “_blank”;
this.f.method = “post”;
this.r.insertBefore(this.f, this.r.childNodes[0]);
}
ForceWindow.prototype.open = function (sUrl) //定义open方法 , 参数sUrl:字符串,要打开窗口的URL, 无返回值
{
this.f.action = sUrl;
this.f.submit();
}
window.force = new ForceWindow();


/**************
拷贝/复制文本框内容。(兼容IE和FF)
用法:
1,<input type=”text” name=”d” id=”d” value=”<http://www.cssrain.cn><http://www.cssrain.cn>” /><input id=”Button1″ type=”button” onclick=”copyText(document.getElementById(‘d’));” value=”复制” /> <br/>
2,<textarea name=”c” id=”c” rows=”4″ cols=”20″><http://www.cssrain.cn></textarea>
<input id=”Button2″ type=”button” onclick=”copyText(document.getElementById(‘c’));” value=”复制” />
**************/
function copyText(obj)
{
if( obj.type !=”hidden” )
{
obj.focus();
}
obj.select();
copyToClipboard(obj.value);
alert(“拷贝成功!”);
}
function copyToClipboard(txt) {
if(window.clipboardData)
{
window.clipboardData.clearData();
window.clipboardData.setData(“Text”, txt);
}
else if(navigator.userAgent.indexOf(“Opera”) != -1)
{
window.location = txt;
}
else if (window.netscape)
{
try {
netscape.security.PrivilegeManager.enablePrivilege(“UniversalXPConnect”);
}
catch (e)
{
alert(“您使用的浏览器不支持此复制功能,请使用ctrl+c或者浏览器右键复制”);
}
var clip = Components.classes['@mozilla.org/widget/clipboard;1'].createInstance(Components.interfaces.nsIClipboard);
if (!clip)
return;
var trans = Components.classes['@mozilla.org/widget/transferable;1'].createInstance(Components.interfaces.nsITransferable);
if (!trans)
return;
trans.addDataFlavor(‘text/unicode’);
var str = new Object();
var len = new Object();
var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
var copytext = txt;
str.data = copytext;
trans.setTransferData(“text/unicode”,str,copytext.length*2);
var clipid = Components.interfaces.nsIClipboard;
if (!clip)
return false;
clip.setData(trans,null,clipid.kGlobalClipboard);
}
return true;
}


//运行代码
//用法:
//<textarea id=”a”>aaaaaaaa</textarea>
//<input type=”button” value=”运行” onclick=”runEx(‘a’)” />

function runEx(cod1) {
cod=document.getElementById(cod1)
var code=cod.value;
if (code!=”"){
var newwin=window.open(”,”,”);
newwin.opener = null
newwin.document.write(code);
newwin.document.close();
}
}


/*
插入Flash文件
在你要插入的位置 。
<script>
document.write( GetFlashStr(“pro.swf”,”400px”,”100px”,true) );
</script>
*/
function GetFlashStr(Path,Width,Height,Transparent){
var Temp,T=”";
Temp=’<object classid=”clsid:D27CDB6E-AE6D-11CF-96B8-444553540000″ id=”FlashH” codebase=”http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0″ border=”0″ width=”‘+Width+’” height=”‘+Height+’”>’
Temp+=’<param name=”movie” value=”‘+Path+’”/>’
Temp+=’<param name=”quality” value=”High”/>’
Temp+=’<param name=”scale” value=”ExactFit”/>’
if (Transparent) {Temp+=’ <param name=”wmode” value=”transparent”/>’;T=’wmode=”transparent”‘}
Temp+=’<embed src=”‘+Path+’” pluginspage=”http://www.macromedia.com/go/getflashplayer” type=”application/x-shockwave-flash” name=”FlashH” width=”‘+Width+’” height=”‘+Height+’” quality=”High”‘+T+’ scale=”ExactFit”/>’
Temp+=’</object>’
return Temp;
}

/**************
//间歇性循环滚动新闻。从下往上滚动。
//拷贝以下内容,到单独的页面 即可。

<div id=”icefable1″ style=”font-size:12px;”>
<div style=”text-align:left; width:100%; height:20px;”><a target=”_blank” href=”#” title=”111″>111</a></div>
<div style=”text-align:left; width:100%; height:20px;”><a target=”_blank” href=”#” title=”222″>222</a></div>
<div style=”text-align:left; width:100%; height:20px;”><a target=”_blank” href=”#” title=”333″>333</a></div>
<div style=”text-align:left; width:100%; height:20px;”><a target=”_blank” href=”#” title=”444″>444</a></div>
<SCRIPT LANGUAGE=”JavaScript”>
var marqueesRows=4; //滚动行数,与上面的div数目对应
var marqueesHeight=20; //滚动区域的高度,请同时修改上面div样式内的高度
var marqueeSpeed=30; //滚动速度(越小越快)
var pauseTime=70; //停留时间
var stopscroll=false;
var preTop=0, theTop=marqueesHeight*marqueesRows, currentTop=marqueesHeight, stoptime=0;
with(icefable1){
style.width=186; //滚动区域的宽度
style.height=marqueesHeight;
style.overflowX=”visible”;
style.overflowY=”hidden”;
noWrap=false;
onmouseover=new Function(“stopscroll=true”);
onmouseout=new Function(“stopscroll=false”);
innerHTML+=innerHTML;
scrollTop=0;
}
setInterval(“scrollUp()”,marqueeSpeed);
function scrollUp(){//Modified by Dakular
if(stopscroll==true) return;
currentTop+=1;
if(currentTop==marqueesHeight+1){
stoptime+=1; currentTop-=1;
if(stoptime==pauseTime){currentTop=0; stoptime=0;}
}else {
preTop=(++icefable1.scrollTop);
if(preTop==theTop){icefable1.scrollTop=0;}
}
}
</SCRIPT>
</div>
**************/


/**************
显示/隐藏内容。
用法:
<img src=”images/close.gif” id=”img_a” onClick=”show_hide_display(table_a,img_a)”>
<table id=”table_a”>
<tr>
<td>aaa</td>
</tr>
</table>
**************/
function show_hide_display(t_id,i_id){//显示/隐藏
var t_id;//表格ID
var i_id;//图片ID
var default_img=”images/close.gif”;//默认图片
var on_img=”images/close.gif”;//打开时图片
var off_img=”images/open.gif”;//隐藏时图片
if (t_id.style.display == “none”) {//如果为隐藏状态
t_id.style.display=”";//切换为显示状态
i_id.src=on_img;}//换图
else{//否则
t_id.style.display=”none”;//切换为隐藏状态
i_id.src=off_img;}//换图
}


/**************
使按钮有效/无效。
用法:
<form name=”form_a”>
<INPUT TYPE=”button” NAME=”aa” value=”test” onclick=”input_disabled()” />
<INPUT TYPE=”button” NAME=”bb” value=”cssrain” />
<INPUT TYPE=”button” NAME=”bb” value=”cssrain” />
</form>
**************/
function input_disabled()
{
for(var i=0;i<document.form_a.elements.length;i++)
{
if(document.form_a.elements[i].name.indexOf(“bb”)!=-1)
document.form_a.elements[i].disabled=!document.form_a.elements[i].disabled;
}
}


/**************
* 图片自动缩小方法。
* 用法:
<div id=”d”>
<img src=”http://www.baidu.com/img/logo-yy.gif” width=”300″ height=”300″/>
<img src=”http://www.baidu.com/img/logo-yy.gif” />
</div>

window.onload=function(){
resizeImg(50,’d');
}
**************/
function resizeImg(maxWidth,contentId){
var imgs=document.getElementById(contentId).getElementsByTagName(“img”);
for(var i=0;i<imgs.length;i++){
if(imgs[i].width>maxWidth){
imgs[i].removeAttribute(‘width’);
imgs[i].removeAttribute(‘height’);
imgs[i].removeAttribute(’style’);
imgs[i].width=maxWidth;
imgs[i].style.cursor=”hand”;
imgs[i].onclick = function(){
window.open(this.src);
}
}
}
}


/**************
判断浏览器和操作系统。
用法:
window.onload=function(){
alert(getPlatform());
}
**************/
/*–GLOBAL VARIABLES–*/
var OS;
var browser;
function checkIt(string) {
var detect = navigator.userAgent.toLowerCase();
return detect.indexOf(string) + 1;
}
function getPlatform() {
if (checkIt(‘konqueror’)) {
browser = “Konqueror”;
OS = “Linux”;
}
else if (checkIt(’safari’)) browser = “Safari”
else if (checkIt(‘omniweb’)) browser = “OmniWeb”
else if (checkIt(‘opera’)) browser = “Opera”
else if (checkIt(‘webtv’)) browser = “WebTV”;
else if (checkIt(‘icab’)) browser = “iCab”
else if (checkIt(‘msie 7′)) browser = “Internet Explorer 7″
else if (checkIt(‘msie’)) browser = “Internet Explorer”
else if (!checkIt(‘compatible’)) browser = “Netscape Navigator”
else browser = “Unknown Browser”;

if (!OS) {
if (checkIt(‘linux’)) OS = “Linux”;
else if (checkIt(‘x11′)) OS = “Unix”;
else if (checkIt(‘mac’)) OS = “Mac”
else if (checkIt(‘win’)) OS = “Windows”
else OS = “Unknown Operating System”;
}
return browser+”|”+OS;
}


/**************
图片,超链接提示效果.tooltips
用法:
Demo1:<img src=”a.gif” onmouseover=”showToolTip(event,’<font style=font-size:14px;font-weight:bold;color:#000000>测试1</font><img src=b.gif border=0 align=absmiddle>’);” alt=”" onmouseout=”hideToolTip();” />
Demo2:<a href=”a.html” onmouseover=”showToolTip(event,’<font style=font-size:14px;font-weight:bold;color:#000000>测试2</font><img src=b.gif border=0 align=absmiddle>’);” alt=”" onmouseout=”hideToolTip();”>cssrain.cn</a>
引用此方法注意 在页面上加入:
<div id=”frDiv_cssrain” style=”overflow: visible; position: absolute; visibility: hidden;z-index: 500″>
<iframe id=”ifr_cssrain” src=”javascript:null” style=”overflow: visible; position: relative;z-index: 500; width: 342px;height:0px;” scrolling=”no” frameborder=”0″ marginwidth=”0″ marginheight=”0″></iframe>
</div>
**************/
function hideToolTip(){
parent.document.getElementById(“frDiv_cssrain”).style.visibility=”hidden”;
}
function showToolTip(event,msg){
var event =event || window.event;
var ifr_cssrain = getIFrameDocument(“ifr_cssrain”);
var e_html = ifr_cssrain.createElement(“html”);
var e_body = ifr_cssrain.createElement(“body”);
e_body.style.marginLeft = “0px”;
e_body.style.marginTop = “0px”;
e_body.style.marginBottom = “0px”;
e_body.style.marginRight = “0px”;
var e_div = ifr_cssrain.createElement(“div”);
e_div.id = “divContent”;
e_div.style.wordWrap=”break-word”;
e_div.style.backgroundColor=”#aad5ff”;
e_div.style.borderStyle=”solid”;
e_div.style.borderWidth=”1px”;
e_div.style.borderColor=”#336699″;
e_div.style.paddingLeft = “3px”;
e_div.style.paddingTop = “3px”;
e_div.style.paddingBottom = “3px”;
e_div.style.paddingRight = “3px”;
e_div.innerHTML = msg;
e_body.appendChild(e_div);
e_html.appendChild(e_body);
ifr_cssrain.body.innerHTML = e_body.innerHTML;
var oBody = ifr_cssrain.getElementById(“divContent”);
var oFrame = document.getElementById(“ifr_cssrain”);
var oFrDiv = document.getElementById(“frDiv_cssrain”);
oFrame.style.height = oBody.offsetHeight;
//oFrame.style.width = oBody.offsetWidth;
oFrDiv.style.visibility=”visible”;
/*event.x与event.y问题
说明:IE下,even对象有x,y属性,但是没有pageX,pageY属性;
Firefox下,even对象有pageX,pageY属性,但是没有x,y属性.
解决方法:
使用mX(mX = event.x ? event.x : event.pageX;)
来代替IE下的event.x或者Firefox下的event.pageX.
*/
oFrDiv.style.left = ((event.x ? event.x : event.pageX)+1)+”px”;
oFrDiv.style.top = ((event.y ? event.y : event.pageY)+1)+”px”;
}
function getIFrameDocument(aID) {
var rv = null;
if (document.getElementById(aID).contentWindow){
rv = document.getElementById(aID).contentWindow.document;
} else {
// IE
rv = document.frames[aID].document;
}
return rv;
}


/**************
*window.open居中打开.(兼容IE和FF)
*用法:
*<input type=button onclick=”NewWindow(‘a.html’,'cssrain’,'200′,’200′,yes)”/>
**************/
var win = null;
function NewWindow(mypage,myname,w,h,scroll){
LeftPosition = (screen.width) ? (screen.width-w)/2 : 0;
TopPosition = (screen.height) ? (screen.height-h)/2 : 0;
settings =’height=’+h+’,width=’+w+’,top=’+TopPosition+’,left=’+LeftPosition+’,scrollbars=’+scroll+’,resizable’;
win = window.open(mypage,myname,settings);
win.focus();
}


/**************
*大小写金额转换函数。
把数字转成中文 — “零壹” 这种。
*用法:
小写金额:<input type=”text” name=”aaa” id=”aaa” onkeyup=”nst_convert(this)”><br>
大写金额:<input type=”text” name=”bbb” id=”bbb” size=80>
**************/
function convertCurrency(currencyDigits) {
// Constants:
var MAXIMUM_NUMBER = 99999999999.99;
// Predefine the radix characters and currency symbols for output:
var CN_ZERO = “零”;
var CN_ONE = “壹”;
var CN_TWO = “贰”;
var CN_THREE = “叁”;
var CN_FOUR = “肆”;
var CN_FIVE = “伍”;
var CN_SIX = “陆”;
var CN_SEVEN = “柒”;
var CN_EIGHT = “捌”;
var CN_NINE = “玖”;
var CN_TEN = “拾”;
var CN_HUNDRED = “佰”;
var CN_THOUSAND = “仟”;
var CN_TEN_THOUSAND = “万”;
var CN_HUNDRED_MILLION = “亿”;
var CN_SYMBOL = “人民币”;
var CN_DOLLAR = “元”;
var CN_TEN_CENT = “角”;
var CN_CENT = “分”;
var CN_INTEGER = “整”;

// Variables:
var integral; // Represent integral part of digit number.
var decimal; // Represent decimal part of digit number.
var outputCharacters; // The output result.
var parts;
var digits, radices, bigRadices, decimals;
var zeroCount;
var i, p, d;
var quotient, modulus;

// Validate input string:
currencyDigits = currencyDigits.toString();
if (currencyDigits == “”) {
alert(“Empty input!”);
return “”;
}
if (currencyDigits.match(/[^,.\d]/) != null) {
alert(“Invalid characters in the input string!”);
return “”;
}
if ((currencyDigits).match(/^((\d{1,3}(,\d{3})*(.((\d{3},)*\d{1,3}))?)|(\d+(.\d+)?))$/) == null) {
alert(“Illegal format of digit number!”);
return “”;
}

// Normalize the format of input digits:
currencyDigits = currencyDigits.replace(/,/g, “”); // Remove comma delimiters.
currencyDigits = currencyDigits.replace(/^0+/, “”); // Trim zeros at the beginning.
// Assert the number is not greater than the maximum number.
if (Number(currencyDigits) > MAXIMUM_NUMBER) {
alert(“Too large a number to convert!”);
return “”;
}
// http://www.knowsky.com/ Process the coversion from currency digits to characters:
// Separate integral and decimal parts before processing coversion:
parts = currencyDigits.split(“.”);
if (parts.length > 1) {
integral = parts[0];
decimal = parts[1];
// Cut down redundant decimal digits that are after the second.
decimal = decimal.substr(0, 2);
}
else {
integral = parts[0];
decimal = “”;
}
// Prepare the characters corresponding to the digits:
digits = new Array(CN_ZERO, CN_ONE, CN_TWO, CN_THREE, CN_FOUR, CN_FIVE, CN_SIX, CN_SEVEN, CN_EIGHT,CN_NINE);
radices = new Array(“”, CN_TEN, CN_HUNDRED, CN_THOUSAND);
bigRadices = new Array(“”, CN_TEN_THOUSAND, CN_HUNDRED_MILLION);
decimals = new Array(CN_TEN_CENT, CN_CENT);
// Start processing:
outputCharacters = “”;
// Process integral part if it is larger than 0:
if (Number(integral) > 0) {
zeroCount = 0;
for (i = 0; i < integral.length; i++) {
p = integral.length – i – 1;
d = integral.substr(i, 1);
quotient = p / 4;
modulus = p % 4;
if (d == “0″) {
zeroCount++;
}
else {
if (zeroCount > 0)
{
outputCharacters += digits[0];
}
zeroCount = 0;
outputCharacters += digits[Number(d)] + radices[modulus];
}
if (modulus == 0 && zeroCount < 4) {


outputCharacters += bigRadices[quotient];
}
}
outputCharacters += CN_DOLLAR;
}
// Process decimal part if there is:
if (decimal != “”) {
for (i = 0; i < decimal.length; i++) {
d = decimal.substr(i, 1);
if (d != “0″) {
outputCharacters += digits[Number(d)] + decimals[i];
}
}
}
// Confirm and return the final output string:
if (outputCharacters == “”) {
outputCharacters = CN_ZERO + CN_DOLLAR;
}
if (decimal == “”) {
outputCharacters += CN_INTEGER;
}
//outputCharacters = CN_SYMBOL + outputCharacters;
outputCharacters = outputCharacters;
return outputCharacters;
}//
var stmp = “”;
function nst_convert(t)
{
if(t.value==stmp) return;//如果等于上次输入则返回
var ms = t.value.replace(/[^\d\.]/g,”").replace(/(\.\d{2}).+$/,”$1″).replace(/^0+([1-9])/,”$1″).replace(/^0+$/,”0″);
//replace(/[^\d\.]/g,”")去掉输入当中不是数字和.的字符
//replace(/(\.\d{2}).+$/,”$1″)
//匹配从字符开始的第一个.后面的所有字符,由于没有使用g标记,
//所以只匹配开始第一次 然后用小数点和后两位进行替换以确定数值最后的格式正确 高.
//replace(/^0+([1-9])/,”$1″) 匹配以多个0开头的数值替换为去掉0后的数值做为数字的第一位 也是匹配开始的一次.
//replace(/^0+$/,”0″) 匹配以0开始和结束的多个0为一个0 也就是0000000 输入->转换成一个0
//以下确定输入的为过滤后的合法数字
//alert(ms);
var txt = ms.split(“.”);
//alert(txt[0]);
//如果ms值不小数点存在则txt[0]=小数点前的值否则等于ms
//regexp:/\d{4}(,|$)/ 匹配四位数字和,的集合或者四位数字和字符结尾的集合
while(/\d{4}(,|$)/.test(txt[0]))//如果为txt[0]=4123
txt[0] = txt[0].replace(/(\d)(\d{3}(,|$))/,”$1,$2″);
//txt[0].replace(/(\d)(\d{3}(,|$))/,”$1,$2″)是将txt[0]进行替换后再赋给它
//regexp:/(\d)(\d{3}(,|$))/ 将四个数字份为两组第一个数字为第一位,后三位和其他结尾为每二位
//并替换成 第一位,第二位 注意 ,的使用很好. 也就是将4123先替换成4,123
//由于此表达式默认采用贪婪匹配所以从数值后向前匹配再通过循环进行再匹配替换从而可以将
//12345678分成你想要的123,456,78 楼主彩用(,|$)很精典,因为它略去了第二次匹配时的,问题
t.value = stmp = txt[0]+(txt.length>1?”.”+txt[1]:”");
//最终赋值到输入框中
//如果有小数点则加上并购成最终数字否则显示替换后的txt[0]
bbb.value = convertCurrency(ms-0);
//将ms转换为数字送到number2num1去转换
}

/**********
简单的实时时间显示.
<body onload=”startclock()”>
<form name=”clock”>
<script language=”JavaScript”>
var timerID = null;
var timerRunning = false;
function stopclock (){
if(timerRunning)
clearTimeout(timerID);
timerRunning = false;}
function startclock () {
stopclock();
showtime();}
function showtime () {
var now = new Date();
var hours = now.getHours();
var minutes = now.getMinutes();
var seconds = now.getSeconds()
var timeValue = now.getYear()+”年”+(now.getMonth()+1)+”月”+now.getDate()+”日” +((hours >= 12) ? ” 下午 ” : ” 上午 ” )
timeValue += ((hours >12) ? hours -12 :hours)
timeValue += ((minutes < 10) ? “:0″ : “:”) + minutes
timeValue += ((seconds < 10) ? “:0″ : “:”) + seconds
document.clock.thetime.value = timeValue;
timerID = setTimeout(“showtime()”,1000);
timerRunning = true;}
</script>
<input name=”thetime” style=”font-size:9pt;color:#000000;border:1px solid #FFFFFF;” size=”28″>
</form>
*/




/* pengpeng滚动组件 */
/*
组件注意地方:滚动的部分高度或宽度要高于滚动框架的高度或宽度。调用方式放在Html架构代码下方。
关于w_demo的问题,由于横向滚动的时候需要调整整体的宽度,所以要多套一层框架。
<script language=”JavaScript” type=”text/javascript” src=”ppRoll.js”></script>
(上下)
<div id=”demo”>
<div id=”demo1″>
滚动主题
</div>
<div id=”demo2″>
</div>
</div>
(左右)
<div id=”demo”>
<table border=0 cellspacing=0 cellpadding=0>
<tr>
<td id=”demo1″>滚动内容(注意横向滚动内容的东西里一定要有宽度,比如嵌入一table,一定要让它有宽度)</td>
<td id=”demo2″></td>
</tr>
</table>
</div>
//调用方式
<script type=”text/javascript”>
var ppRoll = new ppRoll({
speed:60, //速度
demo:”demo”, //外框架div
demo1:”demo1″, //滚动主体div
demo2:”demo2″, //复制的div
objStr:”ppRoll”, //创建的对象名
width:”192px”, //外框架demo的宽度
height:”360px”, //外框架demo的高度
direction:”top” //滚动方向,可选值:top、down、left、right
});
</script>
*/
function ppRoll(a)
{
this.myA = a;
this.myA.IsPlay = 1;
this.$(a.demo).style.overflow = “hidden”;
this.$(a.demo).style.width = a.width;
this.$(a.demo).style.height = a.height;
this.$(a.demo2).innerHTML=this.$(a.demo1).innerHTML;
this.$(a.demo).scrollTop=this.$(a.demo).scrollHeight;
this.Marquee();
this.$(a.demo).onmouseover=function() {eval(a.objStr+”.clearIntervalpp();”);}
this.$(a.demo).onmouseout=function() {eval(a.objStr+”.setTimeoutpp();”)}
}
ppRoll.prototype.$ = function(Id)
{
return document.getElementById(Id);
}
ppRoll.prototype.getV = function(){
alert(this.$(this.myA.demo2).offsetWidth-this.$(this.myA.demo).scrollLeft);
alert(this.$(this.myA.demo2).offsetWidth);
alert(this.$(this.myA.demo).scrollLeft);}
ppRoll.prototype.Marquee = function()
{
this.MyMar=setTimeout(this.myA.objStr+”.Marquee();”,this.myA.speed);
if(this.myA.IsPlay == 1)
{
//向上滚动
if(this.myA.direction == “top”)
{
if(this.$(this.myA.demo).scrollTop>=this.$(this.myA.demo2).offsetHeight)
this.$(this.myA.demo).scrollTop-=this.$(this.myA.demo2).offsetHeight;
else{
this.$(this.myA.demo).scrollTop++;
}
}
//向下滚动
if(this.myA.direction == “down”)
{
if(this.$(this.myA.demo1).offsetTop-this.$(this.myA.demo).scrollTop>=0)
this.$(this.myA.demo).scrollTop+=this.$(this.myA.demo2).offsetHeight;
else{
this.$(this.myA.demo).scrollTop–;
}
}
//向左滚动
if(this.myA.direction == “left”)
{
if(this.$(this.myA.demo2).offsetWidth-this.$(this.myA.demo).scrollLeft<=0)
this.$(this.myA.demo).scrollLeft-=this.$(this.myA.demo1).offsetWidth;
else{
this.$(this.myA.demo).scrollLeft++;
}
}
//向右滚动
if(this.myA.direction == “right”)
{
if(this.$(this.myA.demo).scrollLeft<=0)
this.$(this.myA.demo).scrollLeft+=this.$(this.myA.demo2).offsetWidth;
else{
this.$(this.myA.demo).scrollLeft–;
}
}

}
}
ppRoll.prototype.clearIntervalpp = function()
{
this.myA.IsPlay = 0;
}
ppRoll.prototype.setTimeoutpp = function()
{
this.myA.IsPlay = 1;
}


/**************
*双击鼠标滚动屏幕的代码.(兼容IE和FF)
*用法:直接嵌入js,就可以用了。
**************/
var scroll_currentpos,scroll_timer;
function scroll_initialize()
{
scroll_timer=setInterval (“scrollwindow ()”,30);
}
function scroll_sc()
{
clearInterval(scroll_timer);
}
function scrollwindow()
{
scroll_currentpos=document.body.scrollTop;
window.scroll(0,++scroll_currentpos);
if (scroll_currentpos !=document.body.scrollTop)
scroll_sc();
}
document.onmousedown=scroll_sc
document.ondblclick=scroll_initialize


/**************
网页中常用的iframe分割.
经常我们看到由左,分割线,和右3部分组成的网站。
其实不难,分割线也是一个iframe,然后在里面写入下面的脚本 就可以了。
用法:
http://www.cssrain.cn/demo/2/iframe/iframe.rar
**************/
function switchSysBar(){
if (parent.document.getElementById(‘attachucp’).cols==”160,10,*”){
document.getElementById(‘leftbar’).style.display=”";
parent.document.getElementById(‘attachucp’).cols=”0,10,*”;
}
else{
parent.document.getElementById(‘attachucp’).cols=”160,10,*”;
document.getElementById(‘leftbar’).style.display=”none”
}
}
function c_load(){
if (parent.document.getElementById(‘attachucp’).cols==”0,10,*”){
document.getElementById(‘leftbar’).style.display=”";
}
}




/**************
根据年和月取当月的最后一天.(也就是当月有多少天)
用法:
var a =getLastDay(2008,5);
alert(a); // 31
**************/
function getLastDay(year,month)
{
//取年
var new_year = year;
//取到下一个月的第一天,注意这里传入的month是从1~12
var new_month = month++;
//如果当前是12月,则转至下一年
if(month>12)
{
new_month -=12;
new_year++;
}
var new_date = new Date(new_year,new_month,1);
return (new Date(new_date.getTime()-1000*60*60*24)).getDate();
}




/**************
*获取上一页的来源。
*注意此方法在本地上测试是为空。
必须放到服务器上,才有用。
**************/
function check_referrer(){
var url=document.referrer; //document.referrer是上一页的来源
var p=url.toLowerCase().indexOf(“cssrain.cn”);
if(p>=0){
}else{
}
}



/**************
创建用于ajax技术的 XMLHttpRequest对象。
用法:
try{
createXMLHttpRequest();
xmlHttp_siteTotal.open(“POST”, url);
xmlHttp_siteTotal.send(xml);
}catch(e) {
}
**************/
var xmlHttp_siteTotal;
function createXMLHttpRequest() {
if(window.XMLHttpRequest) {
xmlHttp_siteTotal = new XMLHttpRequest();
}else if(window.ActiveXObject) {
xmlHttp_siteTotal = new ActiveXObject(“Microsoft.XMLHTTP”);
}
}



/*
或其显示的高度和宽度:
必须等页面加载完后,才能获取。 onload后、
*/
// 获取显示高度
function getViewportHeight() {
if (window.innerHeight!=window.undefined) return window.innerHeight;
if (document.compatMode==’CSS1Compat’) return document.documentElement.clientHeight;
if (document.body) return document.body.clientHeight;
return window.undefined;
}
// 获取显示宽度
function getViewportWidth() {
if (window.innerWidth!=window.undefined) return window.innerWidth;
if (document.compatMode==’CSS1Compat’) return document.documentElement.clientWidth;
if (document.body) return document.body.clientWidth;
return window.undefined;
}


/*
对表单中 textarea 中的空格 和 换行处理。
*/
function convertToHtml(str)
{
var re;
re = / /g;
str = str.replace(re,” “);
re = /\r\n/g;
str = str.replace(re,”<br>”);
return str;
}
function makeToHtml(formName)
{
var form;
form = eval(formName);
for(i=0;i<form.elements.length;i++)
if(form.elements[i].type==”textarea”)
{
form.elements[i].value = convertToHtml(form.elements[i].value);
}
}


/*
得到Form数据,以 & 号 拼接起来。
在ajax传递数据中,经常用到这个方法。
用法:
<form id=”cs”>
<input type=”text” name=”aa” value=”aa”/>
<input type=”text” name=”bb” value=”bb”/>
<textarea name=”cc”>cc</textarea>
<input type=”button” value=”test” name=”btn” onclick=”alert( formdata(‘cs’) )” />
</form>
*/
function formdata(formN){
var str=”"
for(i=0;i<document.forms[formN].elements.length;i++){
if(document.forms[formN].elements[i].type!=”button”)
{ //这里可以根据需求,来判断那些类型不要
var e = document.forms[formN].elements[i];
str+=e.name+”=”+e.value+”&”
}
}
str=str+”date=”+new Date().getTime();
return str;
}


/*
字符串连接操作类
类似java里的。
用法:
var str=new StringBuilder();
str.append(“my “).append(“name “).append(“is “).append(“cssrain! “);
alert( str.toString() );
*/
function StringBuilder(sString){
this.length=0;
this.append=function(sString){
this.length+=(this._parts[this._current++]=String(sString)).length;
this._string=null;
return this;
}
this.toString=function(){
if(this._string!=null)
return this._string;
var s=this._parts.join(“”);
this._parts=[s];
this._current=1;
return this._string=s;
}
this._current=0;
this._parts=[];
this._string=null;
if(sString!=null)
this.append(sString);
}


/*
//判断两个object的值是不是相同
用法:
var a=new Object();
a["1"]=”1″
a["2"]=”2″
var b=new Object();
b["1"]=”1″
b["2"]=”2″
var c=new Object();
c["1"]=”2″
c["2"]=”3″
alert(a.compare(b))
alert(a.compare(c))
*/
function Object.prototype.compare(obj){
for(elements in this){
if(this[elements] != obj[elements])
return false
}
return true
}

/*
//得到选中的多选框值的Array
用法:
window.onload = function(){
var a = document.getElementsByName(“a”);
var get_a = getCheckBoxArray(a);
alert(get_a + ” | ” + get_a[1] )
}
<input type=”checkbox” value=”1″ name=”a” checked/>
<input type=”checkbox” value=”2″ name=”a” />
<input type=”checkbox” value=”3″ name=”a” checked/>
*/
function getCheckBoxArray(element){
var values = new Array();
if(null == element){
//alert(“no data!”);
}else if(null == element.length){
if(element.checked){
values.push(element.value);
}
}else{
for(i=0; i<element.length; i++){
if(element[i].checked){
values.push(element[i].value);
}
}
}
return values;
}

菜鸟学PHP之Smarty入门(组图)

Smarty介绍

  什么是模版引擎
  模版引擎的目的,就是要达到上述提到的逻辑分离的功能。它能让程序开发者专注于资料的控制或是功能的达成;而视觉设计师则可专注于网页排版,让网页看起来更具有专业感!因此模版引擎很适合公司的网站开发团队使用,使每个人都能发挥其专长!

  就笔者接触过的模版引擎来说,依资料呈现方式大概分成:需搭配程序处理的模版引擎和完全由模版本身自行决定的模版引擎两种形式。

  在需搭配程序处理的模版引擎中,程序开发者必须要负责变量的呈现逻辑,也就是说他必须把变量的内容在输出到模版前先处理好,才能做 assign 的工作。换句话说,程序开发者还是得多写一些程序来决定变量呈现的风貌。而完全由模版本身自行决定的模版引擎,它允许变量直接 assign 到模版中,让视觉设计师在设计模版时再决定变量要如何呈现。因此它就可能会有另一套属于自己的模版程序语法 (如 Smarty) ,以方便控制变量的呈现。但这样一来,视觉设计师也得学习如何使用模版语言。

  模版引擎的运作原理,首先我们先看看以下的运行图:
   
  一般的模版引擎 (如 PHPLib) 都是在建立模版对象时取得要解析的模版,然后把变量套入后,透过 parse() 这个方法来解析模版,最后再将网页输出。
   
  对 Smarty 的使用者来说,程序里也不需要做任何 parse 的动作了,这些 Smarty 自动会帮我们做。而且已经编译过的网页,如果模版没有变动的话, Smarty 就自动跳过编译的动作,直接执行编译过的网页,以节省编译的时间。

  使用Smarty的一些概念

  在一般模版引擎中,我们常看到区域的观念,所谓区块大概都会长成这样:
  <!– START : Block name –>
  区域内容
  <!– END : Block name –>

  这些区块大部份都会在 PHP 程序中以 if 或 for, while 来控制它们的显示状态,虽然模版看起来简洁多了,但只要一换了显示方式不同的模版, PHP 程序势必要再改一次!

  在 Smarty 中,一切以变量为主,所有的呈现逻辑都让模版自行控制。因为 Smarty 会有自己的模版语言,所以不管是区块是否要显示还是要重复,都是用 Smarty 的模版语法 (if, foreach, section) 搭配变量内容作呈现。这样一来感觉上好象模版变得有点复杂,但好处是只要规划得当, PHP 程序一行都不必改。

  由上面的说明,我们可以知道使用Smarty 要掌握一个原则:将程序应用逻辑与网页呈现逻辑明确地分离。就是说 PHP 程序里不要有太多的 HTML 码。程序中只要决定好那些变量要塞到模版里,让模版自己决定该如何呈现这些变量 (甚至不出现也行) 。

  Smarty的基础

  安装Smarty


  首先,我们先决定程序放置的位置。

  Windows下可能会类似这样的位置:「 d:\appserv\web\demo\ 」。

  Linux下可能会类似这样的位置:「 /home/jaceju/public_html/ 」。

  到Smarty的官方网站下载最新的Smarty套件:http://smarty.php.net。

  解开 Smarty 2.6.0 后,会看到很多档案,其中有个 libs 资料夹。在 libs 中应该会有 3 个 class.php 檔 + 1 个 debug.tpl + 1 个 plugin 资料夹 + 1 个 core 资料夹。然后直接将 libs 复制到您的程序主资料夹下,再更名为 class 就可以了。就这样?没错!这种安装法比较简单,适合一般没有自己主机的使用者。

  至于 Smarty 官方手册中为什么要介绍一些比较复杂的安装方式呢?基本上依照官方的方式安装,可以只在主机安装一次,然后提供给该主机下所有设计者开发不同程序时直接引用,而不会重复安装太多的 Smarty 复本。而笔者所提供的方式则是适合要把程序带过来移过去的程序开发者使用,这样不用烦恼主机有没有安装 Smarty 。

  程序的资料夹设定

  以笔者在Windows安装Appserv为例,程序的主资料夹是「d:\appserv\web\demo\」。安装好Smarty后,我们在主资料夹下再建立这样的资料夹:
   
  在 Linux 底下,请记得将 templates_c 的权限变更为 777 。Windows 下则将其只读取消。

  第一个用Smarty写的小程序

  我们先设定 Smarty 的路径,请将以下这个档案命名为 main.php ,并放置到主资料夹下:

  main.php:
  <?php
  include “class/Smarty.class.php”;
  define(‘__SITE_ROOT’, ‘d:/appserv/web/demo’); // 最后没有斜线
  $tpl = new Smarty();
  $tpl->template_dir = __SITE_ROOT . “/templates/”;
  $tpl->compile_dir = __SITE_ROOT . “/templates_c/”;
  $tpl->config_dir = __SITE_ROOT . “/configs/”;
  $tpl->cache_dir = __SITE_ROOT . “/cache/”;
  $tpl->left_delimiter = ‘<{‘;
  $tpl->right_delimiter = ‘}>’;
  ?>

  照上面方式设定的用意在于,程序如果要移植到其它地方,只要改 __SITE_ROOT 就可以啦。 (这里是参考 XOOPS 的 )

  Smarty 的模版路径设定好后,程序会依照这个路径来抓所有模版的相对位置 (范例中是 ‘d:/appserv/web/demo/templates/’ ) 。然后我们用 display() 这个 Smarty 方法来显示我们的模版。

  接下来我们在 templates 资料夹下放置一个 test.htm:(扩展名叫什么都无所谓,但便于视觉设计师开发,笔者都还是以 .htm 为主。)

  templates/test.htm:
  <html>
  <head>
  <meta http-equiv=”Content-Type” content=”text/html; charset=big5″>
  <title><{$title}></title>
  </head>
  <body>
  <{$content}>
  </body>
  </html>

  现在我们要将上面的模版显示出来,并将网页标题 ($title) 与内容 ($content) 更换,请将以下档案内容命名为 test.php ,并放置在主资料夹下:

  test.php:
  <?php
  require “main.php”;
  $tpl->assign(“title”, “测试用的网页标题”);
  $tpl->assign(“content”, “测试用的网页内容”);
  // 上面两行也可以用这行代替
  // $tpl->assign(array(“title” => “测试用的网页标题”, “content” => “测试用的网页内容”));
  $tpl->display(‘test.htm’);
  ?>

  请打开浏览器,输入 http://localhost/demo/test.php 试试看(依您的环境决定网址),应该会看到以下的画面:
   
  再到 templates_c 底下,我们会看到一个奇怪的资料夹 (%%179) ,再点选下去也是一个奇怪的资料夹 (%%1798044067) ,而其中有一个档案:

  templates_c/%%179/%%1798044067/test.htm.php:
  <?php /* Smarty version 2.6.0, created on 2003-12-15 22:19:45 compiled from test.htm */ ?>
  <html>
  <head>
  <meta http-equiv=”Content-Type” content=”text/html; charset=big5″>
  <title><?php echo $this->_tpl_vars['title']; ?></title>
  </head>
  <body>
  <?php echo $this->_tpl_vars['content']; ?>
  </body>
  </html>

  没错,这就是 Smarty 编译过的档案。它将我们在模版中的变量转换成了 PHP 的语法来执行,下次再读取同样的内容时, Smarty 就会直接抓取这个档案来执行了。

  最后我们整理一下整个 Smarty 程序撰写步骤:

  Step 1. 加载 Smarty 模版引擎。

  Step 2. 建立 Smarty 对象。

  Step 3. 设定 Smarty 对象的参数。

  Step 4. 在程序中处理变量后,再用 Smarty 的 assign 方法将变量置入模版里。

  Step 5. 利用 Smarty 的 display 方法将网页秀出。

  如何安排你的程序架构

  上面我们看到除了 Smarty 所需要的资料夹外 (class 、 configs 、 templates 、 templates_c) ,还有两个资料夹: includes 、 modules 。其实这是笔者模仿 XOOPS 的架构所建立出来的,因为 XOOPS 是笔者所接触到的程序中,少数使用 Smarty 模版引擎的架站程序。所谓西瓜偎大边,笔者这样的程序架构虽没有 XOOPS 的百分之一强,但至少给人看时还有 XOOPS 撑腰。

  includes 这个资料夹主要是用来放置一些 function 、 sql 檔,这样在 main.php 就可以将它们引入了,如下:

  main.php:

  <?php
  include “class/Smarty.class.php”;
  define(‘__SITE_ROOT’, ‘d:/appserv/web/demo’); // 最后没有斜线
  // 以 main.php 的位置为基准
  require_once “includes/functions.php”;
  require_once “includes/include.php”;
  $tpl = new Smarty();
  $tpl->template_dir = __SITE_ROOT . “/templates/”;
  $tpl->compile_dir = __SITE_ROOT . “/templates_c/”;
  $tpl->config_dir = __SITE_ROOT . “/configs/”;
  $tpl->cache_dir = __SITE_ROOT . “/cache/”;
  $tpl->left_delimiter = ‘<{‘;
  $tpl->right_delimiter = ‘}>’;
  ?>

  modules 这个资料夹则是用来放置程序模块的,如此一来便不会把程序丢得到处都是,整体架构一目了然。

  上面我们也提到 main.php ,这是整个程序的主要核心,不论是常数定义、外部程序加载、共享变量建立等,都是在这里开始的。所以之后的模块都只要将这个档案包含进来就可以啦。因此在程序流程规划期间,就必须好好构思 main.php 中应该要放那些东西;当然利用 include 或 require 指令,把每个环节清楚分离是再好不过了。
   
  在上节提到的 Smarty 程序 5 步骤, main.php 就会帮我们先将前 3 个步骤做好,后面的模块程序只要做后面两个步骤就可以了。

  从变量开始

  如何使用变量

  从上一章范例中,我们可以清楚地看到我们利用 <{ 及 }> 这两个标示符号将变量包起来。预设的标示符号为 { 及 } ,但为了中文冲码及 Javascript 的关系,因此笔者还是模仿 XOOPS ,将标示符号换掉。变量的命名方式和 PHP 的变量命名方式是一模一样的,前面也有个 $ 字号 (这和一般的模版引擎不同)。标示符号就有点像是 PHP 中的 <?php 及 ?> (事实上它们的确会被替换成这个) ,所以以下的模版变量写法都是可行的:

  1. <{$var}>

  2. <{ $var }> <!– 和变量之间有空格 –>

  3. <{$var

  }> <!– 启始的标示符号和结束的标示符号不在同一行 –>
  在 Smarty 里,变量预设是全域的,也就是说你只要指定一次就好了。指定两次以上的话,变量内容会以最后指定的为主。就算我们在主模版中加载了外部的子模版,子模版中同样的变量一样也会被替代,这样我们就不用再针对子模版再做一次解析的动作。

  而在 PHP 程序中,我们用 Smarty 的 assign 来将变量置放到模版中。 assign 的用法官方手册中已经写得很多了,用法就如同上一节的范例所示。不过在重复区块时,我们就必须将变量做一些手脚后,才能将变量 assign 到模版中,这在下一章再提。

  修饰你的变量

  上面我们提到 Smarty 变量呈现的风貌是由模版自行决定的,所以 Smarty 提供了许多修饰变量的函式。使用的方法如下:

  <{变量|修饰函式}> <!– 当修饰函式没有参数时 –>

  <{变量|修饰函式:”参数(非必要,视函式而定)”}> <!– 当修饰函式有参数时 –>
  范例如下:

  <{$var|nl2br}> <!– 将变量中的换行字符换成 <br /> –>

  <{$var|string_format:”%02d”}> <!– 将变量格式化 –>
  好,那为什么要让模版自行决定变量呈现的风貌?先看看底下的 HTML ,这是某个购物车结帐的部份画面。

  <input name=”total” type=”hidden” value=”21000″ />

  总金额:21,000 元
  一般模版引擎的模版可能会这样写:

  <input name=”total” type=”hidden” value=”{total}” />

  总金额:{format_total} 元
  它们的 PHP 程序中要这样写:

  <?php
  $total = 21000;
  $tpl->assign(“total”, $total);
  $tpl->assign(“format_total”, number_format($total));
  ?>

  而 Smarty 的模版就可以这样写: (number_format 修饰函式请到Smarty 官方网页下载)

  <input name=”total” type=”hidden” value=”<{$total}>” />

  总金额:<{$total|number_format:”"}> 元
  Smarty 的 PHP 程序中只要这样写:

  <?php
  $total = 21000;
  $tpl->assign(“total”, $total);
  ?>

  所以在 Smarty 中我们只要指定一次变量,剩下的交给模版自行决定即可。这样了解了吗?这就是让模版自行决定变量呈现风貌的好处!

  控制模版的内容

  重复的区块


  在 Smarty 样板中,我们要重复一个区块有两种方式: foreach 及 section 。而在程序中我们则要 assign 一个数组,这个数组中可以包含数组数组。就像下面这个例子:

  首先我们来看 PHP 程序是如何写的:

  test2.php:

  <?php
  require “main.php”;
  $array1 = array(1 => “苹果”, 2 => “菠萝”, 3 => “香蕉”, 4 => “芭乐”);
  $tpl->assign(“array1″, $array1);
  $array2 = array(
  array(“index1″ => “data1-1″, “index2″ => “data1-2″, “index3″ => “data1-3″),
  array(“index1″ => “data2-1″, “index2″ => “data2-2″, “index3″ => “data2-3″),
  array(“index1″ => “data3-1″, “index2″ => “data3-2″, “index3″ => “data3-3″),
  array(“index1″ => “data4-1″, “index2″ => “data4-2″, “index3″ => “data4-3″),
  array(“index1″ => “data5-1″, “index2″ => “data5-2″, “index3″ => “data5-3″));
  $tpl->assign(“array2″, $array2);
  $tpl->display(“test2.htm”);
  ?>

  而模版的写法如下:

  templates/test2.htm:

  <html>
  <head>
  <meta http-equiv=”Content-Type” content=”text/html; charset=big5″>
  <title>测试重复区块</title>
  </head>
  <body>
  <pre>
  利用 foreach 来呈现 array1
  <{foreach item=item1 from=$array1}>
  <{$item1}>
  <{/foreach}>
  利用 section 来呈现 array1
  <{section name=sec1 loop=$array1}>
  <{$array1[sec1]}>
  <{/section}>
  利用 foreach 来呈现 array2
  <{foreach item=index2 from=$array2}>
  <{foreach key=key2 item=item2 from=$index2}>
  <{$key2}>: <{$item2}>
  <{/foreach}>
  <{/foreach}>
  利用 section 来呈现 array1
  <{section name=sec2 loop=$array2}>
  index1: <{$array2[sec2].index1}>
  index2: <{$array2[sec2].index2}>
  index3: <{$array2[sec2].index3}>
  <{/section}>
  </pre>
  </body>
  </html>

  执行上例后,我们发现不管是 foreach 或 section 两个执行结果是一样的。那么两者到底有何不同呢?

  第一个差别很明显,就是foreach 要以巢状处理的方式来呈现我们所 assign 的两层数组变量,而 section 则以「主数组[循环名称].子数组索引」即可将整个数组呈现出来。由此可知, Smarty 在模版中的 foreach 和 PHP 中的 foreach 是一样的;而 section 则是 Smarty 为了处理如上列的数组变量所发展出来的叙述。当然 section 的功能还不只如此,除了下一节所谈到的巢状资料呈现外,官方手册中也提供了好几个 section 的应用范例。

  不过要注意的是,丢给 section 的数组索引必须是从 0 开始的正整数,即 0, 1, 2, 3, …。如果您的数组索引不是从 0 开始的正整数,那么就得改用 foreach 来呈现您的资料。您可以参考官方讨论区中的此篇讨论,其中探讨了 section 和 foreach 的用法。

  巢状资料的呈现

  模版引擎里最令人伤脑筋的大概就是巢状资料的呈现吧,许多著名的模版引擎都会特意强调这点,不过这对 Smarty 来说却是小儿科。

  最常见到的巢状资料,就算论譠程序中的讨论主题区吧。假设要呈现的结果如下:

  公告区

  站务公告

  文学专区

  好书介绍

  奇文共赏

  计算机专区

  硬件外围

  软件讨论

  程序中我们先以静态资料为例:

  test3.php:

  <?php
  require “main.php”;
  $forum = array(
  array(“category_id” => 1, “category_name” => “公告区”,
  ”topic” => array(
  array(“topic_id” => 1, “topic_name” => “站务公告”)
  )
  ),
  array(“category_id” => 2, “category_name” => “文学专区”,
  ”topic” => array(
  array(“topic_id” => 2, “topic_name” => “好书介绍”),
  array(“topic_id” => 3, “topic_name” => “奇文共赏”)
  )
  ),
  array(“category_id” => 3, “category_name” => “计算机专区”,
  ”topic” => array(
  array(“topic_id” => 4, “topic_name” => “硬件外围”),
  array(“topic_id” => 5, “topic_name” => “软件讨论”)
  )
  )
  );
  $tpl->assign(“forum”, $forum);
  $tpl->display(“test3.htm”);
  ?>

  模版的写法如下:

  templates/test3.htm:

  <html>
  <head>
  <title>巢状循环测试</title>
  </head>
  <body>
  <table width=”200″ border=”0″ align=”center” cellpadding=”3″ cellspacing=”0″>
  <{section name=sec1 loop=$forum}>
  <tr>
  <td colspan=”2″><{$forum[sec1].category_name}></td>
  </tr>
  <{section name=sec2 loop=$forum[sec1].topic}>
  <tr>
  <td width=”25″> </td>
  <td width=”164″><{$forum[sec1].topic[sec2].topic_name}></td>
  </tr>
  <{/section}>
  <{/section}>
  </table>
  </body>
  </html>

  执行的结果就像笔者举的例子一样。

  因此呢,在程序中我们只要想办法把所要重复值一层一层的塞到数组中,再利用 <{第一层数组[循环1].第二层数组[循环2].第三层数组[循环3]. … .数组索引}> 这样的方式来显示每一个巢状循环中的值。至于用什么方法呢?下一节使用数据库时我们再提。

  转换数据库中的资料

  上面提到如何显示巢状循环,而实际上应用时我们的资料可能是从数据库中抓取出来的,所以我们就得想办法把数据库的资料变成上述的多重数组的形式。这里笔者用一个 DB 类别来抓取数据库中的资料,您可以自行用您喜欢的方法。

  我们只修改 PHP 程序,模版还是上面那个 (这就是模版引擎的好处~),其中 $db 这个对象假设已经在 main.php 中建立好了,而且抓出来的资料就是上面的例子。

  test3.php:

  <?php
  require “main.php”;
  // 先建立第一层数组
  $category = array();
  $db->setSQL($SQL1, ‘CATEGORY’);
  if (!$db->query(‘CATEGORY’)) die($db->error());
  // 抓取第一层循环的资料
  while ($item_category = $db->fetchAssoc(‘CATEGORY’))
  {
  // 建立第二层数组
  $topic = array();
  $db->setSQL(sprintf($SQL2, $item_category['category_id']), ‘TOPIC’);
  if (!$db->query(‘TOPIC’)) die($db->error());
  // 抓取第二层循环的资料
  while ($item_topic = $db->fetchAssoc(‘TOPIC’))
  {
  // 把抓取的数据推入第二层数组中
  array_push($topic, $item_topic);
  }
  // 把第二层数组指定为第一层数组所抓取的数据中的一个成员
  $item_category['topic'] = $topic;
  // 把第一层数据推入第一层数组中
  array_push($category, $item_category);
  }
  $tpl->assign(“forum”, $category);
  $tpl->display(“test3.htm”);
  ?>

  在数据库抓取一笔资料后,我们得到的是一个包含该笔数据的数组。透过 while 叙述及 array_push 函式,我们将数据库中的资料一笔一笔塞到数组里。如果您只用到单层循环,就把第二层循环 (红色的部份) 去掉即可。

  决定内容是否显示

  要决定是否显示内容,我们可以使用 if 这个语法来做选择。例如如果使用者已经登入的话,我们的模版就可以这样写:

  <{if $is_login == true}>
  显示使用者操作选单
  <{else}>
  显示输入帐号和密码的窗体
  <{/if}>

  要注意的是,「==」号两边一定要各留至少一个空格符,否则 Smarty 会无法解析。

  if 语法一般的应用可以参照官方使用说明,所以笔者在这里就不详加介绍了。不过笔者发现了一个有趣的应用:常常会看到程序里要产生这样的一个表格: (数字代表的是资料集的顺序)

  1 2

  3 4

  5 6

  7 8

  这个笔者称之为「横向重复表格」。它的特色和传统的纵向重复不同,前几节我们看到的重复表格都是从上而下,一列只有一笔资料。而横向重复表格则可以横向地在一列中产生 n 笔资料后,再换下一列,直到整个循环结束。要达到这样的功能,最简单的方式只需要 section 和 if 搭配即可。

  我们来看看下面这个例子:

  test4.php:

  <?php
  require “main.php”;
  $my_array = array(
  array(“value” => “0″),
  array(“value” => “1″),
  array(“value” => “2″),
  array(“value” => “3″),
  array(“value” => “4″),
  array(“value” => “5″),
  array(“value” => “6″),
  array(“value” => “7″),
  array(“value” => “8″),
  array(“value” => “9″));
  $tpl->assign(“my_array”, $my_array);
  $tpl->display(‘test4.htm’);
  ?>

  模版的写法如下:

  templates/test4.htm:

  <html>
  <head>
  <title>横向重复表格测试</title>
  </head>
  <body>
  <table width=”500″ border=”1″ cellspacing=”0″ cellpadding=”3″>
  <tr>
  <{section name=sec1 loop=$my_array}>
  <td><{$my_array[sec1].value}></td>
  <{if $smarty.section.sec1.rownum is div by 2}>
  </tr>
  <tr>
  <{/if}>
  <{/section}>
  </tr>
  </table>
  </body>
  </html>

  重点在于 $smarty.section.sec1.rownum 这个 Smarty 变量,在 section 循环中这个变量会取得从 1 开始的索引值,所以当 rownum 能被 2 除尽时,就输出 </tr><tr> 使表格换列 (注意!是 </tr> 在前面<tr> 在后面) 。因此数字 2 就是我们在一列中想要呈现的资料笔数。各位可以由此去变化其它不同的呈现方式。

  加载外部内容

  我们可以在模版内加载 PHP 程序代码或是另一个子模版,分别是使用 include_php 及 include 这两个 Smarty 模版语法; include_php 笔者较少用,使用方式可以查询官方手册,这里不再叙述。

  在使用 include 时,我们可以预先加载子模版,或是动态加载子模版。预先加载通常使用在有共同的文件标头及版权宣告;而动态加载则可以用在统一的框架页,而进一步达到如 Winamp 般可换 Skin 。当然这两种我们也可以混用,视状况而定。

  我们来看看下面这个例子:

  test5.php:

  <?php
  require “main.php”;
  $tpl->assign(“title”, “Include 测试”);
  $tpl->assign(“content”, “这是模版 2 中的变量”);
  $tpl->assign(“dyn_page”, “test5_3.htm”);
  $tpl->display(‘test5_1.htm’);
  ?>

  模版 1 的写法如下:

  templates/test5_1.htm:

  <html>
  <head>
  <meta http-equiv=”Content-Type” content=”text/html; charset=big5″>
  <title><{$title}></title>
  </head>
  <body>
  <{include file=”test5_2.htm”}><br />
  <{include file=$dyn_page}>
  <{include file=”test5_4.htm” custom_var=”自订变量的内容”}>
  </body>
  </html>

  模版 2 的写法如下:

  templates/test5_2.htm:

  <{$content}>
  模版 3 的写法如下:

  templates/test5_3.htm:

  这是模版 3 的内容
  模版 4 的写法如下:

  templates/test5_4.htm:

  <{$custom_var}>
  这里注意几个重点:1. 模版的位置都是以先前定义的 template_dir 为基准;2. 所有 include 进来的子模版中,其变量也会被解译。;3. include 中可以用「变量名称=变量内容」来指定引含进来的模版中所包含的变量,如同上面模版 4 的做法。

php绝对路径与相对路径之间关系的的深入研究

php中好像不能像asp那样用”/”表示根目录,代之以$_SERVER['DOCUMENT_ROOT'],其它则相同:../表示向上一层。./表示当前层。假如现在a/b/c/s.php要调用根目录下的 /bb/s2.txt,则:

$RootDir = $_SERVER['DOCUMENT_ROOT'];
$fireDir = “$RootDir/bb/s2.txt”;

或者:”../../../bb/s2.txt”表示向上返回到b再向上到a再向上到根目录然后到bb下。

前一阵子老是受php开发中,文件互相引入require()相对位置关系的困扰,为了彻底弄清它们的关系,笔者做了个实验。

以下是实验图:

当前项目(project2)的绝对路径是:D:\www\php_case\Coucom_make。也就是我们当前项目的根目录root.

为了能更加清楚的表述不同级别的目录文件相互的引入问题,偶大胆将引用分成三种类型即:上级对下级的引用(简称上级引用,英文译为:superior to underling。简称(stou)).

下级对上级的引用(简称下级引用,英文反之便是)

平级引用或叫同级引用(英文:paratactic)。  

好了,我们明确了引用类型,下面我们来看不同类型引用它们有着什么样的规则。

我们先来说说上级引用:

看我们的实验图,在图中项目下分别有aa bb ee 三个同级目录和一个index.php文件,在bb下又有cc目录,cc下又有dd目录和cc.php ccc.php两个文件,同样dd下也包含一个dd.php文件。凡是上层对下层均属上级引用.

例如:index.php对于所有文件的引用:
   cc .php对dd.php的引用:
   ee.php对dd.php的引用:

大家仔细看一下目录结构,便会发现这三种引用虽然同属于上级引用,但它们又不完全相同,我把它分成两种情况:即在上级引用中存在两种引用情况:1.从属的上级引用(类如cc.php对dd.php,,因为这两个文件同属于cc目录)2.非从属的上级引用(类如index.php对于所有文件的引用和 ee.php对dd.php的引用都属于这种情况因为它们与被引用的文件并没有一个共同的父目录,在能相对于站点根目录).

对于从属上级引用:

以下是在cc.php对dd.php的引用

require(‘dd/dd.php’);

对于非从属上级引用:

以下是在ee.php中对cc.php的引用

require(‘../bb/cc/cc.php’);

以上所说的是上级引用,下面我们来了解一下下级引用!同理下层对上层的引用都属于下级引用,同样分成从属与非从属两类,从属下级引用相对路径以它们的父目录为根目录,例如:

Ttt.php对bbff.php的引用就属于这种情况:require(‘../bb/cc/cc.php’);

非从属的下级引用却是以网站的根目录为准的,例如:

ccc.php对ee.php的引用: require(‘../../ee/ee.php’);

以上是下级引用的介绍,最后我们来看一下平级引用或者叫同级引用,其实同级引用也是分为这两种情况:从属同级引与非从属同级引用

从属同级引用很简单:即在同一个目录下的两个文件的引用

例如:在dd.php中引用ttt.php require(‘ttt.php’);

非从属同级引用:即不在同一个目录下(没有共同的父目录,只有以网站目站为父目录的情况),但是级别是相同的两个文件的引用,例如: 在aa.php在引用ee.php require(‘../ee/ee.php’);

以上是三种类型不同情况下的引用,另外还有涉及到嵌套引用的问题

比如:

ff.php引用dd.php,而dd.php又引用的gf.php,这种情况,本来dd.php 引用gf.php属于下级引用中的非从属引用,写法是这样的:require(‘../../../ee/gf.php’);而ff.php引用 dd.php属于上级引用中的从属引用,写法是这样的:require(‘./cc/dd/dd.php’); 可是你会发现在ff.php中无法找到 gf.php文件,那该如何写呢?我告诉你应该在dd.php中这样写:require(‘../ee/gf.php’);只有这样写就正确了,为什么呢?因为在涉及到嵌套引用的时候被引用文件的相对路径要以最终的引用文件为准!

简而言之:

其实很简单的,你用你的web根目录做根目录.不管你怎么定,你文件肯定有一个全部都要包含的文件的,比如有的较global.php,有的较common.php

假如这个文件放再根目录

wwwroot/global.php

里面第一行你加个chdir(dirname(__FILE__)); //切换到global.php所在目录就是跟目录

其他文件使用

require “../../../global.php”;
require “aa/aa.php”;
require “bb/bb/cc.php”;

这样就行了,因为你的global.php已经把路径切换到wwwroot了,你不用像很多人那么麻烦

define(‘ROOT_PATH’,dirname(__FILE__));
require ROOT_PATH…..

chdir(dirname(__FILE__)); 的确很好使,相对位置引入这个文件其他引入文件只要以他为基准就好了。

用PHP编程读取汉字点阵数据_PHP技巧

背景知识:  简体中文国标字库(1981年订,中国大陆)。7445个字符,其中汉字6773个,包括一级汉字3755个,二级汉字3008个。采用2字节(16位二进制)编码。   区位码:国标GB2312规定,所有的国标汉字与符号组成一个94×94的矩阵。在此方阵中,每一行称为一个”区”,每一列称为一个”位”,因此,这个方阵实际上组成了一个有94个区(区号分别为0 1到94)、每个区内有94个位(位号分别为01到94)的汉字字符集。一个汉字所在的区号和位号简单地组合在一起就构成了该汉字的”区位码”。在汉字的区位码中,高两位为区号,低两位为位号。由此可见,区位码与汉字或符号之间是一一对应的。  内码:汉字的内码是指在计算机中表示汉字的编码。机内码与区位码稍有区别。为什么不直接用区位码作为计算机内的编码呢? 这是因为汉字的区码和位码的范围都在1到94内, 如果直接用区位码作机内码, 就会与基本ASCII码冲突。 汉字的内码通常与所使用的计算机系统有关。目前,对于国内大多数的计算机系统,一个汉字的内码占两个字节,分别称为高位字节与低位字节,且这两位字节与区位码的关系如下: 内码高位=区码+A0H(H表示十六进制) 内码低位=位码+A0H 例如,汉字”啊”的区位码为”1601″,区码和位码分别用十六进制表示即为”1001H”,则它的内码为”B0A1H”。其中B0H为内码的高位字节,A1H为内码的低位字节。   php代码:返回由0和1组成的字符串。<?php/*** 读取汉字点阵数据** @author legend <legendsky@hotmail.com>* @link http://www.ugia.cn/?p=82* @Copyright www.ugia.cn*/$str = “中华人民共和国” ;$font_file_name = “simsun12.fon” ; // 点阵字库文件名$font_width = 12 ; // 单字宽度$font_height = 12 ; // 单字高度$start_offset = 0 ; // 偏移$fp = fopen ( $font_file_name , “rb” );$offset_size = $font_width * $font_height / 8 ;$string_size = $font_width * $font_height ;$dot_string = “” ;for ( $i = 0 ; $i < strlen ( $str ); $i ++){ if ( ord ( $str { $i }) > 160 ) {  // 先求区位码,然后再计算其在区位码二维表中的位置,进而得出此字符在文件中的偏移  $offset = (( ord ( $str { $i }) – 0xa1 ) * 94 + ord ( $str { $i + 1 }) – 0xa1 ) * $offset_size ;  $i ++; } else {  $offset = ( ord ( $str { $i }) + 156 – 1 ) * $offset_size ; } // 读取其点阵数据 fseek ( $fp , $start_offset + $offset , SEEK_SET ); $bindot = fread ( $fp , $offset_size ); for ( $j = 0 ; $j < $offset_size ; $j ++) {  // 将二进制点阵数据转化为字符串  $dot_string .= sprintf ( “%08b” , ord ( $bindot { $j })); }}fclose ( $fp );echo $dot_string ;?>   其中包括两个点阵字体文件:一个为16×16的chs16.fon,另一个为12×12的simsun12.fon,偏移均为零。