上一篇我们实现了系统模块的一些功能,对angular
的使用更深入了一点.
今天这篇我们要实现实时预览
的功能,将学习到如何使用nw.js
打开额外新窗口,窗口之间如何通信,并将引入新的开源框架marked,用于markdown的解析.
预览的功能我将在编辑器之外的新窗口里实现,因为我平常都习惯使用双显示器,这样能把预览放在另一个显示器.
先在studio/views
里新增PReview.html,作为预览的窗口页面.
12345678910111213 | <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><title>预览</title></head><body> <article class="markdown-body" id="content"> </article> <script src="../../../lib/jquery-2.1.3.js"></script> <script src="../preview.js"></script></body></html> |
studio/directives.js
里增加打开预览窗口的directive
1234567891011121314151617181920212223242526 | //预览studio.directive('studioPreview',function(){ return function($scope,elem){ $(elem[0]).on('click',function(){ var previewWinUrl = ('file:///' + require('path').dirname(process.execPath) + '/app/modules/studio/views/preview.html').replace(////g,'/'); if (!hmd.previewWin) { //开发时为了方便调试,设置toolbar:true,发布时设为false. hmd.previewWin = require('nw.gui').Window.open(previewWinUrl, { position: 'center', "toolbar": true, "frame": true, "width": 800, "height": 600, "min_width": 600, "min_height": 400, "icon": "app/img/logo.png" }); //关闭的时候置空preivewWin变量 hmd.previewWin.on('close', function () { hmd.previewWin = null; this.close(true); }); } }); };}); |
预览窗口每次只能打开一个,所以打开之前会先判断hmd.previewWin
是否已存在,并且窗口关闭事件里将hmd.previewWin
置空.
studio/views/studio.html
里绑定预览按钮
123 | ...<a studio-preview href="javascript://" class="btn btn-primary" title="预览"><i class="glyphicon glyphicon-eye-open"></i></a>... |
这样就实现了点击预览按钮打开预览窗口
markdown
的解析我使用开源的marked.
安装marked打开命令行,进入app
目录,输入安装命令:
1 | npm install marked --save |
为editor.js增加markdown解析的方法,输出当前编辑器内容解析后的结果.
123456789101112131415161718192021222324 | init: function (options,filepath) { ... this.initMarked(); this.cm = CodeMirror.fromTextArea(el, options); ...},//初始化解析模块initMarked:function(){ this.marked = require('../app/node_modules/marked'); this.marked.setOptions({ renderer: new this.marked.Renderer(), gfm: true, tables: true, breaks: false, pedantic: false, sanitize: true, smartLists: true, smartypants: false });},//解析markdownparse:function(){ return this.marked(this.cm.getValue());}, |
这里要注意的是this.marked = require('../app/node_modules/marked');
,而不是直接require('marked')
,这是因为nw.js的这个问题
修改directive
123456789101112131415161718192021222324252627282930 | //预览studio.directive('studioPreview',function(){ return function($scope,elem){ //修改文本时更新预览,change事件触发非常频繁,所以这里使用setTimeout防止无意义的频繁解析. var changeTimer; hmd.editor.on('change',function(){ clearTimeout(changeTimer); changeTimer = setTimeout(function(){ hmd.previewWin && hmd.previewWin.emit('change', hmd.editor.parse()); },200); }); //打开文件时更新预览 hmd.editor.on('setFiled',function(filepath){ hmd.previewWin && hmd.previewWin.emit('change', hmd.editor.parse()); }); $(elem[0]).on('click',function(){ //省略... hmd.previewWin.on('loaded',function(){ hmd.previewWin && hmd.previewWin.emit('change', hmd.editor.parse()); }); hmd.previewWin.on('close', function () { hmd.previewWin = null; this.close(true); }); } }); };}); |
我们通过自定义事件emit('change', hmd.editor.parse())
来与previewWin
窗口通讯. 在初始化窗口,打开文件,修改文件时都触发窗口的change事件,将解析后的内容作为事件参数传递.新建脚本文件studio/preview.js
,并在preview.html
里引用
1234 | var gui = require('nw.gui'), win = gui.Window.get();win.on('change', function (mDHTML) { $('#content').html(mdHtml);}); |
preview.js里监听change
事件,然后将解析后的内容直接显示到页面上.
现在已经可以实时的预览了,但功能还是过于简单,使用起来很不方便,这一节将优化预览窗口的使用体验.
如果文本太多导致出现滚动条,预览窗口还是会一直显示在第一屏,并不会跟随我们在编辑器中的查看位置来实时的更新预览的位置.我们要看预览还要手动去调整预览窗口的滚动条高度,这样的体验完全等于没法使用,因此现在来实现预览窗口随着编辑器的滚动条高度等比随动.
codemirror已经实现了scroll事件,节省了我们大量的工作量,这个框架的作者考虑的真是周到,不得不赞一下.我们在editor.js对scroll
事件进行封装.
1234 | //滚动事件this.cm.on('scroll',function(cm){ me.fire('scroll',cm.getScrollInfo());}); |
在directive
里将编辑器滚动事件传递给预览窗口
123456789101112 | studio.directive('studioPreview',function(){ ... //编辑器滚动 var scrollTimer; hmd.editor.on('scroll',function(scrollInfo){ clearTimeout(scrollTimer); scrollTimer = setTimeout(function(){ hmd.previewWin && hmd.previewWin.emit('editorScroll',scrollInfo); },200); }); ... } |
同样的道理,我们应该防止太频繁的触发
最后在preview.js
里响应editorScroll
事件,并更新预览页面的滚动条高度
1234 | win.on('editorScroll',function(scrollInfo){ var scrollTop = $(document.body).height()*scrollInfo.top/scrollInfo.height; $(document.body).scrollTop(scrollTop);}); |
默认的无样式界面看起来太不舒服了,现在来实现跟编辑器一样的可以选择或者自定义的样式.
我们将预览的样式放在/app/CSS/previewtheme
目录下,先在里面增加两个测试用的样式文件
增加预览样式设置这个跟上一篇的编辑器样式设置类似.
system/model.js
增加默认配置
123456789 | //默认设置var defaultSystemData = { //最后一次打开的文件 lastFile: null, //编辑器样式 theme:'ambiance', //预览窗口样式 preViewTheme:'default'}; |
system/views/system.html
增加表单字段
1234567891011 | <div class="content studio-wrap"> <form class="system-form" name="systemForm"> ... <div class="form-group"> <label>预览样式</label> <select name="preViewTheme" ng-model="systemSetting.preViewTheme" ng-options="k as v for (k, v) in preViewThemes"> </select> </div> ... </form></div> 学习交流
热门图片
猜你喜欢的新闻
新闻热点 2024-04-27 13:35:46
2024-04-27 13:33:47
2024-04-24 22:53:44
2024-04-23 19:32:50
2024-04-23 19:25:50
2024-04-23 19:13:19
疑难解答 |