自己挖的天坑,跪着也要填下去>_<
在上一篇搭建好了布局,实现了第一个模块studio
的基本功能,已经能够进行简单的编辑工作。这里我将会实现以下功能:
- 底部工具条UI
- 新建、打开、保存文件
工具条
由于工具条按钮绑定的都是studio
模块下的功能,因此我把index.html
上的工具条移动到了studio
模块的视图模版modules/studio/views/studio.html
里。
CSS
<div class="content studio-wrap">
<textarea name="" cols="30" rows="10" hmd-editor></textarea>
</div>
<footer class="tool">
<!--状态栏消息-->
<section class="msg" id="msg"></section>
<section class="btn-group studio-btn-group">
<a studio-newfile href="javascript://" class="btn btn-primary" style="border-radius:0;" title="新建文件"><i class="glyphicon glyphicon glyphicon-file"></i></a>
<a studio-openfile href="javascript://" class="btn btn-primary" title="打开文件" ng-click="openTerminal()"><i class="glyphicon glyphicon-folder-open"></i></a>
<a studio-save href="javascript://" class="btn btn-primary" title="保存更改" style="border-radius:0;"><i class="glyphicon glyphicon-floppy-disk"></i></a>
</section>
</footer>
CSS写得比较难看,没什么好说的。
样式里我大量使用了calc
这个功能,这在布局的时候非常的方便,比如:
body {
height: calc(100% - 50px);
overflow: hidden;
color: #fff;
background: #1E1E1E;
}
那么工具条就是这个样子啦。
文件操作
工具条的bt-group里有三个按钮,分别绑定了三个studio下的directive:studio-newfile
,studio-openfile
,studio-save
。首先打开modules/studio/directives.js
,开始实现这3个功能。
新建文件
这个功能很简单,只要把当前文件设为空,并且清空编辑器内容就算是新建文件了,保存的时候才会让用户选择保存路径。
修改editor.js
的setFile
方法
//设置当前文件
setFile:function(filepath){
if(filepath && fs.existsSync(filepath)){
var txt = util.readFileSync(filepath);
this.filepath = filepath;
this.cm.setValue(txt);
}
else{
this.filepath = null;
this.cm.setValue('');
}
}
实现directive
,点击按钮时调用编辑器的setFile
让filepath
为空。
studio.directive('studioNewfile', function () {
return function ($scope, elem) {
$(elem[0]).on('click',function(){
hmd.editor.setFile();
});
};
});
这样新建文件按钮就完成了,其实这按钮的功能就是清空编辑器,真正的保存新文件功能在保存按钮功能里实现。
保存文件
保存按钮只有在文本有改动时才可用,这样用户就能很直观的看到是否已保存(禁用按钮时,按ctrl+s依然可以保存,很多人都习惯一直按ctrl+s)。
通过ng-class
来实现这个功能,将class:disabled绑定到editorChanged
这个上下文变量上。
studio.directive('studioSave',function(){
return function($scope,elem){
var editor = hmd.editor;
//标识是否有未保存的变更.
$scope.editorChanged = false;
editor.on('change', function (cm, change) {
$scope.editorChanged = true;
$scope.$digest();
});
editor.on('saved', function () {
$scope.editorChanged = false;
$scope.$digest();
});
$(elem[0]).on('click',function(){
editor.save();
});
};
});
这样$scope.editorChanged变化时,保存按钮也会跟着变化,不需要直接操作dom元素。
editor.js
里保存功能的实现
//保存文件
save : function () {
var txt = this.cm.getValue();
if(this.filepath){
util.writeFileSync(this.filepath, txt);
this.fire('saved',this.filepath);
}
else{
this.saveAs();
}
}
//另存为对话框
saveAs:function(){
var me = this;
this.saveAsInput = $('<input style="display:none;" type="file" accept=".md" nwsaveas/>');
this.saveAsInput[0].addEventListener("change", function (evt) {
if(this.value){
me.filepath = this.value;
me.save();
}
}, false);
this.saveAsInput.trigger('click');
hmd.msg('保存新文件');
},
打开文件
常用的有2种打开文件的方式:
- 通过按钮
- 双击.md文件打开
通过按钮打开
通过按钮打开与另存为类似,直接上代码,不用多做解释。
openFile:function(){
var me = this;
this.openFileInput = $('<input style="display:none;" type="file" accept=".md"/>');
this.openFileInput[0].addEventListener("change", function (evt) {
if(this.value){
me.setFile(this.value);
}
}, false);
this.openFileInput.trigger('click');
},
然后是实现按钮绑定的directive
。
<a studio-openfile href="javascript://" class="btn btn-primary" title="打开文件" ng-click="openTerminal()">省略..</a>
studio.directive('studioOpenfile', function () {
return function ($scope, elem) {
$(elem[0]).on('click',function(){
hmd.editor.openFile();
});
};
});
双击md文件打开
首先,选随便选中一个md文件,并设置默认用HexoMD程序打开。然后双击随便一个md文件试试,可以看到双击后程序会启动,但是并不会打开双击的文件,接下来就写代码实现它。
studio.directive('hmdEditor', function () {
return function ($scope, elem) {
hmd.editor.init({el:elem[0]});
//省略部分代码...
//双击md文件打开
var gui = require('nw.gui'),
filepath = gui.App.argv[0];
~filepath.indexOf('.md') && hmd.editor.setFile(filepath);
//如果程序已经打开,则会触发open事件
gui.App.on('open', function(cmdline) {
window.focus();
filepath = cmdline.split(' ')[2].replace(/\"/g,'');
~filepath.indexOf('.md') && hmd.editor.setFile(filepath);
});
};
});
相关知识 ,关掉程序,再次双击md文件,就可以看到打开功能正常了。在软件已启动的状态双击文件也可以打开该文件。
总结
实现了文件操作功能,这样编辑器已经可以投入使用了。接下来的工作就是一些设置,云存储,样式之类的功能。