自己動手制作更好用的markdown編輯器-03


這里文章都是從個人的github博客直接復制過來的,排版可能有點亂. 原始地址  http://benq.im/2015/04/24/hexomd-03/
文章目錄
  1. 1. 系統模塊
  2. 2. 記錄上次打開的文件
  3. 3. 編輯器樣式選擇
    1. 3.1. 樣式修改表單
    2. 3.2. 自動生成select列表
  4. 4. 總結
  5. 5. 附件

上一篇我們實現了文件的新建,保存,打開功能.

在這篇里我們將實現以下功能:

  1. 系統模塊,包含一些軟件的設置和存儲功能
  2. 記錄上次打開的文件
  3. 編輯器樣式選擇

系統模塊

跟之前的studio模塊類似,我們在modules模塊下增加system目錄.

比studio多了model.js文件,用來實現系統模塊的一些功能.

app.js里加載system模塊

1
2
3
4
5
6
angular.module('hmd', ['ui.router','hmd.directives','hmd.studio','hmd.system'])
...
//引入模塊
hmd.regModule('studio');
hmd.regModule('system');
...

 

路由、導航欄
angular.js用得不熟,導航欄的狀態根據route來切換一直不知道怎么實現比較優雅.
我直接在app.js里增加了一個導航欄切換的方法,每個route的onEnter事件里自行調用這個方法.

1
2
3
4
5
6
//TODO:更優雅的導航欄切換邏輯
hmd.changeStatus = function (state) {
var $navList = $('#navlist');
$navList.find('li').removeClass('active');
$navList.find('.' + state).addClass('active');
};

 

system/route.js

1
2
3
4
5
6
7
8
9
10
11
hmd.system.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('system', {
url: "/system",
templateUrl: "modules/system/views/system.html",
controller: 'system',
onEnter: function () {
hmd.changeStatus('system');
}
});
});

 

studio/route.js

1
2
3
4
5
...
onEnter: function () {
hmd.changeStatus('studio')
;

}
...

 

然后在index.html里配置好導航

1
2
3
4
5
6
...
<ul class="nav navbar-nav" id="navlist" >
<li class="studio"><a href="#/studio">編輯器</a></li>
<li class="system"><a href="#/system">系統設置</a></li>
</ul>
...

 

導航欄最終效果:

記錄上次打開的文件

每次打開文件都會被記住,下次重新啟動程序時將默認打開最后一次打開的文件.

system設置的讀取和保存

我們先在system/model.js實現保存和讀取設置的功能.

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
31
32
33
34
var util = require('./helpers/util'),
fs = require('fs'),
system = hmd.system,
//存儲設置的文件
dataFile = system.dataPath + '\\system.json';

//初始化存儲目錄
if (!fs.existsSync(system.dataPath)) {
fs.mkdirSync(system.dataPath);
}

//默認設置
var defaultSystemData = {
//最后一次打開的文件
lastFile: null
};

//讀取設置
system.get = function () {
return $.extend(defaultSystemData,util.readJsonSync(dataFile));
};

//保存設置
system.save = function (data) {
data = data || defaultSystemData;
util.writeFileSync(dataFile, JSON.stringify(data));
};

//設置最后打開的文件
system.setLastFile = function (filepath) {
var systemData = system.get();
systemData.lastFile = filepath;
system.save(systemData);
};

 

system實現了getsave方法,所有的設置都存儲在一個簡單的對象里,代碼里並沒有對這個對象做緩存,每次都是從文件里讀取,因為這簡單的文件還遠達不到影響讀取速度的情況.

然后我們修改editorsetFile方法,暴露setFiled事件給外部使用.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//設置當前文件
setFile:function(filepath){
if(filepath && fs.existsSync(filepath)){
var txt = util.readFileSync(filepath);
this.filepath = filepath;
this.cm.setValue(txt);
this.fire('setFiled',this.filepath);
}
else{
this.filepath = null;
this.cm.setValue('');
this.fire('setFiled');
}
}

 

最后修改studio/directives.jshmdEditor,實現這個功能.

1
2
3
4
5
6
7
8
9
10
studio.directive('hmdEditor', function () {
return function ($scope, elem) {
//讀取最后一次打開的文件
var systemData = hmd.system.get();
hmd.editor.init({el:elem[0]},systemData.lastFile);
//保存最后一次打開的文件
hmd.editor.on('setFiled',function(filepath){
hmd.system.setLastFile(filepath);
});
...

 

編輯器樣式選擇

樣式修改表單

樣式文件在目錄app/lib/codemirror/theme.
目錄里每一個樣式文件代表一種編輯器樣式,還記得當初實現editorinit時,樣式已經是通過配置傳入的.

1
2
3
4
5
...
if(options.theme != 'default'){
$('head').append('<link href="lib/codemirror/theme/'+options.theme+'.css" rel="stylesheet" />');
}
...

 

現在我們只要把theme參數存儲到配置里,並提供給用戶修改就可以.

system/model.js里的默認配置增加一個theme字段.

1
2
3
4
5
6
7
8
9
...
//默認設置
var defaultSystemData = {
//最后一次打開的文件
lastFile: null,
//當前樣式
theme:'ambiance'
};
...

 

修改system/views/system.html模版,增加樣式表單

1
2
3
4
5
6
7
8
9
10
11
12
13
<div class="content studio-wrap">
<form class="system-form" name="systemForm">
<div class="form-group">
<label>編輯器樣式</label>
<select ng-model="systemSetting.theme" name="theme">
<option value="ambiance">ambiance</option>
<option value="mbo">mbo</option>
<option value="neat">neat</option>
</select>
</div>
<button type="submit" class="btn btn-default" ng-click="save(systemSetting)">保存</button>
</form>
</div>

 

這里的select控件我們先寫了3個選項.現在先實現這個修改樣式的功能,等完成這個功能后再把選項列表做成自動生成.

對應的system/controllers.js(開發了3天了,終於第一次用到controller了)

1
2
3
4
5
6
system.controller('system', function ($scope) {
$scope.systemSetting = system.get();
$scope.save = function (systemSetting) {
system.save(systemSetting);
};
});

 

controller里讀取system的數據,並賦值給$scope.systemSetting,用於表單的數據綁定.由於angular實現了數據的雙向綁定,因此用戶編輯表單時,綁定的數據也會跟着更新.這樣我們的save方法里只要將表單綁定的數據保存回system即可.

button按鈕綁定save方法ng-click="save(systemSetting)".

這里可以稍微感受到angular讓我們節省了很多工作量.

自動生成select列表

修改controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var system = hmd.system,
fs = require('fs');
system.controller('system', function ($scope) {
//讀取theme目錄,生成樣式列表
var files = fs.readdirSync('./app/lib/codemirror/theme'),themes={};
files.forEach(function (file) {
if(~file.indexOf('.css')){
file = file.replace('.css','');
themes[file] = file;
}
});
$scope.themes = themes;
$scope.systemSetting = system.get();
$scope.save = function (systemSetting) {
system.save(systemSetting);
};
});

 

theme目錄里讀取所有樣式列表,生成鍵值對,然后賦值給$scope.themes

修改視圖模版:

1
2
<select name="theme" ng-model="systemSetting.theme"  ng-options="k as v for (k, v) in themes">
</select>

 

ng-options="k as v for (k, v) in themes"是angular的綁定語法

這樣我們就實現了樣式列表的自動讀取,用戶如果想自定義樣式,只要在app/lib/codemirror/theme目錄新增一個樣式文件,並寫上自己的樣式就可以在系統設置里選擇自定義的樣式了.

總結

今天實現了記憶最后一次打開的文件以及樣式選擇的功能,並且第一次使用了angularcontroller,感受到了angular雙向數據綁定的強大.

我們的程序又更好用一些了(但是隨着界面變多,又更丑了,太為難了).

最終效果截圖

附件

本篇程序打包
項目地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM