存档

‘学习笔记’ 分类的存档

spring2.5+struts2+hibernate3.6 整合心得

2011年3月23日 没有评论

配置log4j属性文件

在tomcat启动的时候,出现这个警告:
log4j:WARN No appenders could be found for logger (org.apache.commons.digester.Digester.sax).
log4j:WARN Please initialize the log4j system properly.

解决办法:
log4j.properties文件需要放到web-inf/class目录下面,在eclipse里面放到src目录下面,会自动拷贝到class目录下面去。

文件:log4j.properties

log4j.rootLogger=CONSOLE,FILE

log4j.addivity.org.apache=true

# 应用于控制台

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender

log4j.appender.CONSOLE.Threshold=INFO

log4j.appender.CONSOLE.Target=System.out

log4j.appender.CONSOLE.Encoding=GBK

log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout

log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

# 每天新建日志

log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender

log4j.appender.A1.File=C:/log4j/log

log4j.appender.A1.Encoding=GBK

log4j.appender.A1.Threshold=DEBUG

log4j.appender.A1.DatePattern='.'yyyy-MM-dd

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

log4j.appender.A1.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L : %m%n

#应用于文件

log4j.appender.FILE=org.apache.log4j.FileAppender

log4j.appender.FILE.File=C:/log4j/file.log

log4j.appender.FILE.Append=false

log4j.appender.FILE.Encoding=GBK

log4j.appender.FILE.layout=org.apache.log4j.PatternLayout

log4j.appender.FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

# 应用于文件回滚

log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender

log4j.appender.ROLLING_FILE.Threshold=ERROR

log4j.appender.ROLLING_FILE.File=rolling.log

log4j.appender.ROLLING_FILE.Append=true

log4j.appender.CONSOLE_FILE.Encoding=GBK

log4j.appender.ROLLING_FILE.MaxFileSize=10KB

log4j.appender.ROLLING_FILE.MaxBackupIndex=1

log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout

log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

#自定义Appender

log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender

log4j.appender.im.host = mail.cybercorlin.net

log4j.appender.im.username = username

log4j.appender.im.password = password

log4j.appender.im.recipient = yyflyons@163.com

log4j.appender.im.layout=org.apache.log4j.PatternLayout

log4j.appender.im.layout.ConversionPattern =[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

#应用于socket

log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender

log4j.appender.SOCKET.RemoteHost=localhost

log4j.appender.SOCKET.Port=5001

log4j.appender.SOCKET.LocationInfo=true

# Set up for Log Facter 5

log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout

log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n

# Log Factor 5 Appender

log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender

log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000

# 发送日志给邮件

log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender

log4j.appender.MAIL.Threshold=FATAL

log4j.appender.MAIL.BufferSize=10

log4j.appender.MAIL.From=yyflyons@163.com

log4j.appender.MAIL.SMTPHost=www.wusetu.com

log4j.appender.MAIL.Subject=Log4J Message

log4j.appender.MAIL.To=yyflyons@126.com

log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout

log4j.appender.MAIL.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n

Spring配置文件

需要注意xml文件的头部

开启对注解和事务的支持需要加语句

<context:annotation-config />

<tx:annotation-driven/>

文件:applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xmlns:aop="http://www.springframework.org/schema/aop"

 xmlns:tx="http://www.springframework.org/schema/tx"

 xmlns:context="http://www.springframework.org/schema/context"

 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd 

 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 

 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">

<!-- 打开依赖注解方式注入 -->

<context:annotation-config />

<!-- 配置数据源 -->

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

<property name="driverClassName" value="com.mysql.jdbc.Driver"/>

<property name="url" value="jdbc:mysql://localhost/ssh"/>

<property name="username" value="root"/>

<property name="password" value="5476"/>

</bean>

<!-- 配置sessionFactory -->

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<property name="dataSource" ref="dataSource" />

<property name="mappingResources">

<list>

<value>com/test/bean/user.hbm.xml</value>

</list>

</property>

<property name="hibernateProperties">

<props>

<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>

<prop key="hibernate.hbm2ddl.auto">update</prop>

<prop key="hibernate.show_sql">true</prop>

</props>

</property>

</bean>

<!-- 配置事务管理器 -->

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

<property name="sessionFactory">

<ref local="sessionFactory" />

</property>

</bean>

<!-- 配置事务拦截器Bean -->

<bean id="transactionInterceptor"

class="org.springframework.transaction.interceptor.TransactionInterceptor">

<!-- 为事务拦截器bean注入一个事物管理器 -->

<property name="transactionManager" ref="transactionManager"></property>

<property name="transactionAttributes">

<!-- 定义事务传播属性 -->

<props>

<prop key="insert*">PROPAGATION_REQUIRED</prop>

<prop key="update*">PROPAGATION_REQUIRED</prop>

<prop key="save*">PROPAGATION_REQUIRED</prop>

<prop key="add*">PROPAGATION_REQUIRED</prop>

<prop key="remove*">PROPAGATION_REQUIRED</prop>

<prop key="delete*">PROPAGATION_REQUIRED</prop>

<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>

<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>

<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>

<prop key="change*">PROPAGATION_REQUIRED</prop>

<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>

</props>

</property>

</bean>

<!-- 打开事务支持 -->

<tx:annotation-driven transaction-manager="transactionManager"/>

<!--<import resource=""/>-->

<bean id="userService" class="com.test.service.impl.UserServiceBean" />

<bean id="userAction" class="com.test.action.UserAction">

<property name="userService" ref="userService"/>

</bean></beans>

Spring 需要的jar包

asm-2.2.3.jar

asm-commons-2.2.3.jar

asm-util-2.2.3.jar

aspectjrt.jar

aspectjweaver.jar

cglib-nodep-2.1_3.jar

common-annotations.jar

commons-dbcp.jar

commons-logging.jar

commons-pool.jar

log4j-1.2.15.jar

spring.jar

spring-webmvc-struts.jar //支持struts2

Struts2配置文件

最重要的一句

<!– 把action对象交给spring创建 –>

<constant value=”spring” />

文件:Struts.xml

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE struts PUBLIC

"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<!-- 指定Web应用的默认编码集,相当于调用HttpServletRequest的setCharacterEncoding方法 -->

<constant name="struts.i18n.encoding" value="UTF-8" />

<!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 -->

<constant name="struts.serve.static.browserCache" value="false" />

<!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 -->

<constant name="struts.configuration.xml.reload" value="true" />

<!-- 开发模式下使用,这样可以打印出更详细的错误信息 -->

<constant name="struts.devMode" value="true" />

<!-- 默认的视图主题 -->

<constant name="struts.ui.theme" value="simple" />

<!-- 最关键的参数 -->

<!-- 把action对象交给spring创建 -->

<constant name="struts.objectFactory" value="spring" />

<package name="myDefault" extends="struts-default">

<default-action-ref name="indexPage" />

<global-results>

<result name="exceptionPage">/exceptionPage.jsp</result>

</global-results>

<global-exception-mappings>

<exception-mapping result="exceptionPage" exception="java.lang.Exception" />

</global-exception-mappings>

<action name="indexPage">

<result>/index.jsp</result>

</action>

</package>

<package name="user" namespace="/user" extends="myDefault">

<!-- 这里面的class不是指完整类路径,而是指在spring中定义的bean的名称 -->

<action name="userAction" class="userAction">

<result name="success">/success.jsp</result>

<result name="input">/index.jsp</result>

</action>

</package>

</struts>

Struts需要的jar包

commons-beanutils-1.7.0.jar

commons-chain-1.2.jar

commons-fileupload-1.2.1.jar

commons-io-1.3.2.jar

commons-logging-1.0.4.jar

commons-logging-api-1.1.jar

commons-validator-1.3.1.jar

freemarker-2.3.15.jar

ognl-2.7.3.jar

oro-2.0.8.jar

struts2-core-2.1.8.jar

struts2-spring-plugin-2.1.8.jar

tiles-api-2.0.6.jar

tiles-core-2.0.6.jar

tiles-jsp-2.0.6.jar

xwork-core-2.1.6.jar

Hibernate的配置

Hibernate需要的jar包

antlr-2.7.6.jar

commons-collections-3.1.jar

dom4j-1.6.1.jar

ehcache-1.5.0.jar

hibernate3.jar

hibernate-jpa-2.0-api-1.0.0.Final.jar

javassist-3.12.0.GA.jar

jta-1.1.jar

slf4j-api-1.6.1.jar

slf4j-log4j12-1.6.1.jar

文件:user.hbm.xml

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping

package="com.test.bean">

<class name="User" table="user">

<id name="id">

<generator class="native"/>

</id>

<property name="name" length="10" not-null="true"/>

<property name="password" length="10" not-null="true"/>

</class>

</hibernate-mapping>

Myeclipse8.0/8.5丢失配置和默认workspace问题

2011年3月23日 没有评论

修改Myeclipse根目录下的configuration/config.ini文件

osgi.instance.area.default=file:\D\:\\projects\\myeclipse

完美解决

分类: 全部文章, 学习笔记 标签:

php 生成日历的简单程序

2011年2月18日 没有评论

<?php

$month = $_GET['m']?$_GET['m']:date(‘n’);
$year = $_GET['y']?$_GET['y']:date(‘Y’);

$start_week = date(‘w’,mktime(0,0,0,$month,1,$year));
$day_num = date(‘t’,mktime(0,0,0,$month,1,$year));
$end = false;
?>
<table>
<tr>
<td>星期日</td><td>星期一</td><td>星期二</td><td>星期三</td><td>星期四</td><td>星期五</td><td>星期六</td>
</tr>
<tr>
<?php
for($i = 0; $i<$start_week; $i++)
{
echo “<td></td>”;
}

$j=1;

while($j<=$day_num)
{
echo “<td>$j</td>”;
$week = ($start_week+$j-1)%7;

if($week ==6){
echo “\n\t</tr>\n”;
if($j != $day_num)
echo “\t<tr>\n\t\t”;
else $end = true;
}
$j++;
}
while($week%7 != 6)
{
echo “<td></td>”;
$week++;
}
if(!$end)
echo “\n</tr>”;
?>

</table>

分类: 全部文章, 学习笔记 标签: ,

javascript 表单 submit()错误

2010年10月18日 没有评论

做个简单的表单验证,调用表单对象的submit对象竟然出现submit is not a function这样的错误,花了半个晚上的时间,终于找出了原因

原来 js对submit关键字敏感,而我的表单中有按钮name=”submit”…

把所有的name=”submit”去掉一切正常

吐血。。。

纯javascript 单行向上滚动效果代码

2010年9月20日 没有评论
<style>
*{margin:0;padding:0;}
#scrollDiv {height:30px;overflow:hidden;position:relative;margin:50px;}
#scrollUl {position:absolute;}
#scrollUl li{height:30px;line-height:30px;}
</style>
<script type="text/javascript">
function scrollOneStep(obj)
{
var ul = document.getElementById(obj);
var li = ul.getElementsByTagName("li");
var li_move = li.item(0);
var line = 0 - parseInt(li_move.clientHeight);
var speed = 10;
var pix = 0;
t2 = setInterval(function(){
if(pix > line){
ul.style.top = ""+pix + "px";
pix --;
}else{
clearInterval(t2);
}
},speed);

ul.style.top += parseInt(ul.style.top)+30+"px";

ul.removeChild(li_move);
ul.appendChild(li_move);
ul.style.top = "0"

}

function scroll(obj)
{
var t= setInterval(function(){scrollOneStep(obj);},1000);
}
</script>
<div id="scrollDiv">
<ul id="scrollUl">
<li>164101***400</li>
<li>334205***400</li>
<li>164101***400</li>
<li>334205***400</li>
<li>164101***400</li>
<li>334205***400</li>
<li>164101***400</li>
</ul>
</div>
<script language="javascript"> scroll('scrollUl'); </script>

smarty 函数插件里使用组合变量(变量连接)

2010年9月14日 没有评论

针对函数传递的变量连接问题:
<?PHP
$var['name'] = ‘shooting’;
?>

我想要在smarty中实现这样的效果:
{fck name = “var[shooting]“}

错误的写法:
{fck name = “var[$var.name]“}
这样$var.name就被解析成了Array.name显然是错误的
正确的写法:
{fck name = “var[`$var.name`]“}
“`”这个符号,是键盘左上角,数字1前面的那个符号

分类: 学习笔记 标签: ,

在php中使用 TCPDF 动态创建 PDF [转载]

2010年9月13日 没有评论

简介

TCPDF 是托管在 Sourceforge.net 上最活跃的项目之一,其完全在 PHP 上实现了强大的 PDF 生成引擎。这使得其更容易安装,即使在您无法访问系统目录或编译自己的代码的站点上。同时,通过让您直接查看 PHP 代码生成的结果,而不使用任何中间步骤,这使迭代开发更加容易。

TCPDF 支持一系列有用的图像格式,包括 SVG 矢量格式和位图格式,如 JPEG 和 PNG。一个简单独立的实用工具让您可以处理 TrueType、OpenType、PostScript Type 1 和 CID-0 字体,使它们可以添加到 TCPDF 创建的文档。您可以使用 TCPDF 来生成无数 1-D 和 2-D 条形码格式,且它支持所有常见的 PDF 功能,如书签、文档链接、压缩、注释、文档加密和数字签名。

用 PHP 编写 TCPDF 并使用其页面,这使其易于创建并部署 PDF 生成的 Web 页面。在您使用任何支持 Web 服务器和您最喜欢的 PHP 开发环境开发并部署 TCPDF 时,我将使用如下工具:

  • Eclipse V3.5.2 — 我最新欢的开源开发环境之一,其支持广泛的编程语言和环境。
  • PHP Development Tools V2.2.0 — 适用于 Eclipse 的 PHP 插件。
  • MAMP Pro V1.9 — 适用于 Mac OS X 的方便的程序包,其通过有用的 GUI 前端在一个隔离的环境中提供 Apache、MySQL 和 PHP。虽然 Mac OS X 附带安装 Apache 和 PHP,但我还是选择使用此工具,因为其提供了一系列稳定且容易分离的 Web 服务器/数据库/PHP。
  • TCPDF V5.0.006 — TCPDF 当前的稳定版本。

您可以在 参考资料 部分找到以上所有工具的下载链接。

如果您已经安装了 PHP,我们就来看看如何在您自己的网站上使用 TCPDF。我们将检查安装过程,然后我们将使用 PHP 生成一个显示可能来自任何电子商务站点的发票式样(invoice-style)文档的网页。此后,我们将使用 TCPDF 来创建一个使用类似格式的可打印的 PDF 版发票。


回页首

安装 TCPDF

当您从 Sourceforge.net 下载 TCPDF 时,它提供一个自包含的 ZIP 存档,也就是说,您可以使用您最喜欢的 ZIP 提取工具来解压存档,您最终将获得一个包含您所需要的所有信息的 TCPDF 目录。

如果您将 TCPDF 目录添加到您的 web 文档目录,则您可以通过加载 doc/index.html 访问 TCPDF 文档并通过加载 examples/index.php 文件查看任何示例,这也可在 TCPDF 网站上找到(请参考 参考资料)。

然而在您可以查看示例以前,您需要配置您的 TCPDF 安装。


回页首

配置 — 类 UNIX 系统

如果您正在类 UNIX® 系统上安装 TCPDF,则您需要更改文件模式,因为它们并没有全部被标记为可执行。在 Microsoft® Windows® 系统上存在一个创建 TCPDF 存档的副作用。幸运的是,很容易在来自 shell 的一个失衡中调整这些(请参考 清单 1)。您还需要确保缓存和图像目录是可写入的,因为 TCPDF 将在那里存储临时文件。

下一步,您需要将文件分配给用户和组 web 服务器;虽然这通常是用户 www 和组 www,但是这将取决于您的系统。如果您正在您的个人网站领域以外运行 TCPDF,(在您的主目录下通常是 public_html),则您可以跳过此步骤。
清单 1. 调整文件模式和所有权

$ cd tcpdf
$ find . -type f | xargs chmod -x
$ chmod +w cache images
$ chown -R www:www .

请注意命令可能使用 . 代替 : 来在一些系统上分离用户和组;如果出现问题,则检查其文档详细资料。


回页首

适用于每个人的配置

使用您最喜欢的文本编辑器,加载 config/tcpdf_config.php 文件。这就是 TCPDF 的配置设置并让您控制库的默认设置,并告诉它如何找到自己的支持文件。

在 tcpdf_config.php 中您想要变更的设置包括:

  • PDF_PAGE_FORMAT — 如果您不使用公制页面格式,则设置其为 letter。除非您手头有一些非常奇特方法,否则 TCPDF 可能比您的打印机支持更大的页面尺寸。
  • PDF_UNIT — 如果您想用点而不是毫米来布置您的 PDF 文档,则设置其为 pt
  • PDF_CREATORPDF_AUTHOR — 一旦您的 PDF 生成代码忘了设置它们,则默认文档创建者和作者。

您可以在您的 PHP 代码中调整这些设置中的任意一个,如果无法确定也无需担心(例如,如果您在此处设置的是像模式文档布局,您仍然可以创建景观文档)。

假设您没有移动文件和目录远离其初始位置,则通过默认配置设置,TCPDF 应该没有呈现任何其附带示例的问题。

在这一点上,您可以加载示例文件以确保您拥有一个正在运行的 TCPDF 安装。让我们使用它来创建一个可打印版的发票。


回页首

创建发票

在您创建了电子商务网站以后,您的客户将订购一些物品,而您将收取他们的货款。虽然这很不错,但是他们将想得到某种发票,以防订单错误或他们的信用卡公司搞混了付款,。

让我们制作一个合理美观的发票网页,这样他们可以看到他们已经订购了什么和您将要向他们收取什么。


回页首

第一个版本 — Web 页面

使用我最喜欢的 PHP 开发环境,我已经创建了一个新的发票文件夹,其包含如下文件:

  • Invoice.php — PHP 生成发票
  • Invoice.css — CSS 式样的发票
  • Azuresol_OnyxTree-S.png — Azuresol 的 “OnyxTree S”,您将其用作您公司的标志(来自 iconfinder.com Web 站点的免费图标(请参考 参考资料))
  • gentleface_print.png — gentleface 的 “Print”,您将使用其触发 PDF 生成(来自 iconfinder.com 的另一个免费图标)

在 Invoice.php 内部,检查看看是否使用 PDF 参数调用页面(请参考 清单 2)。如果不是,用户想要一个正常 web 页面,这样您就可以使用 generateHTML 函数(请参考 清单 3)显示页面。稍后您将看到 generatePDF 函数,但是可以肯定使用它来生成发票数据的 PDF 没任何问题。
Listing 2. 页面生成控制代码

if( array_key_exists( 'PDF', $_REQUEST ) ) {
    generatePDF( $invoiceData );
} else {
    generateHTML( $invoiceData );
}

$invoiceData 阵列拥有所有发票数据;虽然您将直接在 Invoice.php 上创建它,但是您可以设想数据来自于数据库、web 服务或某种网上购物车系统。
清单 3. 生成 HTML

function generateHTML( $data ) {
?>
... HTML code was here ...
<?php
    foreach( $data['items'] as $item ) {
        echo '<tr>' . "\n";
        echo '    <td>' . $item[0] . "</td>\n";
        echo '    <td>' . $item[1] . "</td>\n";
        echo '    <td>' . $item[2] . "</td>\n";
        echo '    <td>' . $item[3]. "</td>\n";
        echo "</tr>\n";
    }
?>
... HTML code was here ...
<?php
    echo '<td>' . $data['total'] . "</td>\n";
?>
... HTML code was here ...
<?php
    echo 'Invoice prepared for ' . $data['user'] . ' on ' . $data['date'] . "\n";
?>
... HTML code was here ...
<?php

}

为了简单明了我已经删掉了此处所有的 HTML 标记代码;您可以在位于 CreatingPDFs-Invoice.zip 存档文件中的 Invoice.php 上看到它, CreatingPDFs-Invoice.zip 存档文件可以在 下载 部分找到。

使用传递给函数的发票信息作为 $data,创建一个包含每个项目一行的表、及其数量、单价和总价的表。在表的末尾,添加一个包含订单的总成本的行。页脚包含用户 ID 和发票生成的日期/时间。

当然,简单明了的事情,以及您在自己站点上实现它的时候所面临的主要挑战,将与您的数据源互动,并获得恰到好处的 CSS 式样。
图 1. 光彩夺目的网页发票
截图显示了一个有吸引力的可打印发票示例;Sumatra Special 的最大数量为 24,而其他的则处于 1 到 5 之间

我完全虚构了一家提供优良咖啡和茶的 South Seas Pacifica 公司,显然我对 Sumatran 品种深深的吸引了。至少他们的价格很吸引人!

右下角的打印机图标是诱人的,您希望能够有单击那里并获得打印发票。这里就是 TCPDF 的用武之地。并不只是打印网页,您将为我们尊贵的客户提供一个时髦的 PDF 版本,这会使他们在轻松的状态下完成打印。


回页首

第二个版本 — PDF

现在,您的网页发票看起来很好,您需要创建可以打印的 PDF 版本。

回忆 清单 2,将 PDF 参数 (http://…/Invoice.php?PDF) 与 Invoice.php 页面一起加载将调用具有相同数据的 generatePDF 函数(请参考清单 4)。
清单 4. 生成 PDF 发票

function generatePDF( $data ) {
    # Create a new PDF document.
    $pdf = new InvoicePdf( $data, 'P', 'pt', 'LETTER' );

    # Generate the invoice.
    $pdf->CreateInvoice();

    # Output the PDF document.
    $pdf->Output( 'Your_Invoice.pdf', 'D' );
}

generatePDF 函数创建了一个 InvoicePdf 对象,调用其 CreateInvoice 方法,然后发送一个名为 Your_Invoice.pdf 的下载 PDF 文档给用户的浏览器。虽然这看起来非常简单,但是隐藏了必须自己创建 InvoicePdf 类的事实,且需要复制原始发票式样。让我们来看看这是如何进行的。

InvoicePdf 类扩展了 TCPDF 的 TCPDF 类,这是主 PDF 生成引擎。在构造函数(请参考 清单 5)中,使用传入的 $orientation(页面方向)、$unit(计量单位)和 $format(页 面大小)初始化父类。TCPDF 构造函数的最后三个参数表明输入的是 Unicode(默认为 Ture),已生成 PDF 的字符编码格式是 UTF-8,且您不应使用磁盘缓存 (False)。虽然在创建 PDF 时,磁盘缓存减少了内存占用,但是速度变得更慢了。因为我们的文件不大也不复杂,所以无需权衡这一点。

在初始化父类以后,将参考存储到发票数据以便今后使用。下一步,使用 SetMargins 方法将页边距设置为宽度 72 点、高度 36 点。SetMargins 最终参数表明您正在用自己的值来重写默认页边距。使用 SetAutoPageBreaks 方法,可在从底部算起有 36 点高时告知 TCPDF 自动创建新页面。
清单 5. InvoicePdf 类构造函数

function __construct( $data, $orientation, $unit, $format ) {
    parent::__construct( $orientation, $unit, $format, true, 'UTF-8', false );

    $this->invoiceData = $data;

    # Set the page margins: 72pt on each side, 36pt on top/bottom.
    $this->SetMargins( 72, 36, 72, true );
    $this->SetAutoPageBreak( true, 36 );

    # Set document meta-information
    $this->SetCreator( PDF_CREATOR );
    $this->SetAuthor( 'Chris Herborth (chrish@pobox.com)' );
    $this->SetTitle( 'Invoice for ' . $this->invoiceData['user'] );
    $this->SetSubject( "A simple invoice example for 'Creating PDFs on
the fly with TCPDF' on IBM's developerWorks" );
    $this->SetKeywords( 'PHP, sample, invoice, PDF, TCPDF' );

    //set image scale factor
    $this->setImageScale(PDF_IMAGE_SCALE_RATIO); 

    //set some language-dependent strings
    global $l;
    $this->setLanguageArray($l);
}

在建立边距以后,设置 PDF 文档元信息。这将显示在您最喜欢的 PDF 查看器中的文档属性窗口。这些仅仅是字符串,因此您可以将它们设置为任何对您的应用程序有意义的信息。

使用 setImageScale 方法,在 TCPDF 的配置文件中使用默认图像缩放比例设置。这是用于将位图图像的大小从像素大小调整为适合的页面。

最后,使用 setLanguageArray 来为 PDF 文件设置一些语言相关的字符串;通过 TCPDF 主配置,这些会在特定语言配置文件中定义。

清单 6 中,您重写了 Header 方法,其被调用以便生成每一个页面的标题内容。首先,定义一些变量。以 14 点的 bigFont 大小开始,您会计算出商标图像的相对大小和相对于 bigFont 大小的正常文本大小。然后您将深入 TCPDF 调用。

ImagePngAlpha 方法插入放置在其左上角宽 72 点、高 32 点的商标图像,其与您以前的边距设置相匹配。因为它是一个正方形的图像,所以您可以指定相同的宽度和高度(已计算的 $imageScale)。您将要说明它是一个 PNG 图像,因为此调用实际可以插入 PNG 和 JPEG 图像(如果在您的 PHP 安装中已安装了 GD 库,则其也可以加载任何由 GD 支持的图像)。下一步,指定一个空值,因为您没有为此图像添加 PDF 链接(通过 AddLink 方法创建)目标。再下一步,使用 T 来说明您想在图像区域的右上角制定下一个 PDF 对象。最后,告知 TCPDF 不要调整图像大小,既保持初始的 72 dpi(一个通用的屏幕分辨率),且图像在页面上应该左对齐。

显然,ImagePngAlpha 方法对如何在 PDF 文档中将图像添加到页面的问题上给予您大量的控制(请参考清单 6)。
清单 6. 页面标题的生成

public function Header() {
    global $webcolor;

    # The image is this much larger than the company name text.
    $bigFont = 14;
    $imageScale = ( 128.0 / 26.0 ) * $bigFont;
    $smallFont = ( 16.0 / 26.0 ) * $bigFont;

    $this->ImagePngAlpha('Azuresol_OnyxTree-S.png', 72, 36, $imageScale,
$imageScale, 'PNG', null, 'T', false, 72, 'L' );
    $this->SetFont('times', 'b', $bigFont );
    $this->Cell( 0, 0, 'South Seas Pacifica', 0, 1 );
    $this->SetFont('times', 'i', $smallFont );
    $this->Cell( $imageScale );
    $this->Cell( 0, 0, '', 0, 1 );
    $this->Cell( $imageScale );
    $this->Cell( 0, 0, '31337 Docks Avenue,', 0, 1 );
    $this->Cell( $imageScale );
    $this->Cell( 0, 0, 'Toronto, Ontario', 0, 1 );

    $this->SetY( 1.5 * 72, true );
    $this->SetLineStyle( array( 'width' => 2, 'color' =>
array( $webcolor['black'] ) ) );
    $this->Line( 72, 36 + $imageScale, $this->getPageWidth() - 72, 36
+ $imageScale );
}

在标题上放置商标图像以后,设置字体(粗体 Times,使用您的 bigFont 大小),然后创建一些单元格来存放公司的名称和地址信息。这些单元格在 HTML 上包含文本,而且有点像表格单元格。Cell 方法采用这些参数(实际上更多;参考 TCPDF 文档获取完整列表):

  • Width — 单元格宽度;如果设置为 0,则单元格一直扩展到右侧边距(或者如果您使用的是从右到左的语言,则扩展到左侧边距)。
  • Height — 单元格高度;如果设置为 0,则单元格高度将扩展,以便能放得下内容。
  • Text — 该文本在单元格内绘制,使用当前的字体和颜色设置。
  • Border — 说明是否边界应该根据单元格制定。在这种情况下,由于您正在使用 0,所以您无需任何边界。您也可以传递 1 来根据单元格制定完整的边界,或字符串以便说明特定的边界。
  • Position — 说明何处创建下一个单元格;1 表明您需要其在下一行的开始出显示,但是您可以使用 0 在此单元格旁边添加下一个单元格,或者 2 以停留在当前的 X 坐标并移到下一行。

最后,我们的 Header 方法在标题的底部绘制了一条两点黑线,一直穿过页面的内容区域。图 2 显示了将如何在页面上查看,如 Mac OS X 的 预览应用程序所呈现的那样。
图 2. 打印标题,就像网页标题
截图对左边的地址显示了带有图形商标的标题,名称使用大的、粗体的字体,且地址使用斜体

现在您已经创建了一个原始标题的合理副本,您也需要重写 Footer 方法,以便于您生成页脚。这非常简单,只包含用户 ID 和发票信息,其通过另外一个两点黑线从剩余的页面中分离出来。

您尚未看到此方法的唯一部分正在使用使用一个负值调用 SetY 方法。在您这样做的时候,相对于页面的底部设置当前的 Y。在这里,您将要为页面页脚留下大量的空间,以确保您的绘制不太接近底部边距(请参考清单 7)。
清单 7. 页面页脚的生成

public function Footer() {
    global $webcolor;

    $this->SetLineStyle( array( 'width' => 2, 'color' =>
array( $webcolor['black'] ) ) );
    $this->Line( 72, $this->getPageHeight() - 1.5 * 72 - 2,
$this->getPageWidth() - 72, $this->getPageHeight() - 1.5 * 72 - 2 );
    $this->SetFont( 'times', '', 8 );
    $this->SetY( -1.5 * 72, true );
    $this->Cell( 72, 0, 'Invoice prepared for ' .
$this->invoiceData['user'] . ' on ' . $this->invoiceData['date'] );
}

在您创建页面时,显示出来的就像发票的网络版,只是减去了打印机的图标。您已经中断了此操作,因为这是打印版本(它是多余的)。图 3 得出了结果。
图 3. 已打印的页脚
截图显示了页脚,其对带有收件人、时间和日期的详细信息用粗体水平线标出

在这一点上,您拥有附带美观的页眉和页脚的空白页。您需要为此添加实际的发票内容,这样做很有用。

在使用 AddPage 方法启动新的页面以后(在这种情况下,这是唯一的页面),将字体设置为 11 点 Helvetica 并将插入点从页面的顶部移动到 144 点处。在表开始以前,这会在页眉以下给我们留出一个小空间。

下一步,要计算您将需要使表居中的缩进量,这基于页面宽度、两个 72 点边距、一个宽列和三个正常列。

在此之后,您将使用以前计算出的值并描绘出每个单元格的完全边界,来创建一系列单元格以呈现列标题。您还要右对齐数字列的标题因为它们通过值进行排列。在标题单元格的最后,您要调用 Ln 方法以便向下移动到下一行的开始。

通过在发票上迭代项目的 foreach 循环,您为每一个内容行进行同类型的布局(请参考清单 8)。
清单 8. 页面内容的生成

public function CreateInvoice() {
    $this->AddPage();
    $this->SetFont( 'helvetica', '', 11 );
    $this->SetY( 144, true );

    # Table parameters
    #
    # Column size, wide (description) column, table indent, row height.
    $col = 72;
    $wideCol = 3 * $col;
    $indent = ( $this->getPageWidth() - 2 * 72 - $wideCol - 3 * $col ) / 2;
    $line = 18;

    # Table header
    $this->SetFont( '', 'b' );
    $this->Cell( $indent );
    $this->Cell( $wideCol, $line, 'Item', 1, 0, 'L' );
    $this->Cell( $col, $line, 'Quantity', 1, 0, 'R' );
    $this->Cell( $col, $line, 'Price', 1, 0, 'R' );
    $this->Cell( $col, $line, 'Cost', 1, 0, 'R' );
    $this->Ln();

    # Table content rows
    $this->SetFont( '', '' );
    foreach( $this->invoiceData['items'] as $item ) {
        $this->Cell( $indent );
        $this->Cell( $wideCol, $line, $item[0], 1, 0, 'L' );
        $this->Cell( $col, $line, $item[1], 1, 0, 'R' );
        $this->Cell( $col, $line, $item[2], 1, 0, 'R' );
        $this->Cell( $col, $line, $item[3], 1, 0, 'R' );
        $this->Ln();
    }

    # Table Total row
    $this->SetFont( '', 'b' );
    $this->Cell( $indent );
    $this->Cell( $wideCol + $col * 2, $line, 'Total:', 1, 0, 'R' );
    $this->SetFont( '', '' );
    $this->Cell( $col, $line, $this->invoiceData['total'], 1, 0, 'R' );
}

代码的最后一位呈现总行数。这演示了您如何可以更容易地在单元格之间变更字体式样(通过调用 SetFont 方法来打开或关闭粗体)。第一个文本单元格的宽度被设置横跨表的前三列,因为您需要发票总数出现在最后一列的底部。

一旦您完成后,发票项目表看起来将非常的棒(请参考图 4)。
图 4. 发票上的项目
附带数量、价格和总数的项目格式化清单的截图

通过逻辑地布局文本单元格,您已经用适合打印的格式重新创建了初始的网页。在无需变更网页本身或任何基础数据的情况下,TCPDF 让您将创建 PDF 的支持添加到您现存的 PHP 网页上。


回页首

结束语

本文向您介绍了 TCPDF,它是一种用于生成 PDF 文档的流行 PHP 库。TCPDF 无需额外的库就能执行此操作,并使其作为您现有 PHP 网站的一部分易于安装。本文向您显示了在类 UNIX 系统中安装并配置 TCPDF 的概述。然后您创建了一个简单的基于 Web 的发票,类似于您可能在一家从事异国热饮的电子商务站点上所看到的诸如此类的事情。

一旦您拥有一个看上去像专业发票的网页,您就可以扩展 TCPDF 类来生产一个 PDF 版本的发票,即客户可以轻松地下载或打印。重写 HeaderFooter 方法让我们用相似的方式建立页面,然后您可以编写一个附加方法来布置发票项目作为一个表。


回页首

下载

描述 名字 大小 下载方法
文章源代码 os-tcpdf-CreatingPDFs-Invoice.zip 21KB HTTP

关于下载方法的信息

本文转载自IBM.COM

http://www.ibm.com/developerworks/cn/opensource/os-tcpdf/index.html?ca=drs-

ajax 返回的innerHTML里面的javascript代码执行问题及Demo [转载]

2010年9月13日 没有评论

解决了一个困扰我许久的问题,用过AJAX的人可能会知道,当把从服务器返回xhr.responseText的数据设定给innerHTML时, 里面的JS代码并不能够执行,查了很多资料,终于找到一个简单而且可行的办法,就是把JS代码封装到一个DIV中通过xhr.responseText打 包给innerHTML,然后把<script></script>标签扒下去,在通过eval()函数执行JS代码(思想转载 自这 里),这里以弹出对话框为例,示例如下:

<!–这是innerHTML的内容–>

<div id=”a”>

<script>

alert(“aa”);

<script>

</div>

<!–这是调用JS的主页内容–>

var pageInfo = xhr.responseText;

document.getElementById(“pageInfo”).innerHTML = pageInfo;

eval(document.getElementById(“aa”).innerHTML.replace(/<script>|<\/script>/,”)); //将<script>标签替换掉,这样才能被eval()函数执行

结果出现了显示”aa”的对话框!

但是问题又出现了,如果执行2句或者两句以上的JS代码就会出现错误了!

这样我们就可以把需要执行的多行JS代码封装成一个方法直接放到需要调用该JS代码的主页面里,然后再被调用的页面里写上这个方法名就可以了,这里 以弹出2个对话框为例,示例如下:

<!–这是innerHTML的内容–>

<div id=”a”>

<script>

doit();

<script>

</div>

<!–这是调用JS的主页内容–>

var pageInfo = xhr.responseText;

document.getElementById(“pageInfo”).innerHTML = pageInfo;

eval(document.getElementById(“aa”).innerHTML.replace(/<script>|<\/script>/,”)); //将<script>标签替换掉,这样才能被eval()

function doit(){

alert(“aa”);

alert(“bb”);

}

结果出现了”aa” “bb”两个对话框!

这样就完美解决了ajax 返回的innerHTML里面的javascript代码执行问题,一些复杂的JS函数都可以,而且一些jQuery的方法也可以哦!

这是在网上找的资料,依据以此,我写了例子来 验证:

Defalut.aspx

<%@ Page Language=”C#” AutoEventWireup=”true” CodeBehind=”Default.aspx.cs” Inherits=”AjaxJsTestWeb._Default” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml” >
<head runat=”server”>
<title>无标题页</title>
<script language=”javascript” type=”text/javascript” >

function getRequest() {
http_request = false;
if (window.XMLHttpRequest) {
//对于Mozilla﹑Netscape﹑Safari等浏览器,创建XMLHttpRequest
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
//如果服务器响应的header不是text/xml,可以调用其它方法修改该header
http_request.overrideMimeType(‘text/xml’);
}
} else if (window.ActiveXObject) {
// 对于Internet Explorer浏览器,创建XMLHttpRequest
try {
http_request = new ActiveXObject(“Msxml2.XMLHTTP”);
} catch (e) {
try {
http_request = new ActiveXObject(“Microsoft.XMLHTTP”);
} catch (e) {}
}
}
return http_request;
}
//获得Url 的responseText

function getResponseText(url)
{
http_request=getRequest();
http_request.open(‘GET’, url, false);
http_request.send(null);

if (http_request.readyState == 4)
{
// 收到完整的服务器响应
if (http_request.status == 200) {
//HTTP服务器响应的值OK
requestdoc = http_request.responseText;
//将服务器返回的字符串写到页面中ID为message的区域
}
else {
requestdoc = http_request.status;
}
}
return requestdoc;
}
//获得Url 的responseXML

//代码片段
function getResponseXml(url)
{
http_request=getRequest();
http_request.open(‘GET’, url, false);
http_request.send(null);

if (http_request.readyState == 4)
{
// 收到完整的服务器响应
if (http_request.status == 200) {
//HTTP服务器响应的值OK
requestdoc = http_request.responseXML;
//将服务器返回的字符串写到页面中ID为message的区域
}
else {
requestdoc = http_request.status;
}
}
return requestdoc;
}

function TestAjaxJs()
{
http_request=getRequest();
http_request.open(‘GET’, “containjsText.aspx”, false);
http_request.send(null);

if (http_request.readyState == 4)
{
// 收到完整的服务器响应
if (http_request.status == 200) {
//HTTP服务器响应的值OK
requestdoc = http_request.responseText;
//将服务器返回的字符串写到页面中ID为message的区域
}
else {
requestdoc = http_request.status;
}
}
// debugger;
document.getElementById(“divJsText”).InnerHTML=requestdoc;
alert( document.getElementById(“divJsText”).InnerHTML);
var str;
str=document.getElementById(“divJsText”).InnerHTML.replace(/<script language=’javascript’>|<\/script>/,”);
str=str.replace(/<\/script>/,”);

alert(str);
eval(str);
// document.write(document.getElementById(“divJsText”).InnerHTML);
return false;
}

</script>
</head>
<body>
<form id=”form1″ runat=”server”>
<div>
<div id=”divJsText” ></div>
<asp:Literal ID=”ltrJsText” runat=”server”></asp:Literal><asp:Label ID=”lblJsText” runat=”server”></asp:Label>
<asp:Button ID=”btnAjax” runat=”server” Text=”Ajax请求返回带有JS脚本的文本 JS脚本执行”  OnClientClick=”return TestAjaxJs();”/>
</div>
</form>
</body>
</html>

ContainJsText.aspx.cs 代码页面

两种情况:

(1)多个JS语句

namespace AjaxJsTestWeb
{
public partial class ContainJsText : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder jsText = new StringBuilder();
jsText.AppendLine(“<script language=’javascript’>function doit(){alert(‘哈哈,我执行了啊!’);alert(‘哈哈,我再次执行了啊!’);} doit();</script>”);
Response.Write(jsText.ToString().Trim());
Response.End();
}
}
}

(2) 就一个js语句

namespace AjaxJsTestWeb
{
public partial class ContainJsText : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
StringBuilder jsText = new StringBuilder();
jsText.AppendLine(“<script language=’javascript’>alert(‘哈哈,我执行了啊!’)</script>”);
Response.Write(jsText.ToString().Trim());
Response.End();
}
}
}

转自 http://www.taotechinfo.com/collect/2010724/n807115732.html

分类: 学习笔记 标签: , , ,

自动开设虚拟主机的bash脚本

2010年6月2日 没有评论

脚本很简单,功能是,自动增加一个以输入域名命名的www根目录,自动生成一个ftp用户,自动创建一个mysql数据库,自动创建一个mysql用户

#!/bin/bash

#输入要增加的域名
echo “Input The Domain”
read
domain=$REPLY

#这里输入ftp密码
echo “Input The Password”
read
ftp_password=$REPLY

#mysql的超级用户名和密码
mysql_root=”root”
mysql_root_pass=”abcdefg”
database_name=${domain//./_}
database_user=${domain//./_}

vhost_file=”${domain}.conf”
echo “Input Mysql Password for Database ${database_name}”
read
database_password=$REPLY
cd /www/wwwroot/
mkdir $domain
chown daemon:daemon $domain
chmod 700 $domain

#生成虚拟机的配置文件
cd /usr/local/apache2/conf/vhost
cp 51rego.com.conf $vhost_file
sed “s/51rego.com/$domain/ig” $vhost_file >temp
cat temp>$vhost_file
#增加ftp虚拟用户和密码
cd /www/users/conf
echo $domain>>vusers.txt
echo $ftp_password>>vusers.txt
db_load -T -t hash -f vusers.txt /etc/vsftpd_login.db
#增加一个ftp账户
cd /etc/vsftpd_user_conf
cp 51rego.com $domain
sed “s/51rego.com/$domain/ig” $domain >temp
cat temp>$domain

#创建mysql数据库
mysql -u${mysql_root} -p${mysql_root_pass} -e “create database ${database_name}”

#创建mysql用户和密码
mysql -u${mysql_root} -p${mysql_root_pass} -e “grant all privileges on ${database_name}.* to ${database_user}@localhost identified by ‘${database_password}’”
echo “Ftp User Name: ${domain}”
echo “Ftp Password: ${ftp_password}”
echo “Mysql database: ${database_name}”
echo “Mysql user: ${database_user}”
echo “Mysql password: ${database_password}”
echo “success! restart httpd…”

#重启httpd
/usr/local/apache2/bin/httpd -S
service httpd graceful
exit

javascript 获取滚动条高度+常用js页面宽度与高度[转]

2010年5月20日 没有评论

/********************
* 取窗口滚动条高度
******************/
function getScrollTop()
{
var scrollTop=0;
if(document.documentElement&&document.documentElement.scrollTop)
{
scrollTop=document.documentElement.scrollTop;
}
else if(document.body)
{
scrollTop=document.body.scrollTop;
}
return scrollTop;
}

/********************
* 取窗口可视范围的高度
*******************/
function getClientHeight()
{
var clientHeight=0;
if(document.body.clientHeight&&document.documentElement.clientHeight)
{
var clientHeight = (document.body.clientHeight<document.documentElement.clientHeight)?document.body.clientHeight:document.documentElement.clientHeight;
}
else
{
var clientHeight = (document.body.clientHeight>document.documentElement.clientHeight)?document.body.clientHeight:document.documentElement.clientHeight;
}
return clientHeight;
}

/********************
* 取文档内容实际高度
*******************/
function getScrollHeight()
{
return Math.max(document.body.scrollHeight,document.documentElement.scrollHeight);
}

////////////////////////////////////////////////////

在IE中:
document.body.clientWidth ==> BODY对象宽度
document.body.clientHeight ==> BODY对象高度
document.documentElement.clientWidth ==> 可见区域宽度
document.documentElement.clientHeight ==> 可见区域高度
在FireFox中:
document.body.clientWidth ==> BODY对象宽度
document.body.clientHeight ==> BODY对象高度
document.documentElement.clientWidth ==> 可见区域宽度
document.documentElement.clientHeight ==> 可见区域高度
?
在 Opera中:
document.body.clientWidth ==> 可见区域宽度
document.body.clientHeight ==> 可见区域高度
document.documentElement.clientWidth ==> 页面对象宽度(即BODY对象宽度加上Margin宽)
document.documentElement.clientHeight ==> 页面对象高度(即BODY对象高度加上Margin高)
而如果没有定义W3C的标准,则
IE为:
document.documentElement.clientWidth ==> 0
document.documentElement.clientHeight ==> 0
FireFox为:
document.documentElement.clientWidth ==> 页面对象宽度(即BODY对象宽度加上Margin宽)document.documentElement.clientHeight ==> 页面对象高度(即BODY对象高度加上Margin高)
Opera为:
document.documentElement.clientWidth ==> 页面对象宽度(即BODY对象宽度加上Margin宽)document.documentElement.clientHeight ==> 页面对象高度(即BODY对象高度加上Margin高)
真是一件麻烦事情,其实就开发来看,宁可少一些对象和方法,不使用最新的标 准要方便许多啊。

//////////////////////////////////////////////////////////////////////////////////////

网页可见区域宽:
document.body.clientWidth

网页可见区域高:
document.body.clientHeight

网页可见区域宽:
document.body.offsetWidth(包 括边线的宽)

网页可见区域高:
document.body.offsetHeight(包括边线的宽)

网页 正文全文宽:
document.body.scrollWidth

网页正文全文高:
document.body.scrollHeight

网 页被卷去的高:
document.body.scrollTop

网页被卷去的左:
document.body.scrollLeft

网 页正文部分上:
window.screenTop

网页正文部分左:
window.screenLeft

屏 幕分辨率的高:
window.screen.height

屏幕分辨率的宽:
window.screen.width

屏 幕可用工作区高度:
window.screen.availHeight

屏幕可用工作区宽度:
window.screen.availWidth

分类: 学习笔记 标签: ,