上周末咱们在JSConf.eu发布了 Cloud9 IDE ,同时发布了对应的GitHub项目。在4天时间里该项目获得340我的的关注和将近50个fork。Cloud9的口号是由"由Javascripters 为Javascripters建立的IED",这口号有点递归,它意味着你能够hack这个ide使它变得更强大。Cloud9项目开始之初就尤为注意考虑这点了;Cloud9中的每个功能点都是一个扩展(extension)。在IED启动的时候咱们用优秀的 requireJS 库加载全部的扩展。前端UI使用 ajax.org platform (apf),apf 使咱们轻松地模块化Cloud9的用户界面。下面开始详细介绍怎样为Cloud9编写扩展。javascript 一个扩展的生命周期是从它做为requireJS的模块开始的。我将简述requireJS的基本语法,想深刻了解requireJS请参考这个文 档。一个扩展会依赖其余的扩展和一些核心模块。咱们将编写一个给编辑器中选定的JSON代码进行格式化的扩展。该扩展依赖核心模块:core/ide, core/ext, core/util 和编辑器管理扩展:ext/editors/editors.让咱们称该扩展为formatjson,而后将其置于ext文件夹下。html
|
![]() jingxing05
|
require.def第一个参数标识扩展的名字,第二参数中 ide,ext ,util和 editors 表明传入该扩展依赖的对象引用,formatjson扩展的第五个依赖是加载为一个文本的xml文件。 ‘text!’ 语法告诉 requireJS 不要将参数引入的文件解析为 javascript,仅将其中的内容做为文本返回便可。全部依赖加载完毕后将调用第三个参数表明的回调函数,在回调函数中将咱们的扩展注册到扩展管理器 中,让咱们看看扩展文件的结构。
{ name : "JSON Formatter", dev : "Your Name Here", alone : true, type : ext.GENERAL, markup : markup, hook : function(){}, init : function(){}, enable : function(){}, disable : function(){}, destroy : function(){} } 属性和方法详解:node 属性
|
![]() jingxing05
|
方法
|
![]() jingxing05
|
实现 Format JSON扩展好,如今咱们已经有了基本概念,让咱们开始真正来实现 format json扩展。首先完成咱们须要属性和方法。我将添加一nodes数组,其中包含该扩展所需的全部UI元素。咱们用hook方法来建立一个菜单来初始化 formatjson扩展,并显示一个格式化窗口接受用户输入的缩进值。代码以下: { name : "JSON Formatter", dev : "Ajax.org", alone : true, type : ext.GENERAL, markup : markup, nodes : [], hook : function(){ var _self = this; this.nodes.push( mnuEdit.appendChild(new apf.item({ caption : "Format JSON", onclick : function(){ ext.initExtension(_self); _self.winFormat.show(); } })) ); }, init : function(amlNode){ this.winFormat = winFormat; }, enable : function(){ this.nodes.each(function(item){ item.enable(); }); }, disable : function(){ this.nodes.each(function(item){ item.disable(); }); }, destroy : function(){ this.nodes.each(function(item){ item.destroy(true, true); }); this.nodes = []; this.winFormat.destroy(true, true); } } 在hook方法中建立一个菜单依附到mnuEdit。mnuEdit是对编辑器菜单的全局引用。如今咱们的UI元素的名字挂靠在全局命名空间下(可能会在未来的版本中变动)。Cloud9中可用的UI元素表以下,并指定了哪些扩展添加了这个元素。
|
![]() jingxing05
|
还有更多建好的元素。能够在各自的扩展或经过DOM/XPath操做找到他们。例如在工具栏和状态栏之间有一个hbox包含3个vbox元素。
<a:hbox> <a:vbox /> <a:vbox /> <a:vbox /> </a:hbox> 能够用XPath选择器来访问元素: vbMain.selectSingleNode("a:hbox/a:vbox[2]"); 这条查询将定位到hbox中的第二个vbox。这个vbox含有了打开的文件tab和控制台面板。而后你能够像咱们在formatjson扩展中对菜单的处理方法同样将你想要的元素添加到该vbox。 |
![]() jingxing05
|
MarkupUI 标记而后format json 扩展会弹出个窗口给用户来设置缩进的空格数。咱们用aml标记语法来建立这个窗口。我将aml代码放到名为formatjson.xml的xml文件中,并在最外层添加了一个扩展所需的根元素:a:application,看起来像这样: <a:application xmlns:a="http://ajax.org/2005/aml"> <!-- Your UI markup here --> </a:application> UI标记能够包含html和 AML元素。咱们使用AML的一个下拉列表spinner和两个按钮来描述对json格式化的窗口。 <a:window id = "winFormat" title = "Format JSON" center = "true" modal = "false" buttons = "close" kbclose = "true" width = "200"> <a:vbox> <a:hbox padding="5" edge="10"> <a:label width="100">Indentation</a:label> <a:spinner id="spIndent" flex="1" min="1" max="20" /> </a:hbox> <a:divider /> <a:hbox pack="end" padding="5" edge="10 10 5 10"> <a:button default="2" caption="Format" onclick = " require('ext/formatjson/formatjson').format(spIndent.value); "/> <a:button onclick="winFormat.hide()">Done</a:button> </a:hbox> </a:vbox> </a:window> 格式化按钮绑定了onclick事件来调用咱们扩展的format方法,它传入了spinner的值。这就是咱们在扩展中须要实现的方法,让咱们动手吧。 |
![]() jingxing05
|
自定义函数格式化函数有一个参数,来指定json中缩进的空格数。首先获取当前选择的代码,若是选中的代码为有效的json,则对其格式化,更新到当前选中的代码,不然给用户一个错误提示。 咱们须要加载另外一个依赖来完成该功能,就是ace编辑器的Range模块。因而我在顶部将ace/Range添加到依赖列表中,而后调用参数"Range"。格式化函数看起来以下(我给每一个部分添加了注解)。 { ... format : function(indent){ //获取当前编辑器 var editor = editors.currentEditor; //从当前编辑器获取选中的对象 var sel = editor.getSelection(); //获取当前的文档对象引用 var doc = editor.getDocument(); //获取当前选中对象的range对象 var range = sel.getRange(); //从range对象获取选中的文本 var value = doc.getTextRange(range); //尝试将选中的文本转换为JSON,并格式化 //而后再回转为文本字符串,若是出现错误则给用户显示错误. try{ value = JSON.stringify(JSON.parse(value), null, indent); } catch(e){ util.alert( "Invalid JSON", "The selection contains an invalid or incomplete JSON string", "Please correct the JSON and try again"); return; } //若是格式化成功则用格式化后值替换掉range对象 var end = doc.replace(range, value); //用格式化的值更新当前选中的部分 sel.setSelectionRange(Range.fromPoints(range.start, end)); }, ... } 咱们的扩展示在可使用了,但让咱们再添加点东西。 |
![]() jingxing05
|
Key快捷键绑定我但愿使用快捷键来使用这个扩展,window使用: Ctrl-Shift-J,mac用Command-Shift-J。Cloud9中用户能够自行配置快捷键。要实现上述功能,还需几个步骤。首先在 ext/keybindings_default文件中为咱们的扩展新添windows和mac的默认键绑定部分。 ... "ext" : { ... "formatjson" : { "format" : "Ctrl-Shift-J" // Or "Command-Shift-J" for the mac file }, ... } ... 而后必需要让快捷键管理器知道该扩展对什么快捷键响应和显示什么UI元素。添加名为hotkeys和hotitems的hash表: hotkeys : {"format":1}, hotitems : {}, 如今你有两种途径为键绑定添加处理器了。直接的方式是在扩展中添加响应方法,方法的名称与hotkeys中指定的名称相同便可,此处就是“format”。由于咱们的json格式化扩展有一个菜单来显示快捷键,我更喜欢将响应方法链接到菜单的onclick事件上,这样当我按下快捷键时这个方法被执行。并且当我使用快捷键时这个菜单按钮应该点亮。能够在hotitems哈希表中添加菜单项来达到目的: this.hotitems["format"] = [this.nodes[0]]; 如今咱们能够在Tools菜单下的Extendtion Manage中来激活该扩展了,能够观看下面这段视频来看看,如何在3分钟内完成这个扩展。(视频下载) |
![]() jingxing05
|
When you need help with creating an extension 在你开发扩展须要帮助的时候请到Cloud9的 Google Group 。能够向github的issue跟踪issue tracker of GitHub提交任何你发现的问题。Cloud9的全部开发者在Twitter上十分活跃。在扩展Cloud9的路上祝你好运。我都等不及要看你会扩展出什么了。 咱们很是乐意将你酷毙了的扩展添加为Cloud9的子模块,或者在Github上提交pull request。
玩得开心!