Opera 刷新页面 创建新 session

奇怪的问题,只发生在 Opera 9.50 版本上。

我把服务端的 session 全部写入数据库,为了方便管理,以便将来有多个前端服务器时可以避免 session 同步的问题。

在各个浏览器测试的时候,发现 Opera 浏览器每次刷新页面,服务端都会创建一个新的 session,只有按 F5 刷新或点击刷新按钮时才会这样,在地址栏按回车就不会。

看浏览器端的 cookie,session_name 对应的值没变,数据库中对应的记录,session 的有效期会相应延长几秒,这对应于每次刷新的时间间隔。

不知道 Opera 为什么会这样。

您目前 UCenter 的程序文件还没有上传

今天升级 Discuz,从 Discuz 6.1升级到 Discuz 7.0。

按照官方的升级文档,先把 UCenter 升级到 1.5,然后才能升级 Discuz。

为了稳妥起见,我把服务器上的程序和数据库都备份到本地,升级一下试试。

果然遇到问题,在升级 Discuz 的时候,运行 upgrade11.php ,结果得到下面的提示:

“您目前 UCenter 的程序文件还没有上传”

后来 Google 了一下,官方有人发帖询问了。

受到启发,可能是 UCenter 的 IP 设置不对。

打开 Discuz 目录下的 config.inc.php,找到 “UC_IP” 的宏定义,把它改成本地 IP:127.0.0.1。

问题解决,成功升级。

顺便说个问题,我在 Google 搜索 “您目前 UCenter 的程序文件还没有上传”,第一条就是结果,显示的是 2 小时前最新抓取的,同样的字符串,在 百度 却没有搜到……

Tags:

vertical-align 各说各话

对vertical-align这个属性,我总是很头疼,一直没有完全理解,好多问题处理起来很麻烦,没有找到统一的方法。

今天看到了一篇blog,比较深入地分析了这个属性,收藏下来!

原文地址:http://www.mikkolee.com/13

转载如下:

最近几天仔细研究了一下vertical-align这个属性,结果让我大吃一惊,这个很“资深”的CSS标准竟然在各个浏览器里面的表现都各不相同。

vertical-align的值有点多,包括 baseline sub supper top text-top bottom text-bottom middle以及各种长度值(%,em,ex等等)。我先给大家看一个我觉得最夸张的值:bottom。代码如下:

p {
    font-size: 18px;
    line-height: 36px;
    font-family: Tahoma, sans-serif;
}
img {
    vertical-align: bottom ;
}

然后大家看一看这段CSS在各个浏览器中的效果(图片是我故意做成那个样子,为了可以看清楚相对位置):

呃,这个结果其实很让人匪夷所思,一般我会认为Firefox会比IE解释得更正确,但是看过Opera之后发现它和IE是一样的,而Safari/Win是站在Firefox那边。说实话,我不知道这是怎么回事。

仔细学习了《CSS权威指南(第二版)》,甚至还去查阅了W3C,然后自己做出一个关于vertical-align的图:

按照W3C的定义,当内联元素的vertical-align设置为:

  • baseline, top, bottom的时候,都是该元素的baseline(或middle, top, bottom)对其周围元素的相同位置,如图片的top和周围文字的top对齐。
  • text-top和text-bottom的时候,是该元素的top(或bottom)对齐周围元素的text-top(或text-bottom)。
  • 长度(%, em, ex)的时候,是基于baseline往上移动,所以正数往上,负数往下。
  • middle的时候,是该元素的中心对齐周围元素的中心。这里“中心”的定义是:图片当然就是height的一半的位置,而文字应该是基于baseline往上移动0.5ex,亦即小写字母“x”的正中心。但是很多浏览器往往把ex这个单位定义为0.5em,以至于其实不一定是x的正中心(以上图为例,x的高度应该是10px,而em是18px,所以两个值不一样)。

但是,即使是按照上面的准则,各个浏览器的解释如此迥异也让我匪夷所思。我也懒得去研究为什么是这样子。总的来说呢,应该就是它们对字体的每一条线的位置的定义都不大一样,所以这个问题不单跟vertical-align有关,而跟浏览器对内联文本和内联图片的结构的解释有很大关系。

最后给大家一个测试页面,可以方面的看看各个浏览器对vertical-align不同值的解释结果。

http://www.mikkolee.com/weblab/001_vertical/

Tags:

IE6 更新 DOM 树 鬼影 GHOST 固定宽度

用JavaScript更新DOM树的节点,先用
element.innerHTML = ”;
把节点内容清空,然后再用
element.appendChild(newNode) ;
插入新节点。

本来操作没什么问题,但是在IE6下,完成 DOM 更新后,附近区域内容的显示会出现问题。

现象是,当光标移动到某些链接上时,部分相邻的内容突然消失!

如果在消失的部分点击一下,那部分内容就恢复正常显示,然后上述问题就彻底消失。

以前写过blog说明这类问题的解决办法,不过那次是因为li元素宽度超过了父层容器。我记得好像是用zoom:1的样式表来处理的,详情请看:IE6 float 异常 消失

这回不是float的问题,是JavaScript造成的。

解决办法用的是给父层容器定义一个绝对宽度,问题解决!

Tags: ,

PHP MySQL localhost 127.0.0.1

今天刚发现一个问题,PHP连接MySQL的时候,不同环境的localhost会有不同的结果。

我的服务器装了2套PHP,其中有一个是用源码编译的,另一个是xampp集成包。

编译的php用于生产环境,xampp用来建立测试环境。

把线上的代码放到测试环境下,居然报告无法连接MySQL!

刚开始以为是端口的问题,可是我在命令行下怎么连接都没问题。最后抱着试试看的想法,把localhost改成了127.0.0.1,这回居然成功了。

我不能理解,线上代码运行的好好的,配置文件就是localhost呀,怎么到测试环境就必须改成127.0.0.1才行?

两套环境,主要的区别就是PHP,虽然版本都一样,不过xampp是编译好的,我估计问题出在这里。

然后立刻写了一个测试程序:

$connA = mysql_connect(‘127.0.0.1:3306’, ‘leakon’, ‘pass’);
$connB = mysql_connect(‘localhost:3306’, ‘leakon’, ‘pass’);
var_dump($connA);
var_dump($connB); 

在命令行下分别用编译和xampp的php执行上述代码,果然发现两项结果不一样。

后来分析了一下,按照这种方式理解:编译PHP的时候需要指定MySQL的安装路径,这个时候localhost就指向对应的MySQL。与编译版的PHP不一样,xampp指向的是随包附带的二进制版MySQL,因此他发现这个MySQL的root密码不对,拒绝连接。

但用127.0.0.1作为主机地址时,PHP就不会按照编译的localhost找MySQL服务器,而是根据端口来找,这回就没问题了。

同时也发现了一个问题,当用localhost:port作为主机地址时,PHP会忽略端口号!

不信你试试上面的代码,那个port写成什么都无所谓,只要是localhost,就会链接特定的MySQL。

不知道为什么,就当经验,记住这个事实吧!

Tags: ,

用CSS实现Tab导航

本文主要讨论的就是导航tab的底部灰线如何用CSS实现,而不是用背景图片实现。用CSS实现的好处是可以避免浏览器发起一次图片请求,另一个是可以方便地改变颜色、尺寸。

做法是用ul和li标签生成tab,在ul的外部用p标签包围,导航底部的那条细线,就是p标签的bottom-border。

过程中遇到的一个难题是,高亮的tab,是白色背景,该tab底部没有border,应该也是白色的。但用普通的方法没法做到,如上面第2个图,“首页”那个tab的出现了底部border。因为p标签是ul和li的外层容器,内部的所有元素默认都在p标签的范围内,无法跨越p的边界。

通常这种导航的底部实现都是用背景图片代替,这样的理由是:1、背景图片的位置可调,可以不用紧紧挨着边框,比如离bottom有4px的距离;2、背景图片显示在最低层,p容器内的任何元素都可以覆盖住背景图片。高亮tab的底部没有border的效果就是靠白色背景挡住了p的背景图片做到的。

基于这种思想,我考虑可以用什么方式让内部元素挡住外层元素呢?

ul元素的position属性设置为absolute,p标签的position设置为relative。这样ul就定义在p标签内浮动,默认top和left都是0,即p的左上角。同时,ul会覆盖住p。只要p的height刚好比ul的height小1px就可以,也就是让ul中li的bottom-border刚好和p的bottom-border在同一个垂直高度上。注意,p标签的overflow属性必须是visible(默认值),也就是说只要你不把overflow设置成其他值就没问题。

经过上面的步骤,可以总结出几个关键点,按重要顺序排列:

  1. ul和p的position属性,分别是absolute和relative(这里告诉你为什么这样设置
  2. p的高度应该比ul小1px(根据你的需要,小几个px都可以)
  3. overflow属性必须使用visible

通过这几个关键点,你就可以基本实现图1的效果,不过还要针对不同浏览器做小小的css hack。

hack的关键点就是p的height值,在我这里,Firefox2/3、Chrome、Opera适合27px,IE7、Safari适合26px,IE6适合25px。

现在我唯一的问题是不知道怎么写出专门适用于Safari的CSS定义,所以在Safari下是图3的效果,其实就差1px,回头找到方法再补充吧。

Tags: , , , , ,

我的互联网每周点评 2008-11-22

百度公关

因为没给某个电视台交保护费,就遭到连续2天的恶意报道,说百度为了利益而改变搜索引擎的排序结果,误导网民,甚至还说什么会影响互联网产业。不管说的对不对,我看那个电视台想说的意思是:百度收了钱才办事儿,不给钱不仅不办事儿,甚至给你屏蔽了。那么我反过来看看那个电视台的行为:给了广告费就帮你忽悠,不给广告费,不仅不给你忽悠,还给你栽赃陷害。如果说百度会影响互联网产业,不知道那个电视台会影响什么?我估计会影响中国的持续发展。不如把这个电视台新盖的楼送给百度,呵呵……

Gmail 主题

Gmail 可真是个好东西,我现在真不敢想象,如果没有 Gmail,我的生活将会受到什么样的影响。现在可以换主题了,我觉得可以吸引很多普通用户,让他们从其他邮箱转移到 Gmail。不要小看换皮肤这个功能。如果你是一个实用主义者,似乎对这类功能不感兴趣。确实,Gmail 最开始是以实用为主的,面向的也都是有经验的互联网用户。当 Google 满足了这部分高端用户的需要后,就开始向更大范围的普通用户下手。看看百度空间,提供了用户自定义CSS的功能。再看看有多少用户创建的模板,数以万计。有人说百度空间有点娱乐型的感觉,比较适合普通用户,尤其是年龄较低的用户。也许 Gmail 的这次开发主题选择,也是为了这部分用户吧。

用户研究

最近又讨论到用户,又说起创业公司的第一步应该怎么走。当我们几个人坐下来讨论,各自为了证明自己观点的正确性而引经据典时,突然发现,这些前人总结的真理,都是正确的。说起如何选择方向的时候,我提出了一个观点,就是创业的初期应该是2条路:1、创业者选定一条自己最擅长的领域或方向,在这个领域潜心钻研,深入探索,然后做一些针对性和目的性很强的用户调研,来为自己设定的目标提供修正或参考;2、创业者有一个“万能”的团队,就想 Jeff 引用的一句话 “创业成功的三要素:Team、Team、Team!”,不管他们选择什么方向,有这个 Team 就保证了成功,至于方向,可以从用户调研中选择一个可行性最高的。

讨论方式

我们在吃饭的时候总会有很多讨论,最有意思的是,本来很激烈的辩论,到最后,突然发现彼此的观点是一致的,呵呵,都不知道之前在争论什么。昨天总结一个方法:在讨论问题时,不要说“对与不对”或“正确与否”,只叙述自己的观点,力求让对方完全理解你自己的本意。其实大家好多的分歧都存在于没有理解彼此的本意,或者说理解不够完全。这也导致会议总是没有休止。

做事深潜

在尝试性地开发一个新功能的时候,应该把这个功能做到尽善尽美,然后再去尝试另一个功能。这里不是说孤注一掷地死死盯住一个方向。我的意思是即便这个功能只能帮助用户完成一件事,那也应该把这一件事彻底解决好,不要有遗留的bug,不要有用户体验上的不友好。功能可以简单,可已单一,但绝不可以不能用、不好用、不易用。本来尝试着开发这个功能就是为了从用户那里得到反馈,让用户帮忙,从用户那里挖掘出更深层次的需求。如果只是浅尝辄止,那从用户那里得到的信息就没有什么实际的意义和价值了。这个时候急于投入下一个功能的开发,等于又是一次轮回。当你浅浅地尝试过N种选择后,得到的结论很可能就是这N种功能都没有用,没有用户喜欢。

我始终坚持我的看法:没有冷门的领域,没有冷门的方向,没有冷门的功能,只有不够深入、没有创新意识的设计者。

如果长时间地专注在某个你比较擅长的方向上,你对这个领域的感悟和理解就会比别人深得多,你能挖掘出来的用户需求也会比别人多得多。就像中国的一句古话:样样稀松不如一门精通。

 

期待下周……

Tags: , ,

SSH 信任 无密码 无口令 登录 ssh-keygen

做 rsync 远程同步文件的时候,总要输入密码,没法做自动运行。查 rsync 的使用方式,用 –password-file=/home/leakon/secret/rsync.pass 这个参数也还是不行,有人说改文件权限为 600,有人说文件里面只写密码,不要写成 user:pass 的格式。反正怎么试都是不行。

只能寻求建立 SSH 信任关系跳过密码的方式来同步文件了。

本来以前查资料,搞定过用 SecureCRT 不要密码登录 FreeBSD 的,详情见:http://www.leakon.com/archives/55

但到了服务器之间,我还没成功过。

查了好多资料,让人难以理解的表达能力和我自己笨到不行的理解能力,实在看不太明白。

现在我还是说清楚一点吧,我的目标是,在 home 服务器 ssh 远程登录 office 服务器时不必输入密码(帐户名都是 leakon)。

那么,我要在 home 服务器上用 ssh-keygen 生成密钥,rsa 或 dsa:

leakon@home shell> ssh-keygen -t rsa

一路回车,会在 ~/.ssh/下生成 id_rsa 和 id_rsa.pub ,分别是私钥和公钥。

然后,要把 id_rsa.pub 的内容追加到 office 服务器 ~/.ssh/authorized_keys 的尾部:

leakon@home shell> scp ~/.ssh/id_rsa.pub leakon@office:~/leakon_random_rsa.pub

这里改名公钥文件是为了避免覆盖 office 端的同名文件。

登录 office 服务器,把新的公钥文件加入到授权文件中:

leakon@office shell> cat ~/leakon_random_rsa.pub >> ~/.ssh/authorized_keys

注意,请检查这个 authorized_keys 的权限,应该是 600,如果之前不存在,那么创建文件默认的权限是 644,这样是不行的,很多情况下加完授权文件后登录还需要密码,就是因为这里权限不对。

注意,公钥文件添加到了 office ,私钥文件也应该添加到 home 的身份文件中。实际上,只要 id_rsa 这个文件存在于 home 的 ~/.ssh/ 下就没问题,但容易被不小心覆盖,所以应该添加到 ~/.ssh/identity 中,这是与 office 端的 authorized_keys 对应的私钥文件:

leakon@home shell> cat ~/.ssh/id_rsa >> ~/.ssh/identity

注意文件权限也应是 600。

通常这个时候就搞定了,在 home 登录 office 不需要输入密码了。

如果还是不行,下述方法可能有帮助:

  1. 检查 /etc/ssh/sshd_config 中 AuthorizedKeysFile .ssh/authorized_keys 文件位置
  2. 把 /etc/ssh/sshd_config 文件中的 RSAAuthentication yes 打开
  3. home 端的 ssh 可能编译没有完全成功,有先例:home 时钟不对,编译不完全,更正时钟,再编译,完成后可解决问题
  4. 清除 home ~/.ssh/known_hosts 
  5. home 和 office 的用户名应该相同

Tags: ,

Javascript Event 事件 特性 总结

简要提纲

  1. addEventListener,the 3rd parameter,true: parent to child,false: child to parent
  2. onMouseOver/Out,与 child 节点交互时,先 Out 再 Over
  3. style.display=none 的 Element,在某些情况下用 document.getElementById() 获取不到

Part 1

在支持 DOM2 事件模型的浏览器上,给元素绑定事件要用 addEventListener 这个方法,他有第 3 个参数:capturePhase。手册上的说明没太看懂,就自己做了个测试(在 http://leakon.googlecode.com/svn/trunk/leakon/javascript/event_phase 可以看到代码),明白了 true 与 false 的区别:当已注册的事件在某个节点上发生时,会按照某个顺序传递下去。true 指定由根节点向叶子节点传递,false 指定由叶子节点向根节点传递。

举个例子,有个 div,内部有个 img,2 个元素都注册了 onclick 事件,分别调用不同的处理函数。当你在图片上点击鼠标时,div 和 img 哪个先触发,就靠这个 capturePhase 来决定。div 是 img 的 parent,如果设置为 true,就是 div 先触发,然后才是 img。

不过一般来说都是设置为 false,即由叶子向根传递,因为 IE 就是这样做的,而且貌似不能改变顺序。

 

Part 2

还是父子节点事件处理的问题,这回讨论 onMouseOver 和 onMouseOut 事件。借用上面的例子,div 内部是 img。我们只给 div 注册一对 onMouseOver/Out ,当光标从 div 部分(这里假设 div 很大,而 img 只占 div 较少一部分面积)经过 img 的边框进入 img 面积内时,会先后触发 div 的 2 个事件:onMouseOut -> onMouseOver。也就是,div 认为鼠标是先离开 div 然后又立刻进入。

换到一个实际的应用场景,比如我们添加 Over 和 Out 事件就是为了给 div 添加一个高亮的样式表,div 背景默认是白色,鼠标划过变成红色,出去后恢复成白色。

要是你在 Over 和 Out 处理函数内部仅仅是 addClass 和 removeClass 这么一下,那你会看到跳动的感觉,也就是鼠标按如下路线行进:inDiv -> inImg -> OutOfImg -> inDiv ,别看鼠标一直在 div 内部,你以为不会有 onMouseOut 事件,事实不是这样,光标进入 img 的那一瞬间,就先后执行了  Out 和 Over 函数。而且,有些情况下,后续的 Over 函数没能得到成功执行,现实是 div 的样式表移除后就没能再添加上。

 

Part 3

这个问题大家应该早就知道,只是我今天才发现。我以为 document.getElementById() 跟 DOM 节点当前的样式无关。今天给一个 Element 注册事件的时候发现找不到该节点,原因是那个节点的 display 样式设置为 none。

按说不应该是这样,可能跟当时运行的环境有关,也可能是我绑定事件的函数有问题,总之看到的现象是跟样式定义有关。总结在这里,以备日后回忆,参考。

 

我现在觉得 Javascript 最难的就是事件处理这部分了。这里的事件不是简单地给某个 div 绑定一个函数来响应鼠标点击,而是一整套的处理流程和逻辑。

事件发生源、事件类型、传递方向、再哪个节点上应该停止传递,等等。

当页面中元素很多,关系错综复杂时,就需要一个事件处理框架来帮忙。我们需要的是结构清晰逻辑合理的代码,而不是满篇重复地 if else 判断。

举个简单的例子,如果你做一个邮件系统,类似 Gmail 那样的,你每点一封未读邮件,或者给某些邮件加上 tag,都会触发一系列的关联事件,例如要把未读邮件总数减少,给 tag 列表里添加新项目,同时用突出的颜色高亮选中的邮件标题,还要在页面顶部给出处理成功的提示,甚至还要问用户是否要撤销刚才的一系列动作。

天啊,看这 2 行文字描述我就觉得很晕了,把他用代码实现出来,并处理各种异常,还要保证代码的可读性,我只能说我自己能力还差得太远太远。

前两天听说 MooTools 这个 Javascript 框架在面向对象方面做的不错,当项目越来越复杂时,按照 MooTools 方式来组织代码可以有很好的可维护性。

找到了电子书,已经放到 blog 中可以下载了。

Tags: ,