分类 网页与编程 中的文章

Apache + PHP + MySQL Windows 下配置

经常碰到的东西,从来记不清,记一下。
几个软件的安装没有什么说的,这里记录下关键的部分。

php.ini
php.ini 放到 Windows 目录下(建议用 php.ini-dist)
启用 php_mysql.dll 扩展

Path
将 Apache 下的 bin 目录路径和 php 路径(或者加上 php 下的 ext 路径)加入到系统环境变量中

http.conf
启用 LoadModule php5_module D:/php/php5apache2.dll
可以在下面使用 PHPIniDir "D:/php" 参数,指定 php.ini 所在目录位置,在放在 Windows 目录下时无需指定。
AddType application/x-httpd-php .php  让 .php 格式文件可以执行 PHP
增加 DirectoryIndex 中的默认首页 index.php

重启服务吧,关于性能优化什么的找 Google 大神。
Pader 2010-10-23 0

简化 PHPWind 伪静态规则

PHPWind 的伪静态规则很简单,一条 RewriteRule 就可以了。

伪静态出来的规则地址如下:
thread.php?fid=1                   thread-htm-fid-1.html
read.php?tid=1                      read-htm-tid-1.html
read.php?tid=1&page=2     read-htm-tid-1-page-2.html
...

有没有发现其实有些东西是多余的,-htm- 这个是干嘛的呢,难道是为了让搜索引擎更加坚定的认为这个是静态页面?是则是,不是则不是,搜索引擎虽然不是很聪明的东西,但也不傻。所以,能简则简,默认的规则是这样的:
RewriteRule ^(.*)-htm-(.*)$ $1.php\?$2

我们首先在后台 核心设置>静态目录部署 设置中,把静态目录这个参数由 “-htm-” (默认时是 .php?)改为 “-”,对就是一个横杠。
然后把 Rewrite 规则改成:
RewriteRule ^([\w\d_]+)-(.*)$ $1.php?$2
或者你也可以使用这条:
RewriteRule ^(.*?)-(.*?\.html)$ $1.php?$2
 
这样地址就变成了:
thread-fid-1.html
read-tid-1.html
read-tid-1-page-2.html
....

看不到这里 -htm- 心里爽多了。
这里规则是 .htaccess 文件中的,Apache 配置文件,IIS 或 Nginx 等规则大同小异,懂的话对比修改一下就行了。
如果还想网站兼容以前的地址的来保证搜录的话,可以在这个规则之前加上下面这个规则:
RewriteRule ^(.*)-htm-(.*)$ $1.php?$2 [L]
记住,是加在之前哦,这样的话,以前的地址仍然可以访问了,不担心以前搜录的失效。
 
实话说,多用几条规则这里的 -fid-, -page- 之类的都可以省掉,像 Discuz 那样,但是还要改程序。还是简单最好,我们做小改动带来小简单。
Pader 2010-10-23 0

IMG 元素的 complete 属性:不在标签上使用 onload 自动调整图像大小

关于网页中调整图像大小的方法大家肯定都会,通常情况下,我们会在 <img/> 标签内使用 onload 在图像加载完成后调用指定的函数来调整大图像的大小,为什么要 onload 之后呢?因为必须等图像加载完成之后,JS才能正确的得到图像的宽高,从而等比缩放图像。

那么问题是什么呢?其实由于一些特殊原因,我们无法保证能在指定区域里的每一个 <img/> 元素中都增加 onload,如果我们在统一的脚本中去获取那一块的 <img/> 元素,然后增加 onload  事件是不靠谱的,因为 onload 事件必须在图像加载完成之前增加到元素上,如果元素已经加载完成后再去附件 onload 事件,那么这个事件是不会被触发的。

如果我们能得知这个元素是否加载完成,那么就好办了,加载完成的话,直接调用指定的 JS 的函数来调整大小,没有加载完成,则赋于这个元素 onload 事件,把调整大小的函数放到 onload 中。

怎么知道这个元素是否加载完成呢?对 complete 属性,比如我们有一个图像元素的 ID 是 "image" ,则可以使用 document.getElementById("image").complete 来得到这个元素是否加载完成。这是一个布尔值,TRUE 则代表加载完成。

那么我们具体的实用演示见下:
 

<!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" xml:lang="cn" lang="cn">
<head>
<meta http-equiv="Content-Language" content="zh-CN" />
<meta http-equiv="Content-Type" content="text/html; charset=gbk" />
<title>关于 IMG 元素的 complete 属性演示,自动调整图像大小 - VGOT.NET</title>
</head>
<body> 

<p>这个演示主要是介绍 img 的 complete 属性,而不是如何调整图像大小,大家注意重心哈。</p>
<p>几张图片也只是我从网上随便搜的演示,不一定随时都能打开。</p>

<!-- 这里先放几张图 -->
<div id="content">
 <img src="http://bbsfile.ifeng.com/bbsfile/attachments/72_OZcuDZ3H9wqU.jpg" border="0" />
 <img src="http://pic.nipic.com/2008-09-04/20089423244653_2.jpg" border="0" />
 <img src="http://www.thegreatwall.com.cn/photo/upload/2005/10/11294617800.jpg" border="0" />
</div>
</body>
<script type="text/javascript">
//这下面的脚本建议就像这样放在网页底部
//不建议放在 window.onload 里,如果使用了 jQuery 则可以放在 $(document).ready(); 里
//或者参考这篇文章:http://www.vgot.net/?A65.htm
function adjustImageSize() {
 //这里使用 this 指针来代替传参的当前元素,下面有解释
 var imgMaxWidth = 350, imgMaxHeight = 300;        //图像限制的最大宽高
 var w = this.offsetWidth, h = this.offsetHeight;  //获取元素的宽高
 //通过计算等比调整图像宽高
 if(imgMaxWidth > 0 && w > imgMaxWidth) {
  this.width = imgMaxWidth;
  this.height = h/(w/imgMaxWidth);
 } else if(imgMaxHeight > 0 && h > imgMaxHeight) {
  this.height = imgMaxHeight;
  this.width = w/(h/imgMaxHeight);
 }
}
var imgs = document.getElementById("content").getElementsByTagName("img");
for(var i=0; i<imgs.length; i++) {
 if(imgs[i].complete) {  //使用 complete 属性判断元素是否加载完成
  //直接调用函数调整图像大小
  //这里使用函数的 call() 方法将函数的 this 指针改为 imgs[i] 元素
  adjustImageSize.call(imgs[i]);
 } else {
  //没有加载完成则将函数赋到元素的 onload 事件中
  //onload 的内部 this 指针本身就是它所属的元素
  imgs[i].onload = adjustImageSize;
 }
}
</script>
</html>
 
点击这里下载示例文件:[attach=212]
Pader 2010-7-23 0

JS 动态加载脚本文件并在完成后执行回调

我们经常在一个交互性强的页面内外嵌了大量的脚本文件,有时候因为需求问题,不得不在某些不太好的位置根据情况下嵌入脚本文件,可是又不知道这些文件是否,什么时候加载完成了,想要在文件加载完成后执行一段代码该怎么办呢?

我们可以动态的创建 <script> 元素,然后通过更改它的 src 属性来加载脚本,但是怎么知道这个脚本文件加载完成了呢,因为我们有些函数需要在脚本加载完成生效后才能开始执行。
经过对网络上资源的搜索,我发现在 IE 浏览器中可以使用 <script> 元素的 onreadystatechange 来监控加载状态的改变,并通过判断它的 readyState 是 loaded 或 complete 来判断脚本是否加载完成。而非 IE 浏览器可以使用 onload 来直接判断脚本是否加载完成。

所以一个简单的实现过程看上去是下面这样的:IE下:

var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.onreadystatechange = function() {
   if(this.readyState == "loaded" || this.readyState == "complete") {
       alert("加载成功啦!");
   }
}
script.setAttribute("src",scripts[i]);

Opera、FF、Chrome等:

var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.onload = function() {
   alert("加载成功啦!");
}
script.setAttribute("src",scripts[i]);

原理很简单吧,根据这两个简单的原理,我们进行一些修改,我把改成了两个函数,分别是串行加载和并行加载脚本。
当传一个包含多个JS文件路径的数组时,串行加载函数从第一个脚本文件加载开始,每加载成功一个便开始加载下一个脚本文件,全部加载完成后执行回调函数。而并行加载是一开始便加载全部的脚本文件,也就是他们从同一点开始加载,当全部加载完成后,执行回调函数。
经过测试,这两个函数兼容目前的所有主游戏浏览器。

/**
 * 串联加载指定的脚本
 *
 * 串联加载[异步]逐个加载,每个加载完成后加载下一个
 * 全部加载完成后执行回调
 *
 * @param array|string 指定的脚本们
 * @param function 成功后回调的函数
 * @return array 所有生成的脚本元素对象数组
 */
function seriesLoadScripts(scripts,callback) {
	if(typeof(scripts) != "object") var scripts = [scripts];
	var HEAD = document.getElementsByTagName("head").item(0) || document.documentElement;
	var s = new Array(), last = scripts.length - 1, recursiveLoad = function(i) {  //递归
		s[i] = document.createElement("script");
		s[i].setAttribute("type","text/javascript");
		s[i].onload = s[i].onreadystatechange = function() {  //Attach handlers for all browsers
			if(!/*@[email protected]*/0 || this.readyState == "loaded" || this.readyState == "complete") {
				this.onload = this.onreadystatechange = null; this.parentNode.removeChild(this);
				if(i != last) recursiveLoad(i + 1); else if(typeof(callback) == "function") callback();
			}
		}
		s[i].setAttribute("src",scripts[i]);
		HEAD.appendChild(s[i]);
	};
	recursiveLoad(0);
}

/**
 * 并联加载指定的脚本
 *
 * 并联加载[同步]同时加载,不管上个是否加载完成,直接加载全部
 * 全部加载完成后执行回调
 *
 * @param array|string 指定的脚本们
 * @param function 成功后回调的函数
 * @return array 所有生成的脚本元素对象数组
 */
function parallelLoadScripts(scripts,callback) {
	if(typeof(scripts) != "object") var scripts = [scripts];
	var HEAD = document.getElementsByTagName("head").item(0) || document.documentElement, s = new Array(), loaded = 0;
	for(var i=0; i<scripts.length; i++) {
		s[i] = document.createElement("script");
		s[i].setAttribute("type","text/javascript");
		s[i].onload = s[i].onreadystatechange = function() {  //Attach handlers for all browsers
			if(!/*@[email protected]*/0 || this.readyState == "loaded" || this.readyState == "complete")  {
				loaded++;
				this.onload = this.onreadystatechange = null; this.parentNode.removeChild(this);
				if(loaded == scripts.length && typeof(callback) == "function") callback();
			}
		};
		s[i].setAttribute("src",scripts[i]);
		HEAD.appendChild(s[i]);
	}
}

在这里是把 <script> 标签动态的插入到页面中的 <head> 标签内部,并且加载完成后标签元素会被自动移除。
细心的你还会发现,这里使用了一种称作条件编译的方法作为表达式(!/*@[email protected]*/0)来判断是否非 IE 浏览器,关于条件编译并不是本文的重点,有兴趣的您可以上网查找相关资料进行学习。

这两个函数的使用方法:

这里我们声明了一个数组变量,里面包含了两个远程的JS文件地址(当然 <script> 标签调用脚本是支持跨域的):

var scripts = [
	"http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js",
	"http://wellstyled.com/files/jquery.debug/jquery.debug.js"
];


这两个文件分别是 jQuery 1.4.2 的库文件和 jQuery Debug 插件
然后你可以使用下面的方法调用并在成功后执行回调了。

seriesLoadScripts(scripts,function(){
   debug = new $.debug({
       posTo : { x:'right', y:'bottom' },
       width: '480px',
       height: '50%',
       itemDivider : '<hr>',
       listDOM : 'all'
   });
   alert('脚本加载完成啦');
});


这里使用的是串联加载的函数,当然你也可以使用并联加载函数,这可以根据情况使用,建议每下一个脚本对上一个脚本有依赖性的使用串联加载,否则使用并联,因为原理上并联要比串联快那么些。

最后鄙视一下看了文章,拿走函数,连评论都没有一个的人。

Pader 2010-7-14 3

换皮

昨晚把 emlog 的一个风格给仿了过来。哇哈哈。

内容模块的评论那块也完成了,终于不再用别人的服务了。。。

博客也改名了,不过这并不代表我就不喜欢《It's my life》了,它仍然是我的最爱。

Pader 2010-6-18 1