Skip navigation.

极湖

无不用其“极”

一些东西搬迁至 GAE

, ,

Google App Engine 是个好东西,可以让你免费创建在线应用。

GAE 默认支持的语言是 Python,后台使用的框架是 django,Python 我不熟悉,正好可以学习学习。

前段时间,我把一个域名 geedigg.com 废了,想想上面的东西丢了也可惜,就把它们搬迁到了 GAE,胡乱取个名字叫“静湖”。这些东西原来都是静态的网页,加了一点JavaScript实现动态显示的功能。这次加了一个留言功能,其实就是把 GAE 提供的例子原样套了进去。

免费的东西难免有限制,GAE也不例外,有一次我上传的文件超过1000个,它就不干了。目前还不知道数据库的存储记录数有没有限制。

最近 GAE 增加了 Java 语言的支持,不过我对 Java 硬是提不起兴趣,所以也没有尝试用 Java 做网站,对于喜欢 Java 的朋友,这应该是个好消息。

JavaScript 查错小帮手: JavaScript Lint

JavaScript 的调试,一般情况下,FireBug 足可应付。可有时候 FireBug 所报的错误太笼统,比如一个括号没有匹配,它不能给出具体的位置,js 文件比较大的时候,查找这样的错误很费功夫。

于是找到了这个 JavaScript Lint ,我用下来的结果,不能说很好,可也是个帮手,有时候实在查不出错误在哪儿,就用它分析一下 js 文件,根据输出的列表(有行号),再去查找错误,有时也可行,能够提高一些效率。

JavaScript Lint 的安装比较简单,看看帮助文件很快就能搞定。安装之后建议把 jsl 的路径追加到用户的 PATH 变量中。

用法:
jsl -conf jsl.conf -process javascript文件名
jsl -process javascript文件名

SQL 关键字 → Zend_Db_Select 函数

,

今天用 Zend_Db 碰上 having 关键字,一开始写在 group() 中,没成功,后来发现有 having() 方法,问题解决了。

顺便总结一下 SQL 关键字与 Zend_Db_Select 函数的对应关系:
FROM → from()
DISTINCT → distinct()
JOIN → join()
LEFT OUTER JOIN → joinLeft()
RIGHT OUTER JOIN → joinRight()
FULL OUTER JOIN → joinFULL()
WHERE → where()、orWhere()
GROUP BY → group()
HAVING → having()
ORDER BY → order()

利用 jQuery 克隆 Object

, ,

在网上搜索关键字 “javascript object clone”,可以找到很多实现克隆 Object 的代码,可是据我测试,让人满意的几乎没有。

今天发现 jQuery 的作者 John Resig 给别人的答复,尝试了一下确实很好用。

方法如下:
// 浅层复制(只复制顶层的非 object 元素)
var newObject = jQuery.extend({}, oldObject);

// 深层复制(一层一层往下复制直到最底层)
var newObject = jQuery.extend(true, {}, oldObject);

测试如下:
var obj1 = {
  'a': 's1',
  'b': [1,2,3,{'a':'s2'}],
  'c': {'a':'s3', 'b': [4,5,6]}
}

var obj2 = $.extend(true, {}, obj1);
obj2.a='s1s1';
obj2.b[0]=100;
obj2.c.b[0]=400;

console.log(obj1);
console.log(obj2);

obj2 内部元素的值改变之后,如果 obj1 的相应值保持不变,就说明复制成功。

ExtJS 也有类似的方法 Ext.apply,因此单独用 ExtJS 应该也能实现同样的功能。

介绍两个处理 flash 文件的 php 模块

, ,

1. SWF Editor for PHP (swfed)
日本人写的扩展模块, 能实现 swf 文件中的图像替换等功能。

下载: http://sourceforge.jp/projects/swfed/downloads/38169/swfed-0.18.tar.gz

安装:
tar -zxvf swfed-0.18.tar.gz
cd swfed-0.18
phpize
./configure
make
cp modules/swfed.so  /usr/local/php5/lib/php/extensions/no-debug-non-zts-20060613/
(注意:以上路径因环境而异)


编辑 php.ini,加入
extension=swfed.so

重新启动 Apache。

2. ffmpeg-php
用于读取视频和音频文件中的信息,能够从视频文件中获取某一帧画面的图片。

首先得安装 ffmpeg
下载: http://ffmpeg.mplayerhq.hu/releases/ffmpeg-0.5.tar.bz2

安装:
tar -jxvf ffmpeg-0.5.tar.bz2
cd ffmpeg-0.5
./configure --enable-shared
make
make install


接下来安装 ffmpeg-php。
下载: http://sourceforge.net/project/downloading.php?group_id=122353&use_mirror=jaist&filename=ffmpeg-php-0.6.0.tbz2

安装:
tar -jxvf ffmpeg-php-0.6.0.tbz2
cd ffmpeg-php-0.6.0
phpize
./configure
make
make install


编辑 php.ini,加入
extension=ffmpeg.so

※补充:
php执行错误:Call to undefined method ffmpeg_frame::toGDImage() 的解决方法:
./configure 执行之后,手动编辑 config.h,加入
#define HAVE_LIBGD20 1
之后再 make clean && make

重新启动 Apache。

Windows 版 gVim 之最佳UTF-8解决方案

,

在 Windows 下安装了 gVim 的官方发行版,按照网上一些方法修改 _vimrc 文件,倒腾来倒腾去,编辑utf-8或其他多字节编码文件的时候,总是有这样那样的问题。

于是找到了这个 vim UTF-8日本語版,作者提供单独的配置文件和完整的Vim压缩包,压缩包下载解压后就能使用,无须安装。经我测试,一打开utf-8文件就正常显示,打开其他编码(Shift-JIS, EUC)的文件,也不用任何其他辅助命令,就能正常显示日文。尝试打开GB2312中文编码的文件,显示乱码,没办法,这是日本人做的,不考虑中文编码的对应也是情理之中。不过,日文中文的处理方法是相通的,编码不同而已,因此我想只要修改一下配置文件,就能解决编辑中文编码(GB2312,GBK等)文件的问题。

下载链接

配置文件(包括dll)压缩包
vim72-cfg.zip

解压后即可使用的压缩包
vim72-aio.zip

提示:解压后把根目录下的 _sample_vimrc 和 _sample_gvimrc 拷贝到当前用户根目录下,并改名为 _vimrc 和 _gvimrc。

几个贴心的 Vim 命令和插件

,

命令
* 向前查找当前光标处的单词
# 向后查找当前光标处的单词
% 查找匹配的括号 {} [] ()
<C-p> 自动补齐(向前查找)
<C-n> 自动补齐(向后查找)
:Ex 文件和目录浏览
gf 打开光标处的文件

插件
matchit.vim
能用 % 查找HTML、PHP中匹配的tags,例如在<tr>输入命令 % 即可查找与之匹配的</tr>。

snipMate
很多人羡慕 OS X 下面的 TextMate,有了这个插件,基本上不用再羡慕了。

The NERD tree
给 Vim 加一个漂亮的树形文件浏览器。

LookupFile
快速查找和打开文件,需要最新版的 genutils

最后补上我比较喜欢的配色方案:
molokai

以上信息整理加工自 LinuxSir.org 的这个帖子

清除Windows系统垃圾的批处理

, ,

偶然在网上发现的批处理脚本,感觉有用且会常用,所以贴一个在这儿。
@echo off
echo 正在清除垃圾文件,请稍等...
del /f /s /q %systemdrive%\*.tmp
del /f /s /q %systemdrive%\*._mp
del /f /s /q %systemdrive%\*.log
del /f /s /q %systemdrive%\*.gid
del /f /s /q %systemdrive%\*.chk
del /f /s /q %systemdrive%\*.old
del /f /s /q %systemdrive%\recycled\*.*
del /f /s /q %windir%\*.bak
del /f /s /q %windir%\prefetch\*.*
rd /s /q %windir%\temp & md %windir%\temp
del /f /q %userprofile%\cookies\*.*
del /f /q %userprofile%\recent\*.*
del /f /s /q "%userprofile%\Local Settings\Temporary Internet Files\*.*"
del /f /s /q "%userprofile%\Local Settings\Temp\*.*"
del /f /s /q "%userprofile%\recent\*.*"
echo 垃圾文件清除完毕!
echo. & pause

没有 SSH 的对策:PHPShell

, ,

闲来没事,更新了一下以前装的 mediawiki,上传新的代码之后,问题产生:数据库等不能通过浏览器更新。

看了一下 mediawiki 的文档,才知道,需要用命令运行 maintenance 目录下的 update.php。

我用的虚拟主机很初级,没有提供 SSH 功能,于是用到了这个叫 PHPShell 的东西。

在服务器上装上 PHPShell 并进行必要的设置之后,在浏览器上就能运行服务器的命令,当然,这只是个简单的模拟,不能和直接用终端相比,不过,能通过浏览器运行命令,目的已经达到了。

ExtJS 控件扩展: 带清空功能的 ComboBox

,

在 ExtJS 官方网的论坛上找到的代码,稍稍改动之后如下:
/*
 * 带清空功能的 ComboBox
*/
Ext.form.ClearableComboBox = Ext.extend(Ext.form.ComboBox, {
    initComponent: function(){
        Ext.form.ClearableComboBox.superclass.initComponent.call(this);
        this.addEvents('clear');
        
        this.triggerConfig = {
            tag:'span',
            cls:'x-form-twin-triggers',
            style:'padding-right:2px',
            cn:[
                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger"},
                {tag: "img", src: Ext.BLANK_IMAGE_URL, cls: "x-form-trigger x-form-clear-trigger"}
            ]
        };
    },

    getTrigger: function(index){
        return this.triggers[index];
    },

    initTrigger: function(){
        var ts = this.trigger.select('.x-form-trigger', true);
        this.wrap.setStyle('overflow', 'hidden');
        var triggerField = this;
        ts.each(function(t, all, index){
            t.hide = function(){
                var w = triggerField.wrap.getWidth();
                this.dom.style.display = 'none';
                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
            };
            t.show = function(){
                var w = triggerField.wrap.getWidth();
                this.dom.style.display = '';
                triggerField.el.setWidth(w-triggerField.trigger.getWidth());
            };
            var triggerIndex = 'Trigger'+(index+1);

            if(this['hide'+triggerIndex]){
                t.dom.style.display = 'none';
            }
            t.on("click", this['on'+triggerIndex+'Click'], this, {preventDefault:true});
            t.addClassOnOver('x-form-trigger-over');
            t.addClassOnClick('x-form-trigger-click');
        }, this);
        this.triggers = ts.elements;
    },

    onTrigger1Click: function() {this.onTriggerClick()},
    onTrigger2Click: function() {this.clearValue(); this.fireEvent('clear', this)}
});

January 2010
S M T W T F S
December 2009February 2010
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30