手机浏览 RSS 2.0 订阅 膘叔的简单人生 , 腾讯云RDS购买 | 超便宜的Vultr , 注册 | 登陆
浏览模式: 标准 | 列表全部文章

EditPlus的一些其他技巧

昨天我转载了别人的一篇editpllus的技巧,现在我也将我常用的一些技巧放出来,算是和大家共享吧。
1、选中一列内容

选中一列内容在从excel等其他文件格式导成Txt的时候特别有用,比如我们不要当中某列数据的时候,确实有点痛苦,如果有规律,我们还能写正则进行替换,如果没有规则怎么办?
1.先关闭自动换行(菜单栏上有一个W,或者按快捷键ctrl+shift+w)
2.按住 alt键,用鼠标进行选择,你就会发现你选择的内容是屏幕中的某一块区域,而不是平时那种按照行来进行选择的了

2、autocomplete
对于我们写PHP代码的人来说,自动完成这个功能,很重要,有的变量经常用,但是打起来很繁,比如:$_POST;$_GET;$_REQUEST等,象这些变量,在写的时候要按着shift键才有用,如果经常写,我当然是希望有快捷的方式了。
1.点击菜单Tools->Preferences然后选中Files->setting&syntax,选择PHP
2.下面有两个选择的地方哦:setting&syntax和auto completion,这两个,一个是语法文件,一个是自动完成文件,有了这两个文件,你的代码就会被自动着色,函数和class等的着色就会和平常不一样,syntax文件官方有下载,但autocomplteion官方就没有了,不过你可以自己写,我就是自己写的。

格式如下:
#TITLE=PHP
#CASE=y

#T=h_401
header( 'HTTP/1.0 401 Unauthorized' );
exit();
#T=h_404
header( 'HTTP/1.0 404 Not Found' );
exit();

#T代表了你要输入的字符,下面的内容就是你输完后,在屏幕上输出的内容
比如,我输入h_401,在我按空格后,屏幕上就会立即跳出:

header( 'HTTP/1.0 401 Unauthorized' );
exit();

多方便呀。

顺便透露一下,htmlbar.acp其实就是一些快捷键的自定义哦,你也可以通过修改这个文件,达到对菜单的自定义。

3、页面函数显示
editplus太轻量级了,没有办法象IDE那样在打开某个文件后还能显示文件中的class和function,但也有一个简单的替代方法,那就是快捷键:ctrl+F11,你就可以快速查看页面中的function了,好象。。。。对public function aaa()这样的无效。这样的话也就是说PHP5文件中的function是看不到的。唉。没办法了。。。

先介绍这一点。功能有太多。慢慢来喽

Tags: software, editplus, 技巧

PHP负载均衡

文章的内容写的不错,所以转载一下。
原文:http://xinsync.xju.edu.cn/index.php/archives/2946
内容如下:

XML/HTML代码
  1. 过去当运行一个大的web应用时候意味着运行一个大型的web服务器。因为你的应用吸引了大量的用户,你将不得不在你的服务器里增加更多的内存和处理器。  
  2.   
  3. 今天,’大型服务器’模式已经过去,取而代之的是大量的小服务器,使用各种各样的负载均衡技术。这是一种更可行的方法,将使硬件成本降至最低。  
  4.   
  5. ‘更多小服务器’的优势超过过去的’大型服务器’模式体现在两个方面:  
  6.   
  7.    1. 如果服务器宕机,那么负载均衡系统将停止请求到宕机的服务器,转而分发负载到其他正常运行的服务器上。  
  8.    2. 扩展你的服务器更加容易。你要做的仅仅是加入新的服务器到负载均衡系统。不需要中断你的应用运行。  
  9.   
  10. 所以,把握住这个机会:). 当然,代价就是这要求你的应用开发时增加一点复杂度。这就是本文要覆盖的内容。  
  11.   
  12. 这时你可能对自己说: ‘但是我怎么知道我正在使用负载均衡呢?’。最诚实的回答是,如果你正在问这个问题,那么答案是你多半没有在使用负载均衡系统并且你的系统不需要考虑这个问题。大多数情况,当应用成长足够大的规模时,负载均衡就需要明确提出和设置了。然而,我也偶尔看见虚拟主机公司为客户的应用做这个负载均衡,或者像下面描述的那样要自己来做。  
  13.   
  14. 在继续下面的内容之前,我要指出本文主要描述PHP的负载均衡。将来我可能会写有关数据负载均衡的文字,但是现在你必须等待。  
  15.   
  16. 注意,我一直提“web应用”而不是website,这是想区分’web应用’是那些复杂的站点往往涉及服务器端编程和数据库,而不是website那样只显示简单的静态内容。  
  17. 1. PHP文件  
  18.   
  19. 第一个问题是,如果你有大量的小型服务器,你怎么把你的php文件上传到所有的服务器上?有如下的方法供你参考:  
  20.   
  21.    1. 分别上传所有的文件到每一个服务器 , 这种方法带来的问题是:想像一下你有20个服务器,那么上传过程中这将很容易导致错误,并且更新时极有可能导致不同服务器上有不同版本的文件。  
  22.    2. 使用 ‘rsync ‘ (或类似的软件) . 这样的工具能同步本地目录和多个远程主机目录上的文件。  
  23.    3. 使用版本控制软件(如subversion ) . 这是我最喜欢的方法。用它可以很好地维护我得代码,当发布我的应用时,可以在每一个服务器上运行svn update命令同步。这种方法也使切换服务器得代码到过去的某一个版本更加容易。  
  24.    4. 使用一个文件服务器(你可能发现NFS 非常适合做这件事情). 这种方式是使用一个文件服务器来存放你的web应用. 当然,如果你的文件服务器宕机,那么多所有你的站点将不能使用。这时,你就需要花费更多的开支来恢复它。  
  25.   
  26. 选择哪种方式依赖于你的需求和你掌握的技能。如果你使用版本控制系统,那么你可能得计划一个方法如果同时执行一个更新命令更新所有服务器上的代码。然而,如果使用文件服务器,你就要实现一些失败恢复机制,防止万一服务器宕机导致请求失败。  
  27. 2. 文件上传  
  28.   
  29. 当只有一台服务器时,文件上传不是一个问题。但是当我们有多台服务器时,那么上传的文件应该怎么存放呢?上传文件的问题和跨服务器php文件存储是类似的。下面是几种可能的方案:  
  30.   
  31.    1. 把文件存储到数据库中 。大多数数据允许存储二进制数据。当你请求文件下载时,访问数据把二进制数据和相应的文件名和类型输出给用户。在使用这种方案前应该考虑数据库怎样存储你的文件。该方法的问题在于如果数据库服务器宕机将使文件不可用。  
  32.    2. 在一个文件服务器上存储上传的文件 . 与前面的介绍一样,你要安装一个文件服务器让所有web服务器共享,把所有上传的文件上传到这里,上传后所有的web服务器就都可以使用它。但是,如果文件服务器宕机,那么可能发生图像文件下载中断。  
  33.    3. 设计你自己的上传机制传输文件到服务器到每一个服务器 . 这个方法没有单个文件服务器或者数据库方案的缺陷,但是将增加你代码的复杂度。例如,如果上传到多个服务器过程中,服务器宕机,你要怎么处理?  
  34.   
  35. 用数据库存储上传文件但是设计一个文件缓存机制是一个不错的方案。当服务器接收一个文件下载请求时,首先检查缓存系统中是否有该文件,如果发现那么从缓存系统下载,否则从数据库读取并把它缓存到文件系统中。  
  36. 3. 会话(Sessions)  
  37.   
  38. 如果你熟悉php的session处理,你将可能知道默认情况下,它存储session数据在服务器的临时文件里。而且,这个文件仅仅在你请求处理的那个服务器上,但是接下来的请求可能被另外一个服务器处理,这将在另一个服务器上生成新的session。这导致session频繁地不被识别,如登录用户总是要求重新登录。  
  39.   
  40. 我推荐的方案是,要么重新php内建的session处理机制存储session数据到数据库,或者实现你自己的机制保证发送一个用户的请求到同一台服务器。  
  41. 4. 配置(Configuration)  
  42.   
  43. 尽管这个话题不是和php特别相关,我感觉还是有必要提及。当运行集群服务器时,用某种方法保持服务器之间的配置文件同步是一个好主意。如果配置文件不一致,可能导致一些非常奇怪的断断续续的行为导致很难排查这些问题。  
  44.   
  45. 我推荐使用版本控制系统单独管理他们。这样你可以为不同的项目安装存储不同的php配置文件,也可以保持所有服务器配置文件同步。  
  46. 5. 日志(Logging)  
  47.   
  48. 像配置问题一样,logging不是仅仅和php相关。但是对于保持服务器健康运行它仍然是非常重要的。没有正确的logging系统,你怎么知道如果PHP代码开始产生错误(在系统正式运行时,你总是关闭display_errors 设置,不是吗?)  
  49.   
  50. 有几种方法你可以实现logging:  
  51.   
  52.    1. 在每一个服务器上记录日志。 这是最简单的方法。每一个机器仅仅记录一个文件。好处是简单,可能只要很少的配置。但是,随着服务器数量的增多,监控每台服务器上的日志文件将变得非常困难。  
  53.    2. 记录日志到一个共享 这种方法每一个服务器仍然有这个日志文件,但是他们通过共享机制被存储在一个中央文件服务器上,这将使监控日志变得更简单。该方案的问题在于,如果文件服务器不可用将导致一个简单的日志不能写入问题最终导致整个应用崩溃。  
  54.    3. 记录日志到logging服务器 你可以使用一个logging软件,如syslog 来把所有的日志写到一个中央服务器。尽管这个方法要求更多的配置,但是他也提供了最健壮的方案。  

SVN的机制确实是很多人现在所考虑的,一来这样保证了代码的同步,二来也不需要担心开发版和上线版的区别,更重要的是,每次的update你肯定不会有错。

文件上传其实才是一个大头,当你的服务器过多的时候,你如何保证每一台服务器的上传内容同步?如果你同步了,那么这么多的冗余文件是否是一个浪费?如果你不同步,而采用同一个NFS服务器来存储,那么就象文中说的如果NFS宕机了怎么办?给NFS也来一个负载均衡?

总之,当服务器越来越多的时候,你考虑的就不仅仅是代码的问题,而是架构的问题

Tags: php, server, 负载均衡, 配置

新闻一则:雨林木风工作室宣布解散

内容来自cnbeta,未作删减。原文网址:http://www.cnbeta.com/articles/73351.htm

内容如下:

据中国站长站报道,国内知名操作系统DIY商雨林木风宣布解散,雨林木风工作室负责人罗先生表示消息属实,并发来正式声明.
罗先生表示,雨林木风工作室选择此举也属无奈,随着国内版权意识的加强、以及早些时候的番茄花园事件.雨林木风的关闭也属大势所趋.而随着雨林木风的关 闭,雨林木风所提供的系统也将成为历史.所有版本仅供爱好者收集纪念,禁止非法用途及传播.而关于雨林木风工作室解散以后的动向问题,罗先生并未回应.

以下为声明全文:

亲爱的会员朋友们:

基于多方面的原因,我们不得不很遗憾地告诉大家,经过雨林木风工作室管理层慎重考虑,决定于2008年12月31日起正式解散.今后,雨林木风将以自主研 发软件产品为主,继续为网民提供服务(不再进行未开源操作系统技术研究),所有成员与工作室脱离一切隶属关系,而雨林木风论坛将继续独立运营,不受本工作 室解散之影响.

为了铭记这些曾经为我们提供了精品资源的技术精英们,同时,也为众多的论坛会员留下一份美好的回忆,我们特别奉献一套经典收藏版[包括:雨林木风 Ghost XP SP3 装机版 YN9.9;雨林木风 Ghost XP SP3 纯净版 YN6.0;雨林木风 WinXP SP3 安装版 YS8.0;雨林木风 Windows Vista ULTIMATE With SP1 精简版V2.1]以供大家收藏留念,禁止非法用途及传播.

历经三载,我们风雨同行,一路走来,雨林木风工作室由衷地感谢各界朋友们对我们的支持与厚爱!雨林木风工作室也将成为一段历史!再次感谢3年来一直支持着本工作室作品的雨林木风迷们!希望大家能继续支持雨林木风旗下软件部门推出的其他软件产品.

特此声明!
雨林木风工作室
二〇〇八年十二月二十六日

Tags: 新闻, 解散, 雨林木风

让Editplus自动格式化css和js

对于我们使用PHP进行网页开发的人员来说,EditPlus应该是我们的常用工具了吧。emeditor我是用不顺手的,UltraEdit的着色也是我不喜欢的(或许是因为我用EP的时间太长了吧)。

经常用啊用,也会有一些技巧的积累,不过今天我是看到了别人的技巧,先贴上来(主要是看上他那个工具了,呵呵)

原文网址:http://www.cnblogs.com/darkangle/archive/2008/12/25/editplus_auto_format_js_css.html

作者是:沙加

原文内容:

受阿一同学的启发俺也来发个小东西.

虽然很喜欢editplus的小巧快速,但是很遗憾它不支持代码的自动格式化,现在写php,css,html都是用的Aptana,这个感觉不错。

今天正好看了一下editplus 的用户工具,它允许通过命令行调用和标准输出输出与其它程序进行交互,可以传入参数可以手动指定,也可以是当前选定内容,当前本件所有文本等,即然这样我 们就利用它的filter模式,即把所有文本内容传过去,再使用回传内容替换当前文本。那么我们还需要一个外部工具,为了方便起见,脚本类语言当然是首 选,而在windows平台下面可以使用vbs和JScript, 那么就用JScript吧,去网上找一个 http://github.com/einars/js-beautify/tree/master 的东西,它提供在线的js格式化功能,正好是js写的, 拿它回来稍做改造一下,使用WScript的Std接口接收和发送内容
var input = "";
while(!WScript.StdIn.AtEndOfStream)
{
   input += WScript.StdIn.ReadAll();
}
从输入端读入数据.
WScript.Echo(formated_code); 发送数据.
那么js的格式化就搞定了, 再来看看css的,很怀念VS里面可以将一个CSS定义都放到一行上面去,这样看起来比较方便,否则代码太长了要拖半天.  这样的话看起来也不是太难, 就自己动手写一个了. 两个文件我已经打包. 下载完可以解压到任意目录,接着就配置Editplus.

打开Tools->ConfigUserTools, 工具名称可以随意,比如jsFormatter, 在Command处写上 Cscript.exe /nologo  e:\jsFormatter.js  后面的路径就是js的引用路径,  并钩选下面的run as text fileter,让它作为文本过滤器使用,OK,现在打开一个待格式化的js 文件,  按下Ctrl+1(默认的第一个用户工具快捷键), 可以看到文本已经格式化好了,  不过等等,  上面怎么有MS的版权申明? 看来这个CScript也不是白用滴;( ,  不过没关系,俺们还是有办法,按下Ctrl+Q, 存到Alt+1里面, 开始录制动作,  依次按下Ctrl+Home 回到文档开始处,Alt+Shift+Del 三次, 删除三行Ctrl+Q退出记录,这样就完成了, 以后在格式化之后播放一次这个键盘操作记录就行了.  感谢 键客 提醒.


后记:
     要是可以格式化html和php那就更好了, js-beautify 里面也可格式化html,可惜效果不太好,我就没放进去,要是能有Aptana编辑器那么出色的效果就好了, 它可以完美处理js脚本, css, html的混合格式化,  想了一下似乎可以建一个java的控制台程序引用Aptana的插件 jar 包就能实现, 通过ICodeFormatter可以完成对各种类型代码的格式化,  留待以后研究.

    不会造工具的猩猩永远是猩猩,会自己制造工具的程序员可以有效提高自己的生产力,windows下面的VBScript, JScript和Python, Perl 等脚本语言都是很好的助手. 在这个应用中先查看Editplus帮助,再搜索MSDN脚本技术参考,顺便复习一下正则表达式应用,  既能解决问题又能提高技能水平,  希望大家都 行动起来自己动手DIY, good luck!

两个文件见附件: darkangle_js_css_Formatter.rar


我自己以使用 PHP beautiful 插件比较多,但JS写的也不少,所以,看到这个工具,我感觉确实有用,所以复制下来了。

本站备份:darkangle_js_css_formatter.rar


Tags: editplus, software, 技巧

[转载]一步一步学习Firefox扩展的开发[据说这将是一个系列]

Firefox的插件也曾经研究过,对于XUL感觉也有点痛苦,当初想研究它是为了给自己的博客增加插件,可以方便的让自己在找到好的资料的时候,可以直接通过插件发送到博客上。但最终我还是放弃了。没有什么理由。。。。

看到有人在贴一步一步学习的教程,又有点拾起了回忆,如果有可能,这个系列,我会在这个作者写的同时,也一点点的转载。
希望作者不要见怪,转载完了,我也贴点我在开发的时候遇到的问题之类。当然一切都到元旦后。。。
原文网址:http://www.cnblogs.com/uubox/archive/2008/12/25/1361278.html
作者:DOMS
内容:Firefox提供开放、强大且灵活的扩展机制,因此衍生出了大量功能丰富的扩展组件,这些扩展组件甚至可以说是某些用户爱上firefox的主要因素。
比较可惜的是firefox扩展开发的中文资料相对比较少,因此在这里我会从简单到深入介绍开发firefox扩展的一些技术及常遇到的问题。

本文主要内容:

  • 制作一个包含工具栏按钮及右键菜单的简单组件
  • 解决扩展安装后工具栏按钮却不显示的问题


因为这个组件不需要设计交互窗口,因此开发过程相对简单,下面是这个组件运行的效果图:
firefox_addons_demo1_view.jpg

在开始之前先介绍一下几个网址:

  1. https://developer.mozilla.org/en/Extensions 官方开发网,类似MSDN,是开发时的主要参考资料;
  2. https://developer.mozilla.org/en/Building_an_Extension,官方的一个基础教程,笔者通过此篇文章而入门;
  3. http://ted.mielczarek.org/code/mozilla/extensionwiz/,一个在线的创建扩展的向导,如果你想立即创建一个属于自己的扩展,可以试试用这个向导制作一个雏形,然后再自己慢慢添砖添瓦。本文所讲的例子也是用这个向导制作出来的。

另外还有本文例子的源代码:http://www.uushare.com/user/csprogram/file/1139797

好了,下面就开始讲解本文的示例组件:uusharedemo1的制作过程。

1、了解扩展组件的构成

Firefox 扩展组件是以一个xpi文件的形式发布的,而xpi文件实际上是zip压缩包文件,我们只要把Firefox扩展组件下载回来(用右键另存为即可下载), 把文件扩展名改为zip即可解压并看到所有的源代码,有时可能还会在压缩包里面看到jar格式文件,这个也是zip压缩包,改名解压即可看到源代码。因此 多下载优秀的扩展回来慢慢研究其源代码也不失为一种快速的学习方法。
一般xpi文件内部有(但不一定都有)如下目录及文件:
xpi_filetree.png
其中 uusharedemo1 为本文示例组件的名称,可以看到压缩包首层有:install.rdf及chrome.manifest两个文件以及一个chrome目录。

  • install.rdf:是该组件的安装信息,例如组件的名称、版本、作者等信息,XML格式;
  • chrome.manifest:是用于描述该组件由哪些文件组成的,即一个资源列表;


在chrome目录里就是该组件的主要内容了,一般有:content、defaults、locale、skin等目录,它们的作用如下:

  • content:这个是最主要的目录,包含组件的界面定义以及程序代码,其中xul文件是界面定义文件,类似SilverLight的XAML文件,同样是XML格式;js文件是组件功能实现的代码,全部用javascript实现的。
  • skin:存放css样式表文件及资源位图,css是用来控制组件界面外观的。
  • locale:如果想让组件能够在不同语言的firefox里显示正确的文本,则将不用的语言列表放到此目录,firefox会自动加载合适的语言文件。这点有些类似Win32PE可执行程序中的资源文件。
  • defaults:存放一些默认值,一般不要此目录也可以;


我 们可以把Firefox程序认为是一个平台,而我们看到firefox浏览器外观本身也是用跟扩展组件类似的结构搭建起来的,感兴趣的朋友可以解压 “C:\Program Files\Mozilla Firefox\chrome”目录下的jar文件观摩一下firefox浏览器外观的源代码,所以我们制作的扩展组件也会成为firefox浏览器自身 的一部分,可以实现非常强大而灵活的功能(例如Firebug这个神奇的组件)。相对来说,开发ie扩展程序显得困难多了,除非只是想做工具栏按钮和右键 菜单(用注册表即搞定),否则需要使用VC,VB,Delphi这些工具开发COM组件才能完成。

如果想了解firefox浏览器本身各个元素的定义,但又不想阅读chrome目录下的脚本代码,可以安装 DOM Inspector 这个组件,这个组件有如开发web时的FireBug,是开发具有界面的扩展组件时的神兵利器!

提醒:自己编写的组件代码文件最好用“UTF-8”格式保存,一般可以减少很多麻烦的问题。

2、认识install.rdf

install.rdf包含组件安装信息,本文例子中它的内容如下:

XML/HTML代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"   
  3.  xmlns:em="http://www.mozilla.org/2004/em-rdf#">  
  4.   <Description about="urn:mozilla:install-manifest">  
  5.     <em:id>uusharedemo1@uushare.com</em:id>  
  6.     <em:name>Uushare书签(示例)</em:name>  
  7.     <em:version>1.0</em:version>  
  8.     <em:creator>KwanhongYoung</em:creator>  
  9.     <em:description>这是一个模仿Uushare书签插件的示例</em:description>  
  10.     <em:homepageURL>http://www.uushare.com</em:homepageURL>  
  11.     <em:iconURL>chrome://uusharedemo1/content/uusharedemo1.png</em:iconURL>  
  12.     <em:targetApplication>  
  13.       <Description>  
  14.         <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- firefox -->  
  15.         <em:minVersion>1.5</em:minVersion>  
  16.         <em:maxVersion>3.0.*</em:maxVersion>  
  17.       </Description>  
  18.     </em:targetApplication>  
  19.   </Description>  
  20. </RDF>  



文件里有很多是固定的写法,这里就不一一讲解了。
第 5行的id是组件的一个标识符号,类似Windows里COM组件的CLSID,用于区别其他组件。可以使用 xxx@yyy.zzz 这样类似email地址的格式组成,而这个“email地址”不要求是真实或有效的。也可以用的GUID来标识,例如“{c45c406e- ab73-11d8-be73-000a95be3b12}”是WebDevelop组件的标识符。

name、version、creator、description、homepageURL分别是组件的名称、版本、创建者的姓名、组件描述、组件官方网站地址。
iconURL用于显示组件的图标,格式一般用32x32pixel的png图片。
这里出现了chrome://这样的地址,跟http://和file://协议类似,chrome://也是用来定位资源的。格式是:
chrome://组件名称/目录路径/文件名
需要注意的是,这里的组件名称可以跟em:name属性中所指定的名称(用于显示的)不一样的,并且这个组件名称需要在chrome.manifest里定义。
这些信息在安装完组件之后能够在firefox的组件管理列表显示,如下图:

firefox_addons_demo1_item.jpg

第14行比较重要,用于标识当前组件是用于哪个平台的(firefox/Thunderbird/SeaMonkey等),如果开发的组件是给firefox用的,则id={ec8030f7-c20a-464f-9b0e-13a3a9e97384}。
第 15、16行用于指定当前组件适用于firefox的哪些版本,因为firefox从1.5到3.0有些地方有所改变,所以如果你不知道自己的组件在哪些 版本下可运行的话,最好先测试一下,然后准确地指定一个范围值,上例的值表示该组件适用于firefox1.5到3.0及3.0所有修订版。版本号码不能 自己随便造,这里有一个完整的列表:
https://addons.mozilla.org/en-US/firefox/pages/appversions

3、认识chrome.manifest

这是资源列表文件,内容如下:

XML/HTML代码
  1. content    uusharedemo1    chrome/content/  
  2. locale    uusharedemo1    en-US    chrome/locale/en-US/  
  3. skin    uusharedemo1    classic/1.0    chrome/skin/  
  4. overlay    chrome://browser/content/browser.xul    chrome://uusharedemo1/content/firefoxOverlay.xul  
  5. style    chrome://global/content/customizeToolbar.xul    chrome://uusharedemo1/skin/overlay.css  



前3行每一行表示一种类型的资源的地址,格式是:
资源名称<Tab>组件名称<Tab>参数<Tab>目录路径
其中组件名称是自定义的,只要跟其他组件名不一样并且使用全小写字母即可。定义好之后,就可以使用chrome://地址来定位资源了。例如,假设当前开发文件路径是“c:/dev/uusharedemo1/”,那么:
chrome://uusharedemo1/content/uusharedemo1.png 实际指的是 c:/dev/uusharedemo1/chrome/content/uusharedemo1.png 这个文件。

第4行及第5行表示将当前组件的界面结合到系统本身的界面,因为当前组件会修改firefox本身的工具栏及右键菜单,所以需要加上这两行。

4、default/、skin/、locale/

这几个目录下的文件比较简单,下载本文的源代码查看一般能明白其中的意思,为了节约篇幅这里就不讲解了,等以后我写后续的章节时再详细介绍。

5、认识 content/firefoxOverlay.xul

Firefox的所有窗口都是使用xul文件定义的,例如在地址栏输入:
chrome://browser/content/aboutDialog.xul
(这个地址对应的源文件是:“C:\Program Files\Mozilla Firefox\chrome\browser.jar/content/aboutDialog.xul”
就可以看到firefox的“关于”对话框,在这个例子里我们用firefoxOverlay.xul定义一个工具栏按钮、右键菜单以及一个工具菜单项,源代码如下:

XML/HTML代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!-- 下面一行指明当前窗口控件所引用的样式表文件 -->  
  3. <?xml-stylesheet href="chrome://uusharedemo1/skin/overlay.css" type="text/css"?>  
  4.   
  5. <!-- 这行指明当前窗口控件所使用的语言文件,注意这里不需指定语言的名称(即zh-CN或en-US等),只需指明文件名即可  
  6. 有了语言文件之后,所有控件的文本(即text/label等属性)都统一写到语言文件里。 -->  
  7. <!DOCTYPE overlay SYSTEM "chrome://uusharedemo1/locale/uusharedemo1.dtd">  
  8.   
  9. <overlay id="uusharedemo1-overlay"  
  10.          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">  
  11.     
  12.   <!-- 这行用于指定当前窗口控件的事件(如单击事件)触发后所执行的代码所在的文件 -->  
  13.   <script src="overlay.js"/>  
  14.   <stringbundleset id="stringbundleset">  
  15.     <stringbundle id="uusharedemo1-strings" src="chrome://uusharedemo1/locale/uusharedemo1.properties"/>  
  16.   </stringbundleset>  
  17.   
  18.   <menupopup id="menu_ToolsPopup">  
  19.     <menuitem id="uusharedemo1-hello" label="&uusharedemo1.label;"   
  20.               oncommand="uusharedemo1.onMenuItemCommand(event);"/>  
  21.   </menupopup>  
  22.     
  23.   <popup id="contentAreaContextMenu">  
  24.     <menuitem id="context-uusharedemo1" label="&uusharedemo1Context.label;"  
  25.               accesskey="&uusharedemo1Context.accesskey;"  
  26.               insertafter="context-stop"  
  27.               oncommand="uusharedemo1.onMenuItemCommand(event)"/>  
  28.   </popup>  
  29.     
  30.   <toolbarpalette id="BrowserToolbarPalette">  
  31.   <toolbarbutton id="uusharedemo1-toolbar-button"  
  32.     label="&uusharedemo1Toolbar.label;"  
  33.     tooltiptext="&uusharedemo1Toolbar.tooltip;"  
  34.     oncommand="uusharedemo1.onToolbarButtonCommand()"  
  35.     class="toolbarbutton-1 chromeclass-toolbar-additional"/>  
  36.   </toolbarpalette>  
  37. </overlay>  

menupopup 段定义了一个位于“工具”菜单栏下的项目,其中id是菜单项的名称,我们自己添加的菜单项、按钮等结合到firefox本身的控件的id必须惟 一;label属性是菜单项显示的文本,这里因为引用了语言文件,所以真正显示的文本内容位于语言文件(uusharedemo1.dtd)里标有 uusharedemo1.label 这行定义的后面;oncommand属性定义菜单被点击后执行 overlay.js 里面的那一个方法过程。

popup 段定义了一个右键菜单项,accesskey为菜单项的快捷键(即带下划线的字母),insertafter为新菜单项所出现的位置位于id为 “context-stop”(即“停止”)这项的后面,如何得知某一项菜单项的id呢?出动Dom Inspector 吧。包括firefox工具栏上面的所有按钮的id,都可以用Dom Inspector查看得知。

toolbarpalette段定义了一个工具栏按钮,其中tooltiptext为鼠标停留在这个新按钮上面时所显示的提示文本。

上面一段代码并没有定义自己的窗口,我会在下一章再讲解。

6、认识content/overlay.js

overlay.js 文件是专门为上面的firefoxOverlay.xul服务的,(怎么知道的呢?在firefoxOverlay.xul文件的第13行有引用啊)。在 xul文件里可以看到菜单被点击之后会调用一个名叫“onMenuItemCommand”的方法过程,而工具栏按钮被点击之后会调用 “onToolbarButtonCommand”方法过程。我们想在他们被点击之后做什么事情呢?为了演示如何在js里编写调用firefox对象的代 码,这里模仿uushare书签的功能,让菜单和按钮点击之后调用Uushare.com网站上的书签服务的添加书签的接口,接口是这样的:

http://www.uushare.com/bookmark/save?v=1&client=ff10&noui=yes&jump=close&url=XXXX&title=YYYY&content=ZZZZ

其中XXXX为待收藏的网页地址,YYYY是网页的标题,ZZZZ是网页中选中的文本。所以我们需要在js里获取当前网页的URL、Title以及被选中的文本。
下面是例子中的代码:

JavaScript代码
  1. var uusharedemo1 = {  
  2.   onLoad: function() {  
  3.     // initialization code  
  4.     this.initialized = true;  
  5.     this.strings = document.getElementById("uusharedemo1-strings");  
  6.     document.getElementById("contentAreaContextMenu")  
  7.             .addEventListener("popupshowing"function(e) { this.showContextMenu(e); }, false);  
  8.   },  
  9.   
  10.   showContextMenu: function(event) {  
  11.     // 根据上下文决定显示/隐藏右键菜单项  
  12.     // see http://kb.mozillazine.org/Adding_items_to_menus  
  13.     document.getElementById("context-uusharedemo1").hidden = gContextMenu.onImage;  
  14.   },  
  15.     
  16.   onMenuItemCommand: function(e) {  
  17.     uusharedemo1.addToUushareBookmark();  
  18.   },  
  19.     
  20.   addToUushareBookmark: function() {  
  21.      //这里调用 uushare.com 书签API的接口  
  22.     var location, title, desc;  
  23.     var browser = window.getBrowser();  
  24.     var webNav = browser.webNavigation;  
  25.   
  26.     if (webNav.currentURI)  
  27.         location = webNav.currentURI.spec;  
  28.     else  
  29.         location = gURLBar.value;  
  30.   
  31.     if (webNav.document.title) {  
  32.         title = webNav.document.title;  
  33.     }  
  34.     else {  
  35.         title = location;  
  36.     }  
  37.   
  38.     var focusedWindow = document.commandDispatcher.focusedWindow;  
  39.     var winWrapper = new XPCNativeWrapper(focusedWindow, 'getSelection()');  
  40.     desc = winWrapper.getSelection().toString();  
  41.   
  42.     var serverUrl = "http://www.uushare.com/bookmark/save?v=1&client=ff10";  
  43.     var saveUrl = serverUrl + "&noui=yes&jump=close&url=" + encodeURIComponent(location) + "&title=" + encodeURIComponent(title) + "&content=" + encodeURIComponent(desc);  
  44.     window.open(saveUrl, 'uusharev1''location=yes,links=no,scrollbars=yes,toolbar=no,width=550,height=550');  
  45.   },  
  46.     
  47.   onToolbarButtonCommand: function(e) {  
  48.     uusharedemo1.addToUushareBookmark();  
  49.   }  
  50.   
  51. };  
  52. window.addEventListener("load"function(e) { uusharedemo1.onLoad(e); }, false);  



相信对于熟悉js的朋友上面的代码并不难。大部分代码跟在普通html页面里写的差不多,只是firefox提供了内置的一些对象需要翻查官方的文档才能知道它的作用及其成员。

7、打包、测试

至 此我们的扩展组件就编写完毕了,下面开始做安装测试。首先用压缩工具将install.rdf、chrome.manifest以及chrome目录打包 成一个zip格式的压缩包,要注意的是这2个文件及chrome目录必须在压缩包的顶层目录,否则安装会失败。然后将压缩包文件的扩展名更改了 “xpi”,并把这个文件拖到firefox窗口当中,firefox应该会提示安装并要求重启,重启完之后若无问题即可看到我们制作的“工具”栏菜单 项、右键菜单等。如果组件的源代码有错误,例如xul文件或js脚本文件有错误,一般什么预期的效果都看不到,这时需要重复卸载->修复错误代码 ->重新打包->安装这几个步骤。
开发firefox扩展组件最烦人的事情可能就是调试问题了,幸好firefox提供了一些工具,例如 Extension Developer's Extension 等可以减少一些麻烦。

8、工具栏按钮怎么看不到?如何解决

刚 才我们测试的时候会发现虽然右键菜单、“工具”菜单项都显示出来了,不过怎么工具栏上面的按钮没有显示呢?估计这是很多扩展组件开发者都会遇到的共同问 题,原来firefox将非系统默认的按钮都放到按钮箱里,如果想显示这些按钮,需要对着工具栏右键鼠标,选择“定制”,然后将需要的按钮拖出来才行。这 个特性某种程度上可以给用户最大的选择权,不过另一方面这特性给初级的用户带来困惑。所以我们最好能将工具栏按钮自动显示出来。下面是目前“民间”常用的 方法:
大致思路跟我们平时修改windows注册表类似。firefox工具栏上面的按钮布局被储存在firefox设置表中 navigator-toolbox/nav-bar/currentset 键下面,键的值为当前各个工具栏按钮id的以逗号分隔而连在一起的字符串。我们必须读出这个字符串,并把自己的按钮的id(本示例中按钮id为uusharedemo1-toolbar-button,见xul文件)掺和在其中,再写入新的字符串到设置表。
那 么在什么执行此连串操作呢?很明显不能在每次firefox启动时都执行,因为这样会耗时并影响firefox的启动速度,“民间”的方法是先在设置表中 检查某个自定义的键(例如extensions.uusharedemo1)的值,如果这个值为空的或者不等于当前组件的版本,则执行上述的连串操作,并 写入当前组件的版本号。所以完整的过程是:

  1. 读取某个自定义键(extensions.uusharedemo1)的值;
  2. 如果键的值为空或者不等于当前组件版本号,则下一步,否则退出过程;
  3. 读取navigator-toolbox/nav-bar/currentset键的字符串;
  4. 寻找自己按钮的id是否在字符串当中,不存在则将id连接到地址栏id(urlbar-container)的前面;
  5. 将新字符串写入键;
  6. 写当前组件的版本号到自定义键。

下面是上面过程的js代码:

JavaScript代码
  1. var uusharedemo1 = {  
  2.     strVersion : '1.0',  
  3.   
  4.     getUBKCharPref: function(strPrefName) {  
  5.         this.prefManager = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);  
  6.         try {  
  7.             return(this.prefManager.getCharPref("extensions.uusharedemo1." + strPrefName));          
  8.         } catch(e) {  
  9.             return(false);      
  10.         }  
  11.     },  
  12.       
  13.         setUBKCharPref: function(strPrefName, strValue) {  
  14.         this.prefManager = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);              
  15.         this.prefManager.setCharPref("extensions.uusharedemo1." + strPrefName, strValue);  
  16.     },  
  17.       
  18.     onLoadEvent: function()  
  19.     {  
  20.         //first load  
  21.         var strPrefVersion = this.getUBKCharPref('version');  
  22.           
  23.         if(strPrefVersion != this.strVersion) {  
  24.               
  25.             var bolWongPostButtonExists = document.getElementById('uusharedemo1-toolbar-button');  
  26.               
  27.             if(!bolWongPostButtonExists) {  
  28.                 var objToolbox = document.getElementById("navigator-toolbox");      
  29.                 var strChild = '';  
  30.                 var strSet = '';  
  31.                 var objNavBar = false;  
  32.               
  33.                 if(objToolbox) {  
  34.                     for (var i = 0; i < objToolbox.childNodes.length; ++i) {  
  35.                         if(objToolbox.childNodes[i].id == "nav-bar" && objToolbox.childNodes[i].getAttribute("customizable") == "true") {  
  36.                             objNavBar = objToolbox.childNodes[i];  
  37.                             break;  
  38.                         }  
  39.                     }  
  40.                 }  
  41.                               
  42.                 if(objNavBar) {  
  43.                     for (var i = 0; i < objNavBar.childNodes.length; i++) {  
  44.                         if(objNavBar.childNodes[i].id == "urlbar-container") {  
  45.                             if(!bolWongPostButtonExists) {  
  46.                                 strSet += "uusharedemo1-toolbar-button,"                                                          
  47.                             }  
  48.                         }  
  49.                         strSet += objNavBar.childNodes[i].id + ",";  
  50.                     }  
  51.                       
  52.                     strSet = strSet.substring(0, strSet.length-1);  
  53.                     objNavBar.currentSet = strSet;  
  54.                     objNavBar.setAttribute("currentset", strSet);  
  55.                     objNavBar.ownerDocument.persist(objNavBar.id, "currentset");  
  56.                     BrowserToolboxCustomizeDone(true);  
  57.                 }   
  58.                   
  59.                 strSet = strSet.substring(0, strSet.length-1);  
  60.                 toolbar.currentSet = strSet;  
  61.                   
  62.                 if(toolbar.setAttribute) {  
  63.                     toolbar.setAttribute("currentset", strSet);  
  64.                 }  
  65.                   
  66.                 toolboxDocument.persist(toolbar.id, "currentset");  
  67.                 BrowserToolboxCustomizeDone(true);          
  68.             }  
  69.               
  70.             this.setUBKCharPref('version'this.strVersion);  
  71.               
  72.         }//end if first load  
  73.     }  
  74. }  
  75.   
  76. window.addEventListener("load"function()                 { uusharedemo1.onLoadEvent(); }, false);  


为了简单起见,这段代码并没有整合到示例的压缩包当中,如果想查看整合后的结果,可以参考uushare书签组件的源代码:http://www.uushare.com/help/bookmark/toolbar_firefox

本文完。

Tags: xul, mozilla, plugin, addon