faunus 发表于 2008-12-22 23:56:10

开始学习XUL及国内现状

最近一直在使用Firefox作为我缺省的浏览器,而且在安装了许多插件后,已经对Mozilla产生了浓厚的兴趣。我也很希望自已动手开发一些插件,因此开始了XUL的学习。而且我更希望的是利用Python来实现XUL的开发,如果不能直接实现,也可以考虑在 NewEdit 中开发一些插件可以快速开发XUL,比如说自动生成XUL的框架,通过写一些简单的 Python 封装来自动生成XUL的源代码,这样我需要生成一个 Python 的中间层。如果想实现这一点,我想我首先要做的就是学习XUL及相关的技术,同时构造 Python 的封装。因此有时间就开始我的 XUL 的学习吧。
那么我学习的资料都来源于网上。主要是从 http://www.xulplanet.com 上来的。在上面的 download 其中有教程 XUL Tutorial (很长,但很详细)和一个 XUL App Tutorial (名称叫XulNote,使用XUL做的记事本)。在国内,有关XUL开发的中文资料非常少、不完整而且分散。
[*]我在mozcn.org的论坛中找到一篇翻译成中文的如何写一个Firefox下的Hello world的插件的文章。[*]在SRP上开始了Mozilla开发文档(与XUL的教程不是一个,XUL只是Mozilla相关技术中的一个)的翻译,在写这篇Blog时共翻译了三章:开场白、Mozilla平台、入门。[*]在mozcn.org中计划开始 XUL Tutorial 的翻译,但没有看到东西。[*]台湾的同胞网站moztw.org已经开始这项工作,不过好象还没有大陆同胞参加。他们有一个wiki,不过只是用来认领任务使用。真正的工作是放在subversion中进行了。我尝试着下载,但好象东西非常大(的确,在xulplanet.com上下载的XUL Tutorial教程有3M之多,这还是压缩的呀),最后放弃了。在wiki上也看不到翻译完成的内容。[*]现在国内几个mozilla相关的中文网站正在考虑联合或整合事宜,希望为中文与软件的使用方面集中资源,把事情做得更好。因此,开发方面的事宜我想还不是短期可以完成的。这样我目前学习XUL只能还是靠个人的努力了。以学习笔记的方式为主,可以把一些口水化的东西去掉,变成一个精简的实践型的教程。我甚至想,可以在原文基础之上把没用的句子去掉,只留下最有用的,然后整理成中文。这就是精简过后的中文教程了。

事情只能一点点来了。

懷念過去↑文 发表于 2008-12-23 00:50:45

Firefox 还没有用过ali59ls

faunus 发表于 2008-12-24 16:03:55

addEventListener的第三個參數

      

W3C DOM裡用來新增觸發事件的函數叫AddEventListener,不過我一直不知道這個函數的第三個參數是要做什麼用的,總是隨便設,也沒發現差異再哪,前兩天看ppk on javascript終於看到說明了,至於很久以前就有的DOM的標準文件,我其實根本沒去找過這個參數的資訊。

      

這個參數叫做useCapture,是一個boolean值,就是true or false,如果送出true的話就是瀏覽器會使用Capture方式,false的話是Bubbling,只有在特定狀況下才會有影響,通常建議是false,而會有影響的情形是目標元素(target element)有祖先元素(ancestor element),而且也有同樣的事件對應函數,我想,看圖會比較清楚。

      


          範例有兩層的div方塊
      

      

像這張圖所顯示的,我的範例有兩層div元素,而且都設定有click事件,一般來說,如果我在內層藍色的元素上click不只會觸發藍色元素的click事件,還會同時觸發紅色元素的click事件,而useCapture這個參數就是在控制這時候兩個click事件的先後順序。如果是false,那就會使用bubbling,他是從內而外的流程,所以會先執行藍色元素的click事件再執行紅色元素的click事件,如果是true,那就是capture,和bubbling相反是由外而內,會先執行紅色元素的click事件才執行藍色元素的click事件。附上兩個範例,capture和bubbling,兩個檔案只有差在此一參數不同,可以發現事件的發生順序不一樣了。

      

那如果不同層的元素使用的useCapture不同呢?就是會先從最外層元素往目標元素尋找設定為capture的事件,到達目標元素執行目標元素的事件後,再尋原路往外尋找設定為bubbling的事件。

faunus 发表于 2008-12-31 13:01:14

Gecko支持的以及能够用于XUL应用软件的技术列表(不包括XUL本身):

# HTML4.0 和XHTML
# CSS2 以及部分CSS3
# DOM2 以及部分DOM3
# XML
# MathML
# RDF
# XSLT
# XPath
# Simple XLinks
# XPointer
# XML Base
# FIXPtr
# XML-RPC
# SOAP (Simple Object Access Protocol)(简单对象访问协议)
# WSDL (Web Services Description Language)(web services 描述语言)
# ECMAScript/Javascript
# XBL (eXtensible Bindings Language)(可扩展绑定语言)
# GIF, JPG, PNG, BMP, ICO 图像
# HTTP 1.1

这个列表不包括Mozilla Mail中使用的所有邮件相关技术,如POP3、IMAP和LDAP,你可以在你自己的软件中支持它们。

faunus 发表于 2008-12-31 13:01:57

XUL支持各种版本的

Windows、
Macintosh、
Linux及
其它版本的Unix

faunus 发表于 2008-12-31 13:06:51

什么是XUL

XML用户界面语言(XUL)是一种用于创建具有丰富动态特性用户界面的标记语言。它是Mozilla浏览器及其相关软件的一部分,同时也是Gecko的一部分。XUL支持各种版本的Windows、Macintosh、Linux及其它版本的Unix。有了XUL和其它Gecko组件,你不需要别的专门工具就能够编写出优秀的应用程序来。
XUL最初是为Mozilla软件,其中包括web浏览器,邮件客户端软件和网页编辑器编写用户界面而设计的。但是,除了编写这类软件外,XUL也同样能够用于你现在使用的web应用软件中的任何地方,比如需要能从网络上检索资源及需要一个功能更加丰富的用户界面。就像HTML一样,你也能在XUL中使用标记语言编写一个界面,使用CSS样式表来定义外观,能使用JavaScript来编写动态效果,不仅如此,你还能为通过网络读写远端文件的内容和调用webservices编写界面。然而,与HTML不同的是,XUL为创建菜单,工具栏,标签属性页和树性列表提供了一组丰富的用户界面构件。这就意味着你不必仅仅为了处理一个弹出式菜单而去寻找第三方代码或者在你的程序中包含进一大段JavaScript源码,XUL已经内建了所有的这些元素。另外,这些元素的外观和使用被设计得和用户所使用的本地平台一致,甚至支持Windows XP和MacOSX的系统风格,如果你愿意,你还能使用标准的CSS来创建你自己的外观。XUL的构件同样支持本地化,并且其实现得到了操作系统界面实现的支持。

XUL是什么?
XUL是一种XML语言,你能使用包括XSLT、XPath和DOM函数在内许多已存在的标准来处理一个用户界面,所有的这些Gecko均支持。实际上,XUL功能非常强大,以至于Mozilla软件的所有用户界面都是用XUL实现的。
除存在XUL中许多内建的用户界面构件之外,你也可以使用一种被称作可扩展绑定语言(XBL)的相关语言来创建别的自定义构件,这种语言可以用来创建自定义标记和实现自定义功能。
XUL程序可以从一个远端的web站点直接打开,或者可以由用户下载并安装。Mozilla的XPInstall技术允许将一个应用程序放在远端站点上,仅通过点击几次鼠标来完成安装,虽然安装文件,或者说是安装步骤会有一个比较长的过程,但是其间却不存在搜索文件的情况。安装应用程序的另一个特点是降低了系统的安全限制,因为应用程序有可能要进行文件的读写,以及访问用户参数和系统信息。
XUL也可以用来单独编写嵌入Gecko引擎中的软件,或者当作浏览器的一部分来使用。XUL的覆盖特性允许第三方为浏览器自身编写扩展,比如说增加自定义的工具栏,改变菜单,或者是增加其他具有特点的部分,这在 MozillaFirefox中比较常见--它有差不多100个扩展。Mozilla将要发布的邮件客户端软件--Thunderbird同样也有许多扩展,实际上,任何XUL软件都能支持扩展。
Gecko也同样支持其他诸如XML-RPC、SOAP和WSDL的web services技术,最近,这些技术被用于开发一个用来浏览amazon.com上商品的软件。

标准与其他支持的技术
下面是一个Gecko支持的以及能够用于XUL应用软件的技术列表(不包括XUL本身):
# HTML4.0 和XHTML
# CSS2 以及部分CSS3
# DOM2 以及部分DOM3
# XML
# MathML
# RDF
# XSLT
# XPath
# Simple XLinks
# XPointer
# XML Base
# FIXPtr
# XML-RPC
# SOAP (Simple Object Access Protocol)(简单对象访问协议)
# WSDL (Web Services Description Language)(web services 描述语言)
# ECMAScript/Javascript
# XBL (eXtensible Bindings Language)(可扩展绑定语言)
# GIF, JPG, PNG, BMP, ICO 图像
# HTTP 1.1
这个列表不包括Mozilla Mail中使用的所有邮件相关技术,如POP3、IMAP和LDAP,你可以在你自己的软件中支持它们。

作为软件平台的XUL
XUL和Gecko对于编写优秀的web软件来说是一个非常好的选择,它提供了一个丰富的用户界面工具包,对标准支持出色的HTML和CSS渲染,对web services的支持和百分之百的跨平台。
Gecko运行时环境(GRE)的开发工作正在进行,其目标是使Gecko成为一个独立运行的软件,如果你愿意的话,还将包括你自己开发的程序。这个想法就是在安装应用软件时,自动安装或下载GRE的相应版本,如果软件需要的话;如果GRE已经安装过了,就没有必要再重新安装或下载一次。对于那些需要的来说,GRE大约有5到10兆的大小(视你所使用的平台而定),这大大小于其他的软件平台。除此之外,也能够直接从网络驱动器或者CD运行Gecko。
由于XUL可以用于web站点的开发,所以它能够用于像PHP和JSP这样的服务器端架构来建立具有动态内容的站点。这就使得Gecko依照你的需要,其软件模型是两层或者三层。目前,目的是将Java、Python和其他语言直接整合进Gecko的项目正在进行中。

从那些地方学习XUL?
XulPlanet提供了XUL、XBL和其他相关技术的指南与参考,mozilla.org上也有相关内容。想了解更复杂的例子,你可以借助各种不同的MozillaFirefox扩展,mozdev.org上的项目,或者甚至是Mozilla软件自身使用的XUL:只需要使用ZIP工具打开Mozilla的chrome目录中扩展名为JAR的文件,然后阅读即可。

faunus 发表于 2008-12-31 13:11:28

同类技术

MS公布的 Longhorn的下一代.Net用户接口语言 (XAML)
Macromedia为了配合 JAVA的FLEX Flash用户接口语言(MXML1,它们都是由最早的SVG、XUL转变过来的。

  XUL是基于现有的 web技术开发出来的.比如CSS和 Java,Script.Web开发人员由于对这些技术都比较熟悉,因此转向XUL技术相对转向其它 UI语言更加容易和平滑,而XAML所涉及的几乎都是.NET的技术,对于web开发人员,这种转变的面临着巨大的技术鸿沟,因此要想在web领域使用 XAML技术.不可避免存在很多困难。

faunus 发表于 2008-12-31 13:17:50

基于XUL的查询文件系统

  查询文件系统的目的是解决用户查询文件的问题.完全实现查询的智能化,从而提高用户的查询效率。一个好的查询文件系统的界面应具备以下几个特点:1)高效性:能否快速输入查询条件直接决定了操作人员的工作效率.因此输入查询条件的速度是非常重要的;2)可移植性:系统可以作为应用程序来运行,也可以作为 Web应用程序来运行.基于以上两点,查询文件系统的表示层利用XUL来实现。
下面是文件查询系统界面的实现代码。
  代码清单 l
<!-- 菜单实现代码 --一>
<!-- 输入查询条件多个tabpanel实现代码-->
<tabbox>
<groupbox orient=”horizontal”>
<caption label=”Search Criteria”/>
<menulist formid=”mainform” id=”searehtype”>
<menupopup>
<menuitem label=” Name”/>
<menuitem label=” Size”/>
<menuitem label=” Date Modified”/>
</menupopup>
</menulist>
<spacer class=” springspace”/>
<menulist formid=’’maiform”id=”searchmode”>
</menulist>
</groupbox>
<tabpanel>
<tabpanel id=”optionspanel” orient=”vertical”>
<checkbox formid=”mainform” id=”casecheck” label=”Case Sensitive Search”/>
<checkbox formid=”maiform” id=” wordscheck” label=”Match Entire Filename”/>
</tabpanel>
</tabpanels>
</tabbox>
  代码清单 l的界面显示
  在两个 tab的输入项中输入数据.点击”Find”钮,Mozilla就会调用代码清单 2中的submit(formid)数.把输入的数据提交到服务器端 http://16.157.130.8:7001/xul/dofind.jsp进行处理.然后把结果返回给Mozilla。
代码清单2中的javascript处理思路如下:XUL没有提供和 html form对应的部件,所以提交数据时首先需要创建一个htmlform ,然后取formid是 mainform(每个需要提交数据 的部件 的 formid属性的 value为mainform)的部件,接着取得它们的 value,如果是checkbox就取 data.item(i).checked.紧接着把id和value以hidden的形式append到http form 中.最后提交httpform 。
代码清单 2
function submit(formid){
vat form =createForm (formid, ”mainform”,”dofind.jsp”,”post”,”_self”);
setFormData(form,formid);
form.submit0;
}
function createForm(formid,name,action,method,target){
vat form =document.getElementByld(formid);
if(form !=nul1){
document.documentElement.removeChild(form);
var form:document.createElementNS {“http://www.w3.org/1999/xhtml”,”html:form”);
form.setAttribute(“id”.formid);
form.setAttribute(“nanle”,name);
form.setAttribute(“action”,action);
form.setAttribute(“method”,method);
form.setAttribute(“target”,target);
document.documentElement.appendChild(form);
}
return form;
}
function setFormData(form,formid){
var data=document.getElementsByAttribute(“formid”,formid);
for(i=0; i<data.1ength; i++){
vat val=document.createElementNS(“http://www.w3.org/1999/xhtml”,”html:input”);
va1.setAttribute(“type”,”hidden”);
va1.setAttribute(“name”,data.item(i).getAttribute(“id”));
alert(data.item(i).checked);
if(data.item(i).value===undefined)f
va1.value=data.item(i).checked;
} else {
va1.value=data.item(i).value;
}
form.appendChild(va1);
}
}

faunus 发表于 2008-12-31 14:34:55

利用XPCOM技术实现Firefox跨平台文件操作JavaScript类
在我们工具条的设定选项模块和历史记录模块都需要操作本地文件以读取和写入配置及记录。但是firefox作为一个跨平台和有沙漏机制的浏览器,对于本地操作系统的文件操作不可能像普通的文件操作一样。必须实现一个安全的,跨平台的本地资源访问机制来解决这个问题。在firefox里面提供了XPCOM(Cross Platform Component ObjectModule)技术已解决这个问题。他类似与微软的COM,但是它们的实现不同。微软的COM组件是注册在系统注册表中的,而XPCOM组件是通过Mozilla自己的注册表注册的。这个信息存在于两个文件中:comreg.dat和xpti.dat。在comreg.dat中你会发现很多信息。XPCOM使我们可以在JavaScript中使用XPCOM组件,并且还可以在JavaScript中开发XPCOM组件。这样就向需要快速解决方案但又不想用C或者C++编写本地XPCOM组件的开发人员打开了创建XPCOM组件的大门。
我们的MTB_File类就使用JavaScript脚本来实现了跨平台的本地文件访问XPCOM组件类。他提供了沙漏模式下对firefox当前运行的Profile文件夹下文件和文件夹的读、写、删、改操作,以及文件和文件夹的大小,类型,是否可执行等属性的获取。
根据MTB_File类所需要实现的功能,我们设计得到一下的MTB_File类图:
http://www.cnblogs.com/images/cnblogs_com/jessezhao/WindowsLiveWriter/XPCOMFirefoxJavaScript_8C04/clip_image001_thumb.jpg
根据类图的要求,我们使用JavaScript来实现该类图,根据业务流程,我们逐一讲解该类的各个关键函数:
首先我们必须获取当前Profile下的我们工具栏配置文件和历史文件的存放的目录。这个目录在firefox的当前用户的Home文件夹或者MyDocument文件夹下的Mozilla/firefox文件夹下面。按照默认规定,我们的工具栏为了和其他的firefox插件区分,所有的配置和历史记录文件都存放在当前Profile文件夹下的FulinToolbarData文件夹下面。为了方便我们获取这个文件夹,我们实现了MTB_getLocalFileDir函数:
   1:function MTB_getLocalFileDir()   2:      3:{   4:      5:      //获取Mozilla提供的原生Directory服务,便于JS桥接   6:      7:      var dirService = Cc["@mozilla.org/file/directory_service;1"]   8:      9:          .getService(Ci.nsIProperties);10:   11:      var localFile = dirService.get("ProfD", Ci.nsIFile);12:   13:      // 添加FulinToolbarData文件夹对象14:   15:      localFile.append("FulinToolbarData");16:   17:      //如果当前的FulinToolbarData文件夹不存在,那么创建它18:   19:      if( !localFile.exists() )20:   21:          //创建文件夹的权限为0700,类似linux下权限分配方法22:   23:          localFile.create(1, parseInt("0700", 8) );24:   25:      return localFile;26:   27:};
我们在获取当前Profile的文件夹的FulinToolbarData后,需要获取该文件夹下面的指定文件名的文件对象。我们实现了MTB_File函数,用于获取改对象。这个也是MTB_File类的构造函数,他会自动的调用上面的MTB_getLocalFileDir函数,然后返回我们所需要的文件对象。
   1:function MTB_File(filename)   2:      3:{   4:      5:      var localfile = MTB_getLocalFileDir();   6:      7:      localfile.append(filename);   8:      9:      this.nowFile = localfile;10:   11:};
我们对一个文件进行增删改等操作前,必须先打开该文件,所以我们提供了文件打开函数open,该函数根据传入的打开类型Mode的不同,分别返回只读,写入和写入及创建三种不同类型的文件流对象,以方便我们使用文件流进行文件的操作。关于文件流的创建,我们使用了Mozilla提供file-input-stream和file-output-stream对象来实现跨平台的文件流功能。
   1:MTB_File.prototype.open = function(mode)   2:      3:{   4:      5:      switch(mode){   6:      7:      / ReadOnly只读模式打开文件流   8:      9:      case "r":10:   11:          var instream   12:   13:            = Cc["@mozilla.org/network/file-input-stream;1"]14:   15:            .createInstance(Ci.nsIFileInputStream);16:   17:          instream.init(this.nowFile, MTB_RDONLY, PERM_IROTH, 0);18:   19:          this.tmpStream = instream;20:   21:          var sctinstream   22:   23:            = Cc["@mozilla.org/scriptableinputstream;1"]24:   25:            .createInstance(Ci.nsIScriptableInputStream);26:   27:          sctinstream.init(this.tmpStream);28:   29:          this.nowStream = sctinstream;30:   31:          break;32:   33:      //Write 可写模式打开文件流34:   35:      case "w":36:   37:          var outstream   38:   39:            = Cc["@mozilla.org/network/file-output-stream;1"]40:   41:                  .createInstance(Ci.nsIFileOutputStream);42:   43:            outstream.init(this.nowFile, MTB_RDWR, PERM_IROTH, 0);44:   45:            this.nowStream = outstream;46:   47:            break;48:   49:          // Write&Create 创建和可写模式打开文件流50:   51:          case "w+":52:   53:            var outstream   54:   55:                  = Cc["@mozilla.org/network/file-output-stream;1"]56:   57:                  .createInstance(Ci.nsIFileOutputStream);58:   59:            if( this.exists() )60:   61:                  this.nowFile.remove( false );62:   63:            outstream.init(64:   65:                  this.nowFile, MTB_WRONLY|MTB_CREATE_FILE,   66:   67:                  PERM_IROTH, 0);68:   69:            this.nowStream = outstream;70:   71:            break;72:   73:          }74:   75:};
在我们打开文件流之后,我们可以使用文件流来操作我们指定的文件。比如我们可以从当前文件流里面读取出指定长度的内容来,下面的read函数就可以实现上面的功能。我们的文件流提供了读取,写入等操作,我们的函数只是在封装这些功能,以方便我们做一些业务逻辑相关的操作,比如指定内容过滤或者当前文件流可用性的判定。
   1:MTB_File.prototype.read = function(count)   2:      3:{   4:      5:       if( this.nowStream == null )   6:      7:          return;   8:      9:      //从当前指定的文件流里面读取指定长度的内容10:   11:      return this.nowStream.read(count);12:   13:};
下面的函数是往我们指定的文件流里面写入我们指定的内容,我们在函数里面加入了对当前文件流是否存在的判断。如果当前文件流存在,那么我们往当前文件流里面写入指定内容,然后Flush整个文件流,防止下次写入上次的输入的内容。
   1:MTB_File.prototype.write = function(str)   2:      3:{   4:      5:      if( this.nowStream == null )   6:      7:      return;   8:      9:   this.nowStream.write( str, str.length );10:   11:   this.nowStream.flush();12:   13:};
在我们对该做的文件操作结束之后,我们必须关闭我们文件流,以便于系统回收资源。关闭文件流的时候,我们首先要调用当前文件流的close方法,然后将当前的文件流设置为null,就可以标识当前文件流为待回收的,当系统在方便的时候回收该文件流资源。
   1:MTB_File.prototype.close = function(){   2:      3:      if(this.nowStream != null)    4:         this.nowStream.close();   5:      6:      if(this.tmpStream != null)   7:      8:   this.tmpStream.close();   9:   10:   this.nowFile = null;11:   12:   this.nowStream = null;13:   14:   this.tmpStream = null;15:   16:};
我们在访问文件流进行读操作的时候,可能会遇到我们要读入长度为10的内容的时候,可是我们当前访问的文件流只有长度为5的可用内容,这种时候如果我们没有任何保护手段来确保访问不会越界,那么可能会造成访问越界异常。为了防止越界异常的发生,我们在每次从文件流里面读取内容时都会检查当前文件流是不是已经到了最后了。下面就是这个EOF函数的实现,他会获得当前文件流可用长度,看他是否大于1,如果不大于1那么就说明当前文件流就已经到达最后,不可在读取了。
   1:MTB_File.prototype.EOF = function()   2:{   3:      4:      if( this.nowStream == null )   5:      6:      return;   7:      8:   if( this.nowStream.available() > 0 )   9:   10:      return false;11:   12:   else13:   14:      return;15:   16:};
另外,通过当前文件流我们还可以获取当前文件的大小,类型以及是否可运行等其他很多属性,我们也提供了相应的函数封装,以便于其他javascript文件调用。最后提供整个js类的下载:
http://www.cnblogs.com/Files/jessezhao/fulin-file.js

lbjyuer 发表于 2016-2-9 22:22:42

支持火车。。。。历史帖子回顾中。
页: [1]
查看完整版本: 开始学习XUL及国内现状